@jasy/pdf 1.0.0-alpha.1 → 1.0.0-alpha.10
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 +100 -13
- package/dist/api/structure.js +179 -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 +132 -11
- package/dist/elements/text-element.js +206 -56
- 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/line-breaker.d.ts +50 -12
- package/dist/text/line-breaker.js +158 -37
- 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/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 +20 -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 +110 -8
- package/dist/utils/pdf-object-manager.js +583 -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,19 +1,28 @@
|
|
|
1
|
-
import { PDFDocumentElement } from "../elements/pdf-document-element";
|
|
2
|
-
import { LayoutContext } from "../elements/pdf-element";
|
|
3
|
-
import { PDFObjectManager } from "../utils/pdf-object-manager";
|
|
1
|
+
import { PDFDocumentElement } from "../elements/pdf-document-element.js";
|
|
2
|
+
import { LayoutContext } from "../elements/pdf-element.js";
|
|
3
|
+
import { PDFObjectManager } from "../utils/pdf-object-manager.js";
|
|
4
4
|
export declare class PDFDocumentRenderer {
|
|
5
5
|
static render(document: PDFDocumentElement, objectManager: PDFObjectManager, ctx: LayoutContext): Promise<number>;
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* The page geometry a physical page will use. `PageElement.calculateLayout` has already folded the
|
|
8
|
+
* document defaults into every page's config by the time we get here (`PDFRenderer` lays the document
|
|
9
|
+
* out before it calls us, and it is our only caller). Merging again is therefore a no-op today - it is
|
|
10
|
+
* here so this stays correct BY CONSTRUCTION rather than by call order: were that order ever changed,
|
|
11
|
+
* an unmerged config would otherwise make `resolvePageSize` fall back to A4 and quietly report the
|
|
12
|
+
* wrong page size.
|
|
13
|
+
*/
|
|
14
|
+
private static configOf;
|
|
15
|
+
/**
|
|
16
|
+
* Splits one logical page into the physical pages it will occupy, without rendering.
|
|
8
17
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
18
|
+
* Only the common shape auto-paginates - a page whose single child is a fragmentation context
|
|
19
|
+
* (a Container). Anything else stays a single page on the unchanged path, so non-overflowing
|
|
20
|
+
* documents keep producing byte-identical output.
|
|
12
21
|
*/
|
|
13
|
-
private static
|
|
22
|
+
private static paginateLogicalPage;
|
|
14
23
|
/**
|
|
15
|
-
* Lays out one fragment
|
|
16
|
-
* header/footer are attached to every physical page so they repeat
|
|
24
|
+
* Lays out one physical page and renders it. A fragment gets a fresh `PageElement` of the same
|
|
25
|
+
* geometry; the header/footer are attached to every physical page so they repeat, and `PageElement`
|
|
17
26
|
* re-places them and the body in the band between.
|
|
18
27
|
*/
|
|
19
28
|
private static renderPhysicalPage;
|
|
@@ -1,104 +1,148 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
1
|
+
import { layoutPageBands, pageFrame, PageElement, resolvePageSize, } from "../elements/page-element.js";
|
|
2
|
+
import { BoxConstraints } from "../layout/box-constraints.js";
|
|
3
|
+
import { isFragmentable, reportOverflow } from "../layout/fragmentation.js";
|
|
4
|
+
import { PageRenderer } from "./page-renderer.js";
|
|
5
|
+
export class PDFDocumentRenderer {
|
|
6
|
+
static async render(document, objectManager, ctx) {
|
|
7
|
+
// Add the pages object first... we need its object number (resources). The count is
|
|
8
|
+
// a placeholder; it is replaced below with the real (post-pagination) page count.
|
|
9
|
+
const pagesObject = `<< /Type /Pages /Kids [] /Count ${document.getProps().children.length} >>`;
|
|
10
|
+
const pagesObjectNumber = objectManager.addObject(pagesObject);
|
|
11
|
+
// Now set the given object number all its childs
|
|
12
|
+
objectManager.setParentObjectNumber(pagesObjectNumber);
|
|
13
|
+
// Pass A - paginate the whole document WITHOUT drawing anything. Fragmentation is synchronous and
|
|
14
|
+
// pure (`{ fitted, remainder }`), so the full list of physical pages can be settled up front. Only
|
|
15
|
+
// then is the total page count known, which is what page numbers in a header/footer need.
|
|
16
|
+
const physicalPages = [];
|
|
17
|
+
// Where each sheet sits WITHIN the logical page it came from. Pass A already knows: one logical
|
|
18
|
+
// `Page` element produces one run of sheets, so the run's length is that section's total.
|
|
19
|
+
const section = [];
|
|
20
|
+
for (const page of document.getProps().children) {
|
|
21
|
+
const sheets = PDFDocumentRenderer.paginateLogicalPage(page, ctx);
|
|
22
|
+
sheets.forEach((_, i) => section.push({ number: i + 1, total: sheets.length }));
|
|
23
|
+
physicalPages.push(...sheets);
|
|
24
|
+
}
|
|
25
|
+
// Pass B - draw them, in order, so the emitted page objects keep their previous numbering. Each page
|
|
26
|
+
// is laid out again with its own PageInfo, which is how a `PageBuilder` anywhere in the tree (header,
|
|
27
|
+
// footer or body) learns its final page number and the now-known document total.
|
|
28
|
+
const pageNumbers = [];
|
|
29
|
+
for (const [index, physical] of physicalPages.entries()) {
|
|
30
|
+
const pageInfo = {
|
|
31
|
+
pageNumber: index + 1,
|
|
32
|
+
pageCount: physicalPages.length,
|
|
33
|
+
subPageNumber: section[index].number,
|
|
34
|
+
subPageTotalPages: section[index].total,
|
|
35
|
+
pageSize: resolvePageSize(PDFDocumentRenderer.configOf(physical, ctx)),
|
|
36
|
+
};
|
|
37
|
+
pageNumbers.push(await PDFDocumentRenderer.renderPhysicalPage(physical, objectManager, {
|
|
38
|
+
...ctx,
|
|
39
|
+
pageInfo,
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
// We must update the pages object with the real physical page numbers and count.
|
|
43
|
+
const updatedPagesObject = `<< /Type /Pages /Kids [${pageNumbers
|
|
44
|
+
.map((num) => `${num} 0 R`)
|
|
45
|
+
.join(" ")}] /Count ${pageNumbers.length} >>`;
|
|
46
|
+
// Now we must replace it in the object manager
|
|
47
|
+
objectManager.replaceObject(pagesObjectNumber, updatedPagesObject);
|
|
48
|
+
return pagesObjectNumber;
|
|
41
49
|
}
|
|
42
50
|
/**
|
|
43
|
-
*
|
|
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
|
+
*/
|
|
58
|
+
static configOf(physical, ctx) {
|
|
59
|
+
const config = physical.kind === "whole" ? physical.page.getProps().config : physical.config;
|
|
60
|
+
return { ...ctx.pageConfig, ...config };
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Splits one logical page into the physical pages it will occupy, without rendering.
|
|
44
64
|
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
65
|
+
* Only the common shape auto-paginates - a page whose single child is a fragmentation context
|
|
66
|
+
* (a Container). Anything else stays a single page on the unchanged path, so non-overflowing
|
|
67
|
+
* documents keep producing byte-identical output.
|
|
48
68
|
*/
|
|
49
|
-
static
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
69
|
+
static paginateLogicalPage(page, ctx) {
|
|
70
|
+
const { children, config, header, footer } = page.getProps();
|
|
71
|
+
if (children.length !== 1 || !isFragmentable(children[0])) {
|
|
72
|
+
return [{ kind: "whole", page }];
|
|
73
|
+
}
|
|
74
|
+
// Header/footer repeat on every physical page, so the body only ever flows into the
|
|
75
|
+
// band between them. Resolve that band once (config is already merged by pass 1).
|
|
76
|
+
// The frame is a throwaway: this pass only wants the band HEIGHTS, and an out-of-flow child
|
|
77
|
+
// contributes none. It exists because a `Positioned` in a band demands one; pass 2 builds the
|
|
78
|
+
// real frame (in `PageElement`) and drains it.
|
|
79
|
+
const pageCtx = {
|
|
80
|
+
metrics: ctx.metrics,
|
|
81
|
+
pageConfig: config,
|
|
82
|
+
textStyle: ctx.textStyle,
|
|
83
|
+
onOverflow: ctx.onOverflow,
|
|
84
|
+
frame: pageFrame(config),
|
|
85
|
+
};
|
|
86
|
+
const { bodyWidth: width, bodyHeight: height } = layoutPageBands(config, header, footer, pageCtx);
|
|
87
|
+
// A `keepTogether` group compares its height against a FULL fresh page (this band), so thread it in.
|
|
88
|
+
pageCtx.pageBodyHeight = height;
|
|
89
|
+
const pages = [];
|
|
90
|
+
let region = children[0];
|
|
91
|
+
let isFirstRegion = true;
|
|
92
|
+
while (region) {
|
|
93
|
+
if (!isFragmentable(region)) {
|
|
94
|
+
// A non-fragmentable remainder is placed whole on its own page.
|
|
95
|
+
pages.push({ kind: "fragment", config, content: region, header, footer });
|
|
96
|
+
break;
|
|
54
97
|
}
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
const { fitted, remainder } = region.fragment(height, width, ctx);
|
|
69
|
-
// Everything fits on one page: render the ORIGINAL page so output is unchanged.
|
|
70
|
-
// Measuring inside fragment() laid the children out at the origin to size them, so
|
|
71
|
-
// re-run the page layout first to restore their real positions (deterministic).
|
|
72
|
-
if (isFirstRegion && remainder === null) {
|
|
73
|
-
page.calculateLayout(new box_constraints_1.BoxConstraints(), { x: 0, y: 0 }, ctx);
|
|
74
|
-
numbers.push(yield page_renderer_1.PageRenderer.render(page, objectManager));
|
|
75
|
-
break;
|
|
76
|
-
}
|
|
77
|
-
if (fitted) {
|
|
78
|
-
numbers.push(yield PDFDocumentRenderer.renderPhysicalPage(config, fitted, header, footer, objectManager, ctx));
|
|
79
|
-
}
|
|
80
|
-
region = remainder;
|
|
81
|
-
isFirstRegion = false;
|
|
98
|
+
// pageCtx, not the document ctx: a descendant that reads `pageConfig` while being measured (a
|
|
99
|
+
// `PageBuilder` sizing its provisional build) must see THIS page's geometry, not the document default.
|
|
100
|
+
const { fitted, remainder, forceBreak } = region.fragment(height, width, pageCtx);
|
|
101
|
+
// Everything fits on one page: keep the ORIGINAL page so output is unchanged. Measuring inside
|
|
102
|
+
// fragment() left its children at the measuring origin; pass B lays the page out again, which
|
|
103
|
+
// restores their real positions (layout is deterministic). A consumed trailing `PageBreak`
|
|
104
|
+
// (forceBreak with no remainder) is the exception: render the packed `fitted` instead, which no
|
|
105
|
+
// longer holds the break marker, so the original with the break does not leak into the render pass.
|
|
106
|
+
if (isFirstRegion && remainder === null && !forceBreak) {
|
|
107
|
+
pages.push({ kind: "whole", page });
|
|
108
|
+
break;
|
|
82
109
|
}
|
|
83
|
-
|
|
84
|
-
|
|
110
|
+
// TERMINATION GUARANTEE. Every page here has the full body height, so `fitted === null` means
|
|
111
|
+
// nothing fit even on a whole page - the region did not get smaller. Advancing to the
|
|
112
|
+
// (identical) remainder would loop forever. So we stop: place the region whole (clipped to the
|
|
113
|
+
// page) and surface it per the overflow policy. A step that shrinks nothing ends the loop, for
|
|
114
|
+
// ANY region - an oversized unbreakable block, a future keep-together group, or an engine bug.
|
|
115
|
+
if (fitted === null) {
|
|
116
|
+
// Measure the region's true height for the message (rare path, so the extra pass is free);
|
|
117
|
+
// pass B lays it out again, so this mutation does not leak.
|
|
118
|
+
const needed = region.calculateLayout(BoxConstraints.loose(width, Infinity), { x: 0, y: 0 }, pageCtx).height;
|
|
119
|
+
reportOverflow(region, needed, height, pageCtx.onOverflow ?? "ignore");
|
|
120
|
+
pages.push({ kind: "fragment", config, content: region, header, footer });
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
pages.push({ kind: "fragment", config, content: fitted, header, footer });
|
|
124
|
+
region = remainder;
|
|
125
|
+
isFirstRegion = false;
|
|
126
|
+
}
|
|
127
|
+
return pages;
|
|
85
128
|
}
|
|
86
129
|
/**
|
|
87
|
-
* Lays out one fragment
|
|
88
|
-
* header/footer are attached to every physical page so they repeat
|
|
130
|
+
* Lays out one physical page and renders it. A fragment gets a fresh `PageElement` of the same
|
|
131
|
+
* geometry; the header/footer are attached to every physical page so they repeat, and `PageElement`
|
|
89
132
|
* re-places them and the body in the band between.
|
|
90
133
|
*/
|
|
91
|
-
static renderPhysicalPage(
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
134
|
+
static async renderPhysicalPage(physical, objectManager, ctx) {
|
|
135
|
+
if (physical.kind === "whole") {
|
|
136
|
+
physical.page.calculateLayout(new BoxConstraints(), { x: 0, y: 0 }, ctx);
|
|
137
|
+
return PageRenderer.render(physical.page, objectManager);
|
|
138
|
+
}
|
|
139
|
+
const page = new PageElement({
|
|
140
|
+
config: physical.config,
|
|
141
|
+
header: physical.header,
|
|
142
|
+
footer: physical.footer,
|
|
143
|
+
children: [physical.content],
|
|
101
144
|
});
|
|
145
|
+
page.calculateLayout(new BoxConstraints(), { x: 0, y: 0 }, ctx);
|
|
146
|
+
return PageRenderer.render(page, objectManager);
|
|
102
147
|
}
|
|
103
148
|
}
|
|
104
|
-
exports.PDFDocumentRenderer = PDFDocumentRenderer;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PDFDocumentElement } from "../elements/pdf-document-element";
|
|
2
|
-
import { PDFObjectManager } from "../utils/pdf-object-manager";
|
|
1
|
+
import { PDFDocumentElement } from "../elements/pdf-document-element.js";
|
|
2
|
+
import { PDFObjectManager } from "../utils/pdf-object-manager.js";
|
|
3
3
|
export declare class PDFRenderer {
|
|
4
4
|
static render(document: PDFDocumentElement, objectManager: PDFObjectManager): Promise<string>;
|
|
5
5
|
}
|
|
@@ -1,92 +1,167 @@
|
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
1
|
+
import { PDFDocumentRenderer } from "./pdf-document-renderer.js";
|
|
2
|
+
import { RendererRegistry } from "../utils/renderer-registry.js";
|
|
3
|
+
import { DefaultTextStyleElement, ExpandedElement, ImageElement, LineElement, PaddingElement, TextElement, } from "../elements/index.js";
|
|
4
|
+
import { TextRenderer } from "./text-renderer.js";
|
|
5
|
+
import { ContainerElement } from "../elements/container-element.js";
|
|
6
|
+
import { RectangleElement } from "../elements/rectangle-element.js";
|
|
7
|
+
import { RowElement } from "../elements/row-element.js";
|
|
8
|
+
import { ContainerRenderer } from "./container-renderer.js";
|
|
9
|
+
import { RectangleRenderer } from "./rectangle-renderer.js";
|
|
10
|
+
import { RowRenderer } from "./row-renderer.js";
|
|
11
|
+
import { ExpandedRenderer } from "./expanded-renderer.js";
|
|
12
|
+
import { PaddingRenderer } from "./padding-renderer.js";
|
|
13
|
+
import { DefaultTextStyleRenderer } from "./default-text-style-renderer.js";
|
|
14
|
+
import { ImageRenderer } from "./image-renderer.js";
|
|
15
|
+
import { LineRenderer } from "./line-renderer.js";
|
|
16
|
+
import { RepeatingHeaderElement } from "../elements/layout/repeating-header-element.js";
|
|
17
|
+
import { RepeatingHeaderRenderer } from "./repeating-header-renderer.js";
|
|
18
|
+
import { DeferredElement } from "../elements/layout/deferred-element.js";
|
|
19
|
+
import { DeferredRenderer } from "./deferred-renderer.js";
|
|
20
|
+
import { PositionedElement } from "../elements/layout/positioned-element.js";
|
|
21
|
+
import { PositionedRenderer } from "./positioned-renderer.js";
|
|
22
|
+
import { StructGroup } from "../elements/layout/struct-group.js";
|
|
23
|
+
import { StructGroupRenderer } from "./struct-group-renderer.js";
|
|
24
|
+
import { LinkElement } from "../elements/layout/link-element.js";
|
|
25
|
+
import { LinkRenderer } from "./link-renderer.js";
|
|
26
|
+
import { BookmarkElement } from "../elements/layout/bookmark-element.js";
|
|
27
|
+
import { BookmarkRenderer } from "./bookmark-renderer.js";
|
|
28
|
+
import { AnchorElement } from "../elements/layout/anchor-element.js";
|
|
29
|
+
import { PageBreakElement } from "../elements/layout/page-break-element.js";
|
|
30
|
+
import { AnchorRenderer } from "./anchor-renderer.js";
|
|
31
|
+
import { PageBreakRenderer } from "./page-break-renderer.js";
|
|
32
|
+
import { KeepTogetherElement } from "../elements/layout/keep-together-element.js";
|
|
33
|
+
import { KeepTogetherRenderer } from "./keep-together-renderer.js";
|
|
34
|
+
import { TextFieldElement } from "../elements/forms/text-field-element.js";
|
|
35
|
+
import { CheckboxElement } from "../elements/forms/checkbox-element.js";
|
|
36
|
+
import { RadioElement } from "../elements/forms/radio-element.js";
|
|
37
|
+
import { ChoiceElement } from "../elements/forms/choice-element.js";
|
|
38
|
+
import { PushButtonElement } from "../elements/forms/push-button-element.js";
|
|
39
|
+
import { SignatureFieldElement } from "../elements/forms/signature-element.js";
|
|
40
|
+
import { FormFieldRenderer } from "./form-field-renderer.js";
|
|
41
|
+
import { PageBuilderElement } from "../elements/layout/page-builder-element.js";
|
|
42
|
+
import { PageBuilderRenderer } from "./page-builder-renderer.js";
|
|
43
|
+
import { RotatedElement } from "../elements/layout/rotated-element.js";
|
|
44
|
+
import { RotatedBoxElement } from "../elements/layout/rotated-box-element.js";
|
|
45
|
+
import { RotatedRenderer } from "./rotated-renderer.js";
|
|
46
|
+
import { PdfBackend } from "./pdf-backend.js";
|
|
47
|
+
import { BoxConstraints } from "../layout/box-constraints.js";
|
|
48
|
+
import { collectImageElements } from "../layout/collect-images.js";
|
|
49
|
+
import { DEFAULT_TEXT_STYLE, mergeTextStyle } from "../text/text-style.js";
|
|
50
|
+
export class PDFRenderer {
|
|
51
|
+
static async render(document, objectManager) {
|
|
52
|
+
// Register all Renderer
|
|
53
|
+
RendererRegistry.register(TextElement, TextRenderer.render);
|
|
54
|
+
RendererRegistry.register(ContainerElement, ContainerRenderer.render);
|
|
55
|
+
RendererRegistry.register(RowElement, RowRenderer.render);
|
|
56
|
+
RendererRegistry.register(RectangleElement, RectangleRenderer.render);
|
|
57
|
+
RendererRegistry.register(ExpandedElement, ExpandedRenderer.render);
|
|
58
|
+
RendererRegistry.register(PaddingElement, PaddingRenderer.render);
|
|
59
|
+
RendererRegistry.register(PageBreakElement, PageBreakRenderer.render);
|
|
60
|
+
RendererRegistry.register(KeepTogetherElement, KeepTogetherRenderer.render);
|
|
61
|
+
RendererRegistry.register(TextFieldElement, FormFieldRenderer.render);
|
|
62
|
+
RendererRegistry.register(CheckboxElement, FormFieldRenderer.render);
|
|
63
|
+
RendererRegistry.register(RadioElement, FormFieldRenderer.render);
|
|
64
|
+
RendererRegistry.register(ChoiceElement, FormFieldRenderer.render);
|
|
65
|
+
RendererRegistry.register(PushButtonElement, FormFieldRenderer.render);
|
|
66
|
+
RendererRegistry.register(SignatureFieldElement, FormFieldRenderer.render);
|
|
67
|
+
RendererRegistry.register(DefaultTextStyleElement, DefaultTextStyleRenderer.render);
|
|
68
|
+
RendererRegistry.register(ImageElement, ImageRenderer.render);
|
|
69
|
+
RendererRegistry.register(LineElement, LineRenderer.render);
|
|
70
|
+
RendererRegistry.register(RepeatingHeaderElement, RepeatingHeaderRenderer.render);
|
|
71
|
+
RendererRegistry.register(DeferredElement, DeferredRenderer.render);
|
|
72
|
+
RendererRegistry.register(PositionedElement, PositionedRenderer.render);
|
|
73
|
+
RendererRegistry.register(StructGroup, StructGroupRenderer.render);
|
|
74
|
+
RendererRegistry.register(LinkElement, LinkRenderer.render);
|
|
75
|
+
RendererRegistry.register(BookmarkElement, BookmarkRenderer.render);
|
|
76
|
+
RendererRegistry.register(AnchorElement, AnchorRenderer.render);
|
|
77
|
+
RendererRegistry.register(PageBuilderElement, PageBuilderRenderer.render);
|
|
78
|
+
RendererRegistry.register(RotatedElement, RotatedRenderer.render);
|
|
79
|
+
RendererRegistry.register(RotatedBoxElement, RotatedRenderer.render);
|
|
80
|
+
let pdfContent = "";
|
|
81
|
+
// Header: version line + the PDF/A binary marker (the object manager owns it so its length
|
|
82
|
+
// matches the xref offset calculation).
|
|
83
|
+
pdfContent += objectManager.getHeader();
|
|
84
|
+
// Layout pass: thread the context explicitly. The seed page config is the document
|
|
85
|
+
// default; each PageElement overrides it for its own subtree.
|
|
86
|
+
const ctx = {
|
|
87
|
+
metrics: objectManager,
|
|
88
|
+
pageConfig: objectManager.getPDFConfig(),
|
|
89
|
+
textStyle: mergeTextStyle(DEFAULT_TEXT_STYLE, document.getDefaultTextStyle()),
|
|
90
|
+
onOverflow: objectManager.getOverflowPolicy(),
|
|
91
|
+
};
|
|
92
|
+
// Pre-layout: resolve every image's intrinsic pixel size (async), so the synchronous layout can
|
|
93
|
+
// give a width-only image a proportional height. init() is idempotent, so the renderer reuses it.
|
|
94
|
+
const images = collectImageElements(document);
|
|
95
|
+
if (images.length > 0)
|
|
96
|
+
await Promise.all(images.map((img) => img.resolveIntrinsicSize()));
|
|
97
|
+
document.calculateLayout(new BoxConstraints(), { x: 0, y: 0 }, ctx);
|
|
98
|
+
// Render pages and contents (the driver paginates overflowing pages).
|
|
99
|
+
await PDFDocumentRenderer.render(document, objectManager, ctx);
|
|
100
|
+
// Add the catalog. XMP metadata (/Metadata) and embedded files (/AF + /Names/EmbeddedFiles)
|
|
101
|
+
// are added only when present; with neither, the catalog is byte-identical to before.
|
|
102
|
+
const catalogParts = [`/Type /Catalog /Pages ${objectManager.getParentObjectNumber()} 0 R`];
|
|
103
|
+
const xmp = objectManager.getXmpMetadata();
|
|
104
|
+
if (xmp) {
|
|
105
|
+
const metadataObject = objectManager.addObject(`<< /Type /Metadata /Subtype /XML /Length ${xmp.length} >>\nstream\n${xmp}\nendstream`);
|
|
106
|
+
catalogParts.push(`/Metadata ${metadataObject} 0 R`);
|
|
107
|
+
}
|
|
108
|
+
const outputIntent = objectManager.getOutputIntent();
|
|
109
|
+
if (outputIntent) {
|
|
110
|
+
catalogParts.push(`/OutputIntents [${outputIntent} 0 R]`);
|
|
111
|
+
}
|
|
112
|
+
// The catalog has exactly one /Names dict; embedded files and named destinations are two entries in
|
|
113
|
+
// it, so collect both and emit the /Names once (below).
|
|
114
|
+
const namesParts = [];
|
|
115
|
+
const attachments = objectManager.getAttachments();
|
|
116
|
+
if (attachments.length > 0) {
|
|
117
|
+
// The name-tree key is a PDF literal string, so it needs the same escaping the /Filespec's /F and
|
|
118
|
+
// /UF get in attachFile(). Unescaped, a ")" or "\" in a file name closes the string early and the
|
|
119
|
+
// rest of it leaks out as raw operators.
|
|
120
|
+
const names = attachments
|
|
121
|
+
.map((a) => `(${PdfBackend.escapePdfString(a.name)}) ${a.filespec} 0 R`)
|
|
122
|
+
.join(" ");
|
|
123
|
+
const af = attachments.map((a) => `${a.filespec} 0 R`).join(" ");
|
|
124
|
+
catalogParts.push(`/AF [${af}]`);
|
|
125
|
+
namesParts.push(`/EmbeddedFiles << /Names [${names}] >>`);
|
|
126
|
+
}
|
|
127
|
+
// Accessible tagging: finalize the structure tree (emits StructTreeRoot + StructElems + ParentTree) and
|
|
128
|
+
// fold /MarkInfo + /StructTreeRoot + /Lang into the catalog. Returns "" (no-op) when tagging is off.
|
|
129
|
+
const structCatalog = objectManager.struct.finalize(objectManager);
|
|
130
|
+
if (structCatalog) {
|
|
131
|
+
catalogParts.push(structCatalog);
|
|
132
|
+
// PDF/UA requires the viewer to show the document title (not the file name).
|
|
133
|
+
catalogParts.push("/ViewerPreferences << /DisplayDocTitle true >>");
|
|
134
|
+
}
|
|
135
|
+
// Document outline (bookmarks): emit the /Outlines tree collected during page rendering. Returns
|
|
136
|
+
// "" (no-op) when no Bookmark was placed, so a plain document's catalog is unchanged.
|
|
137
|
+
const outlineCatalog = objectManager.outline.finalize(objectManager);
|
|
138
|
+
if (outlineCatalog)
|
|
139
|
+
catalogParts.push(outlineCatalog);
|
|
140
|
+
// Interactive form fields: emit the catalog /AcroForm dict collected as pages rendered. Returns ""
|
|
141
|
+
// (no-op) when no field was placed, so a plain document's catalog is unchanged.
|
|
142
|
+
const acroformCatalog = objectManager.acroform.finalize(objectManager);
|
|
143
|
+
if (acroformCatalog)
|
|
144
|
+
catalogParts.push(acroformCatalog);
|
|
145
|
+
// Named destinations (internal-link targets): a /Dests entry in the shared /Names dict.
|
|
146
|
+
const destsNames = objectManager.dests.finalize(objectManager);
|
|
147
|
+
if (destsNames)
|
|
148
|
+
namesParts.push(destsNames);
|
|
149
|
+
// Emit the single /Names dict if either embedded files or destinations contributed to it.
|
|
150
|
+
if (namesParts.length > 0)
|
|
151
|
+
catalogParts.push(`/Names << ${namesParts.join(" ")} >>`);
|
|
152
|
+
const catalogObject = `<< ${catalogParts.join(" ")} >>`;
|
|
153
|
+
objectManager.addObject(catalogObject);
|
|
154
|
+
// Now that the render pass has revealed which glyphs each embedded font uses, fill the reserved
|
|
155
|
+
// font objects with the subset font program (must happen before the objects are serialized).
|
|
156
|
+
objectManager.finalizeCustomFonts();
|
|
157
|
+
// Encrypt every registered stream + add the /Encrypt object (no-op unless a security handler was set).
|
|
158
|
+
await objectManager.finalizeEncryption();
|
|
159
|
+
// Add rendered objects
|
|
160
|
+
pdfContent += objectManager.getRenderedObjects();
|
|
161
|
+
// Add XRef table and trailer
|
|
162
|
+
const startxref = pdfContent.length;
|
|
163
|
+
pdfContent += objectManager.getXRefTable();
|
|
164
|
+
pdfContent += objectManager.getTrailerAndXRef(startxref);
|
|
165
|
+
return pdfContent;
|
|
90
166
|
}
|
|
91
167
|
}
|
|
92
|
-
exports.PDFRenderer = PDFRenderer;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { PDFObjectManager } from "../utils/pdf-object-manager.js";
|
|
2
|
+
import { PositionedElement } from "../elements/layout/positioned-element.js";
|
|
3
|
+
import { IRNode } from "../ir/display-list.js";
|
|
4
|
+
export declare class PositionedRenderer {
|
|
5
|
+
static render(positionedElement: PositionedElement, objectManager: PDFObjectManager): Promise<IRNode[]>;
|
|
6
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { RendererRegistry } from "../utils/renderer-registry.js";
|
|
2
|
+
export class PositionedRenderer {
|
|
3
|
+
static async render(positionedElement, objectManager) {
|
|
4
|
+
// The child was already placed (by the frame) during layout; just emit its IR. It is drawn
|
|
5
|
+
// after the frame's flow content, so it paints on top.
|
|
6
|
+
const { child } = positionedElement.getProps();
|
|
7
|
+
const renderer = RendererRegistry.getRenderer(child);
|
|
8
|
+
return renderer(child, objectManager);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { PDFObjectManager } from "../utils/pdf-object-manager";
|
|
2
|
-
import { RectangleElement } from "../elements/rectangle-element";
|
|
3
|
-
import { IRNode } from "../ir/display-list";
|
|
1
|
+
import { PDFObjectManager } from "../utils/pdf-object-manager.js";
|
|
2
|
+
import { RectangleElement } from "../elements/rectangle-element.js";
|
|
3
|
+
import { IRNode } from "../ir/display-list.js";
|
|
4
4
|
export declare class RectangleRenderer {
|
|
5
5
|
static render(rectangleElement: RectangleElement, objectManager: PDFObjectManager): Promise<IRNode[]>;
|
|
6
6
|
/** One `line` node per present side, along the box edges (top-left coordinates). */
|