@stll/folio-core 0.32.2 → 0.33.1

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 (227) hide show
  1. package/dist/ai-edits/__fixtures__/paragraphs.d.ts +17 -0
  2. package/dist/ai-edits/__fixtures__/paragraphs.js +33 -0
  3. package/dist/ai-edits/apply.d.ts +49 -3
  4. package/dist/ai-edits/apply.js +652 -86
  5. package/dist/ai-edits/blockRange.d.ts +7 -3
  6. package/dist/ai-edits/blockRange.js +14 -6
  7. package/dist/ai-edits/headless.d.ts +39 -5
  8. package/dist/ai-edits/headless.js +76 -17
  9. package/dist/ai-edits/index.d.ts +6 -6
  10. package/dist/ai-edits/index.js +3 -3
  11. package/dist/ai-edits/read.d.ts +4 -0
  12. package/dist/ai-edits/read.js +30 -6
  13. package/dist/ai-edits/scoped-reading.js +4 -3
  14. package/dist/ai-edits/snapshot.d.ts +42 -2
  15. package/dist/ai-edits/snapshot.js +127 -62
  16. package/dist/ai-edits/table-row-column-mutations.d.ts +24 -1
  17. package/dist/ai-edits/table-row-column-mutations.js +98 -6
  18. package/dist/ai-edits/table-targets.d.ts +12 -3
  19. package/dist/ai-edits/table-targets.js +15 -5
  20. package/dist/ai-edits/types.d.ts +219 -15
  21. package/dist/ai-edits/word-diff.d.ts +54 -11
  22. package/dist/ai-edits/word-diff.js +221 -61
  23. package/dist/compare/__fixtures__/body-sequence.d.ts +56 -0
  24. package/dist/compare/__fixtures__/body-sequence.js +136 -0
  25. package/dist/compare/__fixtures__/nested-table.d.ts +16 -0
  26. package/dist/compare/__fixtures__/nested-table.js +50 -0
  27. package/dist/compare/__fixtures__/numbered-list.d.ts +34 -0
  28. package/dist/compare/__fixtures__/numbered-list.js +85 -0
  29. package/dist/compare/column-alignment.d.ts +27 -0
  30. package/dist/compare/column-alignment.js +162 -0
  31. package/dist/compare/compare.d.ts +107 -0
  32. package/dist/compare/compare.js +412 -0
  33. package/dist/compare/formatting.d.ts +29 -0
  34. package/dist/compare/formatting.js +84 -0
  35. package/dist/compare/plan.d.ts +22 -0
  36. package/dist/compare/plan.js +1141 -0
  37. package/dist/compare/reproducible-package.d.ts +21 -0
  38. package/dist/compare/reproducible-package.js +47 -0
  39. package/dist/compare/scenario.d.ts +77 -0
  40. package/dist/compare/scenario.js +263 -0
  41. package/dist/compare/types.d.ts +297 -0
  42. package/dist/compare/types.js +42 -0
  43. package/dist/compare/verification.d.ts +83 -0
  44. package/dist/compare/verification.js +189 -0
  45. package/dist/compat/eigenpal.d.ts +9 -6
  46. package/dist/compat/eigenpal.js +6 -3
  47. package/dist/controller/layoutPipeline.d.ts +13 -0
  48. package/dist/controller/layoutPipeline.js +15 -1
  49. package/dist/display-list/build/buildContext.d.ts +39 -0
  50. package/dist/display-list/build/buildContext.js +31 -0
  51. package/dist/display-list/build/buildDisplayList.d.ts +79 -0
  52. package/dist/display-list/build/buildDisplayList.js +283 -0
  53. package/dist/display-list/build/colors.d.ts +20 -0
  54. package/dist/display-list/build/colors.js +136 -0
  55. package/dist/display-list/build/floatingImages.d.ts +24 -0
  56. package/dist/display-list/build/floatingImages.js +41 -0
  57. package/dist/display-list/build/fontTable.d.ts +31 -0
  58. package/dist/display-list/build/fontTable.js +97 -0
  59. package/dist/display-list/build/furniture.d.ts +86 -0
  60. package/dist/display-list/build/furniture.js +98 -0
  61. package/dist/display-list/build/glyphs.d.ts +55 -0
  62. package/dist/display-list/build/glyphs.js +103 -0
  63. package/dist/display-list/build/headerFooterPrimitives.d.ts +17 -0
  64. package/dist/display-list/build/headerFooterPrimitives.js +40 -0
  65. package/dist/display-list/build/imagePrimitives.d.ts +35 -0
  66. package/dist/display-list/build/imagePrimitives.js +264 -0
  67. package/dist/display-list/build/pageBorderPrimitives.d.ts +23 -0
  68. package/dist/display-list/build/pageBorderPrimitives.js +111 -0
  69. package/dist/display-list/build/pageFurniture.d.ts +35 -0
  70. package/dist/display-list/build/pageFurniture.js +141 -0
  71. package/dist/display-list/build/paragraphPrimitives.d.ts +19 -0
  72. package/dist/display-list/build/paragraphPrimitives.js +819 -0
  73. package/dist/display-list/build/regions.d.ts +46 -0
  74. package/dist/display-list/build/regions.js +56 -0
  75. package/dist/display-list/build/storyPrimitives.d.ts +29 -0
  76. package/dist/display-list/build/storyPrimitives.js +279 -0
  77. package/dist/display-list/build/strokes.d.ts +19 -0
  78. package/dist/display-list/build/strokes.js +78 -0
  79. package/dist/display-list/build/tablePrimitives.d.ts +38 -0
  80. package/dist/display-list/build/tablePrimitives.js +409 -0
  81. package/dist/display-list/build/textBoxPrimitives.d.ts +14 -0
  82. package/dist/display-list/build/textBoxPrimitives.js +129 -0
  83. package/dist/display-list/build/textDecorations.d.ts +29 -0
  84. package/dist/display-list/build/textDecorations.js +29 -0
  85. package/dist/display-list/build/unsupported.d.ts +57 -0
  86. package/dist/display-list/build/unsupported.js +0 -0
  87. package/dist/display-list/build/watermarkPrimitives.d.ts +15 -0
  88. package/dist/display-list/build/watermarkPrimitives.js +128 -0
  89. package/dist/display-list/dom/renderDisplayListToDom.d.ts +26 -0
  90. package/dist/display-list/dom/renderDisplayListToDom.js +620 -0
  91. package/dist/display-list/editor/displayListPagePainter.d.ts +22 -0
  92. package/dist/display-list/editor/displayListPagePainter.js +63 -0
  93. package/dist/display-list/editor/pageRenderer.d.ts +24 -0
  94. package/dist/display-list/editor/pageRenderer.js +36 -0
  95. package/dist/display-list/primitives.d.ts +95 -0
  96. package/dist/display-list/primitives.js +127 -0
  97. package/dist/display-list/types.d.ts +472 -0
  98. package/dist/display-list/types.js +0 -0
  99. package/dist/document-operations.d.ts +39 -8
  100. package/dist/document-operations.js +169 -16
  101. package/dist/document-stories.d.ts +16 -0
  102. package/dist/document-stories.js +48 -4
  103. package/dist/docx/hyperlinkParser.d.ts +9 -1
  104. package/dist/docx/hyperlinkParser.js +19 -13
  105. package/dist/docx/packageParts.d.ts +35 -0
  106. package/dist/docx/packageParts.js +120 -0
  107. package/dist/docx/paraIdRangeNormalization.d.ts +40 -0
  108. package/dist/docx/paraIdRangeNormalization.js +64 -0
  109. package/dist/docx/paragraphParser.js +101 -26
  110. package/dist/docx/paragraphTraversal.js +1 -1
  111. package/dist/docx/renderedPageBreakNormalization.js +3 -1
  112. package/dist/docx/revisionIdNormalization.d.ts +27 -0
  113. package/dist/docx/revisionIdNormalization.js +121 -0
  114. package/dist/docx/rezip.d.ts +6 -0
  115. package/dist/docx/rezip.js +51 -19
  116. package/dist/docx/selectiveSave.js +2 -2
  117. package/dist/docx/serializer/commentSerializer.js +6 -1
  118. package/dist/docx/serializer/paragraphSerializer.js +73 -20
  119. package/dist/docx/serializer/runSerializer.js +11 -10
  120. package/dist/docx/serializer/tableSerializer.js +26 -10
  121. package/dist/docx/server/applyDocxXmlPatchProposal.js +1 -1
  122. package/dist/docx/server/createBilingualDocx.js +3 -2
  123. package/dist/docx/streamingXmlParser.d.ts +13 -1
  124. package/dist/docx/streamingXmlParser.js +49 -11
  125. package/dist/docx/unzip.d.ts +1 -2
  126. package/dist/docx/unzip.js +25 -6
  127. package/dist/docx/xmlParser.d.ts +3 -1
  128. package/dist/docx/xmlParser.js +33 -27
  129. package/dist/export-pdf.d.ts +43 -0
  130. package/dist/export-pdf.js +98 -0
  131. package/dist/fonts/headlessMeasure.d.ts +76 -0
  132. package/dist/fonts/headlessMeasure.js +0 -0
  133. package/dist/fonts/sfnt/parse.d.ts +51 -0
  134. package/dist/fonts/sfnt/parse.js +525 -0
  135. package/dist/fonts/sfnt/subset.d.ts +20 -0
  136. package/dist/fonts/sfnt/subset.js +350 -0
  137. package/dist/fonts/sfnt/tables.d.ts +88 -0
  138. package/dist/fonts/sfnt/tables.js +131 -0
  139. package/dist/fonts/sfnt/woff.d.ts +14 -0
  140. package/dist/fonts/sfnt/woff.js +163 -0
  141. package/dist/generated/text_shaper.js +324 -0
  142. package/dist/generated/text_shaper_bg.wasm +0 -0
  143. package/dist/headless-layout.d.ts +75 -0
  144. package/dist/headless-layout.js +350 -0
  145. package/dist/index.d.ts +9 -6
  146. package/dist/index.js +6 -3
  147. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
  148. package/dist/layout-bridge/convert/footnoteLayout.js +1 -0
  149. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  150. package/dist/layout-bridge/convert/headerFooterLayout.js +2 -0
  151. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +3 -1
  152. package/dist/layout-bridge/convert/toFlowBlocks.js +2 -0
  153. package/dist/layout-engine/measure/advanceComposition.d.ts +62 -0
  154. package/dist/layout-engine/measure/advanceComposition.js +148 -0
  155. package/dist/layout-engine/measure/cache.d.ts +2 -0
  156. package/dist/layout-engine/measure/measureContainer.js +13 -0
  157. package/dist/layout-engine/measure/measureParagraph.js +1 -2
  158. package/dist/layout-engine/measure/measureTypes.d.ts +12 -0
  159. package/dist/layout-engine/measure/tableInlinePlacement.d.ts +3 -2
  160. package/dist/layout-engine/measure/tableInlinePlacement.js +14 -1
  161. package/dist/layout-engine/tableIndentCompatibility.d.ts +5 -0
  162. package/dist/layout-engine/tableIndentCompatibility.js +15 -0
  163. package/dist/layout-engine/types.d.ts +8 -0
  164. package/dist/layout-painter/renderPage.d.ts +29 -1
  165. package/dist/layout-painter/renderPage.js +47 -19
  166. package/dist/layout-painter/renderParagraph.d.ts +21 -2
  167. package/dist/layout-painter/renderParagraph.js +1 -1
  168. package/dist/layout-painter/renderTable.js +37 -4
  169. package/dist/managers/editorShortcuts.d.ts +33 -1
  170. package/dist/managers/editorShortcuts.js +20 -1
  171. package/dist/markdown/renderRuns.js +7 -2
  172. package/dist/markdown/renderTable.js +5 -1
  173. package/dist/model.d.ts +3 -3
  174. package/dist/model.js +2 -2
  175. package/dist/pdf/contentStream.d.ts +73 -0
  176. package/dist/pdf/contentStream.js +143 -0
  177. package/dist/pdf/fonts.d.ts +96 -0
  178. package/dist/pdf/fonts.js +593 -0
  179. package/dist/pdf/images.d.ts +28 -0
  180. package/dist/pdf/images.js +439 -0
  181. package/dist/pdf/objects.d.ts +93 -0
  182. package/dist/pdf/objects.js +237 -0
  183. package/dist/pdf/pageSpace.d.ts +43 -0
  184. package/dist/pdf/pageSpace.js +57 -0
  185. package/dist/pdf/paint.d.ts +32 -0
  186. package/dist/pdf/paint.js +442 -0
  187. package/dist/pdf/writePdf.d.ts +56 -0
  188. package/dist/pdf/writePdf.js +345 -0
  189. package/dist/prosemirror/commands/comments.js +96 -6
  190. package/dist/prosemirror/conversion/fromProseDoc.js +41 -7
  191. package/dist/prosemirror/conversion/toProseDoc.js +41 -4
  192. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +15 -2
  193. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +35 -6
  194. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +2 -2
  195. package/dist/prosemirror/extensions/features/pasteCleanup.js +4 -3
  196. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.d.ts +3 -1
  197. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +5 -3
  198. package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.d.ts +7 -1
  199. package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.js +9 -3
  200. package/dist/prosemirror/extensions/nodes/TableExtension.js +56 -39
  201. package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.d.ts +3 -1
  202. package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.js +5 -3
  203. package/dist/prosemirror/plugins/suggestionMode.js +1 -0
  204. package/dist/prosemirror/revisionCarriers.js +19 -2
  205. package/dist/prosemirror/utils/extractTrackedChanges.d.ts +2 -2
  206. package/dist/prosemirror/utils/extractTrackedChanges.js +59 -23
  207. package/dist/prosemirror/validation.js +55 -27
  208. package/dist/prosemirror/zeroWidthAnchors.d.ts +10 -0
  209. package/dist/prosemirror/zeroWidthAnchors.js +23 -0
  210. package/dist/redline.js +12 -79
  211. package/dist/server.d.ts +3 -3
  212. package/dist/server.js +2 -2
  213. package/dist/shaping/placeRun.d.ts +51 -0
  214. package/dist/shaping/placeRun.js +84 -0
  215. package/dist/shaping/shaper.d.ts +92 -0
  216. package/dist/shaping/shaper.js +102 -0
  217. package/dist/types/block-id.d.ts +18 -2
  218. package/dist/types/block-id.js +49 -5
  219. package/dist/types/content.d.ts +2 -2
  220. package/dist/utils/clipboard.js +4 -3
  221. package/dist/utils/fontResolver.js +183 -0
  222. package/dist/utils/htmlComments.d.ts +17 -0
  223. package/dist/utils/htmlComments.js +22 -0
  224. package/dist/utils/scriptSegments.d.ts +12 -1
  225. package/dist/utils/scriptSegments.js +17 -1
  226. package/dist/version-comparison.d.ts +1 -1
  227. package/package.json +7 -3
