export type ImageScaleMode = 'contain' | 'cover' | 'fill' export function readImageScaleMode(cfg: Record | undefined | null): ImageScaleMode { const v = String(cfg?.scaleMode ?? cfg?.ScaleMode ?? 'contain') .trim() .toLowerCase() if (v === 'cover' || v === 'fill') return v return 'contain' } export function computeImageDrawRect( boxW: number, boxH: number, sourceW: number, sourceH: number, scaleMode: string, ): { dx: number; dy: number; dw: number; dh: number } { const mode = String(scaleMode ?? 'contain').trim().toLowerCase() if (sourceW <= 0 || sourceH <= 0 || mode === 'fill') { return { dx: 0, dy: 0, dw: boxW, dh: boxH } } const ratio = mode === 'cover' ? Math.max(boxW / sourceW, boxH / sourceH) : Math.min(boxW / sourceW, boxH / sourceH) const dw = Math.max(1, Math.round(sourceW * ratio)) const dh = Math.max(1, Math.round(sourceH * ratio)) return { dx: Math.round((boxW - dw) / 2), dy: Math.round((boxH - dh) / 2), dw, dh, } }