mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
fix(android): coerce string width/height in ImageAssetOptions (#10862)
This commit is contained in:
committed by
GitHub
parent
d856826b7a
commit
9db6369aed
@ -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 {
|
||||
@ -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;
|
||||
@ -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);
|
||||
|
||||
27
packages/core/image-asset/image-asset-options.spec.ts
Normal file
27
packages/core/image-asset/image-asset-options.spec.ts
Normal file
@ -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 not shown.
@ -170,6 +170,36 @@ public class Utils {
|
||||
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();
|
||||
|
||||
|
||||
@ -297,8 +327,9 @@ public class Utils {
|
||||
|
||||
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) {
|
||||
|
||||
Reference in New Issue
Block a user