@reportwright/viewer 0.0.0-stage → 0.12.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 (96) hide show
  1. package/CHANGELOG.md +233 -0
  2. package/LICENSE +23 -0
  3. package/README.md +146 -2
  4. package/dist/chunk-2NAW3MAP.js +1284 -0
  5. package/dist/chunk-2NAW3MAP.js.map +6 -0
  6. package/dist/chunk-3D43XGIN.js +1167 -0
  7. package/dist/chunk-3D43XGIN.js.map +6 -0
  8. package/dist/chunk-5N6OFCHJ.js +1667 -0
  9. package/dist/chunk-5N6OFCHJ.js.map +6 -0
  10. package/dist/chunk-72S6DETS.js +40 -0
  11. package/dist/chunk-72S6DETS.js.map +6 -0
  12. package/dist/chunk-AH47FS6Y.js +13 -0
  13. package/dist/chunk-AH47FS6Y.js.map +6 -0
  14. package/dist/chunk-APRPSQOD.js +301 -0
  15. package/dist/chunk-APRPSQOD.js.map +6 -0
  16. package/dist/chunk-BXKUE45K.js +1284 -0
  17. package/dist/chunk-BXKUE45K.js.map +6 -0
  18. package/dist/chunk-D2NTLAKL.js +14 -0
  19. package/dist/chunk-D2NTLAKL.js.map +6 -0
  20. package/dist/chunk-E7INJHTL.js +1284 -0
  21. package/dist/chunk-E7INJHTL.js.map +6 -0
  22. package/dist/chunk-EOVGKHAS.js +20682 -0
  23. package/dist/chunk-EOVGKHAS.js.map +6 -0
  24. package/dist/chunk-FARG6X2U.js +153 -0
  25. package/dist/chunk-FARG6X2U.js.map +6 -0
  26. package/dist/chunk-FGEFSGJT.js +1284 -0
  27. package/dist/chunk-FGEFSGJT.js.map +6 -0
  28. package/dist/chunk-GJS242RR.js +1652 -0
  29. package/dist/chunk-GJS242RR.js.map +6 -0
  30. package/dist/chunk-J56FRCFU.js +1284 -0
  31. package/dist/chunk-J56FRCFU.js.map +6 -0
  32. package/dist/chunk-KJTRZJHN.js +599 -0
  33. package/dist/chunk-KJTRZJHN.js.map +6 -0
  34. package/dist/chunk-M6GENFAH.js +14806 -0
  35. package/dist/chunk-M6GENFAH.js.map +6 -0
  36. package/dist/chunk-NJWQT6VB.js +1284 -0
  37. package/dist/chunk-NJWQT6VB.js.map +6 -0
  38. package/dist/chunk-ODREGGKA.js +219 -0
  39. package/dist/chunk-ODREGGKA.js.map +6 -0
  40. package/dist/chunk-OLLMACWA.js +35 -0
  41. package/dist/chunk-OLLMACWA.js.map +6 -0
  42. package/dist/chunk-PXXMOP4N.js +1284 -0
  43. package/dist/chunk-PXXMOP4N.js.map +6 -0
  44. package/dist/chunk-RKGIVPK5.js +1284 -0
  45. package/dist/chunk-RKGIVPK5.js.map +6 -0
  46. package/dist/chunk-RYHJUQSV.js +98 -0
  47. package/dist/chunk-RYHJUQSV.js.map +6 -0
  48. package/dist/chunk-SBD55ZES.js +316 -0
  49. package/dist/chunk-SBD55ZES.js.map +6 -0
  50. package/dist/chunk-SR2TQ2ZK.js +70 -0
  51. package/dist/chunk-SR2TQ2ZK.js.map +6 -0
  52. package/dist/designer.d.ts +48 -0
  53. package/dist/designer.js +35865 -0
  54. package/dist/designer.js.map +6 -0
  55. package/dist/peer/chunk-2NJMXASD.js +1282 -0
  56. package/dist/peer/chunk-2NJMXASD.js.map +6 -0
  57. package/dist/peer/chunk-76ZABVTI.js +598 -0
  58. package/dist/peer/chunk-76ZABVTI.js.map +6 -0
  59. package/dist/peer/chunk-BPF3SLL4.js +1282 -0
  60. package/dist/peer/chunk-BPF3SLL4.js.map +6 -0
  61. package/dist/peer/chunk-BWVDLOVL.js +1282 -0
  62. package/dist/peer/chunk-BWVDLOVL.js.map +6 -0
  63. package/dist/peer/chunk-CXM3YSWF.js +1282 -0
  64. package/dist/peer/chunk-CXM3YSWF.js.map +6 -0
  65. package/dist/peer/chunk-DQFZ6LVB.js +1282 -0
  66. package/dist/peer/chunk-DQFZ6LVB.js.map +6 -0
  67. package/dist/peer/chunk-GBITRNHE.js +14806 -0
  68. package/dist/peer/chunk-GBITRNHE.js.map +6 -0
  69. package/dist/peer/chunk-IMQRHDR4.js +12 -0
  70. package/dist/peer/chunk-IMQRHDR4.js.map +6 -0
  71. package/dist/peer/chunk-IPU2YRL2.js +300 -0
  72. package/dist/peer/chunk-IPU2YRL2.js.map +6 -0
  73. package/dist/peer/chunk-KBT6ZGGO.js +1666 -0
  74. package/dist/peer/chunk-KBT6ZGGO.js.map +6 -0
  75. package/dist/peer/chunk-M4AGFUWE.js +97 -0
  76. package/dist/peer/chunk-M4AGFUWE.js.map +6 -0
  77. package/dist/peer/chunk-MCJPN2KL.js +152 -0
  78. package/dist/peer/chunk-MCJPN2KL.js.map +6 -0
  79. package/dist/peer/chunk-NPYKZINU.js +6040 -0
  80. package/dist/peer/chunk-NPYKZINU.js.map +6 -0
  81. package/dist/peer/chunk-PG2PNYDX.js +1282 -0
  82. package/dist/peer/chunk-PG2PNYDX.js.map +6 -0
  83. package/dist/peer/chunk-QRAJXW2D.js +1282 -0
  84. package/dist/peer/chunk-QRAJXW2D.js.map +6 -0
  85. package/dist/peer/chunk-SHVCNAUG.js +1282 -0
  86. package/dist/peer/chunk-SHVCNAUG.js.map +6 -0
  87. package/dist/peer/chunk-Y5CAHLXS.js +218 -0
  88. package/dist/peer/chunk-Y5CAHLXS.js.map +6 -0
  89. package/dist/peer/designer.js +35841 -0
  90. package/dist/peer/designer.js.map +6 -0
  91. package/dist/peer/viewer.js +1061 -0
  92. package/dist/peer/viewer.js.map +6 -0
  93. package/dist/viewer.d.ts +77 -0
  94. package/dist/viewer.js +1066 -0
  95. package/dist/viewer.js.map +6 -0
  96. package/package.json +76 -4
