Files
workinf_Blender_Wasm/web/protocol/viewport-dpr.ts
mes123456 380cbed4ff
Some checks are pending
M6 deployable RC / quick (push) Waiting to run
M6 deployable RC / chromium (push) Blocked by required conditions
M6 deployable RC / release (push) Blocked by required conditions
Checkpoint web parity through Chromium input tasks
2026-08-19 10:39:03 -04:00

50 lines
1.8 KiB
TypeScript

export const VIEWPORT_DPR_SCHEMA_VERSION = 1 as const;
export const VIEWPORT_MAX_DPR = 2 as const;
export interface ViewportPixelMetrics {
schemaVersion: typeof VIEWPORT_DPR_SCHEMA_VERSION;
cssWidth: number;
cssHeight: number;
pixelRatio: number;
backingWidth: number;
backingHeight: number;
}
export interface ViewportNDC {
x: number;
y: number;
}
function finitePositive(value: number): boolean {
return Number.isFinite(value) && value > 0;
}
export function resolveViewportPixelRatio(devicePixelRatio: number | undefined, maximum = VIEWPORT_MAX_DPR): number {
if (!finitePositive(maximum)) throw new Error("VIEWPORT_DPR_INVALID");
const observed = finitePositive(devicePixelRatio ?? 1) ? devicePixelRatio! : 1;
return Math.min(observed, maximum);
}
export function resolveViewportPixelMetrics(cssWidth: number, cssHeight: number, devicePixelRatio: number | undefined, maximum = VIEWPORT_MAX_DPR): ViewportPixelMetrics {
if (!finitePositive(cssWidth) || !finitePositive(cssHeight)) throw new Error("VIEWPORT_SIZE_INVALID");
const pixelRatio = resolveViewportPixelRatio(devicePixelRatio, maximum);
return {
schemaVersion: VIEWPORT_DPR_SCHEMA_VERSION,
cssWidth,
cssHeight,
pixelRatio,
backingWidth: Math.max(1, Math.floor(cssWidth * pixelRatio)),
backingHeight: Math.max(1, Math.floor(cssHeight * pixelRatio)),
};
}
export function viewportNDC(clientX: number, clientY: number, bounds: { left: number; top: number; width: number; height: number }): ViewportNDC {
if (![clientX, clientY, bounds.left, bounds.top, bounds.width, bounds.height].every(Number.isFinite) || bounds.width <= 0 || bounds.height <= 0) {
throw new Error("VIEWPORT_BOUNDS_INVALID");
}
return {
x: ((clientX - bounds.left) / bounds.width) * 2 - 1,
y: -((clientY - bounds.top) / bounds.height) * 2 + 1,
};
}