reamkit 0.1.0-alpha.0 → 1.0.0

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 (175) hide show
  1. package/README.md +106 -30
  2. package/dist/esm/{bidi → core/bidi}/algorithm.js +1 -1
  3. package/dist/esm/{bidi → core/bidi}/char-types.js +1 -1
  4. package/dist/esm/{bidi → core/bidi}/index.js +1 -1
  5. package/dist/esm/core/bytes.d.ts +1 -0
  6. package/dist/esm/core/bytes.js +11 -0
  7. package/dist/esm/core/converter/facade.d.ts +45 -0
  8. package/dist/esm/core/converter/facade.js +89 -0
  9. package/dist/esm/core/converter/index.d.ts +4 -0
  10. package/dist/esm/core/converter/project.d.ts +4 -0
  11. package/dist/esm/core/converter/project.js +16 -0
  12. package/dist/esm/core/converter/ream.d.ts +35 -0
  13. package/dist/esm/core/converter/ream.js +100 -0
  14. package/dist/esm/{crypto → core/crypto}/asn1.js +1 -1
  15. package/dist/esm/{crypto → core/crypto}/cms.js +1 -1
  16. package/dist/esm/core/document-model/index.d.ts +1 -0
  17. package/dist/esm/{document-model → core/document-model}/types.d.ts +57 -41
  18. package/dist/esm/{ooxml → core}/drawingml/chart-parser.d.ts +1 -1
  19. package/dist/esm/{ooxml → core}/drawingml/chart-parser.js +6 -29
  20. package/dist/esm/{ooxml → core}/drawingml/colors.d.ts +3 -0
  21. package/dist/esm/{ooxml → core}/drawingml/colors.js +32 -2
  22. package/dist/esm/{ooxml → core}/drawingml/theme-parser.js +2 -2
  23. package/dist/esm/{font → core/font}/arabic-joining.js +1 -1
  24. package/dist/esm/{font → core/font}/binary-reader.js +1 -1
  25. package/dist/esm/{font → core/font}/font-registry.d.ts +1 -0
  26. package/dist/esm/{font → core/font}/font-registry.js +17 -16
  27. package/dist/esm/{font → core/font}/index.d.ts +1 -0
  28. package/dist/esm/{font → core/font}/opentype-layout.js +1 -1
  29. package/dist/esm/{font → core/font}/ttf-parser.js +1 -1
  30. package/dist/esm/{font → core/font}/ttf-subset.js +1 -1
  31. package/dist/esm/core/fonts/provider.d.ts +60 -0
  32. package/dist/esm/core/fonts/provider.js +163 -0
  33. package/dist/esm/{fonts → core/fonts}/remote-fonts.js +1 -1
  34. package/dist/esm/{hyphenation → core/hyphenation}/index.js +1 -1
  35. package/dist/esm/{hyphenation → core/hyphenation}/liang.js +1 -1
  36. package/dist/esm/{hyphenation → core/hyphenation}/patterns-en-us.js +1 -1
  37. package/dist/esm/{hyphenation → core/hyphenation}/patterns-ru.js +1 -1
  38. package/dist/esm/core/ir/adapters.d.ts +37 -0
  39. package/dist/esm/core/ir/features.d.ts +25 -0
  40. package/dist/esm/core/ir/features.js +24 -0
  41. package/dist/esm/core/ir/flow.d.ts +24 -0
  42. package/dist/esm/core/ir/index.d.ts +11 -0
  43. package/dist/esm/core/ir/loss.d.ts +22 -0
  44. package/dist/esm/core/ir/loss.js +15 -0
  45. package/dist/esm/core/ir/resources.d.ts +16 -0
  46. package/dist/esm/core/ir/resources.js +50 -0
  47. package/dist/esm/core/ir/units.d.ts +16 -0
  48. package/dist/esm/core/ir/units.js +41 -0
  49. package/dist/esm/core/line-breaker/index.d.ts +2 -0
  50. package/dist/esm/{line-breaker → core/line-breaker}/knuth-plass.js +1 -1
  51. package/dist/esm/{numbering → core/numbering}/state.js +1 -1
  52. package/dist/esm/{opc → core/opc}/core-properties.js +1 -1
  53. package/dist/esm/{opc → core/opc}/package.js +1 -1
  54. package/dist/esm/{opc → core/opc}/relationship-types.js +1 -1
  55. package/dist/esm/{opc → core/opc}/relationships.js +1 -1
  56. package/dist/esm/{ooxml/wordproc → core}/po-helpers.js +1 -1
  57. package/dist/esm/{style-cascade → core/style-cascade}/index.d.ts +2 -2
  58. package/dist/esm/core/style-cascade/index.js +2 -0
  59. package/dist/esm/{style-cascade → core/style-cascade}/resolver.d.ts +1 -0
  60. package/dist/esm/{style-cascade → core/style-cascade}/resolver.js +14 -9
  61. package/dist/esm/{style-cascade → core/style-cascade}/types.d.ts +8 -7
  62. package/dist/esm/{style-cascade → core/style-cascade}/types.js +9 -8
  63. package/dist/esm/{ooxml/spreadsheet → excel}/cell-reference.js +1 -1
  64. package/dist/esm/{ooxml/spreadsheet → excel}/defined-name-ref.js +1 -1
  65. package/dist/esm/{ooxml/spreadsheet → excel}/index.d.ts +1 -1
  66. package/dist/esm/{ooxml/spreadsheet → excel}/number-format.js +1 -1
  67. package/dist/esm/excel/print-model.d.ts +18 -0
  68. package/dist/esm/{converter/xlsx-to-pdf.js → excel/print-model.js} +39 -148
  69. package/dist/esm/{ooxml/spreadsheet → excel}/shared-strings-parser.js +1 -1
  70. package/dist/esm/{ooxml/spreadsheet → excel}/styles-parser.js +1 -1
  71. package/dist/esm/{ooxml/spreadsheet → excel}/workbook-parser.js +1 -1
  72. package/dist/esm/{ooxml/spreadsheet → excel}/worksheet-parser.js +1 -1
  73. package/dist/esm/excel/xlsx-reader.d.ts +4 -0
  74. package/dist/esm/excel/xlsx-reader.js +91 -0
  75. package/dist/esm/{converter → excel}/xlsx-to-pdf.d.ts +13 -2
  76. package/dist/esm/excel/xlsx-to-pdf.js +69 -0
  77. package/dist/esm/index.d.ts +23 -8
  78. package/dist/esm/index.js +18 -11
  79. package/dist/esm/pdf/chart-geometry.d.ts +1 -1
  80. package/dist/esm/pdf/cid-font.d.ts +7 -1
  81. package/dist/esm/pdf/cid-font.js +33 -22
  82. package/dist/esm/pdf/image-xobject.d.ts +13 -0
  83. package/dist/esm/pdf/image-xobject.js +55 -54
  84. package/dist/esm/pdf/index.d.ts +2 -2
  85. package/dist/esm/pdf/math-layout.d.ts +1 -1
  86. package/dist/esm/pdf/preset-geometry.d.ts +1 -1
  87. package/dist/esm/pdf/signature.js +4 -4
  88. package/dist/esm/pdf/styled-page-emitter.d.ts +5 -0
  89. package/dist/esm/pdf/styled-page-emitter.js +542 -0
  90. package/dist/esm/pdf/styled-page-renderer.d.ts +189 -14
  91. package/dist/esm/pdf/styled-page-renderer.js +168 -654
  92. package/dist/esm/pdf/text-page-renderer.d.ts +1 -1
  93. package/dist/esm/svg/svg-writer.d.ts +8 -0
  94. package/dist/esm/svg/svg-writer.js +138 -0
  95. package/dist/esm/word/document-parser.d.ts +16 -0
  96. package/dist/esm/{ooxml/wordproc → word}/document-parser.js +55 -47
  97. package/dist/esm/word/docx-reader.d.ts +4 -0
  98. package/dist/esm/word/docx-reader.js +190 -0
  99. package/dist/esm/word/docx-to-pdf.d.ts +34 -0
  100. package/dist/esm/word/docx-to-pdf.js +112 -0
  101. package/dist/esm/{ooxml/wordproc → word}/drawing-parser.d.ts +10 -9
  102. package/dist/esm/{ooxml/wordproc → word}/drawing-parser.js +15 -42
  103. package/dist/esm/{ooxml/wordproc → word}/font-table.d.ts +2 -2
  104. package/dist/esm/{ooxml/wordproc → word}/font-table.js +2 -2
  105. package/dist/esm/{ooxml/wordproc → word}/index.d.ts +3 -2
  106. package/dist/esm/{ooxml/wordproc → word}/numbering-parser.d.ts +1 -1
  107. package/dist/esm/{ooxml/wordproc → word}/numbering-parser.js +1 -1
  108. package/dist/esm/{ooxml/math → word}/omml-parser.d.ts +2 -2
  109. package/dist/esm/{ooxml/math → word}/omml-parser.js +2 -2
  110. package/dist/esm/{ooxml/wordproc → word}/paragraph-properties.d.ts +1 -1
  111. package/dist/esm/{ooxml/wordproc → word}/paragraph-properties.js +9 -8
  112. package/dist/esm/{ooxml/wordproc → word}/po-to-flat.d.ts +1 -1
  113. package/dist/esm/{ooxml/wordproc → word}/po-to-flat.js +2 -2
  114. package/dist/esm/{ooxml/wordproc → word}/run-properties.d.ts +1 -1
  115. package/dist/esm/{ooxml/wordproc → word}/run-properties.js +3 -2
  116. package/dist/esm/{ooxml/wordproc → word}/settings-parser.js +2 -2
  117. package/dist/esm/word/styles-parser.d.ts +2 -0
  118. package/dist/esm/{ooxml/wordproc → word}/styles-parser.js +4 -7
  119. package/dist/esm/word/table-parser.d.ts +4 -0
  120. package/dist/esm/{ooxml/wordproc → word}/table-parser.js +80 -26
  121. package/dist/esm/{ooxml/wordproc → word}/xml-helpers.js +1 -1
  122. package/package.json +5 -6
  123. package/dist/esm/converter/docx-to-pdf.d.ts +0 -15
  124. package/dist/esm/converter/docx-to-pdf.js +0 -227
  125. package/dist/esm/converter/index.d.ts +0 -4
  126. package/dist/esm/converter/index.js +0 -2
  127. package/dist/esm/document-model/index.d.ts +0 -1
  128. package/dist/esm/line-breaker/index.d.ts +0 -2
  129. package/dist/esm/ooxml/index.d.ts +0 -1
  130. package/dist/esm/ooxml/wordproc/document-parser.d.ts +0 -9
  131. package/dist/esm/ooxml/wordproc/styles-parser.d.ts +0 -3
  132. package/dist/esm/ooxml/wordproc/table-parser.d.ts +0 -3
  133. /package/dist/esm/{bidi → core/bidi}/algorithm.d.ts +0 -0
  134. /package/dist/esm/{bidi → core/bidi}/char-types.d.ts +0 -0
  135. /package/dist/esm/{bidi → core/bidi}/index.d.ts +0 -0
  136. /package/dist/esm/{crypto → core/crypto}/asn1.d.ts +0 -0
  137. /package/dist/esm/{crypto → core/crypto}/cms.d.ts +0 -0
  138. /package/dist/esm/{crypto → core/crypto}/index.d.ts +0 -0
  139. /package/dist/esm/{crypto → core/crypto}/index.js +0 -0
  140. /package/dist/esm/{document-model → core/document-model}/index.js +0 -0
  141. /package/dist/esm/{ooxml → core}/drawingml/theme-parser.d.ts +0 -0
  142. /package/dist/esm/{font → core/font}/arabic-joining.d.ts +0 -0
  143. /package/dist/esm/{font → core/font}/binary-reader.d.ts +0 -0
  144. /package/dist/esm/{font → core/font}/opentype-layout.d.ts +0 -0
  145. /package/dist/esm/{font → core/font}/ttf-parser.d.ts +0 -0
  146. /package/dist/esm/{font → core/font}/ttf-subset.d.ts +0 -0
  147. /package/dist/esm/{fonts → core/fonts}/index.d.ts +0 -0
  148. /package/dist/esm/{fonts → core/fonts}/remote-fonts.d.ts +0 -0
  149. /package/dist/esm/{hyphenation → core/hyphenation}/index.d.ts +0 -0
  150. /package/dist/esm/{hyphenation → core/hyphenation}/liang.d.ts +0 -0
  151. /package/dist/esm/{hyphenation → core/hyphenation}/patterns-en-us.d.ts +0 -0
  152. /package/dist/esm/{hyphenation → core/hyphenation}/patterns-ru.d.ts +0 -0
  153. /package/dist/esm/{line-breaker → core/line-breaker}/knuth-plass.d.ts +0 -0
  154. /package/dist/esm/{numbering → core/numbering}/index.d.ts +0 -0
  155. /package/dist/esm/{numbering → core/numbering}/state.d.ts +0 -0
  156. /package/dist/esm/{opc → core/opc}/core-properties.d.ts +0 -0
  157. /package/dist/esm/{opc → core/opc}/index.d.ts +0 -0
  158. /package/dist/esm/{opc → core/opc}/index.js +0 -0
  159. /package/dist/esm/{opc → core/opc}/package.d.ts +0 -0
  160. /package/dist/esm/{opc → core/opc}/relationship-types.d.ts +0 -0
  161. /package/dist/esm/{opc → core/opc}/relationships.d.ts +0 -0
  162. /package/dist/esm/{ooxml/wordproc → core}/po-helpers.d.ts +0 -0
  163. /package/dist/esm/{ooxml/spreadsheet → excel}/cell-reference.d.ts +0 -0
  164. /package/dist/esm/{ooxml/spreadsheet → excel}/defined-name-ref.d.ts +0 -0
  165. /package/dist/esm/{ooxml/spreadsheet → excel}/index.js +0 -0
  166. /package/dist/esm/{ooxml/spreadsheet → excel}/number-format.d.ts +0 -0
  167. /package/dist/esm/{ooxml/spreadsheet → excel}/shared-strings-parser.d.ts +0 -0
  168. /package/dist/esm/{ooxml/spreadsheet → excel}/styles-parser.d.ts +0 -0
  169. /package/dist/esm/{ooxml/spreadsheet → excel}/workbook-parser.d.ts +0 -0
  170. /package/dist/esm/{ooxml/spreadsheet → excel}/worksheet-parser.d.ts +0 -0
  171. /package/dist/esm/{ooxml/wordproc → word}/index.js +0 -0
  172. /package/dist/esm/{ooxml/wordproc → word}/settings-parser.d.ts +0 -0
  173. /package/dist/esm/{ooxml/wordproc → word}/text-extractor.d.ts +0 -0
  174. /package/dist/esm/{ooxml/wordproc → word}/text-extractor.js +0 -0
  175. /package/dist/esm/{ooxml/wordproc → word}/xml-helpers.d.ts +0 -0
@@ -1,25 +1,24 @@
1
- import { shapeText } from "../font/opentype-layout.js";
2
- import { resolveFamilyKey } from "../fonts/remote-fonts.js";
3
- import { dict, name, ref, stream, unicodeString } from "./objects.js";
4
- import { embedTtfFont } from "./cid-font.js";
1
+ import { resolveFamilyKey } from "../core/fonts/remote-fonts.js";
2
+ import { shapeText } from "../core/font/opentype-layout.js";
3
+ import { createFontMeasure } from "./cid-font.js";
5
4
  import { PdfDocument } from "./writer.js";
6
- import { computeBidi, reorderVisual } from "../bidi/algorithm.js";
7
- import { analyzeString, hasBidiCharacters, reverseByCodePoint } from "../bidi/index.js";
8
- import { breakLines } from "../line-breaker/knuth-plass.js";
9
- import { NumberingState } from "../numbering/state.js";
10
- import { DEFAULT_RESOLVED_PARAGRAPH, DEFAULT_RESOLVED_RUN } from "../style-cascade/types.js";
11
- import { resolveParagraphProperties, resolveRunProperties } from "../style-cascade/resolver.js";
12
- import { PathBuilder, emitVectorShape } from "./vector-graphics.js";
5
+ import { halfPtToPt } from "../core/ir/units.js";
6
+ import { ResourceStore } from "../core/ir/resources.js";
7
+ import { computeBidi } from "../core/bidi/algorithm.js";
8
+ import { analyzeString, hasBidiCharacters } from "../core/bidi/index.js";
9
+ import { breakLines } from "../core/line-breaker/knuth-plass.js";
10
+ import { NumberingState } from "../core/numbering/state.js";
11
+ import { DEFAULT_RESOLVED_PARAGRAPH, DEFAULT_RESOLVED_RUN } from "../core/style-cascade/types.js";
12
+ import { resolveParagraphProperties, resolveRunProperties } from "../core/style-cascade/resolver.js";
13
+ import "../core/style-cascade/index.js";
14
+ import { PathBuilder } from "./vector-graphics.js";
13
15
  import { arcPoint, arcToBeziers } from "./arc-to-bezier.js";
14
16
  import { buildChartScene } from "./chart-geometry.js";
15
- import { buildSrgbIccProfile } from "./icc-profile.js";
16
- import { embedImage } from "./image-xobject.js";
17
+ import { prepareImage } from "./image-xobject.js";
18
+ import { emitStyledPdf } from "./styled-page-emitter.js";
17
19
  import { layoutMath, mathGlyphSegments, variantStyle } from "./math-layout.js";
18
20
  import { customPaths, presetPaths, rectPath } from "./preset-geometry.js";
19
- import { embedAssociatedFile } from "./embedded-file.js";
20
21
  import { StructTreeBuilder } from "./struct-tree.js";
21
- import { addSignaturePlaceholder } from "./signature.js";
22
- import { buildXmpPacket } from "./xmp.js";
23
22
  //#region src/pdf/styled-page-renderer.ts
24
23
  function parsePdfAProfile(pdfA) {
25
24
  const part = Number(pdfA.charAt(6));
@@ -31,206 +30,87 @@ function parsePdfAProfile(pdfA) {
31
30
  version: part === 1 ? "1.4" : "1.7"
32
31
  };
33
32
  }
34
- var A4_WIDTH = 595;
35
- var A4_HEIGHT = 842;
36
33
  var TWIP_TO_PT = 1 / 20;
37
34
  var EIGHTH_PT = 1 / 8;
38
35
  var DEFAULT_CELL_PADDING_TWIPS = 108;
39
36
  var DEFAULT_BORDER_SIZE_EIGHTH = 4;
