Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 33 additions & 3 deletions packages/core/image-asset/image-asset-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class ImageAssetBase extends Observable implements ImageAssetDefinition {
}

set options(value: ImageAssetOptions) {
this._options = value;
this._options = normalizeImageAssetOptions(value);
}

get nativeImage(): any {
Expand All @@ -35,6 +35,35 @@ export class ImageAssetBase extends Observable implements ImageAssetDefinition {
}
}

function toPositiveInt(value: any): number {
if (value == null) {
return 0;
}
if (typeof value === 'number') {
return value > 0 ? Math.floor(value) : 0;
}
if (typeof value === 'string') {
const parsed = parseInt(value, 10);
return isNaN(parsed) || parsed <= 0 ? 0 : parsed;
}
return 0;
}

function normalizeImageAssetOptions(options: ImageAssetOptions): ImageAssetOptions {
const normalized = options ? { ...options } : ({} as ImageAssetOptions);
// Coerce potential string values to positive integers; fallback to 0
// to trigger default sizing downstream
(normalized as any).width = toPositiveInt((options as any)?.width);
(normalized as any).height = toPositiveInt((options as any)?.height);
if (typeof normalized.keepAspectRatio !== 'boolean') {
normalized.keepAspectRatio = true;
}
if (typeof normalized.autoScaleFactor !== 'boolean') {
normalized.autoScaleFactor = true;
}
return normalized;
}

export function getAspectSafeDimensions(sourceWidth, sourceHeight, reqWidth, reqHeight) {
const widthCoef = sourceWidth / reqWidth;
const heightCoef = sourceHeight / reqHeight;
Expand All @@ -47,8 +76,9 @@ export function getAspectSafeDimensions(sourceWidth, sourceHeight, reqWidth, req
}

export function getRequestedImageSize(src: { width: number; height: number }, options: ImageAssetOptions): { width: number; height: number } {
let reqWidth = options.width || Math.min(src.width, Screen.mainScreen.widthPixels);
let reqHeight = options.height || Math.min(src.height, Screen.mainScreen.heightPixels);
const normalized = normalizeImageAssetOptions(options);
let reqWidth = normalized.width || Math.min(src.width, Screen.mainScreen.widthPixels);
let reqHeight = normalized.height || Math.min(src.height, Screen.mainScreen.heightPixels);

if (options && options.keepAspectRatio) {
const safeAspectSize = getAspectSafeDimensions(src.width, src.height, reqWidth, reqHeight);
Expand Down
27 changes: 27 additions & 0 deletions packages/core/image-asset/image-asset-options.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { getRequestedImageSize } from './image-asset-common';

describe('ImageAssetOptions normalization', () => {
it('coerces string width/height to numbers', () => {
const src = { width: 2000, height: 1500 };
const result = getRequestedImageSize(src as any, { width: '300' as any, height: '200' as any, keepAspectRatio: false, autoScaleFactor: true } as any);
expect(result.width).toBe(300);
expect(result.height).toBe(200);
});

it('falls back to defaults when invalid strings provided', () => {
const src = { width: 800, height: 600 };
const result = getRequestedImageSize(src as any, { width: 'abc' as any, height: '' as any, keepAspectRatio: false } as any);
// should fall back to screen pixel defaults via getRequestedImageSize, but since
// we cannot easily control Screen.mainScreen here, we at least assert they are > 0
expect(result.width).toBeGreaterThan(0);
expect(result.height).toBeGreaterThan(0);
});

it('respects keepAspectRatio by adjusting to safe dimensions', () => {
const src = { width: 2000, height: 1000 };
const result = getRequestedImageSize(src as any, { width: '500' as any, height: '500' as any, keepAspectRatio: true } as any);
// current implementation scales using the smaller coefficient (min), so expect 1000x500
expect(result.width).toBe(1000);
expect(result.height).toBe(500);
});
});
Binary file modified packages/core/platforms/android/widgets-release.aar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,36 @@ static class ImageAssetOptions {
boolean autoScaleFactor;
}

private static int parsePositiveInt(JSONObject object, String key) {
if (object == null || key == null) {
return 0;
}
try {
if (!object.has(key) || object.isNull(key)) {
return 0;
}
Object value = object.get(key);
if (value instanceof Number) {
int parsed = (int) Math.floor(((Number) value).doubleValue());
return parsed > 0 ? parsed : 0;
}
if (value instanceof String) {
String s = ((String) value).trim();
if (s.length() == 0) {
return 0;
}
try {
int parsed = Integer.parseInt(s);
return parsed > 0 ? parsed : 0;
} catch (NumberFormatException ignored) {
return 0;
}
}
} catch (JSONException ignored) {
}
return 0;
}

private static final Executor executors = Executors.newCachedThreadPool();


Expand Down Expand Up @@ -297,8 +327,9 @@ public void run() {

try {
JSONObject object = new JSONObject(options);
opts.width = object.optInt("width", 0);
opts.height = object.optInt("height", 0);
// Coerce numeric strings or numbers; fallback to 0 for invalid values
opts.width = parsePositiveInt(object, "width");
opts.height = parsePositiveInt(object, "height");
opts.keepAspectRatio = object.optBoolean("keepAspectRatio", true);
opts.autoScaleFactor = object.optBoolean("autoScaleFactor", true);
} catch (JSONException ignored) {
Expand Down
Loading