[breaking]: FreeSewing v4 (#7297)
Refer to the CHANGELOG for all info. --------- Co-authored-by: Wouter van Wageningen <wouter.vdub@yahoo.com> Co-authored-by: Josh Munic <jpmunic@gmail.com> Co-authored-by: Jonathan Haas <haasjona@gmail.com>
This commit is contained in:
parent
d22fbe78d9
commit
51dc1d9732
6626 changed files with 142053 additions and 150606 deletions
262
packages/react/components/Editor/lib/export/pdf-maker.mjs
Normal file
262
packages/react/components/Editor/lib/export/pdf-maker.mjs
Normal file
|
@ -0,0 +1,262 @@
|
|||
// __SDEFILE__ - This file is a dependency for the stand-alone environment
|
||||
import { Pdf, mmToPoints } from './pdf.mjs'
|
||||
import SVGtoPDF from 'svg-to-pdfkit'
|
||||
import { logoPath } from '@freesewing/config'
|
||||
|
||||
/** 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}" />
|
||||
</svg>`
|
||||
|
||||
const lineStart = 50
|
||||
/**
|
||||
* 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
|
||||
/** 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
|
||||
lineLevel = 50
|
||||
|
||||
constructor({ svg, pageSettings, pages, strings, cutLayouts }) {
|
||||
this.pageSettings = pageSettings
|
||||
this.pagesWithContent = pages.withContent
|
||||
this.svg = svg
|
||||
this.strings = strings
|
||||
this.cutLayouts = cutLayouts
|
||||
|
||||
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
|
||||
this.svgWidth = this.columns * this.pageWidth
|
||||
this.svgHeight = this.rows * this.pageHeight
|
||||
}
|
||||
|
||||
/** make the pdf */
|
||||
async makePdf() {
|
||||
await this.generateCoverPage()
|
||||
await this.generateCutLayoutPages()
|
||||
await this.generatePages()
|
||||
}
|
||||
|
||||
/** convert the pdf to a blob */
|
||||
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
|
||||
}
|
||||
|
||||
this.nextPage()
|
||||
await this.generateCoverPageTitle()
|
||||
await this.generateSvgPage(this.svg)
|
||||
}
|
||||
|
||||
/** generate a page that has an svg centered in it below any text */
|
||||
async generateSvgPage(svg) {
|
||||
//abitrary margin for visual space
|
||||
let coverMargin = 85
|
||||
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
|
||||
await SVGtoPDF(this.pdf, svg, coverMargin, this.lineLevel + coverMargin, {
|
||||
width: coverWidth,
|
||||
height: coverHeight,
|
||||
assumePt: false,
|
||||
// use aspect ratio to center it
|
||||
preserveAspectRatio: 'xMidYMid meet',
|
||||
})
|
||||
|
||||
// increment page count
|
||||
this.pageCount++
|
||||
}
|
||||
|
||||
/** generate the title for the cover page */
|
||||
async generateCoverPageTitle() {
|
||||
// FreeSewing tag
|
||||
this.addText('FreeSewing', 20).addText(this.strings.tagline, 10, 4)
|
||||
|
||||
// Design name, version, and Measurement Set
|
||||
this.addText(this.strings.design, 32)
|
||||
let savedLineLevel = this.lineLevel - 27
|
||||
let savedWidth = this.pdf.widthOfString(this.strings.design) + 50
|
||||
const versionSetString = ' v' + this.strings.version + ' ( ' + this.strings.setName + ' )'
|
||||
this.pdf.fontSize(18)
|
||||
this.pdf.text(versionSetString, savedWidth, savedLineLevel)
|
||||
|
||||
// Date and timestamp
|
||||
const currentDateTime = new Date().toLocaleString('en', {
|
||||
weekday: 'long',
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
timeZoneName: 'short',
|
||||
})
|
||||
this.addText(currentDateTime, 10)
|
||||
|
||||
// Settings YAML
|
||||
this.addText('Settings: ', 10)
|
||||
savedLineLevel = this.lineLevel - 9
|
||||
savedWidth = this.pdf.widthOfString('Settings: ') + 50
|
||||
this.pdf.fontSize(6)
|
||||
this.pdf.text('(Measurement values are in mm.)', savedWidth, savedLineLevel)
|
||||
this.addText(this.strings.yaml, 8)
|
||||
|
||||
// Notes and Warnings
|
||||
if (this.strings.notes) {
|
||||
this.addText('Notes:', 10).addText(this.strings.notes, 8)
|
||||
}
|
||||
if (this.strings.warns) {
|
||||
this.addText('Warnings:', 10).addText(this.strings.warns, 8)
|
||||
}
|
||||
|
||||
await SVGtoPDF(this.pdf, logoSvg, this.pdf.page.width - lineStart - 50, lineStart, {
|
||||
width: 50,
|
||||
height: this.lineLevel - lineStart,
|
||||
preserveAspectRatio: 'xMaxYMin meet',
|
||||
})
|
||||
|
||||
this.pdf.lineWidth(1)
|
||||
this.pdf
|
||||
.moveTo(lineStart, this.lineLevel)
|
||||
.lineTo(this.pdf.page.width - lineStart, this.lineLevel)
|
||||
.stroke()
|
||||
|
||||
this.lineLevel += 8
|
||||
this.pdf.fillColor('#888888')
|
||||
/*
|
||||
* Don't print URL on pattern. See #5526
|
||||
*/
|
||||
//this.addText(this.strings.url, 10)
|
||||
}
|
||||
|
||||
/** generate the title for a cutting layout page */
|
||||
async generateCutLayoutTitle(materialTitle, materialDimensions) {
|
||||
this.addText(this.strings.cuttingLayout, 12, 2).addText(materialTitle, 28)
|
||||
|
||||
this.pdf.lineWidth(1)
|
||||
this.pdf
|
||||
.moveTo(lineStart, this.lineLevel)
|
||||
.lineTo(this.pdf.page.width - lineStart, this.lineLevel)
|
||||
.stroke()
|
||||
|
||||
this.lineLevel += 5
|
||||
this.addText(materialDimensions, 16)
|
||||
}
|
||||
|
||||
/** generate all cutting layout pages */
|
||||
async generateCutLayoutPages() {
|
||||
if (!this.pageSettings.cutlist || !this.cutLayouts) return
|
||||
|
||||
for (const material in this.cutLayouts) {
|
||||
this.nextPage()
|
||||
const { title, dimensions, svg } = this.cutLayouts[material]
|
||||
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',
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
this.nextPage()
|
||||
|
||||
// add the pdf to the page, offset by the page distances
|
||||
await SVGtoPDF(this.pdf, this.svg, x, y, options)
|
||||
this.pageCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Reset to a clean page */
|
||||
nextPage() {
|
||||
// set the line level back to the top
|
||||
this.lineLevel = lineStart
|
||||
|
||||
// if no pages have been made, we can use the current
|
||||
if (this.pageCount === 0) return
|
||||
|
||||
// otherwise make a new page
|
||||
this.pdf.addPage()
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
addText(text, fontSize, marginBottom = 0) {
|
||||
this.pdf.fontSize(fontSize)
|
||||
this.pdf.text(text, 50, this.lineLevel)
|
||||
|
||||
this.lineLevel += this.pdf.heightOfString(text) + marginBottom
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue