@jasy/pdf 1.0.0-beta.3 → 1.0.0-beta.5

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.
Files changed (246) hide show
  1. package/dist/api/color.d.ts +1 -24
  2. package/dist/api/color.js +2 -278
  3. package/dist/api/content.d.ts +10 -5
  4. package/dist/api/content.js +29 -13
  5. package/dist/api/descriptor.js +30 -3
  6. package/dist/api/flow.d.ts +55 -0
  7. package/dist/api/flow.js +71 -0
  8. package/dist/api/font-url.d.ts +1 -2
  9. package/dist/api/font-url.js +8 -74
  10. package/dist/api/forms.d.ts +3 -0
  11. package/dist/api/forms.js +3 -0
  12. package/dist/api/gradient.d.ts +1 -53
  13. package/dist/api/gradient.js +2 -97
  14. package/dist/api/index.d.ts +4 -0
  15. package/dist/api/index.js +3 -0
  16. package/dist/api/layout.d.ts +6 -0
  17. package/dist/api/layout.js +9 -3
  18. package/dist/api/page-builder.d.ts +4 -0
  19. package/dist/api/page-builder.js +4 -0
  20. package/dist/api/structure.d.ts +10 -2
  21. package/dist/api/structure.js +9 -6
  22. package/dist/api/table.d.ts +5 -3
  23. package/dist/api/table.js +101 -22
  24. package/dist/api/text.d.ts +8 -8
  25. package/dist/api/text.js +6 -0
  26. package/dist/canvas/painter.d.ts +2 -2
  27. package/dist/canvas/painter.js +2 -2
  28. package/dist/common/color-input.d.ts +24 -0
  29. package/dist/common/color-input.js +278 -0
  30. package/dist/common/diagnostics.d.ts +61 -0
  31. package/dist/common/diagnostics.js +77 -0
  32. package/dist/common/gradient.d.ts +53 -0
  33. package/dist/common/gradient.js +97 -0
  34. package/dist/edit/acroform-reader.js +7 -7
  35. package/dist/edit/appearance.js +3 -3
  36. package/dist/edit/attachments.d.ts +52 -0
  37. package/dist/edit/attachments.js +178 -0
  38. package/dist/edit/document.d.ts +38 -8
  39. package/dist/edit/document.js +208 -51
  40. package/dist/edit/fill.js +8 -23
  41. package/dist/edit/filters.d.ts +15 -0
  42. package/dist/edit/filters.js +157 -0
  43. package/dist/edit/index.d.ts +4 -1
  44. package/dist/edit/index.js +3 -1
  45. package/dist/edit/objects.d.ts +3 -4
  46. package/dist/edit/objects.js +5 -18
  47. package/dist/elements/canvas-element.d.ts +3 -0
  48. package/dist/elements/canvas-element.js +14 -3
  49. package/dist/elements/container-element.d.ts +8 -1
  50. package/dist/elements/container-element.js +49 -17
  51. package/dist/elements/forms/checkbox-element.d.ts +2 -0
  52. package/dist/elements/forms/checkbox-element.js +12 -3
  53. package/dist/elements/forms/choice-element.d.ts +6 -1
  54. package/dist/elements/forms/choice-element.js +17 -6
  55. package/dist/elements/forms/field-font.d.ts +8 -0
  56. package/dist/elements/forms/field-font.js +5 -0
  57. package/dist/elements/forms/push-button-element.d.ts +6 -1
  58. package/dist/elements/forms/push-button-element.js +16 -4
  59. package/dist/elements/forms/radio-element.d.ts +2 -0
  60. package/dist/elements/forms/radio-element.js +12 -3
  61. package/dist/elements/forms/signature-element.d.ts +6 -1
  62. package/dist/elements/forms/signature-element.js +16 -4
  63. package/dist/elements/forms/text-field-element.d.ts +6 -1
  64. package/dist/elements/forms/text-field-element.js +16 -4
  65. package/dist/elements/image-element.d.ts +70 -21
  66. package/dist/elements/image-element.js +173 -52
  67. package/dist/elements/index.d.ts +3 -0
  68. package/dist/elements/index.js +3 -0
  69. package/dist/elements/layout/anchor-element.d.ts +8 -10
  70. package/dist/elements/layout/anchor-element.js +10 -18
  71. package/dist/elements/layout/bookmark-element.d.ts +9 -11
  72. package/dist/elements/layout/bookmark-element.js +11 -20
  73. package/dist/elements/layout/column-break-element.d.ts +17 -0
  74. package/dist/elements/layout/column-break-element.js +26 -0
  75. package/dist/elements/layout/default-text-style-element.d.ts +11 -13
  76. package/dist/elements/layout/default-text-style-element.js +14 -31
  77. package/dist/elements/layout/deferred-element.d.ts +20 -4
  78. package/dist/elements/layout/deferred-element.js +41 -9
  79. package/dist/elements/layout/expanded-element.d.ts +11 -0
  80. package/dist/elements/layout/expanded-element.js +53 -18
  81. package/dist/elements/layout/flow-element.d.ts +109 -0
  82. package/dist/elements/layout/flow-element.js +317 -0
  83. package/dist/elements/layout/keep-together-element.d.ts +8 -18
  84. package/dist/elements/layout/keep-together-element.js +33 -45
  85. package/dist/elements/layout/link-element.d.ts +8 -13
  86. package/dist/elements/layout/link-element.js +9 -19
  87. package/dist/elements/layout/padding-element.d.ts +18 -1
  88. package/dist/elements/layout/padding-element.js +63 -28
  89. package/dist/elements/layout/page-break-element.d.ts +4 -1
  90. package/dist/elements/layout/page-break-element.js +6 -1
  91. package/dist/elements/layout/page-builder-element.d.ts +5 -0
  92. package/dist/elements/layout/page-builder-element.js +13 -2
  93. package/dist/elements/layout/positioned-element.d.ts +23 -4
  94. package/dist/elements/layout/positioned-element.js +42 -12
  95. package/dist/elements/layout/proxy-element.d.ts +47 -0
  96. package/dist/elements/layout/proxy-element.js +106 -0
  97. package/dist/elements/layout/region-element.d.ts +53 -0
  98. package/dist/elements/layout/region-element.js +108 -0
  99. package/dist/elements/layout/repeating-header-element.d.ts +9 -0
  100. package/dist/elements/layout/repeating-header-element.js +55 -13
  101. package/dist/elements/layout/rotated-box-element.d.ts +6 -0
  102. package/dist/elements/layout/rotated-box-element.js +27 -14
  103. package/dist/elements/layout/rotated-element.d.ts +9 -0
  104. package/dist/elements/layout/rotated-element.js +33 -2
  105. package/dist/elements/layout/struct-group.d.ts +9 -17
  106. package/dist/elements/layout/struct-group.js +10 -35
  107. package/dist/elements/line-element.d.ts +1 -0
  108. package/dist/elements/line-element.js +6 -0
  109. package/dist/elements/page-element.d.ts +10 -3
  110. package/dist/elements/page-element.js +39 -31
  111. package/dist/elements/pdf-document-element.d.ts +3 -0
  112. package/dist/elements/pdf-document-element.js +7 -0
  113. package/dist/elements/pdf-element.d.ts +105 -16
  114. package/dist/elements/pdf-element.js +118 -19
  115. package/dist/elements/rectangle-element.d.ts +22 -2
  116. package/dist/elements/rectangle-element.js +119 -55
  117. package/dist/elements/row-element.d.ts +17 -12
  118. package/dist/elements/row-element.js +89 -9
  119. package/dist/elements/svg-element.d.ts +30 -6
  120. package/dist/elements/svg-element.js +91 -26
  121. package/dist/elements/text-element.d.ts +48 -13
  122. package/dist/elements/text-element.js +161 -116
  123. package/dist/forms/acroform.d.ts +9 -1
  124. package/dist/forms/acroform.js +83 -34
  125. package/dist/forms/appearance.d.ts +17 -6
  126. package/dist/forms/appearance.js +18 -16
  127. package/dist/ir/display-list.d.ts +18 -3
  128. package/dist/layout/box-constraints.d.ts +17 -0
  129. package/dist/layout/box-constraints.js +31 -0
  130. package/dist/layout/collect-images.d.ts +6 -4
  131. package/dist/layout/collect-images.js +14 -8
  132. package/dist/layout/flex-item.d.ts +11 -0
  133. package/dist/layout/flex-item.js +51 -0
  134. package/dist/layout/fragmentation.d.ts +23 -9
  135. package/dist/layout/fragmentation.js +62 -19
  136. package/dist/layout/layout-cache.d.ts +53 -0
  137. package/dist/layout/layout-cache.js +110 -0
  138. package/dist/platform/browser-fs.d.ts +1 -2
  139. package/dist/platform/browser-fs.js +3 -6
  140. package/dist/platform/node-fs.d.ts +0 -1
  141. package/dist/platform/node-fs.js +0 -4
  142. package/dist/renderer/anchor-renderer.d.ts +2 -1
  143. package/dist/renderer/anchor-renderer.js +5 -4
  144. package/dist/renderer/bookmark-renderer.d.ts +2 -1
  145. package/dist/renderer/bookmark-renderer.js +5 -4
  146. package/dist/renderer/canvas-renderer.d.ts +2 -1
  147. package/dist/renderer/canvas-renderer.js +5 -2
  148. package/dist/renderer/column-break-renderer.d.ts +8 -0
  149. package/dist/renderer/column-break-renderer.js +15 -0
  150. package/dist/renderer/container-renderer.d.ts +2 -1
  151. package/dist/renderer/container-renderer.js +6 -5
  152. package/dist/renderer/default-text-style-renderer.d.ts +2 -1
  153. package/dist/renderer/default-text-style-renderer.js +2 -3
  154. package/dist/renderer/deferred-renderer.d.ts +2 -1
  155. package/dist/renderer/deferred-renderer.js +2 -3
  156. package/dist/renderer/emoji-image.js +3 -1
  157. package/dist/renderer/expanded-renderer.d.ts +2 -1
  158. package/dist/renderer/expanded-renderer.js +2 -3
  159. package/dist/renderer/flow-renderer.d.ts +16 -0
  160. package/dist/renderer/flow-renderer.js +21 -0
  161. package/dist/renderer/form-field-renderer.d.ts +2 -1
  162. package/dist/renderer/form-field-renderer.js +16 -3
  163. package/dist/renderer/image-renderer.d.ts +2 -1
  164. package/dist/renderer/image-renderer.js +33 -53
  165. package/dist/renderer/index.d.ts +2 -0
  166. package/dist/renderer/index.js +2 -0
  167. package/dist/renderer/keep-together-renderer.d.ts +2 -1
  168. package/dist/renderer/keep-together-renderer.js +2 -3
  169. package/dist/renderer/line-renderer.d.ts +2 -1
  170. package/dist/renderer/line-renderer.js +7 -2
  171. package/dist/renderer/link-renderer.d.ts +2 -1
  172. package/dist/renderer/link-renderer.js +36 -5
  173. package/dist/renderer/padding-renderer.d.ts +2 -1
  174. package/dist/renderer/padding-renderer.js +5 -5
  175. package/dist/renderer/page-break-renderer.d.ts +6 -5
  176. package/dist/renderer/page-break-renderer.js +14 -7
  177. package/dist/renderer/page-builder-renderer.d.ts +2 -1
  178. package/dist/renderer/page-builder-renderer.js +2 -3
  179. package/dist/renderer/page-renderer.js +30 -10
  180. package/dist/renderer/pdf-backend.d.ts +4 -3
  181. package/dist/renderer/pdf-backend.js +14 -7
  182. package/dist/renderer/pdf-document-renderer.d.ts +1 -8
  183. package/dist/renderer/pdf-document-renderer.js +17 -17
  184. package/dist/renderer/pdf-renderer.js +20 -11
  185. package/dist/renderer/positioned-renderer.d.ts +18 -1
  186. package/dist/renderer/positioned-renderer.js +43 -6
  187. package/dist/renderer/rectangle-renderer.d.ts +2 -1
  188. package/dist/renderer/rectangle-renderer.js +18 -8
  189. package/dist/renderer/repeating-header-renderer.d.ts +2 -1
  190. package/dist/renderer/repeating-header-renderer.js +6 -5
  191. package/dist/renderer/rotated-renderer.d.ts +2 -1
  192. package/dist/renderer/rotated-renderer.js +9 -5
  193. package/dist/renderer/row-renderer.d.ts +2 -1
  194. package/dist/renderer/row-renderer.js +6 -5
  195. package/dist/renderer/struct-group-renderer.d.ts +2 -1
  196. package/dist/renderer/struct-group-renderer.js +2 -3
  197. package/dist/renderer/svg-renderer.d.ts +2 -1
  198. package/dist/renderer/svg-renderer.js +8 -2
  199. package/dist/renderer/text-renderer.d.ts +4 -6
  200. package/dist/renderer/text-renderer.js +114 -127
  201. package/dist/svg/gradients.js +5 -0
  202. package/dist/svg/index.d.ts +1 -1
  203. package/dist/svg/index.js +36 -6
  204. package/dist/svg/style.d.ts +2 -0
  205. package/dist/svg/style.js +12 -1
  206. package/dist/text/advance.d.ts +4 -0
  207. package/dist/text/advance.js +17 -4
  208. package/dist/text/bidi.d.ts +0 -2
  209. package/dist/text/bidi.js +0 -10
  210. package/dist/text/glyph-coverage.d.ts +1 -1
  211. package/dist/text/glyph-coverage.js +7 -3
  212. package/dist/text/hyphen-breaks.d.ts +17 -0
  213. package/dist/text/hyphen-breaks.js +54 -0
  214. package/dist/text/line-breaker.d.ts +55 -29
  215. package/dist/text/line-breaker.js +453 -188
  216. package/dist/text/line-metrics.d.ts +8 -3
  217. package/dist/text/line-metrics.js +11 -2
  218. package/dist/text/pdf-text-string.d.ts +21 -0
  219. package/dist/text/pdf-text-string.js +114 -0
  220. package/dist/text/text-decoration.d.ts +5 -5
  221. package/dist/text/text-decoration.js +5 -5
  222. package/dist/text/word-splitting.d.ts +15 -2
  223. package/dist/text/word-splitting.js +45 -13
  224. package/dist/utils/afm-parser.d.ts +2 -0
  225. package/dist/utils/afm-parser.js +10 -1
  226. package/dist/utils/dest-registry.d.ts +1 -1
  227. package/dist/utils/dest-registry.js +3 -2
  228. package/dist/utils/fetch-bytes.d.ts +19 -0
  229. package/dist/utils/fetch-bytes.js +79 -0
  230. package/dist/utils/flex-layout.d.ts +16 -14
  231. package/dist/utils/flex-layout.js +427 -217
  232. package/dist/utils/font-metrics.d.ts +4 -3
  233. package/dist/utils/image-helper.d.ts +59 -11
  234. package/dist/utils/image-helper.js +209 -81
  235. package/dist/utils/pdf-object-manager.d.ts +17 -6
  236. package/dist/utils/pdf-object-manager.js +70 -20
  237. package/dist/utils/renderer-registry.d.ts +49 -2
  238. package/dist/utils/renderer-registry.js +40 -0
  239. package/dist/utils/struct-tree.d.ts +24 -0
  240. package/dist/utils/struct-tree.js +61 -9
  241. package/dist/utils/ttf-parser.d.ts +4 -0
  242. package/dist/utils/ttf-parser.js +30 -6
  243. package/dist/validators/element-validator.js +2 -1
  244. package/package.json +1 -1
  245. package/dist/elements/layout/sized-container-element.d.ts +0 -14
  246. package/dist/elements/layout/sized-container-element.js +0 -32
