73 lines
2.5 KiB
TypeScript
73 lines
2.5 KiB
TypeScript
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; // Backing-store density; never part of CSS geometry
|
|
}
|
|
|
|
export function pdfToScreen(p: PdfPoint, vp: ViewportParams): ScreenPoint {
|
|
// Screen points are CSS pixels. Device-pixel-ratio only controls the PDF.js
|
|
// backing canvas; including it here would make Fabric objects overflow the
|
|
// CSS overlay on retina displays.
|
|
const s = vp.scale;
|
|
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 = vp.scale;
|
|
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)
|
|
};
|
|
}
|