@@ -0,0 +1,409 @@
1
+ import { createTableCellFlowState, placeTableCellBlock } from "../../layout-engine/measure/tableCellFlow.js";
2
+ import { buildTableCellGrid, buildTableCellPlacements, getSourceCellAt } from "../../layout-engine/measure/tableCellGrid.js";
3
+ import { resolveTableCellPadding } from "../../layout-engine/types.js";
4
+ import { HIT_REGION_KINDS } from "../primitives.js";
5
+ import { parseDisplayColor } from "./colors.js";
6
+ import { paintImageFragment } from "./imagePrimitives.js";
7
+ import { paintParagraphFragment } from "./paragraphPrimitives.js";
8
+ import { blockRegion, createPageComposer } from "./regions.js";
9
+ import { resolveBorderStroke } from "./strokes.js";
10
+ import { UNSUPPORTED_CONSTRUCT } from "./unsupported.js";
11
+ //#region src/display-list/build/tablePrimitives.ts
12
+ /**
13
+ * Table fragments → primitives.
14
+ *
15
+ * Order per cell is fixed here rather than left to a backend: background,
16
+ * borders, content, diagonals. `renderTable.ts` gets that order from CSS
17
+ * (a background paints under its own border, a `z-index: 1` diagonal over the
18
+ * content); nothing in a display list would reproduce it by accident.
19
+ *
20
+ * One deliberate divergence from the painter: `renderCellDiagonalBorder`
21
+ * (`renderTable.ts:533`) emulates a diagonal with a rotated bar whose dash
22
+ * pattern is a CSS gradient. Here it is a real diagonal `line` with the
23
+ * authored stroke pattern, so a backend draws a line rather than reverse
24
+ * engineering a gradient.
25
+ */
26
+ /** A cell edge is "visible" for collapse purposes on style alone, as the painter decides it. */
27
+ const hasVisibleBorder = (border) => border !== void 0 && border.style !== "none" && border.style !== "nil";
28
+ const strokeFor = (border, context, label) => {
29
+ if (!hasVisibleBorder(border) || !border) return;
30
+ const { stroke, unresolvedColor } = resolveBorderStroke(border);
31
+ if (unresolvedColor !== void 0) context.unsupported.report(UNSUPPORTED_CONSTRUCT.unresolvedColor, context.pageIndex, `${label} colour ${unresolvedColor}`);
32
+ return stroke;
33
+ };
34
+ const paintCell = ({ composer, cell, cellMeasure, box, context, paintTextBox, sides }) => {
35
+ const primitives = [];
36
+ if (cell.background) {
37
+ const fill = parseDisplayColor(cell.background);
38
+ if (fill) primitives.push({
39
+ kind: "rect",
40
+ rect: {
41
+ xPx: box.xPx,
42
+ yPx: box.yPx,
43
+ widthPx: box.widthPx,
44
+ heightPx: box.heightPx
45
+ },
46
+ fill
47
+ });
48
+ else context.unsupported.report(UNSUPPORTED_CONSTRUCT.unresolvedColor, context.pageIndex, `table cell background ${cell.background}`);
49
+ }
50
+ const borders = cell.borders;
51
+ const strokes = {
52
+ top: sides.top ? strokeFor(borders?.top, context, "table cell top border") : void 0,
53
+ bottom: sides.bottom ? strokeFor(borders?.bottom, context, "table cell bottom border") : void 0,
54
+ left: sides.left ? strokeFor(borders?.left, context, "table cell left border") : void 0,
55
+ right: strokeFor(borders?.right, context, "table cell right border")
56
+ };
57
+ const widths = {
58
+ top: strokes.top?.thicknessPx ?? 0,
59
+ right: strokes.right?.thicknessPx ?? 0,
60
+ bottom: strokes.bottom?.thicknessPx ?? 0,
61
+ left: strokes.left?.thicknessPx ?? 0
62
+ };
63
+ if (strokes.top) primitives.push({
64
+ kind: "line",
65
+ x1Px: box.xPx,
66
+ y1Px: box.yPx + widths.top / 2,
67
+ x2Px: box.xPx + box.widthPx,
68
+ y2Px: box.yPx + widths.top / 2,
69
+ stroke: strokes.top
70
+ });
71
+ if (strokes.bottom) primitives.push({
72
+ kind: "line",
73
+ x1Px: box.xPx,
74
+ y1Px: box.yPx + box.heightPx - widths.bottom / 2,
75
+ x2Px: box.xPx + box.widthPx,
76
+ y2Px: box.yPx + box.heightPx - widths.bottom / 2,
77
+ stroke: strokes.bottom
78
+ });
79
+ if (strokes.left) primitives.push({
80
+ kind: "line",
81
+ x1Px: box.xPx + widths.left / 2,
82
+ y1Px: box.yPx,
83
+ x2Px: box.xPx + widths.left / 2,
84
+ y2Px: box.yPx + box.heightPx,
85
+ stroke: strokes.left
86
+ });
87
+ if (strokes.right) primitives.push({
88
+ kind: "line",
89
+ x1Px: box.xPx + box.widthPx - widths.right / 2,
90
+ y1Px: box.yPx,
91
+ x2Px: box.xPx + box.widthPx - widths.right / 2,
92
+ y2Px: box.yPx + box.heightPx,
93
+ stroke: strokes.right
94
+ });
95
+ const padding = resolveTableCellPadding(cell);
96
+ const contentXPx = box.xPx + widths.left + padding.left;
97
+ const contentYPx = box.yPx + widths.top + padding.top;
98
+ const contentWidthPx = Math.max(0, cellMeasure.width - padding.left - padding.right);
99
+ if (cell.textDirection === "btLr" || cell.textDirection === "tbRl") context.unsupported.report(UNSUPPORTED_CONSTRUCT.verticalCellText, context.pageIndex, `w:textDirection ${cell.textDirection} paints horizontally`);
100
+ composer.push(primitives);
101
+ primitives.length = 0;
102
+ paintCellBlocks({
103
+ composer,
104
+ blocks: cell.blocks,
105
+ measures: cellMeasure.blocks,
106
+ xPx: contentXPx,
107
+ yPx: contentYPx,
108
+ widthPx: contentWidthPx,
109
+ context,
110
+ paintTextBox
111
+ });
112
+ const diagonals = [{
113
+ border: borders?.topLeftToBottomRight,
114
+ from: "topLeft"
115
+ }, {
116
+ border: borders?.topRightToBottomLeft,
117
+ from: "topRight"
118
+ }];
119
+ for (const { border, from } of diagonals) {
120
+ const stroke = strokeFor(border, context, "table cell diagonal border");
121
+ if (!stroke) continue;
122
+ primitives.push({
123
+ kind: "line",
124
+ x1Px: box.xPx,
125
+ y1Px: from === "topLeft" ? box.yPx : box.yPx + box.heightPx,
126
+ x2Px: box.xPx + box.widthPx,
127
+ y2Px: from === "topLeft" ? box.yPx + box.heightPx : box.yPx,
128
+ stroke
129
+ });
130
+ }
131
+ composer.push(primitives);
132
+ };
133
+ /**
134
+ * A cell's inner blocks, stacked by the same flow state the measurer used, so
135
+ * paragraph spacing collapses in paint exactly where it collapsed in layout.
136
+ */
137
+ const paintCellBlocks = ({ composer, blocks, measures, xPx, yPx, widthPx, context, paintTextBox }) => {
138
+ const flowState = createTableCellFlowState();
139
+ for (let index = 0; index < blocks.length; index += 1) {
140
+ const block = blocks[index];
141
+ const measure = measures[index];
142
+ if (!block || !measure) {
143
+ context.unsupported.report(UNSUPPORTED_CONSTRUCT.missingBlock, context.pageIndex, block === void 0 ? `table cell content at index ${String(index)} has no block` : `table cell block ${String(block.id)} has no measure`);
144
+ continue;
145
+ }
146
+ const placement = placeTableCellBlock(flowState, block, measure);
147
+ if (block.kind === "paragraph" && measure.kind === "paragraph") {
148
+ const previous = blocks[index - 1];
149
+ const next = blocks[index + 1];
150
+ const fragment = {
151
+ kind: "paragraph",
152
+ blockId: block.id,
153
+ x: xPx,
154
+ y: yPx + placement.contentTop,
155
+ width: widthPx,
156
+ height: placement.contentHeight,
157
+ fromLine: 0,
158
+ toLine: measure.lines.length
159
+ };
160
+ composer.region(blockRegion({
161
+ fragment,
162
+ kind: HIT_REGION_KINDS.paragraph,
163
+ context
164
+ }), () => {
165
+ paintParagraphFragment({
166
+ composer,
167
+ fragment,
168
+ block,
169
+ measure,
170
+ context,
171
+ ...previous?.kind === "paragraph" && previous.attrs?.borders !== void 0 ? { prevBorders: previous.attrs.borders } : {},
172
+ ...next?.kind === "paragraph" && next.attrs?.borders !== void 0 ? { nextBorders: next.attrs.borders } : {}
173
+ });
174
+ });
175
+ continue;
176
+ }
177
+ if (block.kind === "table" && measure.kind === "table") {
178
+ const fragment = {
179
+ blockId: block.id,
180
+ x: xPx,
181
+ y: yPx + placement.contentTop,
182
+ width: measure.totalWidth,
183
+ height: measure.totalHeight
184
+ };
185
+ composer.region(blockRegion({
186
+ fragment,
187
+ kind: HIT_REGION_KINDS.table,
188
+ context
189
+ }), () => {
190
+ paintTableBlock({
191
+ composer,
192
+ block,
193
+ measure,
194
+ xPx: fragment.x,
195
+ yPx: fragment.y,
196
+ context,
197
+ paintTextBox
198
+ });
199
+ });
200
+ continue;
201
+ }
202
+ if (block.kind === "image" && measure.kind === "image") {
203
+ const fragment = {
204
+ kind: "image",
205
+ blockId: block.id,
206
+ x: xPx,
207
+ y: yPx + placement.contentTop,
208
+ width: measure.width,
209
+ height: measure.height
210
+ };
211
+ composer.region(blockRegion({
212
+ fragment,
213
+ kind: HIT_REGION_KINDS.image,
214
+ context
215
+ }), () => {
216
+ composer.push(paintImageFragment(fragment, block, context));
217
+ });
218
+ continue;
219
+ }
220
+ if (block.kind === "textBox" && measure.kind === "textBox") {
221
+ const fragment = {
222
+ kind: "textBox",
223
+ blockId: block.id,
224
+ x: xPx,
225
+ y: yPx + placement.contentTop,
226
+ width: measure.width,
227
+ height: measure.height
228
+ };
229
+ composer.region(blockRegion({
230
+ fragment,
231
+ kind: HIT_REGION_KINDS.textBox,
232
+ context
233
+ }), () => {
234
+ paintTextBox({
235
+ composer,
236
+ fragment,
237
+ block,
238
+ measure,
239
+ context
240
+ });
241
+ });
242
+ continue;
243
+ }
244
+ context.unsupported.report(UNSUPPORTED_CONSTRUCT.fragmentKind, context.pageIndex, `table cell content of kind ${block.kind} is not painted`);
245
+ }
246
+ };
247
+ const rowIsPainted = (row) => row !== void 0 && row.hidden !== true;
248
+ const paintTableBody = ({ composer, block, measure, xPx, yPx, fromRow, toRow, headerRowCount, context, paintTextBox }) => {
249
+ const grid = buildTableCellGrid(block.rows, measure.columnWidths.length);
250
+ const placements = buildTableCellPlacements({
251
+ grid,
252
+ columnWidths: measure.columnWidths,
253
+ bidi: block.bidi === true
254
+ });
255
+ const rowTops = [0];
256
+ for (const rowMeasure of measure.rows) rowTops.push((rowTops.at(-1) ?? 0) + rowMeasure.height);
257
+ const paintRow = (rowIndex, rowYPx) => {
258
+ const row = block.rows[rowIndex];
259
+ const rowMeasure = measure.rows[rowIndex];
260
+ if (!rowIsPainted(row) || !rowMeasure) return;
261
+ composer.region({
262
+ kind: HIT_REGION_KINDS.tableRow,
263
+ rect: {
264
+ xPx,
265
+ yPx: rowYPx,
266
+ widthPx: measure.columnWidths.reduce((total, width) => total + width, 0),
267
+ heightPx: rowMeasure.height
268
+ },
269
+ model: { rowIndex }
270
+ }, () => {
271
+ paintRowCells(row, rowMeasure, rowIndex, rowYPx);
272
+ });
273
+ };
274
+ const paintRowCells = (row, rowMeasure, rowIndex, rowYPx) => {
275
+ for (let cellIndex = 0; cellIndex < row.cells.length; cellIndex += 1) {
276
+ const cell = row.cells[cellIndex];
277
+ const cellMeasure = rowMeasure.cells[cellIndex];
278
+ if (!cell || !cellMeasure) continue;
279
+ const placement = placements.get(cell);
280
+ if (!placement) continue;
281
+ const rowSpan = Math.max(1, Math.trunc(cell.rowSpan ?? 1));
282
+ const spanEnd = Math.min(rowTops.length - 1, rowIndex + rowSpan);
283
+ const heightPx = spanEnd > rowIndex ? rowTops[spanEnd] - rowTops[rowIndex] : rowMeasure.height;
284
+ const atLogicalStart = placement.sourceColumn === 0;
285
+ const atLogicalEnd = placement.sourceColumn + placement.columnSpan >= measure.columnWidths.length;
286
+ const isFirstColumn = block.bidi === true ? atLogicalEnd : atLogicalStart;
287
+ const aboveCell = getSourceCellAt(grid, rowIndex - 1, placement.sourceColumn);
288
+ const leftNeighborColumn = block.bidi === true ? placement.sourceColumn + placement.columnSpan : placement.sourceColumn - 1;
289
+ const leftCell = getSourceCellAt(grid, rowIndex, leftNeighborColumn);
290
+ const box = {
291
+ xPx: xPx + placement.left,
292
+ yPx: rowYPx,
293
+ widthPx: placement.width,
294
+ heightPx
295
+ };
296
+ composer.region({
297
+ kind: HIT_REGION_KINDS.tableCell,
298
+ rect: box,
299
+ model: {
300
+ rowIndex,
301
+ columnIndex: placement.sourceColumn
302
+ }
303
+ }, () => {
304
+ paintCell({
305
+ composer,
306
+ cell,
307
+ cellMeasure,
308
+ box,
309
+ context,
310
+ paintTextBox,
311
+ sides: {
312
+ top: rowIndex === fromRow || !hasVisibleBorder(aboveCell?.borders?.bottom),
313
+ bottom: true,
314
+ left: isFirstColumn || !hasVisibleBorder(leftCell?.borders?.right),
315
+ right: true
316
+ }
317
+ });
318
+ });
319
+ }
320
+ };
321
+ let cursorYPx = yPx;
322
+ for (let rowIndex = 0; rowIndex < headerRowCount; rowIndex += 1) {
323
+ const rowMeasure = measure.rows[rowIndex];
324
+ if (!rowMeasure) continue;
325
+ paintRow(rowIndex, cursorYPx);
326
+ cursorYPx += rowMeasure.height;
327
+ }
328
+ for (let rowIndex = fromRow; rowIndex < toRow; rowIndex += 1) {
329
+ const rowMeasure = measure.rows[rowIndex];
330
+ if (!rowMeasure) continue;
331
+ paintRow(rowIndex, cursorYPx);
332
+ cursorYPx += rowMeasure.height;
333
+ }
334
+ };
335
+ /** A whole, unpaginated table: what a nested table inside a cell or box is. */
336
+ const paintTableBlock = ({ composer, block, measure, xPx, yPx, context, paintTextBox }) => paintTableBody({
337
+ composer,
338
+ block,
339
+ measure,
340
+ xPx,
341
+ yPx,
342
+ fromRow: 0,
343
+ toRow: block.rows.length,
344
+ headerRowCount: 0,
345
+ context,
346
+ paintTextBox
347
+ });
348
+ /**
349
+ * A table fragment's primitives. A fragment that cuts a row mid-content wraps
350
+ * its rows in a `clipGroup` and starts them `topClip` px higher, which is what
351
+ * the painter's negative row-stack offset plus `overflow: hidden` does.
352
+ */
353
+ const paintTableFragment = ({ composer, fragment, block, measure, context, paintTextBox }) => {
354
+ const headerRowCount = fragment.continuesFromPrev === true ? fragment.headerRowCount ?? 0 : 0;
355
+ let headerHeightPx = 0;
356
+ for (let rowIndex = 0; rowIndex < headerRowCount; rowIndex += 1) headerHeightPx += measure.rows[rowIndex]?.height ?? 0;
357
+ const paintHeaders = (into) => {
358
+ if (headerRowCount === 0) return;
359
+ paintTableBody({
360
+ composer: into,
361
+ block,
362
+ measure,
363
+ xPx: fragment.x,
364
+ yPx: fragment.y,
365
+ fromRow: 0,
366
+ toRow: 0,
367
+ headerRowCount,
368
+ context,
369
+ paintTextBox
370
+ });
371
+ };
372
+ const topClipPx = fragment.topClip ?? 0;
373
+ const paintBody = (into) => {
374
+ paintTableBody({
375
+ composer: into,
376
+ block,
377
+ measure,
378
+ xPx: fragment.x,
379
+ yPx: fragment.y + headerHeightPx - topClipPx,
380
+ fromRow: fragment.fromRow,
381
+ toRow: fragment.toRow,
382
+ headerRowCount: 0,
383
+ context,
384
+ paintTextBox
385
+ });
386
+ };
387
+ if (fragment.topClip === void 0 && fragment.bottomClip === void 0) {
388
+ paintHeaders(composer);
389
+ paintBody(composer);
390
+ return;
391
+ }
392
+ paintHeaders(composer);
393
+ const clipped = createPageComposer();
394
+ paintBody(clipped);
395
+ const clip = {
396
+ xPx: fragment.x,
397
+ yPx: fragment.y + headerHeightPx,
398
+ widthPx: fragment.width,
399
+ heightPx: Math.max(0, fragment.height - headerHeightPx)
400
+ };
401
+ composer.push([{
402
+ kind: "clipGroup",
403
+ rect: clip,
404
+ children: [...clipped.primitives()],
405
+ regions: [...clipped.regions()]
406
+ }]);
407
+ };
408
+ //#endregion
409
+ export { paintTableBlock, paintTableFragment };
@@ -0,0 +1,14 @@
1
+ import { TextBoxBlock, TextBoxFragment, TextBoxMeasure } from "../../layout-engine/types.js";
2
+ import { BuildContext } from "./buildContext.js";
3
+ import { PageComposer } from "./regions.js";
4
+ //#region src/display-list/build/textBoxPrimitives.d.ts
5
+ type TextBoxPaintOptions = {
6
+ readonly composer: PageComposer;
7
+ readonly fragment: TextBoxFragment;
8
+ readonly block: TextBoxBlock;
9
+ readonly measure: TextBoxMeasure;
10
+ readonly context: BuildContext;
11
+ };
12
+ declare const paintTextBoxFragment: ({ composer, fragment, block, measure, context }: TextBoxPaintOptions) => void;
13
+ //#endregion
14
+ export { TextBoxPaintOptions, paintTextBoxFragment };
@@ -0,0 +1,129 @@
1
+ import { layoutTextBoxContent } from "../../layout-engine/measure/textBoxParagraphLayout.js";
2
+ import { DEFAULT_TEXTBOX_MARGINS } from "../../layout-engine/types.js";
3
+ import { HIT_REGION_KINDS } from "../primitives.js";
4
+ import { parseDisplayColor } from "./colors.js";
5
+ import { paintParagraphFragment } from "./paragraphPrimitives.js";
6
+ import { blockRegion } from "./regions.js";
7
+ import { resolveBorderStroke } from "./strokes.js";
8
+ import { paintTableBlock } from "./tablePrimitives.js";
9
+ import { UNSUPPORTED_CONSTRUCT } from "./unsupported.js";
10
+ //#region src/display-list/build/textBoxPrimitives.ts
11
+ /**
12
+ * Text-box fragments → primitives: fill, outline, then the inner block story.
13
+ *
14
+ * The box's own content flow is `layoutTextBoxContent`, the same helper the
15
+ * measurer used, so the paragraphs land where their heights were reserved.
16
+ */
17
+ const paintTextBoxFragment = ({ composer, fragment, block, measure, context }) => {
18
+ const primitives = [];
19
+ const box = {
20
+ xPx: fragment.x,
21
+ yPx: fragment.y,
22
+ widthPx: fragment.width,
23
+ heightPx: fragment.height
24
+ };
25
+ if (block.fillColor) {
26
+ const fill = parseDisplayColor(block.fillColor);
27
+ if (fill) primitives.push({
28
+ kind: "rect",
29
+ rect: box,
30
+ fill
31
+ });
32
+ else context.unsupported.report(UNSUPPORTED_CONSTRUCT.unresolvedColor, context.pageIndex, `text box fill ${block.fillColor}`);
33
+ }
34
+ let outlineWidthPx = 0;
35
+ if (block.outlineWidth !== void 0 && block.outlineWidth > 0) {
36
+ const { stroke, unresolvedColor } = resolveBorderStroke({
37
+ width: block.outlineWidth,
38
+ style: block.outlineStyle ?? "solid",
39
+ color: block.outlineColor ?? "#000000"
40
+ });
41
+ if (unresolvedColor !== void 0) context.unsupported.report(UNSUPPORTED_CONSTRUCT.unresolvedColor, context.pageIndex, `text box outline ${unresolvedColor}`);
42
+ if (stroke) {
43
+ outlineWidthPx = stroke.thicknessPx;
44
+ const inset = stroke.thicknessPx / 2;
45
+ primitives.push({
46
+ kind: "rect",
47
+ rect: {
48
+ xPx: box.xPx + inset,
49
+ yPx: box.yPx + inset,
50
+ widthPx: Math.max(0, box.widthPx - stroke.thicknessPx),
51
+ heightPx: Math.max(0, box.heightPx - stroke.thicknessPx)
52
+ },
53
+ stroke
54
+ });
55
+ }
56
+ }
57
+ const margins = block.margins ?? DEFAULT_TEXTBOX_MARGINS;
58
+ const innerWidthPx = fragment.width - margins.left - margins.right;
59
+ const layout = layoutTextBoxContent(block.content, measure.innerMeasures);
60
+ let cursorYPx = box.yPx + outlineWidthPx + margins.top;
61
+ for (let index = 0; index < block.content.length; index += 1) {
62
+ const contentBlock = block.content[index];
63
+ const contentMeasure = measure.innerMeasures[index];
64
+ const placement = layout.placements[index];
65
+ if (!contentBlock || !contentMeasure || !placement) continue;
66
+ cursorYPx += placement.leadingSpacing;
67
+ if (contentBlock.kind === "paragraph" && contentMeasure.kind === "paragraph") {
68
+ const previous = block.content[index - 1];
69
+ const next = block.content[index + 1];
70
+ composer.push(primitives);
71
+ primitives.length = 0;
72
+ const contentFragment = {
73
+ kind: "paragraph",
74
+ blockId: contentBlock.id,
75
+ x: box.xPx + outlineWidthPx + margins.left,
76
+ y: cursorYPx,
77
+ width: innerWidthPx,
78
+ height: placement.contentHeight,
79
+ fromLine: 0,
80
+ toLine: contentMeasure.lines.length
81
+ };
82
+ composer.region(blockRegion({
83
+ fragment: contentFragment,
84
+ kind: HIT_REGION_KINDS.paragraph,
85
+ context
86
+ }), () => {
87
+ paintParagraphFragment({
88
+ composer,
89
+ fragment: contentFragment,
90
+ block: contentBlock,
91
+ measure: contentMeasure,
92
+ context,
93
+ ...previous?.kind === "paragraph" && previous.attrs?.borders !== void 0 ? { prevBorders: previous.attrs.borders } : {},
94
+ ...next?.kind === "paragraph" && next.attrs?.borders !== void 0 ? { nextBorders: next.attrs.borders } : {}
95
+ });
96
+ });
97
+ } else if (contentBlock.kind === "table" && contentMeasure.kind === "table") {
98
+ composer.push(primitives);
99
+ primitives.length = 0;
100
+ const contentFragment = {
101
+ blockId: contentBlock.id,
102
+ x: box.xPx + outlineWidthPx + margins.left,
103
+ y: cursorYPx,
104
+ width: contentMeasure.totalWidth,
105
+ height: contentMeasure.totalHeight
106
+ };
107
+ composer.region(blockRegion({
108
+ fragment: contentFragment,
109
+ kind: HIT_REGION_KINDS.table,
110
+ context
111
+ }), () => {
112
+ paintTableBlock({
113
+ composer,
114
+ block: contentBlock,
115
+ measure: contentMeasure,
116
+ xPx: contentFragment.x,
117
+ yPx: contentFragment.y,
118
+ context,
119
+ paintTextBox: paintTextBoxFragment
120
+ });
121
+ });
122
+ } else context.unsupported.report(UNSUPPORTED_CONSTRUCT.fragmentKind, context.pageIndex, `text box content of kind ${contentBlock.kind} is not painted`);
123
+ cursorYPx += placement.contentHeight;
124
+ }
125
+ if (block.verticalAlign === "middle" || block.verticalAlign === "bottom") context.unsupported.report(UNSUPPORTED_CONSTRUCT.textBoxVerticalAlign, context.pageIndex, `text box anchor ${block.verticalAlign} paints from the top`);
126
+ composer.push(primitives);
127
+ };
128
+ //#endregion
129
+ export { paintTextBoxFragment };
@@ -0,0 +1,29 @@
1
+ //#region src/display-list/build/textDecorations.d.ts
2
+ /**
3
+ * Text-decoration geometry.
4
+ *
5
+ * The DOM painter delegates underlines and strikethroughs to CSS
6
+ * `text-decoration`, which derives its position and thickness from the font's
7
+ * own `post`/`OS/2` tables. A display list has to state the geometry, and the
8
+ * builder has no font binary, so these ratios stand in for the font-derived
9
+ * metrics.
10
+ *
11
+ * They are approximations of what a browser computes from the face, chosen to
12
+ * match the common Latin text faces at body sizes. The follow-up is to read
13
+ * `underlinePosition` / `underlineThickness` from the embedded face and thread
14
+ * them through the measure seam alongside ascent and descent; until then a
15
+ * decoration on an unusual face sits a fraction of an em off where Word puts
16
+ * it. Every constant is in one place so that follow-up is a single edit.
17
+ */
18
+ /** Distance below the baseline to the centre of the underline, as a fraction of the em. */
19
+ declare const UNDERLINE_OFFSET_RATIO = 0.1;
20
+ /** Underline thickness as a fraction of the em, floored so a hairline stays visible. */
21
+ declare const UNDERLINE_THICKNESS_RATIO: number;
22
+ declare const MIN_DECORATION_THICKNESS_PX = 1;
23
+ /** Distance above the baseline to the centre of the strikethrough, as a fraction of the em. */
24
+ declare const STRIKETHROUGH_OFFSET_RATIO = 0.28;
25
+ declare const underlineThicknessPx: (fontSizePx: number) => number;
26
+ declare const underlineCenterYPx: (baselineYPx: number, fontSizePx: number) => number;
27
+ declare const strikethroughCenterYPx: (baselineYPx: number, fontSizePx: number) => number;
28
+ //#endregion
29
+ export { MIN_DECORATION_THICKNESS_PX, STRIKETHROUGH_OFFSET_RATIO, UNDERLINE_OFFSET_RATIO, UNDERLINE_THICKNESS_RATIO, strikethroughCenterYPx, underlineCenterYPx, underlineThicknessPx };
@@ -0,0 +1,29 @@
1
+ //#region src/display-list/build/textDecorations.ts
2
+ /**
3
+ * Text-decoration geometry.
4
+ *
5
+ * The DOM painter delegates underlines and strikethroughs to CSS
6
+ * `text-decoration`, which derives its position and thickness from the font's
7
+ * own `post`/`OS/2` tables. A display list has to state the geometry, and the
8
+ * builder has no font binary, so these ratios stand in for the font-derived
9
+ * metrics.
10
+ *
11
+ * They are approximations of what a browser computes from the face, chosen to
12
+ * match the common Latin text faces at body sizes. The follow-up is to read
13
+ * `underlinePosition` / `underlineThickness` from the embedded face and thread
14
+ * them through the measure seam alongside ascent and descent; until then a
15
+ * decoration on an unusual face sits a fraction of an em off where Word puts
16
+ * it. Every constant is in one place so that follow-up is a single edit.
17
+ */
18
+ /** Distance below the baseline to the centre of the underline, as a fraction of the em. */
19
+ const UNDERLINE_OFFSET_RATIO = .1;
20
+ /** Underline thickness as a fraction of the em, floored so a hairline stays visible. */
21
+ const UNDERLINE_THICKNESS_RATIO = 1 / 14;
22
+ const MIN_DECORATION_THICKNESS_PX = 1;
23
+ /** Distance above the baseline to the centre of the strikethrough, as a fraction of the em. */
24
+ const STRIKETHROUGH_OFFSET_RATIO = .28;
25
+ const underlineThicknessPx = (fontSizePx) => Math.max(1, fontSizePx * UNDERLINE_THICKNESS_RATIO);
26
+ const underlineCenterYPx = (baselineYPx, fontSizePx) => baselineYPx + fontSizePx * UNDERLINE_OFFSET_RATIO;
27
+ const strikethroughCenterYPx = (baselineYPx, fontSizePx) => baselineYPx - fontSizePx * STRIKETHROUGH_OFFSET_RATIO;
28
+ //#endregion
29
+ export { MIN_DECORATION_THICKNESS_PX, STRIKETHROUGH_OFFSET_RATIO, UNDERLINE_OFFSET_RATIO, UNDERLINE_THICKNESS_RATIO, strikethroughCenterYPx, underlineCenterYPx, underlineThicknessPx };
@@ -0,0 +1,57 @@
1
+ import { DisplayUnsupported } from "../types.js";
2
+ //#region src/display-list/build/unsupported.d.ts
3
+ /**
4
+ * Every construct name the builder can report. Named rather than free-form so
5
+ * a consumer can switch over them, and so a typo cannot invent a new category.
6
+ */
7
+ declare const UNSUPPORTED_CONSTRUCT: {
8
+ /** `w:effect` animations (blinkBackground, shimmer, …). */
9
+ readonly textEffect: "textEffect";
10
+ /** `w:smallCaps`: advances are correct, the small-cap glyph choice is not expressible. */
11
+ readonly smallCaps: "smallCaps";
12
+ /** `w:w` horizontal scale: folded into advances, but the glyphs are not narrowed. */
13
+ readonly horizontalScale: "horizontalScale";
14
+ /** `w:em` emphasis marks. */
15
+ readonly emphasisMark: "emphasisMark";
16
+ /** `w:emboss` / `w:imprint` / `w:shadow` shadow effects. */
17
+ readonly textShadowEffect: "textShadowEffect";
18
+ /** `w:vanish` hidden text, suppressed as Word's print view does. */
19
+ readonly hiddenRun: "hiddenRun";
20
+ /** OMML equations, painted as `renderMathFallback`'s plain text. */
21
+ readonly mathRun: "mathRun";
22
+ /** An image whose bytes are not PNG or JPEG (WMF/EMF/TIFF/SVG/GIF/BMP). */
23
+ readonly imageFormat: "imageFormat";
24
+ /** An image whose bytes the builder could not reach (remote or opaque `src`). */
25
+ readonly imageSource: "imageSource";
26
+ /** A colour literal the producer could not resolve to concrete channels. */
27
+ readonly unresolvedColor: "unresolvedColor";
28
+ /** Runs placed in logical order because the builder runs no bidi algorithm. */
29
+ readonly bidiReordering: "bidiReordering";
30
+ /** `w:textDirection` vertical cell text. */
31
+ readonly verticalCellText: "verticalCellText";
32
+ /** Page borders, which the layout does not carry. */
33
+ readonly pageBorders: "pageBorders";
34
+ /** Watermarks, which the layout does not carry. */
35
+ readonly watermark: "watermark";
36
+ /** Footnote bodies, which the layout does not carry. */
37
+ readonly footnoteContent: "footnoteContent";
38
+ /** Header and footer stories, which the layout does not carry. */
39
+ readonly headerFooterContent: "headerFooterContent";
40
+ /** `a:bodyPr` middle/bottom anchoring inside a text box. */
41
+ readonly textBoxVerticalAlign: "textBoxVerticalAlign";
42
+ /** A fragment kind with no builder. */
43
+ readonly fragmentKind: "fragmentKind";
44
+ /** A fragment whose block or measure is missing from the block lookup. */
45
+ readonly missingBlock: "missingBlock";
46
+ /** A block/measure pair whose kinds disagree. */
47
+ readonly measureMismatch: "measureMismatch";
48
+ };
49
+ type UnsupportedConstruct = (typeof UNSUPPORTED_CONSTRUCT)[keyof typeof UNSUPPORTED_CONSTRUCT];
50
+ declare class UnsupportedCollector {
51
+ private readonly entries;
52
+ private readonly seen;
53
+ report(construct: UnsupportedConstruct, pageIndex: number, detail: string): void;
54
+ snapshot(): readonly DisplayUnsupported[];
55
+ }
56
+ //#endregion
57
+ export { UNSUPPORTED_CONSTRUCT, UnsupportedCollector, UnsupportedConstruct };
@@ -0,0 +1,15 @@
1
+ import { document_d_exports } from "../../types/document.js";
2
+ import { Page } from "../../layout-engine/types.js";
3
+ import { DisplayPrimitive } from "../types.js";
4
+ import { BuildContext } from "./buildContext.js";
5
+ //#region src/display-list/build/watermarkPrimitives.d.ts
6
+ type WatermarkPaintOptions = {
7
+ readonly page: Page;
8
+ readonly watermark: document_d_exports.Watermark;
9
+ /** Resolved `data:` source for a picture watermark; absent means unresolved. */
10
+ readonly imageSrc?: string;
11
+ readonly context: BuildContext;
12
+ };
13
+ declare const paintWatermark: ({ page, watermark, imageSrc, context }: WatermarkPaintOptions) => readonly DisplayPrimitive[];
14
+ //#endregion
15
+ export { WatermarkPaintOptions, paintWatermark };