@@ -1,7 +1,9 @@
1
1
  import { readFileBytes } from "../platform/node-fs.js";
2
2
  import { SvgParseError, svgSize, svgToIr } from "../svg/index.js";
3
- import { extentSpecs, resolveSize, } from "../layout/box-constraints.js";
3
+ import { extentSpecs, resolveSize, sizeAtOwnRatio, } from "../layout/box-constraints.js";
4
4
  import { SizedPDFElement } from "./pdf-element.js";
5
+ import { IMAGE_FETCH_LIMITS, ImageUrlError, isImageUrl } from "./image-element.js";
6
+ import { fetchBytes } from "../utils/fetch-bytes.js";
5
7
  /** Markup is recognised by its first non-space character - anything else is treated as a path. */
6
8
  const looksLikeMarkup = (value) => /^\s*[<]/.test(value);
7
9
  /**
@@ -24,30 +26,78 @@ function readSource(path) {
24
26
  *
25
27
  * Unlike a bitmap it needs no decoder, so its intrinsic size is known SYNCHRONOUSLY, in the
26
28
  * constructor - which also means a broken file fails on the line that asked for it rather than deep
27
- * inside a later render, the same bargain `addFont` makes.
29
+ * inside a later render, the same bargain `addFont` makes. An SVG from a URL is the exception: like
30
+ * an image from a URL it is fetched when the document renders (`resolveIntrinsicSize`, or the
31
+ * renderer for a subtree built during layout), and a dead link stops the render naming it.
28
32
  */
