const name = 'Pages Plugin' const version = '1.0.0' export const sizes = { a4: [ 210, 297 ], a3: [ 297, 420 ], a2: [ 420, 594 ], a1: [ 594, 841 ], a0: [ 841, 1188 ], letter: [ 215.9, 279.4 ], tabloid: [ 279.4, 431.8 ], } /** get a letter to represent an index */ const indexLetter = (i) => String.fromCharCode('A'.charCodeAt(0) + i - 1) /** * A plugin to add printer pages * */ export const pagesPlugin = ({ size='a4', orientation='portrait', margin=10, printStyle = false, /** should the pages be rendered for printing or for screen viewing? */ setPatternSize = true }) => { const ls = orientation === 'landscape' let sheetHeight = sizes[size][ls ? 0 : 1] let sheetWidth = sizes[size][ls ? 1 : 0] sheetWidth -= margin * 2 sheetHeight -= margin * 2 return basePlugin({sheetWidth, sheetHeight, orientation, printStyle, setPatternSize}) } const doScanForBlanks = (parts, layout, x, y, w, h) => { let hasContent = false for (var p in parts) { let part = parts[p] // skip the pages part and any that aren't rendered if (part === this || part.render === false || part.isEmpty()) continue // get the position of the part let partLayout = layout.parts[p] let partMinX = (partLayout.tl?.x || (partLayout.move.x + part.topLeft.x)) let partMinY = (partLayout.tl?.y || (partLayout.move.y + part.topLeft.y)) let partMaxX = (partLayout.br?.x || (partMinX + part.width)) let partMaxY = (partLayout.br?.y || (partMinY + part.height)) // check if the part overlaps the page extents if ( // if the left of the part is further left than the right end of the page partMinX < x + w && // and the top of the part is above the bottom of the page partMinY < y + h && // and the right of the part is further right than the left of the page partMaxX > x && // and the bottom of the part is below the top to the page partMaxY > y ) { // the part has content inside the page hasContent = true; // so we stop looking break; } } return hasContent } /** * The base plugin for adding a layout helper part like pages or fabric * sheetWidth: the width of the helper part * sheetHeight: the height of the helper part * boundary: should the helper part calculate its boundary? * responsiveColumns: should the part make more columns if the pattern exceed its width? (for pages you want this, for fabric you don't) * printStyle: hould the pages be rendered for printing or for screen viewing? * */ const basePlugin = ({ sheetWidth, sheetHeight, boundary=false, partName="pages", responsiveColumns=true, printStyle=false, scanForBlanks=true, renderBlanks=true, setPatternSize=false }) => ({ name, version, hooks: { postLayout: function(pattern) { // Add part pattern.parts[partName] = pattern.Part(partName) // Keep part out of layout pattern.parts[partName].layout = false // But add the part to the autoLayout property pattern.autoLayout.parts[partName] = { move: { x: 0, y: 0 } } // Add pages const { macro } = pattern.parts[partName].shorthand() let { height, width } = pattern if (!responsiveColumns) width = sheetWidth; if (pattern.settings.layout?.topLeft) { height += pattern.settings.layout.topLeft.y responsiveColumns && (width += pattern.settings.layout.topLeft.x) } macro('addPages', { size: [sheetHeight,sheetWidth, ], height, width }) if (boundary) pattern.parts[partName].boundary(); if (setPatternSize) { pattern.width = sheetWidth * pattern.parts[partName].pages.cols pattern.height = sheetHeight * pattern.parts[partName].pages.rows } } }, macros: { /** draft the pages */ addPages: function(so) { const [h,w] = so.size const cols = Math.ceil(so.width / w) const rows = Math.ceil(so.height / h) const { points, Point, paths, Path, macro } = this.shorthand() let count = 0 let withContent = {} // get the layout from the pattern const layout = typeof this.context.settings.layout === 'object' ? this.context.settings.layout : this.context.autoLayout; for (let row=0;row