@jasy/pdf 1.0.0-beta.2 → 1.0.0-beta.4
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/dist/api/content.d.ts +5 -5
- package/dist/api/content.js +12 -6
- package/dist/api/font-url.d.ts +1 -2
- package/dist/api/font-url.js +8 -74
- package/dist/api/forms.d.ts +3 -0
- package/dist/api/forms.js +3 -0
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.js +1 -0
- package/dist/api/layout.d.ts +6 -0
- package/dist/api/layout.js +7 -2
- package/dist/api/page-builder.d.ts +4 -0
- package/dist/api/page-builder.js +4 -0
- package/dist/api/structure.d.ts +10 -2
- package/dist/api/structure.js +9 -6
- package/dist/api/table.d.ts +5 -3
- package/dist/api/table.js +99 -22
- package/dist/common/diagnostics.d.ts +53 -0
- package/dist/common/diagnostics.js +77 -0
- package/dist/edit/acroform-reader.js +7 -7
- package/dist/edit/appearance.js +3 -3
- package/dist/edit/attachments.d.ts +52 -0
- package/dist/edit/attachments.js +178 -0
- package/dist/edit/document.d.ts +38 -8
- package/dist/edit/document.js +208 -51
- package/dist/edit/fill.js +8 -23
- package/dist/edit/filters.d.ts +15 -0
- package/dist/edit/filters.js +157 -0
- package/dist/edit/index.d.ts +4 -1
- package/dist/edit/index.js +3 -1
- package/dist/edit/objects.d.ts +3 -4
- package/dist/edit/objects.js +5 -18
- package/dist/elements/canvas-element.d.ts +3 -0
- package/dist/elements/canvas-element.js +14 -3
- package/dist/elements/container-element.d.ts +5 -1
- package/dist/elements/container-element.js +35 -15
- package/dist/elements/forms/checkbox-element.d.ts +2 -0
- package/dist/elements/forms/checkbox-element.js +12 -3
- package/dist/elements/forms/choice-element.d.ts +6 -1
- package/dist/elements/forms/choice-element.js +17 -6
- package/dist/elements/forms/field-font.d.ts +8 -0
- package/dist/elements/forms/field-font.js +5 -0
- package/dist/elements/forms/push-button-element.d.ts +6 -1
- package/dist/elements/forms/push-button-element.js +16 -4
- package/dist/elements/forms/radio-element.d.ts +2 -0
- package/dist/elements/forms/radio-element.js +12 -3
- package/dist/elements/forms/signature-element.d.ts +6 -1
- package/dist/elements/forms/signature-element.js +16 -4
- package/dist/elements/forms/text-field-element.d.ts +6 -1
- package/dist/elements/forms/text-field-element.js +16 -4
- package/dist/elements/image-element.d.ts +39 -1
- package/dist/elements/image-element.js +95 -12
- package/dist/elements/layout/anchor-element.d.ts +8 -10
- package/dist/elements/layout/anchor-element.js +10 -18
- package/dist/elements/layout/bookmark-element.d.ts +9 -11
- package/dist/elements/layout/bookmark-element.js +11 -20
- package/dist/elements/layout/default-text-style-element.d.ts +11 -13
- package/dist/elements/layout/default-text-style-element.js +14 -31
- package/dist/elements/layout/deferred-element.d.ts +12 -4
- package/dist/elements/layout/deferred-element.js +24 -7
- package/dist/elements/layout/expanded-element.d.ts +7 -0
- package/dist/elements/layout/expanded-element.js +40 -18
- package/dist/elements/layout/keep-together-element.d.ts +8 -18
- package/dist/elements/layout/keep-together-element.js +21 -45
- package/dist/elements/layout/link-element.d.ts +8 -13
- package/dist/elements/layout/link-element.js +9 -19
- package/dist/elements/layout/padding-element.d.ts +15 -1
- package/dist/elements/layout/padding-element.js +55 -27
- package/dist/elements/layout/page-break-element.d.ts +4 -1
- package/dist/elements/layout/page-break-element.js +6 -1
- package/dist/elements/layout/page-builder-element.d.ts +5 -0
- package/dist/elements/layout/page-builder-element.js +11 -0
- package/dist/elements/layout/positioned-element.d.ts +14 -2
- package/dist/elements/layout/positioned-element.js +36 -10
- package/dist/elements/layout/proxy-element.d.ts +43 -0
- package/dist/elements/layout/proxy-element.js +94 -0
- package/dist/elements/layout/repeating-header-element.d.ts +6 -0
- package/dist/elements/layout/repeating-header-element.js +40 -13
- package/dist/elements/layout/rotated-box-element.d.ts +6 -0
- package/dist/elements/layout/rotated-box-element.js +27 -14
- package/dist/elements/layout/rotated-element.d.ts +7 -0
- package/dist/elements/layout/rotated-element.js +25 -2
- package/dist/elements/layout/struct-group.d.ts +9 -17
- package/dist/elements/layout/struct-group.js +10 -35
- package/dist/elements/line-element.d.ts +1 -0
- package/dist/elements/line-element.js +6 -0
- package/dist/elements/page-element.d.ts +10 -3
- package/dist/elements/page-element.js +39 -31
- package/dist/elements/pdf-document-element.d.ts +3 -0
- package/dist/elements/pdf-document-element.js +7 -0
- package/dist/elements/pdf-element.d.ts +75 -15
- package/dist/elements/pdf-element.js +68 -18
- package/dist/elements/rectangle-element.d.ts +14 -0
- package/dist/elements/rectangle-element.js +97 -52
- package/dist/elements/row-element.d.ts +11 -0
- package/dist/elements/row-element.js +58 -8
- package/dist/elements/svg-element.d.ts +30 -6
- package/dist/elements/svg-element.js +88 -17
- package/dist/elements/text-element.d.ts +40 -13
- package/dist/elements/text-element.js +144 -99
- package/dist/forms/acroform.d.ts +9 -1
- package/dist/forms/acroform.js +83 -34
- package/dist/forms/appearance.d.ts +17 -6
- package/dist/forms/appearance.js +18 -16
- package/dist/ir/display-list.d.ts +12 -2
- package/dist/layout/box-constraints.d.ts +5 -0
- package/dist/layout/box-constraints.js +14 -0
- package/dist/layout/collect-images.d.ts +6 -4
- package/dist/layout/collect-images.js +6 -4
- package/dist/layout/flex-item.d.ts +9 -0
- package/dist/layout/flex-item.js +39 -0
- package/dist/layout/fragmentation.d.ts +12 -4
- package/dist/layout/fragmentation.js +37 -14
- package/dist/layout/layout-cache.d.ts +53 -0
- package/dist/layout/layout-cache.js +107 -0
- package/dist/renderer/anchor-renderer.d.ts +2 -1
- package/dist/renderer/anchor-renderer.js +5 -4
- package/dist/renderer/bookmark-renderer.d.ts +2 -1
- package/dist/renderer/bookmark-renderer.js +5 -4
- package/dist/renderer/canvas-renderer.d.ts +2 -1
- package/dist/renderer/canvas-renderer.js +5 -2
- package/dist/renderer/container-renderer.d.ts +2 -1
- package/dist/renderer/container-renderer.js +6 -5
- package/dist/renderer/default-text-style-renderer.d.ts +2 -1
- package/dist/renderer/default-text-style-renderer.js +2 -3
- package/dist/renderer/deferred-renderer.d.ts +2 -1
- package/dist/renderer/deferred-renderer.js +2 -3
- package/dist/renderer/expanded-renderer.d.ts +2 -1
- package/dist/renderer/expanded-renderer.js +2 -3
- package/dist/renderer/form-field-renderer.d.ts +2 -1
- package/dist/renderer/form-field-renderer.js +16 -3
- package/dist/renderer/image-renderer.d.ts +2 -1
- package/dist/renderer/image-renderer.js +5 -2
- package/dist/renderer/keep-together-renderer.d.ts +2 -1
- package/dist/renderer/keep-together-renderer.js +2 -3
- package/dist/renderer/line-renderer.d.ts +2 -1
- package/dist/renderer/line-renderer.js +7 -2
- package/dist/renderer/link-renderer.d.ts +2 -1
- package/dist/renderer/link-renderer.js +36 -5
- package/dist/renderer/padding-renderer.d.ts +2 -1
- package/dist/renderer/padding-renderer.js +5 -5
- package/dist/renderer/page-break-renderer.d.ts +6 -5
- package/dist/renderer/page-break-renderer.js +14 -7
- package/dist/renderer/page-builder-renderer.d.ts +2 -1
- package/dist/renderer/page-builder-renderer.js +2 -3
- package/dist/renderer/page-renderer.js +28 -7
- package/dist/renderer/pdf-backend.d.ts +4 -3
- package/dist/renderer/pdf-backend.js +5 -5
- package/dist/renderer/pdf-document-renderer.d.ts +1 -8
- package/dist/renderer/pdf-document-renderer.js +15 -16
- package/dist/renderer/pdf-renderer.js +11 -11
- package/dist/renderer/positioned-renderer.d.ts +6 -1
- package/dist/renderer/positioned-renderer.js +6 -5
- package/dist/renderer/rectangle-renderer.d.ts +2 -1
- package/dist/renderer/rectangle-renderer.js +9 -4
- package/dist/renderer/repeating-header-renderer.d.ts +2 -1
- package/dist/renderer/repeating-header-renderer.js +6 -5
- package/dist/renderer/rotated-renderer.d.ts +2 -1
- package/dist/renderer/rotated-renderer.js +8 -5
- package/dist/renderer/row-renderer.d.ts +2 -1
- package/dist/renderer/row-renderer.js +6 -5
- package/dist/renderer/struct-group-renderer.d.ts +2 -1
- package/dist/renderer/struct-group-renderer.js +2 -3
- package/dist/renderer/svg-renderer.d.ts +2 -1
- package/dist/renderer/svg-renderer.js +8 -2
- package/dist/renderer/text-renderer.d.ts +4 -6
- package/dist/renderer/text-renderer.js +101 -111
- package/dist/svg/gradients.js +5 -0
- package/dist/svg/index.js +10 -1
- package/dist/svg/style.d.ts +2 -0
- package/dist/svg/style.js +11 -0
- package/dist/text/advance.d.ts +4 -0
- package/dist/text/advance.js +49 -4
- package/dist/text/bidi.d.ts +0 -2
- package/dist/text/bidi.js +0 -10
- package/dist/text/glyph-coverage.d.ts +1 -1
- package/dist/text/glyph-coverage.js +7 -3
- package/dist/text/hyphen-breaks.d.ts +17 -0
- package/dist/text/hyphen-breaks.js +54 -0
- package/dist/text/line-breaker.d.ts +34 -31
- package/dist/text/line-breaker.js +364 -176
- package/dist/text/line-metrics.d.ts +6 -3
- package/dist/text/line-metrics.js +7 -2
- package/dist/text/pdf-text-string.d.ts +21 -0
- package/dist/text/pdf-text-string.js +114 -0
- package/dist/text/text-decoration.d.ts +5 -5
- package/dist/text/text-decoration.js +5 -5
- package/dist/text/word-splitting.d.ts +15 -2
- package/dist/text/word-splitting.js +34 -8
- package/dist/utils/afm-parser.d.ts +3 -0
- package/dist/utils/afm-parser.js +19 -1
- package/dist/utils/dest-registry.d.ts +1 -1
- package/dist/utils/dest-registry.js +3 -2
- package/dist/utils/fetch-bytes.d.ts +19 -0
- package/dist/utils/fetch-bytes.js +79 -0
- package/dist/utils/flex-layout.d.ts +13 -13
- package/dist/utils/flex-layout.js +318 -216
- package/dist/utils/font-metrics.d.ts +4 -3
- package/dist/utils/image-helper.js +2 -1
- package/dist/utils/pdf-object-manager.d.ts +11 -3
- package/dist/utils/pdf-object-manager.js +41 -15
- package/dist/utils/renderer-registry.d.ts +43 -2
- package/dist/utils/renderer-registry.js +40 -0
- package/dist/utils/struct-tree.d.ts +24 -0
- package/dist/utils/struct-tree.js +61 -9
- package/dist/utils/ttf-parser.d.ts +4 -0
- package/dist/utils/ttf-parser.js +27 -4
- package/dist/validators/element-validator.js +2 -1
- package/package.json +1 -1
- package/dist/elements/layout/sized-container-element.d.ts +0 -14
- package/dist/elements/layout/sized-container-element.js +0 -32
|
@@ -18,7 +18,7 @@ export class PDFDocumentRenderer {
|
|
|
18
18
|
// `Page` element produces one run of sheets, so the run's length is that section's total.
|
|
19
19
|
const section = [];
|
|
20
20
|
for (const page of document.getProps().children) {
|
|
21
|
-
const sheets = PDFDocumentRenderer.paginateLogicalPage(page, ctx);
|
|
21
|
+
const sheets = PDFDocumentRenderer.paginateLogicalPage(page, ctx, physicalPages.length + 1);
|
|
22
22
|
sheets.forEach((_, i) => section.push({ number: i + 1, total: sheets.length }));
|
|
23
23
|
physicalPages.push(...sheets);
|
|
24
24
|
}
|
|
@@ -47,17 +47,11 @@ export class PDFDocumentRenderer {
|
|
|
47
47
|
objectManager.replaceObject(pagesObjectNumber, updatedPagesObject);
|
|
48
48
|
return pagesObjectNumber;
|
|
49
49
|
}
|
|
50
|
-
/**
|
|
51
|
-
* The page geometry a physical page will use. `PageElement.calculateLayout` has already folded the
|
|
52
|
-
* document defaults into every page's config by the time we get here (`PDFRenderer` lays the document
|
|
53
|
-
* out before it calls us, and it is our only caller). Merging again is therefore a no-op today - it is
|
|
54
|
-
* here so this stays correct BY CONSTRUCTION rather than by call order: were that order ever changed,
|
|
55
|
-
* an unmerged config would otherwise make `resolvePageSize` fall back to A4 and quietly report the
|
|
56
|
-
* wrong page size.
|
|
57
|
-
*/
|
|
50
|
+
/** The page geometry a physical page will use: resolved, never read back from an earlier layout. */
|
|
58
51
|
static configOf(physical, ctx) {
|
|
59
|
-
|
|
60
|
-
|
|
52
|
+
return physical.kind === "whole"
|
|
53
|
+
? physical.page.resolveConfig(ctx.pageConfig)
|
|
54
|
+
: physical.config;
|
|
61
55
|
}
|
|
62
56
|
/**
|
|
63
57
|
* Splits one logical page into the physical pages it will occupy, without rendering.
|
|
@@ -66,13 +60,15 @@ export class PDFDocumentRenderer {
|
|
|
66
60
|
* (a Container). Anything else stays a single page on the unchanged path, so non-overflowing
|
|
67
61
|
* documents keep producing byte-identical output.
|
|
68
62
|
*/
|
|
69
|
-
static paginateLogicalPage(page, ctx) {
|
|
70
|
-
const { children,
|
|
63
|
+
static paginateLogicalPage(page, ctx, firstPage) {
|
|
64
|
+
const { children, header, footer } = page.getProps();
|
|
65
|
+
// Resolved here, not read back from an earlier layout pass that happened to merge it.
|
|
66
|
+
const config = page.resolveConfig(ctx.pageConfig);
|
|
71
67
|
if (children.length !== 1 || !isFragmentable(children[0])) {
|
|
72
68
|
return [{ kind: "whole", page }];
|
|
73
69
|
}
|
|
74
70
|
// Header/footer repeat on every physical page, so the body only ever flows into the
|
|
75
|
-
// band between them. Resolve that band once
|
|
71
|
+
// band between them. Resolve that band once.
|
|
76
72
|
// The frame is a throwaway: this pass only wants the band HEIGHTS, and an out-of-flow child
|
|
77
73
|
// contributes none. It exists because a `Positioned` in a band demands one; pass 2 builds the
|
|
78
74
|
// real frame (in `PageElement`) and drains it.
|
|
@@ -81,7 +77,9 @@ export class PDFDocumentRenderer {
|
|
|
81
77
|
pageConfig: config,
|
|
82
78
|
textStyle: ctx.textStyle,
|
|
83
79
|
onOverflow: ctx.onOverflow,
|
|
80
|
+
diagnostics: ctx.diagnostics,
|
|
84
81
|
frame: pageFrame(config),
|
|
82
|
+
paginatingPage: firstPage, // the bands are laid out here once, for the first sheet
|
|
85
83
|
};
|
|
86
84
|
const { bodyWidth: width, bodyHeight: height } = layoutPageBands(config, header, footer, pageCtx);
|
|
87
85
|
// A `keepTogether` group compares its height against a FULL fresh page (this band), so thread it in.
|
|
@@ -97,6 +95,7 @@ export class PDFDocumentRenderer {
|
|
|
97
95
|
}
|
|
98
96
|
// pageCtx, not the document ctx: a descendant that reads `pageConfig` while being measured (a
|
|
99
97
|
// `PageBuilder` sizing its provisional build) must see THIS page's geometry, not the document default.
|
|
98
|
+
pageCtx.paginatingPage = firstPage + pages.length;
|
|
100
99
|
const { fitted, remainder, forceBreak } = region.fragment(height, width, pageCtx);
|
|
101
100
|
// Everything fits on one page: keep the ORIGINAL page so output is unchanged. Measuring inside
|
|
102
101
|
// fragment() left its children at the measuring origin; pass B lays the page out again, which
|
|
@@ -115,8 +114,8 @@ export class PDFDocumentRenderer {
|
|
|
115
114
|
if (fitted === null) {
|
|
116
115
|
// Measure the region's true height for the message (rare path, so the extra pass is free);
|
|
117
116
|
// pass B lays it out again, so this mutation does not leak.
|
|
118
|
-
const needed = region.
|
|
119
|
-
reportOverflow(region, needed, height, pageCtx
|
|
117
|
+
const needed = region.measure(BoxConstraints.loose(width, Infinity), pageCtx).height;
|
|
118
|
+
reportOverflow(region, needed, height, pageCtx);
|
|
120
119
|
pages.push({ kind: "fragment", config, content: region, header, footer });
|
|
121
120
|
break;
|
|
122
121
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { comparePdfText } from "../text/pdf-text-string.js";
|
|
1
2
|
import { PDFDocumentRenderer } from "./pdf-document-renderer.js";
|
|
2
3
|
import { RendererRegistry } from "../utils/renderer-registry.js";
|
|
3
4
|
import { DefaultTextStyleElement, ExpandedElement, ImageElement, LineElement, CanvasElement, PaddingElement, SvgElement, TextElement, } from "../elements/index.js";
|
|
@@ -45,8 +46,6 @@ import { PageBuilderRenderer } from "./page-builder-renderer.js";
|
|
|
45
46
|
import { RotatedElement } from "../elements/layout/rotated-element.js";
|
|
46
47
|
import { RotatedBoxElement } from "../elements/layout/rotated-box-element.js";
|
|
47
48
|
import { RotatedRenderer } from "./rotated-renderer.js";
|
|
48
|
-
import { PdfBackend } from "./pdf-backend.js";
|
|
49
|
-
import { BoxConstraints } from "../layout/box-constraints.js";
|
|
50
49
|
import { collectImageElements } from "../layout/collect-images.js";
|
|
51
50
|
import { DEFAULT_TEXT_STYLE, mergeTextStyle } from "../text/text-style.js";
|
|
52
51
|
export class PDFRenderer {
|
|
@@ -85,21 +84,21 @@ export class PDFRenderer {
|
|
|
85
84
|
// Header: version line + the PDF/A binary marker (the object manager owns it so its length
|
|
86
85
|
// matches the xref offset calculation).
|
|
87
86
|
pdfContent += objectManager.getHeader();
|
|
88
|
-
//
|
|
89
|
-
//
|
|
87
|
+
// The layout context, threaded explicitly. The seed page config is the document default; each
|
|
88
|
+
// PageElement overrides it for its own subtree.
|
|
90
89
|
const ctx = {
|
|
91
90
|
metrics: objectManager,
|
|
92
91
|
pageConfig: objectManager.getPDFConfig(),
|
|
93
92
|
textStyle: mergeTextStyle(DEFAULT_TEXT_STYLE, document.getDefaultTextStyle()),
|
|
94
93
|
onOverflow: objectManager.getOverflowPolicy(),
|
|
94
|
+
diagnostics: objectManager.diagnostics,
|
|
95
95
|
};
|
|
96
96
|
// Pre-layout: resolve every image's intrinsic pixel size (async), so the synchronous layout can
|
|
97
97
|
// give a width-only image a proportional height. init() is idempotent, so the renderer reuses it.
|
|
98
98
|
const images = collectImageElements(document);
|
|
99
99
|
if (images.length > 0)
|
|
100
100
|
await Promise.all(images.map((img) => img.resolveIntrinsicSize()));
|
|
101
|
-
|
|
102
|
-
// Render pages and contents (the driver paginates overflowing pages).
|
|
101
|
+
// Paginate, then lay out and render page by page (the driver does both; nothing is laid out before).
|
|
103
102
|
await PDFDocumentRenderer.render(document, objectManager, ctx);
|
|
104
103
|
// Add the catalog. XMP metadata (/Metadata) and embedded files (/AF + /Names/EmbeddedFiles)
|
|
105
104
|
// are added only when present; with neither, the catalog is byte-identical to before.
|
|
@@ -118,11 +117,12 @@ export class PDFRenderer {
|
|
|
118
117
|
const namesParts = [];
|
|
119
118
|
const attachments = objectManager.getAttachments();
|
|
120
119
|
if (attachments.length > 0) {
|
|
121
|
-
// The name-tree key is a
|
|
122
|
-
//
|
|
123
|
-
//
|
|
124
|
-
const names = attachments
|
|
125
|
-
.
|
|
120
|
+
// The name-tree key is a text string like the /Filespec's /F and /UF, so it goes through the same
|
|
121
|
+
// choke point - encoded and, in an encrypted file, enciphered. A name tree is SORTED by its keys
|
|
122
|
+
// (a reader may search it), so the keys are ordered by their bytes first.
|
|
123
|
+
const names = [...attachments]
|
|
124
|
+
.sort((a, b) => comparePdfText(a.name, b.name))
|
|
125
|
+
.map((a) => `${objectManager.pdfString(a.name)} ${a.filespec} 0 R`)
|
|
126
126
|
.join(" ");
|
|
127
127
|
const af = attachments.map((a) => `${a.filespec} 0 R`).join(" ");
|
|
128
128
|
catalogParts.push(`/AF [${af}]`);
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { PDFObjectManager } from "../utils/pdf-object-manager.js";
|
|
2
2
|
import { PositionedElement } from "../elements/layout/positioned-element.js";
|
|
3
|
+
import { type RenderScope } from "../utils/renderer-registry.js";
|
|
3
4
|
import { IRNode } from "../ir/display-list.js";
|
|
4
5
|
export declare class PositionedRenderer {
|
|
5
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Drawn at its own place in the tree (tree order is paint order), from its frame: the child was laid
|
|
8
|
+
* out relative to the frame's top-left, not to the flow it sits in.
|
|
9
|
+
*/
|
|
10
|
+
static render(positionedElement: PositionedElement, objectManager: PDFObjectManager, scope: RenderScope): Promise<IRNode[]>;
|
|
6
11
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { RendererRegistry } from "../utils/renderer-registry.js";
|
|
2
2
|
export class PositionedRenderer {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Drawn at its own place in the tree (tree order is paint order), from its frame: the child was laid
|
|
5
|
+
* out relative to the frame's top-left, not to the flow it sits in.
|
|
6
|
+
*/
|
|
7
|
+
static async render(positionedElement, objectManager, scope) {
|
|
6
8
|
const { child } = positionedElement.getProps();
|
|
7
|
-
|
|
8
|
-
return renderer(child, objectManager);
|
|
9
|
+
return RendererRegistry.render(child, objectManager, { ...scope, origin: scope.frame });
|
|
9
10
|
}
|
|
10
11
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { PDFObjectManager } from "../utils/pdf-object-manager.js";
|
|
2
2
|
import { RectangleElement } from "../elements/rectangle-element.js";
|
|
3
|
+
import { type RenderScope } from "../utils/renderer-registry.js";
|
|
3
4
|
import { IRNode } from "../ir/display-list.js";
|
|
4
5
|
export declare class RectangleRenderer {
|
|
5
|
-
static render(rectangleElement: RectangleElement, objectManager: PDFObjectManager): Promise<IRNode[]>;
|
|
6
|
+
static render(rectangleElement: RectangleElement, objectManager: PDFObjectManager, scope: RenderScope): Promise<IRNode[]>;
|
|
6
7
|
/** One `line` node per present side, along the box edges (top-left coordinates). */
|
|
7
8
|
private static sideLines;
|
|
8
9
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { RendererRegistry } from "../utils/renderer-registry.js";
|
|
2
2
|
import { isGradientInput, resolveGradient } from "../api/gradient.js";
|
|
3
3
|
export class RectangleRenderer {
|
|
4
|
-
static async render(rectangleElement, objectManager) {
|
|
5
|
-
const { x, y, width, height, children, color, backgroundColor, borderWidth, radius, sideBorders, overflow, } = rectangleElement.getProps();
|
|
4
|
+
static async render(rectangleElement, objectManager, scope) {
|
|
5
|
+
const { x: ownX, y: ownY, width, height, children, color, backgroundColor, borderWidth, radius, sideBorders, overflow, relative, } = rectangleElement.getProps();
|
|
6
|
+
// Its own position is relative to `scope.origin`; the IR wants page coordinates.
|
|
7
|
+
const x = scope.origin.x + (ownX ?? 0);
|
|
8
|
+
const y = scope.origin.y + (ownY ?? 0);
|
|
6
9
|
const h = height;
|
|
7
10
|
const nodes = [];
|
|
8
11
|
// A gradient is written box-relative (an angle and stops); this is the first place the box is
|
|
@@ -41,10 +44,12 @@ export class RectangleRenderer {
|
|
|
41
44
|
if (clip) {
|
|
42
45
|
nodes.push({ type: "clip-push", x, y, width, height: h, ...(radius ? { radius } : {}) });
|
|
43
46
|
}
|
|
47
|
+
// Its children are placed relative to its own top-left; a `relative` box is also the frame its
|
|
48
|
+
// `Positioned` descendants were placed against.
|
|
49
|
+
const childScope = { origin: { x, y }, frame: relative ? { x, y } : scope.frame };
|
|
44
50
|
if (children)
|
|
45
51
|
for (const child of children) {
|
|
46
|
-
|
|
47
|
-
nodes.push(...(await renderer(child, objectManager)));
|
|
52
|
+
nodes.push(...(await RendererRegistry.render(child, objectManager, childScope)));
|
|
48
53
|
}
|
|
49
54
|
if (clip)
|
|
50
55
|
nodes.push({ type: "clip-pop" });
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PDFObjectManager } from "../utils/pdf-object-manager.js";
|
|
2
2
|
import { RepeatingHeaderElement } from "../elements/layout/repeating-header-element.js";
|
|
3
|
+
import { type RenderScope } from "../utils/renderer-registry.js";
|
|
3
4
|
import { IRNode } from "../ir/display-list.js";
|
|
4
5
|
export declare class RepeatingHeaderRenderer {
|
|
5
|
-
static render(element: RepeatingHeaderElement, objectManager: PDFObjectManager): Promise<IRNode[]>;
|
|
6
|
+
static render(element: RepeatingHeaderElement, objectManager: PDFObjectManager, scope: RenderScope): Promise<IRNode[]>;
|
|
6
7
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { RendererRegistry } from "../utils/renderer-registry.js";
|
|
1
|
+
import { RendererRegistry, within } from "../utils/renderer-registry.js";
|
|
2
2
|
export class RepeatingHeaderRenderer {
|
|
3
|
-
static async render(element, objectManager) {
|
|
4
|
-
const { header, body } = element.getProps();
|
|
3
|
+
static async render(element, objectManager, scope) {
|
|
4
|
+
const { x, y, header, body } = element.getProps();
|
|
5
5
|
const nodes = [];
|
|
6
|
+
// Header and body are placed relative to its own top-left.
|
|
7
|
+
const inner = within(scope, { x, y });
|
|
6
8
|
for (const child of [header, body]) {
|
|
7
|
-
|
|
8
|
-
nodes.push(...(await renderer(child, objectManager)));
|
|
9
|
+
nodes.push(...(await RendererRegistry.render(child, objectManager, inner)));
|
|
9
10
|
}
|
|
10
11
|
return nodes;
|
|
11
12
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { PDFObjectManager } from "../utils/pdf-object-manager.js";
|
|
2
2
|
import { RotatedElement } from "../elements/layout/rotated-element.js";
|
|
3
3
|
import { RotatedBoxElement } from "../elements/layout/rotated-box-element.js";
|
|
4
|
+
import { type RenderScope } from "../utils/renderer-registry.js";
|
|
4
5
|
import { IRNode } from "../ir/display-list.js";
|
|
5
6
|
export declare class RotatedRenderer {
|
|
6
|
-
static render(element: RotatedElement | RotatedBoxElement, objectManager: PDFObjectManager): Promise<IRNode[]>;
|
|
7
|
+
static render(element: RotatedElement | RotatedBoxElement, objectManager: PDFObjectManager, scope: RenderScope): Promise<IRNode[]>;
|
|
7
8
|
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { RendererRegistry } from "../utils/renderer-registry.js";
|
|
1
|
+
import { RendererRegistry, within } from "../utils/renderer-registry.js";
|
|
2
2
|
export class RotatedRenderer {
|
|
3
3
|
// Both `Rotated` (paint-only) and `RotatedBox` (layout-aware quarter-turns) expose the same
|
|
4
4
|
// `{ angle, child, x, y, width, height }` and rotate the child around the box center - shared here.
|
|
5
|
-
static async render(element, objectManager) {
|
|
6
|
-
const { angle, child, x, y, width, height } = element.getProps();
|
|
5
|
+
static async render(element, objectManager, scope) {
|
|
6
|
+
const { angle, child, x: ownX, y: ownY, width, height } = element.getProps();
|
|
7
|
+
// Its own position is relative to `scope.origin`; the IR wants page coordinates.
|
|
8
|
+
const x = scope.origin.x + (ownX ?? 0);
|
|
9
|
+
const y = scope.origin.y + (ownY ?? 0);
|
|
7
10
|
// Rotate around the box CENTER, in the engine's top-left coordinates (the IR->backend seam flips
|
|
8
11
|
// the matrix to PDF space per page). A positive angle reads clockwise on the page.
|
|
9
12
|
const cx = x + width / 2;
|
|
@@ -21,8 +24,8 @@ export class RotatedRenderer {
|
|
|
21
24
|
cx - cos * cx + sin * cy,
|
|
22
25
|
cy - sin * cx - cos * cy,
|
|
23
26
|
];
|
|
24
|
-
|
|
25
|
-
const childNodes = await
|
|
27
|
+
// The child is placed relative to the box top-left.
|
|
28
|
+
const childNodes = await RendererRegistry.render(child, objectManager, within(scope, { x: ownX, y: ownY }));
|
|
26
29
|
// Wrap the child's drawing between a push (apply the matrix) and a pop (restore).
|
|
27
30
|
return [{ type: "transform-push", matrix }, ...childNodes, { type: "transform-pop" }];
|
|
28
31
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PDFObjectManager } from "../utils/pdf-object-manager.js";
|
|
2
2
|
import { RowElement } from "../elements/row-element.js";
|
|
3
|
+
import { type RenderScope } from "../utils/renderer-registry.js";
|
|
3
4
|
import { IRNode } from "../ir/display-list.js";
|
|
4
5
|
export declare class RowRenderer {
|
|
5
|
-
static render(rowElement: RowElement, objectManager: PDFObjectManager): Promise<IRNode[]>;
|
|
6
|
+
static render(rowElement: RowElement, objectManager: PDFObjectManager, scope: RenderScope): Promise<IRNode[]>;
|
|
6
7
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { RendererRegistry } from "../utils/renderer-registry.js";
|
|
1
|
+
import { RendererRegistry, within } from "../utils/renderer-registry.js";
|
|
2
2
|
export class RowRenderer {
|
|
3
|
-
static async render(rowElement, objectManager) {
|
|
4
|
-
const { children } = rowElement.getProps();
|
|
3
|
+
static async render(rowElement, objectManager, scope) {
|
|
4
|
+
const { x, y, children } = rowElement.getProps();
|
|
5
5
|
const nodes = [];
|
|
6
|
+
// Its children are placed relative to its own top-left.
|
|
7
|
+
const inner = within(scope, { x, y });
|
|
6
8
|
if (children)
|
|
7
9
|
for (const child of children) {
|
|
8
|
-
|
|
9
|
-
nodes.push(...(await renderer(child, objectManager)));
|
|
10
|
+
nodes.push(...(await RendererRegistry.render(child, objectManager, inner)));
|
|
10
11
|
}
|
|
11
12
|
return nodes;
|
|
12
13
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { StructGroup } from "../elements/layout/struct-group.js";
|
|
2
2
|
import { PDFObjectManager } from "../utils/pdf-object-manager.js";
|
|
3
3
|
import { IRNode } from "../ir/display-list.js";
|
|
4
|
+
import { type RenderScope } from "../utils/renderer-registry.js";
|
|
4
5
|
/**
|
|
5
6
|
* Renders a StructGroup: opens its structure element, renders the child under it, closes it. With accessible
|
|
6
7
|
* tagging off it is fully transparent - just the child's IR.
|
|
7
8
|
*/
|
|
8
9
|
export declare class StructGroupRenderer {
|
|
9
|
-
static render(group: StructGroup, objectManager: PDFObjectManager): Promise<IRNode[]>;
|
|
10
|
+
static render(group: StructGroup, objectManager: PDFObjectManager, scope: RenderScope): Promise<IRNode[]>;
|
|
10
11
|
}
|
|
@@ -4,11 +4,10 @@ import { RendererRegistry } from "../utils/renderer-registry.js";
|
|
|
4
4
|
* tagging off it is fully transparent - just the child's IR.
|
|
5
5
|
*/
|
|
6
6
|
export class StructGroupRenderer {
|
|
7
|
-
static async render(group, objectManager) {
|
|
7
|
+
static async render(group, objectManager, scope) {
|
|
8
8
|
const { role, child } = group.getProps();
|
|
9
9
|
const renderChild = async () => {
|
|
10
|
-
|
|
11
|
-
return renderer(child, objectManager);
|
|
10
|
+
return RendererRegistry.render(child, objectManager, scope);
|
|
12
11
|
};
|
|
13
12
|
if (!objectManager.struct.enabled)
|
|
14
13
|
return renderChild();
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RenderScope } from "../utils/renderer-registry.js";
|
|
1
2
|
import { PDFObjectManager } from "../utils/pdf-object-manager.js";
|
|
2
3
|
import { SvgElement } from "../elements/svg-element.js";
|
|
3
4
|
import type { IRNode } from "../ir/display-list.js";
|
|
@@ -7,5 +8,5 @@ import type { IRNode } from "../ir/display-list.js";
|
|
|
7
8
|
* that colour emoji already draw through carries it.
|
|
8
9
|
*/
|
|
9
10
|
export declare class SvgRenderer {
|
|
10
|
-
static render(element: SvgElement, objectManager: PDFObjectManager): Promise<IRNode[]>;
|
|
11
|
+
static render(element: SvgElement, objectManager: PDFObjectManager, scope: RenderScope): Promise<IRNode[]>;
|
|
11
12
|
}
|
|
@@ -5,8 +5,14 @@ import { svgToIr } from "../svg/index.js";
|
|
|
5
5
|
* that colour emoji already draw through carries it.
|
|
6
6
|
*/
|
|
7
7
|
export class SvgRenderer {
|
|
8
|
-
static async render(element, objectManager) {
|
|
9
|
-
|
|
8
|
+
static async render(element, objectManager, scope) {
|
|
9
|
+
await element.load(); // an SVG from a URL; already done when the pre-layout pass reached it
|
|
10
|
+
const { x: ownX, y: ownY, width, height, source, alt } = element.getProps();
|
|
11
|
+
if (source === undefined)
|
|
12
|
+
throw new Error("@jasy/pdf: an SVG was drawn before it was loaded");
|
|
13
|
+
// Its own position is relative to `scope.origin`; the IR wants page coordinates.
|
|
14
|
+
const x = scope.origin.x + (ownX ?? 0);
|
|
15
|
+
const y = scope.origin.y + (ownY ?? 0);
|
|
10
16
|
const nodes = svgToIr(source, {
|
|
11
17
|
x: x ?? 0,
|
|
12
18
|
y: y ?? 0,
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import type { RenderScope } from "../utils/renderer-registry.js";
|
|
2
|
+
import { TextElement } from "../elements/text-element.js";
|
|
3
|
+
import { PDFObjectManager } from "../utils/pdf-object-manager.js";
|
|
4
4
|
import { IRNode } from "../ir/display-list.js";
|
|
5
|
-
import { type LineOptions, TextOverflow } from "../text/line-breaker.js";
|
|
6
5
|
export declare class TextRenderer {
|
|
7
|
-
static
|
|
8
|
-
static render(textElement: TextElement, objectManager: PDFObjectManager): Promise<IRNode[]>;
|
|
6
|
+
static render(textElement: TextElement, objectManager: PDFObjectManager, scope: RenderScope): Promise<IRNode[]>;
|
|
9
7
|
private static _expandColorGlyphs;
|
|
10
8
|
private static _glyphToPath;
|
|
11
9
|
private static _toGradient;
|