40
- var encoder = new TextEncoder();
37
+ new TextEncoder();
38
+ function paintPlan(commands) {
39
+ const fills = [];
40
+ const images = [];
41
+ const borders = [];
42
+ const shapes = [];
43
+ const lines = [];
44
+ for (const c of commands) switch (c.type) {
45
+ case "fill":
46
+ fills.push(c);
47
+ break;
48
+ case "image":
49
+ images.push(c);
50
+ break;
51
+ case "border":
52
+ borders.push(c);
53
+ break;
54
+ case "shape":
55
+ shapes.push(c);
56
+ break;
57
+ case "line":
58
+ lines.push(c);
59
+ break;
60
+ default: assertNeverPageItem(c);
61
+ }
62
+ return {
63
+ fills,
64
+ images,
65
+ borders,
66
+ shapes,
67
+ lines
68
+ };
69
+ }
70
+ function assertNeverPageItem(item) {
71
+ throw new Error(`Unhandled PageItem kind: ${String(item.type)}`);
72
+ }
41
73
  function renderStyledPdf(body, options) {
74
+ return emitStyledPdf(layoutStyledDocument(body, options), options, new PdfDocument());
75
+ }
76
+ function layoutStyledDocument(body, options) {
42
77
  const sectionList = resolveSectionList(body, options);
43
78
  const numberedBody = applyNumbering(body, options.numbering);
44
79
  const numberedHeadersFooters = applyNumberingToHeadersFooters(options.headersFooters, options.numbering);
45
- const doc = new PdfDocument();
46
80
  const pdfaProfile = options.pdfA ? parsePdfAProfile(options.pdfA) : void 0;
47
81
  const tagged = options.tagged === true || (pdfaProfile?.tagged ?? false);
48
82
  const structBuilder = tagged ? new StructTreeBuilder() : void 0;
49
- const fontResources = embedUsedFonts(doc, numberedBody, numberedHeadersFooters, options);
50
- const imageResources = embedUsedImages(doc, numberedBody, numberedHeadersFooters, options);
83
+ const fontResources = collectFontResources(numberedBody, numberedHeadersFooters, options);
84
+ const imageResources = collectImageResources(numberedBody, numberedHeadersFooters, options);
51
85
  const sectionCtxs = sectionList.map((s) => buildSectionContext(s, options, numberedHeadersFooters, fontResources));
52
86
  let sectionIdx = 0;
53
- const renderedPages = paginateSections(numberedBody.map((el, idx) => {
54
- while (sectionIdx < sectionCtxs.length - 1 && idx >= sectionCtxs[sectionIdx].endIndex) sectionIdx++;
55
- const ctx = sectionCtxs[sectionIdx];
56
- return layoutBodyElement(el, options, fontResources, imageResources, ctx.contentWidth, ctx.pageContentHeight);
57
- }), sectionCtxs, structBuilder, options.language ?? "en-US");
58
- const pagesDict = dict({
59
- Type: name("Pages"),
60
- Count: 0,
61
- Kids: []
62
- });
63
- const pagesRef = doc.add(pagesDict);
64
- let firstPageDict;
65
- const fontResourceDict = buildFontResourceDict(fontResources);
66
- const xobjectResourceDict = buildXObjectResourceDict(imageResources);
67
- const resourcesDict = dict({
68
- Font: fontResourceDict,
69
- ...xobjectResourceDict ? { XObject: xobjectResourceDict } : {}
70
- });
71
- let pdfaIccRef;
72
- let transparencyGroup;
73
- if (pdfaProfile) {
74
- pdfaIccRef = doc.add(stream({
75
- N: 3,
76
- Alternate: name("DeviceRGB")
77
- }, buildSrgbIccProfile()));
78
- if (pdfaProfile.part >= 2) transparencyGroup = dict({
79
- S: name("Transparency"),
80
- CS: [name("ICCBased"), ref(pdfaIccRef.id)]
81
- });
82
- }
83
- const pageRefs = [];
84
- renderedPages.forEach((page, pageIndex) => {
85
- let pageTagging;
86
- if (structBuilder) {
87
- const builder = structBuilder;
88
- pageTagging = {
89
- next: 0,
90
- assigned: false,
91
- record: (structId, mcid) => builder.addMcref(structId, pageIndex, mcid),
92
- tagFor: (structId) => builder.node(structId).type
93
- };
94
- }
95
- const contentBytes = emitPageContent(page.commands, pageTagging);
96
- const contentsRef = doc.add(stream({}, contentBytes));
97
- const pageEntries = {
98
- Type: name("Page"),
99
- Parent: ref(pagesRef.id),
100
- MediaBox: [
101
- 0,
102
- 0,
103
- page.width,
104
- page.height
105
- ],
106
- Resources: resourcesDict,
107
- Contents: ref(contentsRef.id)
108
- };
109
- if (transparencyGroup) pageEntries["Group"] = transparencyGroup;
110
- if (pageTagging?.assigned) {
111
- pageEntries["StructParents"] = pageIndex;
112
- pageEntries["Tabs"] = name("S");
113
- }
114
- const pageDictObj = dict(pageEntries);
115
- if (firstPageDict === void 0) firstPageDict = pageDictObj;
116
- pageRefs.push(doc.add(pageDictObj));
117
- });
118
- if (pageRefs.length === 0) {
119
- const fallback = sectionCtxs[0] ?? defaultPageCtx();
120
- const contentsRef = doc.add(stream({}, new Uint8Array(0)));
121
- const fallbackDict = dict({
122
- Type: name("Page"),
123
- Parent: ref(pagesRef.id),
124
- MediaBox: [
125
- 0,
126
- 0,
127
- fallback.pageWidth,
128
- fallback.pageHeight
129
- ],
130
- Resources: resourcesDict,
131
- Contents: ref(contentsRef.id),
132
- ...transparencyGroup ? { Group: transparencyGroup } : {}
133
- });
134
- firstPageDict = fallbackDict;
135
- pageRefs.push(doc.add(fallbackDict));
136
- }
137
- pagesDict.set("Count", pageRefs.length);
138
- pagesDict.set("Kids", pageRefs);
139
- const catalogEntries = {
140
- Type: name("Catalog"),
141
- Pages: ref(pagesRef.id)
142
- };
143
- if (pdfaProfile) {
144
- catalogEntries["OutputIntents"] = [ref(doc.add(dict({
145
- Type: name("OutputIntent"),
146
- S: name("GTS_PDFA1"),
147
- OutputConditionIdentifier: "sRGB",
148
- Info: "sRGB IEC61966-2.1",
149
- DestOutputProfile: ref(pdfaIccRef.id)
150
- })).id)];
151
- catalogEntries["Metadata"] = ref(doc.add(stream({
152
- Type: name("Metadata"),
153
- Subtype: name("XML")
154
- }, buildXmpPacket(xmpFromInfo(options.info, options.pdfA)))).id);
155
- }
156
- if (tagged && structBuilder) {
157
- const structRootRef = structBuilder.emit(doc, pageRefs);
158
- catalogEntries["MarkInfo"] = dict({ Marked: true });
159
- catalogEntries["StructTreeRoot"] = ref(structRootRef.id);
160
- catalogEntries["Lang"] = options.language ?? "en-US";
161
- if (options.info?.title) catalogEntries["ViewerPreferences"] = dict({ DisplayDocTitle: true });
162
- }
163
- if (options.attachments?.length && (!pdfaProfile || pdfaProfile.part === 3)) {
164
- const embedded = options.attachments.map((file) => ({
165
- file,
166
- ref: embedAssociatedFile(doc, file)
167
- }));
168
- catalogEntries["AF"] = embedded.map((e) => ref(e.ref.id));
169
- const sorted = [...embedded].sort((a, b) => a.file.name < b.file.name ? -1 : a.file.name > b.file.name ? 1 : 0);
170
- const names = [];
171
- for (const e of sorted) names.push(e.file.name, ref(e.ref.id));
172
- catalogEntries["Names"] = dict({ EmbeddedFiles: ref(doc.add(dict({ Names: names })).id) });
173
- }
174
- if (options.signaturePlaceholder && firstPageDict) {
175
- const { fieldRef, acroForm } = addSignaturePlaceholder(doc, options.signaturePlaceholder, pageRefs[0]);
176
- firstPageDict.set("Annots", [ref(fieldRef.id)]);
177
- catalogEntries["AcroForm"] = acroForm;
178
- }
179
- const catalogRef = doc.add(dict(catalogEntries));
180
- const infoRef = buildInfoDict(doc, options.info);
181
- return doc.build(catalogRef, infoRef, { ...pdfaProfile ? {
182
- version: pdfaProfile.version,
183
- id: true
184
- } : {} });
185
- }
186
- var DEFAULT_PRODUCER = "Ream";
187
- function xmpFromInfo(info, pdfA) {
188
- const p = pdfA ? parsePdfAProfile(pdfA) : void 0;
189
87
  return {
190
- pdfaPart: p ? String(p.part) : "1",
191
- pdfaConformance: p ? p.level.toUpperCase() : "B",
192
- producer: info?.producer ?? DEFAULT_PRODUCER,
193
- ...info?.title ? { title: info.title } : {},
194
- ...info?.author ? { author: info.author } : {},
195
- ...info?.subject ? { subject: info.subject } : {},
196
- ...info?.keywords ? { keywords: info.keywords } : {},
197
- ...info?.creator ? { creator: info.creator } : {},
198
- ...info?.creationDate ? { createDate: info.creationDate } : {},
199
- ...info?.modificationDate ? { modifyDate: info.modificationDate } : {}
200
- };
201
- }
202
- function buildInfoDict(doc, info) {
203
- const merged = {
204
- ...info,
205
- producer: info?.producer ?? DEFAULT_PRODUCER
88
+ pages: paginateSections(numberedBody.map((el, idx) => {
89
+ while (sectionIdx < sectionCtxs.length - 1 && idx >= sectionCtxs[sectionIdx].endIndex) sectionIdx++;
90
+ const ctx = sectionCtxs[sectionIdx];
91
+ return layoutBodyElement(el, options, fontResources, imageResources, ctx.contentWidth, ctx.pageContentHeight);
92
+ }), sectionCtxs, structBuilder, options.language ?? "en-US"),
93
+ resources: options.resources ?? new ResourceStore(),
94
+ fontResources,
95
+ imageResources,
96
+ structBuilder,
97
+ sectionCtxs,
98
+ pdfaProfile,
99
+ tagged
206
100
  };
207
- const entries = {};
208
- if (merged.title) entries["Title"] = unicodeString(merged.title);
209
- if (merged.author) entries["Author"] = unicodeString(merged.author);
210
- if (merged.subject) entries["Subject"] = unicodeString(merged.subject);
211
- if (merged.keywords) entries["Keywords"] = unicodeString(merged.keywords);
212
- if (merged.creator) entries["Creator"] = unicodeString(merged.creator);
213
- entries["Producer"] = unicodeString(merged.producer);
214
- if (merged.creationDate) entries["CreationDate"] = formatPdfDate(merged.creationDate);
215
- if (merged.modificationDate) entries["ModDate"] = formatPdfDate(merged.modificationDate);
216
- return doc.add(dict(entries));
217
- }
218
- function formatPdfDate(d) {
219
- const pad = (n, w = 2) => String(n).padStart(w, "0");
220
- return `D:${pad(d.getUTCFullYear(), 4)}${pad(d.getUTCMonth() + 1)}${pad(d.getUTCDate())}${pad(d.getUTCHours())}${pad(d.getUTCMinutes())}${pad(d.getUTCSeconds())}Z`;
221
101
  }
