Let the GPS watermark be placed, sized and hung landscape
Three WATERMARK/FRAME behaviours that share the stamp geometry: * GPS mark: drag it anywhere on the frame/photo area and pinch it bigger or smaller. The 0..1 anchor plus the size multiplier ride along in the export options, so a framed file (whose canvas IS the card/frame) burns the mark in at exactly the fraction the preview showed. * The photo's own pinch zoom stays available while the WATERMARK editor is closed, so a two-finger zoom is never swallowed by the mark while its panel is open. * WALL FRAME gains a WALL PORTRAIT / WALL LANDSCAPE chip: the artwork hangs in its own 4000x3117 orientation instead of the default 90-degree rotation.
This commit is contained in:
+32
-12
@@ -53,6 +53,17 @@ export const WALLFRAME_WIN = {
|
||||
w: 1766 / 3117, // ≈ 0.56657
|
||||
h: 2647 / 4000, // 0.66175
|
||||
} as const;
|
||||
// Landscape hang: the PNG's OWN orientation, so nothing is rotated — the
|
||||
// canvas is the artwork (4000x3117) and the opening is the source window as
|
||||
// fractions of it. Same 3:2 mat opening, hung the other way round.
|
||||
export const WALLFRAME_LAND_W = WALLFRAME_PNG_W; // 4000
|
||||
export const WALLFRAME_LAND_H = WALLFRAME_PNG_H; // 3117
|
||||
export const WALLFRAME_LAND_WIN = {
|
||||
left: 675 / WALLFRAME_PNG_W, // 0.16875
|
||||
top: 675 / WALLFRAME_PNG_H, // ≈ 0.21688
|
||||
w: 2647 / WALLFRAME_PNG_W, // 0.66175
|
||||
h: 1766 / WALLFRAME_PNG_H, // ≈ 0.56657
|
||||
} as const;
|
||||
|
||||
export interface WallframeLayout {
|
||||
frame: { x: number; y: number; w: number; h: number };
|
||||
@@ -63,36 +74,45 @@ export interface WallframeLayout {
|
||||
drawMatrix: number[];
|
||||
}
|
||||
|
||||
// Geometry of the ROTATED wall-frame inside an arbitrary container. The frame
|
||||
// is contain-fitted ('contain', centered, letterboxed) for the live viewfinder,
|
||||
// Geometry of the wall-frame inside an arbitrary container. The frame is
|
||||
// contain-fitted ('contain', centered, letterboxed) for the live viewfinder,
|
||||
// or fills the container exactly ('fill', export canvas already at frame size).
|
||||
// `landscape` hangs the artwork the other way round: same PNG, no rotation.
|
||||
export function wallframeLayout(
|
||||
contW: number,
|
||||
contH: number,
|
||||
mode: 'contain' | 'fill' = 'contain'
|
||||
mode: 'contain' | 'fill' = 'contain',
|
||||
landscape = false
|
||||
): WallframeLayout {
|
||||
const FW = landscape ? WALLFRAME_LAND_W : WALLFRAME_W;
|
||||
const FH = landscape ? WALLFRAME_LAND_H : WALLFRAME_H;
|
||||
const WIN = landscape ? WALLFRAME_LAND_WIN : WALLFRAME_WIN;
|
||||
let frameW: number;
|
||||
let frameH: number;
|
||||
if (mode === 'fill') {
|
||||
frameW = contW;
|
||||
frameH = contH;
|
||||
} else {
|
||||
const s = Math.min(contW / WALLFRAME_W, contH / WALLFRAME_H);
|
||||
frameW = WALLFRAME_W * s;
|
||||
frameH = WALLFRAME_H * s;
|
||||
const s = Math.min(contW / FW, contH / FH);
|
||||
frameW = FW * s;
|
||||
frameH = FH * s;
|
||||
}
|
||||
const fx = (contW - frameW) / 2;
|
||||
const fy = (contH - frameH) / 2;
|
||||
const scale = frameW / WALLFRAME_W; // == frameH / WALLFRAME_H
|
||||
const scale = frameW / FW; // == frameH / FH
|
||||
return {
|
||||
frame: { x: fx, y: fy, w: frameW, h: frameH },
|
||||
window: {
|
||||
x: fx + WALLFRAME_WIN.left * frameW,
|
||||
y: fy + WALLFRAME_WIN.top * frameH,
|
||||
w: WALLFRAME_WIN.w * frameW,
|
||||
h: WALLFRAME_WIN.h * frameH,
|
||||
x: fx + WIN.left * frameW,
|
||||
y: fy + WIN.top * frameH,
|
||||
w: WIN.w * frameW,
|
||||
h: WIN.h * frameH,
|
||||
},
|
||||
drawMatrix: [0, -scale, fx + frameW, scale, 0, fy, 0, 0, 1],
|
||||
// Portrait: the source PNG must be turned 90° CW onto the canvas.
|
||||
// Landscape: it already sits the right way up — scale and centre it.
|
||||
drawMatrix: landscape
|
||||
? [scale, 0, fx, 0, scale, fy, 0, 0, 1]
|
||||
: [0, -scale, fx + frameW, scale, 0, fy, 0, 0, 1],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user