mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-16 03:42:20 +02:00
Photoshop-parity editor client: layers, selection/masking, brushes,
smart filters, LUT import, Quick Edit, mobile gestures, workspaces,
batch operations, and the service-worker versioning (v978->v1006).
Source: vendor/photocraft (ad1cff44) photo-editor client files, merged
onto upstream/dev (a8c147b2). Conflict resolution documented in
pr_work/A_conflicts.md; editor files taken from vendor/photocraft
(upstream's editor is an earlier snapshot of the same feature).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
36 lines
1.4 KiB
JavaScript
36 lines
1.4 KiB
JavaScript
// Pure aspect-fitting geometry for the editor. When a whole-image resize is
|
|
// asked for a target aspect that differs from the current image, content must
|
|
// be cropped to that aspect (centred on a focus point) and then scaled
|
|
// UNIFORMLY — never stretched.
|
|
//
|
|
// aspectFitCropRect returns the document-space rectangle to crop FIRST so a
|
|
// subsequent uniform scale-to-{targetW,targetH} preserves the subject aspect
|
|
// ratio. Returns the full image unchanged when the aspect already matches.
|
|
|
|
export function aspectFitCropRect({ width, height, focusX, focusY, targetAspect, tolerance = 0.005 } = {}) {
|
|
const w = Number(width);
|
|
const h = Number(height);
|
|
const a = Number(targetAspect);
|
|
if (!(w > 0) || !(h > 0) || !(a > 0)) return null;
|
|
const curAspect = w / h;
|
|
if (Math.abs(curAspect - a) / a <= tolerance) return { x: 0, y: 0, width: Math.round(w), height: Math.round(h) };
|
|
const fx = Number.isFinite(Number(focusX)) ? Number(focusX) : w / 2;
|
|
const fy = Number.isFinite(Number(focusY)) ? Number(focusY) : h / 2;
|
|
let cw;
|
|
let ch;
|
|
if (curAspect > a) {
|
|
ch = h;
|
|
cw = Math.max(1, Math.round(ch * a));
|
|
} else {
|
|
cw = w;
|
|
ch = Math.max(1, Math.round(cw / a));
|
|
}
|
|
let x = Math.round(fx - cw / 2);
|
|
let y = Math.round(fy - ch / 2);
|
|
x = Math.max(0, Math.min(w - cw, x));
|
|
y = Math.max(0, Math.min(h - ch, y));
|
|
return { x, y, width: cw, height: ch };
|
|
}
|
|
|
|
export default { aspectFitCropRect };
|