@jasy/pdf 1.0.0-alpha.1 → 1.0.0-alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +35 -21
- package/dist/api/args.d.ts +1 -1
- package/dist/api/args.js +2 -5
- package/dist/api/color.d.ts +4 -4
- package/dist/api/color.js +11 -17
- package/dist/api/content.d.ts +20 -13
- package/dist/api/content.js +44 -29
- package/dist/api/descriptor.d.ts +2 -2
- package/dist/api/descriptor.js +121 -31
- package/dist/api/dimension.d.ts +76 -0
- package/dist/api/dimension.js +43 -0
- package/dist/api/font-url.d.ts +28 -0
- package/dist/api/font-url.js +134 -0
- package/dist/api/forms.d.ts +347 -0
- package/dist/api/forms.js +189 -0
- package/dist/api/gradient.d.ts +53 -0
- package/dist/api/gradient.js +97 -0
- package/dist/api/index.d.ts +13 -8
- package/dist/api/index.js +13 -24
- package/dist/api/insets.d.ts +19 -12
- package/dist/api/insets.js +19 -12
- package/dist/api/layout.d.ts +149 -25
- package/dist/api/layout.js +182 -51
- package/dist/api/page-builder.d.ts +40 -0
- package/dist/api/page-builder.js +44 -0
- package/dist/api/structure.d.ts +107 -13
- package/dist/api/structure.js +187 -88
- package/dist/api/table.d.ts +5 -5
- package/dist/api/table.js +38 -26
- package/dist/api/text.d.ts +90 -4
- package/dist/api/text.js +116 -31
- package/dist/assets/font-data.d.ts +2 -0
- package/dist/assets/font-data.js +21 -0
- package/dist/assets/font-data.ts +37 -0
- package/dist/common/color.js +1 -5
- package/dist/constants/page-sizes.js +3 -6
- package/dist/constants/pdf-parts.js +1 -4
- package/dist/crypto/legacy-handler.d.ts +43 -0
- package/dist/crypto/legacy-handler.js +145 -0
- package/dist/crypto/security-handler.d.ts +62 -0
- package/dist/crypto/security-handler.js +155 -0
- package/dist/crypto/webcrypto.d.ts +11 -0
- package/dist/crypto/webcrypto.js +62 -0
- package/dist/edit/acroform-reader.d.ts +70 -0
- package/dist/edit/acroform-reader.js +126 -0
- package/dist/edit/appearance.d.ts +47 -0
- package/dist/edit/appearance.js +171 -0
- package/dist/edit/document.d.ts +145 -0
- package/dist/edit/document.js +642 -0
- package/dist/edit/fill.d.ts +65 -0
- package/dist/edit/fill.js +424 -0
- package/dist/edit/flatten.d.ts +54 -0
- package/dist/edit/flatten.js +462 -0
- package/dist/edit/index.d.ts +20 -0
- package/dist/edit/index.js +18 -0
- package/dist/edit/lexer.d.ts +30 -0
- package/dist/edit/lexer.js +285 -0
- package/dist/edit/objects.d.ts +68 -0
- package/dist/edit/objects.js +83 -0
- package/dist/edit/writer.d.ts +60 -0
- package/dist/edit/writer.js +283 -0
- package/dist/elements/container-element.d.ts +50 -5
- package/dist/elements/container-element.js +100 -39
- package/dist/elements/forms/checkbox-element.d.ts +51 -0
- package/dist/elements/forms/checkbox-element.js +48 -0
- package/dist/elements/forms/choice-element.d.ts +53 -0
- package/dist/elements/forms/choice-element.js +59 -0
- package/dist/elements/forms/push-button-element.d.ts +56 -0
- package/dist/elements/forms/push-button-element.js +49 -0
- package/dist/elements/forms/radio-element.d.ts +52 -0
- package/dist/elements/forms/radio-element.js +49 -0
- package/dist/elements/forms/signature-element.d.ts +54 -0
- package/dist/elements/forms/signature-element.js +47 -0
- package/dist/elements/forms/text-field-element.d.ts +61 -0
- package/dist/elements/forms/text-field-element.js +54 -0
- package/dist/elements/image-element.d.ts +58 -6
- package/dist/elements/image-element.js +145 -111
- package/dist/elements/index.d.ts +26 -10
- package/dist/elements/index.js +26 -28
- package/dist/elements/layout/anchor-element.d.ts +23 -0
- package/dist/elements/layout/anchor-element.js +27 -0
- package/dist/elements/layout/bookmark-element.d.ts +27 -0
- package/dist/elements/layout/bookmark-element.js +30 -0
- package/dist/elements/layout/default-text-style-element.d.ts +30 -0
- package/dist/elements/layout/default-text-style-element.js +47 -0
- package/dist/elements/layout/deferred-element.d.ts +3 -3
- package/dist/elements/layout/deferred-element.js +4 -8
- package/dist/elements/layout/expanded-element.d.ts +6 -4
- package/dist/elements/layout/expanded-element.js +22 -17
- package/dist/elements/layout/keep-together-element.d.ts +42 -0
- package/dist/elements/layout/keep-together-element.js +85 -0
- package/dist/elements/layout/link-element.d.ts +33 -0
- package/dist/elements/layout/link-element.js +39 -0
- package/dist/elements/layout/padding-element.d.ts +10 -5
- package/dist/elements/layout/padding-element.js +25 -16
- package/dist/elements/layout/page-break-element.d.ts +17 -0
- package/dist/elements/layout/page-break-element.js +24 -0
- package/dist/elements/layout/page-builder-element.d.ts +32 -0
- package/dist/elements/layout/page-builder-element.js +45 -0
- package/dist/elements/layout/positioned-element.d.ts +47 -0
- package/dist/elements/layout/positioned-element.js +73 -0
- package/dist/elements/layout/repeating-header-element.d.ts +3 -3
- package/dist/elements/layout/repeating-header-element.js +8 -12
- package/dist/elements/layout/rotated-box-element.d.ts +35 -0
- package/dist/elements/layout/rotated-box-element.js +54 -0
- package/dist/elements/layout/rotated-element.d.ts +32 -0
- package/dist/elements/layout/rotated-element.js +41 -0
- package/dist/elements/layout/sized-container-element.d.ts +2 -2
- package/dist/elements/layout/sized-container-element.js +6 -11
- package/dist/elements/layout/struct-group.d.ts +28 -0
- package/dist/elements/layout/struct-group.js +42 -0
- package/dist/elements/line-element.d.ts +3 -3
- package/dist/elements/line-element.js +5 -10
- package/dist/elements/page-element.d.ts +26 -6
- package/dist/elements/page-element.js +72 -27
- package/dist/elements/pdf-document-element.d.ts +10 -4
- package/dist/elements/pdf-document-element.js +11 -10
- package/dist/elements/pdf-element.d.ts +150 -4
- package/dist/elements/pdf-element.js +138 -20
- package/dist/elements/rectangle-element.d.ts +52 -11
- package/dist/elements/rectangle-element.js +129 -36
- package/dist/elements/row-element.d.ts +45 -4
- package/dist/elements/row-element.js +66 -18
- package/dist/elements/text-element.d.ts +139 -11
- package/dist/elements/text-element.js +234 -57
- package/dist/forms/acroform.d.ts +63 -0
- package/dist/forms/acroform.js +427 -0
- package/dist/forms/appearance.d.ts +58 -0
- package/dist/forms/appearance.js +204 -0
- package/dist/forms/field.d.ts +164 -0
- package/dist/forms/field.js +1 -0
- package/dist/forms/pdf.d.ts +19 -0
- package/dist/forms/pdf.js +28 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -19
- package/dist/ir/display-list.d.ts +197 -8
- package/dist/ir/display-list.js +8 -2
- package/dist/layout/alignment.d.ts +10 -0
- package/dist/layout/alignment.js +6 -0
- package/dist/layout/box-constraints.d.ts +61 -0
- package/dist/layout/box-constraints.js +88 -6
- package/dist/layout/collect-images.d.ts +9 -0
- package/dist/layout/collect-images.js +34 -0
- package/dist/layout/fragmentation.d.ts +20 -1
- package/dist/layout/fragmentation.js +74 -18
- package/dist/layout/insets.d.ts +28 -0
- package/dist/layout/insets.js +20 -0
- package/dist/platform/browser-fs.d.ts +2 -0
- package/dist/platform/browser-fs.js +9 -0
- package/dist/platform/browser-image.d.ts +5 -0
- package/dist/platform/browser-image.js +13 -0
- package/dist/platform/node-fs.d.ts +2 -0
- package/dist/platform/node-fs.js +10 -0
- package/dist/platform/node-image.d.ts +5 -0
- package/dist/platform/node-image.js +9 -0
- package/dist/renderer/anchor-renderer.d.ts +6 -0
- package/dist/renderer/anchor-renderer.js +11 -0
- package/dist/renderer/bookmark-renderer.d.ts +6 -0
- package/dist/renderer/bookmark-renderer.js +11 -0
- package/dist/renderer/container-renderer.d.ts +3 -3
- package/dist/renderer/container-renderer.js +11 -28
- package/dist/renderer/default-text-style-renderer.d.ts +6 -0
- package/dist/renderer/default-text-style-renderer.js +10 -0
- package/dist/renderer/deferred-renderer.d.ts +3 -3
- package/dist/renderer/deferred-renderer.js +8 -23
- package/dist/renderer/emoji-image.d.ts +9 -0
- package/dist/renderer/emoji-image.js +68 -0
- package/dist/renderer/expanded-renderer.d.ts +3 -3
- package/dist/renderer/expanded-renderer.js +6 -21
- package/dist/renderer/form-field-renderer.d.ts +20 -0
- package/dist/renderer/form-field-renderer.js +12 -0
- package/dist/renderer/image-renderer.d.ts +4 -4
- package/dist/renderer/image-renderer.js +86 -75
- package/dist/renderer/index.d.ts +10 -10
- package/dist/renderer/index.js +10 -26
- package/dist/renderer/keep-together-renderer.d.ts +10 -0
- package/dist/renderer/keep-together-renderer.js +12 -0
- package/dist/renderer/line-renderer.d.ts +3 -3
- package/dist/renderer/line-renderer.js +13 -28
- package/dist/renderer/link-renderer.d.ts +6 -0
- package/dist/renderer/link-renderer.js +11 -0
- package/dist/renderer/padding-renderer.d.ts +3 -3
- package/dist/renderer/padding-renderer.js +6 -21
- package/dist/renderer/page-break-renderer.d.ts +14 -0
- package/dist/renderer/page-break-renderer.js +15 -0
- package/dist/renderer/page-builder-renderer.d.ts +6 -0
- package/dist/renderer/page-builder-renderer.js +11 -0
- package/dist/renderer/page-renderer.d.ts +2 -2
- package/dist/renderer/page-renderer.js +115 -77
- package/dist/renderer/pdf-backend.d.ts +31 -4
- package/dist/renderer/pdf-backend.js +287 -49
- package/dist/renderer/pdf-config.js +4 -7
- package/dist/renderer/pdf-document-class.d.ts +5 -5
- package/dist/renderer/pdf-document-class.js +27 -41
- package/dist/renderer/pdf-document-renderer.d.ts +19 -10
- package/dist/renderer/pdf-document-renderer.js +135 -91
- package/dist/renderer/pdf-renderer.d.ts +2 -2
- package/dist/renderer/pdf-renderer.js +165 -90
- package/dist/renderer/positioned-renderer.d.ts +6 -0
- package/dist/renderer/positioned-renderer.js +10 -0
- package/dist/renderer/rectangle-renderer.d.ts +3 -3
- package/dist/renderer/rectangle-renderer.js +49 -44
- package/dist/renderer/repeating-header-renderer.d.ts +3 -3
- package/dist/renderer/repeating-header-renderer.js +10 -26
- package/dist/renderer/rotated-renderer.d.ts +7 -0
- package/dist/renderer/rotated-renderer.js +29 -0
- package/dist/renderer/row-renderer.d.ts +3 -3
- package/dist/renderer/row-renderer.js +11 -28
- package/dist/renderer/struct-group-renderer.d.ts +10 -0
- package/dist/renderer/struct-group-renderer.js +24 -0
- package/dist/renderer/text-renderer.d.ts +9 -5
- package/dist/renderer/text-renderer.js +437 -89
- package/dist/text/advance.d.ts +34 -0
- package/dist/text/advance.js +45 -0
- package/dist/text/arabic.d.ts +20 -0
- package/dist/text/arabic.js +101 -0
- package/dist/text/bidi.d.ts +33 -0
- package/dist/text/bidi.js +94 -0
- package/dist/text/emoji-codepoints.d.ts +1 -0
- package/dist/text/emoji-codepoints.js +29 -0
- package/dist/text/font-fallback.d.ts +25 -0
- package/dist/text/font-fallback.js +38 -0
- package/dist/text/glyph-coverage.d.ts +15 -0
- package/dist/text/glyph-coverage.js +77 -0
- package/dist/text/line-breaker.d.ts +50 -12
- package/dist/text/line-breaker.js +200 -54
- package/dist/text/line-metrics.d.ts +49 -0
- package/dist/text/line-metrics.js +57 -0
- package/dist/text/orphans-widows.d.ts +27 -0
- package/dist/text/orphans-widows.js +53 -0
- package/dist/text/shape.d.ts +29 -0
- package/dist/text/shape.js +67 -0
- package/dist/text/text-decoration.d.ts +50 -0
- package/dist/text/text-decoration.js +62 -0
- package/dist/text/text-style.d.ts +60 -0
- package/dist/text/text-style.js +79 -0
- package/dist/text/whitespace.d.ts +4 -0
- package/dist/text/whitespace.js +43 -0
- package/dist/utils/afm-parser.d.ts +34 -0
- package/dist/utils/afm-parser.js +76 -17
- package/dist/utils/bytes.d.ts +24 -0
- package/dist/utils/bytes.js +76 -0
- package/dist/utils/dest-registry.d.ts +22 -0
- package/dist/utils/dest-registry.js +32 -0
- package/dist/utils/flex-layout.d.ts +36 -9
- package/dist/utils/flex-layout.js +207 -30
- package/dist/utils/font-metrics.d.ts +26 -1
- package/dist/utils/font-metrics.js +1 -2
- package/dist/utils/font-path.js +3 -6
- package/dist/utils/gsub.d.ts +36 -0
- package/dist/utils/gsub.js +178 -0
- package/dist/utils/image-helper.d.ts +6 -5
- package/dist/utils/image-helper.js +101 -111
- package/dist/utils/inflate.d.ts +16 -0
- package/dist/utils/inflate.js +52 -0
- package/dist/utils/md5.d.ts +4 -0
- package/dist/utils/md5.js +79 -0
- package/dist/utils/outline.d.ts +21 -0
- package/dist/utils/outline.js +79 -0
- package/dist/utils/pdf-object-manager.d.ts +127 -8
- package/dist/utils/pdf-object-manager.js +615 -141
- package/dist/utils/renderer-registry.d.ts +13 -1
- package/dist/utils/renderer-registry.js +23 -6
- package/dist/utils/struct-tree.d.ts +44 -0
- package/dist/utils/struct-tree.js +129 -0
- package/dist/utils/ttf-parser.d.ts +134 -2
- package/dist/utils/ttf-parser.js +873 -50
- package/dist/utils/ttf-subsetter.d.ts +1 -1
- package/dist/utils/ttf-subsetter.js +40 -42
- package/dist/utils/ua-xmp.d.ts +9 -0
- package/dist/utils/ua-xmp.js +32 -0
- package/dist/utils/utf8-to-windows1252-encoder.d.ts +6 -0
- package/dist/utils/utf8-to-windows1252-encoder.js +11 -4
- package/dist/utils/woff.d.ts +10 -0
- package/dist/utils/woff.js +116 -0
- package/dist/validators/element-validator.d.ts +2 -2
- package/dist/validators/element-validator.js +31 -26
- package/package.json +22 -2
|
@@ -1,81 +1,119 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
1
|
+
import { pageFormats, PageSize } from "../constants/page-sizes.js";
|
|
2
|
+
import { RendererRegistry } from "../utils/renderer-registry.js";
|
|
3
|
+
import { Orientation } from "./pdf-config.js";
|
|
4
|
+
import { PdfBackend } from "./pdf-backend.js";
|
|
5
|
+
export class PageRenderer {
|
|
6
|
+
static async render(page, objectManager) {
|
|
7
|
+
const { children, config, header, footer } = page.getProps();
|
|
8
|
+
// Header (top band) and footer (bottom band) sit around the body and repeat on every
|
|
9
|
+
// physical page; they are placed by `PageElement.calculateLayout` / the page driver.
|
|
10
|
+
const renderables = [...(header ? [header] : []), ...children, ...(footer ? [footer] : [])];
|
|
11
|
+
// Page geometry (also the MediaBox below). Needed up front because flipping the
|
|
12
|
+
// display list to PDF coordinates uses the page height. config is fully resolved
|
|
13
|
+
// by the layout pass; fall back to the document default rather than asserting.
|
|
14
|
+
let [width, height] = config?.customSize ?? pageFormats[config?.pageSize ?? PageSize.A4];
|
|
15
|
+
if (config?.orientation === Orientation.landscape) {
|
|
16
|
+
[width, height] = [height, width];
|
|
17
|
+
}
|
|
18
|
+
// Collect the whole page as a display list (top-left coordinates), flip it to PDF
|
|
19
|
+
// coordinates at this one seam, then serialize once. Serializing registers the
|
|
20
|
+
// fonts/images used below, so it must run before the resource section.
|
|
21
|
+
const nodes = [];
|
|
22
|
+
for (const element of renderables) {
|
|
23
|
+
const renderer = RendererRegistry.getRenderer(element);
|
|
24
|
+
nodes.push(...(await renderer(element, objectManager)));
|
|
25
|
+
}
|
|
26
|
+
// Accessible tagging: one struct context per page (allocates its StructParents index), threaded into
|
|
27
|
+
// serialize so each drawable node is wrapped in marked content. Undefined = tagging off (byte-identical).
|
|
28
|
+
const structCtx = objectManager.struct.enabled ? objectManager.struct.beginPage() : undefined;
|
|
29
|
+
const flipped = PdfBackend.flipY(nodes, height);
|
|
30
|
+
const pageContent = PdfBackend.serialize(flipped, objectManager, structCtx);
|
|
31
|
+
// Add the page content as a new object (FlateDecode-compressed when enabled). The /Length is
|
|
32
|
+
// computed inside, with an explicit EOL before `endstream` (PDF/A clause 6.1.7.1).
|
|
33
|
+
const contentObjectNumber = objectManager.addContentStream(pageContent);
|
|
34
|
+
// Get the parent object number dynamically (linked with the page object)
|
|
35
|
+
const parentObjectNumber = objectManager.getParentObjectNumber(); // Get parent object number
|
|
36
|
+
// Page object with MediaBox
|
|
37
|
+
// - Get all fonts and add it to the page (reference)
|
|
38
|
+
objectManager.registerFont("Helvetica");
|
|
39
|
+
const fontReferences = [];
|
|
40
|
+
objectManager.getAllFontsRaw().forEach((value, _key) => {
|
|
41
|
+
const fontRef = `/F${value.fontIndex} ${value.resourceIndex} 0 R`;
|
|
42
|
+
fontReferences.push(fontRef);
|
|
43
|
+
});
|
|
44
|
+
// - Get all images and add it to the page (reference)
|
|
45
|
+
const imageReferences = [];
|
|
46
|
+
objectManager.getAllImagesRaw().forEach((value) => {
|
|
47
|
+
const imageRef = `/IM${value} ${value} 0 R`;
|
|
48
|
+
imageReferences.push(imageRef);
|
|
49
|
+
});
|
|
50
|
+
const imageCode = imageReferences.length > 0
|
|
51
|
+
? "/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] /XObject <<\n" +
|
|
52
|
+
imageReferences.join("\n") +
|
|
53
|
+
"\n>>\n"
|
|
54
|
+
: "";
|
|
55
|
+
// - Transparency (ExtGState) references, registered during serialize above
|
|
56
|
+
const extGStateReferences = [];
|
|
57
|
+
objectManager.getAllExtGStatesRaw().forEach((objectNumber, name) => {
|
|
58
|
+
extGStateReferences.push(`/${name} ${objectNumber} 0 R`);
|
|
59
|
+
});
|
|
60
|
+
const extGStateCode = extGStateReferences.length > 0
|
|
61
|
+
? "/ExtGState <<\n" + extGStateReferences.join("\n") + "\n>>\n"
|
|
62
|
+
: "";
|
|
63
|
+
// - Gradient shadings (color-glyph fills), registered during serialize above
|
|
64
|
+
const shadingReferences = [];
|
|
65
|
+
objectManager.getAllShadingsRaw().forEach((objectNumber, name) => {
|
|
66
|
+
shadingReferences.push(`/${name} ${objectNumber} 0 R`);
|
|
67
|
+
});
|
|
68
|
+
const shadingCode = shadingReferences.length > 0 ? "/Shading <<\n" + shadingReferences.join("\n") + "\n>>\n" : "";
|
|
69
|
+
// Hyperlinks: a `Link` IR node drew nothing into the content stream - here its (already Y-flipped)
|
|
70
|
+
// rect + href become a /Link annotation object. `/Border [0 0 0]` hides the default visible frame;
|
|
71
|
+
// the URL is escaped like any PDF literal string. Refs are collected into the page's /Annots below.
|
|
72
|
+
const num = (n) => Number(n.toFixed(2));
|
|
73
|
+
const annotRefs = [];
|
|
74
|
+
for (const node of flipped) {
|
|
75
|
+
// A form field: build its Widget annotation + register it as an /AcroForm field (the logic lives in
|
|
76
|
+
// forms/acroform.ts), then reference it here in the page /Annots - the same side channel as a link.
|
|
77
|
+
if (node.type === "formfield") {
|
|
78
|
+
annotRefs.push(`${objectManager.acroform.addField(node, objectManager)} 0 R`);
|
|
79
|
+
continue;
|
|
31
80
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
81
|
+
if (node.type !== "link")
|
|
82
|
+
continue;
|
|
83
|
+
const rect = `[${num(node.x)} ${num(node.y)} ${num(node.x + node.width)} ${num(node.y + node.height)}]`;
|
|
84
|
+
// Either an external URL (/URI) or an internal named destination (/GoTo, resolved via /Names /Dests).
|
|
85
|
+
// The Link IR guarantees exactly one is set; prefer `dest` when present.
|
|
86
|
+
const action = node.dest !== undefined
|
|
87
|
+
? `/A << /S /GoTo /D ${objectManager.pdfString(node.dest)} >>`
|
|
88
|
+
: `/A << /S /URI /URI ${objectManager.pdfString(node.href ?? "")} >>`;
|
|
89
|
+
const annot = objectManager.addObject(`<< /Type /Annot /Subtype /Link /Rect ${rect} /Border [0 0 0] ${action} >>`);
|
|
90
|
+
annotRefs.push(`${annot} 0 R`);
|
|
91
|
+
}
|
|
92
|
+
const annotsCode = annotRefs.length > 0 ? ` /Annots [${annotRefs.join(" ")}]` : "";
|
|
93
|
+
// Tagging only: /StructParents links this page's marked content to the ParentTree, /Tabs /S makes the
|
|
94
|
+
// logical structure order the tab/reading order (a PDF/UA requirement).
|
|
95
|
+
const structAttrs = structCtx ? ` /StructParents ${structCtx.structParents} /Tabs /S` : "";
|
|
96
|
+
const pageObject = `<< /Type /Page /Parent ${parentObjectNumber} 0 R /Contents ${contentObjectNumber} 0 R /Resources <<\n/Font <<\n${fontReferences.join("\n")}\n>>\n${imageCode}${extGStateCode}${shadingCode}>>\n/MediaBox [0 0 ${width} ${height}]${structAttrs}${annotsCode} >>`;
|
|
97
|
+
// Add page as new object; register its object number with the struct tree (for /Pg refs), then return it.
|
|
98
|
+
const pageObjNum = objectManager.addObject(pageObject);
|
|
99
|
+
if (structCtx)
|
|
100
|
+
objectManager.struct.setPageObject(structCtx.structParents, pageObjNum);
|
|
101
|
+
// Bookmarks + named destinations: an `Outline`/`Anchor` IR node drew nothing; record it now that the
|
|
102
|
+
// page's object number is known. `node.y` is already Y-flipped to the page-space scroll target.
|
|
103
|
+
// PDFRenderer builds /Outlines and /Names /Dests at the end.
|
|
104
|
+
for (const node of flipped) {
|
|
105
|
+
if (node.type === "outline") {
|
|
106
|
+
objectManager.outline.add({
|
|
107
|
+
title: node.title,
|
|
108
|
+
level: node.level,
|
|
109
|
+
pageObjNum,
|
|
110
|
+
top: node.y,
|
|
111
|
+
});
|
|
41
112
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const parentObjectNumber = objectManager.getParentObjectNumber(); // Get parent object number
|
|
48
|
-
// Page object with MediaBox
|
|
49
|
-
// - Get all fonts and add it to the page (reference)
|
|
50
|
-
objectManager.registerFont("Helvetica");
|
|
51
|
-
const fontReferences = [];
|
|
52
|
-
objectManager.getAllFontsRaw().forEach((value, _key) => {
|
|
53
|
-
const fontRef = `/F${value.fontIndex} ${value.resourceIndex} 0 R`;
|
|
54
|
-
fontReferences.push(fontRef);
|
|
55
|
-
});
|
|
56
|
-
// - Get all images and add it to the page (reference)
|
|
57
|
-
const imageReferences = [];
|
|
58
|
-
objectManager.getAllImagesRaw().forEach((value) => {
|
|
59
|
-
const imageRef = `/IM${value} ${value} 0 R`;
|
|
60
|
-
imageReferences.push(imageRef);
|
|
61
|
-
});
|
|
62
|
-
const imageCode = imageReferences.length > 0
|
|
63
|
-
? "/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] /XObject <<\n" +
|
|
64
|
-
imageReferences.join("\n") +
|
|
65
|
-
"\n>>\n"
|
|
66
|
-
: "";
|
|
67
|
-
// - Transparency (ExtGState) references, registered during serialize above
|
|
68
|
-
const extGStateReferences = [];
|
|
69
|
-
objectManager.getAllExtGStatesRaw().forEach((objectNumber, name) => {
|
|
70
|
-
extGStateReferences.push(`/${name} ${objectNumber} 0 R`);
|
|
71
|
-
});
|
|
72
|
-
const extGStateCode = extGStateReferences.length > 0
|
|
73
|
-
? "/ExtGState <<\n" + extGStateReferences.join("\n") + "\n>>\n"
|
|
74
|
-
: "";
|
|
75
|
-
const pageObject = `<< /Type /Page /Parent ${parentObjectNumber} 0 R /Contents ${contentObjectNumber} 0 R /Resources <<\n/Font <<\n${fontReferences.join("\n")}\n>>\n${imageCode}${extGStateCode}>>\n/MediaBox [0 0 ${width} ${height}] >>`;
|
|
76
|
-
// Add page as new object and return the page number
|
|
77
|
-
return objectManager.addObject(pageObject);
|
|
78
|
-
});
|
|
113
|
+
else if (node.type === "anchor") {
|
|
114
|
+
objectManager.dests.add(node.name, { pageObjNum, top: node.y });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return pageObjNum;
|
|
79
118
|
}
|
|
80
119
|
}
|
|
81
|
-
exports.PageRenderer = PageRenderer;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { IRNode } from "../ir/display-list";
|
|
2
|
-
import { PDFObjectManager } from "../utils/pdf-object-manager";
|
|
1
|
+
import { IRNode } from "../ir/display-list.js";
|
|
2
|
+
import { PDFObjectManager } from "../utils/pdf-object-manager.js";
|
|
3
|
+
import type { PageStructContext } from "../utils/struct-tree.js";
|
|
3
4
|
/**
|
|
4
5
|
* PDF backend - turns display-list primitives into content-stream operators.
|
|
5
6
|
*
|
|
@@ -17,14 +18,34 @@ export declare class PdfBackend {
|
|
|
17
18
|
* directly. (image is migrated in a later slice and still arrives pre-flipped.)
|
|
18
19
|
*/
|
|
19
20
|
static flipY(nodes: IRNode[], pageHeight: number): IRNode[];
|
|
20
|
-
/** Serialize a whole display list into one content stream (page-level entry point).
|
|
21
|
-
|
|
21
|
+
/** Serialize a whole display list into one content stream (page-level entry point). When a
|
|
22
|
+
* `PageStructContext` is given (accessible tagging on), each drawable node is wrapped in a marked-content
|
|
23
|
+
* sequence (`/Role <</MCID n>> BDC … EMC`, or `/Artifact` when untagged); graphics-state and empty nodes
|
|
24
|
+
* pass through untouched, so untagged output stays byte-identical. */
|
|
25
|
+
/**
|
|
26
|
+
* Every number reaching the backend must be finite. A non-finite coordinate is a layout bug, but
|
|
27
|
+
* silence turns it into a corrupt PDF: `Infinity` is written into the operator stream verbatim, and a
|
|
28
|
+
* viewer then discards everything from that point on - including the footer, which is drawn last. That
|
|
29
|
+
* failure is invisible until somebody opens the file, so we refuse instead.
|
|
30
|
+
*
|
|
31
|
+
* Checks the node's numbers, not the serialized text: a document containing the WORD "Infinity" is
|
|
32
|
+
* perfectly legal and must not trip this.
|
|
33
|
+
*/
|
|
34
|
+
private static assertFinite;
|
|
35
|
+
static serialize(nodes: IRNode[], om: PDFObjectManager, struct?: PageStructContext): string;
|
|
22
36
|
/**
|
|
23
37
|
* Escapes a string for a PDF literal string `( ... )`. The backslash must be doubled
|
|
24
38
|
* first, then the parentheses that delimit the string. Without this, a ")" in the
|
|
25
39
|
* text closes the string early and the remaining characters leak as raw operators.
|
|
26
40
|
*/
|
|
27
41
|
static escapePdfString(text: string): string;
|
|
42
|
+
/**
|
|
43
|
+
* Builds the `[ ... ]` operand of a `TJ` from a run and its per-gap kern adjustments (em/1000, the
|
|
44
|
+
* sign the font declares - negative tightens). A `TJ` number moves the pen LEFT, so it is the
|
|
45
|
+
* NEGATED kern. Consecutive un-kerned glyphs stay in one encoded chunk, so `[(T) 40 (otal)]` rather
|
|
46
|
+
* than one chunk per glyph. `kerns[i]` is the adjustment AFTER code point `i`.
|
|
47
|
+
*/
|
|
48
|
+
static kernedArray(text: string, kerns: number[], encode: (chunk: string) => string): string;
|
|
28
49
|
/**
|
|
29
50
|
* Returns the `/GSx gs` operator that selects a transparency state, or `""` when both
|
|
30
51
|
* alphas are fully opaque. Opaque draws emit nothing here, so output stays
|
|
@@ -37,6 +58,12 @@ export declare class PdfBackend {
|
|
|
37
58
|
* (kappa ≈ 0.5523). Returns m/l/c/h ops WITHOUT the paint operator.
|
|
38
59
|
*/
|
|
39
60
|
private static roundedRectPath;
|
|
61
|
+
/**
|
|
62
|
+
* Clamp the four radii into the box. Each is capped at half the box, and two radii sharing an edge
|
|
63
|
+
* are scaled down together when they would overlap - the CSS rule, and what keeps the path from
|
|
64
|
+
* folding back on itself.
|
|
65
|
+
*/
|
|
66
|
+
private static clampRadii;
|
|
40
67
|
/**
|
|
41
68
|
* Serialize a single display-list node to its content-stream operators.
|
|
42
69
|
* `om` is used only by primitives that allocate PDF resources (images, fonts).
|