222
102
  function resolvePageDimensions(options, section) {
223
- const sectionPageWidth = section?.pageSize !== void 0 ? section.pageSize.widthTwips * TWIP_TO_PT : void 0;
224
- const sectionPageHeight = section?.pageSize !== void 0 ? section.pageSize.heightTwips * TWIP_TO_PT : void 0;
225
- const sectionLeft = section?.margins?.leftTwips !== void 0 ? section.margins.leftTwips * TWIP_TO_PT : void 0;
226
- const sectionRight = section?.margins?.rightTwips !== void 0 ? section.margins.rightTwips * TWIP_TO_PT : void 0;
227
- const sectionTop = section?.margins?.topTwips !== void 0 ? section.margins.topTwips * TWIP_TO_PT : void 0;
228
- const sectionBottom = section?.margins?.bottomTwips !== void 0 ? section.margins.bottomTwips * TWIP_TO_PT : void 0;
229
- const headerOffsetPt = (section?.margins?.headerTwips ?? 720) * TWIP_TO_PT;
230
- const footerOffsetPt = (section?.margins?.footerTwips ?? 720) * TWIP_TO_PT;
103
+ const sectionPageWidth = section?.pageSize !== void 0 ? section.pageSize.width : void 0;
104
+ const sectionPageHeight = section?.pageSize !== void 0 ? section.pageSize.height : void 0;
105
+ const sectionLeft = section?.margins?.left !== void 0 ? section.margins.left : void 0;
106
+ const sectionRight = section?.margins?.right !== void 0 ? section.margins.right : void 0;
107
+ const sectionTop = section?.margins?.top !== void 0 ? section.margins.top : void 0;
108
+ const sectionBottom = section?.margins?.bottom !== void 0 ? section.margins.bottom : void 0;
109
+ const headerOffsetPt = section?.margins?.header ?? 720 * TWIP_TO_PT;
110
+ const footerOffsetPt = section?.margins?.footer ?? 720 * TWIP_TO_PT;
231
111
  return {
232
- pageWidth: options.pageWidth ?? sectionPageWidth ?? A4_WIDTH,
233
- pageHeight: options.pageHeight ?? sectionPageHeight ?? A4_HEIGHT,
112
+ pageWidth: options.pageWidth ?? sectionPageWidth ?? 595,
113
+ pageHeight: options.pageHeight ?? sectionPageHeight ?? 842,
234
114
  marginLeft: options.marginLeft ?? sectionLeft ?? 72,
235
115
  marginRight: options.marginRight ?? sectionRight ?? 72,
236
116
  marginTop: options.marginTop ?? sectionTop ?? 72,
@@ -239,34 +119,6 @@ function resolvePageDimensions(options, section) {
239
119
  footerOffsetPt
240
120
  };
241
121
  }
242
- function defaultPageCtx() {
243
- return {
244
- endIndex: 0,
245
- properties: {
246
- headers: [],
247
- footers: []
248
- },
249
- pageWidth: A4_WIDTH,
250
- pageHeight: A4_HEIGHT,
251
- marginLeft: 72,
252
- marginTop: 72,
253
- marginBottom: 72,
254
- contentWidth: A4_WIDTH - 144,
255
- pageContentHeight: A4_HEIGHT - 144,
256
- headerSet: {
257
- default: [],
258
- first: [],
259
- even: []
260
- },
261
- footerSet: {
262
- default: [],
263
- first: [],
264
- even: []
265
- },
266
- titlePg: false,
267
- evenAndOddHeaders: false
268
- };
269
- }
270
122
  function resolveSectionList(body, options) {
271
123
  if (options.sections && options.sections.length > 0) return options.sections;
272
124
  if (options.section) return [{
@@ -370,14 +222,14 @@ function layoutBodyElement(el, options, fontResources, imageResources, contentWi
370
222
  }
371
223
  var EMU_PER_PT = 12700;
372
224
  function layoutImageBlock(image, imageResources, contentWidth) {
373
- let widthPt = image.widthEmu / EMU_PER_PT;
374
- let heightPt = image.heightEmu / EMU_PER_PT;
225
+ let widthPt = image.width;
226
+ let heightPt = image.height;
375
227
  if (widthPt > contentWidth) {
376
228
  const scale = contentWidth / widthPt;
377
229
  widthPt = contentWidth;
378
230
  heightPt = heightPt * scale;
379
231
  }
380
- const res = imageResources?.get(image.imageId);
232
+ const res = image.resource ? imageResources?.get(image.resource) : void 0;
381
233
  const resolvedAlignment = image.paragraphProperties.alignment ?? "left";
382
234
  return {
383
235
  kind: "image",
@@ -385,8 +237,8 @@ function layoutImageBlock(image, imageResources, contentWidth) {
385
237
  heightPt,
386
238
  resolvedAlignment,
387
239
  resourceName: res?.resourceName ?? "",
388
- spacingBeforePt: (image.paragraphProperties.spacingBeforeTwips ?? 0) * TWIP_TO_PT,
389
- spacingAfterPt: (image.paragraphProperties.spacingAfterTwips ?? 0) * TWIP_TO_PT,
240
+ spacingBeforePt: image.paragraphProperties.spacingBefore ?? 0,
241
+ spacingAfterPt: image.paragraphProperties.spacingAfter ?? 0,
390
242
  ...image.altText ? { altText: image.altText } : {}
391
243
  };
392
244
  }
@@ -394,8 +246,8 @@ var DEFAULT_LINE_WIDTH_EMU = 9525;
394
246
  var DEFAULT_INSET_LR_EMU = 91440;
395
247
  var DEFAULT_INSET_TB_EMU = 45720;
396
248
  function layoutShapeBlock(shape, options, fontResources, imageResources, contentWidth, maxHeight) {
397
- let widthPt = shape.widthEmu / EMU_PER_PT;
398
- let heightPt = shape.heightEmu / EMU_PER_PT;
249
+ let widthPt = shape.width;
250
+ let heightPt = shape.height;
399
251
  if (widthPt > contentWidth && widthPt > 0) {
400
252
  const scale = contentWidth / widthPt;
401
253
  widthPt = contentWidth;
@@ -412,10 +264,10 @@ function layoutShapeBlock(shape, options, fontResources, imageResources, content
412
264
  const t = shape.transform;
413
265
  const pp = shape.paragraphProperties;
414
266
  const text = shape.text;
415
- const insetLeftPt = (text?.insetLeftEmu ?? DEFAULT_INSET_LR_EMU) / EMU_PER_PT;
416
- const insetRightPt = (text?.insetRightEmu ?? DEFAULT_INSET_LR_EMU) / EMU_PER_PT;
417
- const insetTopPt = (text?.insetTopEmu ?? DEFAULT_INSET_TB_EMU) / EMU_PER_PT;
418
- const insetBottomPt = (text?.insetBottomEmu ?? DEFAULT_INSET_TB_EMU) / EMU_PER_PT;
267
+ const insetLeftPt = text?.insetLeft ?? DEFAULT_INSET_LR_EMU / EMU_PER_PT;
268
+ const insetRightPt = text?.insetRight ?? DEFAULT_INSET_LR_EMU / EMU_PER_PT;
269
+ const insetTopPt = text?.insetTop ?? DEFAULT_INSET_TB_EMU / EMU_PER_PT;
270
+ const insetBottomPt = text?.insetBottom ?? DEFAULT_INSET_TB_EMU / EMU_PER_PT;
419
271
  const textLines = [];
420
272
  let textHeightPt = 0;
421
273
  if (text && text.content.length > 0) {
@@ -441,8 +293,8 @@ function layoutShapeBlock(shape, options, fontResources, imageResources, content
441
293
  flipH: t?.flipH ?? false,
442
294
  flipV: t?.flipV ?? false,
443
295
  resolvedAlignment: pp.alignment ?? "left",
444
- spacingBeforePt: (pp.spacingBeforeTwips ?? 0) * TWIP_TO_PT,
445
- spacingAfterPt: (pp.spacingAfterTwips ?? 0) * TWIP_TO_PT,
296
+ spacingBeforePt: pp.spacingBefore ?? 0,
297
+ spacingAfterPt: pp.spacingAfter ?? 0,
446
298
  textLines,
447
299
  textHeightPt,
448
300
  insetLeftPt,
@@ -460,7 +312,7 @@ function buildShapePaths(geometry, widthPt, heightPt) {
460
312
  }
461
313
  function buildStroke(line) {
462
314
  if (!line || line.fill === "none") return void 0;
463
- const widthPt = (line.widthEmu ?? DEFAULT_LINE_WIDTH_EMU) / EMU_PER_PT;
315
+ const widthPt = line.width ?? DEFAULT_LINE_WIDTH_EMU / EMU_PER_PT;
464
316
  const dash = line.dash && line.dash !== "solid" ? dashPattern(line.dash, widthPt) : void 0;
465
317
  const cap = line.cap === "flat" ? "butt" : line.cap;
466
318
  return {
@@ -517,8 +369,8 @@ function buildShapeTransform(pageX, pageY, widthPt, heightPt, rotation60k, flipH
517
369
  ];
518
370
  }
519
371
  function layoutChartBlock(block, options, fontResources, contentWidth, maxHeight) {
520
- let widthPt = block.widthEmu / EMU_PER_PT;
521
- let heightPt = block.heightEmu / EMU_PER_PT;
372
+ let widthPt = block.width;
373
+ let heightPt = block.height;
522
374
  if (widthPt > contentWidth && widthPt > 0) {
523
375
  const scale = contentWidth / widthPt;
524
376
  widthPt = contentWidth;
@@ -544,13 +396,13 @@ function layoutChartBlock(block, options, fontResources, contentWidth, maxHeight
544
396
  heightPt,
545
397
  layout,
546
398
  resolvedAlignment: pp.alignment ?? "left",
547
- spacingBeforePt: (pp.spacingBeforeTwips ?? 0) * TWIP_TO_PT,
548
- spacingAfterPt: (pp.spacingAfterTwips ?? 0) * TWIP_TO_PT,
399
+ spacingBeforePt: pp.spacingBefore ?? 0,
400
+ spacingAfterPt: pp.spacingAfter ?? 0,
549
401
  ...altText ? { altText } : {}
550
402
  };
551
403
  }
552
404
  function buildChartLayout(chart, widthPt, heightPt, font) {
553
- const measure = (text, sizePt) => font.embedded.textWidthPt(text, sizePt);
405
+ const measure = (text, sizePt) => font.measure.textWidthPt(text, sizePt);
554
406
  const scene = buildChartScene(chart, widthPt, heightPt, measure);
555
407
  if (!scene) return {
556
408
  shapes: [{
@@ -630,7 +482,7 @@ function labelPrim(l, font) {
630
482
  };
631
483
  }
632
484
  function makeChartLabelLine(text, font, sizePt, colorHex) {
633
- const widthPt = font.embedded.textWidthPt(text, sizePt);
485
+ const widthPt = font.measure.textWidthPt(text, sizePt);
634
486
  return {
635
487
  tokens: [{
636
488
  kind: "text",
@@ -639,7 +491,7 @@ function makeChartLabelLine(text, font, sizePt, colorHex) {
639
491
  resolvedRun: {
640
492
  ...DEFAULT_RESOLVED_RUN,
641
493
  colorHex,
642
- fontSizeHalfPoints: Math.round(sizePt * 2)
494
+ fontSizePt: halfPtToPt(Math.round(sizePt * 2))
643
495
  },
644
496
  font,
645
497
  fontSizePt: sizePt,
@@ -654,14 +506,15 @@ function makeChartLabelLine(text, font, sizePt, colorHex) {
654
506
  isLastInParagraph: true
655
507
  };
656
508
  }
657
- function embedUsedImages(doc, body, headersFooters, options) {
509
+ function collectImageResources(body, headersFooters, options) {
658
510
  const out = /* @__PURE__ */ new Map();
659
- if (!options.images || options.images.size === 0) return out;
511
+ if (!options.resources || options.resources.size === 0) return out;
660
512
  const seen = /* @__PURE__ */ new Set();
661
513
  const visit = (elements) => {
662
- for (const el of elements) if (el.kind === "image") seen.add(el.image.imageId);
663
- else if (el.kind === "paragraph") {
664
- for (const run of el.paragraph.runs) if (run.inlineImage) seen.add(run.inlineImage.imageId);
514
+ for (const el of elements) if (el.kind === "image") {
515
+ if (el.image.resource) seen.add(el.image.resource);
516
+ } else if (el.kind === "paragraph") {
517
+ for (const run of el.paragraph.runs) if (run.inlineImage?.resource) seen.add(run.inlineImage.resource);
665
518
  } else if (el.kind === "table") for (const row of el.table.rows) for (const cell of row.cells) visit(cell.content);
666
519
  else if (el.kind === "shape") {
667
520
  if (el.shape.text) visit(el.shape.text.content);
@@ -671,19 +524,19 @@ function embedUsedImages(doc, body, headersFooters, options) {
671
524
  for (const hf of headersFooters.values()) visit(hf);
672
525
  const flattenAlpha = options.pdfA ? parsePdfAProfile(options.pdfA).part === 1 : false;
673
526
  let counter = 0;
674
- for (const imageId of seen) {
675
- const bytes = options.images.get(imageId);
527
+ for (const resourceId of seen) {
528
+ const bytes = options.resources.get(resourceId);
676
529
  if (!bytes) continue;
677
- let embedded;
530
+ let prepared;
678
531
  try {
679
- embedded = embedImage(doc, bytes, { flattenAlpha });
532
+ prepared = prepareImage(bytes, { flattenAlpha });
680
533
  } catch {
681
534
  continue;
682
535
  }
683
536
  counter++;
684
- out.set(imageId, {
537
+ out.set(resourceId, {
685
538
  resourceName: `Im${counter}`,
686
- ref: embedded.ref
539
+ prepared
687
540
  });
688
541
  }
689
542
  return out;
@@ -697,7 +550,7 @@ function drawBlocksSequentially(blocks, startX, startY) {
697
550
  for (const line of block.lines) {
698
551
  const h = computeLineHeight(line, block.resolved);
699
552
  cursorY -= h;
700
- const indentLeft = block.resolved.indentLeftTwips * TWIP_TO_PT + (line.firstLine ? block.resolved.indentFirstLineTwips * TWIP_TO_PT : 0);
553
+ const indentLeft = block.resolved.indentLeft + (line.firstLine ? block.resolved.indentFirstLine : 0);
701
554
  const offset = alignmentOffset(block.resolved.alignment, line.contentWidthPt, line.availableWidthPt);
702
555
  out.push({
703
556
  type: "line",
@@ -756,9 +609,9 @@ function applyNumbering(body, numbering) {
756
609
  function mergeIndentFromLevel(paragraphProps, levelProps) {
757
610
  if (!levelProps) return paragraphProps;
758
611
  const out = { ...paragraphProps };
759
- if (out.indentLeftTwips === void 0 && levelProps.indentLeftTwips !== void 0) out.indentLeftTwips = levelProps.indentLeftTwips;
760
- if (out.indentRightTwips === void 0 && levelProps.indentRightTwips !== void 0) out.indentRightTwips = levelProps.indentRightTwips;
761
- if (out.indentFirstLineTwips === void 0 && levelProps.indentFirstLineTwips !== void 0) out.indentFirstLineTwips = levelProps.indentFirstLineTwips;
612
+ if (out.indentLeft === void 0 && levelProps.indentLeft !== void 0) out.indentLeft = levelProps.indentLeft;
613
+ if (out.indentRight === void 0 && levelProps.indentRight !== void 0) out.indentRight = levelProps.indentRight;
614
+ if (out.indentFirstLine === void 0 && levelProps.indentFirstLine !== void 0) out.indentFirstLine = levelProps.indentFirstLine;
762
615
  return out;
763
616
  }
764
617
  function runFontKeyAndParsed(options, ascii, bold, italic) {
@@ -796,7 +649,7 @@ function runFontKeyAndParsed(options, ascii, bold, italic) {
796
649
  function lookupFont(resources, fontKey) {
797
650
  return resources.get(fontKey) ?? resources.values().next().value;
798
651
  }
799
- function embedUsedFonts(doc, body, headersFooters, options) {
652
+ function collectFontResources(body, headersFooters, options) {
800
653
  const used = /* @__PURE__ */ new Map();
801
654
  const addRun = (run, para) => {
802
655
  const resolved = resolveRunProperties(run.properties, para.properties, options.styles);
@@ -870,35 +723,20 @@ function embedUsedFonts(doc, body, headersFooters, options) {
870
723
  gids: new Set([0])
871
724
  });
872
725
  }
873
- const cidSet = options.pdfA ? parsePdfAProfile(options.pdfA).part === 1 : false;
874
726
  const out = /* @__PURE__ */ new Map();
875
727
  let counter = 0;
876
728
  for (const [variant, info] of used) {
877
729
  counter++;
878
730
  const resourceName = `F${counter}`;
879
- const embedded = embedTtfFont(doc, info.parsed, {
880
- usedGids: info.gids,
881
- cidSet
882
- });
883
731
  out.set(variant, {
884
732
  resourceName,
885
733
  parsed: info.parsed,
886
- embedded
734
+ measure: createFontMeasure(info.parsed),
735
+ gids: info.gids
887
736
  });
888
737
  }
889
738
  return out;
890
739
  }
891
- function buildFontResourceDict(resources) {
892
- const entries = {};
893
- for (const res of resources.values()) entries[res.resourceName] = ref(res.embedded.fontRef.id);
894
- return dict(entries);
895
- }
896
- function buildXObjectResourceDict(resources) {
897
- if (resources.size === 0) return void 0;
898
- const entries = {};
899
- for (const res of resources.values()) entries[res.resourceName] = ref(res.ref.id);
900
- return dict(entries);
901
- }
902
740
  function layoutParagraphBlock(paragraph, options, fontResources, imageResources, contentWidth) {
903
741
  const baseResolved = resolveParagraphProperties(paragraph.properties, options.styles);
904
742
  const baseDir = paragraphBaseDirection(paragraph, baseResolved);
@@ -915,8 +753,8 @@ function layoutParagraphBlock(paragraph, options, fontResources, imageResources,
915
753
  resolved,
916
754
  lines,
917
755
  heightPt,
918
- spacingBeforePt: resolved.spacingBeforeTwips * TWIP_TO_PT,
919
- spacingAfterPt: resolved.spacingAfterTwips * TWIP_TO_PT,
756
+ spacingBeforePt: resolved.spacingBefore,
757
+ spacingAfterPt: resolved.spacingAfter,
920
758
  ...numbering ? { list: {
921
759
  numId: numbering.numId,
922
760
  level: numbering.ilvl
@@ -956,18 +794,18 @@ function resolveMathItems(items, fontFor) {
956
794
  function tokenizeParagraph(paragraph, options, fontResources, imageResources, contentWidth, baseDir) {
957
795
  const plans = paragraph.runs.map((run) => {
958
796
  if (run.inlineImage) {
959
- const naturalW = run.inlineImage.widthEmu / EMU_PER_PT;
797
+ const naturalW = run.inlineImage.width;
960
798
  const widthPt = Math.min(naturalW, contentWidth);
961
799
  const scale = naturalW > 0 ? widthPt / naturalW : 1;
962
- const heightPt = run.inlineImage.heightEmu / EMU_PER_PT * scale;
963
- const res = imageResources?.get(run.inlineImage.imageId);
800
+ const heightPt = run.inlineImage.height * scale;
801
+ const res = run.inlineImage.resource ? imageResources?.get(run.inlineImage.resource) : void 0;
964
802
  const resolvedRun = resolveRunProperties(run.properties, paragraph.properties, options.styles);
965
803
  const { fontKey } = runFontKeyAndParsed(options, resolvedRun.fontFamily.ascii, resolvedRun.bold, resolvedRun.italic);
966
804
  return {
967
805
  run,
968
806
  resolvedRun,
969
807
  font: lookupFont(fontResources, fontKey),
970
- fontSizePt: resolvedRun.fontSizeHalfPoints / 2,
808
+ fontSizePt: resolvedRun.fontSizePt,
971
809
  isImage: true,
972
810
  imageWidthPt: widthPt,
973
811
  imageHeightPt: heightPt,
@@ -976,13 +814,13 @@ function tokenizeParagraph(paragraph, options, fontResources, imageResources, co
976
814
  }
977
815
  if (run.math) {
978
816
  const resolvedRun = resolveRunProperties(run.properties, paragraph.properties, options.styles);
979
- const sizePt = resolvedRun.fontSizeHalfPoints / 2;
817
+ const sizePt = resolvedRun.fontSizePt;
980
818
  const fontFor = (v) => {
981
819
  const { bold, italic } = variantStyle(v);
982
820
  const r = options.registry.resolveByStyle(bold, italic);
983
821
  return fontResources.get(r.variant) ?? fontResources.get(options.registry.resolveByStyle(false, false).variant);
984
822
  };
985
- const measure = (text, sz, v) => fontFor(v).embedded.textWidthPt(text, sz);
823
+ const measure = (text, sz, v) => fontFor(v).measure.textWidthPt(text, sz);
986
824
  const box = layoutMath(run.math, { sizePt }, measure);
987
825
  const { variant } = options.registry.resolveByStyle(resolvedRun.bold, resolvedRun.italic);
988
826
  return {
@@ -1008,7 +846,7 @@ function tokenizeParagraph(paragraph, options, fontResources, imageResources, co
1008
846
  run,
1009
847
  resolvedRun,
1010
848
  font: lookupFont(fontResources, fontKey),
1011
- fontSizePt: resolvedRun.fontSizeHalfPoints / 2,
849
+ fontSizePt: resolvedRun.fontSizePt,
1012
850
  isImage: false,
1013
851
  imageWidthPt: 0,
1014
852
  imageHeightPt: 0,
@@ -1083,7 +921,7 @@ function tokenizePlansLtr(plans) {
1083
921
  resolvedRun: plan.resolvedRun,
1084
922
  font: plan.font,
1085
923
  fontSizePt: plan.fontSizePt,
1086
- widthPt: plan.font.embedded.textWidthPt(t.text, plan.fontSizePt),
924
+ widthPt: plan.font.measure.textWidthPt(t.text, plan.fontSizePt),
1087
925
  bidiLevel: 0
1088
926
  });
1089
927
  }
@@ -1133,7 +971,7 @@ function tokenizePlansBidi(plans, realLevels) {
1133
971
  resolvedRun: plan.resolvedRun,
1134
972
  font: plan.font,
1135
973
  fontSizePt: plan.fontSizePt,
1136
- widthPt: plan.font.embedded.textWidthPt(text, plan.fontSizePt),
974
+ widthPt: plan.font.measure.textWidthPt(text, plan.fontSizePt),
1137
975
  bidiLevel: curLevel
1138
976
  });
1139
977
  };
@@ -1167,9 +1005,9 @@ function paragraphBaseDirection(paragraph, resolved) {
1167
1005
  return analyzeString(text, "auto").paragraphLevel === 1 ? "rtl" : "ltr";
1168
1006
  }
1169
1007
  function paragraphMaxWidth(p, contentWidth, firstLine) {
1170
- const indentLeft = p.indentLeftTwips * TWIP_TO_PT;
1171
- const indentRight = p.indentRightTwips * TWIP_TO_PT;
1172
- const firstLineExtra = firstLine ? p.indentFirstLineTwips * TWIP_TO_PT : 0;
1008
+ const indentLeft = p.indentLeft;
1009
+ const indentRight = p.indentRight;
1010
+ const firstLineExtra = firstLine ? p.indentFirstLine : 0;
1173
1011
  return Math.max(1, contentWidth - indentLeft - indentRight - firstLineExtra);
1174
1012
  }
1175
1013
  function tokenizeText(text) {
@@ -1222,12 +1060,12 @@ function wrap(tokens, firstLineWidth, otherWidth, resolved, hyphenator) {
1222
1060
  }, tok);
1223
1061
  continue;
1224
1062
  }
1225
- const hyphenWidth = tok.font.embedded.textWidthPt("-", tok.fontSizePt);
1063
+ const hyphenWidth = tok.font.measure.textWidthPt("-", tok.fontSizePt);
1226
1064
  let prev = 0;
1227
1065
  for (let pi = 0; pi <= positions.length; pi++) {
1228
1066
  const end = pi < positions.length ? positions[pi] : tok.text.length;
1229
1067
  const fragText = tok.text.substring(prev, end);
1230
- const fragWidth = tok.font.embedded.textWidthPt(fragText, tok.fontSizePt);
1068
+ const fragWidth = tok.font.measure.textWidthPt(fragText, tok.fontSizePt);
1231
1069
  const fragTok = {
1232
1070
  kind: "text",
1233
1071
  text: fragText,
@@ -1325,9 +1163,10 @@ function computeLineHeight(line, p) {
1325
1163
  const fontSize = line.maxFontSizePt || 12;
1326
1164
  const mathH = (line.mathAscentPt ?? 0) + (line.mathDescentPt ?? 0);
1327
1165
  const mathNeed = mathH > 0 ? mathH * 1.05 : 0;
1328
- if (p.spacingLineRule === "exact" && p.spacingLineTwips > 0) return Math.max(p.spacingLineTwips * TWIP_TO_PT, mathNeed);
1329
- if (p.spacingLineRule === "atLeast" && p.spacingLineTwips > 0) return Math.max(fontSize * 1.2, p.spacingLineTwips * TWIP_TO_PT, mathNeed);
1330
- const multiple = p.spacingLineTwips > 0 ? p.spacingLineTwips / 240 : 1;
1166
+ if (p.spacingLineRule === "exact" && p.spacingLine > 0) return Math.max(p.spacingLine, mathNeed);
1167
+ if (p.spacingLineRule === "atLeast" && p.spacingLine > 0) return Math.max(fontSize * 1.2, p.spacingLine, mathNeed);
1168
+ const lineTwips = Math.round(p.spacingLine * 20);
1169
+ const multiple = lineTwips > 0 ? lineTwips / 240 : 1;
1331
1170
  return Math.max(fontSize * 1.2 * multiple, mathNeed);
1332
1171
  }
1333
1172
  function lineDescent(line) {
@@ -1341,7 +1180,7 @@ function alignmentOffset(alignment, lineWidth, available) {
1341
1180
  }
1342
1181
  function layoutTableBlock(table, options, fontResources, imageResources, contentWidth) {
1343
1182
  const columnWidthsPt = computeColumnWidths(table, options, fontResources, contentWidth);
1344
- const mergeRoles = computeMergeRoles(table);
1183
+ const mergeRoles = table.rows.map((r) => r.cells.map((c) => c.properties.merge ?? "standalone"));
1345
1184
  const rows = [];
1346
1185
  const colCount = columnWidthsPt.length;
1347
1186
  let aboveBordersByCol = [];
@@ -1350,7 +1189,7 @@ function layoutTableBlock(table, options, fontResources, imageResources, content
1350
1189
  const nextAbove = [];
1351
1190
  let ci = 0;
1352
1191
  for (const cell of table.rows[r].cells) {
1353
- const span = Math.max(1, cell.properties.gridSpan ?? 1);
1192
+ const span = Math.max(1, cell.properties.colSpan ?? 1);
1354
1193
  for (let k = 0; k < span; k++) nextAbove[ci + k] = cell.properties.borders;
1355
1194
  ci += span;
1356
1195
  }
@@ -1378,43 +1217,11 @@ function tableXOffset(alignment, contentWidth, totalWidthPt) {
1378
1217
  if (slack <= 0 || !alignment || alignment === "left") return 0;
1379
1218
  return alignment === "center" ? slack / 2 : slack;
1380
1219
  }
1381
- function computeMergeRoles(table) {
1382
- const out = table.rows.map((r) => new Array(r.cells.length).fill("standalone"));
1383
- const colSlots = /* @__PURE__ */ new Map();
1384
- for (let rowIdx = 0; rowIdx < table.rows.length; rowIdx++) {
1385
- const row = table.rows[rowIdx];
1386
- let colIdx = 0;
1387
- for (let cellIdx = 0; cellIdx < row.cells.length; cellIdx++) {
1388
- const cell = row.cells[cellIdx];
1389
- let arr = colSlots.get(colIdx);
1390
- if (!arr) {
1391
- arr = [];
1392
- colSlots.set(colIdx, arr);
1393
- }
1394
- arr.push({
1395
- rowIdx,
1396
- cellIdx,
1397
- vMerge: cell.properties.vMerge
1398
- });
1399
- colIdx += Math.max(1, cell.properties.gridSpan ?? 1);
1400
- }
1401
- }
1402
- for (const slots of colSlots.values()) for (let i = 0; i < slots.length; i++) {
1403
- const cur = slots[i];
1404
- const next = slots[i + 1];
1405
- const nextIsContinue = !!next && next.vMerge === "continue";
1406
- let role = "standalone";
1407
- if (cur.vMerge === "restart") role = nextIsContinue ? "start" : "standalone";
1408
- else if (cur.vMerge === "continue") role = nextIsContinue ? "middle" : "end";
1409
- out[cur.rowIdx][cur.cellIdx] = role;
1410
- }
1411
- return out;
1412
- }
1413
1220
  function computeColumnWidths(table, options, fontResources, contentWidth) {
1414
1221
  let colCount = table.grid.length;
1415
1222
  for (const row of table.rows) {
1416
1223
  let rowCols = 0;
1417
- for (const cell of row.cells) rowCols += Math.max(1, cell.properties.gridSpan ?? 1);
1224
+ for (const cell of row.cells) rowCols += Math.max(1, cell.properties.colSpan ?? 1);
1418
1225
  if (rowCols > colCount) colCount = rowCols;
1419
1226
  }
1420
1227
  if (colCount === 0) return [];
@@ -1424,9 +1231,9 @@ function computeColumnWidths(table, options, fontResources, contentWidth) {
1424
1231
  let colIdx = 0;
1425
1232
  for (let i = 0; i < row.cells.length; i++) {
1426
1233
  const cell = row.cells[i];
1427
- const span = Math.max(1, cell.properties.gridSpan ?? 1);
1428
- const padLeft = (cell.properties.margins?.leftTwips ?? table.properties.defaultCellMargins?.leftTwips ?? DEFAULT_CELL_PADDING_TWIPS) * TWIP_TO_PT;
1429
- const padRight = (cell.properties.margins?.rightTwips ?? table.properties.defaultCellMargins?.rightTwips ?? DEFAULT_CELL_PADDING_TWIPS) * TWIP_TO_PT;
1234
+ const span = Math.max(1, cell.properties.colSpan ?? 1);
1235
+ const padLeft = cell.properties.margins?.left ?? table.properties.defaultCellMargins?.left ?? DEFAULT_CELL_PADDING_TWIPS * TWIP_TO_PT;
1236
+ const padRight = cell.properties.margins?.right ?? table.properties.defaultCellMargins?.right ?? DEFAULT_CELL_PADDING_TWIPS * TWIP_TO_PT;
1430
1237
  let maxContent = 0;
1431
1238
  for (const el of cell.content) {
1432
1239
  if (el.kind !== "paragraph") continue;
@@ -1451,11 +1258,15 @@ function computeColumnWidths(table, options, fontResources, contentWidth) {
1451
1258
  }
1452
1259
  return colNaturalWidths;
1453
1260
  }
1261
+ function gridColTwips(table) {
1262
+ return table.grid.map((w) => Math.round(w * 20));
1263
+ }
1454
1264
  function gridWidthsScaled(table, contentWidth, colCount) {
1455
- const totalGridTwips = table.grid.reduce((s, w) => s + w, 0);
1265
+ const gridTwips = gridColTwips(table);
1266
+ const totalGridTwips = gridTwips.reduce((s, w) => s + w, 0);
1456
1267
  if (totalGridTwips > 0) {
1457
1268
  const target = totalTableTarget(table, contentWidth);
1458
- return table.grid.map((w) => w / totalGridTwips * target);
1269
+ return gridTwips.map((w) => w / totalGridTwips * target);
1459
1270
  }
1460
1271
  const each = contentWidth / colCount;
1461
1272
  return new Array(colCount).fill(each);
@@ -1463,15 +1274,16 @@ function gridWidthsScaled(table, contentWidth, colCount) {
1463
1274
  function totalTableTarget(table, contentWidth) {
1464
1275
  const explicit = explicitTableTargetWidth(table, contentWidth);
1465
1276
  if (explicit !== void 0 && explicit > 0) return explicit;
1466
- const sum = table.grid.reduce((s, g) => s + g, 0);
1277
+ const sum = gridColTwips(table).reduce((s, g) => s + g, 0);
1467
1278
  if (sum > 0) return sum * TWIP_TO_PT;
1468
1279
  return contentWidth;
1469
1280
  }
1470
1281
  function explicitTableTargetWidth(table, contentWidth) {
1471
- const w = table.properties.widthTwips;
1282
+ const w = table.properties.widthPt;
1472
1283
  const type = table.properties.widthType;
1473
- if (w !== void 0 && w > 0 && type === "dxa") return w * TWIP_TO_PT;
1474
- if (w !== void 0 && type === "pct") return w / 5e3 * contentWidth;
1284
+ if (w !== void 0 && w > 0 && type === "dxa") return w;
1285
+ const f = table.properties.widthFraction;
1286
+ if (f !== void 0 && type === "pct") return f * contentWidth;
1475
1287
  }
1476
1288
  function measureSingleLine(paragraph, options, fontResources) {
1477
1289
  let total = 0;
@@ -1479,8 +1291,8 @@ function measureSingleLine(paragraph, options, fontResources) {
1479
1291
  const resolved = resolveRunProperties(run.properties, paragraph.properties, options.styles);
1480
1292
  const { variant } = options.registry.resolveByStyle(resolved.bold, resolved.italic);
1481
1293
  const font = fontResources.get(variant);
1482
- const fontSizePt = resolved.fontSizeHalfPoints / 2;
1483
- total += font.embedded.textWidthPt(run.text, fontSizePt);
1294
+ const fontSizePt = resolved.fontSizePt;
1295
+ total += font.measure.textWidthPt(run.text, fontSizePt);
1484
1296
  }
1485
1297
  return total;
1486
1298
  }
@@ -1491,7 +1303,7 @@ function layoutTableRow(row, rowIdx, rowCount, colCount, tableProps, columnWidth
1491
1303
  let colIdx = 0;
1492
1304
  for (let cellIdx = 0; cellIdx < row.cells.length; cellIdx++) {
1493
1305
  const cell = row.cells[cellIdx];
1494
- const span = Math.max(1, cell.properties.gridSpan ?? 1);
1306
+ const span = Math.max(1, cell.properties.colSpan ?? 1);
1495
1307
  let widthPt = 0;
1496
1308
  for (let k = 0; k < span && colIdx + k < columnWidthsPt.length; k++) widthPt += columnWidthsPt[colIdx + k];
1497
1309
  columnXOffsets.push(cursorX);
@@ -1504,8 +1316,8 @@ function layoutTableRow(row, rowIdx, rowCount, colCount, tableProps, columnWidth
1504
1316
  }
1505
1317
  let heightPt = 0;
1506
1318
  for (const c of cells) if (c.totalHeightPt > heightPt) heightPt = c.totalHeightPt;
1507
- if (row.properties.heightTwips && row.properties.heightRule === "exact") heightPt = row.properties.heightTwips * TWIP_TO_PT;
1508
- else if (row.properties.heightTwips && row.properties.heightRule === "atLeast") heightPt = Math.max(heightPt, row.properties.heightTwips * TWIP_TO_PT);
1319
+ if (row.properties.height && row.properties.heightRule === "exact") heightPt = row.properties.height;
1320
+ else if (row.properties.height && row.properties.heightRule === "atLeast") heightPt = Math.max(heightPt, row.properties.height);
1509
1321
  return {
1510
1322
  heightPt,
1511
1323
  cells,
@@ -1517,10 +1329,10 @@ function layoutTableRow(row, rowIdx, rowCount, colCount, tableProps, columnWidth
1517
1329
  function layoutTableCell(cell, tableProps, widthPt, options, fontResources, imageResources, rowIdx, colStart, colSpan, rowCount, colCount, mergeRole, leftNeighborBorders, aboveNeighborBorders) {
1518
1330
  const cellMar = cell.properties.margins;
1519
1331
  const tableMar = tableProps.defaultCellMargins;
1520
- const padTopPt = (cellMar?.topTwips ?? tableMar?.topTwips ?? 0) * TWIP_TO_PT;
1521
- const padBottomPt = (cellMar?.bottomTwips ?? tableMar?.bottomTwips ?? 0) * TWIP_TO_PT;
1522
- const padLeftPt = (cellMar?.leftTwips ?? tableMar?.leftTwips ?? DEFAULT_CELL_PADDING_TWIPS) * TWIP_TO_PT;
1523
- const padRightPt = (cellMar?.rightTwips ?? tableMar?.rightTwips ?? DEFAULT_CELL_PADDING_TWIPS) * TWIP_TO_PT;
1332
+ const padTopPt = cellMar?.top ?? tableMar?.top ?? 0;
1333
+ const padBottomPt = cellMar?.bottom ?? tableMar?.bottom ?? 0;
1334
+ const padLeftPt = cellMar?.left ?? tableMar?.left ?? DEFAULT_CELL_PADDING_TWIPS * TWIP_TO_PT;
1335
+ const padRightPt = cellMar?.right ?? tableMar?.right ?? DEFAULT_CELL_PADDING_TWIPS * TWIP_TO_PT;
1524
1336
  const innerWidth = Math.max(1, widthPt - padLeftPt - padRightPt);
1525
1337
  const lines = [];
1526
1338
  const nestedTables = [];
@@ -1569,7 +1381,7 @@ var BORDER_STYLE_RANK = {
1569
1381
  };
1570
1382
  function borderWeight(b) {
1571
1383
  if (!b || b.style === "none") return 0;
1572
- return b.sizeEighthPt ?? 4;
1384
+ return b.width ?? .5;
1573
1385
  }
1574
1386
  function heavierBorder(a, b) {
1575
1387
  const wa = borderWeight(a);
@@ -1715,7 +1527,7 @@ function paginateSections(blocks, sectionCtxs, builder, defaultLang = "en-US") {
1715
1527
  const h = computeLineHeight(line, block.resolved);
1716
1528
  if (cursorY - h < ctx.marginBottom && current.length > 0) flushPage();
1717
1529
  cursorY -= h;
1718
- const indentLeft = block.resolved.indentLeftTwips * TWIP_TO_PT + (line.firstLine ? block.resolved.indentFirstLineTwips * TWIP_TO_PT : 0);
1530
+ const indentLeft = block.resolved.indentLeft + (line.firstLine ? block.resolved.indentFirstLine : 0);
1719
1531
  const offset = alignmentOffset(block.resolved.alignment, line.contentWidthPt, line.availableWidthPt);
1720
1532
  current.push({
1721
1533
  type: "line",
@@ -1998,7 +1810,7 @@ function splitRowIntoChunks(row, capacity) {
1998
1810
  function emitCellBorders(out, cell, cellX, cellY, rowHeight, rowIdx, rowCount, colCount) {
1999
1811
  const pushSide = (side, border) => {
2000
1812
  if (!border || border.style === "none") return;
2001
- const sz = (border.sizeEighthPt ?? DEFAULT_BORDER_SIZE_EIGHTH) * EIGHTH_PT;
1813
+ const sz = border.width ?? DEFAULT_BORDER_SIZE_EIGHTH * EIGHTH_PT;
2002
1814
  out.push({
2003
1815
  type: "border",
2004
1816
  side,
@@ -2015,303 +1827,5 @@ function emitCellBorders(out, cell, cellX, cellY, rowHeight, rowIdx, rowCount, c
2015
1827
  if (rowIdx === rowCount - 1) pushSide("bottom", cell.borders.bottom);
2016
1828
  if (cell.colStart + cell.colSpan - 1 === colCount - 1) pushSide("right", cell.borders.right);
2017
1829
  }
2018
- function emitTaggedRuns(out, cmds, tagging, body) {
2019
- if (!tagging) {
2020
- for (const c of cmds) body(c);
2021
- return;
2022
- }
2023
- let openKey = null;
2024
- const close = () => {
2025
- if (openKey !== null) {
2026
- out.push("EMC");
2027
- openKey = null;
2028
- }
2029
- };
2030
- for (const c of cmds) {
2031
- const key = c.structId !== void 0 ? `f${c.structId}` : c.artifact === "pagination" ? "p" : "a";
2032
- if (key !== openKey) {
2033
- close();
2034
- if (c.structId !== void 0) {
2035
- const mcid = tagging.next++;
2036
- tagging.assigned = true;
2037
- tagging.record(c.structId, mcid);
2038
- out.push(`/${tagging.tagFor(c.structId)} <</MCID ${mcid}>> BDC`);
2039
- } else if (c.artifact === "pagination") out.push("/Artifact <</Type /Pagination>> BDC");
2040
- else out.push("/Artifact BMC");
2041
- openKey = key;
2042
- }
2043
- body(c);
2044
- }
2045
- close();
2046
- }
2047
- function emitPageContent(commands, tagging) {
2048
- if (commands.length === 0) return new Uint8Array(0);
2049
- const out = [];
2050
- const fills = commands.filter((c) => c.type === "fill");
2051
- if (fills.length > 0) {
2052
- if (tagging) out.push("/Artifact BMC");
2053
- out.push("q");
2054
- let lastColor = "";
2055
- for (const f of fills) {
2056
- const color = f.fillColorHex;
2057
- if (color !== lastColor) {
2058
- const [r, g, b] = hexToRgb01(color);
2059
- out.push(`${formatNumber(r)} ${formatNumber(g)} ${formatNumber(b)} rg`);
2060
- lastColor = color;
2061
- }
2062
- out.push(`${formatNumber(f.x)} ${formatNumber(f.y)} ${formatNumber(f.width)} ${formatNumber(f.height)} re`);
2063
- out.push("f");
2064
- }
2065
- out.push("Q");
2066
- if (tagging) out.push("EMC");
2067
- }
2068
- emitTaggedRuns(out, commands.filter((c) => c.type === "image" && !!c.imageResourceName), tagging, (img) => {
2069
- out.push("q");
2070
- out.push(`${formatNumber(img.width)} 0 0 ${formatNumber(img.height)} ${formatNumber(img.x)} ${formatNumber(img.y)} cm`);
2071
- out.push(`/${img.imageResourceName} Do`);
2072
- out.push("Q");
2073
- });
2074
- const borders = commands.filter((c) => c.type === "border");
2075
- if (borders.length > 0) {
2076
- if (tagging) out.push("/Artifact BMC");
2077
- out.push("q");
2078
- let lastWidth = -1;
2079
- let lastColor = "";
2080
- for (const b of borders) {
2081
- const width = b.borderSizePt;
2082
- const color = b.borderColorHex;
2083
- if (width !== lastWidth) {
2084
- out.push(`${formatNumber(width)} w`);
2085
- lastWidth = width;
2086
- }
2087
- if (color !== lastColor) {
2088
- const [r, g, bl] = hexToRgb01(color);
2089
- out.push(`${formatNumber(r)} ${formatNumber(g)} ${formatNumber(bl)} RG`);
2090
- lastColor = color;
2091
- }
2092
- const x = b.x;
2093
- const y = b.y;
2094
- const w = b.width;
2095
- const h = b.height;
2096
- switch (b.side) {
2097
- case "top":
2098
- out.push(`${formatNumber(x)} ${formatNumber(y + h)} m`);
2099
- out.push(`${formatNumber(x + w)} ${formatNumber(y + h)} l`);
2100
- break;
2101
- case "bottom":
2102
- out.push(`${formatNumber(x)} ${formatNumber(y)} m`);
2103
- out.push(`${formatNumber(x + w)} ${formatNumber(y)} l`);
2104
- break;
2105
- case "left":
2106
- out.push(`${formatNumber(x)} ${formatNumber(y)} m`);
2107
- out.push(`${formatNumber(x)} ${formatNumber(y + h)} l`);
2108
- break;
2109
- case "right":
2110
- out.push(`${formatNumber(x + w)} ${formatNumber(y)} m`);
2111
- out.push(`${formatNumber(x + w)} ${formatNumber(y + h)} l`);
2112
- break;
2113
- }
2114
- out.push("S");
2115
- }
2116
- out.push("Q");
2117
- if (tagging) out.push("EMC");
2118
- }
2119
- emitTaggedRuns(out, commands.filter((c) => c.type === "shape"), tagging, (sh) => {
2120
- for (const op of emitVectorShape(sh.shape)) out.push(op);
2121
- });
2122
- const lines = commands.filter((c) => c.type === "line");
2123
- if (lines.length > 0) {
2124
- let inBT = false;
2125
- let lastFont = "";
2126
- let lastSize = -1;
2127
- let lastColor = "";
2128
- const switchFontIfNeeded = (tok) => {
2129
- const fontKey = tok.font.resourceName;
2130
- if (fontKey !== lastFont || tok.fontSizePt !== lastSize) {
2131
- out.push(`/${fontKey} ${formatNumber(tok.fontSizePt)} Tf`);
2132
- lastFont = fontKey;
2133
- lastSize = tok.fontSizePt;
2134
- }
2135
- if (tok.resolvedRun.colorHex !== lastColor) {
2136
- const [r, g, b] = hexToRgb01(tok.resolvedRun.colorHex);
2137
- out.push(`${formatNumber(r)} ${formatNumber(g)} ${formatNumber(b)} rg`);
2138
- lastColor = tok.resolvedRun.colorHex;
2139
- }
2140
- };
2141
- const emitImageToken = (tok, x, baselineY) => {
2142
- if (!tok.imageResourceName) return;
2143
- if (inBT) {
2144
- out.push("ET");
2145
- inBT = false;
2146
- }
2147
- out.push("q");
2148
- out.push(`${formatNumber(tok.widthPt)} 0 0 ${formatNumber(tok.heightPt)} ${formatNumber(x)} ${formatNumber(baselineY)} cm`);
2149
- out.push(`/${tok.imageResourceName} Do`);
2150
- out.push("Q");
2151
- lastFont = "";
2152
- lastSize = -1;
2153
- lastColor = "";
2154
- };
2155
- const emitMathToken = (tok, originX, baselineY) => {
2156
- for (const it of tok.items) if (it.kind === "glyph") {
2157
- if (!inBT) {
2158
- out.push("BT");
2159
- inBT = true;
2160
- }
2161
- if (it.font.resourceName !== lastFont || it.sizePt !== lastSize) {
2162
- out.push(`/${it.font.resourceName} ${formatNumber(it.sizePt)} Tf`);
2163
- lastFont = it.font.resourceName;
2164
- lastSize = it.sizePt;
2165
- }
2166
- if (lastColor !== "000000") {
2167
- out.push("0 0 0 rg");
2168
- lastColor = "000000";
2169
- }
2170
- out.push(`1 0 0 1 ${formatNumber(originX + it.x)} ${formatNumber(baselineY + it.y)} Tm`);
2171
- out.push(`<${it.font.embedded.encodeTextAsCidHex(it.text)}> Tj`);
2172
- } else if (it.kind === "rule") {
2173
- if (inBT) {
2174
- out.push("ET");
2175
- inBT = false;
2176
- }
2177
- out.push("q");
2178
- out.push("0 0 0 rg");
2179
- out.push(`${formatNumber(originX + it.x)} ${formatNumber(baselineY + it.y)} ${formatNumber(it.w)} ${formatNumber(it.h)} re`);
2180
- out.push("f");
2181
- out.push("Q");
2182
- lastFont = "";
2183
- lastSize = -1;
2184
- lastColor = "";
2185
- } else {
2186
- if (inBT) {
2187
- out.push("ET");
2188
- inBT = false;
2189
- }
2190
- const shape = {
2191
- paths: [{ segments: it.segments }],
2192
- ...it.fill ? { fillColorHex: "000000" } : {},
2193
- ...it.strokeWidthPt !== void 0 ? { stroke: {
2194
- colorHex: "000000",
2195
- widthPt: it.strokeWidthPt
2196
- } } : {},
2197
- transform: [
2198
- 1,
2199
- 0,
2200
- 0,
2201
- 1,
2202
- originX,
2203
- baselineY
2204
- ]
2205
- };
2206
- for (const op of emitVectorShape(shape)) out.push(op);
2207
- lastFont = "";
2208
- lastSize = -1;
2209
- lastColor = "";
2210
- }
2211
- };
2212
- const emitOneLine = (cmd) => {
2213
- const line = cmd.line;
2214
- const originX = cmd.originX;
2215
- const baselineY = cmd.baselineY;
2216
- const extraPerSpace = computeJustifyExtra(line);
2217
- const hasImageToken = line.tokens.some((t) => t.kind === "image");
2218
- const hasMathToken = line.tokens.some((t) => t.kind === "math");
2219
- const hasRtl = line.tokens.some((t) => t.bidiLevel % 2 === 1);
2220
- const encodeToken = (tok) => {
2221
- const text = tok.bidiLevel % 2 === 1 ? reverseByCodePoint(tok.text) : tok.text;
2222
- return tok.font.embedded.encodeTextAsCidHex(text);
2223
- };
2224
- if (extraPerSpace > 0 || hasImageToken || hasMathToken || hasRtl) {
2225
- const order = hasRtl ? lineVisualOrder(line) : line.tokens.map((_, i) => i);
2226
- let x = originX;
2227
- for (const ti of order) {
2228
- const tok = line.tokens[ti];
2229
- if (tok.kind === "image") {
2230
- emitImageToken(tok, x, baselineY);
2231
- x += tok.widthPt;
2232
- continue;
2233
- }
2234
- if (tok.kind === "math") {
2235
- emitMathToken(tok, x, baselineY);
2236
- x += tok.widthPt;
2237
- continue;
2238
- }
2239
- if (!inBT) {
2240
- out.push("BT");
2241
- inBT = true;
2242
- }
2243
- switchFontIfNeeded(tok);
2244
- out.push(`1 0 0 1 ${formatNumber(x)} ${formatNumber(baselineY)} Tm`);
2245
- out.push(`<${encodeToken(tok)}> Tj`);
2246
- x += tok.widthPt;
2247
- if (tok.isSpace) x += extraPerSpace;
2248
- }
2249
- } else {
2250
- if (!inBT) {
2251
- out.push("BT");
2252
- inBT = true;
2253
- }
2254
- out.push(`1 0 0 1 ${formatNumber(originX)} ${formatNumber(baselineY)} Tm`);
2255
- for (const tok of line.tokens) {
2256
- if (tok.kind !== "text") continue;
2257
- switchFontIfNeeded(tok);
2258
- const hex = tok.font.embedded.encodeTextAsCidHex(tok.text);
2259
- out.push(`<${hex}> Tj`);
2260
- }
2261
- }
2262
- };
2263
- if (tagging) for (const cmd of lines) {
2264
- if (inBT) {
2265
- out.push("ET");
2266
- inBT = false;
2267
- }
2268
- const sid = cmd.structId;
2269
- if (sid !== void 0) {
2270
- const mcid = tagging.next++;
2271
- tagging.assigned = true;
2272
- tagging.record(sid, mcid);
2273
- out.push(`/${tagging.tagFor(sid)} <</MCID ${mcid}>> BDC`);
2274
- } else if (cmd.artifact === "pagination") out.push("/Artifact <</Type /Pagination>> BDC");
2275
- else out.push("/Artifact BMC");
2276
- emitOneLine(cmd);
2277
- if (inBT) {
2278
- out.push("ET");
2279
- inBT = false;
2280
- }
2281
- out.push("EMC");
2282
- }
2283
- else {
2284
- out.push("BT");
2285
- inBT = true;
2286
- for (const cmd of lines) emitOneLine(cmd);
2287
- if (inBT) out.push("ET");
2288
- }
2289
- }
2290
- return encoder.encode(out.join("\n"));
2291
- }
2292
- function lineVisualOrder(line) {
2293
- return reorderVisual(line.tokens.map((t) => t.bidiLevel));
2294
- }
2295
- function computeJustifyExtra(line) {
2296
- if (line.resolved.alignment !== "both") return 0;
2297
- if (line.isLastInParagraph) return 0;
2298
- let spaces = 0;
2299
- for (const tok of line.tokens) if (tok.isSpace) spaces++;
2300
- if (spaces === 0) return 0;
2301
- const extra = line.availableWidthPt - line.contentWidthPt;
2302
- if (extra <= 0) return 0;
2303
- return extra / spaces;
2304
- }
2305
- function hexToRgb01(hex) {
2306
- return [
2307
- parseInt(hex.slice(0, 2), 16) / 255,
2308
- parseInt(hex.slice(2, 4), 16) / 255,
2309
- parseInt(hex.slice(4, 6), 16) / 255
2310
- ];
2311
- }
2312
- function formatNumber(n) {
2313
- if (Number.isInteger(n)) return String(n);
2314
- return n.toFixed(3).replace(/0+$/, "").replace(/\.$/, "");
2315
- }
2316
1830
  //#endregion
2317
- export { renderStyledPdf };
1831
+ export { layoutStyledDocument, paintPlan, renderStyledPdf };