add single-page pdf export
This commit is contained in:
parent
bf417a201f
commit
2867b9c340
6 changed files with 83 additions and 45 deletions
|
@ -155,13 +155,11 @@ export const handleExport = async ({
|
|||
let pattern = themedPattern(Design, settings, { layout }, format, t)
|
||||
|
||||
// a specified size should override the settings one
|
||||
if (format !== 'pdf') {
|
||||
pageSettings.size = format
|
||||
}
|
||||
pageSettings.size = format
|
||||
|
||||
try {
|
||||
// add pages to pdf exports
|
||||
if (format !== 'svg') {
|
||||
if (!exportTypes.exportForEditing.includes(format)) {
|
||||
pattern.use(
|
||||
pagesPlugin({
|
||||
...pageSettings,
|
||||
|
@ -184,11 +182,13 @@ export const handleExport = async ({
|
|||
pattern.draft()
|
||||
workerArgs.svg = pattern.render()
|
||||
|
||||
if (format === 'pdf') pageSettings.size = [pattern.width, pattern.height]
|
||||
|
||||
// add the svg and pages data to the worker args
|
||||
workerArgs.pages = pattern.setStores[pattern.activeSet].get('pages')
|
||||
|
||||
// add cutting layouts if requested
|
||||
if (format !== 'svg' && pageSettings.cutlist) {
|
||||
if (!exportTypes.exportForEditing.includes(format) && pageSettings.cutlist) {
|
||||
workerArgs.cutLayouts = generateCutLayouts(pattern, Design, settings, format, t, ui)
|
||||
}
|
||||
} catch (err) {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import yaml from 'js-yaml'
|
||||
import axios from 'axios'
|
||||
import { PdfMaker } from './pdf-maker'
|
||||
import { SinglePdfMaker } from './single-pdf-maker.mjs'
|
||||
|
||||
/** when the worker receives data from the page, do the appropriate export */
|
||||
addEventListener('message', async (e) => {
|
||||
|
@ -49,7 +50,7 @@ const exportYaml = (settings) => exportBlob(yaml.dump(settings), 'application/x-
|
|||
const exportSvg = (svg) => exportBlob(svg, 'image/svg+xml')
|
||||
|
||||
const exportPdf = async (data) => {
|
||||
const maker = new PdfMaker(data)
|
||||
const maker = data.format === 'pdf' ? new SinglePdfMaker(data) : new PdfMaker(data)
|
||||
await maker.makePdf()
|
||||
postSuccess(await maker.toBlob())
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import PDFDocument from 'pdfkit/js/pdfkit.standalone'
|
||||
import { Pdf, mmToPoints } from './pdf.mjs'
|
||||
import SVGtoPDF from 'svg-to-pdfkit'
|
||||
import { logoPath } from 'shared/components/logos/freesewing.mjs'
|
||||
|
||||
|
@ -8,11 +8,6 @@ const logoSvg = `<svg viewBox="0 0 25 25">
|
|||
<path d="${logoPath}" />
|
||||
</svg>`
|
||||
|
||||
/**
|
||||
* PdfKit, the library we're using for pdf generation, uses points as a unit, so when we tell it things like where to put the svg and how big the svg is, we need those numbers to be in points
|
||||
* The svg uses mm internally, so when we do spatial reasoning inside the svg, we need to know values in mm
|
||||
* */
|
||||
const mmToPoints = 2.834645669291339
|
||||
const lineStart = 50
|
||||
/**
|
||||
* Freesewing's first explicit class?
|
||||
|
@ -58,7 +53,10 @@ export class PdfMaker {
|
|||
this.strings = strings
|
||||
this.cutLayouts = cutLayouts
|
||||
|
||||
this.initPdf()
|
||||
this.pdf = Pdf({
|
||||
size: this.pageSettings.size.toUpperCase(),
|
||||
layout: this.pageSettings.orientation,
|
||||
})
|
||||
|
||||
this.margin = this.pageSettings.margin * mmToPoints // margin is in mm because it comes from us, so we convert it to points
|
||||
this.pageHeight = this.pdf.page.height - this.margin * 2 // this is in points because it comes from pdfKit
|
||||
|
@ -73,22 +71,6 @@ export class PdfMaker {
|
|||
this.svgHeight = this.rows * this.pageHeight
|
||||
}
|
||||
|
||||
/** create the pdf document */
|
||||
initPdf() {
|
||||
// instantiate with the correct size and orientation
|
||||
this.pdf = new PDFDocument({
|
||||
size: this.pageSettings.size.toUpperCase(),
|
||||
layout: this.pageSettings.orientation,
|
||||
})
|
||||
|
||||
// PdfKit wants to flush the buffer on each new page.
|
||||
// We can't save directly from inside a worker, so we have to manage the buffers ourselves so we can return a blob
|
||||
this.buffers = []
|
||||
|
||||
// use a listener to add new data to our buffer storage
|
||||
this.pdf.on('data', this.buffers.push.bind(this.buffers))
|
||||
}
|
||||
|
||||
/** make the pdf */
|
||||
async makePdf() {
|
||||
await this.generateCoverPage()
|
||||
|
@ -97,21 +79,8 @@ export class PdfMaker {
|
|||
}
|
||||
|
||||
/** convert the pdf to a blob */
|
||||
toBlob() {
|
||||
return new Promise((resolve) => {
|
||||
// have to do it this way so that the document flushes everything to buffers
|
||||
this.pdf.on('end', () => {
|
||||
// convert buffers to a blob
|
||||
resolve(
|
||||
new Blob(this.buffers, {
|
||||
type: 'application/pdf',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
// end the stream
|
||||
this.pdf.end()
|
||||
})
|
||||
async toBlob() {
|
||||
return this.pdf.toBlob()
|
||||
}
|
||||
|
||||
/** generate the cover page for the pdf */
|
||||
|
|
45
sites/shared/components/workbench/exporting/pdf.mjs
Normal file
45
sites/shared/components/workbench/exporting/pdf.mjs
Normal file
|
@ -0,0 +1,45 @@
|
|||
import PDFDocument from 'pdfkit/js/pdfkit.standalone'
|
||||
|
||||
/**
|
||||
* PdfKit, the library we're using for pdf generation, uses points as a unit, so when we tell it things like where to put the svg and how big the svg is, we need those numbers to be in points
|
||||
* The svg uses mm internally, so when we do spatial reasoning inside the svg, we need to know values in mm
|
||||
* */
|
||||
export const mmToPoints = 2.834645669291339
|
||||
|
||||
/**
|
||||
* A PDFKit Pdf with a few of our utilities included
|
||||
* @returns
|
||||
*/
|
||||
export const Pdf = ({ size, layout }) => {
|
||||
const pdf = new PDFDocument({
|
||||
size,
|
||||
layout,
|
||||
})
|
||||
|
||||
// PdfKit wants to flush the buffer on each new page.
|
||||
// We can't save directly from inside a worker, so we have to manage the buffers ourselves so we can return a blob
|
||||
const buffers = []
|
||||
|
||||
// use a listener to add new data to our buffer storage
|
||||
pdf.on('data', buffers.push.bind(buffers))
|
||||
|
||||
/** convert the pdf to a blob */
|
||||
pdf.toBlob = function () {
|
||||
return new Promise((resolve) => {
|
||||
// have to do it this way so that the document flushes everything to buffers
|
||||
pdf.on('end', () => {
|
||||
// convert buffers to a blob
|
||||
resolve(
|
||||
new Blob(buffers, {
|
||||
type: 'application/pdf',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
// end the stream
|
||||
pdf.end()
|
||||
})
|
||||
}
|
||||
|
||||
return pdf
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
import { Pdf, mmToPoints } from './pdf.mjs'
|
||||
import SVGtoPDF from 'svg-to-pdfkit'
|
||||
|
||||
/**
|
||||
* Basic exporter for a single-page pdf containing the rendered pattern.
|
||||
* This generates a PDF that is the size of the pattern and has no additional frills*/
|
||||
export class SinglePdfMaker {
|
||||
pdf
|
||||
svg
|
||||
|
||||
constructor({ svg, pageSettings }) {
|
||||
this.pdf = Pdf({ size: pageSettings.size.map((s) => s * mmToPoints) })
|
||||
this.svg = svg
|
||||
}
|
||||
|
||||
async makePdf() {
|
||||
await SVGtoPDF(this.pdf, this.svg)
|
||||
}
|
||||
|
||||
async toBlob() {
|
||||
return this.pdf.toBlob()
|
||||
}
|
||||
}
|
|
@ -73,7 +73,7 @@ export const PrintView = ({
|
|||
|
||||
const exportIt = () => {
|
||||
handleExport({
|
||||
format: 'pdf',
|
||||
format: pageSettings.size,
|
||||
settings,
|
||||
design,
|
||||
t,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue