page.ts
1 import type { PDFFont, PDFPage } from "@cantoo/pdf-lib"; 2 import type { Element } from "~/elements"; 3 import type { MemoryFont } from "~/utils/fonts"; 4 import { PageSizes } from "@cantoo/pdf-lib"; 5 import Yoga, { Direction } from "yoga-layout"; 6 7 export class Page { 8 private _elements: Array<Element> = []; 9 private _h: number; 10 private _w: number; 11 12 constructor() { 13 [this._w, this._h] = PageSizes.A4; 14 } 15 16 child(element: Element): Page { 17 this._elements.push(element); 18 return this; 19 } 20 21 /** 22 * Defines the height of the page in pt. 23 * @default 841.8898 // A4 24 */ 25 h(height: number): Page { 26 this._h = height; 27 return this; 28 } 29 30 /** 31 * Calculate the layout and draw elements in the page. 32 * Internal only, you must not use the function. 33 * 34 * @internal 35 */ 36 render(page: PDFPage, fonts: Map<MemoryFont, PDFFont>): void { 37 const root = Yoga.Node.create(); 38 page.setSize(this._w, this._h); 39 40 // Append all nodes to Yoga to calculate layout. 41 for (let i = 0; i < this._elements.length; i++) { 42 const element = this._elements[i]!; 43 const node = element.getLayoutNode(page, fonts); 44 45 root.insertChild(node, i); 46 } 47 48 // Calculate the layout of all the elements inside this page. 49 root.calculateLayout(this._w, this._h, Direction.LTR); 50 51 // Once we have the layout with proper dimensions, we can draw to the PDF. 52 for (const element of this._elements) { 53 element.draw(page, fonts); 54 } 55 } 56 57 /** 58 * Defines the width and height of the page in pt. 59 * @default [595.276, 841.8898] // A4 60 * @example 61 * page().size([595.276, 841.8898]); 62 * @example 63 * page().size(PageSizes.A4); 64 */ 65 size(size: [w: number, h: number]): Page { 66 [this._w, this._h] = size; 67 return this; 68 } 69 70 /** 71 * Defines the width of the page in pt. 72 * @default 595.276 // A4 73 */ 74 w(width: number): Page { 75 this._w = width; 76 return this; 77 } 78 } 79 export const page = (): Page => new Page();