@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
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { BoxConstraints, Offset, Size } from "../../layout/box-constraints.js";
|
|
2
|
+
import { Fragmentable, FragmentResult } from "../../layout/fragmentation.js";
|
|
3
|
+
import { LayoutContext, PDFElement } from "../pdf-element.js";
|
|
4
|
+
/**
|
|
5
|
+
* A wrapper that is transparent to layout (Flutter's `RenderProxyBox`): its one child gets the same
|
|
6
|
+
* constraints, sits at the same offset and gives the same size. Every sizing and pagination signal the
|
|
7
|
+
* child sends is passed on, so wrapping something never changes how it is sized or broken across
|
|
8
|
+
* pages - a `PageBreak` inside a `Link` breaks, a `Bookmark` around a chapter splits like the chapter.
|
|
9
|
+
*
|
|
10
|
+
* What a wrapper adds (a link, a jump target, a role, inherited text defaults) it adds through two
|
|
11
|
+
* hooks: `childContext` for what the child is laid out in, and `rewrap` for the pieces of a split.
|
|
12
|
+
*/
|
|
13
|
+
export declare abstract class ProxyElement extends PDFElement implements Fragmentable {
|
|
14
|
+
protected readonly child: PDFElement;
|
|
15
|
+
protected x: number;
|
|
16
|
+
protected y: number;
|
|
17
|
+
protected width: number;
|
|
18
|
+
protected height: number;
|
|
19
|
+
protected constructor(child: PDFElement);
|
|
20
|
+
/** The context the child is laid out in: unchanged, unless the wrapper hands something down. */
|
|
21
|
+
protected childContext(ctx: LayoutContext): LayoutContext;
|
|
22
|
+
/**
|
|
23
|
+
* This wrapper around a piece of its split child. `continued` is true for every piece but the first
|
|
24
|
+
* one that holds something: a wrapper that marks a single place (a jump target, an outline entry)
|
|
25
|
+
* returns the piece bare there, so the mark is not repeated on the next page.
|
|
26
|
+
*/
|
|
27
|
+
protected abstract rewrap(child: PDFElement, continued: boolean): PDFElement;
|
|
28
|
+
calculateLayout(constraints: BoxConstraints, offset: Offset, ctx: LayoutContext): Size;
|
|
29
|
+
protected computeSize(constraints: BoxConstraints, ctx: LayoutContext): Size;
|
|
30
|
+
layoutChildren(): readonly PDFElement[];
|
|
31
|
+
/** Transparent to a surrounding Row or Column too: it sees the child's flex properties. */
|
|
32
|
+
proxied(): PDFElement;
|
|
33
|
+
relativeSizeFactor(horizontal: boolean): number | undefined;
|
|
34
|
+
needsBoundedMain(horizontal: boolean): boolean;
|
|
35
|
+
minIntrinsicMain(horizontal: boolean, ctx: LayoutContext): number;
|
|
36
|
+
isPageBreak(): boolean;
|
|
37
|
+
hasForcedBreak(): boolean;
|
|
38
|
+
breaksBefore(): boolean;
|
|
39
|
+
breaksAfter(): boolean;
|
|
40
|
+
/** Splittable exactly when the child is; otherwise the parent moves it to the next page whole. */
|
|
41
|
+
canFragment(): boolean;
|
|
42
|
+
fragment(maxHeight: number, width: number, ctx: LayoutContext): FragmentResult;
|
|
43
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { BoxConstraints } from "../../layout/box-constraints.js";
|
|
2
|
+
import { isFragmentable } from "../../layout/fragmentation.js";
|
|
3
|
+
import { PDFElement } from "../pdf-element.js";
|
|
4
|
+
/**
|
|
5
|
+
* A wrapper that is transparent to layout (Flutter's `RenderProxyBox`): its one child gets the same
|
|
6
|
+
* constraints, sits at the same offset and gives the same size. Every sizing and pagination signal the
|
|
7
|
+
* child sends is passed on, so wrapping something never changes how it is sized or broken across
|
|
8
|
+
* pages - a `PageBreak` inside a `Link` breaks, a `Bookmark` around a chapter splits like the chapter.
|
|
9
|
+
*
|
|
10
|
+
* What a wrapper adds (a link, a jump target, a role, inherited text defaults) it adds through two
|
|
11
|
+
* hooks: `childContext` for what the child is laid out in, and `rewrap` for the pieces of a split.
|
|
12
|
+
*/
|
|
13
|
+
export class ProxyElement extends PDFElement {
|
|
14
|
+
constructor(child) {
|
|
15
|
+
super();
|
|
16
|
+
this.child = child;
|
|
17
|
+
// The box the child took, for renderers that mark it (a link's hit area, a jump target's top).
|
|
18
|
+
this.x = 0;
|
|
19
|
+
this.y = 0;
|
|
20
|
+
this.width = 0;
|
|
21
|
+
this.height = 0;
|
|
22
|
+
}
|
|
23
|
+
/** The context the child is laid out in: unchanged, unless the wrapper hands something down. */
|
|
24
|
+
childContext(ctx) {
|
|
25
|
+
return ctx;
|
|
26
|
+
}
|
|
27
|
+
calculateLayout(constraints, offset, ctx) {
|
|
28
|
+
const size = this.child.calculateLayout(constraints, offset, this.childContext(ctx));
|
|
29
|
+
this.x = offset.x;
|
|
30
|
+
this.y = offset.y;
|
|
31
|
+
this.width = size.width;
|
|
32
|
+
this.height = size.height;
|
|
33
|
+
return size;
|
|
34
|
+
}
|
|
35
|
+
computeSize(constraints, ctx) {
|
|
36
|
+
return this.child.measure(constraints, this.childContext(ctx));
|
|
37
|
+
}
|
|
38
|
+
layoutChildren() {
|
|
39
|
+
return [this.child];
|
|
40
|
+
}
|
|
41
|
+
/** Transparent to a surrounding Row or Column too: it sees the child's flex properties. */
|
|
42
|
+
proxied() {
|
|
43
|
+
return this.child;
|
|
44
|
+
}
|
|
45
|
+
relativeSizeFactor(horizontal) {
|
|
46
|
+
return this.child.relativeSizeFactor(horizontal);
|
|
47
|
+
}
|
|
48
|
+
needsBoundedMain(horizontal) {
|
|
49
|
+
return this.child.needsBoundedMain(horizontal);
|
|
50
|
+
}
|
|
51
|
+
minIntrinsicMain(horizontal, ctx) {
|
|
52
|
+
return this.child.minIntrinsicMain(horizontal, this.childContext(ctx));
|
|
53
|
+
}
|
|
54
|
+
isPageBreak() {
|
|
55
|
+
return this.child.isPageBreak();
|
|
56
|
+
}
|
|
57
|
+
hasForcedBreak() {
|
|
58
|
+
return this.child.hasForcedBreak();
|
|
59
|
+
}
|
|
60
|
+
breaksBefore() {
|
|
61
|
+
return this.child.breaksBefore();
|
|
62
|
+
}
|
|
63
|
+
breaksAfter() {
|
|
64
|
+
return this.child.breaksAfter();
|
|
65
|
+
}
|
|
66
|
+
/** Splittable exactly when the child is; otherwise the parent moves it to the next page whole. */
|
|
67
|
+
canFragment() {
|
|
68
|
+
return isFragmentable(this.child);
|
|
69
|
+
}
|
|
70
|
+
fragment(maxHeight, width, ctx) {
|
|
71
|
+
if (!isFragmentable(this.child))
|
|
72
|
+
return { fitted: null, remainder: this };
|
|
73
|
+
const childCtx = this.childContext(ctx);
|
|
74
|
+
const split = this.child.fragment(maxHeight, width, childCtx);
|
|
75
|
+
// The child handed itself back (it all fits, or none of it does): so does the wrapper, mark included.
|
|
76
|
+
const wrap = (piece, continued) => {
|
|
77
|
+
if (piece === this.child)
|
|
78
|
+
return this;
|
|
79
|
+
const wrapped = this.rewrap(piece, continued);
|
|
80
|
+
// A wrapper dropped from a continued piece still leaves that piece in its place in the flow.
|
|
81
|
+
return wrapped === piece ? piece.takeFlexItemFrom(this) : wrapped.asPieceOf(this);
|
|
82
|
+
};
|
|
83
|
+
// A fitted piece with no height (what a leading `PageBreak` leaves) holds nothing to mark: the
|
|
84
|
+
// mark goes on with the remainder, where the content is.
|
|
85
|
+
const placed = split.fitted !== null &&
|
|
86
|
+
(split.remainder === null ||
|
|
87
|
+
split.fitted.measure(BoxConstraints.loose(width, Infinity), childCtx).height > 0);
|
|
88
|
+
return {
|
|
89
|
+
fitted: split.fitted && wrap(split.fitted, !placed),
|
|
90
|
+
remainder: split.remainder && wrap(split.remainder, placed),
|
|
91
|
+
forceBreak: split.forceBreak,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -17,7 +17,13 @@ export declare class RepeatingHeaderElement extends PDFElement implements Fragme
|
|
|
17
17
|
private height;
|
|
18
18
|
constructor(header: PDFElement, body: PDFElement, gap?: number);
|
|
19
19
|
calculateLayout(constraints: BoxConstraints, offset: Offset, ctx: LayoutContext): Size;
|
|
20
|
+
protected computeSize(constraints: BoxConstraints, ctx: LayoutContext): Size;
|
|
21
|
+
/** The one sizing path: `layout` places header and body (relative to this box), `measure` sizes. */
|
|
22
|
+
private sizeWith;
|
|
20
23
|
fragment(maxHeight: number, width: number, ctx: LayoutContext): FragmentResult;
|
|
24
|
+
/** A break inside the body is a break in the flow the table sits in. */
|
|
25
|
+
hasForcedBreak(): boolean;
|
|
26
|
+
layoutChildren(): readonly PDFElement[];
|
|
21
27
|
getProps(): {
|
|
22
28
|
x: number;
|
|
23
29
|
y: number;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BoxConstraints } from "../../layout/box-constraints.js";
|
|
2
|
-
import { isFragmentable } from "../../layout/fragmentation.js";
|
|
2
|
+
import { insetContext, isFragmentable, } from "../../layout/fragmentation.js";
|
|
3
3
|
import { PDFElement } from "../pdf-element.js";
|
|
4
4
|
/**
|
|
5
5
|
* Stacks a `header` above a `body` and, when it paginates, **repeats the header on every
|
|
@@ -19,30 +19,57 @@ export class RepeatingHeaderElement extends PDFElement {
|
|
|
19
19
|
this.height = 0;
|
|
20
20
|
}
|
|
21
21
|
calculateLayout(constraints, offset, ctx) {
|
|
22
|
+
const size = this.sizeWith(constraints, ctx, "layout");
|
|
22
23
|
this.x = offset.x;
|
|
23
24
|
this.y = offset.y;
|
|
25
|
+
this.width = size.width;
|
|
26
|
+
this.height = size.height;
|
|
27
|
+
return size;
|
|
28
|
+
}
|
|
29
|
+
computeSize(constraints, ctx) {
|
|
30
|
+
return this.sizeWith(constraints, ctx, "measure");
|
|
31
|
+
}
|
|
32
|
+
/** The one sizing path: `layout` places header and body (relative to this box), `measure` sizes. */
|
|
33
|
+
sizeWith(constraints, ctx, mode) {
|
|
24
34
|
const width = constraints.hasBoundedWidth ? constraints.maxWidth : 0;
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
const inner = BoxConstraints.loose(width, Infinity);
|
|
36
|
+
const h = mode === "layout"
|
|
37
|
+
? this.header.calculateLayout(inner, { x: 0, y: 0 }, ctx)
|
|
38
|
+
: this.header.measure(inner, ctx);
|
|
39
|
+
const b = mode === "layout"
|
|
40
|
+
? this.body.calculateLayout(inner, { x: 0, y: h.height + this.gap }, ctx)
|
|
41
|
+
: this.body.measure(inner, ctx);
|
|
42
|
+
return { width, height: h.height + this.gap + b.height };
|
|
30
43
|
}
|
|
31
44
|
fragment(maxHeight, width, ctx) {
|
|
32
45
|
// Reserve the header's height on every page; the body flows in what's left.
|
|
33
|
-
const headerHeight = this.header.
|
|
46
|
+
const headerHeight = this.header.measure(BoxConstraints.loose(width, Infinity), ctx).height;
|
|
34
47
|
if (!isFragmentable(this.body))
|
|
35
48
|
return { fitted: this, remainder: null };
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
49
|
+
const chrome = headerHeight + this.gap;
|
|
50
|
+
const split = this.body.fragment(Math.max(0, maxHeight - chrome), width, insetContext(ctx, chrome));
|
|
51
|
+
// Body fits whole, no break inside → the whole thing fits on this page.
|
|
52
|
+
if (split.remainder === null && !split.forceBreak)
|
|
39
53
|
return { fitted: this, remainder: null };
|
|
40
|
-
// Re-wrap each body piece with the SAME header → it reappears on the next page too.
|
|
54
|
+
// Re-wrap each body piece with the SAME header → it reappears on the next page too. A forced
|
|
55
|
+
// break inside the body is passed on, so the page ends there.
|
|
41
56
|
return {
|
|
42
|
-
fitted: split.fitted
|
|
43
|
-
|
|
57
|
+
fitted: split.fitted
|
|
58
|
+
? new RepeatingHeaderElement(this.header, split.fitted, this.gap).asPieceOf(this)
|
|
59
|
+
: null,
|
|
60
|
+
remainder: split.remainder
|
|
61
|
+
? new RepeatingHeaderElement(this.header, split.remainder, this.gap).asPieceOf(this)
|
|
62
|
+
: null,
|
|
63
|
+
forceBreak: split.forceBreak,
|
|
44
64
|
};
|
|
45
65
|
}
|
|
66
|
+
/** A break inside the body is a break in the flow the table sits in. */
|
|
67
|
+
hasForcedBreak() {
|
|
68
|
+
return this.body.hasForcedBreak();
|
|
69
|
+
}
|
|
70
|
+
layoutChildren() {
|
|
71
|
+
return [this.header, this.body];
|
|
72
|
+
}
|
|
46
73
|
getProps() {
|
|
47
74
|
return {
|
|
48
75
|
x: this.x,
|
|
@@ -23,7 +23,13 @@ export declare class RotatedBoxElement extends PDFElement {
|
|
|
23
23
|
child: PDFElement;
|
|
24
24
|
});
|
|
25
25
|
calculateLayout(constraints: BoxConstraints, offset: Offset, ctx: LayoutContext): Size;
|
|
26
|
+
protected computeSize(constraints: BoxConstraints, ctx: LayoutContext): Size;
|
|
27
|
+
/** 90 or 270 degrees swap the axes: the child experiences the box's constraints turned. */
|
|
28
|
+
private get quarter();
|
|
29
|
+
private childConstraints;
|
|
30
|
+
private swap;
|
|
26
31
|
/** Same shape as `RotatedElement` (angle + box), so both share `RotatedRenderer`. */
|
|
32
|
+
layoutChildren(): readonly PDFElement[];
|
|
27
33
|
getProps(): {
|
|
28
34
|
angle: number;
|
|
29
35
|
child: PDFElement;
|
|
@@ -22,25 +22,38 @@ export class RotatedBoxElement extends PDFElement {
|
|
|
22
22
|
this.child = child;
|
|
23
23
|
}
|
|
24
24
|
calculateLayout(constraints, offset, ctx) {
|
|
25
|
-
const quarter = this.turns % 2 === 1; // 90 or 270: axes swap
|
|
26
|
-
// A quarter-turned child experiences the box's constraints with the axes swapped.
|
|
27
|
-
const childConstraints = quarter
|
|
28
|
-
? new BoxConstraints(constraints.minHeight, constraints.maxHeight, constraints.minWidth, constraints.maxWidth)
|
|
29
|
-
: constraints;
|
|
30
25
|
// Measure the child to learn its natural size, then take that size swapped as our own box.
|
|
31
|
-
const child = this.child.
|
|
32
|
-
|
|
33
|
-
this.
|
|
26
|
+
const child = this.child.measure(this.childConstraints(constraints), ctx);
|
|
27
|
+
const size = this.swap(child);
|
|
28
|
+
this.width = size.width;
|
|
29
|
+
this.height = size.height;
|
|
34
30
|
this.x = offset.x;
|
|
35
31
|
this.y = offset.y;
|
|
36
|
-
//
|
|
37
|
-
// child's (w x h) box exactly onto our (swapped) box - so the shared renderer
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
// Place the child CENTERED on the box center (relative to our top-left): a rotation around that
|
|
33
|
+
// center then maps the child's (w x h) box exactly onto our (swapped) box - so the shared renderer
|
|
34
|
+
// needs no special case.
|
|
35
|
+
this.child.calculateLayout(this.childConstraints(constraints), { x: (this.width - child.width) / 2, y: (this.height - child.height) / 2 }, ctx);
|
|
36
|
+
return size;
|
|
37
|
+
}
|
|
38
|
+
computeSize(constraints, ctx) {
|
|
39
|
+
return this.swap(this.child.measure(this.childConstraints(constraints), ctx));
|
|
40
|
+
}
|
|
41
|
+
/** 90 or 270 degrees swap the axes: the child experiences the box's constraints turned. */
|
|
42
|
+
get quarter() {
|
|
43
|
+
return this.turns % 2 === 1;
|
|
44
|
+
}
|
|
45
|
+
childConstraints(constraints) {
|
|
46
|
+
return this.quarter
|
|
47
|
+
? new BoxConstraints(constraints.minHeight, constraints.maxHeight, constraints.minWidth, constraints.maxWidth)
|
|
48
|
+
: constraints;
|
|
49
|
+
}
|
|
50
|
+
swap(child) {
|
|
51
|
+
return this.quarter ? { width: child.height, height: child.width } : child;
|
|
42
52
|
}
|
|
43
53
|
/** Same shape as `RotatedElement` (angle + box), so both share `RotatedRenderer`. */
|
|
54
|
+
layoutChildren() {
|
|
55
|
+
return [this.child];
|
|
56
|
+
}
|
|
44
57
|
getProps() {
|
|
45
58
|
return {
|
|
46
59
|
angle: this.turns * 90,
|
|
@@ -21,6 +21,13 @@ export declare class RotatedElement extends PDFElement {
|
|
|
21
21
|
child: PDFElement;
|
|
22
22
|
});
|
|
23
23
|
calculateLayout(constraints: BoxConstraints, offset: Offset, ctx: LayoutContext): Size;
|
|
24
|
+
protected computeSize(constraints: BoxConstraints, ctx: LayoutContext): Size;
|
|
25
|
+
layoutChildren(): readonly PDFElement[];
|
|
26
|
+
relativeSizeFactor(horizontal: boolean): number | undefined;
|
|
27
|
+
needsBoundedMain(horizontal: boolean): boolean;
|
|
28
|
+
minIntrinsicMain(horizontal: boolean, ctx: LayoutContext): number;
|
|
29
|
+
breaksBefore(): boolean;
|
|
30
|
+
breaksAfter(): boolean;
|
|
24
31
|
getProps(): {
|
|
25
32
|
angle: number;
|
|
26
33
|
child: PDFElement;
|
|
@@ -19,15 +19,38 @@ export class RotatedElement extends PDFElement {
|
|
|
19
19
|
this.child = child;
|
|
20
20
|
}
|
|
21
21
|
calculateLayout(constraints, offset, ctx) {
|
|
22
|
-
// Delegate entirely to the child, then record its
|
|
22
|
+
// Delegate entirely to the child (at our own top-left), then record its size as our own - the
|
|
23
23
|
// rotation does not change what space we take, only how the child is painted.
|
|
24
|
-
const size = this.child.calculateLayout(constraints,
|
|
24
|
+
const size = this.child.calculateLayout(constraints, { x: 0, y: 0 }, ctx);
|
|
25
25
|
this.x = offset.x;
|
|
26
26
|
this.y = offset.y;
|
|
27
27
|
this.width = size.width;
|
|
28
28
|
this.height = size.height;
|
|
29
29
|
return size;
|
|
30
30
|
}
|
|
31
|
+
computeSize(constraints, ctx) {
|
|
32
|
+
return this.child.measure(constraints, ctx);
|
|
33
|
+
}
|
|
34
|
+
layoutChildren() {
|
|
35
|
+
return [this.child];
|
|
36
|
+
}
|
|
37
|
+
// It takes the child's space, so the child's sizing hints and its break-before/after are its own.
|
|
38
|
+
// It is never split - half a rotation on each page means nothing - so a break INSIDE stays inside.
|
|
39
|
+
relativeSizeFactor(horizontal) {
|
|
40
|
+
return this.child.relativeSizeFactor(horizontal);
|
|
41
|
+
}
|
|
42
|
+
needsBoundedMain(horizontal) {
|
|
43
|
+
return this.child.needsBoundedMain(horizontal);
|
|
44
|
+
}
|
|
45
|
+
minIntrinsicMain(horizontal, ctx) {
|
|
46
|
+
return this.child.minIntrinsicMain(horizontal, ctx);
|
|
47
|
+
}
|
|
48
|
+
breaksBefore() {
|
|
49
|
+
return this.child.breaksBefore();
|
|
50
|
+
}
|
|
51
|
+
breaksAfter() {
|
|
52
|
+
return this.child.breaksAfter();
|
|
53
|
+
}
|
|
31
54
|
getProps() {
|
|
32
55
|
return {
|
|
33
56
|
angle: this.angle,
|
|
@@ -1,28 +1,20 @@
|
|
|
1
|
-
import { PDFElement
|
|
2
|
-
import {
|
|
3
|
-
import { Fragmentable, FragmentResult } from "../../layout/fragmentation.js";
|
|
1
|
+
import { PDFElement } from "../pdf-element.js";
|
|
2
|
+
import { ProxyElement } from "./proxy-element.js";
|
|
4
3
|
/**
|
|
5
|
-
* A layout-
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* A layout-transparent wrapper (a `ProxyElement`) that assigns an accessibility structure role
|
|
5
|
+
* (Table / TR / TH / TD / …) to its single child; only its renderer opens a structure element and nests
|
|
6
|
+
* the child's tags underneath.
|
|
8
7
|
*
|
|
9
|
-
* Split across pages, the
|
|
10
|
-
*
|
|
8
|
+
* Split across pages, the pieces share this group's `structId`, so it stays ONE logical structure
|
|
9
|
+
* element (a table broken over pages is a single <Table>, exactly as Acrobat produces).
|
|
11
10
|
*/
|
|
12
|
-
export declare class StructGroup extends
|
|
11
|
+
export declare class StructGroup extends ProxyElement {
|
|
13
12
|
private role;
|
|
14
|
-
private child;
|
|
15
13
|
constructor({ role, child }: {
|
|
16
14
|
role: string;
|
|
17
15
|
child: PDFElement;
|
|
18
16
|
});
|
|
19
|
-
|
|
20
|
-
minIntrinsicMain(horizontal: boolean, ctx: LayoutContext): number;
|
|
21
|
-
calculateLayout(constraints: BoxConstraints, offset: Offset, ctx: LayoutContext): Size;
|
|
22
|
-
/** Only splittable when the wrapped child is - so a StructGroup(Row) is moved whole to the next page,
|
|
23
|
-
* not clipped at the boundary (isFragmentable honours this veto). */
|
|
24
|
-
canFragment(): boolean;
|
|
25
|
-
fragment(maxHeight: number, width: number, ctx: LayoutContext): FragmentResult;
|
|
17
|
+
protected rewrap(child: PDFElement): PDFElement;
|
|
26
18
|
getProps(): {
|
|
27
19
|
role: string;
|
|
28
20
|
child: PDFElement;
|
|
@@ -1,44 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { isFragmentable } from "../../layout/fragmentation.js";
|
|
1
|
+
import { ProxyElement } from "./proxy-element.js";
|
|
3
2
|
/**
|
|
4
|
-
* A layout-
|
|
5
|
-
*
|
|
6
|
-
*
|
|
3
|
+
* A layout-transparent wrapper (a `ProxyElement`) that assigns an accessibility structure role
|
|
4
|
+
* (Table / TR / TH / TD / …) to its single child; only its renderer opens a structure element and nests
|
|
5
|
+
* the child's tags underneath.
|
|
7
6
|
*
|
|
8
|
-
* Split across pages, the
|
|
9
|
-
*
|
|
7
|
+
* Split across pages, the pieces share this group's `structId`, so it stays ONE logical structure
|
|
8
|
+
* element (a table broken over pages is a single <Table>, exactly as Acrobat produces).
|
|
10
9
|
*/
|
|
11
|
-
export class StructGroup extends
|
|
10
|
+
export class StructGroup extends ProxyElement {
|
|
12
11
|
constructor({ role, child }) {
|
|
13
|
-
super();
|
|
12
|
+
super(child);
|
|
14
13
|
this.role = role;
|
|
15
|
-
this.child = child;
|
|
16
14
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return this.child.minIntrinsicMain(horizontal, ctx);
|
|
20
|
-
}
|
|
21
|
-
calculateLayout(constraints, offset, ctx) {
|
|
22
|
-
return this.child.calculateLayout(constraints, offset, ctx);
|
|
23
|
-
}
|
|
24
|
-
/** Only splittable when the wrapped child is - so a StructGroup(Row) is moved whole to the next page,
|
|
25
|
-
* not clipped at the boundary (isFragmentable honours this veto). */
|
|
26
|
-
canFragment() {
|
|
27
|
-
return isFragmentable(this.child);
|
|
28
|
-
}
|
|
29
|
-
fragment(maxHeight, width, ctx) {
|
|
30
|
-
if (!isFragmentable(this.child))
|
|
31
|
-
return { fitted: null, remainder: this };
|
|
32
|
-
const { fitted, remainder } = this.child.fragment(maxHeight, width, ctx);
|
|
33
|
-
// Re-wrap each half with the SAME role + identity, so both pages point at one structure element.
|
|
34
|
-
return {
|
|
35
|
-
fitted: fitted
|
|
36
|
-
? new StructGroup({ role: this.role, child: fitted }).adoptStructId(this)
|
|
37
|
-
: null,
|
|
38
|
-
remainder: remainder
|
|
39
|
-
? new StructGroup({ role: this.role, child: remainder }).adoptStructId(this)
|
|
40
|
-
: null,
|
|
41
|
-
};
|
|
15
|
+
rewrap(child) {
|
|
16
|
+
return new StructGroup({ role: this.role, child });
|
|
42
17
|
}
|
|
43
18
|
getProps() {
|
|
44
19
|
return { role: this.role, child: this.child };
|
|
@@ -17,6 +17,7 @@ export declare class LineElement extends SizedPDFElement {
|
|
|
17
17
|
private sizeMemory;
|
|
18
18
|
constructor({ color, strokeWidth, x, y, xEnd, yEnd }: LineElementParams);
|
|
19
19
|
calculateLayout(constraints: BoxConstraints, offset: Offset, _ctx: LayoutContext): Size;
|
|
20
|
+
protected computeSize(constraints: BoxConstraints): Size;
|
|
20
21
|
getProps(): {
|
|
21
22
|
x: number;
|
|
22
23
|
y: number;
|
|
@@ -24,6 +24,12 @@ export class LineElement extends SizedPDFElement {
|
|
|
24
24
|
// Top-left coordinates; the Y-flip happens once at the IR -> backend seam.
|
|
25
25
|
return { width: this.width ?? 0, height: this.height ?? 0 };
|
|
26
26
|
}
|
|
27
|
+
computeSize(constraints) {
|
|
28
|
+
if (!constraints.hasBoundedWidth) {
|
|
29
|
+
throw new Error("The LineElement must be placed inside a parent container that defines its width");
|
|
30
|
+
}
|
|
31
|
+
return { width: this.width ?? 0, height: this.height ?? 0 };
|
|
32
|
+
}
|
|
27
33
|
getProps() {
|
|
28
34
|
return {
|
|
29
35
|
x: this.x,
|
|
@@ -59,19 +59,26 @@ export interface PageBands {
|
|
|
59
59
|
* resolve a `Positioned` against this same box, so `top`/`bottom` mean the same thing in each.
|
|
60
60
|
*
|
|
61
61
|
* `layoutPageBands` lays the bands out, so its caller must hand it a context carrying this frame -
|
|
62
|
-
* otherwise a `Positioned` in a band has nothing to resolve against (ISSUE-4).
|
|
63
|
-
*
|
|
64
|
-
* contributes no height.
|
|
62
|
+
* otherwise a `Positioned` in a band has nothing to resolve against (ISSUE-4). An out-of-flow child
|
|
63
|
+
* contributes no height, so a caller that only wants the band HEIGHTS needs nothing more.
|
|
65
64
|
*/
|
|
66
65
|
export declare function pageFrame(config: PDFPageConfig): PositioningFrame;
|
|
67
66
|
export declare function layoutPageBands(config: PDFPageConfig, header: PDFElement | undefined, footer: PDFElement | undefined, ctx: LayoutContext): PageBands;
|
|
68
67
|
export declare class PageElement extends PDFElement {
|
|
68
|
+
private readonly ownConfig;
|
|
69
69
|
private config;
|
|
70
70
|
private children;
|
|
71
71
|
private header?;
|
|
72
72
|
private footer?;
|
|
73
73
|
constructor({ children, config, header, footer }: PDFPageParams);
|
|
74
74
|
calculateLayout(_constraints: BoxConstraints, _offset: Offset, ctx: LayoutContext): Size;
|
|
75
|
+
/** Its size is its own page config. */
|
|
76
|
+
dependsOnPage(): boolean;
|
|
77
|
+
/** A page is as large as its content box, whatever it holds. */
|
|
78
|
+
protected computeSize(_constraints: BoxConstraints, ctx: LayoutContext): Size;
|
|
79
|
+
/** The document defaults with this page's own settings on top. Pure: no pass has to run first. */
|
|
80
|
+
resolveConfig(defaults: PDFPageConfig | undefined): PDFPageConfig;
|
|
81
|
+
layoutChildren(): readonly PDFElement[];
|
|
75
82
|
getProps(): PDFPageParams;
|
|
76
83
|
addTextElement(element: TextElement): this;
|
|
77
84
|
}
|
|
@@ -2,6 +2,7 @@ import { pageFormats, PageSize } from "../constants/page-sizes.js";
|
|
|
2
2
|
import { Orientation } from "../renderer/pdf-config.js";
|
|
3
3
|
import { BoxConstraints } from "../layout/box-constraints.js";
|
|
4
4
|
import { PDFElement } from "./pdf-element.js";
|
|
5
|
+
import { positionedIn } from "./layout/positioned-element.js";
|
|
5
6
|
/**
|
|
6
7
|
* The full page (media box) size in points, orientation applied. This is what a `PageBuilder` sees as
|
|
7
8
|
* `pageSize`; `resolvePageContentBox` below then subtracts the margins.
|
|
@@ -19,14 +20,14 @@ export function resolvePageSize(config) {
|
|
|
19
20
|
* driver so they can never drift.
|
|
20
21
|
*/
|
|
21
22
|
export function resolvePageContentBox(config) {
|
|
23
|
+
// The margins are the TURNED page's: `left` is the left edge of a landscape page, as `origin` says.
|
|
22
24
|
const margin = config.margin;
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
return { origin: { x: margin.left, y: margin.top }, width, height };
|
|
25
|
+
const page = resolvePageSize(config);
|
|
26
|
+
return {
|
|
27
|
+
origin: { x: margin.left, y: margin.top },
|
|
28
|
+
width: page.width - margin.left - margin.right,
|
|
29
|
+
height: page.height - margin.top - margin.bottom,
|
|
30
|
+
};
|
|
30
31
|
}
|
|
31
32
|
/**
|
|
32
33
|
* Lays out the header (top) and footer (bottom) of a page and returns the body band left
|
|
@@ -41,13 +42,12 @@ export function resolvePageContentBox(config) {
|
|
|
41
42
|
* resolve a `Positioned` against this same box, so `top`/`bottom` mean the same thing in each.
|
|
42
43
|
*
|
|
43
44
|
* `layoutPageBands` lays the bands out, so its caller must hand it a context carrying this frame -
|
|
44
|
-
* otherwise a `Positioned` in a band has nothing to resolve against (ISSUE-4).
|
|
45
|
-
*
|
|
46
|
-
* contributes no height.
|
|
45
|
+
* otherwise a `Positioned` in a band has nothing to resolve against (ISSUE-4). An out-of-flow child
|
|
46
|
+
* contributes no height, so a caller that only wants the band HEIGHTS needs nothing more.
|
|
47
47
|
*/
|
|
48
48
|
export function pageFrame(config) {
|
|
49
49
|
const { origin, width, height } = resolvePageContentBox(config);
|
|
50
|
-
return { origin, size: { width, height }
|
|
50
|
+
return { origin, size: { width, height } };
|
|
51
51
|
}
|
|
52
52
|
export function layoutPageBands(config, header, footer, ctx) {
|
|
53
53
|
const { origin, width, height } = resolvePageContentBox(config);
|
|
@@ -57,13 +57,8 @@ export function layoutPageBands(config, header, footer, ctx) {
|
|
|
57
57
|
}
|
|
58
58
|
let footerHeight = 0;
|
|
59
59
|
if (footer) {
|
|
60
|
-
// Measure first to learn its height, then place it flush against the bottom edge.
|
|
61
|
-
|
|
62
|
-
// laid out, and this subtree is laid out twice. Only the second, real pass may register.
|
|
63
|
-
const measureCtx = ctx.frame
|
|
64
|
-
? { ...ctx, frame: { ...ctx.frame, place: [] } }
|
|
65
|
-
: ctx;
|
|
66
|
-
footerHeight = footer.calculateLayout(BoxConstraints.loose(width, Infinity), origin, measureCtx).height;
|
|
60
|
+
// Measure first to learn its height, then place it flush against the bottom edge.
|
|
61
|
+
footerHeight = footer.measure(BoxConstraints.loose(width, Infinity), ctx).height;
|
|
67
62
|
footer.calculateLayout(BoxConstraints.loose(width, Infinity), { x: origin.x, y: origin.y + height - footerHeight }, ctx);
|
|
68
63
|
}
|
|
69
64
|
return {
|
|
@@ -78,20 +73,21 @@ export class PageElement extends PDFElement {
|
|
|
78
73
|
constructor({ children, config, header, footer }) {
|
|
79
74
|
super();
|
|
80
75
|
this.children = children;
|
|
81
|
-
this.
|
|
76
|
+
this.ownConfig = config ?? {};
|
|
77
|
+
this.config = this.ownConfig;
|
|
82
78
|
this.header = header;
|
|
83
79
|
this.footer = footer;
|
|
84
80
|
}
|
|
85
81
|
calculateLayout(_constraints, _offset, ctx) {
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
this.config = { ...ctx.pageConfig, ...this.config };
|
|
82
|
+
// Hand descendants a context bound to THIS page's geometry. This is what fixes the old
|
|
83
|
+
// last-page-wins global page-config bug.
|
|
84
|
+
this.config = this.resolveConfig(ctx.pageConfig);
|
|
90
85
|
const pageCtx = {
|
|
91
86
|
metrics: ctx.metrics,
|
|
92
87
|
pageConfig: this.config,
|
|
93
88
|
textStyle: ctx.textStyle,
|
|
94
89
|
onOverflow: ctx.onOverflow,
|
|
90
|
+
diagnostics: ctx.diagnostics,
|
|
95
91
|
pageInfo: ctx.pageInfo, // the render pass supplies it; absent during pagination
|
|
96
92
|
};
|
|
97
93
|
// The PAGE is a positioning frame, and the frame is the content box - not the body region left
|
|
@@ -110,16 +106,28 @@ export class PageElement extends PDFElement {
|
|
|
110
106
|
const bands = layoutPageBands(this.config, this.header, this.footer, frameCtx);
|
|
111
107
|
const childConstraints = BoxConstraints.loose(bands.bodyWidth, bands.bodyHeight);
|
|
112
108
|
this.children.forEach((child) => child.calculateLayout(childConstraints, bands.bodyOrigin, frameCtx));
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
// must still see a frame. It appends to `frame.place` while we walk it, and a `for..of` over an
|
|
118
|
-
// array visits what was appended, so nested placements drain in the same loop.
|
|
119
|
-
for (const place of frame.place)
|
|
120
|
-
place(frame, frameCtx);
|
|
109
|
+
// Last, once the bands and the body are laid out: the page's out-of-flow descendants, placed
|
|
110
|
+
// relative to its content box. Each is drawn at its own place in the tree (tree order).
|
|
111
|
+
for (const p of positionedIn([this.header, ...this.children, this.footer]))
|
|
112
|
+
p.placeIn(frame.size, frameCtx);
|
|
121
113
|
return { width: frame.size.width, height: frame.size.height };
|
|
122
114
|
}
|
|
115
|
+
/** Its size is its own page config. */
|
|
116
|
+
dependsOnPage() {
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
/** A page is as large as its content box, whatever it holds. */
|
|
120
|
+
computeSize(_constraints, ctx) {
|
|
121
|
+
const { width, height } = resolvePageContentBox(this.resolveConfig(ctx.pageConfig));
|
|
122
|
+
return { width, height };
|
|
123
|
+
}
|
|
124
|
+
/** The document defaults with this page's own settings on top. Pure: no pass has to run first. */
|
|
125
|
+
resolveConfig(defaults) {
|
|
126
|
+
return { ...defaults, ...this.ownConfig };
|
|
127
|
+
}
|
|
128
|
+
layoutChildren() {
|
|
129
|
+
return [this.header, ...this.children, this.footer].filter((el) => el !== undefined);
|
|
130
|
+
}
|
|
123
131
|
getProps() {
|
|
124
132
|
return {
|
|
125
133
|
children: this.children,
|
|
@@ -14,6 +14,9 @@ export declare class PDFDocumentElement extends PDFElement {
|
|
|
14
14
|
/** The document-level text defaults; the renderer merges them into the cascade root. */
|
|
15
15
|
getDefaultTextStyle(): Partial<ResolvedTextStyle> | undefined;
|
|
16
16
|
calculateLayout(_constraints: BoxConstraints, _offset: Offset, ctx: LayoutContext): Size;
|
|
17
|
+
/** The root has no size of its own. */
|
|
18
|
+
protected computeSize(): Size;
|
|
19
|
+
layoutChildren(): readonly PDFElement[];
|
|
17
20
|
getProps(): PDFDocumentParams;
|
|
18
21
|
}
|
|
19
22
|
export {};
|