@@ -0,0 +1,1666 @@
1
+ import {
2
+ asciiUrl,
3
+ drillUrl,
4
+ safeUrl
5
+ } from "../chunk-72S6DETS.js";
6
+ import {
7
+ withDeadline
8
+ } from "../chunk-D2NTLAKL.js";
9
+ import {
10
+ needsTableData,
11
+ visualLines
12
+ } from "../chunk-SR2TQ2ZK.js";
13
+ import {
14
+ IMAGE_LIMITS,
15
+ altOf,
16
+ cellVisuals,
17
+ dataUriBytes,
18
+ dataUriBytesOf,
19
+ figures,
20
+ imageInfoOf,
21
+ parseColor,
22
+ svgLength,
23
+ svgRootAttrs,
24
+ xmlAttrs,
25
+ xmlTags
26
+ } from "../chunk-3D43XGIN.js";
27
+
28
+ // src/exporters/pdf.js
29
+ import { PDFDocument, PDFName as PDFName3, PDFString as PDFString4, PDFHexString as PDFHexString5, PDFRawStream as PDFRawStream2, rgb as rgb3 } from "pdf-lib";
30
+ import fontkitModule from "@pdf-lib/fontkit";
31
+
32
+ // src/exporters/pdfa.js
33
+ import { PDFName, PDFNumber, PDFString, PDFHexString, PDFArray, PDFDict } from "pdf-lib";
34
+ var xml = (s) => String(s).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
35
+ function makePdfA(doc, { icc, title = "Report", author, created = /* @__PURE__ */ new Date(), conformance = "B", ua = false, id } = {}) {
36
+ if (!icc?.length) throw new Error("PDF/A needs an sRGB colour profile: pass pdfa.icc (public/icc/sRGB-v2-magic.icc)");
37
+ const when = new Date(Math.floor(created.getTime() / 1e3) * 1e3);
38
+ const stamp = when.toISOString().replace(".000Z", "Z");
39
+ doc.setTitle(title);
40
+ doc.setProducer("ReportWright");
41
+ doc.setCreator("ReportWright");
42
+ if (author) doc.setAuthor(author);
43
+ setInfoDates(doc, when);
44
+ setMetadata(doc, xmpPacket({ title, author, stamp, pdfa: conformance, ua }));
45
+ const ctx = doc.context;
46
+ const profile = ctx.register(ctx.flateStream(icc, { N: 3 }));
47
+ const intent = ctx.register(ctx.obj({ Type: "OutputIntent", S: "GTS_PDFA1", OutputConditionIdentifier: PDFString.of("sRGB"), Info: PDFString.of("sRGB IEC61966-2.1"), DestOutputProfile: profile }));
48
+ doc.catalog.set(PDFName.of("OutputIntents"), ctx.obj([intent]));
49
+ for (const page of doc.getPages()) {
50
+ const annots = page.node.lookup(PDFName.of("Annots"));
51
+ if (!(annots instanceof PDFArray)) continue;
52
+ for (let i = 0; i < annots.size(); i++) {
53
+ const a = annots.lookup(i);
54
+ if (!(a instanceof PDFDict)) continue;
55
+ const f = a.lookup(PDFName.of("F"));
56
+ const flags = f instanceof PDFNumber ? f.asNumber() : 0;
57
+ a.set(PDFName.of("F"), PDFNumber.of((flags | 4) & ~(1 | 2 | 32 | 256)));
58
+ }
59
+ }
60
+ const acro = doc.catalog.lookup(PDFName.of("AcroForm"));
61
+ if (acro instanceof PDFDict) acro.delete(PDFName.of("NeedAppearances"));
62
+ const fileId = id ?? Array.from(crypto.getRandomValues(new Uint8Array(16)), (b) => b.toString(16).padStart(2, "0")).join("").toUpperCase();
63
+ ctx.trailerInfo.ID = ctx.obj([PDFHexString.of(fileId), PDFHexString.of(fileId)]);
64
+ }
65
+ function setInfoDates(doc, when) {
66
+ const s = new Date(Math.floor(when.getTime() / 1e3) * 1e3).toISOString().replace(/\D/g, "").slice(0, 14);
67
+ const info = (
68
+ /** @type {any} */
69
+ doc.getInfoDict()
70
+ );
71
+ info.set(PDFName.of("CreationDate"), PDFString.of(`D:${s}+00'00'`));
72
+ info.set(PDFName.of("ModDate"), PDFString.of(`D:${s}+00'00'`));
73
+ }
74
+ function xmpPacket({ title, author, stamp, pdfa = null, ua = false }) {
75
+ return `<?xpacket begin="\uFEFF" id="W5M0MpCehiHzreSzNTczkc9d"?>
76
+ <x:xmpmeta xmlns:x="adobe:ns:meta/">
77
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
78
+ ${pdfa ? `<rdf:Description rdf:about="" xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/"><pdfaid:part>2</pdfaid:part><pdfaid:conformance>${pdfa}</pdfaid:conformance></rdf:Description>
79
+ ` : ""}${ua ? `<rdf:Description rdf:about="" xmlns:pdfuaid="http://www.aiim.org/pdfua/ns/id/"><pdfuaid:part>1</pdfuaid:part></rdf:Description>
80
+ ` : ""}${ua && pdfa ? PDFUA_SCHEMA : ""}<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:format>application/pdf</dc:format><dc:title><rdf:Alt><rdf:li xml:lang="x-default">${xml(title)}</rdf:li></rdf:Alt></dc:title>${author ? `<dc:creator><rdf:Seq><rdf:li>${xml(author)}</rdf:li></rdf:Seq></dc:creator>` : ""}</rdf:Description>
81
+ <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/"><xmp:CreatorTool>ReportWright</xmp:CreatorTool><xmp:CreateDate>${stamp}</xmp:CreateDate><xmp:ModifyDate>${stamp}</xmp:ModifyDate><xmp:MetadataDate>${stamp}</xmp:MetadataDate></rdf:Description>
82
+ <rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/"><pdf:Producer>ReportWright</pdf:Producer></rdf:Description>
83
+ </rdf:RDF>
84
+ </x:xmpmeta>
85
+ <?xpacket end="w"?>`;
86
+ }
87
+ var PDFUA_SCHEMA = `<rdf:Description rdf:about="" xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/" xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema#" xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property#"><pdfaExtension:schemas><rdf:Bag><rdf:li rdf:parseType="Resource"><pdfaSchema:schema>PDF/UA identification schema</pdfaSchema:schema><pdfaSchema:namespaceURI>http://www.aiim.or\
88
+ g/pdfua/ns/id/</pdfaSchema:namespaceURI><pdfaSchema:prefix>pdfuaid</pdfaSchema:prefix><pdfaSchema:property><rdf:Seq><rdf:li rdf:parseType="Resource"><pdfaProperty:name>part</pdfaProperty:name><pdfaProperty:valueType>Integer</pdfaProperty:valueType><pdfaProperty:category>internal</pdfaProperty:category><pdfaProperty:description>PDF/UA version identifier</pdfaProperty:description></rdf:li></rdf:Seq>\
89
+ </pdfaSchema:property></rdf:li></rdf:Bag></pdfaExtension:schemas></rdf:Description>
90
+ `;
91
+ function setMetadata(doc, xmp) {
92
+ const ctx = doc.context;
93
+ const bytes = new TextEncoder().encode(xmp);
94
+ doc.catalog.set(PDFName.of("Metadata"), ctx.register(ctx.stream(bytes, { Type: "Metadata", Subtype: "XML", Length: bytes.length })));
95
+ }
96
+ function setUaMetadata(doc, { title = "Report", author = void 0, created = /* @__PURE__ */ new Date() } = {}) {
97
+ const when = new Date(Math.floor(created.getTime() / 1e3) * 1e3);
98
+ setInfoDates(doc, when);
99
+ if (author) doc.setAuthor(author);
100
+ setMetadata(doc, xmpPacket({ title, author, stamp: when.toISOString().replace(".000Z", "Z"), ua: true }));
101
+ }
102
+
103
+ // src/exporters/svgimage.js
104
+ import { pushGraphicsState, popGraphicsState, concatTransformationMatrix, rgb } from "pdf-lib";
105
+ var mul = (a, b) => [a[0] * b[0] + a[2] * b[1], a[1] * b[0] + a[3] * b[1], a[0] * b[2] + a[2] * b[3], a[1] * b[2] + a[3] * b[3], a[0] * b[4] + a[2] * b[5] + a[4], a[1] * b[4] + a[3] * b[5] + a[5]];
106
+ var I = [1, 0, 0, 1, 0, 0];
107
+ var TRANSFORMS = /* @__PURE__ */ new Set(["matrix", "translate", "scale", "rotate", "skewX", "skewY"]);
108
+ function parseTransform(s) {
109
+ let m = I;
110
+ const parts = String(s || "").split(")");
111
+ for (let k = 0; k < parts.length && k < 64; k++) {
112
+ const part = parts[k], p = part.indexOf("(");
113
+ if (p < 0) continue;
114
+ const fn = part.slice(0, p).replace(/[\s,]/g, "");
115
+ if (!TRANSFORMS.has(fn)) continue;
116
+ const a = part.slice(p + 1, p + 200).split(/[\s,]+/).filter(Boolean).map(Number);
117
+ if (a.some((x) => !Number.isFinite(x))) continue;
118
+ const r = (d) => d * Math.PI / 180;
119
+ let t = I;
120
+ if (fn === "matrix" && a.length === 6) t = /** @type {M} */
121
+ a;
122
+ else if (fn === "translate") t = [1, 0, 0, 1, a[0] || 0, a[1] || 0];
123
+ else if (fn === "scale") t = [a[0] ?? 1, 0, 0, a[1] ?? a[0] ?? 1, 0, 0];
124
+ else if (fn === "rotate") {
125
+ const c = Math.cos(r(a[0] || 0)), sn = Math.sin(r(a[0] || 0)), cx = a[1] || 0, cy = a[2] || 0;
126
+ t = mul(mul([1, 0, 0, 1, cx, cy], [c, sn, -sn, c, 0, 0]), [1, 0, 0, 1, -cx, -cy]);
127
+ } else if (fn === "skewX") t = [1, 0, Math.tan(r(a[0] || 0)), 1, 0, 0];
128
+ else if (fn === "skewY") t = [1, Math.tan(r(a[0] || 0)), 0, 1, 0, 0];
129
+ m = mul(m, t);
130
+ }
131
+ return m;
132
+ }
133
+ function attrs(s) {
134
+ const a = xmlAttrs(s);
135
+ for (const d of String(a.style || "").split(";")) {
136
+ const i = d.indexOf(":");
137
+ if (i > 0) a[d.slice(0, i).trim()] = d.slice(i + 1).trim();
138
+ }
139
+ return a;
140
+ }
141
+ var num = (v, d = 0) => {
142
+ const n = parseFloat(v);
143
+ return Number.isFinite(n) ? n : d;
144
+ };
145
+ var pts = (v) => (String(v || "").match(/-?[\d.]+(?:e[-+]?\d+)?/gi) || []).map(Number);
146
+ function shapePath(tag, a) {
147
+ switch (tag) {
148
+ case "path":
149
+ return a.d || null;
150
+ case "rect": {
151
+ const x = num(a.x), y = num(a.y), w = num(a.width), h = num(a.height);
152
+ if (!(w > 0 && h > 0)) return null;
153
+ let rx = num(a.rx, NaN), ry = num(a.ry, NaN);
154
+ if (!Number.isFinite(rx)) rx = Number.isFinite(ry) ? ry : 0;
155
+ if (!Number.isFinite(ry)) ry = rx;
156
+ rx = Math.min(Math.max(rx, 0), w / 2);
157
+ ry = Math.min(Math.max(ry, 0), h / 2);
158
+ if (!rx || !ry) return `M${x} ${y}H${x + w}V${y + h}H${x}Z`;
159
+ return `M${x + rx} ${y}H${x + w - rx}A${rx} ${ry} 0 0 1 ${x + w} ${y + ry}V${y + h - ry}A${rx} ${ry} 0 0 1 ${x + w - rx} ${y + h}H${x + rx}A${rx} ${ry} 0 0 1 ${x} ${y + h - ry}V${y + ry}A${rx} ${ry} 0 0 1 ${x + rx} ${y}Z`;
160
+ }
161
+ case "circle":
162
+ case "ellipse": {
163
+ const cx = num(a.cx), cy = num(a.cy), rx = tag === "circle" ? num(a.r) : num(a.rx), ry = tag === "circle" ? num(a.r) : num(a.ry);
164
+ if (!(rx > 0 && ry > 0)) return null;
165
+ return `M${cx - rx} ${cy}A${rx} ${ry} 0 1 0 ${cx + rx} ${cy}A${rx} ${ry} 0 1 0 ${cx - rx} ${cy}Z`;
166
+ }
167
+ case "line":
168
+ return `M${num(a.x1)} ${num(a.y1)}L${num(a.x2)} ${num(a.y2)}`;
169
+ case "polyline":
170
+ case "polygon": {
171
+ const p = pts(a.points);
172
+ if (p.length < 4) return null;
173
+ let d = `M${p[0]} ${p[1]}`;
174
+ for (let i = 2; i + 1 < p.length; i += 2) d += `L${p[i]} ${p[i + 1]}`;
175
+ return tag === "polygon" ? d + "Z" : d;
176
+ }
177
+ }
178
+ return null;
179
+ }
180
+ var SKIP = /* @__PURE__ */ new Set(["defs", "clipPath", "mask", "pattern", "linearGradient", "radialGradient", "symbol", "marker", "text", "style", "script", "title", "desc", "metadata", "filter", "foreignObject"]);
181
+ function parseSvg(text) {
182
+ if (typeof text !== "string" || text.length > IMAGE_LIMITS.svgBytes) return null;
183
+ const root = svgRootAttrs(text);
184
+ if (!root) return null;
185
+ const vb = String(root.viewBox || "").trim().split(/[\s,]+/).map(Number);
186
+ const hasVb = vb.length === 4 && vb.every(Number.isFinite) && vb[2] > 0 && vb[3] > 0;
187
+ const w = svgLength(root.width) || (hasVb ? vb[2] : 0), h = svgLength(root.height) || (hasVb ? vb[3] : 0);
188
+ if (!(w > 0 && h > 0)) return null;
189
+ let base = I;
190
+ if (hasVb) {
191
+ const s = Math.min(w / vb[2], h / vb[3]);
192
+ base = [s, 0, 0, s, (w - vb[2] * s) / 2 - vb[0] * s, (h - vb[3] * s) / 2 - vb[1] * s];
193
+ }
194
+ const shapes = [];
195
+ const top = { m: base, fill: "#000", stroke: "none", sw: 1, op: 1, fo: 1, so: 1, skip: 0 };
196
+ const stack = [top];
197
+ let seenRoot = false;
198
+ for (const { close, name: tag, attrs: rest, self } of xmlTags(text)) {
199
+ const cur = stack[stack.length - 1];
200
+ if (close) {
201
+ if (stack.length > 1) stack.pop();
202
+ continue;
203
+ }
204
+ if (tag === "svg" && !seenRoot) {
205
+ seenRoot = true;
206
+ if (self) break;
207
+ continue;
208
+ }
209
+ const a = attrs(rest);
210
+ const g = {
211
+ m: a.transform ? mul(cur.m, parseTransform(a.transform)) : cur.m,
212
+ fill: a.fill ?? cur.fill,
213
+ stroke: a.stroke ?? cur.stroke,
214
+ sw: a["stroke-width"] != null ? num(a["stroke-width"], cur.sw) : cur.sw,
215
+ op: cur.op * (a.opacity != null ? Math.min(1, Math.max(0, num(a.opacity, 1))) : 1),
216
+ fo: a["fill-opacity"] != null ? num(a["fill-opacity"], 1) : cur.fo,
217
+ so: a["stroke-opacity"] != null ? num(a["stroke-opacity"], 1) : cur.so,
218
+ skip: cur.skip || (SKIP.has(tag) || a.display === "none" || a.visibility === "hidden" ? 1 : 0)
219
+ };
220
+ if (tag === "svg") {
221
+ g.m = mul(g.m, [1, 0, 0, 1, num(a.x), num(a.y)]);
222
+ }
223
+ if (!g.skip) {
224
+ const d = shapePath(tag, a);
225
+ if (d) {
226
+ if (shapes.length >= IMAGE_LIMITS.svgShapes) break;
227
+ const fill = tag === "line" ? null : parseColor(paint(g.fill));
228
+ shapes.push({ d, m: g.m, fill, stroke: parseColor(paint(g.stroke)), sw: g.sw, fo: g.fo * g.op, so: g.so * g.op });
229
+ }
230
+ }
231
+ if (!self && !/^(path|rect|circle|ellipse|line|polyline|polygon|image|use)$/.test(tag)) stack.push(g);
232
+ }
233
+ return { w, h, shapes };
234
+ }
235
+ var clamp01 = (v) => Number.isFinite(v) ? Math.min(1, Math.max(0, v)) : 1;
236
+ var paint = (v) => v === "currentColor" ? "#000" : /^url\(/.test(String(v || "")) ? "none" : v;
237
+ function drawSvg(page, svg, at) {
238
+ const place = [at.sx, 0, 0, -at.sy, at.x, at.y + svg.h * at.sy];
239
+ for (const s of svg.shapes) {
240
+ if (!s.fill && !s.stroke) continue;
241
+ const m = mul(mul(place, s.m), [1, 0, 0, -1, 0, 0]);
242
+ if (!m.every(Number.isFinite)) continue;
243
+ page.pushOperators(pushGraphicsState(), concatTransformationMatrix(...m));
244
+ try {
245
+ page.drawSvgPath(s.d, {
246
+ x: 0,
247
+ y: 0,
248
+ color: s.fill ? rgb(s.fill.r, s.fill.g, s.fill.b) : void 0,
249
+ opacity: s.fill ? clamp01(s.fill.a * s.fo) : void 0,
250
+ borderColor: s.stroke ? rgb(s.stroke.r, s.stroke.g, s.stroke.b) : void 0,
251
+ borderWidth: s.stroke ? s.sw : 0,
252
+ borderOpacity: s.stroke ? clamp01(s.stroke.a * s.so) : void 0
253
+ });
254
+ } catch {
255
+ }
256
+ page.pushOperators(popGraphicsState());
257
+ }
258
+ }
259
+
260
+ // src/exporters/encrypt.js
261
+ import { PDFArray as PDFArray2, PDFDict as PDFDict2, PDFNumber as PDFNumber2, PDFString as PDFString2, PDFHexString as PDFHexString2, PDFRawStream, PDFStream, PDFBool } from "pdf-lib";
262
+ var subtle = () => {
263
+ const s = globalThis.crypto?.subtle;
264
+ if (!s) throw new Error("PDF encryption needs WebCrypto (a browser, or Node 20 or later)");
265
+ return s;
266
+ };
267
+ var random = (n) => globalThis.crypto.getRandomValues(new Uint8Array(n));
268
+ var cat = (...parts) => {
269
+ const out = new Uint8Array(parts.reduce((s, p) => s + p.length, 0));
270
+ let o = 0;
271
+ for (const p of parts) {
272
+ out.set(p, o);
273
+ o += p.length;
274
+ }
275
+ return out;
276
+ };
277
+ var hex = (b) => Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
278
+ async function aesCbc(key, iv, data) {
279
+ const k = await subtle().importKey("raw", key, "AES-CBC", false, ["encrypt"]);
280
+ return new Uint8Array(await subtle().encrypt({ name: "AES-CBC", iv }, k, data));
281
+ }
282
+ var aesCbcNoPad = async (key, iv, data) => (await aesCbc(key, iv, data)).subarray(0, data.length);
283
+ var sha = async (alg, data) => new Uint8Array(await subtle().digest(alg, data));
284
+ async function hash2B(pw, salt, udata) {
285
+ let K = await sha("SHA-256", cat(pw, salt, udata));
286
+ for (let round = 0; ; round++) {
287
+ const one = cat(pw, K, udata);
288
+ const K1 = new Uint8Array(one.length * 64);
289
+ for (let i = 0; i < 64; i++) K1.set(one, i * one.length);
290
+ const E = await aesCbcNoPad(K.subarray(0, 16), K.subarray(16, 32), K1);
291
+ let mod = 0;
292
+ for (let i = 0; i < 16; i++) mod += E[i];
293
+ K = await sha(["SHA-256", "SHA-384", "SHA-512"][mod % 3], E);
294
+ if (round >= 63 && E[E.length - 1] <= round + 1 - 32) break;
295
+ }
296
+ return K.subarray(0, 32);
297
+ }
298
+ function passwordBytes(pw, which) {
299
+ const b = new TextEncoder().encode(String(pw ?? "").normalize("NFKC"));
300
+ if (b.length > 127) throw Object.assign(new Error(`The ${which} password is too long (at most 127 bytes in UTF-8)`), { status: 400 });
301
+ return b;
302
+ }
303
+ var PERMISSION_BITS = { print: 3, modify: 4, copy: 5, annotate: 6, fillForms: 9, accessibility: 10, assemble: 11, printHighQuality: 12 };
304
+ function permissionsValue(perms = {}) {
305
+ for (const k of Object.keys(perms)) if (!(k in PERMISSION_BITS)) throw Object.assign(new Error(`Unknown PDF permission "${String(k).slice(0, 40)}". Use ${Object.keys(PERMISSION_BITS).join(", ")}.`), { status: 400 });
306
+ let p = 4294963392;
307
+ for (const [k, bit] of Object.entries(PERMISSION_BITS)) if (perms[k] !== false) p |= 1 << bit - 1;
308
+ return p | 0;
309
+ }
310
+ async function encryptPdf(doc, opt) {
311
+ const user = passwordBytes(opt.userPassword, "user");
312
+ const owner = opt.ownerPassword != null && opt.ownerPassword !== "" ? passwordBytes(opt.ownerPassword, "owner") : random(32);
313
+ const P = permissionsValue(opt.permissions || {});
314
+ const fileKey = random(32);
315
+ const zero = new Uint8Array(16);
316
+ const uvs = random(8), uks = random(8);
317
+ const U = cat(await hash2B(user, uvs, new Uint8Array()), uvs, uks);
318
+ const UE = await aesCbcNoPad(await hash2B(user, uks, new Uint8Array()), zero, fileKey);
319
+ const ovs = random(8), oks = random(8);
320
+ const O = cat(await hash2B(owner, ovs, U), ovs, oks);
321
+ const OE = await aesCbcNoPad(await hash2B(owner, oks, U), zero, fileKey);
322
+ const perms = new Uint8Array(16);
323
+ new DataView(perms.buffer).setInt32(0, P, true);
324
+ perms.set([255, 255, 255, 255, 84, 97, 100, 98], 4);
325
+ perms.set(random(4), 12);
326
+ const Perms = await aesCbcNoPad(fileKey, zero, perms);
327
+ await doc.flush();
328
+ const ctx = doc.context;
329
+ const enc = async (bytes) => {
330
+ const iv = random(16);
331
+ return cat(iv, await aesCbc(fileKey, iv, bytes));
332
+ };
333
+ const seen = /* @__PURE__ */ new Set();
334
+ const walk = async (obj) => {
335
+ if (obj instanceof PDFString2 || obj instanceof PDFHexString2) return PDFHexString2.of(hex(await enc(obj.asBytes())));
336
+ if (obj instanceof PDFArray2) {
337
+ for (let i = 0; i < obj.size(); i++) obj.set(i, await walk(obj.get(i)));
338
+ return obj;
339
+ }
340
+ if (obj instanceof PDFDict2) {
341
+ if (seen.has(obj)) return obj;
342
+ seen.add(obj);
343
+ for (const [k, v] of obj.entries()) obj.set(k, await walk(v));
344
+ return obj;
345
+ }
346
+ if (obj instanceof PDFStream) {
347
+ await walk(obj.dict);
348
+ const contents = obj instanceof PDFRawStream ? obj.contents : (
349
+ /** @type {any} */
350
+ obj.getContents()
351
+ );
352
+ return PDFRawStream.of(obj.dict, await enc(contents));
353
+ }
354
+ return obj;
355
+ };
356
+ for (const [ref, obj] of ctx.enumerateIndirectObjects()) ctx.assign(ref, await walk(obj));
357
+ const encrypt = ctx.obj({
358
+ Filter: "Standard",
359
+ V: 5,
360
+ R: 6,
361
+ Length: 256,
362
+ CF: { StdCF: { AuthEvent: "DocOpen", CFM: "AESV3", Length: 32 } },
363
+ StmF: "StdCF",
364
+ StrF: "StdCF",
365
+ O: PDFHexString2.of(hex(O)),
366
+ U: PDFHexString2.of(hex(U)),
367
+ OE: PDFHexString2.of(hex(OE)),
368
+ UE: PDFHexString2.of(hex(UE)),
369
+ P: PDFNumber2.of(P),
370
+ Perms: PDFHexString2.of(hex(Perms)),
371
+ EncryptMetadata: PDFBool.True
372
+ });
373
+ ctx.trailerInfo.Encrypt = ctx.register(encrypt);
374
+ const id = PDFHexString2.of(hex(random(16)));
375
+ ctx.trailerInfo.ID = ctx.obj([id, id]);
376
+ }
377
+
378
+ // src/exporters/pdfua.js
379
+ import { PDFName as PDFName2, PDFNumber as PDFNumber3, PDFHexString as PDFHexString3, PDFDict as PDFDict3, PDFArray as PDFArray3, PDFString as PDFString3 } from "pdf-lib";
380
+ var MARKER = /^\s*(?:[•◦▪▫‣·○●■□–—-]|\d{1,4}[.)]|[a-zA-Z][.)]|[ivxlcdmIVXLCDM]{1,6}[.)])\s*$/;
381
+ function createTagger(model, doc) {
382
+ const ctx = doc.context;
383
+ const root = node("Document");
384
+ const plans = model.pages.map((pg, pi) => {
385
+ const p = plan(model, pg, pi, root);
386
+ endPage(root);
387
+ return p;
388
+ });
389
+ const mcids = model.pages.map(() => []);
390
+ const annots = [];
391
+ return {
392
+ /**
393
+ * Marked content around item ii of page pi: the operator that opens it, or null (nothing is drawn for it).
394
+ * @returns {string|null}
395
+ */
396
+ open(pi, ii, it) {
397
+ if (it.t === "link" || it.t === "field" || it.t === "bookmark") return null;
398
+ const p = plans[pi].get(ii);
399
+ if (!p?.el) return p?.art === "Pagination" ? "/Artifact <</Type /Pagination>> BDC\n" : "/Artifact BMC\n";
400
+ const mcid = mcids[pi].length;
401
+ mcids[pi].push(p.el);
402
+ p.el.kids.push({ mcid, pi });
403
+ return `/${p.el.S === "Document" ? "P" : p.el.S} <</MCID ${mcid}>> BDC
404
+ `;
405
+ },
406
+ /** A link annotation of item ii (or a field's widget): its structure element; returns its StructParent key. */
407
+ annot(pi, ii, ref, kind) {
408
+ const p = plans[pi].get(ii);
409
+ const el = node(kind === "field" ? "Form" : "Link");
410
+ (p?.near || root).kids.push(el);
411
+ el.parent = p?.near || root;
412
+ el.kids.push({ objr: ref, pi });
413
+ annots.push({ ref, el, pi });
414
+ },
415
+ finish({ lang = "en", title = "Report" } = {}) {
416
+ const pages = doc.getPages();
417
+ const refOf = /* @__PURE__ */ new Map();
418
+ const all = [];
419
+ for (const t of root.tables?.values() || []) regular(t);
420
+ const walk = (n) => {
421
+ refOf.set(n, ctx.nextRef());
422
+ all.push(n);
423
+ for (const k of n.kids) if (k.S) {
424
+ k.parent || (k.parent = n);
425
+ walk(k);
426
+ }
427
+ };
428
+ walk(root);
429
+ const nums = [];
430
+ let key = 0;
431
+ pages.forEach((pg, pi) => {
432
+ if (!mcids[pi].length) return;
433
+ pg.node.set(PDFName2.of("StructParents"), PDFNumber3.of(key));
434
+ nums.push(PDFNumber3.of(key++), ctx.obj(mcids[pi].map((n) => refOf.get(n))));
435
+ });
436
+ for (const a of annots) {
437
+ const d = ctx.lookup(a.ref);
438
+ if (d instanceof PDFDict3) d.set(PDFName2.of("StructParent"), PDFNumber3.of(key));
439
+ nums.push(PDFNumber3.of(key++), refOf.get(a.el));
440
+ pages[a.pi]?.node.set(PDFName2.of("Tabs"), PDFName2.of("S"));
441
+ }
442
+ const treeRef = ctx.nextRef();
443
+ for (const n of all) {
444
+ const pgOf = n.kids.find((k) => k.mcid != null)?.pi;
445
+ const K = n.kids.map((k) => {
446
+ if (k.S) return refOf.get(k);
447
+ if (k.objr) return ctx.obj({ Type: "OBJR", Obj: k.objr, Pg: pages[k.pi].ref });
448
+ return k.pi === pgOf ? PDFNumber3.of(k.mcid) : ctx.obj({ Type: "MCR", Pg: pages[k.pi].ref, MCID: k.mcid });
449
+ });
450
+ const d = ctx.obj({ Type: "StructElem", S: n.S, P: n === root ? treeRef : refOf.get(n.parent || root), K });
451
+ if (pgOf != null) d.set(PDFName2.of("Pg"), pages[pgOf].ref);
452
+ if (n.alt != null) d.set(PDFName2.of("Alt"), PDFHexString3.fromText(n.alt));
453
+ if (n.attrs) d.set(PDFName2.of("A"), ctx.obj(n.attrs));
454
+ ctx.assign(refOf.get(n), d);
455
+ }
456
+ ctx.assign(treeRef, ctx.obj({ Type: "StructTreeRoot", K: refOf.get(root), ParentTree: ctx.obj({ Nums: nums }), ParentTreeNextKey: key }));
457
+ const cat2 = doc.catalog;
458
+ cat2.set(PDFName2.of("StructTreeRoot"), treeRef);
459
+ cat2.set(PDFName2.of("MarkInfo"), ctx.obj({ Marked: true }));
460
+ cat2.set(PDFName2.of("Lang"), PDFString3.of(String(lang).replace(/[^A-Za-z0-9-]/g, "") || "en"));
461
+ cat2.set(PDFName2.of("ViewerPreferences"), ctx.obj({ DisplayDocTitle: true }));
462
+ doc.setTitle(title, { showInWindowTitleBar: true });
463
+ }
464
+ };
465
+ }
466
+ function node(S, extra = {}) {
467
+ return (
468
+ /** @type {any} */
469
+ { S, kids: [], ...extra }
470
+ );
471
+ }
472
+ function plan(model, pg, pi, root) {
473
+ const items = pg.items;
474
+ const out = /* @__PURE__ */ new Map();
475
+ const H = pg.height ?? model.height;
476
+ const figAt = /* @__PURE__ */ new Map();
477
+ for (const f of figures(items)) {
478
+ const deco = (f.tag.k === "shape" || f.tag.k === "line") && !f.tag.alt;
479
+ for (let k = f.at; k <= f.last; k++) figAt.set(k, deco ? "deco" : f);
480
+ }
481
+ const marks = (model.bookmarks || []).filter((b) => b.page === pi + 1);
482
+ const headingOf = (it) => {
483
+ if (it.tag?.h) return Math.min(6, Math.max(1, it.tag.h));
484
+ if (!marks.length || !it.clip) return 0;
485
+ const txt = visualLines(it).join(" ").trim();
486
+ const b = marks.find((m) => Math.abs(m.y - it.clip.y) < 1 && txt && String(m.label).trim().startsWith(txt.slice(0, 40)));
487
+ return b ? Math.min(6, (Number(b.level) || 0) + 1) : 0;
488
+ };
489
+ const tables = root.tables || (root.tables = /* @__PURE__ */ new Map());
490
+ const rich = /* @__PURE__ */ new Map();
491
+ let list = null, listId = null;
492
+ const figEls = /* @__PURE__ */ new Map();
493
+ const cellsByTable = /* @__PURE__ */ new Map();
494
+ for (const it of items) if (it.t === "text" && it.cell && !it.art) (cellsByTable.get(it.cell.table) || cellsByTable.set(it.cell.table, { cells: [] }).get(it.cell.table)).cells.push(it);
495
+ const visAt = /* @__PURE__ */ new Map();
496
+ const taken = /* @__PURE__ */ new Set([...figAt.keys()]);
497
+ const index = new Map(items.map((it, i) => [it, i]));
498
+ for (const [tkey, m] of cellVisuals(items, taken, cellsByTable)) {
499
+ const proto = cellsByTable.get(tkey).cells[0].cell;
500
+ for (const [rc, v] of m) {
501
+ const [row, col2] = rc.split("|");
502
+ const rowCell = cellsByTable.get(tkey).cells.find((c) => String(c.cell.row) === row)?.cell;
503
+ const vis = { cell: { ...proto, row: rowCell ? rowCell.row : row, col: Number(col2), kind: rowCell?.kind || "detail", span: 1, rowSpan: 1 } };
504
+ for (const it of v.items) visAt.set(index.get(it), { vis, box: v.box, kind: v.items.some((x) => x.t === "path") ? "sparkline" : "databar" });
505
+ }
506
+ }
507
+ const add = (el) => {
508
+ root.kids.push(el);
509
+ el.parent = root;
510
+ return el;
511
+ };
512
+ let lastText = null;
513
+ items.forEach((it, i) => {
514
+ if (it.t === "bookmark") return;
515
+ if (it.t === "link" || it.t === "field") {
516
+ out.set(i, { near: lastText && overlaps(lastText.it, it) ? lastText.el : null });
517
+ return;
518
+ }
519
+ const f = figAt.get(i);
520
+ if (f === "deco") {
521
+ out.set(i, { art: "Layout" });
522
+ return;
523
+ }
524
+ if (it.art) {
525
+ out.set(i, { art: "Pagination" });
526
+ return;
527
+ }
528
+ const vis = visAt.get(i);
529
+ if (vis) {
530
+ let el2 = figEls.get(vis.vis);
531
+ if (!el2) {
532
+ const td = cellEl(tables, root, vis.vis, add);
533
+ if (td.art) {
534
+ out.set(i, { art: "Layout" });
535
+ return;
536
+ }
537
+ const b = vis.box;
538
+ el2 = node("Figure", { alt: "Chart in a table cell", attrs: { O: "Layout", BBox: [r2(b.x), r2(H - b.y - b.h), r2(b.x + b.w), r2(H - b.y)] } });
539
+ el2.parent = td;
540
+ td.kids.push(el2);
541
+ figEls.set(vis.vis, el2);
542
+ }
543
+ out.set(i, { el: el2 });
544
+ return;
545
+ }
546
+ if (f) {
547
+ let el2 = figEls.get(f);
548
+ if (!el2) {
549
+ const b = f.box;
550
+ el2 = add(node("Figure", { alt: altOf(f.tag), attrs: { O: "Layout", BBox: [r2(b.x), r2(H - b.y - b.h), r2(b.x + b.w), r2(H - b.y)] } }));
551
+ figEls.set(f, el2);
552
+ }
553
+ out.set(i, { el: el2 });
554
+ return;
555
+ }
556
+ if (it.t !== "text" || !it.lines?.length || !visualLines(it).join("").trim()) {
557
+ out.set(i, { art: "Layout" });
558
+ return;
559
+ }
560
+ let el;
561
+ if (it.cell) el = cellEl(tables, root, it, add);
562
+ else if (it.rich) {
563
+ const key = `${it.rich.id}${it.rich.p}`;
564
+ el = rich.get(key);
565
+ if (!el) {
566
+ const marker = MARKER.test(it.lines[0].text);
567
+ if (marker) {
568
+ if (listId !== it.rich.id || !list) {
569
+ list = add(node("L"));
570
+ listId = it.rich.id;
571
+ }
572
+ const li = node("LI");
573
+ li.parent = list;
574
+ list.kids.push(li);
575
+ const lbl = node("Lbl");
576
+ lbl.parent = li;
577
+ li.kids.push(lbl);
578
+ const body = node("LBody");
579
+ body.parent = li;
580
+ li.kids.push(body);
581
+ rich.set(key, body);
582
+ out.set(i, { el: lbl });
583
+ lastText = { it, el: body };
584
+ return;
585
+ }
586
+ list = null;
587
+ const h = headingOf(it);
588
+ el = add(node(h ? `H${h}` : "P"));
589
+ rich.set(key, el);
590
+ }
591
+ } else {
592
+ const h = headingOf(it);
593
+ el = add(node(h ? `H${h}` : "P"));
594
+ }
595
+ if (el.art) {
596
+ out.set(i, { art: "Pagination" });
597
+ return;
598
+ }
599
+ out.set(i, { el });
600
+ lastText = { it, el };
601
+ });
602
+ return out;
603
+ }
604
+ var r2 = (v) => Math.round(v * 100) / 100;
605
+ function overlaps(t, l) {
606
+ const c = t.clip || { x: t.lines[0].x, y: t.lines[0].y - t.size, w: t.lines[0].w || 0, h: t.size * 1.3 };
607
+ return l.x < c.x + c.w && c.x < l.x + l.w && l.y < c.y + c.h && c.y < l.y + l.h;
608
+ }
609
+ function cellEl(tables, root, it, add) {
610
+ const c = it.cell;
611
+ let t = tables.get(c.table);
612
+ if (!t || t.closed) {
613
+ t = { el: add(node("Table")), rows: /* @__PURE__ */ new Map(), cols: c.cols.length };
614
+ tables.set(c.table, t);
615
+ for (const [k, o] of tables) if (k !== c.table) o.closed = true;
616
+ }
617
+ let r = t.rows.get(c.row);
618
+ if (!r) {
619
+ r = { el: node("TR"), cells: /* @__PURE__ */ new Map(), kind: c.kind };
620
+ r.el.parent = t.el;
621
+ t.el.kids.push(r.el);
622
+ t.rows.set(c.row, r);
623
+ } else if (c.kind === "header" && r.done) return { art: true };
624
+ let cell = r.cells.get(c.col);
625
+ if (!cell) {
626
+ const attrs2 = { O: "Table" };
627
+ if (c.kind === "header") attrs2.Scope = "Column";
628
+ if (c.span > 1) attrs2.ColSpan = c.span;
629
+ if (c.rowSpan > 1) attrs2.RowSpan = c.rowSpan;
630
+ cell = node(c.kind === "header" ? "TH" : "TD", { attrs: attrs2 });
631
+ cell.parent = r.el;
632
+ r.el.kids.push(cell);
633
+ r.cells.set(c.col, cell);
634
+ }
635
+ r.pageSeen = true;
636
+ return cell;
637
+ }
638
+ function endPage(root) {
639
+ for (const t of root.tables?.values() || []) for (const r of t.rows.values()) if (r.kind === "header") r.done = true;
640
+ }
641
+ function regular(t) {
642
+ const down = /* @__PURE__ */ new Map();
643
+ for (const r of t.rows.values()) {
644
+ const kids = [];
645
+ for (let c = 0; c < t.cols; ) {
646
+ const left = down.get(c);
647
+ if (left) {
648
+ if (left.n <= 1) down.delete(c);
649
+ else left.n--;
650
+ c += left.span;
651
+ continue;
652
+ }
653
+ let cell = r.cells.get(c);
654
+ if (!cell) {
655
+ cell = node(r.kind === "header" ? "TH" : "TD", { attrs: r.kind === "header" ? { O: "Table", Scope: "Column" } : void 0 });
656
+ cell.parent = r.el;
657
+ }
658
+ const span = Math.max(1, cell.attrs?.ColSpan || 1), rs = Math.max(1, cell.attrs?.RowSpan || 1);
659
+ if (rs > 1) down.set(c, { n: rs - 1, span });
660
+ kids.push(cell);
661
+ c += span;
662
+ }
663
+ const placed = new Set(kids);
664
+ const rest = [...r.cells.entries()].sort((x, y) => x[0] - y[0]).map((e) => e[1]).filter((k) => !placed.has(k));
665
+ r.el.kids = [...kids, ...rest, ...r.el.kids.filter((k) => !k.S || k.S !== "TD" && k.S !== "TH")];
666
+ }
667
+ }
668
+
669
+ // src/exporters/png.js
670
+ import { Unzlib } from "fflate";
671
+ var CRC = new Uint32Array(256).map((_, n) => {
672
+ let c = n;
673
+ for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
674
+ return c >>> 0;
675
+ });
676
+ function crc32(b, from, to) {
677
+ let c = 4294967295;
678
+ for (let i = from; i < to; i++) c = CRC[(c ^ b[i]) & 255] ^ c >>> 8;
679
+ return (c ^ 4294967295) >>> 0;
680
+ }
681
+ var CHANNELS = { 0: 1, 2: 3, 3: 1, 4: 2, 6: 4 };
682
+ var PNG_LIMITS = { pixels: 1e8, rawBytes: 256 * 1048576, chunks: 4096 };
683
+ function rawBytes(w, h, bits, interlace) {
684
+ const line = (pw) => pw > 0 ? 1 + Math.ceil(pw * bits / 8) : 0;
685
+ if (!interlace) return h * line(w);
686
+ let n = 0;
687
+ for (const [x0, y0, dx, dy] of [[0, 0, 8, 8], [4, 0, 8, 8], [0, 4, 4, 8], [2, 0, 4, 4], [0, 2, 2, 4], [1, 0, 2, 2], [0, 1, 1, 2]]) {
688
+ const pw = Math.ceil((w - x0) / dx), ph = Math.ceil((h - y0) / dy);
689
+ if (pw > 0 && ph > 0) n += ph * line(pw);
690
+ }
691
+ return n;
692
+ }
693
+ function pngProblem(b) {
694
+ const SIG = [137, 80, 78, 71, 13, 10, 26, 10];
695
+ if (b.length < 8 || SIG.some((x, i) => b[i] !== x)) return "not a PNG";
696
+ const u32 = (i) => (b[i] << 24 | b[i + 1] << 16 | b[i + 2] << 8 | b[i + 3]) >>> 0;
697
+ let off = 8, ihdr = null, idat = [], end = false, first = true, chunks = 0;
698
+ while (off < b.length) {
699
+ if (++chunks > PNG_LIMITS.chunks) return `more than ${PNG_LIMITS.chunks} chunks`;
700
+ if (off + 12 > b.length) return "the file is cut short";
701
+ const len = u32(off);
702
+ if (off + 12 + len > b.length) return "the file is cut short";
703
+ const t = String.fromCharCode(b[off + 4], b[off + 5], b[off + 6], b[off + 7]);
704
+ if (crc32(b, off + 4, off + 8 + len) !== u32(off + 8 + len)) return `the ${t} chunk is damaged (CRC)`;
705
+ const d = off + 8;
706
+ if (first && t !== "IHDR") return "IHDR is not first";
707
+ first = false;
708
+ if (t === "IHDR") {
709
+ if (ihdr || len !== 13) return "a bad IHDR";
710
+ ihdr = { w: u32(d), h: u32(d + 4), depth: b[d + 8], color: b[d + 9], interlace: b[d + 12] };
711
+ if (ihdr.w * ihdr.h > PNG_LIMITS.pixels) return `${ihdr.w}×${ihdr.h} pixels, more than ${PNG_LIMITS.pixels / 1e6} MP`;
712
+ } else if (t === "IDAT") idat.push(b.subarray(d, d + len));
713
+ else if (t === "IEND") {
714
+ end = true;
715
+ break;
716
+ }
717
+ off = d + len + 4;
718
+ }
719
+ if (!ihdr) return "no IHDR";
720
+ if (!idat.length) return "no image data (IDAT)";
721
+ if (!end) return "no IEND: the file is cut short";
722
+ const ch = CHANNELS[ihdr.color];
723
+ if (!ch || ![1, 2, 4, 8, 16].includes(ihdr.depth) || ihdr.w < 1 || ihdr.h < 1 || ihdr.interlace > 1) return "an unsupported PNG header";
724
+ const want = rawBytes(ihdr.w, ihdr.h, ch * ihdr.depth, ihdr.interlace);
725
+ if (want > PNG_LIMITS.rawBytes) return `${Math.round(want / 1048576)} MB of pixel data, more than ${PNG_LIMITS.rawBytes / 1048576} MB`;
726
+ let got = 0, over = false, failed = false;
727
+ const OVER = new Error("over");
728
+ const z = new Unzlib((chunk) => {
729
+ got += chunk.length;
730
+ if (got > want) {
731
+ over = true;
732
+ throw OVER;
733
+ }
734
+ });
735
+ try {
736
+ for (let i = 0; i < idat.length && !over; i++) z.push(idat[i], i === idat.length - 1);
737
+ } catch (e) {
738
+ if (e !== OVER) failed = true;
739
+ }
740
+ if (failed) return "the image data does not inflate";
741
+ if (over) return "the image data is larger than its header says";
742
+ if (got !== want) return "the image data is cut short";
743
+ return null;
744
+ }
745
+
746
+ // src/exporters/pdfpaint.js
747
+ import { PDFHexString as PDFHexString4, rgb as rgb2 } from "pdf-lib";
748
+ var colors = /* @__PURE__ */ new Map();
749
+ var col = (c) => {
750
+ if (colors.has(c)) return colors.get(c);
751
+ const p = parseColor(c), v = p ? { color: rgb2(p.r, p.g, p.b), opacity: p.a, rgb: `${n3(p.r)} ${n3(p.g)} ${n3(p.b)}` } : null;
752
+ if (colors.size < 1e3) colors.set(c, v);
753
+ return v;
754
+ };
755
+ var BLACK = { color: rgb2(0, 0, 0), opacity: 1, rgb: "0 0 0" };
756
+ var n2 = (v) => Math.round(v * 100) / 100;
757
+ var n3 = (v) => Math.round(v * 1e3) / 1e3;
758
+ var n4 = (v) => Math.round(v * 1e4) / 1e4;
759
+ var hex4 = (id) => id.toString(16).padStart(4, "0");
760
+ var KAPPA = 4 * ((Math.SQRT2 - 1) / 3);
761
+ var cleanText = (t) => t.replace(/\t|\u0085|\u2028|\u2029/g, " ").replace(/[\b\v]/g, "");
762
+ function drawRun(c, run, x, y, size, pf, color, spans, texts) {
763
+ const f = pf.embedder.font;
764
+ const per = 1e3 / size;
765
+ const span = (text) => `/Span <</ActualText ${PDFHexString4.fromText(text).toString()}>> BDC
766
+ `;
767
+ c.et();
768
+ c.paint(color, null);
769
+ c.font(pf, size);
770
+ if (!run.rtl) c.s += span(run.text);
771
+ c.s += `BT ${n2(x)} ${n2(y)} Td
772
+ `;
773
+ let arr = "";
774
+ let pen = 0, rise = 0;
775
+ const flush = () => {
776
+ if (arr) c.s += `[${arr}] TJ
777
+ `;
778
+ arr = "";
779
+ };
780
+ const all = run.glyphs;
781
+ const adv = (id) => f.getGlyph(id).advanceWidth;
782
+ let g = all, quietAt = -1;
783
+ if (run.rtl) {
784
+ const hasBase = /* @__PURE__ */ new Set();
785
+ for (let i = 0; i < all.length; i += 4) if (adv(all[i]) > 0) hasBase.add(all[i + 3]);
786
+ const quiet = (i) => spans?.has(all[i + 3]) ? adv(all[i]) === 0 && hasBase.has(all[i + 3]) : texts?.get(all[i]) === "";
787
+ g = [];
788
+ for (const late of [false, true]) {
789
+ if (late) quietAt = g.length;
790
+ for (let i = 0; i < all.length; i += 4) if (quiet(i) === late) g.push(all[i], all[i + 1], all[i + 2], all[i + 3]);
791
+ }
792
+ if (quietAt === g.length) quietAt = -1;
793
+ }
794
+ const starts = run.rtl ? [...new Set(all.filter((_, i) => i % 4 === 3))].sort((a, b) => a - b) : [];
795
+ let inSpan = false;
796
+ for (let i = 0; i < g.length; i += 4) {
797
+ const id = g[i], gx = g[i + 1], gy = g[i + 2], cl = g[i + 3];
798
+ if (i === quietAt) {
799
+ flush();
800
+ c.s += span("");
801
+ inSpan = true;
802
+ } else if (run.rtl && spans?.has(cl) && (quietAt < 0 || i < quietAt) && (i === 0 || g[i - 1] !== cl)) {
803
+ flush();
804
+ c.s += span(run.text.slice(cl, starts[starts.indexOf(cl) + 1] ?? run.text.length));
805
+ inSpan = true;
806
+ }
807
+ if (gy !== rise) {
808
+ flush();
809
+ c.s += `${n4(gy)} Ts
810
+ `;
811
+ rise = gy;
812
+ }
813
+ const adj = Math.round((pen - gx) * per * 1e3) / 1e3;
814
+ if (id === 0 && c.tagged) pen = gx;
815
+ else {
816
+ arr += (adj ? `${adj}` : "") + `<${hex4(id)}>`;
817
+ pen = gx + adv(id) * size / f.unitsPerEm;
818
+ }
819
+ if (inSpan && (i + 4 >= g.length || (quietAt < 0 || i + 4 < quietAt) && g[i + 7] !== cl || i + 4 === quietAt)) {
820
+ flush();
821
+ c.s += "EMC\n";
822
+ inSpan = false;
823
+ }
824
+ }
825
+ flush();
826
+ if (rise) c.s += "0 Ts\n";
827
+ c.s += "ET\n";
828
+ if (!run.rtl) c.s += "EMC\n";
829
+ }
830
+ function glyphText(run, font, out, spans) {
831
+ const g = run.glyphs;
832
+ const starts = [...new Set(g.filter((_, i) => i % 4 === 3))].sort((a, b) => a - b);
833
+ for (let k = 0; k < starts.length; k++) {
834
+ const chars = [...run.text.slice(starts[k], starts[k + 1] ?? run.text.length)];
835
+ const ids = [];
836
+ for (let i = 0; i < g.length; i += 4) if (g[i + 3] === starts[k]) ids.push(g[i]);
837
+ const own = new Map(chars.map((ch) => [font.glyphForCodePoint(ch.codePointAt(0)).id, ch]));
838
+ const rest = chars.filter((ch) => !ids.includes(font.glyphForCodePoint(ch.codePointAt(0)).id)).join("");
839
+ const carrier = rest ? ids.find((id) => !own.has(id) && font.getGlyph(id).advanceWidth > 0) ?? ids.find((id) => !own.has(id)) : void 0;
840
+ let ok = !rest || carrier !== void 0;
841
+ const want = /* @__PURE__ */ new Map();
842
+ for (const id of ids) {
843
+ const t = own.get(id) ?? (id === carrier ? rest : "");
844
+ if (want.has(id) && want.get(id) !== t) ok = false;
845
+ want.set(id, t);
846
+ }
847
+ for (const [id, t] of want) {
848
+ if (!out.has(id)) out.set(id, t);
849
+ else if (out.get(id) !== t) ok = false;
850
+ }
851
+ if (!ok && run.rtl && spans) {
852
+ let s = spans.get(run);
853
+ if (!s) spans.set(run, s = /* @__PURE__ */ new Set());
854
+ s.add(starts[k]);
855
+ }
856
+ }
857
+ }
858
+ function insideClip(it, m) {
859
+ const k = it.clip, asc = m.asc * it.size, desc = m.desc * it.size;
860
+ return it.lines.every((l) => l.w != null && !l.runs && l.x >= k.x && l.x + l.w <= k.x + k.w && l.y - asc >= k.y && l.y + desc <= k.y + k.h);
861
+ }
862
+ var Content = class {
863
+ constructor(shared) {
864
+ this.shared = shared;
865
+ this._s = "";
866
+ this.bt = false;
867
+ this.tx = 0;
868
+ this.ty = 0;
869
+ this.st = { fill: "0 0 0", stroke: "0 0 0", lw: 1, dash: "[] 0", ca: 1, CA: 1, font: "", size: 0 };
870
+ this.saved = [];
871
+ this.lines = null;
872
+ this.tagged = false;
873
+ }
874
+ /**
875
+ * The operators so far. Any other drawing reads or appends to it, so the lines waiting are drawn first: the text
876
+ * of a table's cells stays in one text object (relative moves, which compress to little) instead of one per cell.
877
+ */
878
+ get s() {
879
+ this.flushLines();
880
+ return this._s;
881
+ }
882
+ set s(v) {
883
+ this._s = v;
884
+ }
885
+ /**
886
+ * A straight line. Untagged, it waits until something other than text is drawn (table borders between cell
887
+ * texts); collinear segments that touch, in the same stroke, become one (a row's border is one line).
888
+ * ponytail: lines move after the text drawn just after them; both are thin and do not cover each other.
889
+ */
890
+ line(stroke, w, dash, x1, y1, x2, y2) {
891
+ if (this.tagged) {
892
+ this.paint(null, stroke, w, dash);
893
+ this._s += `${n2(x1)} ${n2(y1)} m ${n2(x2)} ${n2(y2)} l S
894
+ `;
895
+ return;
896
+ }
897
+ const key = `${stroke.rgb}|${stroke.opacity}|${w}|${(dash || []).join(" ")}`;
898
+ if (this.lines && this.lines.key !== key) this.flushLines();
899
+ this.lines || (this.lines = { key, stroke, w, dash, segs: [] });
900
+ const segs = this.lines.segs, last = segs[segs.length - 1];
901
+ const eq = (a, b) => Math.abs(a - b) < 5e-3;
902
+ if (last && eq(last[1], y1) && eq(last[3], y2) && eq(y1, y2) && eq(last[2], x1)) last[2] = x2;
903
+ else if (last && eq(last[0], x1) && eq(last[2], x2) && eq(x1, x2) && eq(last[3], y1)) last[3] = y2;
904
+ else segs.push([x1, y1, x2, y2]);
905
+ }
906
+ flushLines() {
907
+ const L = this.lines;
908
+ if (!L) return;
909
+ this.lines = null;
910
+ this.et();
911
+ this.paint(null, L.stroke, L.w, L.dash);
912
+ const g = L.segs;
913
+ const dy = g.length > 2 ? Math.round((g[1][1] - g[0][1]) * 100) : 0;
914
+ if (dy && g.every((q, i) => q[1] === q[3] && n2(q[0]) === n2(g[0][0]) && n2(q[2]) === n2(g[0][2]) && Math.abs(q[1] - (g[0][1] + i * dy / 100)) < 0.01)) {
915
+ const one = `${n2(g[0][0])} ${n2(g[0][1])} m ${n2(g[0][2])} ${n2(g[0][1])} l S
916
+ `;
917
+ this._s += `q
918
+ ${one}${`1 0 0 1 0 ${dy / 100} cm ${one}`.repeat(g.length - 1)}Q
919
+ `;
920
+ return;
921
+ }
922
+ this._s += g.map(([a, b, c, d]) => `${n2(a)} ${n2(b)} m ${n2(c)} ${n2(d)} l`).join(" ") + " S\n";
923
+ }
924
+ q() {
925
+ this.et();
926
+ this._s += "q\n";
927
+ this.saved.push({ ...this.st });
928
+ }
929
+ Q() {
930
+ this.et();
931
+ this._s += "Q\n";
932
+ this.st = this.saved.pop();
933
+ }
934
+ /**
935
+ * A line of plain text at (x, y). Lines follow one another in one text object, each placed relative to the
936
+ * last (in whole hundredths, so nothing drifts): most of a table page is these.
937
+ * @param {string} str the glyphs, as a literal string's escaped body (array: a TJ array's body)
938
+ */
939
+ text(pf, size, color, x, y, str, array = false) {
940
+ this.setPaint(color, null);
941
+ this.setFont(pf, size);
942
+ const X = Math.round(x * 10) * 10, Y = Math.round(y * 10) * 10;
943
+ if (!this.bt) {
944
+ this._s += "BT\n";
945
+ this.bt = true;
946
+ this.tx = 0;
947
+ this.ty = 0;
948
+ }
949
+ this._s += array ? `${(X - this.tx) / 100} ${(Y - this.ty) / 100} Td [${str}] TJ
950
+ ` : `${(X - this.tx) / 100} ${(Y - this.ty) / 100} Td (${str}) Tj
951
+ `;
952
+ this.tx = X;
953
+ this.ty = Y;
954
+ }
955
+ /** end the open text object, if any: anything but text needs that (and draws the lines waiting) */
956
+ et() {
957
+ if (this.bt) {
958
+ this._s += "ET\n";
959
+ this.bt = false;
960
+ }
961
+ if (this.lines) this.flushLines();
962
+ }
963
+ lineWidth(w) {
964
+ if (this.lines) this.flushLines();
965
+ this.setLineWidth(w);
966
+ }
967
+ setLineWidth(w) {
968
+ if (this.st.lw !== w) {
969
+ this._s += `${n3(w)} w
970
+ `;
971
+ this.st.lw = w;
972
+ }
973
+ }
974
+ /** the graphics state that sets these opacities, or undefined when they are set already */
975
+ gsFor(ca, CA) {
976
+ return ca === this.st.ca && CA === this.st.CA ? void 0 : this.shared.gs(ca, CA);
977
+ }
978
+ alpha(ca, CA) {
979
+ if (this.lines) this.flushLines();
980
+ this.setAlpha(ca, CA);
981
+ }
982
+ setAlpha(ca, CA) {
983
+ const g = this.gsFor(ca, CA);
984
+ if (g) {
985
+ this._s += `/${g} gs
986
+ `;
987
+ this.st.ca = ca;
988
+ this.st.CA = CA;
989
+ }
990
+ }
991
+ /** set up to fill with fill and/or stroke with stroke (width w, dash); the lines waiting are drawn first */
992
+ paint(fill, stroke, w = 1, dash = null) {
993
+ if (this.lines) this.flushLines();
994
+ this.setPaint(fill, stroke, w, dash);
995
+ }
996
+ setPaint(fill, stroke, w = 1, dash = null) {
997
+ const st = this.st;
998
+ if (fill && fill.rgb !== st.fill) {
999
+ this._s += `${fill.rgb} rg
1000
+ `;
1001
+ st.fill = fill.rgb;
1002
+ }
1003
+ if (stroke) {
1004
+ if (stroke.rgb !== st.stroke) {
1005
+ this._s += `${stroke.rgb} RG
1006
+ `;
1007
+ st.stroke = stroke.rgb;
1008
+ }
1009
+ this.setLineWidth(w);
1010
+ const d = `[${(dash || []).map(n3).join(" ")}] 0`;
1011
+ if (d !== st.dash) {
1012
+ this._s += `${d} d
1013
+ `;
1014
+ st.dash = d;
1015
+ }
1016
+ }
1017
+ this.setAlpha(fill ? fill.opacity : st.ca, stroke ? stroke.opacity : st.CA);
1018
+ }
1019
+ font(pf, size) {
1020
+ if (this.lines) this.flushLines();
1021
+ this.setFont(pf, size);
1022
+ }
1023
+ setFont(pf, size) {
1024
+ const name = this.shared.font(pf);
1025
+ if (name !== this.st.font || size !== this.st.size) {
1026
+ this._s += `/${name} ${n3(size)} Tf
1027
+ `;
1028
+ this.st.font = name;
1029
+ this.st.size = size;
1030
+ }
1031
+ }
1032
+ };
1033
+ function latin1(s) {
1034
+ const B = (
1035
+ /** @type {any} */
1036
+ globalThis.Buffer
1037
+ );
1038
+ if (B) return B.from(s, "latin1");
1039
+ const out = new Uint8Array(s.length);
1040
+ for (let i = 0; i < s.length; i++) out[i] = s.charCodeAt(i);
1041
+ return out;
1042
+ }
1043
+ async function deflate(bytes) {
1044
+ if (zslots.free > 0) zslots.free--;
1045
+ else await new Promise((ok) => zslots.wait.push(
1046
+ /** @type {() => void} */
1047
+ ok
1048
+ ));
1049
+ try {
1050
+ return await deflateNow(bytes);
1051
+ } finally {
1052
+ const next = zslots.wait.shift();
1053
+ if (next) next();
1054
+ else zslots.free++;
1055
+ }
1056
+ }
1057
+ var zslots = { free: 4, wait: (
1058
+ /** @type {(() => void)[]} */
1059
+ []
1060
+ ) };
1061
+ var NODE_ZLIB = (
1062
+ /** @type {any} */
1063
+ globalThis.process?.getBuiltinModule?.("node:zlib")
1064
+ );
1065
+ async function deflateNow(bytes) {
1066
+ const zlib = NODE_ZLIB;
1067
+ if (zlib) return new Promise((ok, fail) => zlib.deflate(bytes, { level: 9 }, (e, z) => e ? fail(e) : ok(z)));
1068
+ if (typeof CompressionStream === "undefined") return (await import("fflate")).zlibSync(bytes);
1069
+ return new Uint8Array(await new Response(new Blob([bytes]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
1070
+ }
1071
+
1072
+ // src/exporters/pdf.js
1073
+ var fontkit = (
1074
+ /** @type {any} */
1075
+ fontkitModule.default || fontkitModule
1076
+ );
1077
+ function exportPdf(model, fontStore, opt = {}) {
1078
+ return withDeadline(
1079
+ pdfOf(model, fontStore, opt),
1080
+ /** @type {any} */
1081
+ opt.timeoutMs
1082
+ );
1083
+ }
1084
+ async function pdfOf(model, fontStore, opt) {
1085
+ const fixed = fixedDate(opt);
1086
+ const when = fixed ?? /* @__PURE__ */ new Date();
1087
+ const fileId = fixed ? await contentId(model, opt, when) : void 0;
1088
+ const doc = await PDFDocument.create({ updateMetadata: false });
1089
+ doc.registerFontkit(fontkit);
1090
+ doc.setTitle(opt.title || "Report");
1091
+ doc.setProducer("ReportWright");
1092
+ doc.setCreator("ReportWright");
1093
+ if (opt.author) doc.setAuthor(opt.author);
1094
+ setInfoDates(doc, when);
1095
+ if (fileId) doc.context.trailerInfo.ID = doc.context.obj([PDFHexString5.of(fileId), PDFHexString5.of(fileId)]);
1096
+ const used = /* @__PURE__ */ new Map();
1097
+ const shaped = /* @__PURE__ */ new Map();
1098
+ const spans = /* @__PURE__ */ new WeakMap();
1099
+ const chars = (key) => {
1100
+ let c = used.get(key);
1101
+ if (!c) {
1102
+ c = /* @__PURE__ */ new Set([32]);
1103
+ used.set(key, c);
1104
+ }
1105
+ return c;
1106
+ };
1107
+ for (const pg of model.pages) for (const it of pg.items.flatMap((i) => i.t === "field" ? i.draw.filter((d) => d.t === "text") : i.t === "text" ? [i] : [])) {
1108
+ for (const l of it.lines) {
1109
+ if (!l.runs) {
1110
+ const c = chars(it.font);
1111
+ for (const ch of l.text) c.add(
1112
+ /** @type {number} */
1113
+ ch.codePointAt(0)
1114
+ );
1115
+ continue;
1116
+ }
1117
+ for (const r of l.runs) {
1118
+ const c = chars(r.font);
1119
+ for (const ch of r.text) c.add(
1120
+ /** @type {number} */
1121
+ ch.codePointAt(0)
1122
+ );
1123
+ let g = shaped.get(r.font);
1124
+ if (!g) {
1125
+ g = /* @__PURE__ */ new Map();
1126
+ shaped.set(r.font, g);
1127
+ }
1128
+ glyphText(r, fontStore.get(r.font), g, spans);
1129
+ }
1130
+ }
1131
+ }
1132
+ const fieldFonts = /* @__PURE__ */ new Set();
1133
+ for (const pg of model.pages) for (const it of pg.items) if (it.t === "field") fieldFonts.add(fieldFont(it));
1134
+ const fonts = /* @__PURE__ */ new Map();
1135
+ const font = async (key) => {
1136
+ if (!fonts.has(key)) {
1137
+ const full = fontStore.bytes.get(key);
1138
+ let bytes = full;
1139
+ if (!bytes) throw new Error(`Font "${key}" is not loaded`);
1140
+ const glyphs = shaped.get(key);
1141
+ if (opt.subset && !fieldFonts.has(key) && !fontStore.get(key)["OS/2"]?.fsType?.noSubsetting) {
1142
+ const cps = used.get(key) || /* @__PURE__ */ new Set([32]);
1143
+ try {
1144
+ const sub = withPadding(await opt.subset(bytes, cps, glyphs ? { glyphs: glyphs.keys() } : void 0));
1145
+ const f = fontkit.create(sub);
1146
+ for (const cp of cps) void f.glyphForCodePoint(cp).advanceWidth;
1147
+ for (const id of glyphs?.keys() || []) void f.getGlyph(id).advanceWidth;
1148
+ bytes = sub;
1149
+ } catch {
1150
+ }
1151
+ }
1152
+ const pf = await doc.embedFont(bytes, { subset: false, customName: bytes === full ? void 0 : `${subsetTag(bytes)}+${fontStore.get(key).postscriptName || "Font"}` });
1153
+ plainEncoding(pf);
1154
+ if (glyphs) addGlyphs(pf, glyphs, !!opt.tagged);
1155
+ const file = bytes, e = (
1156
+ /** @type {any} */
1157
+ pf.embedder
1158
+ );
1159
+ if (!e.isCFF()) e.embedFontStream = async (c) => c.register(PDFRawStream2.of(c.obj({ Filter: "FlateDecode", Length1: file.length }), await deflate(file)));
1160
+ fonts.set(key, pf);
1161
+ }
1162
+ return fonts.get(key);
1163
+ };
1164
+ const images = /* @__PURE__ */ new Map();
1165
+ const image = async (src) => {
1166
+ if (images.has(src)) return images.get(src);
1167
+ const out = await loadImage(src).catch((e) => ({ img: null, why: `it could not be embedded (${e?.message || e})` }));
1168
+ images.set(src, out);
1169
+ return out;
1170
+ };
1171
+ async function loadImage(src) {
1172
+ const local = /^data:/i.test(src);
1173
+ if (local && dataUriBytes(src) > IMAGE_LIMITS.bytes) return { img: null, why: "it is larger than the image size limit" };
1174
+ if (!local && !opt.fetchImage) return { img: null, why: "it is a URL, and no fetchImage was given to load it" };
1175
+ const bytes = local ? dataUriBytesOf(src) : await opt.fetchImage(src);
1176
+ if (!bytes?.length) return { img: null, why: "it could not be loaded" };
1177
+ if (bytes.length > IMAGE_LIMITS.bytes) return { img: null, why: "it is larger than the image size limit" };
1178
+ const info = imageInfoOf(bytes);
1179
+ if (info?.type === "svg") {
1180
+ const svg = parseSvg(new TextDecoder().decode(bytes));
1181
+ return svg ? { img: { svg, width: svg.w, height: svg.h } } : { img: null, why: "the SVG could not be read" };
1182
+ }
1183
+ if (info?.type === "png") {
1184
+ const why = "w" in info && !/** @type {any} */
1185
+ info.suspect && info.w * info.h <= IMAGE_LIMITS.pixels ? pngProblem(bytes) : "too large or animated";
1186
+ return why ? { img: null, why: `the PNG is not usable (${why})` } : { img: await doc.embedPng(bytes) };
1187
+ }
1188
+ if (info?.type === "jpeg") return { img: await doc.embedJpg(bytes) };
1189
+ return { img: null, why: info ? `${info.type.toUpperCase()} is not embedded (PNG, JPEG and SVG are)` : "it is not a PNG, JPEG or SVG" };
1190
+ }
1191
+ const ctx = doc.context;
1192
+ const res = ctx.obj({ Font: {}, ExtGState: {}, XObject: {} });
1193
+ const resRef = ctx.register(res);
1194
+ const names = /* @__PURE__ */ new Map();
1195
+ const nameOf = (kind, key, value) => {
1196
+ let n = names.get(key);
1197
+ if (!n) {
1198
+ n = `${kind[0]}${names.size + 1}`;
1199
+ names.set(key, n);
1200
+ res.get(PDFName3.of(kind)).set(PDFName3.of(n), value());
1201
+ }
1202
+ return n;
1203
+ };
1204
+ const shared = {
1205
+ font: (pf) => nameOf("Font", pf, () => pf.ref),
1206
+ gs: (ca, CA) => nameOf("ExtGState", `gs ${ca} ${CA}`, () => ctx.obj({ Type: "ExtGState", ca, CA })),
1207
+ image: (img) => nameOf("XObject", img, () => img.ref)
1208
+ };
1209
+ const links = [];
1210
+ const taken = /* @__PURE__ */ new Set();
1211
+ const uniqueName = (n) => {
1212
+ let name = n, i = 1;
1213
+ while (taken.has(name)) name = `${n}_${++i}`;
1214
+ taken.add(name);
1215
+ return name;
1216
+ };
1217
+ const contents = [];
1218
+ if (opt.tagged) needsTableData(model, "An accessible PDF");
1219
+ const tags = opt.tagged ? createTagger(model, doc) : null;
1220
+ let pi = -1;
1221
+ const vm = /* @__PURE__ */ new Map();
1222
+ const vmetrics = (key) => {
1223
+ let m = vm.get(key);
1224
+ if (!m) {
1225
+ const f = fontStore.get(key), u = f?.unitsPerEm || 1e3;
1226
+ vm.set(key, m = { asc: (f?.ascent ?? u) / u, desc: -(f?.descent ?? 0) / u });
1227
+ }
1228
+ return m;
1229
+ };
1230
+ for (const pg of model.pages) {
1231
+ pi++;
1232
+ const H = pg.height ?? model.height;
1233
+ const p = doc.addPage([pg.width ?? model.width, H]);
1234
+ p.node.normalize();
1235
+ p.node.set(PDFName3.of("Resources"), resRef);
1236
+ const c = new Content(shared);
1237
+ if (tags) c.tagged = true;
1238
+ p.maybeEmbedGraphicsState = (o) => c.gsFor(o.opacity ?? 1, o.borderOpacity ?? 1);
1239
+ const viaPdfLib = (draw) => {
1240
+ c.et();
1241
+ c.lineWidth(1);
1242
+ draw();
1243
+ const ops = (
1244
+ /** @type {any} */
1245
+ p.getContentStream().operators
1246
+ );
1247
+ for (const op of ops) c.s += op.toString() + "\n";
1248
+ ops.length = 0;
1249
+ };
1250
+ for (let ii = 0; ii < pg.items.length; ii++) {
1251
+ const it = pg.items[ii];
1252
+ const mark = tags && tags.open(pi, ii, it);
1253
+ if (mark) {
1254
+ c.et();
1255
+ c.s += mark;
1256
+ }
1257
+ if (it.t !== "text" && it.t !== "line" || it.rotate) c.et();
1258
+ if (it.rotate) {
1259
+ const t = -it.rotate.a * Math.PI / 180, cs = Math.cos(t), sn = Math.sin(t);
1260
+ const px = it.rotate.cx, py = H - it.rotate.cy;
1261
+ c.q();
1262
+ c.s += `${n4(cs)} ${n4(sn)} ${n4(-sn)} ${n4(cs)} ${n2(px - px * cs + py * sn)} ${n2(py - px * sn - py * cs)} cm
1263
+ `;
1264
+ }
1265
+ switch (it.t) {
1266
+ case "rect": {
1267
+ const fill = col(it.fill), stroke = col(it.stroke);
1268
+ if (!fill && !stroke) break;
1269
+ if (it.radius) {
1270
+ viaPdfLib(() => p.drawSvgPath(roundRect(it.x, it.y, it.w, it.h, it.radius), {
1271
+ x: 0,
1272
+ y: H,
1273
+ color: fill?.color,
1274
+ opacity: fill?.opacity,
1275
+ borderColor: stroke?.color,
1276
+ borderWidth: stroke ? it.strokeWidth || 1 : 0,
1277
+ borderOpacity: stroke?.opacity,
1278
+ borderDashArray: it.dash || void 0
1279
+ }));
1280
+ } else {
1281
+ c.paint(fill, stroke, it.strokeWidth || 1, it.dash);
1282
+ const x = n2(it.x), y = n2(H - it.y - it.h), w = n2(it.w), h = n2(it.h);
1283
+ c.s += (stroke && it.dash?.length ? `${x} ${y} m ${x} ${n2(y + h)} l ${n2(x + w)} ${n2(y + h)} l ${n2(x + w)} ${y} l h` : `${x} ${y} ${w} ${h} re`) + (fill && stroke ? " B\n" : fill ? " f\n" : " S\n");
1284
+ }
1285
+ break;
1286
+ }
1287
+ case "ellipse": {
1288
+ const fill = col(it.fill), stroke = col(it.stroke);
1289
+ if (!fill && !stroke) break;
1290
+ c.paint(fill, stroke, it.strokeWidth || 1, it.dash);
1291
+ const cx = it.cx, cy = H - it.cy, rx = it.rx, ry = it.ry, ox = rx * KAPPA, oy = ry * KAPPA;
1292
+ c.s += `${n2(cx - rx)} ${n2(cy)} m ${n2(cx - rx)} ${n2(cy - oy)} ${n2(cx - ox)} ${n2(cy - ry)} ${n2(cx)} ${n2(cy - ry)} c ${n2(cx + ox)} ${n2(cy - ry)} ${n2(cx + rx)} ${n2(cy - oy)} ${n2(cx + rx)} ${n2(cy)} c ${n2(cx + rx)} ${n2(cy + oy)} ${n2(cx + ox)} ${n2(cy + ry)} ${n2(cx)} ${n2(cy + ry)} c ${n2(cx - ox)} ${n2(cy + ry)} ${n2(cx - rx)} ${n2(cy + oy)} ${n2(cx - rx)} ${n2(cy)} c h ${fill &&
1293
+ stroke ? "B" : fill ? "f" : "S"}
1294
+ `;
1295
+ break;
1296
+ }
1297
+ case "line": {
1298
+ const s = col(it.stroke);
1299
+ if (!s) break;
1300
+ c.line(s, it.strokeWidth || 1, it.dash, it.x1, H - it.y1, it.x2, H - it.y2);
1301
+ break;
1302
+ }
1303
+ case "text": {
1304
+ const f = it.lines.some((l) => !l.runs) ? await font(it.font) : null;
1305
+ const color = col(it.color) || BLACK;
1306
+ const clipped = it.clip && !insideClip(it, vmetrics(it.font));
1307
+ if (clipped) {
1308
+ c.q();
1309
+ c.s += `${n2(it.clip.x)} ${n2(H - it.clip.y - it.clip.h)} ${n2(it.clip.w)} ${n2(it.clip.h)} re W n
1310
+ `;
1311
+ }
1312
+ for (const l of it.lines) {
1313
+ if (!l.runs) {
1314
+ const tj = tags && /** @type {any} */
1315
+ f.embedder.tjOf(cleanText(l.text));
1316
+ if (tj) c.text(f, it.size, color, l.x, H - l.y, tj, true);
1317
+ else c.text(
1318
+ f,
1319
+ it.size,
1320
+ color,
1321
+ l.x,
1322
+ H - l.y,
1323
+ /** @type {any} */
1324
+ f.embedder.literalOf(cleanText(l.text))
1325
+ );
1326
+ continue;
1327
+ }
1328
+ for (const r of l.runs) if (r.text.trim()) drawRun(c, r, l.x + r.x, H - l.y, it.size, await font(r.font), color, spans.get(r), shaped.get(r.font));
1329
+ }
1330
+ if (clipped) c.Q();
1331
+ break;
1332
+ }
1333
+ case "path": {
1334
+ const fill = col(it.fill), stroke = col(it.stroke);
1335
+ viaPdfLib(() => p.drawSvgPath(it.d, { x: it.x, y: H - it.y, color: fill?.color, opacity: fill?.opacity, borderColor: stroke?.color, borderWidth: stroke ? it.strokeWidth || 1 : 0, borderOpacity: stroke?.opacity, borderLineCap: it.lineCap === "butt" ? 0 : 1, borderDashArray: it.dash || void 0 }));
1336
+ break;
1337
+ }
1338
+ case "field": {
1339
+ const form = doc.getForm();
1340
+ const f = await font(fieldFont(it));
1341
+ const name = uniqueName(it.name);
1342
+ const box = { x: it.x, y: H - it.y - it.h, width: it.w, height: it.h, borderColor: rgb3(0.61, 0.64, 0.69), borderWidth: 0.75, backgroundColor: rgb3(1, 1, 1) };
1343
+ let field;
1344
+ if (it.kind === "checkbox") {
1345
+ field = form.createCheckBox(name);
1346
+ field.addToPage(p, box);
1347
+ if (it.value) field.check();
1348
+ } else {
1349
+ if (it.kind === "choice") {
1350
+ field = form.createDropdown(name);
1351
+ field.addOptions(it.options);
1352
+ field.addToPage(p, { ...box, font: f });
1353
+ if (it.options.includes(String(it.value))) field.select(String(it.value));
1354
+ } else {
1355
+ field = form.createTextField(name);
1356
+ if (it.kind === "multiline") field.enableMultiline();
1357
+ field.addToPage(p, { ...box, font: f });
1358
+ field.setText(String(it.value ?? ""));
1359
+ }
1360
+ field.setFontSize(it.size);
1361
+ field.updateAppearances(f);
1362
+ const lines = it.draw.filter((d) => d.t === "text").flatMap((d) => d.lines.map((l) => ({ d, l })));
1363
+ if (lines.some((x) => x.l.runs)) {
1364
+ const a = new Content(shared);
1365
+ const top = it.y + it.h;
1366
+ a.s += "/Tx BMC\n";
1367
+ a.paint({ rgb: "1 1 1", opacity: 1 }, { rgb: "0.61 0.64 0.69", opacity: 1 }, 0.75);
1368
+ a.s += `0.375 0.375 ${n2(it.w - 0.75)} ${n2(it.h - 0.75)} re B
1369
+ `;
1370
+ a.q();
1371
+ a.s += `1 1 ${n2(it.w - 2)} ${n2(it.h - 2)} re W n
1372
+ `;
1373
+ for (const { d, l } of lines) {
1374
+ const color = col(d.color) || BLACK;
1375
+ if (!l.runs) {
1376
+ const pf = await font(d.font);
1377
+ a.text(
1378
+ pf,
1379
+ d.size,
1380
+ color,
1381
+ l.x - it.x,
1382
+ top - l.y,
1383
+ /** @type {any} */
1384
+ pf.embedder.literalOf(cleanText(l.text))
1385
+ );
1386
+ continue;
1387
+ }
1388
+ for (const r of l.runs) if (r.text.trim()) drawRun(a, r, l.x - it.x + r.x, top - l.y, d.size, await font(r.font), color, spans.get(r), shaped.get(r.font));
1389
+ }
1390
+ a.Q();
1391
+ a.s += "EMC\n";
1392
+ const ap = ctx.register(ctx.flateStream(a.s, { Type: "XObject", Subtype: "Form", BBox: [0, 0, it.w, it.h], Resources: resRef }));
1393
+ for (const w of field.acroField.getWidgets()) w.setNormalAppearance(ap);
1394
+ }
1395
+ }
1396
+ if (it.required) field.enableRequired();
1397
+ if (it.readOnly) field.enableReadOnly();
1398
+ if (tags) {
1399
+ field.acroField.dict.set(PDFName3.of("TU"), PDFHexString5.fromText(it.label || it.name || name));
1400
+ const w = field.acroField.getWidgets()[0];
1401
+ const ref2 = w && doc.context.getObjectRef(w.dict);
1402
+ if (ref2) tags.annot(pi, ii, ref2, "field");
1403
+ }
1404
+ break;
1405
+ }
1406
+ case "link": {
1407
+ const rect = [it.x, H - it.y - it.h, it.x + it.w, H - it.y];
1408
+ const text = tags ? coveredText(pg.items, it) : "";
1409
+ if (it.action?.type === "url" && safeUrl(it.action.href)) links.push({ page: p, rect, href: it.action.href, pi, ii, tip: it.tip, text });
1410
+ else if (it.action?.type === "drill") {
1411
+ const href = drillUrl(opt.drillBase, it.action);
1412
+ if (href) links.push({ page: p, rect, href, pi, ii, tip: it.tip || `Open the report "${it.action.report}"`, text });
1413
+ } else if (it.action?.type === "bookmark") {
1414
+ const to = it.action.page ? it.action : model.bookmarks?.find((b) => b.label === it.action.target);
1415
+ if (to) links.push({ page: p, rect, to, pi, ii, tip: it.tip || `Go to ${it.action.target || `page ${to.page}`}`, text });
1416
+ }
1417
+ break;
1418
+ }
1419
+ case "image": {
1420
+ const { img, why } = await image(it.src);
1421
+ if (!img) {
1422
+ const alt = it.tag?.alt;
1423
+ opt.onWarning?.(`Image on page ${pi + 1} (${alt ? `"${alt}"` : String(it.src).slice(0, 40)}) was left out: ${why}`);
1424
+ break;
1425
+ }
1426
+ let w = it.w, h = it.h, x = it.x, y = it.y;
1427
+ const clipBox = it.fit === "clip" ? [it.x, H - it.y - it.ch, it.cw, it.ch] : it.fit === "cover" ? [it.x, H - it.y - it.h, it.w, it.h] : null;
1428
+ if (it.fit !== "fill" && it.fit !== "clip") {
1429
+ const s = it.fit === "cover" ? Math.max(it.w / img.width, it.h / img.height) : Math.min(it.w / img.width, it.h / img.height);
1430
+ w = img.width * s;
1431
+ h = img.height * s;
1432
+ x = it.x + (it.w - w) / 2;
1433
+ y = it.y + (it.h - h) / 2;
1434
+ }
1435
+ c.q();
1436
+ if (clipBox) c.s += `${clipBox.map(n2).join(" ")} re W n
1437
+ `;
1438
+ if (img.svg) viaPdfLib(() => drawSvg(p, img.svg, { x, y: H - y - h, sx: w / img.width, sy: h / img.height }));
1439
+ else {
1440
+ c.alpha(1, c.st.CA);
1441
+ c.s += `${n4(w)} 0 0 ${n4(h)} ${n2(x)} ${n2(H - y - h)} cm /${shared.image(img)} Do
1442
+ `;
1443
+ }
1444
+ c.Q();
1445
+ break;
1446
+ }
1447
+ }
1448
+ if (it.rotate) c.Q();
1449
+ if (mark) {
1450
+ c.et();
1451
+ c.s += "EMC\n";
1452
+ }
1453
+ }
1454
+ c.et();
1455
+ const own = (
1456
+ /** @type {any} */
1457
+ p.contentStreamRef
1458
+ );
1459
+ if (own) ctx.delete(own);
1460
+ const ref = ctx.nextRef();
1461
+ p.node.set(PDFName3.of("Contents"), ref);
1462
+ contents.push(deflate(latin1(c.s)).then((z) => ctx.assign(ref, PDFRawStream2.of(ctx.obj({ Filter: "FlateDecode" }), z))));
1463
+ if (NODE_ZLIB && contents.length > 8) await contents[contents.length - 9];
1464
+ }
1465
+ await Promise.all(contents);
1466
+ const pageH = (n) => model.pages[n - 1]?.height ?? model.height;
1467
+ const pages = doc.getPages();
1468
+ const dest = (b) => pages[b.page - 1] && [pages[b.page - 1].ref, PDFName3.of("XYZ"), null, pageH(b.page) - b.y + 4, null];
1469
+ for (const l of links) {
1470
+ const to = l.href ? { A: { Type: "Action", S: "URI", URI: pdfLiteral(asciiUrl(l.href)) } } : { Dest: dest(l.to) };
1471
+ if (!l.href && !to.Dest) continue;
1472
+ const annot = doc.context.obj({ Type: "Annot", Subtype: "Link", F: 4, Rect: l.rect, Border: [0, 0, 0], ...to });
1473
+ if (tags) annot.set(PDFName3.of("Contents"), PDFHexString5.fromText(String(l.text || l.tip || l.href || "Link")));
1474
+ const ref = doc.context.register(annot);
1475
+ if (tags) tags.annot(l.pi, l.ii, ref, "link");
1476
+ const annots = l.page.node.lookup(PDFName3.of("Annots"));
1477
+ if (annots) annots.push(ref);
1478
+ else l.page.node.set(PDFName3.of("Annots"), doc.context.obj([ref]));
1479
+ }
1480
+ const marks = outlineEntries(model);
1481
+ if (marks.length) addOutline(doc, marks, dest);
1482
+ pageLabels(doc, model);
1483
+ if (tags) tags.finish({ lang: opt.tagged?.lang, title: opt.title || "Report" });
1484
+ if (opt.prepare) await opt.prepare(doc);
1485
+ if (opt.pdfa) makePdfA(doc, { ...opt.pdfa, title: opt.title || "Report", author: opt.author, created: when, id: fileId, ...tags ? { conformance: "A", ua: true } : {} });
1486
+ else if (tags) setUaMetadata(doc, { title: opt.title || "Report", author: opt.author, created: when });
1487
+ if (opt.encrypt) {
1488
+ if (opt.pdfa) throw Object.assign(new Error("A PDF/A file cannot have a password. Turn off PDF/A or the password."), { status: 400 });
1489
+ if (opt.prepare) throw Object.assign(new Error("A signed PDF cannot have a password here. Turn off signing or the password."), { status: 400 });
1490
+ await encryptPdf(doc, opt.encrypt);
1491
+ return doc.save({ updateFieldAppearances: false, ...opt.save || {}, useObjectStreams: false });
1492
+ }
1493
+ return doc.save({ updateFieldAppearances: false, ...opt.save || {} });
1494
+ }
1495
+ function coveredText(items, box) {
1496
+ const lines = [];
1497
+ for (const t of items) if (t.t === "text" && t.lines) {
1498
+ for (const l of t.lines) if (l.text?.trim() && l.x >= box.x && l.x <= box.x + box.w && l.y >= box.y && l.y <= box.y + box.h) lines.push(l);
1499
+ }
1500
+ return lines.sort((a, b) => a.y - b.y || a.x - b.x).map((l) => l.text.trim()).join(" ");
1501
+ }
1502
+ function fixedDate(opt) {
1503
+ if (opt.creationDate !== void 0) {
1504
+ if (!(opt.creationDate instanceof Date) || Number.isNaN(opt.creationDate.getTime())) throw Object.assign(new Error("creationDate must be a valid Date"), { status: 400 });
1505
+ return opt.creationDate;
1506
+ }
1507
+ const epoch = globalThis.process?.env?.SOURCE_DATE_EPOCH;
1508
+ return epoch && /^\d+$/.test(epoch) ? new Date(Number(epoch) * 1e3) : null;
1509
+ }
1510
+ async function contentId(model, opt, when) {
1511
+ const bytes = new TextEncoder().encode(JSON.stringify([{ ...model, stats: void 0 }, opt.title || "Report", opt.author || "", when.toISOString()]));
1512
+ const digest = new Uint8Array(await globalThis.crypto.subtle.digest("SHA-256", bytes));
1513
+ return Array.from(digest.subarray(0, 16), (b) => b.toString(16).padStart(2, "0")).join("").toUpperCase();
1514
+ }
1515
+ function fieldFont(it) {
1516
+ for (const d of it.draw) if (d.t === "text") {
1517
+ for (const l of d.lines) for (const r of l.runs || []) if (r.font !== it.font && r.text.trim()) return r.font;
1518
+ }
1519
+ return it.font;
1520
+ }
1521
+ var pdfLiteral = (s) => PDFString4.of(String(s).replace(/[\\()]/g, "\\$&"));
1522
+ function plainEncoding(pf) {
1523
+ const e = pf.embedder, f = e.font, memo = /* @__PURE__ */ new Map();
1524
+ e.hexOf = (text) => {
1525
+ let hex2 = "";
1526
+ for (const ch of text) {
1527
+ const cp = (
1528
+ /** @type {number} */
1529
+ ch.codePointAt(0)
1530
+ );
1531
+ let h = memo.get(cp);
1532
+ if (h === void 0) memo.set(cp, h = hex4(f.glyphForCodePoint(cp).id));
1533
+ hex2 += h;
1534
+ }
1535
+ return hex2;
1536
+ };
1537
+ e.encodeText = (text) => PDFHexString5.of(e.hexOf(text));
1538
+ e.widthOfTextAtSize = (text, size) => {
1539
+ let w = 0;
1540
+ for (const ch of text) w += f.glyphForCodePoint(
1541
+ /** @type {number} */
1542
+ ch.codePointAt(0)
1543
+ ).advanceWidth || 0;
1544
+ return w * size / f.unitsPerEm;
1545
+ };
1546
+ const lit = /* @__PURE__ */ new Map();
1547
+ const esc = (b) => b === 40 || b === 41 || b === 92 ? "\\" + String.fromCharCode(b) : b === 13 ? "\\r" : String.fromCharCode(b);
1548
+ e.tjOf = (text) => {
1549
+ let out = "", cur = "", any = false;
1550
+ for (const ch of text) {
1551
+ const cp = (
1552
+ /** @type {number} */
1553
+ ch.codePointAt(0)
1554
+ );
1555
+ if (f.glyphForCodePoint(cp).id === 0) {
1556
+ any = true;
1557
+ if (cur) out += `(${cur})`;
1558
+ cur = "";
1559
+ out += `${-Math.round(f.getGlyph(0).advanceWidth * 1e3 / f.unitsPerEm)}`;
1560
+ continue;
1561
+ }
1562
+ cur += e.literalOf(ch);
1563
+ }
1564
+ return any ? out + (cur ? `(${cur})` : "") : null;
1565
+ };
1566
+ e.literalOf = (text) => {
1567
+ let out = "";
1568
+ for (const ch of text) {
1569
+ const cp = (
1570
+ /** @type {number} */
1571
+ ch.codePointAt(0)
1572
+ );
1573
+ let b = lit.get(cp);
1574
+ if (b === void 0) {
1575
+ const id = f.glyphForCodePoint(cp).id;
1576
+ lit.set(cp, b = esc(id >> 8) + esc(id & 255));
1577
+ }
1578
+ out += b;
1579
+ }
1580
+ return out;
1581
+ };
1582
+ }
1583
+ function addGlyphs(pf, glyphs, tagged = false) {
1584
+ const e = pf.embedder;
1585
+ const byId = new Map(e.glyphCache.access().map((g) => [g.id, g]));
1586
+ for (const [id, text] of glyphs) byId.set(id, { id, advanceWidth: e.font.getGlyph(id).advanceWidth, codePoints: text || !tagged ? [...text].map((ch) => ch.codePointAt(0)) : [8205] });
1587
+ const all = [...byId.values()].sort((a, b) => a.id - b.id);
1588
+ e.glyphCache = { access: () => all };
1589
+ const cmap = e.embedUnicodeCmap.bind(e);
1590
+ e.embedUnicodeCmap = (ctx) => {
1591
+ e.glyphCache = { access: () => all.filter((g) => g.codePoints.length) };
1592
+ try {
1593
+ return cmap(ctx);
1594
+ } finally {
1595
+ e.glyphCache = { access: () => all };
1596
+ }
1597
+ };
1598
+ }
1599
+ function outlineEntries(model) {
1600
+ const seen = /* @__PURE__ */ new Set();
1601
+ return [...model.bookmarks || [], ...model.headings || []].map((b, i) => ({ b, i })).sort((p, q) => p.b.page - q.b.page || (p.b.y ?? 0) - (q.b.y ?? 0) || p.i - q.i).map(({ b }) => b).filter((b) => {
1602
+ const k = `${b.page}|${Math.round(b.y ?? 0)}|${b.label}`;
1603
+ if (seen.has(k)) return false;
1604
+ seen.add(k);
1605
+ return true;
1606
+ });
1607
+ }
1608
+ function pageLabels(doc, model) {
1609
+ const n = doc.getPageCount();
1610
+ if (!n) return;
1611
+ const starts = [.../* @__PURE__ */ new Set([0, ...model.pageStarts || []])].filter((i) => i >= 0 && i < n).sort((a, b) => a - b);
1612
+ const ctx = doc.context;
1613
+ const nums = starts.flatMap((i) => [i, ctx.obj({ S: "D", St: 1 })]);
1614
+ doc.catalog.set(PDFName3.of("PageLabels"), ctx.obj({ Nums: nums }));
1615
+ }
1616
+ function addOutline(doc, bookmarks, dest) {
1617
+ const ctx = doc.context;
1618
+ const root = { ref: ctx.nextRef(), level: -1, kids: (
1619
+ /** @type {any[]} */
1620
+ []
1621
+ ) };
1622
+ const stack = [root];
1623
+ for (const b of bookmarks) {
1624
+ const Dest = dest(b);
1625
+ if (!Dest) continue;
1626
+ const level = Math.max(0, Math.min(9, Number(b.level) || 0));
1627
+ while (stack[stack.length - 1].level >= level) stack.pop();
1628
+ const node2 = { ref: ctx.nextRef(), level, kids: [], Title: PDFHexString5.fromText(b.label), Dest };
1629
+ stack[stack.length - 1].kids.push(node2);
1630
+ stack.push(node2);
1631
+ }
1632
+ if (!root.kids.length) return;
1633
+ const count = (n) => n.kids.reduce((s, k) => s + 1 + count(k), 0);
1634
+ const children = (n) => n.kids.length ? { First: n.kids[0].ref, Last: n.kids[n.kids.length - 1].ref, Count: count(n) } : {};
1635
+ const write = (n) => n.kids.forEach((k, i) => {
1636
+ ctx.assign(k.ref, ctx.obj({ Title: k.Title, Parent: n.ref, Dest: k.Dest, ...i > 0 ? { Prev: n.kids[i - 1].ref } : {}, ...i < n.kids.length - 1 ? { Next: n.kids[i + 1].ref } : {}, ...children(k) }));
1637
+ write(k);
1638
+ });
1639
+ write(root);
1640
+ ctx.assign(root.ref, ctx.obj({ Type: "Outlines", ...children(root) }));
1641
+ doc.catalog.set(PDFName3.of("Outlines"), root.ref);
1642
+ doc.catalog.set(PDFName3.of("PageMode"), PDFName3.of("UseOutlines"));
1643
+ }
1644
+ function withPadding(font) {
1645
+ const out = new Uint8Array(font.length + 16);
1646
+ out.set(font);
1647
+ return out;
1648
+ }
1649
+ function subsetTag(bytes) {
1650
+ let h = 2166136261;
1651
+ for (let i = 0; i < bytes.length; i++) h = Math.imul(h ^ bytes[i], 16777619);
1652
+ let tag = "";
1653
+ for (let i = 0; i < 6; i++) {
1654
+ tag += String.fromCharCode(65 + (h >>> 0) % 26);
1655
+ h = Math.imul(h ^ i, 16777619) >>> 0;
1656
+ }
1657
+ return tag;
1658
+ }
1659
+ function roundRect(x, y, w, h, r) {
1660
+ r = Math.min(r, w / 2, h / 2);
1661
+ return `M ${x + r} ${y} H ${x + w - r} A ${r} ${r} 0 0 1 ${x + w} ${y + r} V ${y + h - r} A ${r} ${r} 0 0 1 ${x + w - r} ${y + h} H ${x + r} A ${r} ${r} 0 0 1 ${x} ${y + h - r} V ${y + r} A ${r} ${r} 0 0 1 ${x + r} ${y} Z`;
1662
+ }
1663
+ export {
1664
+ exportPdf
1665
+ };
1666
+ //# sourceMappingURL=chunk-KBT6ZGGO.js.map