Phase 3 implementation. Coordinate system implemented. Initial text box tool implemented.
This commit is contained in:
parent
c159ad4f37
commit
4cb038ec78
34 changed files with 6676 additions and 130 deletions
74
frontend/src/lib/coords.ts
Normal file
74
frontend/src/lib/coords.ts
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
export interface PdfPoint { x: number; y: number }
|
||||
export interface ScreenPoint { x: number; y: number }
|
||||
|
||||
export interface PdfRect { x: number; y: number; width: number; height: number }
|
||||
export interface ScreenRect { x: number; y: number; width: number; height: number }
|
||||
|
||||
export interface ViewportParams {
|
||||
scale: number; // CSS Zoom level (1.0 = 100%)
|
||||
rotation: number; // 0, 90, 180, 270 (clockwise)
|
||||
canonicalWidth: number; // Unrotated CropBox width in PDF points
|
||||
canonicalHeight: number;// Unrotated CropBox height in PDF points
|
||||
dpr?: number; // Device Pixel Ratio (defaults to 1)
|
||||
}
|
||||
|
||||
function getEffectiveScale(vp: ViewportParams): number {
|
||||
return vp.scale * (vp.dpr || 1);
|
||||
}
|
||||
|
||||
export function pdfToScreen(p: PdfPoint, vp: ViewportParams): ScreenPoint {
|
||||
const s = getEffectiveScale(vp);
|
||||
const { rotation, canonicalWidth: W, canonicalHeight: H } = vp;
|
||||
const { x, y } = p;
|
||||
|
||||
const rot = ((rotation % 360) + 360) % 360;
|
||||
|
||||
switch (rot) {
|
||||
case 0: return { x: x * s, y: y * s };
|
||||
case 90: return { x: (H - y) * s, y: x * s };
|
||||
case 180: return { x: (W - x) * s, y: (H - y) * s };
|
||||
case 270: return { x: y * s, y: (W - x) * s };
|
||||
default: throw new Error(`Invalid rotation: ${rotation}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function screenToPdf(p: ScreenPoint, vp: ViewportParams): PdfPoint {
|
||||
const s = getEffectiveScale(vp);
|
||||
const { rotation, canonicalWidth: W, canonicalHeight: H } = vp;
|
||||
const sx = p.x / s;
|
||||
const sy = p.y / s;
|
||||
|
||||
const rot = ((rotation % 360) + 360) % 360;
|
||||
|
||||
switch (rot) {
|
||||
case 0: return { x: sx, y: sy };
|
||||
case 90: return { x: sy, y: H - sx };
|
||||
case 180: return { x: W - sx, y: H - sy };
|
||||
case 270: return { x: W - sy, y: sx };
|
||||
default: throw new Error(`Invalid rotation: ${rotation}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function pdfRectToScreen(r: PdfRect, vp: ViewportParams): ScreenRect {
|
||||
const p1 = pdfToScreen({ x: r.x, y: r.y }, vp);
|
||||
const p2 = pdfToScreen({ x: r.x + r.width, y: r.y + r.height }, vp);
|
||||
|
||||
return {
|
||||
x: Math.min(p1.x, p2.x),
|
||||
y: Math.min(p1.y, p2.y),
|
||||
width: Math.abs(p2.x - p1.x),
|
||||
height: Math.abs(p2.y - p1.y)
|
||||
};
|
||||
}
|
||||
|
||||
export function screenRectToPdf(r: ScreenRect, vp: ViewportParams): PdfRect {
|
||||
const p1 = screenToPdf({ x: r.x, y: r.y }, vp);
|
||||
const p2 = screenToPdf({ x: r.x + r.width, y: r.y + r.height }, vp);
|
||||
|
||||
return {
|
||||
x: Math.min(p1.x, p2.x),
|
||||
y: Math.min(p1.y, p2.y),
|
||||
width: Math.abs(p2.x - p1.x),
|
||||
height: Math.abs(p2.y - p1.y)
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue