1
0
Fork 0
freesewing/sites/shared/components/workbench/exporting/pdf-maker.mjs

223 lines
6.4 KiB
JavaScript
Raw Normal View History

2023-08-06 18:24:14 +00:00
import { Pdf, mmToPoints } from './pdf.mjs'
2022-08-17 13:11:22 -05:00
import SVGtoPDF from 'svg-to-pdfkit'
import { logoPath } from 'shared/components/logos/freesewing.mjs'
2022-08-17 13:11:22 -05:00
2022-08-24 12:07:08 -05:00
/** an svg of the logo to put on the cover page */
const logoSvg = `<svg viewBox="0 0 25 25">
<style> path {fill: none; stroke: #555555; stroke-width: 0.25} </style>
<path d="${logoPath}" />
2022-08-24 00:23:45 -05:00
</svg>`
2023-03-15 12:48:46 -05:00
const lineStart = 50
2022-08-17 13:11:22 -05:00
/**
* Freesewing's first explicit class?
* handles pdf exporting
*/
export class PdfMaker {
/** the svg as text to embed in the pdf */
svg
/** the document configuration */
pageSettings
/** the pdfKit instance that is writing the document */
pdf
/** the export buffer to hold pdfKit output */
buffers
/** translated strings to add to the cover page */
strings
2023-03-19 20:39:31 -05:00
/** cutting layout svgs and strings */
cutLayouts
/** the usable width (excluding margin) of the pdf page, in points */
pageWidth
/** the usable height (excluding margin) of the pdf page, in points */
pageHeight
/** the page margin, in points */
margin
/** the number of columns of pages in the svg */
columns
/** the number of rows of pages in the svg */
rows
/** the width of the entire svg, in points */
svgWidth
/** the height of the entire svg, in points */
svgHeight
pageCount = 0
2023-03-15 12:48:46 -05:00
lineLevel = 50
constructor({ svg, pageSettings, pages, strings, cutLayouts }) {
this.pageSettings = pageSettings
this.pagesWithContent = pages.withContent
this.svg = svg
this.strings = strings
2023-03-15 12:48:46 -05:00
this.cutLayouts = cutLayouts
2023-08-06 18:24:14 +00:00
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
this.pageWidth = this.pdf.page.width - this.margin * 2 // this is in points because it comes from pdfKit
// get the pages data
this.columns = pages.cols
this.rows = pages.rows
// calculate the width of the svg in points
2022-11-14 14:02:11 -06:00
this.svgWidth = this.columns * this.pageWidth
this.svgHeight = this.rows * this.pageHeight
}
/** make the pdf */
async makePdf() {
await this.generateCoverPage()
2023-03-15 12:48:46 -05:00
await this.generateCutLayoutPages()
await this.generatePages()
}
/** convert the pdf to a blob */
2023-08-06 18:24:14 +00:00
async toBlob() {
return this.pdf.toBlob()
}
/** generate the cover page for the pdf */
async generateCoverPage() {
// don't make one if it's not requested
if (!this.pageSettings.coverPage) {
return
}
2023-03-15 12:48:46 -05:00
this.nextPage()
await this.generateCoverPageTitle()
await this.generateSvgPage(this.svg)
}
2023-03-19 20:39:31 -05:00
/** generate a page that has an svg centered in it below any text */
2023-03-15 12:48:46 -05:00
async generateSvgPage(svg) {
//abitrary margin for visual space
let coverMargin = 85
2023-03-15 12:48:46 -05:00
let coverHeight = this.pdf.page.height - coverMargin * 2 - this.lineLevel
let coverWidth = this.pdf.page.width - coverMargin * 2
// add the entire pdf to the page, so that it fills the available space as best it can
2023-03-15 12:48:46 -05:00
await SVGtoPDF(this.pdf, svg, coverMargin, this.lineLevel + coverMargin, {
width: coverWidth,
height: coverHeight,
assumePt: false,
// use aspect ratio to center it
preserveAspectRatio: 'xMidYMid meet',
})
2023-03-19 20:39:31 -05:00
// increment page count
this.pageCount++
}
2023-03-19 20:39:31 -05:00
/** generate the title for the cover page */
async generateCoverPageTitle() {
2023-03-15 12:48:46 -05:00
this.addText('FreeSewing', 28)
.addText(this.strings.tagline, 12, 20)
.addText(this.strings.design, 48, -8)
await SVGtoPDF(this.pdf, logoSvg, this.pdf.page.width - lineStart - 100, lineStart, {
width: 100,
2023-03-15 12:48:46 -05:00
height: this.lineLevel - lineStart,
preserveAspectRatio: 'xMaxYMin meet',
})
this.pdf.lineWidth(1)
this.pdf
2023-03-15 12:48:46 -05:00
.moveTo(lineStart, this.lineLevel)
.lineTo(this.pdf.page.width - lineStart, this.lineLevel)
.stroke()
2023-03-15 12:48:46 -05:00
this.lineLevel += 8
this.pdf.fillColor('#888888')
2023-03-15 12:48:46 -05:00
this.addText(this.strings.url, 10)
}
2023-03-19 20:39:31 -05:00
/** generate the title for a cutting layout page */
2023-06-06 11:17:14 -05:00
async generateCutLayoutTitle(materialTitle, materialDimensions) {
this.addText(this.strings.cuttingLayout, 12, 2).addText(materialTitle, 28)
2023-03-15 12:48:46 -05:00
this.pdf.lineWidth(1)
this.pdf
.moveTo(lineStart, this.lineLevel)
.lineTo(this.pdf.page.width - lineStart, this.lineLevel)
.stroke()
this.lineLevel += 5
2023-06-06 11:17:14 -05:00
this.addText(materialDimensions, 16)
2023-03-15 12:48:46 -05:00
}
2023-03-19 20:39:31 -05:00
/** generate all cutting layout pages */
2023-03-15 12:48:46 -05:00
async generateCutLayoutPages() {
if (!this.pageSettings.cutlist || !this.cutLayouts) return
2023-03-15 12:48:46 -05:00
2023-06-06 11:17:14 -05:00
for (const material in this.cutLayouts) {
2023-03-15 12:48:46 -05:00
this.nextPage()
2023-06-06 11:17:14 -05:00
const { title, dimensions, svg } = this.cutLayouts[material]
2023-03-15 12:48:46 -05:00
await this.generateCutLayoutTitle(title, dimensions)
await this.generateSvgPage(svg)
}
}
/** generate the pages of the pdf */
async generatePages() {
// pass the same options to the svg converter for each page
const options = {
assumePt: true,
width: this.svgWidth,
height: this.svgHeight,
preserveAspectRatio: 'xMinYMin slice',
}
2022-11-14 14:02:11 -06:00
// everything is offset by a margin so that it's centered on the page
const startMargin = this.margin
for (var h = 0; h < this.rows; h++) {
for (var w = 0; w < this.columns; w++) {
// skip empty pages
if (!this.pagesWithContent[h][w]) continue
// position it
let x = -w * this.pageWidth + startMargin
let y = -h * this.pageHeight + startMargin
2023-03-15 12:48:46 -05:00
this.nextPage()
// add the pdf to the page, offset by the page distances
await SVGtoPDF(this.pdf, this.svg, x, y, options)
this.pageCount++
}
}
}
2023-03-15 12:48:46 -05:00
2023-03-19 20:39:31 -05:00
/** Reset to a clean page */
2023-03-15 12:48:46 -05:00
nextPage() {
2023-03-19 20:39:31 -05:00
// set the line level back to the top
2023-03-15 12:48:46 -05:00
this.lineLevel = lineStart
2023-03-19 20:39:31 -05:00
// if no pages have been made, we can use the current
2023-03-15 12:48:46 -05:00
if (this.pageCount === 0) return
// otherwise make a new page
this.pdf.addPage()
}
2023-03-19 20:39:31 -05:00
/**
* Add Text to the page at the current line level
* @param {String} text the text to add
* @param {Number} fontSize the size for the text
* @param {Number} marginBottom additional margin to add below the text
*/
2023-03-15 12:48:46 -05:00
addText(text, fontSize, marginBottom = 0) {
this.pdf.fontSize(fontSize)
this.pdf.text(text, 50, this.lineLevel)
this.lineLevel += fontSize + marginBottom
return this
}
2022-08-17 13:11:22 -05:00
}