diff --git a/src/shared/EmbeddedFileLoader.ts b/src/shared/EmbeddedFileLoader.ts index b7b1523..6f2e595 100644 --- a/src/shared/EmbeddedFileLoader.ts +++ b/src/shared/EmbeddedFileLoader.ts @@ -19,7 +19,7 @@ import { ExportSettings } from "../view/ExcalidrawView"; import { t } from "../lang/helpers"; import { tex2dataURL } from "./LaTeX"; import ExcalidrawPlugin from "../core/main"; -import { blobToBase64, getDataURLFromURL, getMimeType, getPDFDoc, getURLImageExtension, hasExcalidrawEmbeddedImagesTreeChanged, readLocalFileBinary } from "../utils/fileUtils"; +import { blobToBase64, getDataURLFromURL, getMimeType, getPDFDoc, getURLImageExtension, readLocalFileBinary } from "../utils/fileUtils"; import { errorlog, getDataURL, @@ -91,6 +91,7 @@ export type PDFPageViewProps = { bottom: number; right: number; top: number; + rotate?: number; //may be undefined in legacy files } export type Size = { @@ -866,19 +867,58 @@ export class EmbeddedFilesLoader { } const [left, bottom, right, top] = page.view; viewProps = {left, bottom, right, top}; + viewProps.rotate = page.rotate; if(validRect) { - const pageHeight = top - bottom; - width = (cropRect[2] - cropRect[0]) * scale; - height = (cropRect[3] - cropRect[1]) * scale; - const crop = validRect ? { - left: (cropRect[0] - left) * scale, - top: (bottom + pageHeight - cropRect[3]) * scale, - width, - height, - } : undefined; - if(crop) { + const pageHeight = top - bottom; + const pageWidth = right - left; + + if(!page.rotate || page.rotate === 0) { + width = (cropRect[2] - cropRect[0]) * scale; + height = (cropRect[3] - cropRect[1]) * scale; + + const crop = { + left: (cropRect[0] - left) * scale, + top: (bottom + pageHeight - cropRect[3]) * scale, + width, + height, + }; + return cropCanvas(canvas, crop); + } + if(page.rotate === 90) { + width = (cropRect[3] - cropRect[1]) * scale; + height = (cropRect[2] - cropRect[0]) * scale; + const crop = { + left: cropRect[1] * scale, + top: (pageHeight - cropRect[2]) * scale, + width, + height, + }; + return cropCanvas(canvas, crop); + } + + if(page.rotate === 180) { + width = (cropRect[2] - cropRect[0]) * scale; + height = (cropRect[3] - cropRect[1]) * scale; + const crop = { + left: (pageWidth - cropRect[2]) * scale, + top: cropRect[1] * scale, + width, + height, + }; + return cropCanvas(canvas, crop); + } + + if(page.rotate === 270) { + width = (cropRect[3] - cropRect[1]) * scale; + height = (cropRect[2] - cropRect[0]) * scale; + const crop = { + left: (pageWidth - cropRect[3]) * scale, + top: cropRect[0] * scale, + width, + height, + }; return cropCanvas(canvas, crop); } } diff --git a/src/utils/PDFUtils.ts b/src/utils/PDFUtils.ts index 1e42af5..0c62897 100644 --- a/src/utils/PDFUtils.ts +++ b/src/utils/PDFUtils.ts @@ -15,17 +15,76 @@ export function getPDFCropRect (props: { return null; } + const rotate = props.pdfPageViewProps.rotate ?? 0; const { left, bottom } = props.pdfPageViewProps; const R0 = parseInt(rectVal[1]); const R1 = parseInt(rectVal[2]); const R2 = parseInt(rectVal[3]); const R3 = parseInt(rectVal[4]); + if(rotate === 90) { + const _top = R0; + const _left = R1; + const _bottom = R2; + const _right = R3; + + const x = _left * props.scale; + const y = _top * props.scale; + return { + x, + y, + width: _right*props.scale - x, + height: _bottom*props.scale - y, + naturalWidth: props.naturalWidth, + naturalHeight: props.naturalHeight, + } + } + if(rotate === 180) { + const _right = R0; + const _top = R1; + const _left = R2; + const _bottom = R3; + + const y = _top * props.scale; + const x = props.naturalWidth - _left * props.scale; + + return { + x, + y, + width: props.naturalWidth - x - _right * props.scale, + height: _bottom * props.scale - y, + naturalWidth: props.naturalWidth, + naturalHeight: props.naturalHeight, + } + } + if(rotate === 270) { + const _bottom = R0; + const _right = R1; + const _top = R2; + const _left = R3; + + const x = props.naturalWidth - _left * props.scale; + const y = props.naturalHeight - _top * props.scale; + return { + x, + y, + width: props.naturalWidth - x - _right * props.scale, + height: props.naturalHeight - y - _bottom * props.scale, + naturalWidth: props.naturalWidth, + naturalHeight: props.naturalHeight, + } + } + // default to 0° rotation + const _left = R0; + const _bottom = R1; + const _right = R2; + const _top = R3; + return { - x: (R0 - left) * props.scale, - y: (bottom + props.naturalHeight/props.scale - R3) * props.scale, - width: (R2 - R0) * props.scale, - height: (R3 - R1) * props.scale, + x: (_left - left) * props.scale, + y: props.naturalHeight - (_top - bottom) * props.scale, + width: (_right - _left) * props.scale, + height: (_top - _bottom) * props.scale, naturalWidth: props.naturalWidth, naturalHeight: props.naturalHeight, } @@ -34,13 +93,36 @@ export function getPDFCropRect (props: { export function getPDFRect({elCrop, scale, customData}:{ elCrop: ImageCrop, scale: number, customData: Record }): string { + const rotate = (customData.pdfPageViewProps as PDFPageViewProps)?.rotate ?? 0; const { left, bottom } = (customData && customData.pdfPageViewProps) ? customData.pdfPageViewProps as PDFPageViewProps : { left: 0, bottom: 0 }; - const R0 = elCrop.x / scale + left; - const R2 = elCrop.width / scale + R0; - const R3 = bottom + (elCrop.naturalHeight - elCrop.y) / scale; - const R1 = R3 - elCrop.height / scale; - return `&rect=${Math.round(R0)},${Math.round(R1)},${Math.round(R2)},${Math.round(R3)}`; -} \ No newline at end of file + if(rotate === 90) { + const _top = (elCrop.y) / scale; + const _left = (elCrop.x) / scale; + const _bottom = (elCrop.height + elCrop.y) / scale; + const _right = (elCrop.width + elCrop.x) / scale; + return `&rect=${Math.round(_top)},${Math.round(_left)},${Math.round(_bottom)},${Math.round(_right)}`; + } + if(rotate === 180) { + const _right = (elCrop.naturalWidth-elCrop.x-elCrop.width) / scale; + const _top = (elCrop.y) / scale; + const _left = (elCrop.naturalWidth - elCrop.x) / scale; + const _bottom = (elCrop.height + elCrop.y) / scale; + return `&rect=${Math.round(_right)},${Math.round(_top)},${Math.round(_left)},${Math.round(_bottom)}`; + + } + if(rotate === 270) { + const _bottom = (elCrop.naturalHeight - elCrop.height-elCrop.y) / scale; + const _right = (elCrop.naturalWidth - elCrop.width - elCrop.x) / scale; + const _top = (elCrop.naturalHeight - elCrop.y) / scale; + const _left = (elCrop.naturalWidth - elCrop.x) / scale; + return `&rect=${Math.round(_bottom)},${Math.round(_right)},${Math.round(_top)},${Math.round(_left)}`; + } + const _left = elCrop.x / scale + left; + const _right = elCrop.width / scale + _left; + const _top = bottom + (elCrop.naturalHeight - elCrop.y) / scale; + const _bottom = _top - elCrop.height / scale; + return `&rect=${Math.round(_left)},${Math.round(_bottom)},${Math.round(_right)},${Math.round(_top)}`; +}