diff --git a/src/utils/download.ts b/src/utils/download.ts index af9b388..6e4b45d 100644 --- a/src/utils/download.ts +++ b/src/utils/download.ts @@ -14,23 +14,14 @@ export function downloadBlob(blob: Blob, filename: string) { URL.revokeObjectURL(url); } -export async function prepareSVG( - handler: VectraceHandler, - imageRender: CanvasImageEx -): Promise { +export async function prepareSVG(handler: VectraceHandler, imageRender: CanvasImageEx): Promise { if (imageRender.svg.scale !== imageRender.scale || imageRender.svg.dirty) { handler.redrawSvg(imageRender.id); } return new Blob([imageRender.svg.data], { type: "image/svg+xml" }); } - - -function getGridCells( - paperWidth: number, - paperHeight: number, - grid: string -): GridCell[] { +function getGridCells(paperWidth: number, paperHeight: number, grid: string): GridCell[] { const cols = grid === "3x3" ? 3 : grid === "2x2" ? 2 : 1; const rows = grid === "3x3" ? 3 : grid === "2x2" ? 2 : 1; const cellW = paperWidth / cols; @@ -51,39 +42,51 @@ function getGridCells( return cells; } +function getGridCellsMm(paperWidth: number, paperHeight: number, grid: string): GridCell[] { + const cols = grid === "3x3" ? 3 : grid === "2x2" ? 2 : 1; + const rows = grid === "3x3" ? 3 : grid === "2x2" ? 2 : 1; + const cellW = paperWidth / cols; + const cellH = paperHeight / rows; + const cells: GridCell[] = []; + for (let row = 0; row < rows; row++) { + for (let col = 0; col < cols; col++) { + cells.push({ + col, + row, + x: col * cellW, + y: row * cellH, + w: cellW, + h: cellH, + }); + } + } + return cells; +} -function createCellPdf( - handler: VectraceHandler, - cell: GridCell -): jsPDF { +function createCellPdf(handler: VectraceHandler, cellMm: GridCell): jsPDF { + const { DPI } = handler.globalSettingsHandler.settings; + const pxToMm = (px: number): number => (px / DPI) * MM_TO_INCH; const doc = new jsPDF({ - orientation: cell.w > cell.h ? "landscape" : "portrait", + orientation: cellMm.w > cellMm.h ? "landscape" : "portrait", unit: "mm", - format: [cell.w, cell.h], + format: [cellMm.w, cellMm.h], }); for (const imageObject of handler.imagesRenders) { if (!imageObject.visible) continue; - const imgX = imageObject.x - cell.x; - const imgY = imageObject.y - cell.y; - const imgW = imageObject.image.naturalWidth * imageObject.scale; - const imgH = imageObject.image.naturalHeight * imageObject.scale; + const imgXMm = pxToMm(imageObject.x) - cellMm.x; + const imgYMm = pxToMm(imageObject.y) - cellMm.y; + const imgWMm = pxToMm(imageObject.image.naturalWidth * imageObject.scale); + const imgHMm = pxToMm(imageObject.image.naturalHeight * imageObject.scale); - const overlapX = imgX + imgW > 0 && imgX < cell.w; - const overlapY = imgY + imgH > 0 && imgY < cell.h; + const overlapX = imgXMm + imgWMm > 0 && imgXMm < cellMm.w; + const overlapY = imgYMm + imgHMm > 0 && imgYMm < cellMm.h; if (!overlapX || !overlapY) continue; - doc.addImage( - imageObject.image, - "PNG", - imgX, - imgY, - imgW, - imgH - ); + doc.addImage(imageObject.image, "PNG", imgXMm, imgYMm, imgWMm, imgHMm); } return doc; @@ -95,47 +98,44 @@ const gridConfigs: Record = { }; export function createPdf(handler: VectraceHandler, withGuides: boolean): jsPDF { const { DPI, paperHeight, paperWidth } = handler.globalSettingsHandler.settings; - const width = (paperWidth / MM_TO_INCH) * DPI; - const height = (paperHeight / MM_TO_INCH) * DPI; + + const pxToMm = (px: number): number => (px / DPI) * MM_TO_INCH; const doc = new jsPDF({ orientation: paperWidth > paperHeight ? "landscape" : "portrait", unit: "mm", - format: [width, height], + format: [paperWidth, paperHeight], }); if (withGuides) { - const setLine = () => { - doc.setDrawColor(64, 64, 64); - doc.setLineWidth(1); - }; + doc.setDrawColor(64, 64, 64); + doc.setLineWidth(0.5); + const fractions = gridConfigs[handler.globalSettingsHandler.settings.grid]; if (fractions) { - setLine(); - fractions.forEach(f => { - doc.line(width * f, 0, width * f, height); - doc.line(0, height * f, width, height * f); + fractions.forEach((f) => { + doc.line(paperWidth * f, 0, paperWidth * f, paperHeight); + doc.line(0, paperHeight * f, paperWidth, paperHeight * f); }); } } for (const imageObject of handler.imagesRenders) { - if (imageObject.visible) { - doc.addImage( - imageObject.image, - "PNG", - imageObject.x, - imageObject.y, - imageObject.image.naturalWidth * imageObject.scale, - imageObject.image.naturalHeight * imageObject.scale - ); - } + if (!imageObject.visible) continue; + + doc.addImage( + imageObject.image, + "PNG", + pxToMm(imageObject.x), + pxToMm(imageObject.y), + pxToMm(imageObject.image.naturalWidth * imageObject.scale), + pxToMm(imageObject.image.naturalHeight * imageObject.scale), + ); } return doc; } - export function createSVGDoc(handler: VectraceHandler) { const { paperWidth, paperHeight, DPI } = handler.globalSettingsHandler.settings; const width = (paperWidth / MM_TO_INCH) * DPI; @@ -172,7 +172,7 @@ export async function downloadZip(handler: VectraceHandler): Promise { canvas.height = render.image.naturalHeight * render.scale; ctx.drawImage(render.image, 0, 0, canvas.width, canvas.height); const blob = new Promise((resolve, reject) => { - canvas.toBlob(data => { + canvas.toBlob((data) => { if (data) { resolve(data); } else { @@ -204,16 +204,17 @@ export async function downloadZip(handler: VectraceHandler): Promise { if (grid !== "none") { const cells = getGridCells(width, height, grid); + const cellsMm = getGridCellsMm(paperWidth, paperHeight, grid); const cellPdfs = mainFolder.folder("cells/pdfs")!; const cellSvgs = mainFolder.folder("cells/svgs")!; - for (const cell of cells) { - const label = `cell-r${cell.row}-c${cell.col}`; + for (let i = 0; i < cells.length; i++) { + const label = `cell-r${cells[i].row}-c${cells[i].col}`; - const cellPdf = createCellPdf(handler, cell); + const cellPdf = createCellPdf(handler, cellsMm[i]); cellPdfs.file(`${label}.pdf`, cellPdf.output("blob")); - const cellSvgBlob = await createCellSvg(handler, cell); + const cellSvgBlob = await createCellSvg(handler, cells[i]); cellSvgs.file(`${label}.svg`, cellSvgBlob); } } @@ -231,10 +232,7 @@ function collectPaths(node: INode): INode[] { return results; } -export async function createCellSvg( - handler: VectraceHandler, - cell: GridCell -) { +export async function createCellSvg(handler: VectraceHandler, cell: GridCell) { const pathElements: string[] = []; for (const imageObject of handler.imagesRenders) { if (!imageObject.visible) continue; @@ -249,11 +247,7 @@ export async function createCellSvg( const imgH = imageObject.image.naturalHeight * imageObject.scale; // Does this image even overlap the cell at all? - const overlaps = - imgX + imgW > cell.x && - imgX < cell.x + cell.w && - imgY + imgH > cell.y && - imgY < cell.y + cell.h; + const overlaps = imgX + imgW > cell.x && imgX < cell.x + cell.w && imgY + imgH > cell.y && imgY < cell.y + cell.h; if (!overlaps) continue; @@ -270,8 +264,8 @@ export async function createCellSvg( pathElements.push( `` + - `` + - `` + `` + + ``, ); } } @@ -284,4 +278,4 @@ export async function createCellSvg( ${pathElements.join("\n ")} `; return new Blob([svgString], { type: "image/svg+xml" }); -} \ No newline at end of file +}