pdf-parser.js 5.2.30 → 5.3.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 (189) hide show
  1. package/dist/{afm-widths-BHD2HZIL.cjs → afm-widths-C6U0SQj9.cjs} +5 -1448
  2. package/dist/{afm-widths-B_IGbGky.js → afm-widths-p3UfaXme.js} +3 -1398
  3. package/dist/afm-widths.cjs +1 -1
  4. package/dist/afm-widths.js +1 -1
  5. package/dist/annotations.d.cts +3 -3
  6. package/dist/annotations.d.ts +3 -3
  7. package/dist/attachments.d.cts +2 -2
  8. package/dist/attachments.d.ts +2 -2
  9. package/dist/builtin-encoding.cjs +4 -3
  10. package/dist/builtin-encoding.js +2 -1
  11. package/dist/cmap.d.cts +1 -1
  12. package/dist/cmap.d.ts +1 -1
  13. package/dist/content-read.d.cts +1 -1
  14. package/dist/content-read.d.ts +1 -1
  15. package/dist/content-write.cjs +1 -1
  16. package/dist/content-write.d.cts +1 -1
  17. package/dist/content-write.d.ts +1 -1
  18. package/dist/content-write.js +1 -1
  19. package/dist/diagnostics-C9FxfZ6H.d.cts +22 -0
  20. package/dist/diagnostics-C9FxfZ6H.d.ts +22 -0
  21. package/dist/diagnostics.d.cts +1 -21
  22. package/dist/diagnostics.d.ts +1 -21
  23. package/dist/document.d.cts +1 -1
  24. package/dist/document.d.ts +1 -1
  25. package/dist/{embedded-font-ByD7ZiQS.d.ts → embedded-font-CQZbTTDM.d.ts} +1 -1
  26. package/dist/{embedded-font-DgVBedw6.d.cts → embedded-font-CqePfvrl.d.cts} +1 -1
  27. package/dist/embedded-font-write.d.cts +1 -1
  28. package/dist/embedded-font-write.d.ts +1 -1
  29. package/dist/embedded-font.cjs +2 -2
  30. package/dist/embedded-font.d.cts +1 -1
  31. package/dist/embedded-font.d.ts +1 -1
  32. package/dist/embedded-font.js +2 -2
  33. package/dist/encoding-glyph-unicode.cjs +353 -0
  34. package/dist/encoding-glyph-unicode.d.cts +4 -0
  35. package/dist/encoding-glyph-unicode.d.ts +4 -0
  36. package/dist/encoding-glyph-unicode.js +352 -0
  37. package/dist/encoding-standard-tables.cjs +531 -0
  38. package/dist/encoding-standard-tables.d.cts +7 -0
  39. package/dist/encoding-standard-tables.d.ts +7 -0
  40. package/dist/encoding-standard-tables.js +527 -0
  41. package/dist/encoding-symbol-tables.cjs +533 -0
  42. package/dist/encoding-symbol-tables.d.cts +7 -0
  43. package/dist/encoding-symbol-tables.d.ts +7 -0
  44. package/dist/encoding-symbol-tables.js +529 -0
  45. package/dist/encoding.cjs +1 -9
  46. package/dist/encoding.d.cts +1 -9
  47. package/dist/encoding.d.ts +1 -9
  48. package/dist/encoding.js +2 -2
  49. package/dist/encrypt.d.cts +1 -1
  50. package/dist/encrypt.d.ts +1 -1
  51. package/dist/filters.d.cts +1 -1
  52. package/dist/filters.d.ts +1 -1
  53. package/dist/font-read.cjs +4 -3
  54. package/dist/font-read.d.cts +2 -2
  55. package/dist/font-read.d.ts +2 -2
  56. package/dist/font-read.js +2 -1
  57. package/dist/font-registry.d.cts +1 -1
  58. package/dist/font-registry.d.ts +1 -1
  59. package/dist/form.d.cts +2 -2
  60. package/dist/form.d.ts +2 -2
  61. package/dist/gdef-table-D0Hzn4KD.d.cts +15 -0
  62. package/dist/gdef-table-DL0V8wEZ.d.ts +15 -0
  63. package/dist/gdef-table.d.cts +1 -14
  64. package/dist/gdef-table.d.ts +1 -14
  65. package/dist/glyf-contours.d.cts +12 -1
  66. package/dist/glyf-contours.d.ts +12 -1
  67. package/dist/gsub-context.cjs +13 -0
  68. package/dist/gsub-context.d.cts +34 -0
  69. package/dist/gsub-context.d.ts +34 -0
  70. package/dist/gsub-context.js +2 -0
  71. package/dist/gsub-table-BDpJWqpf.d.ts +52 -0
  72. package/dist/gsub-table-D6niKeLi.js +556 -0
  73. package/dist/gsub-table-DW7Wmi9V.d.cts +52 -0
  74. package/dist/gsub-table-hFfYmf1W.cjs +741 -0
  75. package/dist/gsub-table.cjs +21 -556
  76. package/dist/gsub-table.d.cts +2 -2
  77. package/dist/gsub-table.d.ts +2 -2
  78. package/dist/gsub-table.js +2 -554
  79. package/dist/images-read.d.cts +2 -2
  80. package/dist/images-read.d.ts +2 -2
  81. package/dist/index.cjs +6 -6
  82. package/dist/index.d.cts +2 -2
  83. package/dist/index.d.ts +2 -2
  84. package/dist/index.js +6 -6
  85. package/dist/interpret-CqXdXgkY.cjs +712 -0
  86. package/dist/interpret-aWWhdIzr.js +677 -0
  87. package/dist/interpret-colors.cjs +6 -0
  88. package/dist/interpret-colors.d.cts +9 -0
  89. package/dist/interpret-colors.d.ts +9 -0
  90. package/dist/interpret-colors.js +2 -0
  91. package/dist/interpret-marked.cjs +25 -0
  92. package/dist/interpret-marked.d.cts +11 -0
  93. package/dist/interpret-marked.d.ts +11 -0
  94. package/dist/interpret-marked.js +23 -0
  95. package/dist/interpret-shapes.cjs +212 -0
  96. package/dist/interpret-shapes.d.cts +32 -0
  97. package/dist/interpret-shapes.d.ts +32 -0
  98. package/dist/interpret-shapes.js +199 -0
  99. package/dist/interpret-types.cjs +0 -0
  100. package/dist/interpret-types.d.cts +123 -0
  101. package/dist/interpret-types.d.ts +123 -0
  102. package/dist/interpret-types.js +0 -0
  103. package/dist/interpret.cjs +3 -887
  104. package/dist/interpret.d.cts +5 -116
  105. package/dist/interpret.d.ts +5 -116
  106. package/dist/interpret.js +2 -887
  107. package/dist/math-font.cjs +1 -1
  108. package/dist/math-font.js +1 -1
  109. package/dist/measure.cjs +1 -1
  110. package/dist/measure.js +1 -1
  111. package/dist/names.d.cts +2 -2
  112. package/dist/names.d.ts +2 -2
  113. package/dist/navigation.d.cts +2 -2
  114. package/dist/navigation.d.ts +2 -2
  115. package/dist/optional-content.d.cts +2 -2
  116. package/dist/optional-content.d.ts +2 -2
  117. package/dist/ot-layout-common-BcsGRFBS.d.cts +10 -0
  118. package/dist/ot-layout-common-BcsGRFBS.d.ts +10 -0
  119. package/dist/ot-layout-common.d.cts +1 -9
  120. package/dist/ot-layout-common.d.ts +1 -9
  121. package/dist/parse.d.cts +1 -1
  122. package/dist/parse.d.ts +1 -1
  123. package/dist/predictors.d.cts +1 -1
  124. package/dist/predictors.d.ts +1 -1
  125. package/dist/raster-Cdm3idP_.js +794 -0
  126. package/dist/raster-EG2KYRZ0.cjs +829 -0
  127. package/dist/raster-text.cjs +5 -0
  128. package/dist/raster-text.d.cts +20 -0
  129. package/dist/raster-text.d.ts +20 -0
  130. package/dist/raster-text.js +2 -0
  131. package/dist/raster.cjs +4 -795
  132. package/dist/raster.d.cts +17 -6
  133. package/dist/raster.d.ts +17 -6
  134. package/dist/raster.js +2 -792
  135. package/dist/read-convert.cjs +310 -0
  136. package/dist/read-convert.d.cts +58 -0
  137. package/dist/read-convert.d.ts +58 -0
  138. package/dist/read-convert.js +295 -0
  139. package/dist/read.cjs +5 -293
  140. package/dist/read.d.cts +1 -1
  141. package/dist/read.d.ts +1 -1
  142. package/dist/read.js +4 -292
  143. package/dist/structure.d.cts +2 -2
  144. package/dist/structure.d.ts +2 -2
  145. package/dist/winansi.cjs +1 -1
  146. package/dist/winansi.js +1 -1
  147. package/dist/write-annotations.cjs +132 -0
  148. package/dist/write-annotations.d.cts +29 -0
  149. package/dist/write-annotations.d.ts +29 -0
  150. package/dist/write-annotations.js +121 -0
  151. package/dist/write-font-objects.cjs +76 -0
  152. package/dist/write-font-objects.d.cts +35 -0
  153. package/dist/write-font-objects.d.ts +35 -0
  154. package/dist/write-font-objects.js +75 -0
  155. package/dist/write-form.cjs +91 -0
  156. package/dist/write-form.d.cts +19 -0
  157. package/dist/write-form.d.ts +19 -0
  158. package/dist/write-form.js +89 -0
  159. package/dist/write-images.cjs +148 -0
  160. package/dist/write-images.d.cts +25 -0
  161. package/dist/write-images.d.ts +25 -0
  162. package/dist/write-images.js +140 -0
  163. package/dist/write-outline.cjs +46 -0
  164. package/dist/write-outline.d.cts +18 -0
  165. package/dist/write-outline.d.ts +18 -0
  166. package/dist/write-outline.js +45 -0
  167. package/dist/write-page-emit.cjs +97 -0
  168. package/dist/write-page-emit.d.cts +63 -0
  169. package/dist/write-page-emit.d.ts +63 -0
  170. package/dist/write-page-emit.js +96 -0
  171. package/dist/write-pages.cjs +37 -0
  172. package/dist/write-pages.d.cts +21 -0
  173. package/dist/write-pages.d.ts +21 -0
  174. package/dist/write-pages.js +36 -0
  175. package/dist/write-strings.cjs +41 -0
  176. package/dist/write-strings.d.cts +9 -0
  177. package/dist/write-strings.d.ts +9 -0
  178. package/dist/write-strings.js +37 -0
  179. package/dist/write.cjs +53 -553
  180. package/dist/write.d.cts +1 -1
  181. package/dist/write.d.ts +1 -1
  182. package/dist/write.js +49 -549
  183. package/dist/xref.d.cts +1 -1
  184. package/dist/xref.d.ts +1 -1
  185. package/package.json +1 -1
  186. package/dist/glyf-contours-B1PsI9oA.d.ts +0 -13
  187. package/dist/glyf-contours-NHBpgks-.d.cts +0 -13
  188. package/dist/gsub-table-Bm9kSMzk.d.cts +0 -16
  189. package/dist/gsub-table-CdfESH2-.d.ts +0 -16
