@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
@@ -39,19 +39,23 @@ const EQUIVALENTS = {
39
39
  * Replaces or removes what `fontFamily` cannot draw. Returns the input unchanged (and no allocation
40
40
  * beyond the scan) when everything is drawable, which is the overwhelmingly common case.
41
41
  */
42
- export function coverText(text, fontFamily, fontStyle, metrics) {
42
+ export function coverText(text, fontFamily, fontStyle, metrics,
43
+ // Whether colour emoji count as drawable: in `Text` they are drawn from the emoji source; a form
44
+ // field's appearance has only its own font.
45
+ emoji = true) {
43
46
  let out = null; // built only once something has to change
44
47
  const dropped = [];
45
48
  let index = 0;
46
49
  for (const char of text) {
47
50
  const cp = char.codePointAt(0);
48
- // A space and a line break are handled by the breaker, never drawn as a glyph.
51
+ // A space, a line break and a soft hyphen are handled by the breaker, never drawn as a glyph.
49
52
  const drawable = cp === 0x20 ||
50
53
  cp === 0x0a ||
54
+ cp === 0xad ||
51
55
  metrics.hasGlyph(cp, fontFamily, fontStyle) ||
52
56
  // Colour emoji is drawn from a fallback font or an image, NOT from the text font - it is missing
53
57
  // there by design, and removing it would delete the very thing `Document({ emoji })` exists for.
54
- metrics.rendersAsEmoji?.(cp, fontFamily, fontStyle) === true;
58
+ (emoji && metrics.rendersAsEmoji?.(cp, fontFamily, fontStyle) === true);
55
59
  if (!drawable) {
56
60
  if (out === null)
57
61
  out = text.slice(0, index);
@@ -0,0 +1,17 @@
1
+ export declare const NO_BREAKS: readonly number[];
2
+ /** Whether a word holds anything it may break after: a hyphen or a soft hyphen. */
3
+ export declare const mayBreak: (word: string) => boolean;
4
+ /**
5
+ * Where a word may break, as offsets into it - after a hyphen (U+002D) as UAX #14 has it: never before
6
+ * it, never before a digit ("CODE-2", "2026-10-16", "-5" stay whole), never after one that starts the
7
+ * word; and after a soft hyphen (U+00AD), the break its author marked.
8
+ */
9
+ export declare function hyphenBreaks(word: string): number[];
10
+ /**
11
+ * What the line ending at break `k` draws of `word`: everything before it, and at a soft hyphen a REAL
12
+ * hyphen in its place - the only time a soft hyphen shows. The breaker draws this; measuring it measures
13
+ * what is drawn.
14
+ */
15
+ export declare function headAt(word: string, k: number): string;
16
+ /** A word cut at its break opportunities: the pieces no line can split, as they are drawn. */
17
+ export declare function hyphenPieces(word: string): string[];
@@ -0,0 +1,54 @@
1
+ import { SOFT_HYPHEN } from "./advance.js";
2
+ import { HYPHEN } from "./word-splitting.js";
3
+ // Where a word MAY break inside itself - pure text rules, no font and no line. Filling lines is
4
+ // `line-breaker.ts`; this only answers which offsets are allowed.
5
+ export const NO_BREAKS = [];
6
+ /** Whether a word holds anything it may break after: a hyphen or a soft hyphen. */
7
+ export const mayBreak = (word) => word.includes("-") || word.includes(SOFT_HYPHEN);
8
+ /**
9
+ * Where a word may break, as offsets into it - after a hyphen (U+002D) as UAX #14 has it: never before
10
+ * it, never before a digit ("CODE-2", "2026-10-16", "-5" stay whole), never after one that starts the
11
+ * word; and after a soft hyphen (U+00AD), the break its author marked.
12
+ */
13
+ export function hyphenBreaks(word) {
14
+ const out = [];
15
+ for (let i = 1; i < word.length - 1; i++) {
16
+ const next = word[i + 1];
17
+ if (NO_BREAK_BEFORE.has(next))
18
+ continue;
19
+ if (word[i] === SOFT_HYPHEN) {
20
+ out.push(i + 1);
21
+ continue;
22
+ }
23
+ if (word[i] !== "-")
24
+ continue;
25
+ if (next === "-" || (next >= "0" && next <= "9"))
26
+ continue;
27
+ out.push(i + 1);
28
+ }
29
+ return out;
30
+ }
31
+ // UAX #14 never breaks before closing punctuation, a slash or a quote (LB13, LB19): "Lohn-, Gehalts-",
32
+ // "(well-known)", "Ein-/Ausgang" stay together.
33
+ const NO_BREAK_BEFORE = new Set(")]}!?,.:;/\"'«»‘’“”");
34
+ /**
35
+ * What the line ending at break `k` draws of `word`: everything before it, and at a soft hyphen a REAL
36
+ * hyphen in its place - the only time a soft hyphen shows. The breaker draws this; measuring it measures
37
+ * what is drawn.
38
+ */
39
+ export function headAt(word, k) {
40
+ if (word[k - 1] !== SOFT_HYPHEN)
41
+ return word.slice(0, k);
42
+ // A soft hyphen right after a real one adds nothing: "ab-" + "cd", not "ab--".
43
+ return word[k - 2] === "-" ? word.slice(0, k - 1) : word.slice(0, k - 1) + HYPHEN;
44
+ }
45
+ /** A word cut at its break opportunities: the pieces no line can split, as they are drawn. */
46
+ export function hyphenPieces(word) {
47
+ const breaks = mayBreak(word) ? hyphenBreaks(word) : NO_BREAKS;
48
+ if (breaks.length === 0)
49
+ return [word];
50
+ return [0, ...breaks].map((from, k) => {
51
+ const to = breaks[k];
52
+ return to === undefined ? word.slice(from) : headAt(word, to).slice(from);
53
+ });
54
+ }
@@ -1,6 +1,7 @@
1
1
  import type { FontStyle } from "../utils/pdf-object-manager.js";
2
2
  import type { FontMetrics } from "../utils/font-metrics.js";
3
3
  import type { TextSegment } from "../elements/text-element.js";
4
+ import { type RunFont } from "./advance.js";
4
5
  import { type WordSplitting } from "./word-splitting.js";
5
6
  /**
6
7
  * How far a JUSTIFIED line's spaces may be squeezed to keep one more word on it.
@@ -27,18 +28,32 @@ export interface LineOptions {
27
28
  splitting?: WordSplitting;
28
29
  /** Whether the run gets the font's ligatures. Changes which glyphs are drawn, hence the width. */
29
30
  ligatures?: boolean;
31
+ /** Only the first N lines belong to this element: a paragraph split across pages, continued on the
32
+ * next one. Applied after `maxLines`, so every pass that breaks the text sees the same lines. */
33
+ shownLines?: number;
30
34
  }
31
- /** Default font for segments that don't override it. */
32
- export interface SegmentDefaults {
35
+ /** What a span that does not set its own draws with: the paragraph's font and spacing. */
36
+ export interface RunDefaults {
33
37
  fontFamily: string;
34
38
  fontSize: number;
35
39
  fontStyle: FontStyle;
36
40
  /** Extra space after every glyph, in points; a segment may override it. Default 0. */
37
41
  letterSpacing?: number;
38
- /** Same knobs as the string path - see `LineOptions.splitting`. */
39
- splitting?: WordSplitting;
40
- ligatures?: boolean;
41
42
  }
43
+ /** Everything the breaker reads besides the spans: what they inherit, and how lines end. */
44
+ export type SegmentDefaults = RunDefaults & LineOptions;
45
+ /** How one span is measured, broken and drawn. */
46
+ export interface RunStyle {
47
+ font: RunFont;
48
+ letterSpacing: number;
49
+ wordSpacing: number;
50
+ splitting: WordSplitting;
51
+ }
52
+ /**
53
+ * A span's run style: what it sets itself, else what the paragraph sets. The ONE place a span inherits
54
+ * it, so breaking, drawing and the element's own sizing ask the same question.
55
+ */
56
+ export declare function runStyleOf(seg: TextSegment, defaults: SegmentDefaults): RunStyle;
42
57
  /** What happens to text beyond `maxLines`: `"clip"` drops it, `"ellipsis"` ends the last kept line
43
58
  * with an ellipsis. Mirrors Flutter's `TextOverflow`. */
44
59
  export type TextOverflow = "clip" | "ellipsis";
@@ -47,40 +62,51 @@ export type TextOverflow = "clip" | "ellipsis";
47
62
  export interface SegmentLine {
48
63
  segments: TextSegment[];
49
64
  width: number;
65
+ /** Where the line begins in the source: the span, and the offset in that span's content. */
66
+ start: SegmentPosition;
67
+ end: LineEnd;
68
+ /** How far the line, as drawn, runs past the room it was broken in: above 0 only for a piece that
69
+ * could not break. */
70
+ overrun: number;
50
71
  }
51
72
  /**
52
- * Break a plain string into lines that each fit within `maxWidth`, splitting on
53
- * spaces (greedy: a word stays on the current line unless it would overflow).
54
- *
55
- * Single source of truth for plain-string wrapping: both height measurement and
56
- * rendering call this, so they can never disagree. Depends only on `FontMetrics`,
57
- * not the PDF byte writer - the future fragmentation pass can reuse it.
73
+ * A line's spaces, each as wide as its own span makes it - what justification spreads the slack over,
74
+ * and squeezes by at most `shrink` of their width.
58
75
  */
76
+ export declare function lineGaps(segments: TextSegment[], defaults: SegmentDefaults, metrics: FontMetrics): {
77
+ gaps: number;
78
+ width: number;
79
+ };
80
+ export interface SegmentPosition {
81
+ segment: number;
82
+ offset: number;
83
+ }
59
84
  /**
60
- * The width of `text` set as ONE line, accumulated in EXACTLY the order `wrapStringIntoLines` builds a
61
- * line: the first word, then `+ (space + word)` each time. The order matters because floating-point
85
+ * The width of `text` set as ONE line, accumulated in EXACTLY the order the breaker builds a line: the
86
+ * first word, then `+ (space + word)` each time. The order matters because floating-point
62
87
  * addition is not associative - a box sized by a differently-grouped sum can be one bit too small for
63
88
  * the very line the breaker then measures, and the text wraps inside a box made to fit it. That is not
64
89
  * hypothetical: it is what split a footer sized to its own content.
65
90
  */
66
- export declare function singleLineWidth(text: string, font: {
67
- fontFamily: string;
68
- fontSize: number;
69
- fontStyle: FontStyle;
70
- }, metrics: FontMetrics, letterSpacing?: number, wordSpacing?: number): number;
91
+ export declare function singleLineWidth(text: string, font: RunFont, metrics: FontMetrics, letterSpacing?: number, wordSpacing?: number): number;
71
92
  export declare function wrapStringIntoLines(text: string, fontFamily: string, fontSize: number, fontStyle: FontStyle, maxWidth: number, metrics: FontMetrics, maxLines?: number, overflow?: TextOverflow, letterSpacing?: number, options?: LineOptions): string[];
93
+ /** How a line ends - which is what justification and splitting a paragraph across pages need. */
94
+ export type LineEnd = "soft" | "hard" | "split" | "hyphen" | "end";
95
+ /** A broken line, and where it came from: `start` is the offset in the source text it begins at. */
96
+ export interface BrokenLine {
97
+ text: string;
98
+ start: number;
99
+ end: LineEnd;
100
+ }
72
101
  /**
73
- * Break styled segments into lines that fit within `maxWidth`. Same greedy word-splitting as the
74
- * string breaker; each line keeps the segments that landed on it, which is what `line-metrics.ts`
75
- * later derives the line's height from. Single source of truth: both height measurement and
76
- * rendering call this.
102
+ * `wrapStringIntoLines`, with each line's source offset and ending. The ONE breaking pass both share,
103
+ * so a line's position in the source can never disagree with the line itself.
77
104
  */
78
- export declare function breakSegmentsIntoLines(segments: TextSegment[], defaults: SegmentDefaults, maxWidth: number, metrics: FontMetrics, maxLines?: number, overflow?: TextOverflow): SegmentLine[];
105
+ export declare function breakStringIntoLines(text: string, fontFamily: string, fontSize: number, fontStyle: FontStyle, maxWidth: number, metrics: FontMetrics, maxLines?: number, overflow?: TextOverflow, letterSpacing?: number, options?: LineOptions): BrokenLine[];
79
106
  /**
80
- * Inverse of `breakSegmentsIntoLines`: flatten broken lines back into a `TextSegment[]`
81
- * that re-wraps to exactly those lines. The wrap consumed the space at each line break,
82
- * so re-insert one between lines (unless the piece already ends with one) - otherwise the
83
- * last word of a line and the first of the next would fuse ("a b" + "c d" -> "a bc d").
84
- * Used by text fragmentation to rebuild the fitted/remainder halves of a split paragraph.
107
+ * Break text - spans; a plain string is one - into lines that fit within `maxWidth`, greedily: a word
108
+ * stays on the current line unless it would overflow. Each line keeps the segments that landed on it,
109
+ * which is what `line-metrics.ts` derives the line's height from. The one breaker: measuring,
110
+ * fragmenting and drawing all call this.
85
111
  */
86
- export declare function segmentLinesToSegments(lines: SegmentLine[]): TextSegment[];
112
+ export declare function breakSegmentsIntoLines(segments: TextSegment[], defaults: SegmentDefaults, maxWidth: number, metrics: FontMetrics, maxLines?: number, overflow?: TextOverflow): SegmentLine[];