29
33
  export class SvgElement extends SizedPDFElement {
30
34
  constructor(params) {
31
35
  super({ x: 0, y: 0, width: params.width, height: params.height });
36
+ this.failed = false;
32
37
  const { source, alt, widthFactor, heightFactor, ...sizing } = params;
33
38
  this.widthFactor = widthFactor;
34
39
  this.heightFactor = heightFactor;
35
- this.source =
36
- typeof source === "string"
40
+ if (typeof source === "string" && isImageUrl(source))
41
+ this.url = source;
42
+ else
43
+ this.parse(typeof source === "string"
37
44
  ? looksLikeMarkup(source)
38
45
  ? source
39
46
  : new TextDecoder().decode(readSource(source))
40
- : new TextDecoder().decode(source);
41
- // Parsed here on purpose: an unreadable file is an error where it was NAMED, not inside a render
42
- // three call frames later. The whole document is walked, not just its root, so an element outside
43
- // the subset surfaces here too - which is what makes the error predictable rather than a lottery
44
- // between construction and render time. A logo parses in well under a millisecond.
45
- this.intrinsic = svgSize(this.source);
46
- svgToIr(this.source, { x: 0, y: 0, width: 1, height: 1 });
47
+ : new TextDecoder().decode(source));
47
48
  this.alt = alt;
48
49
  this.sizing = sizing;
49
50
  this.requested = { width: params.width, height: params.height };
50
51
  }
52
+ /**
53
+ * Parsed on purpose where the source is given: an unreadable file is an error where it was NAMED,
54
+ * not inside a render three call frames later. The whole document is walked, not just its root, so
55
+ * an element outside the subset surfaces here too. A logo parses in well under a millisecond.
56
+ */
57
+ parse(source) {
58
+ this.intrinsic = svgSize(source);
59
+ svgToIr(source, { x: 0, y: 0, width: 1, height: 1 });
60
+ this.source = source;
61
+ }
62
+ /**
63
+ * Fetches and parses an SVG from a URL - once per render, however often it is asked. A no-op
64
+ * otherwise. A failure sticks for that render only: `fresh` (a new render begins) asks again.
65
+ */
66
+ async load(fresh = false) {
67
+ const url = this.url;
68
+ if (url === undefined)
69
+ return;
70
+ if (fresh && this.failed)
71
+ this.loading = undefined;
72
+ this.loading ?? (this.loading = fetchBytes(url, "SVG", ImageUrlError, IMAGE_FETCH_LIMITS)
73
+ .then((bytes) => {
74
+ try {
75
+ this.parse(new TextDecoder().decode(bytes));
76
+ }
77
+ catch (e) {
78
+ throw new ImageUrlError(`the SVG at ${url} could not be read: ${String(e?.message ?? e)}`);
79
+ }
80
+ })
81
+ .then(() => {
82
+ this.failed = false;
83
+ }, (e) => {
84
+ this.failed = true;
85
+ throw e;
86
+ }));
87
+ await this.loading;
88
+ }
89
+ /**
90
+ * The pre-layout pass, as for an `ImageElement`: best-effort, so a failure leaves the size unknown
91
+ * and the renderer, which loads again, surfaces the real error.
92
+ */
93
+ async resolveIntrinsicSize() {
94
+ try {
95
+ await this.load(true); // a render begins here
96
+ }
97
+ catch {
98
+ // the renderer reports it
99
+ }
100
+ }
51
101
  getProps() {
52
102
  return {
53
103
  x: this.x,
@@ -60,8 +110,18 @@ export class SvgElement extends SizedPDFElement {
60
110
  };
61
111
  }
62
112
  calculateLayout(constraints, offset, _ctx) {
113
+ const size = this.sizeFor(constraints);
63
114
  this.x = offset.x;
64
115
  this.y = offset.y;
116
+ this.width = size.width;
117
+ this.height = size.height;
118
+ return size;
119
+ }
120
+ computeSize(constraints) {
121
+ return this.sizeFor(constraints);
122
+ }
123
+ /** Its size under these constraints - the one computation both `measure` and layout use. */
124
+ sizeFor(constraints) {
65
125
  const specs = extentSpecs({
66
126
  ...this.sizing,
67
127
  width: this.requested.width,
@@ -73,21 +133,26 @@ export class SvgElement extends SizedPDFElement {
73
133
  let w = resolved.width;
74
134
  let h = resolved.height;
75
135
  const bounds = resolved.constraints;
76
- // One pinned axis derives the other from the drawing's own ratio (CSS `width: 120; height: auto`).
77
- // A bitmap needs a decode pass before it can do this; an SVG knows it from its viewBox.
78
- if (this.sizing.aspectRatio === undefined &&
79
- this.intrinsic.width > 0 &&
80
- this.intrinsic.height > 0) {
81
- const ratio = this.intrinsic.width / this.intrinsic.height;
82
- if (w !== undefined && h === undefined)
83
- h = bounds.constrainHeight(w / ratio);
84
- else if (h !== undefined && w === undefined)
85
- w = bounds.constrainWidth(h * ratio);
136
+ // An SVG from a URL that was never fetched sits in content built DURING layout (a PageBuilder, an auto
137
+ // table column), which the pass before layout cannot reach. Its ratio is unknown here, so it needs
138
+ // its whole box - a named error instead of a drawing sized to nothing. A FAILED fetch is not this
139
+ // case: the renderer reports that one by its URL.
140
+ if (this.url !== undefined &&
141
+ this.loading === undefined &&
142
+ (w === undefined || h === undefined)) {
143
+ throw new ImageUrlError(`the SVG at ${this.url} sits in content built during layout (a PageBuilder or an auto table ` +
144
+ `column), where its size cannot be read before it is placed - give it both a width and a ` +
145
+ `height, or an aspectRatio`);
146
+ }
147
+ // Its own ratio fills an open axis, as for a bitmap - which needs a decode pass for it; an SVG
148
+ // knows it from its viewBox. Unsized, it is its own size scaled down to fit: a 24pt icon stays 24pt.
149
+ const intrinsic = this.intrinsic ?? { width: 0, height: 0 };
150
+ if (this.sizing.aspectRatio === undefined && intrinsic.width > 0 && intrinsic.height > 0) {
151
+ ({ width: w, height: h } = sizeAtOwnRatio(w, h, intrinsic, bounds));
86
152
  }
87
- // Nothing pinned: draw at the intrinsic size, as an unsized `<img>` does - never fill the region,
88
- // which would blow a 24pt icon up to the whole page.
89
- this.width = w ?? bounds.constrainWidth(this.intrinsic.width);
90
- this.height = h ?? bounds.constrainHeight(this.intrinsic.height);
91
- return { width: this.width, height: this.height };
153
+ return {
154
+ width: w ?? bounds.constrainWidth(intrinsic.width),
155
+ height: h ?? bounds.constrainHeight(intrinsic.height),
156
+ };
92
157
  }
93
158
  }
@@ -4,7 +4,7 @@ import { BoxConstraints, Offset, Size } from "../layout/box-constraints.js";
4
4
  import type { Direction } from "../text/bidi.js";
5
5
  import { type TextTransform } from "../text/text-style.js";
6
6
  import { Fragmentable, FragmentResult } from "../layout/fragmentation.js";
7
- import { TextOverflow } from "../text/line-breaker.js";
7
+ import { type SegmentDefaults, TextOverflow } from "../text/line-breaker.js";
8
8
  import { HorizontalAlignment, LayoutContext, SizedPDFElement } from "./pdf-element.js";
9
9
  import type { Hyphenator } from "../text/word-splitting.js";
10
10
  export interface TextSegment {
@@ -22,8 +22,16 @@ export interface TextSegment {
22
22
  /** Unset inherits the Text's own setting; `true`/`false` overrides it for this run only. */
23
23
  underline?: boolean;
24
24
  strikethrough?: boolean;
25
+ skipInk?: boolean;
25
26
  /** Extra space after every glyph, in points; unset inherits the Text's own value. */
26
27
  letterSpacing?: number;
28
+ textTransform?: TextTransform;
29
+ wordSpacing?: number;
30
+ ligatures?: boolean;
31
+ /** How a word wider than the box splits, for the characters of THIS run (Chrome: a break after a
32
+ * character is allowed by that character's own `overflow-wrap`). */
33
+ breakWord?: boolean;
34
+ hyphenate?: Hyphenator;
27
35
  /**
28
36
  * CSS `vertical-align`, for a footnote marker or a formula index. Shifts THIS run's baseline;
29
37
  * it does not resize the text, and it does not change the line's height - set `fontSize` yourself
@@ -83,6 +91,9 @@ interface TextElementParams {
83
91
  hyphenate?: Hyphenator;
84
92
  /** Accessibility role for the tagged structure tree (heading level or paragraph; default `"p"`). */
85
93
  role?: TextRole;
94
+ /** Set by pagination, not by authors: this element is the first N lines of a paragraph that
95
+ * continues on the next page. See `LineOptions.shownLines`. */
96
+ shownLines?: number;
86
97
  }
87
98
  export declare class TextElement extends SizedPDFElement implements Fragmentable {
88
99
  private readonly rawFontSize?;
@@ -116,6 +127,7 @@ export declare class TextElement extends SizedPDFElement implements Fragmentable
116
127
  private direction;
117
128
  private fontFallback;
118
129
  private resolved?;
130
+ private broken;
119
131
  private textTransform;
120
132
  private wordSpacing;
121
133
  private textIndent;
@@ -123,12 +135,17 @@ export declare class TextElement extends SizedPDFElement implements Fragmentable
123
135
  private ligatures;
124
136
  private hyphenate?;
125
137
  private content;
138
+ /** What `covered` had to remove, reported where the text is laid out on its page (see
139
+ * `calculateLayout`). A split paragraph's first piece carries its parent's, as `lostBefore`. */
140
+ private lostGlyphs;
141
+ private lostBefore;
126
142
  private maxLines?;
127
143
  private orphans?;
128
144
  private widows?;
129
145
  private overflow;
130
146
  private readonly role?;
131
- constructor({ fontSize, content, fontFamily, fontStyle, color, textAlignment, maxLines, orphans, widows, overflow, lineHeight, underline, strikethrough, skipInk, letterSpacing, direction, fontFallback, textTransform, wordSpacing, textIndent, breakWord, hyphenate, ligatures, role, }: TextElementParams);
147
+ private readonly shownLines?;
148
+ constructor({ fontSize, content, fontFamily, fontStyle, color, textAlignment, maxLines, orphans, widows, overflow, lineHeight, underline, strikethrough, skipInk, letterSpacing, direction, fontFallback, textTransform, wordSpacing, textIndent, breakWord, hyphenate, ligatures, role, shownLines, }: TextElementParams);
132
149
  private resolveStyle;
133
150
  /**
134
151
  * The last `display(metrics)` result, with what it depended on - recasing, coverage and the fallback
@@ -153,7 +170,7 @@ export declare class TextElement extends SizedPDFElement implements Fragmentable
153
170
  * back unchanged, so an ordinary document is byte-identical.
154
171
  */
155
172
  private covered;
156
- /** The content with `text-transform` applied, and nothing else. */
173
+ /** The content as spans, with `text-transform` applied, and nothing else. */
157
174
  private recased;
158
175
  private lineOptions;
159
176
  private applyStyle;
@@ -161,23 +178,36 @@ export declare class TextElement extends SizedPDFElement implements Fragmentable
161
178
  * Splits the paragraph at line boxes (Slice 1). The lines that fit in `maxHeight` stay;
162
179
  * the rest become a remainder `TextElement` re-wrapped on the next page. If not even one
163
180
  * line fits, nothing is forced here - the caller (the container) decides whether to move
164
- * the whole element on for progress. Handles both plain strings and styled segments.
181
+ * the whole element on for progress.
165
182
  */
166
183
  fragment(maxHeight: number, width: number, ctx: LayoutContext): FragmentResult;
167
- private fragmentString;
168
- private fragmentSegments;
184
+ /** How the text is broken: the knobs `textHeight` and the renderer pass too. */
185
+ private segmentDefaults;
169
186
  /** The orphan/widow minimums for this paragraph; unset means the CSS default of 2 lines each. */
170
187
  private breakRule;
171
188
  private cloneWithContent;
172
189
  calculateLayout(constraints: BoxConstraints, offset: Offset, ctx: LayoutContext): Size;
190
+ /**
191
+ * The size `calculateLayout` would take, without placing anything. Resolving the inherited style
192
+ * and filling the memos below are its only writes, and both are a pure function of the context:
193
+ * the same inputs leave the same state, which a later layout reads back unchanged.
194
+ */
195
+ /** A text's size reads only the width it may take: it wraps to it, and a height bound never changes
196
+ * the lines (a box that is too short cuts them, it does not reflow them). */
197
+ protected sizeInputs(constraints: BoxConstraints): BoxConstraints;
198
+ protected computeSize(constraints: BoxConstraints, ctx: LayoutContext): Size;
199
+ /**
200
+ * The one sizing path, for measuring and layout alike: a bounded width wraps to it (in a Column), an
201
+ * unbounded one takes the natural single-line width (in a Row). The lines are what layout checks.
202
+ * The style is resolved here, as drawing reads it.
203
+ */
204
+ /** The text broken at `width`: once per context and width, for measuring, layout and splitting. */
205
+ private linesAt;
206
+ private sizeWith;
173
207
  /** The unwrapped single-line width of the content (used when width is unbounded, e.g. inside a Row).
174
- * Must match the LINE-BREAKER's one-line measure EXACTLY - not just algebraically but BIT-for-bit,
175
- * so a text laid out at this width never re-wraps inside its own natural-width box. The breaker
176
- * accumulates `currentWidth += wordWidth + spaceWidth`, grouping the word and its trailing space
177
- * into one term; we must group the same way. Adding word and space as two separate steps is
178
- * algebraically equal but, because floating-point addition is not associative, drifts by a sub-ULP
179
- * - enough to tip a borderline string (e.g. "20 Jun 2026", wider than "04 Jul 2026" only because
180
- * 'n' beats 'l') one bit over its own width, dropping the last word onto a second line. */
208
+ * Must match the breaker's one-line sum BIT for bit - it adds `width + (space + word)`, and the same
209
+ * numbers grouped differently drift by a sub-ULP, enough to wrap a text inside its own natural-width
210
+ * box. `singleLineWidth` is that sum. */
181
211
  private naturalWidth;
182
212
  /**
183
213
  * The widest piece of this text that cannot be broken - CSS's `min-content` width. A shrinking flex
@@ -198,6 +228,10 @@ export declare class TextElement extends SizedPDFElement implements Fragmentable
198
228
  fontStyle: FontStyle;
199
229
  color: Color;
200
230
  content: string | TextSegment[];
231
+ /** The content as it is measured and drawn: spans, recased, split by font, drawable glyphs only. */
232
+ spans: TextSegment[];
233
+ /** How the text is broken - the settings it is measured with, so drawing breaks it the same. */
234
+ breaking: SegmentDefaults;
201
235
  textAlignment: HorizontalAlignment;
202
236
  maxLines: number | undefined;
203
237
  orphans: number | undefined;
@@ -215,6 +249,7 @@ export declare class TextElement extends SizedPDFElement implements Fragmentable
215
249
  ligatures: boolean;
216
250
  hyphenate: Hyphenator | undefined;
217
251
  role: TextRole | undefined;
252
+ shownLines: number | undefined;
218
253
  };
219
254
  }
220
255
  export {};