@@ -0,0 +1,829 @@
1
+ const require_objects = require("./objects.cjs");
2
+ const require_bytes_writer = require("./bytes/writer.cjs");
3
+ const require_matrix = require("./matrix.cjs");
4
+ const require_filters = require("./filters.cjs");
5
+ const require_sfnt = require("./sfnt.cjs");
6
+ const require_cmap_table = require("./cmap-table.cjs");
7
+ const require_font_tables = require("./font-tables.cjs");
8
+ const require_images_read = require("./images-read.cjs");
9
+ const require_optional_content = require("./optional-content.cjs");
10
+ const require_diagnostics = require("./diagnostics.cjs");
11
+ const require_document = require("./document.cjs");
12
+ const require_util_abort = require("./util/abort.cjs");
13
+ const require_font_read = require("./font-read.cjs");
14
+ const require_interpret = require("./interpret-CqXdXgkY.cjs");
15
+ const require_read = require("./read.cjs");
16
+ const require_glyf = require("./glyf.cjs");
17
+ const require_glyf_contours = require("./glyf-contours.cjs");
18
+ //#region src/raster-text.ts
19
+ const CFF_HEADER_SIZE = 4;
20
+ function openEmbeddedProgram(descriptorOwner, resolver) {
21
+ const descriptor = resolver.resolveDict(require_objects.dictGet(descriptorOwner, "FontDescriptor"));
22
+ if (descriptor === void 0) return { kind: "absent" };
23
+ for (const key of ["FontFile2", "FontFile3"]) {
24
+ const stream = resolver.resolve(require_objects.dictGet(descriptor, key));
25
+ if (stream?.kind !== "stream") continue;
26
+ const bytes = require_filters.decodeStream(stream.raw, stream.dict, require_diagnostics.NOOP_DIAGNOSTIC_SINK).bytes;
27
+ if (bytes[0] === 1 && bytes[1] === 0 && bytes[2] === CFF_HEADER_SIZE) return { kind: "cff" };
28
+ const sfnt = require_sfnt.parseSfnt(bytes);
29
+ if (sfnt === void 0) continue;
30
+ if (sfnt.tables.has("CFF ")) return { kind: "cff" };
31
+ const head = require_font_tables.parseHead(sfnt);
32
+ const maxp = require_font_tables.parseMaxp(sfnt);
33
+ if (head === void 0 || maxp === void 0) continue;
34
+ const glyf = require_glyf.parseGlyf(sfnt, {
35
+ numGlyphs: maxp.numGlyphs,
36
+ indexToLocFormat: head.indexToLocFormat
37
+ });
38
+ if (glyf === void 0) continue;
39
+ return {
40
+ kind: "glyf",
41
+ sfnt,
42
+ face: {
43
+ glyf,
44
+ unitsPerEm: head.unitsPerEm
45
+ }
46
+ };
47
+ }
48
+ return { kind: "absent" };
49
+ }
50
+ function resolveTextOutlineFace(fontResourceName, resources, resolver, fontResolver, outlineFaces, sink) {
51
+ const fontsDict = resolver.resolveDict(require_objects.dictGet(resources, "Font"));
52
+ const fontDict = fontsDict !== void 0 ? resolver.resolveDict(require_objects.dictGet(fontsDict, fontResourceName)) : void 0;
53
+ if (fontDict === void 0) return;
54
+ if (outlineFaces.has(fontDict)) return outlineFaces.get(fontDict);
55
+ const face = buildTextOutlineFace(fontDict, resolver, fontResolver, fontResourceName, resources, sink);
56
+ outlineFaces.set(fontDict, face);
57
+ return face;
58
+ }
59
+ const BITS_PER_BYTE = 8;
60
+ function buildTextOutlineFace(fontDict, resolver, fontResolver, fontResourceName, resources, sink) {
61
+ const faceName = require_objects.asName(require_objects.dictGet(fontDict, "BaseFont")) ?? require_objects.asName(require_objects.dictGet(fontDict, "Subtype")) ?? "font";
62
+ const unavailable = (reason) => {
63
+ sink({
64
+ code: "raster/text-outlines-unavailable",
65
+ severity: "warning",
66
+ message: `font resource /${fontResourceName} (${faceName}) has no drawable outline (${reason}); its text is not rendered`
67
+ });
68
+ };
69
+ const cff = () => {
70
+ sink({
71
+ code: "raster/text-cff-outlines",
72
+ severity: "warning",
73
+ message: `font resource /${fontResourceName} (${faceName}) carries CFF outlines; this raster surface fills sfnt (TrueType/glyf) outlines only, so its text is not rendered rather than approximated`
74
+ });
75
+ };
76
+ const subtype = require_objects.asName(require_objects.dictGet(fontDict, "Subtype"));
77
+ if (subtype === "Type0") {
78
+ const encoding = resolver.resolve(require_objects.dictGet(fontDict, "Encoding"));
79
+ if (encoding?.kind !== "name" || encoding.name !== "Identity-H" && encoding.name !== "Identity-V") return unavailable("a Type0 font whose /Encoding is neither Identity-H nor Identity-V (a predefined or embedded CMap this raster walk does not decode)");
80
+ const descendants = require_objects.asArray(require_objects.dictGet(fontDict, "DescendantFonts"));
81
+ const descendant = descendants !== void 0 ? resolver.resolveDict(descendants[0]) : void 0;
82
+ if (descendant === void 0) return unavailable("a Type0 font with no readable /DescendantFonts entry");
83
+ const descendantSubtype = require_objects.asName(require_objects.dictGet(descendant, "Subtype"));
84
+ if (descendantSubtype === "CIDFontType0") return cff();
85
+ if (descendantSubtype !== "CIDFontType2") return unavailable(`a descendant font of subtype ${descendantSubtype ?? "(none)"}`);
86
+ const cidToGidMap = resolver.resolve(require_objects.dictGet(descendant, "CIDToGIDMap"));
87
+ const program = openEmbeddedProgram(descendant, resolver);
88
+ if (program.kind === "cff") return cff();
89
+ if (program.kind === "absent") return unavailable("no readable /FontFile2 (or glyf-bearing /FontFile3) stream");
90
+ if (cidToGidMap !== void 0 && cidToGidMap.kind !== "name" && cidToGidMap.kind !== "stream") return unavailable("a /CIDToGIDMap that is neither /Identity nor a readable stream");
91
+ if (cidToGidMap?.kind === "stream") {
92
+ const decodedBytes = require_filters.decodeStream(cidToGidMap.raw, cidToGidMap.dict, require_diagnostics.NOOP_DIAGNOSTIC_SINK).bytes;
93
+ const entries = [];
94
+ for (let i = 0; i + 1 < decodedBytes.length; i += 2) entries.push(decodedBytes[i] << BITS_PER_BYTE | decodedBytes[i + 1]);
95
+ return {
96
+ glyf: program.face.glyf,
97
+ unitsPerEm: program.face.unitsPerEm,
98
+ glyphIdOf: (codes, offset) => {
99
+ const cid = codes[offset] << BITS_PER_BYTE | codes[offset + 1];
100
+ return entries[cid];
101
+ }
102
+ };
103
+ }
104
+ return {
105
+ glyf: program.face.glyf,
106
+ unitsPerEm: program.face.unitsPerEm,
107
+ glyphIdOf: (codes, offset) => codes[offset] << BITS_PER_BYTE | codes[offset + 1]
108
+ };
109
+ }
110
+ if (subtype === "TrueType") {
111
+ const program = openEmbeddedProgram(fontDict, resolver);
112
+ if (program.kind === "cff") return cff();
113
+ if (program.kind === "absent") return unavailable("no /FontDescriptor or no readable embedded program (a standard-14 or otherwise unembedded face states no outlines at all)");
114
+ const cmapLookup = require_cmap_table.buildCmapLookup(program.sfnt);
115
+ if (cmapLookup === void 0) return unavailable("an embedded program with no usable Unicode cmap subtable");
116
+ return {
117
+ glyf: program.face.glyf,
118
+ unitsPerEm: program.face.unitsPerEm,
119
+ glyphIdOf: (codes, offset) => {
120
+ const codePoint = (fontResolver.resolve(fontResourceName, resources)?.decodeToUnicode(codes.subarray(offset, offset + 1)))?.codePointAt(0);
121
+ return codePoint === void 0 ? void 0 : cmapLookup(codePoint);
122
+ }
123
+ };
124
+ }
125
+ if (subtype === "Type1" || subtype === "MMType1") {
126
+ if (openEmbeddedProgram(fontDict, resolver).kind === "cff") return cff();
127
+ return unavailable("a Type 1 PostScript program, whose outlines are charstrings rather than sfnt glyf data");
128
+ }
129
+ return unavailable(`a font of subtype ${subtype ?? "(none)"} (a Type3 glyph-procedure font has no static outline at all)`);
130
+ }
131
+ const METRICS_PER_1000_SCALE = 1e3;
132
+ function drawTextRun(item, fontResolver, resolver, outlineFaces, interpretToDeviceMatrix, rasteriser, sink) {
133
+ const face = resolveTextOutlineFace(item.fontResourceName, item.resources, resolver, fontResolver, outlineFaces, sink);
134
+ if (face === void 0) return;
135
+ const placements = [];
136
+ let offset = 0;
137
+ let cumulative = 0;
138
+ while (offset < item.codes.length) {
139
+ const advance = fontResolver.metrics.glyphAdvance(item.fontResourceName, item.resources, item.codes, offset);
140
+ const byteLength = advance.byteLengthConsumed;
141
+ placements.push({
142
+ glyphId: face.glyphIdOf(item.codes, offset),
143
+ advance: cumulative,
144
+ positionX: (advance.vertical?.positionXPer1000 ?? 0) / METRICS_PER_1000_SCALE,
145
+ positionY: (advance.vertical?.positionYPer1000 ?? 0) / METRICS_PER_1000_SCALE
146
+ });
147
+ cumulative += (advance.vertical?.displacementPer1000 ?? advance.widthPer1000) / METRICS_PER_1000_SCALE * item.sizePt;
148
+ offset += byteLength;
149
+ }
150
+ const startDeviceMatrix = require_matrix.multiplyMatrices(item.startMatrix, interpretToDeviceMatrix);
151
+ const endDeviceMatrix = require_matrix.multiplyMatrices(item.endMatrix, interpretToDeviceMatrix);
152
+ const vertical = item.vertical === true;
153
+ const startPoint = require_matrix.applyMatrix(startDeviceMatrix, {
154
+ x: 0,
155
+ y: 0
156
+ });
157
+ const endPoint = require_matrix.applyMatrix(endDeviceMatrix, {
158
+ x: 0,
159
+ y: 0
160
+ });
161
+ const rawEndPoint = require_matrix.applyMatrix(startDeviceMatrix, vertical ? {
162
+ x: 0,
163
+ y: cumulative
164
+ } : {
165
+ x: cumulative,
166
+ y: 0
167
+ });
168
+ const rawExtent = Math.hypot(rawEndPoint.x - startPoint.x, rawEndPoint.y - startPoint.y);
169
+ const actualExtent = Math.hypot(endPoint.x - startPoint.x, endPoint.y - startPoint.y);
170
+ const correction = rawExtent > 1e-9 ? actualExtent / rawExtent : 1;
171
+ const firstPlacement = placements[0];
172
+ const glyphScale = require_matrix.scaleMatrix(1 / face.unitsPerEm, 1 / face.unitsPerEm);
173
+ for (const placement of placements) {
174
+ if (placement.glyphId === void 0) continue;
175
+ const outline = require_glyf_contours.decodeGlyphOutline(face.glyf, placement.glyphId);
176
+ if (outline === void 0) continue;
177
+ const trm = require_matrix.multiplyMatrices(require_matrix.translationMatrix((firstPlacement?.positionX ?? 0) - placement.positionX, (firstPlacement?.positionY ?? 0) - placement.positionY), require_matrix.multiplyMatrices(vertical ? require_matrix.translationMatrix(0, placement.advance * correction) : require_matrix.translationMatrix(placement.advance * correction, 0), item.startMatrix));
178
+ drawGlyphOutline(outline, require_matrix.multiplyMatrices(glyphScale, require_matrix.multiplyMatrices(trm, interpretToDeviceMatrix)), item.color, rasteriser);
179
+ }
180
+ }
181
+ function drawGlyphOutline(outline, glyphMatrix, color, rasteriser) {
182
+ const subpaths = glyphOutlineSubpaths(outline, glyphMatrix);
183
+ if (subpaths.length === 0) return;
184
+ rasteriser.draw({
185
+ kind: "path",
186
+ subpaths,
187
+ fill: {
188
+ color,
189
+ fillRule: "nonzero"
190
+ }
191
+ });
192
+ }
193
+ const MIN_CONTOUR_POINTS = 3;
194
+ const QUADRATIC_TO_CUBIC_CONTROL_FRACTION = 2 / 3;
195
+ function glyphOutlineSubpaths(outline, matrix) {
196
+ const subpaths = [];
197
+ for (const contour of outline.contours) {
198
+ if (contour.length < MIN_CONTOUR_POINTS) continue;
199
+ const firstOn = contour.findIndex((point) => point.onCurve);
200
+ const contourPoints = contour.map((point) => ({
201
+ x: point.x,
202
+ y: point.y,
203
+ onCurve: point.onCurve
204
+ }));
205
+ const hasLeadingOnCurvePoint = firstOn >= 0;
206
+ const ordered = hasLeadingOnCurvePoint ? [...contourPoints.slice(firstOn), ...contourPoints.slice(0, firstOn)] : contourPoints;
207
+ let current = hasLeadingOnCurvePoint ? {
208
+ x: contourPoints[firstOn].x,
209
+ y: contourPoints[firstOn].y
210
+ } : {
211
+ x: (contourPoints[contourPoints.length - 1].x + contourPoints[0].x) / 2,
212
+ y: (contourPoints[contourPoints.length - 1].y + contourPoints[0].y) / 2
213
+ };
214
+ const start = current;
215
+ const segments = [];
216
+ let pendingOffCurve;
217
+ const emitQuad = (from, control, to) => {
218
+ const p0 = require_matrix.applyMatrix(matrix, from);
219
+ const q = require_matrix.applyMatrix(matrix, control);
220
+ const p1 = require_matrix.applyMatrix(matrix, to);
221
+ segments.push({
222
+ kind: "cubic",
223
+ c1xPx: p0.x + QUADRATIC_TO_CUBIC_CONTROL_FRACTION * (q.x - p0.x),
224
+ c1yPx: p0.y + QUADRATIC_TO_CUBIC_CONTROL_FRACTION * (q.y - p0.y),
225
+ c2xPx: p1.x + QUADRATIC_TO_CUBIC_CONTROL_FRACTION * (q.x - p1.x),
226
+ c2yPx: p1.y + QUADRATIC_TO_CUBIC_CONTROL_FRACTION * (q.y - p1.y),
227
+ xPx: p1.x,
228
+ yPx: p1.y
229
+ });
230
+ };
231
+ const emitLine = (to) => {
232
+ const p1 = require_matrix.applyMatrix(matrix, to);
233
+ segments.push({
234
+ kind: "line",
235
+ xPx: p1.x,
236
+ yPx: p1.y
237
+ });
238
+ };
239
+ for (const point of ordered) if (point.onCurve) {
240
+ if (pendingOffCurve === void 0) emitLine(point);
241
+ else emitQuad(current, pendingOffCurve, point);
242
+ current = point;
243
+ pendingOffCurve = void 0;
244
+ } else {
245
+ if (pendingOffCurve !== void 0) {
246
+ const implied = {
247
+ x: (pendingOffCurve.x + point.x) / 2,
248
+ y: (pendingOffCurve.y + point.y) / 2
249
+ };
250
+ emitQuad(current, pendingOffCurve, implied);
251
+ current = implied;
252
+ }
253
+ pendingOffCurve = point;
254
+ }
255
+ if (pendingOffCurve !== void 0) emitQuad(current, pendingOffCurve, start);
256
+ const startPx = require_matrix.applyMatrix(matrix, start);
257
+ subpaths.push({
258
+ startXPx: startPx.x,
259
+ startYPx: startPx.y,
260
+ segments,
261
+ closed: true
262
+ });
263
+ }
264
+ return subpaths;
265
+ }
266
+ //#endregion
267
+ //#region src/raster.ts
268
+ const PIXEL_ROUNDING_EPSILON = 1e-9;
269
+ const POINTS_PER_INCH = 72;
270
+ const EXTENT_ZERO_EPSILON = 1e-9;
271
+ function regionPixels(extentPt, scale) {
272
+ return Math.max(1, Math.ceil(extentPt * scale - PIXEL_ROUNDING_EPSILON));
273
+ }
274
+ const HEADER_SEARCH_WINDOW = 1024;
275
+ const DEFAULT_PAGE_WIDTH_PT = 612;
276
+ const DEFAULT_PAGE_HEIGHT_PT = 792;
277
+ const NEWLINE_BYTE = 10;
278
+ function hasPdfHeader(bytes) {
279
+ const window = bytes.subarray(0, Math.min(HEADER_SEARCH_WINDOW, bytes.length));
280
+ return new TextDecoder("latin1").decode(window).includes("%PDF-");
281
+ }
282
+ function readDeclaredPageBox(page, key) {
283
+ const arr = require_objects.asArray(require_objects.dictGet(page, key));
284
+ if (arr === void 0) return;
285
+ const a = require_objects.asNumber(arr[0]) ?? 0;
286
+ const b = require_objects.asNumber(arr[1]) ?? 0;
287
+ const c = require_objects.asNumber(arr[2]) ?? 0;
288
+ const d = require_objects.asNumber(arr[3]) ?? 0;
289
+ return {
290
+ llx: Math.min(a, c),
291
+ lly: Math.min(b, d),
292
+ urx: Math.max(a, c),
293
+ ury: Math.max(b, d)
294
+ };
295
+ }
296
+ function readMediaBox(page) {
297
+ return readDeclaredPageBox(page, "MediaBox") ?? {
298
+ llx: 0,
299
+ lly: 0,
300
+ urx: DEFAULT_PAGE_WIDTH_PT,
301
+ ury: DEFAULT_PAGE_HEIGHT_PT
302
+ };
303
+ }
304
+ function rotatedRectBounds(rect, matrix) {
305
+ const transformed = [
306
+ [rect.llx, rect.lly],
307
+ [rect.urx, rect.lly],
308
+ [rect.llx, rect.ury],
309
+ [rect.urx, rect.ury]
310
+ ].map(([x, y]) => require_matrix.applyMatrix(matrix, {
311
+ x,
312
+ y
313
+ }));
314
+ const xs = transformed.map((point) => point.x);
315
+ const ys = transformed.map((point) => point.y);
316
+ return {
317
+ minX: Math.min(...xs),
318
+ minY: Math.min(...ys),
319
+ maxX: Math.max(...xs),
320
+ maxY: Math.max(...ys)
321
+ };
322
+ }
323
+ function readPageContentBytes(page, resolver, sink) {
324
+ const contentsObj = resolver.resolve(require_objects.dictGet(page, "Contents"));
325
+ if (contentsObj?.kind === "stream") return require_filters.decodeStream(contentsObj.raw, contentsObj.dict, sink).bytes;
326
+ if (contentsObj?.kind === "array") {
327
+ const chunks = [];
328
+ for (const entry of contentsObj.items) {
329
+ const streamObj = resolver.resolve(entry);
330
+ if (streamObj?.kind === "stream") chunks.push(require_filters.decodeStream(streamObj.raw, streamObj.dict, sink).bytes, new Uint8Array([NEWLINE_BYTE]));
331
+ }
332
+ return require_bytes_writer.concatBytes(chunks);
333
+ }
334
+ return /* @__PURE__ */ new Uint8Array(0);
335
+ }
336
+ function renderPdfPage(pdfBytes, pageIndex, options, rasteriser) {
337
+ const sink = options.sink ?? require_diagnostics.NOOP_DIAGNOSTIC_SINK;
338
+ if (options.scale !== void 0 && options.dpi !== void 0) throw new Error("renderPdfPage accepts at most one of scale and dpi; they name the same factor in different units (dpi = 72 x scale)");
339
+ const scale = options.dpi !== void 0 ? options.dpi / POINTS_PER_INCH : options.scale;
340
+ if (scale !== void 0 && !(scale > 0)) throw new Error(`renderPdfPage requires a positive scale factor (received scale ${options.scale}, dpi ${options.dpi})`);
341
+ const pixelsPerPt = scale ?? 1;
342
+ if (options.clipPt !== void 0 && (!(options.clipPt.widthPt > 0) || !(options.clipPt.heightPt > 0))) throw new Error("renderPdfPage clipPt must carry positive widthPt and heightPt; a zero-extent region has no pixels to render");
343
+ require_util_abort.throwIfAborted(options.signal);
344
+ if (!hasPdfHeader(pdfBytes)) throw new require_diagnostics.PdfParseError("pdf/no-header", "no \"%PDF-\" header found within the first bytes of the file; this does not look like a PDF at all");
345
+ const doc = require_document.openPdfDocument(pdfBytes, sink);
346
+ const pages = doc.pages();
347
+ if (pageIndex < 0 || pageIndex >= pages.length) throw new require_diagnostics.PdfParseError("pdf/page-index-out-of-range", `page index ${pageIndex} is outside this document's page tree (it declares ${pages.length} page${pages.length === 1 ? "" : "s"})`);
348
+ const page = pages[pageIndex];
349
+ const mediaBox = readMediaBox(page);
350
+ let cropBox = readDeclaredPageBox(page, "CropBox") ?? mediaBox;
351
+ if (cropBox.urx - cropBox.llx <= 0 || cropBox.ury - cropBox.lly <= 0) {
352
+ sink({
353
+ code: "pdf/invalid-crop-box",
354
+ severity: "warning",
355
+ pageIndex,
356
+ message: "page /CropBox is degenerate (zero width or height); falling back to the /MediaBox as the visible region"
357
+ });
358
+ cropBox = mediaBox;
359
+ }
360
+ const rotation = require_read.normalizeRotation(require_objects.asNumber(require_objects.dictGet(page, "Rotate")));
361
+ const rotationResult = require_read.pageRotationTransform(rotation, 0, 0);
362
+ const visibleRect = rotatedRectBounds(cropBox, rotationResult.matrix);
363
+ const pageWidthPt = visibleRect.maxX - visibleRect.minX;
364
+ const pageHeightPt = visibleRect.maxY - visibleRect.minY;
365
+ const pageMatrix = require_matrix.multiplyMatrices(rotationResult.matrix, require_matrix.translationMatrix(-visibleRect.minX, -visibleRect.minY));
366
+ const requested = options.clipPt ?? {
367
+ xPt: 0,
368
+ yPt: 0,
369
+ widthPt: pageWidthPt,
370
+ heightPt: pageHeightPt
371
+ };
372
+ const clipLeft = Math.max(0, requested.xPt);
373
+ const clipBottom = Math.max(0, requested.yPt);
374
+ const clipRight = Math.min(pageWidthPt, requested.xPt + requested.widthPt);
375
+ const clipTop = Math.min(pageHeightPt, requested.yPt + requested.heightPt);
376
+ if (clipRight - clipLeft <= 0 || clipTop - clipBottom <= 0) throw new Error(`renderPdfPage clipPt does not intersect the page's visible region (clip x ${requested.xPt}..${requested.xPt + requested.widthPt}, y ${requested.yPt}..${requested.yPt + requested.heightPt}; page 0..${pageWidthPt} x 0..${pageHeightPt})`);
377
+ const regionWidthPt = clipRight - clipLeft;
378
+ const regionHeightPt = clipTop - clipBottom;
379
+ const widthPx = regionPixels(regionWidthPt, pixelsPerPt);
380
+ const heightPx = regionPixels(regionHeightPt, pixelsPerPt);
381
+ const pageToDeviceMatrix = [
382
+ pixelsPerPt,
383
+ 0,
384
+ 0,
385
+ -pixelsPerPt,
386
+ -clipLeft * pixelsPerPt,
387
+ (clipBottom + regionHeightPt) * pixelsPerPt
388
+ ];
389
+ const interpretToDeviceMatrix = require_matrix.multiplyMatrices(pageMatrix, pageToDeviceMatrix);
390
+ const resources = doc.resolveDict(require_objects.dictGet(page, "Resources"));
391
+ rasteriser.beginPage({
392
+ widthPx,
393
+ heightPx,
394
+ scale: pixelsPerPt,
395
+ widthPt: regionWidthPt,
396
+ heightPt: regionHeightPt
397
+ });
398
+ if (resources === void 0) {
399
+ sink({
400
+ code: "pdf/object-missing-value",
401
+ severity: "warning",
402
+ message: "page has no /Resources dict; its content stream cannot be interpreted"
403
+ });
404
+ return rasteriser.finish();
405
+ }
406
+ const fontResolver = require_font_read.createFontResolver({
407
+ resolver: doc,
408
+ sink
409
+ });
410
+ const { layers, layerNameOf } = require_optional_content.readOptionalContent(doc.catalog, doc, sink);
411
+ const hiddenLayers = new Set(layers.filter((layer) => !layer.visible).map((layer) => layer.name));
412
+ const extracted = require_interpret.interpretContentStream(readPageContentBytes(page, doc, sink), resources, {
413
+ fontMetrics: fontResolver.metrics,
414
+ resolver: doc,
415
+ sink,
416
+ layerNameOf
417
+ });
418
+ const outlineFaces = /* @__PURE__ */ new Map();
419
+ for (const item of extracted) {
420
+ require_util_abort.throwIfAborted(options.signal);
421
+ if (item.layerName !== void 0 && hiddenLayers.has(item.layerName)) continue;
422
+ drawExtractedItem(item, doc, fontResolver, outlineFaces, interpretToDeviceMatrix, pixelsPerPt, rasteriser, sink);
423
+ }
424
+ return rasteriser.finish();
425
+ }
426
+ function drawExtractedItem(item, resolver, fontResolver, outlineFaces, interpretToDeviceMatrix, pixelsPerPt, rasteriser, sink) {
427
+ if (item.kind === "text") {
428
+ drawTextRun(item, fontResolver, resolver, outlineFaces, interpretToDeviceMatrix, rasteriser, sink);
429
+ return;
430
+ }
431
+ if (item.kind === "rect") {
432
+ drawRect(item, interpretToDeviceMatrix, pixelsPerPt, rasteriser);
433
+ return;
434
+ }
435
+ if (item.kind === "ellipse") {
436
+ drawEllipse(item, interpretToDeviceMatrix, pixelsPerPt, rasteriser);
437
+ return;
438
+ }
439
+ if (item.kind === "line") {
440
+ drawLine(item, interpretToDeviceMatrix, pixelsPerPt, rasteriser);
441
+ return;
442
+ }
443
+ if (item.kind === "path") {
444
+ drawPath(item, interpretToDeviceMatrix, pixelsPerPt, rasteriser);
445
+ return;
446
+ }
447
+ if (item.kind === "image") {
448
+ drawImageXObjectItem(item, resolver, interpretToDeviceMatrix, rasteriser, sink);
449
+ return;
450
+ }
451
+ drawInlineImageItem(item, resolver, interpretToDeviceMatrix, rasteriser, sink);
452
+ }
453
+ function drawRect(item, matrix, pixelsPerPt, rasteriser) {
454
+ const corners = [
455
+ require_matrix.applyMatrix(matrix, {
456
+ x: item.xPt,
457
+ y: item.yPt
458
+ }),
459
+ require_matrix.applyMatrix(matrix, {
460
+ x: item.xPt + item.widthPt,
461
+ y: item.yPt
462
+ }),
463
+ require_matrix.applyMatrix(matrix, {
464
+ x: item.xPt,
465
+ y: item.yPt + item.heightPt
466
+ }),
467
+ require_matrix.applyMatrix(matrix, {
468
+ x: item.xPt + item.widthPt,
469
+ y: item.yPt + item.heightPt
470
+ })
471
+ ];
472
+ const minX = Math.min(...corners.map((corner) => corner.x));
473
+ const minY = Math.min(...corners.map((corner) => corner.y));
474
+ const maxX = Math.max(...corners.map((corner) => corner.x));
475
+ const maxY = Math.max(...corners.map((corner) => corner.y));
476
+ if (item.fill !== void 0) rasteriser.draw({
477
+ kind: "fillRect",
478
+ xPx: minX,
479
+ yPx: minY,
480
+ widthPx: maxX - minX,
481
+ heightPx: maxY - minY,
482
+ color: item.fill
483
+ });
484
+ if (item.stroke !== void 0) rasteriser.draw({
485
+ kind: "path",
486
+ subpaths: [{
487
+ startXPx: minX,
488
+ startYPx: minY,
489
+ segments: [
490
+ {
491
+ kind: "line",
492
+ xPx: maxX,
493
+ yPx: minY
494
+ },
495
+ {
496
+ kind: "line",
497
+ xPx: maxX,
498
+ yPx: maxY
499
+ },
500
+ {
501
+ kind: "line",
502
+ xPx: minX,
503
+ yPx: maxY
504
+ }
505
+ ],
506
+ closed: true
507
+ }],
508
+ stroke: strokeSpec(item.stroke, void 0, pixelsPerPt)
509
+ });
510
+ }
511
+ const ELLIPSE_QUADRANT_COUNT = 4;
512
+ function drawEllipse(item, matrix, pixelsPerPt, rasteriser) {
513
+ const cx = item.xPt + item.widthPt / 2;
514
+ const cy = item.yPt + item.heightPt / 2;
515
+ const rx = item.widthPt / 2;
516
+ const ry = item.heightPt / 2;
517
+ const dx = rx * require_matrix.BEZIER_KAPPA;
518
+ const dy = ry * require_matrix.BEZIER_KAPPA;
519
+ const cardinalPoints = [
520
+ [cx + rx, cy],
521
+ [cx, cy + ry],
522
+ [cx - rx, cy],
523
+ [cx, cy - ry]
524
+ ];
525
+ const controls = [
526
+ [cx + rx, cy + dy],
527
+ [cx + dx, cy + ry],
528
+ [cx - dx, cy + ry],
529
+ [cx - rx, cy + dy],
530
+ [cx - rx, cy - dy],
531
+ [cx - dx, cy - ry],
532
+ [cx + dx, cy - ry],
533
+ [cx + rx, cy - dy]
534
+ ];
535
+ const transformed = (point) => require_matrix.applyMatrix(matrix, {
536
+ x: point[0],
537
+ y: point[1]
538
+ });
539
+ const start = transformed(cardinalPoints[0]);
540
+ const segments = [];
541
+ for (let i = 0; i < ELLIPSE_QUADRANT_COUNT; i++) {
542
+ const end = transformed(cardinalPoints[(i + 1) % ELLIPSE_QUADRANT_COUNT]);
543
+ const c1 = transformed(controls[i * 2]);
544
+ const c2 = transformed(controls[i * 2 + 1]);
545
+ segments.push({
546
+ kind: "cubic",
547
+ c1xPx: c1.x,
548
+ c1yPx: c1.y,
549
+ c2xPx: c2.x,
550
+ c2yPx: c2.y,
551
+ xPx: end.x,
552
+ yPx: end.y
553
+ });
554
+ }
555
+ rasteriser.draw({
556
+ kind: "path",
557
+ subpaths: [{
558
+ startXPx: start.x,
559
+ startYPx: start.y,
560
+ segments,
561
+ closed: true
562
+ }],
563
+ ...item.fill !== void 0 ? { fill: {
564
+ color: item.fill,
565
+ fillRule: "nonzero"
566
+ } } : {},
567
+ ...item.stroke !== void 0 ? { stroke: strokeSpec(item.stroke, void 0, pixelsPerPt) } : {}
568
+ });
569
+ }
570
+ function drawLine(item, matrix, pixelsPerPt, rasteriser) {
571
+ const p1 = require_matrix.applyMatrix(matrix, {
572
+ x: item.x1Pt,
573
+ y: item.y1Pt
574
+ });
575
+ const p2 = require_matrix.applyMatrix(matrix, {
576
+ x: item.x2Pt,
577
+ y: item.y2Pt
578
+ });
579
+ if (item.style === "dotted") {
580
+ drawDottedSegment(p1, p2, item.widthPt * pixelsPerPt, item.color, rasteriser);
581
+ return;
582
+ }
583
+ rasteriser.draw({
584
+ kind: "path",
585
+ subpaths: [{
586
+ startXPx: p1.x,
587
+ startYPx: p1.y,
588
+ segments: [{
589
+ kind: "line",
590
+ xPx: p2.x,
591
+ yPx: p2.y
592
+ }],
593
+ closed: false
594
+ }],
595
+ stroke: strokeSpec({
596
+ color: item.color,
597
+ widthPt: item.widthPt
598
+ }, item.style, pixelsPerPt)
599
+ });
600
+ }
601
+ function drawPath(item, matrix, pixelsPerPt, rasteriser) {
602
+ if (item.stroke !== void 0 && item.style === "dotted") {
603
+ const widthPx = item.stroke.widthPt * pixelsPerPt;
604
+ for (const subpath of item.subpaths) {
605
+ let prev = require_matrix.applyMatrix(matrix, {
606
+ x: subpath.startXPt,
607
+ y: subpath.startYPt
608
+ });
609
+ const emitTo = (end) => {
610
+ drawDottedSegment(prev, end, widthPx, item.stroke.color, rasteriser);
611
+ prev = end;
612
+ };
613
+ for (const segment of subpath.segments) if (segment.kind === "line") emitTo(require_matrix.applyMatrix(matrix, {
614
+ x: segment.xPt,
615
+ y: segment.yPt
616
+ }));
617
+ else {
618
+ const flattened = flattenCubic(prev, require_matrix.applyMatrix(matrix, {
619
+ x: segment.c1xPt,
620
+ y: segment.c1yPt
621
+ }), require_matrix.applyMatrix(matrix, {
622
+ x: segment.c2xPt,
623
+ y: segment.c2yPt
624
+ }), require_matrix.applyMatrix(matrix, {
625
+ x: segment.xPt,
626
+ y: segment.yPt
627
+ }));
628
+ for (const point of flattened) emitTo(point);
629
+ }
630
+ }
631
+ return;
632
+ }
633
+ const subpaths = item.subpaths.map((subpath) => ({
634
+ startXPx: require_matrix.applyMatrix(matrix, {
635
+ x: subpath.startXPt,
636
+ y: subpath.startYPt
637
+ }).x,
638
+ startYPx: require_matrix.applyMatrix(matrix, {
639
+ x: subpath.startXPt,
640
+ y: subpath.startYPt
641
+ }).y,
642
+ segments: subpath.segments.map((segment) => {
643
+ if (segment.kind === "line") {
644
+ const end = require_matrix.applyMatrix(matrix, {
645
+ x: segment.xPt,
646
+ y: segment.yPt
647
+ });
648
+ return {
649
+ kind: "line",
650
+ xPx: end.x,
651
+ yPx: end.y
652
+ };
653
+ }
654
+ const c1 = require_matrix.applyMatrix(matrix, {
655
+ x: segment.c1xPt,
656
+ y: segment.c1yPt
657
+ });
658
+ const c2 = require_matrix.applyMatrix(matrix, {
659
+ x: segment.c2xPt,
660
+ y: segment.c2yPt
661
+ });
662
+ const end = require_matrix.applyMatrix(matrix, {
663
+ x: segment.xPt,
664
+ y: segment.yPt
665
+ });
666
+ return {
667
+ kind: "cubic",
668
+ c1xPx: c1.x,
669
+ c1yPx: c1.y,
670
+ c2xPx: c2.x,
671
+ c2yPx: c2.y,
672
+ xPx: end.x,
673
+ yPx: end.y
674
+ };
675
+ }),
676
+ closed: subpath.closed
677
+ }));
678
+ rasteriser.draw({
679
+ kind: "path",
680
+ subpaths,
681
+ ...item.fill !== void 0 ? { fill: {
682
+ color: item.fill,
683
+ fillRule: item.fillRule
684
+ } } : {},
685
+ ...item.stroke !== void 0 ? { stroke: strokeSpec(item.stroke, item.style, pixelsPerPt) } : {}
686
+ });
687
+ }
688
+ function drawImageXObjectItem(item, resolver, interpretToDeviceMatrix, rasteriser, sink) {
689
+ const xobjects = resolver.resolveDict(require_objects.dictGet(item.resources, "XObject"));
690
+ const stream = xobjects !== void 0 ? resolver.resolve(require_objects.dictGet(xobjects, item.resourceName)) : void 0;
691
+ if (stream?.kind !== "stream") return;
692
+ const image = require_images_read.readImageXObject(stream.dict, stream.raw, resolver, sink);
693
+ if (image === void 0) return;
694
+ drawImage(image, item.matrix, interpretToDeviceMatrix, rasteriser);
695
+ }
696
+ function drawInlineImageItem(item, resolver, interpretToDeviceMatrix, rasteriser, sink) {
697
+ const image = require_images_read.readImageXObject(item.dict, item.data, resolver, sink);
698
+ if (image === void 0) return;
699
+ drawImage(image, item.matrix, interpretToDeviceMatrix, rasteriser);
700
+ }
701
+ function drawImage(image, ctm, interpretToDeviceMatrix, rasteriser) {
702
+ const matrix = require_matrix.multiplyMatrices([
703
+ 1,
704
+ 0,
705
+ 0,
706
+ -1,
707
+ 0,
708
+ 1
709
+ ], require_matrix.multiplyMatrices(ctm, interpretToDeviceMatrix));
710
+ rasteriser.draw({
711
+ kind: "image",
712
+ format: image.format,
713
+ bytes: image.bytes,
714
+ sourceWidthPx: image.widthPx,
715
+ sourceHeightPx: image.heightPx,
716
+ matrix
717
+ });
718
+ }
719
+ const DASHED_STROKE_WIDTH_MULTIPLE = 3;
720
+ function strokeSpec(stroke, style, pixelsPerPt) {
721
+ const widthPx = stroke.widthPt * pixelsPerPt;
722
+ if (style === "dashed") return {
723
+ color: stroke.color,
724
+ widthPx,
725
+ dashPx: [widthPx * DASHED_STROKE_WIDTH_MULTIPLE, widthPx * DASHED_STROKE_WIDTH_MULTIPLE]
726
+ };
727
+ return {
728
+ color: stroke.color,
729
+ widthPx
730
+ };
731
+ }
732
+ function drawDottedSegment(p1, p2, widthPx, color, rasteriser) {
733
+ const length = Math.hypot(p2.x - p1.x, p2.y - p1.y);
734
+ if (length === 0) return;
735
+ const spacing = Math.max(widthPx * 2, 1);
736
+ const dotHalf = widthPx / 2;
737
+ for (let distance = 0; distance <= length; distance += spacing) {
738
+ const t = distance / length;
739
+ rasteriser.draw({
740
+ kind: "fillRect",
741
+ xPx: p1.x + (p2.x - p1.x) * t - dotHalf,
742
+ yPx: p1.y + (p2.y - p1.y) * t - dotHalf,
743
+ widthPx,
744
+ heightPx: widthPx,
745
+ color
746
+ });
747
+ }
748
+ }
749
+ const STROKE_FLATTEN_TOLERANCE_PX = .05;
750
+ const MAX_FLATTEN_DEPTH = 16;
751
+ function flattenCubic(p0, c1, c2, p1) {
752
+ const points = [];
753
+ const flatten = (a, b, c, d, depth) => {
754
+ const chordX = d.x - a.x;
755
+ const chordY = d.y - a.y;
756
+ const chordLength = Math.hypot(chordX, chordY) || 1;
757
+ const dist1 = Math.abs((b.x - a.x) * chordY - (b.y - a.y) * chordX) / chordLength;
758
+ const dist2 = Math.abs((c.x - a.x) * chordY - (c.y - a.y) * chordX) / chordLength;
759
+ if (depth >= MAX_FLATTEN_DEPTH || Math.max(dist1, dist2) <= STROKE_FLATTEN_TOLERANCE_PX) {
760
+ points.push(d);
761
+ return;
762
+ }
763
+ const ab = {
764
+ x: (a.x + b.x) / 2,
765
+ y: (a.y + b.y) / 2
766
+ };
767
+ const bc = {
768
+ x: (b.x + c.x) / 2,
769
+ y: (b.y + c.y) / 2
770
+ };
771
+ const cd = {
772
+ x: (c.x + d.x) / 2,
773
+ y: (c.y + d.y) / 2
774
+ };
775
+ const abc = {
776
+ x: (ab.x + bc.x) / 2,
777
+ y: (ab.y + bc.y) / 2
778
+ };
779
+ const bcd = {
780
+ x: (bc.x + cd.x) / 2,
781
+ y: (bc.y + cd.y) / 2
782
+ };
783
+ const mid = {
784
+ x: (abc.x + bcd.x) / 2,
785
+ y: (abc.y + bcd.y) / 2
786
+ };
787
+ flatten(a, ab, abc, mid, depth + 1);
788
+ flatten(mid, bcd, cd, d, depth + 1);
789
+ };
790
+ flatten(p0, c1, c2, p1, 0);
791
+ return points;
792
+ }
793
+ //#endregion
794
+ Object.defineProperty(exports, "EXTENT_ZERO_EPSILON", {
795
+ enumerable: true,
796
+ get: function() {
797
+ return EXTENT_ZERO_EPSILON;
798
+ }
799
+ });
800
+ Object.defineProperty(exports, "drawGlyphOutline", {
801
+ enumerable: true,
802
+ get: function() {
803
+ return drawGlyphOutline;
804
+ }
805
+ });
806
+ Object.defineProperty(exports, "drawTextRun", {
807
+ enumerable: true,
808
+ get: function() {
809
+ return drawTextRun;
810
+ }
811
+ });
812
+ Object.defineProperty(exports, "flattenCubic", {
813
+ enumerable: true,
814
+ get: function() {
815
+ return flattenCubic;
816
+ }
817
+ });
818
+ Object.defineProperty(exports, "glyphOutlineSubpaths", {
819
+ enumerable: true,
820
+ get: function() {
821
+ return glyphOutlineSubpaths;
822
+ }
823
+ });
824
+ Object.defineProperty(exports, "renderPdfPage", {
825
+ enumerable: true,
826
+ get: function() {
827
+ return renderPdfPage;
828
+ }
829
+ });