@reportwright/cli 0.11.0 → 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.
package/dist/pw.mjs CHANGED
@@ -13348,8 +13348,8 @@ function rgbOf(c) {
13348
13348
  if (h.length === 3) h = h.replace(/./g, (x) => x + x);
13349
13349
  return [0, 2, 4].map((i) => parseInt(h.slice(i, i + 2), 16) / 255);
13350
13350
  }
13351
- var lum = (rgb3) => {
13352
- const [r, g, b] = rgb3.map((v) => v <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4);
13351
+ var lum = (rgb4) => {
13352
+ const [r, g, b] = rgb4.map((v) => v <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4);
13353
13353
  return 0.2126 * r + 0.7152 * g + 0.0722 * b;
13354
13354
  };
13355
13355
  function contrast(a, b) {
@@ -17884,7 +17884,7 @@ register("table", {
17884
17884
  (item.groups || []).forEach((g, i) => {
17885
17885
  if (g.name) groupChains[g.name] = { rows, keys: item.groups.slice(0, i + 1).map((x) => x.expr) };
17886
17886
  });
17887
- const base = { ...tctx, aggRows: rows, aggIndex: void 0, fields: rows[0] || null, scopes, region: tableScope, group: void 0, groupChains: { ...tctx.groupChains || {}, ...groupChains } };
17887
+ const base = { ...tctx, aggRows: rows, aggIndex: void 0, fields: lc.win?.first || rows[0] || null, scopes, region: tableScope, group: void 0, groupChains: { ...tctx.groupChains || {}, ...groupChains } };
17888
17888
  const units = [];
17889
17889
  let y = 0;
17890
17890
  let repeatH = 0;
@@ -18122,7 +18122,8 @@ register("table", {
18122
18122
  openSpans = [];
18123
18123
  };
18124
18124
  const fl = base.bandRows === "first-last";
18125
- const headerUnits = (item.header || []).map((r) => layRow(r, fl && rows.length ? { ...base, pendingRows: [rows[0]] } : base, "header")).filter(Boolean);
18125
+ const first0 = lc.win?.first || rows[0];
18126
+ const headerUnits = (item.header || []).map((r) => layRow(r, fl && rows.length ? { ...base, pendingRows: [first0] } : base, "header")).filter(Boolean);
18126
18127
  endBand();
18127
18128
  const headerHeight = headerUnits.reduce((s, u) => s + u.height, 0);
18128
18129
  if (item.repeatHeader !== false) repeatH = headerHeight;
@@ -18136,7 +18137,7 @@ register("table", {
18136
18137
  y += tl.needed;
18137
18138
  }
18138
18139
  const groups = item.groups || [];
18139
- let rowNo = 0;
18140
+ let rowNo = lc.win?.rowOffset || 0;
18140
18141
  const groupTables = [];
18141
18142
  const tableKey = `${item.name}#${lc.nextId()}`;
18142
18143
  const emit2 = (level, grows, ctx, chain, keyPath) => {
@@ -18156,9 +18157,16 @@ register("table", {
18156
18157
  const dctx = { ...ctx, fields: grows[i], aggRows: grows, aggIndex: i, rowNumber: rowNo };
18157
18158
  const u0 = units.length;
18158
18159
  for (const r of item.detail || []) layRow(r, dctx, "detail", { level: groups.length });
18159
- if (groups.length && item.widowControl !== false) for (let k = u0; k < units.length; k++) units[k].grp = tableKey + keyPath;
18160
+ if (lc.win && units[u0]) {
18161
+ units[u0].rowHead = true;
18162
+ for (let k = u0; k < units.length; k++) units[k].dataRow = rowNo;
18163
+ }
18164
+ if (groups.length && item.widowControl !== false) for (let k = u0; k < units.length; k++) {
18165
+ units[k].grp = tableKey + keyPath;
18166
+ if (ctx.__before) units[k].grpBefore = ctx.__before;
18167
+ }
18160
18168
  const every = Math.trunc(Number(item.pageBreakEvery)) || 0;
18161
- if (every > 0 && rowNo > 1 && (rowNo - 1) % every === 0 && units[u0]) units[u0].breakBefore = true;
18169
+ if (every > 0 && rowNo > (lc.win?.rowOffset || 0) + 1 && (rowNo - 1) % every === 0 && units[u0]) units[u0].breakBefore = true;
18162
18170
  endBand();
18163
18171
  }
18164
18172
  return;
@@ -18218,7 +18226,8 @@ register("table", {
18218
18226
  if (lc.rowBudget?.cut || shown2.has(bk)) return;
18219
18227
  shown2.add(bk);
18220
18228
  const sc = { rows: bk.rows, index: -1, run: [], number: bi + 1, prevRows: bi > 0 ? sibs[bi - 1].rows : null, siblings: sibRows(sibs), ...kids ? { level: depth, recRows: recOf.get(bk) } : {} };
18221
- const gctx = { ...ctx, fields: bk.rows[0], aggRows: bk.rows, aggIndex: void 0, scopes: { ...ctx.scopes, [gname]: sc }, groupKey: bk.key, group: sc };
18229
+ const cont = bi === 0 && (level === 0 || ctx.__cont) ? lc.win?.cont?.[level] : null;
18230
+ const gctx = { ...ctx, fields: cont ? cont.first : bk.rows[0], aggRows: bk.rows, aggIndex: void 0, scopes: { ...ctx.scopes, [gname]: sc }, groupKey: bk.key, group: sc, __cont: !!cont, __before: cont && level === groups.length - 1 ? cont.before : 0 };
18222
18231
  if (kids) {
18223
18232
  gctx.level = depth;
18224
18233
  if (g.indent) gctx.indent = (ctx.indent || 0) + depth * Number(g.indent);
@@ -18228,10 +18237,15 @@ register("table", {
18228
18237
  const dflt = kids && g.expandLevels != null ? depth < Number(g.expandLevels) : !g.initiallyCollapsed;
18229
18238
  const open = !g.collapsible ? true : lc.state?.toggles?.[tkey] ?? dflt;
18230
18239
  const start = units.length;
18231
- const hctx = g.header?.length ? { ...gctx, pendingRows: fl ? [bk.rows[0]] : recOf.get(bk) || bk.rows } : gctx;
18232
- const hu = (g.header || []).map((r, ri) => layRow(r, hctx, "groupHeader", { level, ...ri === 0 && g.collapsible ? { toggle: { key: tkey, open } } : {} })).filter(Boolean);
18240
+ const hctx = g.header?.length ? { ...gctx, pendingRows: fl ? [cont ? cont.first : bk.rows[0]] : recOf.get(bk) || bk.rows } : gctx;
18241
+ const hu = (cont && !g.repeatHeader ? [] : g.header || []).map((r, ri) => layRow(r, hctx, "groupHeader", { level, ...ri === 0 && g.collapsible ? { toggle: { key: tkey, open } } : {} })).filter(Boolean);
18233
18242
  endBand();
18234
18243
  const before = units.length;
18244
+ if (lc.win && !cont && before > start) {
18245
+ for (let k = start; k < before; k++) units[k].dataRow = rowNo + 1;
18246
+ units[start].rowHead = true;
18247
+ units[start].headLevel = level;
18248
+ }
18235
18249
  const rep = g.repeatHeader && before > start && !lc.fixed ? [...ctx.__rep || [], (() => {
18236
18250
  const hdr = units.slice(start, before), h0 = hdr[0].top, its = [];
18237
18251
  for (const u of hdr) for (const it of shiftLocal(u.items.filter((i) => i.t !== "link" && i.t !== "bookmark"), u.top - h0)) its.push(it);
@@ -18271,7 +18285,10 @@ register("table", {
18271
18285
  if (g.pageBreak === "after" && bi < sibs.length - 1) units[units.length - 1].breakAfter = true;
18272
18286
  if (g.keepTogether) {
18273
18287
  const id = `${item.name}:g${level}:${path2}:${lc.nextId()}`;
18274
- for (let k = start; k < units.length; k++) units[k].block ||= id;
18288
+ for (let k = start; k < units.length; k++) if (!units[k].block) {
18289
+ units[k].block = id;
18290
+ if (cont) units[k].blockOpen = true;
18291
+ }
18275
18292
  }
18276
18293
  }
18277
18294
  };
@@ -19161,7 +19178,8 @@ function paginate(units, tables, pageH, warn, stats) {
19161
19178
  if (b) {
19162
19179
  b.top = Math.min(b.top, u.top);
19163
19180
  b.bottom = Math.max(b.bottom, u.top + u.height);
19164
- } else blockMap.set(u.block, { top: u.top, bottom: u.top + u.height });
19181
+ if (u.blockOpen) b.open = true;
19182
+ } else blockMap.set(u.block, { top: u.top, bottom: u.top + u.height, open: !!u.blockOpen });
19165
19183
  }
19166
19184
  const blockUnits = /* @__PURE__ */ new Map();
19167
19185
  for (const u of units) if (u.block) {
@@ -19169,18 +19187,18 @@ function paginate(units, tables, pageH, warn, stats) {
19169
19187
  if (!l) blockUnits.set(u.block, l = []);
19170
19188
  l.push(u);
19171
19189
  }
19172
- const blocks = [...blockMap.values()].filter((b) => b.bottom - b.top <= pageH + EPS2);
19190
+ const blocks = [...blockMap.values()].filter((b) => !b.open && b.bottom - b.top <= pageH + EPS2);
19173
19191
  for (const b of blocks) cand.push(b.top, b.bottom);
19174
19192
  cand.sort((a, b) => a - b);
19175
19193
  const grpRows = /* @__PURE__ */ new Map();
19176
19194
  for (const u of units) if (u.grp) {
19177
19195
  let g = grpRows.get(u.grp);
19178
- if (!g) grpRows.set(u.grp, g = { tops: /* @__PURE__ */ new Set(), first: u.top, last: 0, block: u.block || null });
19196
+ if (!g) grpRows.set(u.grp, g = { tops: /* @__PURE__ */ new Set(), first: u.top, last: 0, block: u.block || null, before: u.grpBefore || 0 });
19179
19197
  g.tops.add(u.top);
19180
19198
  g.last = Math.max(g.last, u.top + u.height);
19181
19199
  if (g.block !== (u.block || null)) g.block = void 0;
19182
19200
  }
19183
- const widowGroups = [...grpRows.values()].map((g) => ({ first: g.first, last: g.last, tops: [...g.tops].sort((a, b) => a - b), block: g.block })).filter((g) => g.tops.length >= 4 || g.tops.length >= 2 && g.last - g.first <= pageH + EPS2).sort((a, b) => a.first - b.first);
19201
+ const widowGroups = [...grpRows.values()].map((g) => ({ first: g.first, last: g.last, tops: [...g.tops].sort((a, b) => a - b), block: g.block, before: g.before, n: g.tops.size + g.before })).filter((g) => g.n >= 4 || !g.before && g.n >= 2 && g.last - g.first <= pageH + EPS2).sort((a, b) => a.first - b.first);
19184
19202
  const wFirst = widowGroups.map((g) => g.first);
19185
19203
  const wMaxLast = [];
19186
19204
  widowGroups.forEach((g, i) => wMaxLast.push(Math.max(i ? wMaxLast[i - 1] : -Infinity, g.last)));
@@ -19207,9 +19225,9 @@ function paginate(units, tables, pageH, warn, stats) {
19207
19225
  tick(1);
19208
19226
  const g = widowGroups[i];
19209
19227
  if (g.last <= y + EPS2 || g.block && !withBlocks) continue;
19210
- if (g.tops.length < 4) return false;
19211
- const above = rowsAbove(g.tops, y);
19212
- if (above < 2 || g.tops.length - above < 2) return false;
19228
+ if (g.n < 4) return false;
19229
+ const above = g.before + rowsAbove(g.tops, y);
19230
+ if (above < 2 || g.n - above < 2) return false;
19213
19231
  }
19214
19232
  return true;
19215
19233
  };
@@ -19264,7 +19282,7 @@ function paginate(units, tables, pageH, warn, stats) {
19264
19282
  if (u.block) {
19265
19283
  const bl = blockMap.get(u.block);
19266
19284
  if (movedBlocks.has(bl)) continue;
19267
- if (!bl || bl.bottom - bl.top > room + EPS2 || bl.top <= top2 + EPS2) return null;
19285
+ if (!bl || bl.open || bl.bottom - bl.top > room + EPS2 || bl.top <= top2 + EPS2) return null;
19268
19286
  movedBlocks.add(bl);
19269
19287
  for (const m of blockUnits.get(u.block)) if (!placed.has(m)) moved.push(m);
19270
19288
  continue;
@@ -22775,14 +22793,16 @@ async function render(def0, opts = {}) {
22775
22793
  ctxFor: (item) => {
22776
22794
  const ds = item.dataSet || defaultDs;
22777
22795
  const rows = ds && dataSets[ds] || [];
22778
- return { ...baseCtx, globals, fields: rows[0] || null, aggRows: rows };
22796
+ return { ...baseCtx, globals, fields: (opts.pageWindow?.first && ds === defaultDs ? opts.pageWindow.first : rows[0]) || null, aggRows: rows };
22779
22797
  },
22780
22798
  subreports: null,
22781
22799
  bodyWidth: opts.bodyWidth ?? page.bodyWidth,
22782
22800
  images: def.images || {},
22783
22801
  imageBudget,
22784
- cellItems: { left: 1e5 }
22802
+ cellItems: { left: 1e5 },
22785
22803
  // rows of items inside table cells, for the whole render (items/index.js)
22804
+ win: opts.pageWindow || null
22805
+ // paged.js: units carry their row number (dataRow, rowHead), rows and groups continue
22786
22806
  };
22787
22807
  return lc;
22788
22808
  };
@@ -22920,12 +22940,14 @@ async function render(def0, opts = {}) {
22920
22940
  const bodyTop = mt + g.hH;
22921
22941
  const items = [];
22922
22942
  const cut = lc.rowBudget?.cut;
22923
- const globals = { ...baseCtx.globals, PageNumber: n5 - secStart[n5] + 1, TotalPages: cut ? "…" : secLen.get(secStart[n5]), OverallPageNumber: n5 + 1, OverallTotalPages: cut ? "…" : total };
22943
+ const win = opts.pageWindow, off = win ? win.offset : 0, all = win ? win.total ?? "…" : null;
22944
+ const globals = { ...baseCtx.globals, PageNumber: n5 - secStart[n5] + 1 + (secStart[n5] ? 0 : off), TotalPages: cut ? "…" : all ?? secLen.get(secStart[n5]), OverallPageNumber: n5 + 1 + off, OverallTotalPages: cut ? "…" : all ?? total };
22945
+ const isFirst = n5 + off === 0, isLast = n5 === total - 1 && (!win || win.final);
22924
22946
  const plc = makeLc(globals, true);
22925
- const band = (section, y0, isFirst, isLast) => {
22947
+ const band = (section, y0, isFirst2, isLast2) => {
22926
22948
  if (!section) return;
22927
- if (isFirst && section.printOnFirstPage === false) return;
22928
- if (isLast && section.printOnLastPage === false) return;
22949
+ if (isFirst2 && section.printOnFirstPage === false) return;
22950
+ if (isLast2 && section.printOnLastPage === false) return;
22929
22951
  const capped2 = () => warn(`The page headers and footers would draw more than ${BAND_ITEMS.toLocaleString("en-US")} items in this report; they are left out of the later pages. Make them lighter, or the report shorter.`);
22930
22952
  if (bandWork.left <= 0) {
22931
22953
  capped2();
@@ -22946,7 +22968,7 @@ async function render(def0, opts = {}) {
22946
22968
  for (const u of r.units) if (c.paged) placeItems(u.items, ml, y0 + u.top, items);
22947
22969
  else for (const it of shiftItems(u.items, ml, y0 + u.top)) items.push(it);
22948
22970
  };
22949
- band(g.hdr, mt, g.own.h ? k === 0 : n5 === 0, g.own.h ? last : n5 === total - 1);
22971
+ band(g.hdr, mt, g.own.h ? k === 0 : isFirst, g.own.h ? last : isLast);
22950
22972
  const frozen = [];
22951
22973
  for (let c = 0; c < colCount; c++) {
22952
22974
  const p = slices[k * colCount + c];
@@ -22956,30 +22978,38 @@ async function render(def0, opts = {}) {
22956
22978
  for (const t of body.tables) {
22957
22979
  if (!(t.top < p.bottom - EPS4 && t.bottom > p.top + EPS4)) continue;
22958
22980
  const cont = p.repeat.includes(t);
22959
- let off = 0;
22981
+ let off2 = 0;
22960
22982
  if (!cont) {
22961
- for (const r of p.repeat) if (t.x0 < r.x1 - EPS4 && r.x0 < t.x1 - EPS4) off = Math.max(off, r.headerHeight);
22983
+ for (const r of p.repeat) if (t.x0 < r.x1 - EPS4 && r.x0 < t.x1 - EPS4) off2 = Math.max(off2, r.headerHeight);
22962
22984
  }
22963
- const y = cont ? bodyTop : bodyTop + off + t.top - p.top;
22964
- frozen.push({ x: cx + t.x0, y, w: t.x1 - t.x0, h: t.headerHeight, end: bodyTop + (cont ? t.headerHeight : off) + Math.min(t.bottom, p.bottom) - p.top });
22985
+ const y = cont ? bodyTop : bodyTop + off2 + t.top - p.top;
22986
+ frozen.push({ x: cx + t.x0, y, w: t.x1 - t.x0, h: t.headerHeight, end: bodyTop + (cont ? t.headerHeight : off2) + Math.min(t.bottom, p.bottom) - p.top });
22965
22987
  }
22966
22988
  for (const u of p.units) {
22967
- let off = 0;
22968
- for (const t of p.repeat) if (u.x0 < t.x1 - EPS4 && t.x0 < u.x1 - EPS4) off = Math.max(off, t.headerHeight);
22969
- if (u.atBottom) off += Math.max(0, cH - off - (p.bottom - p.top));
22970
- if (u.cont && u.top <= p.top + EPS4) placeItems(u.cont, cx, bodyTop + off, items);
22971
- placeItems(u.items, cx, bodyTop + off + (u.top - p.top), items);
22989
+ let off2 = 0;
22990
+ for (const t of p.repeat) if (u.x0 < t.x1 - EPS4 && t.x0 < u.x1 - EPS4) off2 = Math.max(off2, t.headerHeight);
22991
+ if (u.atBottom) off2 += Math.max(0, cH - off2 - (p.bottom - p.top));
22992
+ if (u.cont && u.top <= p.top + EPS4) placeItems(u.cont, cx, bodyTop + off2, items);
22993
+ placeItems(u.items, cx, bodyTop + off2 + (u.top - p.top), items);
22972
22994
  }
22973
22995
  }
22974
- band(g.ftr, ph - pg.margins.bottom - g.fH, g.own.f ? k === 0 : n5 === 0, g.own.f ? last : n5 === total - 1);
22996
+ band(g.ftr, ph - pg.margins.bottom - g.fH, g.own.f ? k === 0 : isFirst, g.own.f ? last : isLast);
22975
22997
  let j = 0;
22976
22998
  for (let i = 0; i < items.length; i++) {
22977
22999
  const it = items[i];
22978
- if (it.t === "bookmark") (it.heading ? headings : bookmarks2).push({ label: it.label, page: n5 + 1, y: it.y, level: it.level || 0, ...secStart[n5] ? { shown: n5 - secStart[n5] + 1 } : {} });
23000
+ if (it.t === "bookmark") (it.heading ? headings : bookmarks2).push({ label: it.label, page: n5 + 1 + off, y: it.y, level: it.level || 0, ...secStart[n5] ? { shown: n5 - secStart[n5] + 1 } : {} });
22979
23001
  else items[j++] = it;
22980
23002
  }
22981
23003
  items.length = j;
22982
23004
  const out = frozen.length ? { items, frozen } : { items };
23005
+ if (win) {
23006
+ const u = slices[k * colCount]?.units[0];
23007
+ if (u?.dataRow != null) {
23008
+ out.firstRow = u.dataRow;
23009
+ out.rowHead = !!u.rowHead;
23010
+ if (u.headLevel != null) out.headLevel = u.headLevel;
23011
+ }
23012
+ }
22983
23013
  if (pg.width !== first.width || ph !== pageH) {
22984
23014
  out.width = pg.width;
22985
23015
  out.height = ph;
@@ -23378,36 +23408,9 @@ function pdfEncryptOptions(pdf) {
23378
23408
  }
23379
23409
 
23380
23410
  // src/exporters/pdf.js
23381
- import { PDFDocument, PDFName as PDFName3, PDFString as PDFString4, PDFHexString as PDFHexString4, PDFRawStream as PDFRawStream2, rgb as rgb2 } from "pdf-lib";
23411
+ import { PDFDocument, PDFName as PDFName3, PDFString as PDFString4, PDFHexString as PDFHexString5, PDFRawStream as PDFRawStream2, rgb as rgb3 } from "pdf-lib";
23382
23412
  import fontkitModule2 from "@pdf-lib/fontkit";
23383
23413
 
23384
- // src/exporters/color.js
23385
- var NAMED2 = { black: "#000000", white: "#ffffff", red: "#ff0000", green: "#008000", blue: "#0000ff", gray: "#808080", grey: "#808080", orange: "#ffa500", yellow: "#ffff00" };
23386
- function parseColor(c) {
23387
- if (!c || c === "none" || c === "transparent") return null;
23388
- let s = String(c).trim().toLowerCase();
23389
- if (NAMED2[s]) s = NAMED2[s];
23390
- let m = /^#([0-9a-f]{3,8})$/.exec(s);
23391
- if (m) {
23392
- let h = m[1];
23393
- if (h.length === 3 || h.length === 4) h = [...h].map((x) => x + x).join("");
23394
- const n5 = parseInt(h.slice(0, 6), 16);
23395
- const a = h.length === 8 ? parseInt(h.slice(6, 8), 16) / 255 : 1;
23396
- return { r: (n5 >> 16 & 255) / 255, g: (n5 >> 8 & 255) / 255, b: (n5 & 255) / 255, a };
23397
- }
23398
- m = /^rgba?\(([^)]+)\)$/.exec(s);
23399
- if (m) {
23400
- const [r, g, b, a = 1] = m[1].split(/[\s,/]+/).map(Number);
23401
- return { r: r / 255, g: g / 255, b: b / 255, a };
23402
- }
23403
- return null;
23404
- }
23405
- function cssColor(c) {
23406
- const p = parseColor(c);
23407
- if (!p) return "none";
23408
- return `rgba(${Math.round(p.r * 255)},${Math.round(p.g * 255)},${Math.round(p.b * 255)},${p.a})`;
23409
- }
23410
-
23411
23414
  // src/exporters/pdfa.js
23412
23415
  import { PDFName, PDFNumber as PDFNumber2, PDFString as PDFString2, PDFHexString as PDFHexString2, PDFArray as PDFArray2, PDFDict as PDFDict2 } from "pdf-lib";
23413
23416
  var xml = (s) => String(s).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
@@ -23481,6 +23484,35 @@ function setUaMetadata(doc, { title: title2 = "Report", author = void 0, created
23481
23484
 
23482
23485
  // src/exporters/svgimage.js
23483
23486
  import { pushGraphicsState, popGraphicsState, concatTransformationMatrix, rgb } from "pdf-lib";
23487
+
23488
+ // src/exporters/color.js
23489
+ var NAMED2 = { black: "#000000", white: "#ffffff", red: "#ff0000", green: "#008000", blue: "#0000ff", gray: "#808080", grey: "#808080", orange: "#ffa500", yellow: "#ffff00" };
23490
+ function parseColor(c) {
23491
+ if (!c || c === "none" || c === "transparent") return null;
23492
+ let s = String(c).trim().toLowerCase();
23493
+ if (NAMED2[s]) s = NAMED2[s];
23494
+ let m = /^#([0-9a-f]{3,8})$/.exec(s);
23495
+ if (m) {
23496
+ let h = m[1];
23497
+ if (h.length === 3 || h.length === 4) h = [...h].map((x) => x + x).join("");
23498
+ const n5 = parseInt(h.slice(0, 6), 16);
23499
+ const a = h.length === 8 ? parseInt(h.slice(6, 8), 16) / 255 : 1;
23500
+ return { r: (n5 >> 16 & 255) / 255, g: (n5 >> 8 & 255) / 255, b: (n5 & 255) / 255, a };
23501
+ }
23502
+ m = /^rgba?\(([^)]+)\)$/.exec(s);
23503
+ if (m) {
23504
+ const [r, g, b, a = 1] = m[1].split(/[\s,/]+/).map(Number);
23505
+ return { r: r / 255, g: g / 255, b: b / 255, a };
23506
+ }
23507
+ return null;
23508
+ }
23509
+ function cssColor(c) {
23510
+ const p = parseColor(c);
23511
+ if (!p) return "none";
23512
+ return `rgba(${Math.round(p.r * 255)},${Math.round(p.g * 255)},${Math.round(p.b * 255)},${p.a})`;
23513
+ }
23514
+
23515
+ // src/exporters/svgimage.js
23484
23516
  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]];
23485
23517
  var I = [1, 0, 0, 1, 0, 0];
23486
23518
  var TRANSFORMS = /* @__PURE__ */ new Set(["matrix", "translate", "scale", "rotate", "skewX", "skewY"]);
@@ -24547,11 +24579,8 @@ function pngProblem(b) {
24547
24579
  return null;
24548
24580
  }
24549
24581
 
24550
- // src/exporters/pdf.js
24551
- var fontkit2 = (
24552
- /** @type {any} */
24553
- fontkitModule2.default || fontkitModule2
24554
- );
24582
+ // src/exporters/pdfpaint.js
24583
+ import { PDFHexString as PDFHexString4, rgb as rgb2 } from "pdf-lib";
24555
24584
  var colors = /* @__PURE__ */ new Map();
24556
24585
  var col = (c) => {
24557
24586
  if (colors.has(c)) return colors.get(c);
@@ -24566,148 +24595,463 @@ var n4 = (v) => Math.round(v * 1e4) / 1e4;
24566
24595
  var hex4 = (id) => id.toString(16).padStart(4, "0");
24567
24596
  var KAPPA = 4 * ((Math.SQRT2 - 1) / 3);
24568
24597
  var cleanText = (t) => t.replace(/\t|\u0085|\u2028|\u2029/g, " ").replace(/[\b\v]/g, "");
24569
- function exportPdf(model, fontStore2, opt = {}) {
24570
- return withDeadline(
24571
- pdfOf(model, fontStore2, opt),
24572
- /** @type {any} */
24573
- opt.timeoutMs
24574
- );
24575
- }
24576
- async function pdfOf(model, fontStore2, opt) {
24577
- const fixed2 = fixedDate(opt);
24578
- const when = fixed2 ?? /* @__PURE__ */ new Date();
24579
- const fileId = fixed2 ? await contentId(model, opt, when) : void 0;
24580
- const doc = await PDFDocument.create({ updateMetadata: false });
24581
- doc.registerFontkit(fontkit2);
24582
- doc.setTitle(opt.title || "Report");
24583
- doc.setProducer("ReportWright");
24584
- doc.setCreator("ReportWright");
24585
- if (opt.author) doc.setAuthor(opt.author);
24586
- setInfoDates(doc, when);
24587
- if (fileId) doc.context.trailerInfo.ID = doc.context.obj([PDFHexString4.of(fileId), PDFHexString4.of(fileId)]);
24588
- const used = /* @__PURE__ */ new Map();
24589
- const shaped = /* @__PURE__ */ new Map();
24590
- const spans2 = /* @__PURE__ */ new WeakMap();
24591
- const chars = (key) => {
24592
- let c = used.get(key);
24593
- if (!c) {
24594
- c = /* @__PURE__ */ new Set([32]);
24595
- used.set(key, c);
24596
- }
24597
- return c;
24598
+ function drawRun(c, run, x, y, size, pf, color2, spans2, texts) {
24599
+ const f4 = pf.embedder.font;
24600
+ const per = 1e3 / size;
24601
+ const span = (text2) => `/Span <</ActualText ${PDFHexString4.fromText(text2).toString()}>> BDC
24602
+ `;
24603
+ c.et();
24604
+ c.paint(color2, null);
24605
+ c.font(pf, size);
24606
+ if (!run.rtl) c.s += span(run.text);
24607
+ c.s += `BT ${n2(x)} ${n2(y)} Td
24608
+ `;
24609
+ let arr = "";
24610
+ let pen = 0, rise = 0;
24611
+ const flush = () => {
24612
+ if (arr) c.s += `[${arr}] TJ
24613
+ `;
24614
+ arr = "";
24598
24615
  };
24599
- 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] : [])) {
24600
- for (const l of it.lines) {
24601
- if (!l.runs) {
24602
- const c = chars(it.font);
24603
- for (const ch of l.text) c.add(
24604
- /** @type {number} */
24605
- ch.codePointAt(0)
24606
- );
24607
- continue;
24608
- }
24609
- for (const r of l.runs) {
24610
- const c = chars(r.font);
24611
- for (const ch of r.text) c.add(
24612
- /** @type {number} */
24613
- ch.codePointAt(0)
24614
- );
24615
- let g = shaped.get(r.font);
24616
- if (!g) {
24617
- g = /* @__PURE__ */ new Map();
24618
- shaped.set(r.font, g);
24619
- }
24620
- glyphText(r, fontStore2.get(r.font), g, spans2);
24621
- }
24616
+ const all = run.glyphs;
24617
+ const adv = (id) => f4.getGlyph(id).advanceWidth;
24618
+ let g = all, quietAt = -1;
24619
+ if (run.rtl) {
24620
+ const hasBase = /* @__PURE__ */ new Set();
24621
+ for (let i = 0; i < all.length; i += 4) if (adv(all[i]) > 0) hasBase.add(all[i + 3]);
24622
+ const quiet = (i) => spans2?.has(all[i + 3]) ? adv(all[i]) === 0 && hasBase.has(all[i + 3]) : texts?.get(all[i]) === "";
24623
+ g = [];
24624
+ for (const late of [false, true]) {
24625
+ if (late) quietAt = g.length;
24626
+ 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]);
24622
24627
  }
24628
+ if (quietAt === g.length) quietAt = -1;
24623
24629
  }
24624
- const fieldFonts = /* @__PURE__ */ new Set();
24625
- for (const pg of model.pages) for (const it of pg.items) if (it.t === "field") fieldFonts.add(fieldFont(it));
24626
- const fonts = /* @__PURE__ */ new Map();
24627
- const font = async (key) => {
24628
- if (!fonts.has(key)) {
24629
- const full = fontStore2.bytes.get(key);
24630
- let bytes = full;
24631
- if (!bytes) throw new Error(`Font "${key}" is not loaded`);
24632
- const glyphs = shaped.get(key);
24633
- if (opt.subset && !fieldFonts.has(key) && !fontStore2.get(key)["OS/2"]?.fsType?.noSubsetting) {
24634
- const cps = used.get(key) || /* @__PURE__ */ new Set([32]);
24635
- try {
24636
- const sub = withPadding(await opt.subset(bytes, cps, glyphs ? { glyphs: glyphs.keys() } : void 0));
24637
- const f4 = fontkit2.create(sub);
24638
- for (const cp of cps) void f4.glyphForCodePoint(cp).advanceWidth;
24639
- for (const id of glyphs?.keys() || []) void f4.getGlyph(id).advanceWidth;
24640
- bytes = sub;
24641
- } catch {
24642
- }
24643
- }
24644
- const pf = await doc.embedFont(bytes, { subset: false, customName: bytes === full ? void 0 : `${subsetTag(bytes)}+${fontStore2.get(key).postscriptName || "Font"}` });
24645
- plainEncoding(pf);
24646
- if (glyphs) addGlyphs(pf, glyphs, !!opt.tagged);
24647
- const file = bytes, e2 = (
24648
- /** @type {any} */
24649
- pf.embedder
24650
- );
24651
- if (!e2.isCFF()) e2.embedFontStream = async (c) => c.register(PDFRawStream2.of(c.obj({ Filter: "FlateDecode", Length1: file.length }), await deflate(file)));
24652
- fonts.set(key, pf);
24630
+ const starts = run.rtl ? [...new Set(all.filter((_, i) => i % 4 === 3))].sort((a, b) => a - b) : [];
24631
+ let inSpan = false;
24632
+ for (let i = 0; i < g.length; i += 4) {
24633
+ const id = g[i], gx = g[i + 1], gy = g[i + 2], cl = g[i + 3];
24634
+ if (i === quietAt) {
24635
+ flush();
24636
+ c.s += span("");
24637
+ inSpan = true;
24638
+ } else if (run.rtl && spans2?.has(cl) && (quietAt < 0 || i < quietAt) && (i === 0 || g[i - 1] !== cl)) {
24639
+ flush();
24640
+ c.s += span(run.text.slice(cl, starts[starts.indexOf(cl) + 1] ?? run.text.length));
24641
+ inSpan = true;
24653
24642
  }
24654
- return fonts.get(key);
24655
- };
24656
- const images = /* @__PURE__ */ new Map();
24657
- const image2 = async (src) => {
24658
- if (images.has(src)) return images.get(src);
24659
- const out = await loadImage(src).catch((e2) => ({ img: null, why: `it could not be embedded (${e2?.message || e2})` }));
24660
- images.set(src, out);
24661
- return out;
24662
- };
24663
- async function loadImage(src) {
24664
- const local = /^data:/i.test(src);
24665
- if (local && dataUriBytes(src) > IMAGE_LIMITS.bytes) return { img: null, why: "it is larger than the image size limit" };
24666
- if (!local && !opt.fetchImage) return { img: null, why: "it is a URL, and no fetchImage was given to load it" };
24667
- const bytes = local ? dataUriBytesOf(src) : await opt.fetchImage(src);
24668
- if (!bytes?.length) return { img: null, why: "it could not be loaded" };
24669
- if (bytes.length > IMAGE_LIMITS.bytes) return { img: null, why: "it is larger than the image size limit" };
24670
- const info = imageInfoOf(bytes);
24671
- if (info?.type === "svg") {
24672
- const svg = parseSvg(new TextDecoder().decode(bytes));
24673
- return svg ? { img: { svg, width: svg.w, height: svg.h } } : { img: null, why: "the SVG could not be read" };
24643
+ if (gy !== rise) {
24644
+ flush();
24645
+ c.s += `${n4(gy)} Ts
24646
+ `;
24647
+ rise = gy;
24674
24648
  }
24675
- if (info?.type === "png") {
24676
- const why = "w" in info && !/** @type {any} */
24677
- info.suspect && info.w * info.h <= IMAGE_LIMITS.pixels ? pngProblem(bytes) : "too large or animated";
24678
- return why ? { img: null, why: `the PNG is not usable (${why})` } : { img: await doc.embedPng(bytes) };
24649
+ const adj = Math.round((pen - gx) * per * 1e3) / 1e3;
24650
+ if (id === 0 && c.tagged) pen = gx;
24651
+ else {
24652
+ arr += (adj ? `${adj}` : "") + `<${hex4(id)}>`;
24653
+ pen = gx + adv(id) * size / f4.unitsPerEm;
24679
24654
  }
24680
- if (info?.type === "jpeg") return { img: await doc.embedJpg(bytes) };
24681
- return { img: null, why: info ? `${info.type.toUpperCase()} is not embedded (PNG, JPEG and SVG are)` : "it is not a PNG, JPEG or SVG" };
24682
- }
24683
- const ctx = doc.context;
24684
- const res = ctx.obj({ Font: {}, ExtGState: {}, XObject: {} });
24685
- const resRef = ctx.register(res);
24686
- const names = /* @__PURE__ */ new Map();
24687
- const nameOf = (kind, key, value) => {
24688
- let n5 = names.get(key);
24689
- if (!n5) {
24690
- n5 = `${kind[0]}${names.size + 1}`;
24691
- names.set(key, n5);
24692
- res.get(PDFName3.of(kind)).set(PDFName3.of(n5), value());
24655
+ if (inSpan && (i + 4 >= g.length || (quietAt < 0 || i + 4 < quietAt) && g[i + 7] !== cl || i + 4 === quietAt)) {
24656
+ flush();
24657
+ c.s += "EMC\n";
24658
+ inSpan = false;
24693
24659
  }
24694
- return n5;
24695
- };
24696
- const shared = {
24697
- font: (pf) => nameOf("Font", pf, () => pf.ref),
24698
- gs: (ca, CA) => nameOf("ExtGState", `gs ${ca} ${CA}`, () => ctx.obj({ Type: "ExtGState", ca, CA })),
24699
- image: (img) => nameOf("XObject", img, () => img.ref)
24700
- };
24701
- const links = [];
24702
- const taken = /* @__PURE__ */ new Set();
24703
- const uniqueName = (n5) => {
24704
- let name = n5, i = 1;
24705
- while (taken.has(name)) name = `${n5}_${++i}`;
24706
- taken.add(name);
24707
- return name;
24708
- };
24709
- const contents = [];
24710
- if (opt.tagged) needsTableData(model, "An accessible PDF");
24660
+ }
24661
+ flush();
24662
+ if (rise) c.s += "0 Ts\n";
24663
+ c.s += "ET\n";
24664
+ if (!run.rtl) c.s += "EMC\n";
24665
+ }
24666
+ function glyphText(run, font, out, spans2) {
24667
+ const g = run.glyphs;
24668
+ const starts = [...new Set(g.filter((_, i) => i % 4 === 3))].sort((a, b) => a - b);
24669
+ for (let k = 0; k < starts.length; k++) {
24670
+ const chars = [...run.text.slice(starts[k], starts[k + 1] ?? run.text.length)];
24671
+ const ids = [];
24672
+ for (let i = 0; i < g.length; i += 4) if (g[i + 3] === starts[k]) ids.push(g[i]);
24673
+ const own = new Map(chars.map((ch) => [font.glyphForCodePoint(ch.codePointAt(0)).id, ch]));
24674
+ const rest2 = chars.filter((ch) => !ids.includes(font.glyphForCodePoint(ch.codePointAt(0)).id)).join("");
24675
+ const carrier = rest2 ? ids.find((id) => !own.has(id) && font.getGlyph(id).advanceWidth > 0) ?? ids.find((id) => !own.has(id)) : void 0;
24676
+ let ok = !rest2 || carrier !== void 0;
24677
+ const want = /* @__PURE__ */ new Map();
24678
+ for (const id of ids) {
24679
+ const t = own.get(id) ?? (id === carrier ? rest2 : "");
24680
+ if (want.has(id) && want.get(id) !== t) ok = false;
24681
+ want.set(id, t);
24682
+ }
24683
+ for (const [id, t] of want) {
24684
+ if (!out.has(id)) out.set(id, t);
24685
+ else if (out.get(id) !== t) ok = false;
24686
+ }
24687
+ if (!ok && run.rtl && spans2) {
24688
+ let s = spans2.get(run);
24689
+ if (!s) spans2.set(run, s = /* @__PURE__ */ new Set());
24690
+ s.add(starts[k]);
24691
+ }
24692
+ }
24693
+ }
24694
+ function insideClip(it, m) {
24695
+ const k = it.clip, asc = m.asc * it.size, desc = m.desc * it.size;
24696
+ 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);
24697
+ }
24698
+ var Content = class {
24699
+ constructor(shared) {
24700
+ this.shared = shared;
24701
+ this._s = "";
24702
+ this.bt = false;
24703
+ this.tx = 0;
24704
+ this.ty = 0;
24705
+ this.st = { fill: "0 0 0", stroke: "0 0 0", lw: 1, dash: "[] 0", ca: 1, CA: 1, font: "", size: 0 };
24706
+ this.saved = [];
24707
+ this.lines = null;
24708
+ this.tagged = false;
24709
+ }
24710
+ /**
24711
+ * The operators so far. Any other drawing reads or appends to it, so the lines waiting are drawn first: the text
24712
+ * of a table's cells stays in one text object (relative moves, which compress to little) instead of one per cell.
24713
+ */
24714
+ get s() {
24715
+ this.flushLines();
24716
+ return this._s;
24717
+ }
24718
+ set s(v) {
24719
+ this._s = v;
24720
+ }
24721
+ /**
24722
+ * A straight line. Untagged, it waits until something other than text is drawn (table borders between cell
24723
+ * texts); collinear segments that touch, in the same stroke, become one (a row's border is one line).
24724
+ * ponytail: lines move after the text drawn just after them; both are thin and do not cover each other.
24725
+ */
24726
+ line(stroke, w, dash, x1, y1, x2, y2) {
24727
+ if (this.tagged) {
24728
+ this.paint(null, stroke, w, dash);
24729
+ this._s += `${n2(x1)} ${n2(y1)} m ${n2(x2)} ${n2(y2)} l S
24730
+ `;
24731
+ return;
24732
+ }
24733
+ const key = `${stroke.rgb}|${stroke.opacity}|${w}|${(dash || []).join(" ")}`;
24734
+ if (this.lines && this.lines.key !== key) this.flushLines();
24735
+ this.lines ||= { key, stroke, w, dash, segs: [] };
24736
+ const segs = this.lines.segs, last = segs[segs.length - 1];
24737
+ const eq = (a, b) => Math.abs(a - b) < 5e-3;
24738
+ if (last && eq(last[1], y1) && eq(last[3], y2) && eq(y1, y2) && eq(last[2], x1)) last[2] = x2;
24739
+ else if (last && eq(last[0], x1) && eq(last[2], x2) && eq(x1, x2) && eq(last[3], y1)) last[3] = y2;
24740
+ else segs.push([x1, y1, x2, y2]);
24741
+ }
24742
+ flushLines() {
24743
+ const L = this.lines;
24744
+ if (!L) return;
24745
+ this.lines = null;
24746
+ this.et();
24747
+ this.paint(null, L.stroke, L.w, L.dash);
24748
+ const g = L.segs;
24749
+ const dy = g.length > 2 ? Math.round((g[1][1] - g[0][1]) * 100) : 0;
24750
+ if (dy && g.every((q3, i) => q3[1] === q3[3] && n2(q3[0]) === n2(g[0][0]) && n2(q3[2]) === n2(g[0][2]) && Math.abs(q3[1] - (g[0][1] + i * dy / 100)) < 0.01)) {
24751
+ const one = `${n2(g[0][0])} ${n2(g[0][1])} m ${n2(g[0][2])} ${n2(g[0][1])} l S
24752
+ `;
24753
+ this._s += `q
24754
+ ${one}${`1 0 0 1 0 ${dy / 100} cm ${one}`.repeat(g.length - 1)}Q
24755
+ `;
24756
+ return;
24757
+ }
24758
+ this._s += g.map(([a, b, c, d]) => `${n2(a)} ${n2(b)} m ${n2(c)} ${n2(d)} l`).join(" ") + " S\n";
24759
+ }
24760
+ q() {
24761
+ this.et();
24762
+ this._s += "q\n";
24763
+ this.saved.push({ ...this.st });
24764
+ }
24765
+ Q() {
24766
+ this.et();
24767
+ this._s += "Q\n";
24768
+ this.st = this.saved.pop();
24769
+ }
24770
+ /**
24771
+ * A line of plain text at (x, y). Lines follow one another in one text object, each placed relative to the
24772
+ * last (in whole hundredths, so nothing drifts): most of a table page is these.
24773
+ * @param {string} str the glyphs, as a literal string's escaped body (array: a TJ array's body)
24774
+ */
24775
+ text(pf, size, color2, x, y, str, array = false) {
24776
+ this.setPaint(color2, null);
24777
+ this.setFont(pf, size);
24778
+ const X = Math.round(x * 10) * 10, Y = Math.round(y * 10) * 10;
24779
+ if (!this.bt) {
24780
+ this._s += "BT\n";
24781
+ this.bt = true;
24782
+ this.tx = 0;
24783
+ this.ty = 0;
24784
+ }
24785
+ this._s += array ? `${(X - this.tx) / 100} ${(Y - this.ty) / 100} Td [${str}] TJ
24786
+ ` : `${(X - this.tx) / 100} ${(Y - this.ty) / 100} Td (${str}) Tj
24787
+ `;
24788
+ this.tx = X;
24789
+ this.ty = Y;
24790
+ }
24791
+ /** end the open text object, if any: anything but text needs that (and draws the lines waiting) */
24792
+ et() {
24793
+ if (this.bt) {
24794
+ this._s += "ET\n";
24795
+ this.bt = false;
24796
+ }
24797
+ if (this.lines) this.flushLines();
24798
+ }
24799
+ lineWidth(w) {
24800
+ if (this.lines) this.flushLines();
24801
+ this.setLineWidth(w);
24802
+ }
24803
+ setLineWidth(w) {
24804
+ if (this.st.lw !== w) {
24805
+ this._s += `${n3(w)} w
24806
+ `;
24807
+ this.st.lw = w;
24808
+ }
24809
+ }
24810
+ /** the graphics state that sets these opacities, or undefined when they are set already */
24811
+ gsFor(ca, CA) {
24812
+ return ca === this.st.ca && CA === this.st.CA ? void 0 : this.shared.gs(ca, CA);
24813
+ }
24814
+ alpha(ca, CA) {
24815
+ if (this.lines) this.flushLines();
24816
+ this.setAlpha(ca, CA);
24817
+ }
24818
+ setAlpha(ca, CA) {
24819
+ const g = this.gsFor(ca, CA);
24820
+ if (g) {
24821
+ this._s += `/${g} gs
24822
+ `;
24823
+ this.st.ca = ca;
24824
+ this.st.CA = CA;
24825
+ }
24826
+ }
24827
+ /** set up to fill with fill and/or stroke with stroke (width w, dash); the lines waiting are drawn first */
24828
+ paint(fill3, stroke, w = 1, dash = null) {
24829
+ if (this.lines) this.flushLines();
24830
+ this.setPaint(fill3, stroke, w, dash);
24831
+ }
24832
+ setPaint(fill3, stroke, w = 1, dash = null) {
24833
+ const st = this.st;
24834
+ if (fill3 && fill3.rgb !== st.fill) {
24835
+ this._s += `${fill3.rgb} rg
24836
+ `;
24837
+ st.fill = fill3.rgb;
24838
+ }
24839
+ if (stroke) {
24840
+ if (stroke.rgb !== st.stroke) {
24841
+ this._s += `${stroke.rgb} RG
24842
+ `;
24843
+ st.stroke = stroke.rgb;
24844
+ }
24845
+ this.setLineWidth(w);
24846
+ const d = `[${(dash || []).map(n3).join(" ")}] 0`;
24847
+ if (d !== st.dash) {
24848
+ this._s += `${d} d
24849
+ `;
24850
+ st.dash = d;
24851
+ }
24852
+ }
24853
+ this.setAlpha(fill3 ? fill3.opacity : st.ca, stroke ? stroke.opacity : st.CA);
24854
+ }
24855
+ font(pf, size) {
24856
+ if (this.lines) this.flushLines();
24857
+ this.setFont(pf, size);
24858
+ }
24859
+ setFont(pf, size) {
24860
+ const name = this.shared.font(pf);
24861
+ if (name !== this.st.font || size !== this.st.size) {
24862
+ this._s += `/${name} ${n3(size)} Tf
24863
+ `;
24864
+ this.st.font = name;
24865
+ this.st.size = size;
24866
+ }
24867
+ }
24868
+ };
24869
+ function latin1(s) {
24870
+ const B = (
24871
+ /** @type {any} */
24872
+ globalThis.Buffer
24873
+ );
24874
+ if (B) return B.from(s, "latin1");
24875
+ const out = new Uint8Array(s.length);
24876
+ for (let i = 0; i < s.length; i++) out[i] = s.charCodeAt(i);
24877
+ return out;
24878
+ }
24879
+ async function deflate(bytes) {
24880
+ if (zslots.free > 0) zslots.free--;
24881
+ else await new Promise((ok) => zslots.wait.push(
24882
+ /** @type {() => void} */
24883
+ ok
24884
+ ));
24885
+ try {
24886
+ return await deflateNow(bytes);
24887
+ } finally {
24888
+ const next = zslots.wait.shift();
24889
+ if (next) next();
24890
+ else zslots.free++;
24891
+ }
24892
+ }
24893
+ var zslots = { free: 4, wait: (
24894
+ /** @type {(() => void)[]} */
24895
+ []
24896
+ ) };
24897
+ var NODE_ZLIB = (
24898
+ /** @type {any} */
24899
+ globalThis.process?.getBuiltinModule?.("node:zlib")
24900
+ );
24901
+ async function deflateNow(bytes) {
24902
+ const zlib = NODE_ZLIB;
24903
+ if (zlib) return new Promise((ok, fail2) => zlib.deflate(bytes, { level: 9 }, (e2, z) => e2 ? fail2(e2) : ok(z)));
24904
+ if (typeof CompressionStream === "undefined") return (await import("fflate")).zlibSync(bytes);
24905
+ return new Uint8Array(await new Response(new Blob([bytes]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
24906
+ }
24907
+
24908
+ // src/exporters/pdf.js
24909
+ var fontkit2 = (
24910
+ /** @type {any} */
24911
+ fontkitModule2.default || fontkitModule2
24912
+ );
24913
+ function exportPdf(model, fontStore2, opt = {}) {
24914
+ return withDeadline(
24915
+ pdfOf(model, fontStore2, opt),
24916
+ /** @type {any} */
24917
+ opt.timeoutMs
24918
+ );
24919
+ }
24920
+ async function pdfOf(model, fontStore2, opt) {
24921
+ const fixed2 = fixedDate(opt);
24922
+ const when = fixed2 ?? /* @__PURE__ */ new Date();
24923
+ const fileId = fixed2 ? await contentId(model, opt, when) : void 0;
24924
+ const doc = await PDFDocument.create({ updateMetadata: false });
24925
+ doc.registerFontkit(fontkit2);
24926
+ doc.setTitle(opt.title || "Report");
24927
+ doc.setProducer("ReportWright");
24928
+ doc.setCreator("ReportWright");
24929
+ if (opt.author) doc.setAuthor(opt.author);
24930
+ setInfoDates(doc, when);
24931
+ if (fileId) doc.context.trailerInfo.ID = doc.context.obj([PDFHexString5.of(fileId), PDFHexString5.of(fileId)]);
24932
+ const used = /* @__PURE__ */ new Map();
24933
+ const shaped = /* @__PURE__ */ new Map();
24934
+ const spans2 = /* @__PURE__ */ new WeakMap();
24935
+ const chars = (key) => {
24936
+ let c = used.get(key);
24937
+ if (!c) {
24938
+ c = /* @__PURE__ */ new Set([32]);
24939
+ used.set(key, c);
24940
+ }
24941
+ return c;
24942
+ };
24943
+ 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] : [])) {
24944
+ for (const l of it.lines) {
24945
+ if (!l.runs) {
24946
+ const c = chars(it.font);
24947
+ for (const ch of l.text) c.add(
24948
+ /** @type {number} */
24949
+ ch.codePointAt(0)
24950
+ );
24951
+ continue;
24952
+ }
24953
+ for (const r of l.runs) {
24954
+ const c = chars(r.font);
24955
+ for (const ch of r.text) c.add(
24956
+ /** @type {number} */
24957
+ ch.codePointAt(0)
24958
+ );
24959
+ let g = shaped.get(r.font);
24960
+ if (!g) {
24961
+ g = /* @__PURE__ */ new Map();
24962
+ shaped.set(r.font, g);
24963
+ }
24964
+ glyphText(r, fontStore2.get(r.font), g, spans2);
24965
+ }
24966
+ }
24967
+ }
24968
+ const fieldFonts = /* @__PURE__ */ new Set();
24969
+ for (const pg of model.pages) for (const it of pg.items) if (it.t === "field") fieldFonts.add(fieldFont(it));
24970
+ const fonts = /* @__PURE__ */ new Map();
24971
+ const font = async (key) => {
24972
+ if (!fonts.has(key)) {
24973
+ const full = fontStore2.bytes.get(key);
24974
+ let bytes = full;
24975
+ if (!bytes) throw new Error(`Font "${key}" is not loaded`);
24976
+ const glyphs = shaped.get(key);
24977
+ if (opt.subset && !fieldFonts.has(key) && !fontStore2.get(key)["OS/2"]?.fsType?.noSubsetting) {
24978
+ const cps = used.get(key) || /* @__PURE__ */ new Set([32]);
24979
+ try {
24980
+ const sub = withPadding(await opt.subset(bytes, cps, glyphs ? { glyphs: glyphs.keys() } : void 0));
24981
+ const f4 = fontkit2.create(sub);
24982
+ for (const cp of cps) void f4.glyphForCodePoint(cp).advanceWidth;
24983
+ for (const id of glyphs?.keys() || []) void f4.getGlyph(id).advanceWidth;
24984
+ bytes = sub;
24985
+ } catch {
24986
+ }
24987
+ }
24988
+ const pf = await doc.embedFont(bytes, { subset: false, customName: bytes === full ? void 0 : `${subsetTag(bytes)}+${fontStore2.get(key).postscriptName || "Font"}` });
24989
+ plainEncoding(pf);
24990
+ if (glyphs) addGlyphs(pf, glyphs, !!opt.tagged);
24991
+ const file = bytes, e2 = (
24992
+ /** @type {any} */
24993
+ pf.embedder
24994
+ );
24995
+ if (!e2.isCFF()) e2.embedFontStream = async (c) => c.register(PDFRawStream2.of(c.obj({ Filter: "FlateDecode", Length1: file.length }), await deflate(file)));
24996
+ fonts.set(key, pf);
24997
+ }
24998
+ return fonts.get(key);
24999
+ };
25000
+ const images = /* @__PURE__ */ new Map();
25001
+ const image2 = async (src) => {
25002
+ if (images.has(src)) return images.get(src);
25003
+ const out = await loadImage(src).catch((e2) => ({ img: null, why: `it could not be embedded (${e2?.message || e2})` }));
25004
+ images.set(src, out);
25005
+ return out;
25006
+ };
25007
+ async function loadImage(src) {
25008
+ const local = /^data:/i.test(src);
25009
+ if (local && dataUriBytes(src) > IMAGE_LIMITS.bytes) return { img: null, why: "it is larger than the image size limit" };
25010
+ if (!local && !opt.fetchImage) return { img: null, why: "it is a URL, and no fetchImage was given to load it" };
25011
+ const bytes = local ? dataUriBytesOf(src) : await opt.fetchImage(src);
25012
+ if (!bytes?.length) return { img: null, why: "it could not be loaded" };
25013
+ if (bytes.length > IMAGE_LIMITS.bytes) return { img: null, why: "it is larger than the image size limit" };
25014
+ const info = imageInfoOf(bytes);
25015
+ if (info?.type === "svg") {
25016
+ const svg = parseSvg(new TextDecoder().decode(bytes));
25017
+ return svg ? { img: { svg, width: svg.w, height: svg.h } } : { img: null, why: "the SVG could not be read" };
25018
+ }
25019
+ if (info?.type === "png") {
25020
+ const why = "w" in info && !/** @type {any} */
25021
+ info.suspect && info.w * info.h <= IMAGE_LIMITS.pixels ? pngProblem(bytes) : "too large or animated";
25022
+ return why ? { img: null, why: `the PNG is not usable (${why})` } : { img: await doc.embedPng(bytes) };
25023
+ }
25024
+ if (info?.type === "jpeg") return { img: await doc.embedJpg(bytes) };
25025
+ return { img: null, why: info ? `${info.type.toUpperCase()} is not embedded (PNG, JPEG and SVG are)` : "it is not a PNG, JPEG or SVG" };
25026
+ }
25027
+ const ctx = doc.context;
25028
+ const res = ctx.obj({ Font: {}, ExtGState: {}, XObject: {} });
25029
+ const resRef = ctx.register(res);
25030
+ const names = /* @__PURE__ */ new Map();
25031
+ const nameOf = (kind, key, value) => {
25032
+ let n5 = names.get(key);
25033
+ if (!n5) {
25034
+ n5 = `${kind[0]}${names.size + 1}`;
25035
+ names.set(key, n5);
25036
+ res.get(PDFName3.of(kind)).set(PDFName3.of(n5), value());
25037
+ }
25038
+ return n5;
25039
+ };
25040
+ const shared = {
25041
+ font: (pf) => nameOf("Font", pf, () => pf.ref),
25042
+ gs: (ca, CA) => nameOf("ExtGState", `gs ${ca} ${CA}`, () => ctx.obj({ Type: "ExtGState", ca, CA })),
25043
+ image: (img) => nameOf("XObject", img, () => img.ref)
25044
+ };
25045
+ const links = [];
25046
+ const taken = /* @__PURE__ */ new Set();
25047
+ const uniqueName = (n5) => {
25048
+ let name = n5, i = 1;
25049
+ while (taken.has(name)) name = `${n5}_${++i}`;
25050
+ taken.add(name);
25051
+ return name;
25052
+ };
25053
+ const contents = [];
25054
+ if (opt.tagged) needsTableData(model, "An accessible PDF");
24711
25055
  const tags = opt.tagged ? createTagger(model, doc) : null;
24712
25056
  let pi = -1;
24713
25057
  const vm = /* @__PURE__ */ new Map();
@@ -24831,7 +25175,7 @@ async function pdfOf(model, fontStore2, opt) {
24831
25175
  const form = doc.getForm();
24832
25176
  const f4 = await font(fieldFont(it));
24833
25177
  const name = uniqueName(it.name);
24834
- const box = { x: it.x, y: H - it.y - it.h, width: it.w, height: it.h, borderColor: rgb2(0.61, 0.64, 0.69), borderWidth: 0.75, backgroundColor: rgb2(1, 1, 1) };
25178
+ 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) };
24835
25179
  let field;
24836
25180
  if (it.kind === "checkbox") {
24837
25181
  field = form.createCheckBox(name);
@@ -24888,7 +25232,7 @@ async function pdfOf(model, fontStore2, opt) {
24888
25232
  if (it.required) field.enableRequired();
24889
25233
  if (it.readOnly) field.enableReadOnly();
24890
25234
  if (tags) {
24891
- field.acroField.dict.set(PDFName3.of("TU"), PDFHexString4.fromText(it.label || it.name || name));
25235
+ field.acroField.dict.set(PDFName3.of("TU"), PDFHexString5.fromText(it.label || it.name || name));
24892
25236
  const w = field.acroField.getWidgets()[0];
24893
25237
  const ref3 = w && doc.context.getObjectRef(w.dict);
24894
25238
  if (ref3) tags.annot(pi, ii, ref3, "field");
@@ -24962,7 +25306,7 @@ async function pdfOf(model, fontStore2, opt) {
24962
25306
  const to = l.href ? { A: { Type: "Action", S: "URI", URI: pdfLiteral(asciiUrl(l.href)) } } : { Dest: dest(l.to) };
24963
25307
  if (!l.href && !to.Dest) continue;
24964
25308
  const annot = doc.context.obj({ Type: "Annot", Subtype: "Link", F: 4, Rect: l.rect, Border: [0, 0, 0], ...to });
24965
- if (tags) annot.set(PDFName3.of("Contents"), PDFHexString4.fromText(String(l.text || l.tip || l.href || "Link")));
25309
+ if (tags) annot.set(PDFName3.of("Contents"), PDFHexString5.fromText(String(l.text || l.tip || l.href || "Link")));
24966
25310
  const ref2 = doc.context.register(annot);
24967
25311
  if (tags) tags.annot(l.pi, l.ii, ref2, "link");
24968
25312
  const annots = l.page.node.lookup(PDFName3.of("Annots"));
@@ -24989,122 +25333,26 @@ function coveredText(items, box) {
24989
25333
  for (const t of items) if (t.t === "text" && t.lines) {
24990
25334
  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);
24991
25335
  }
24992
- return lines.sort((a, b) => a.y - b.y || a.x - b.x).map((l) => l.text.trim()).join(" ");
24993
- }
24994
- function fixedDate(opt) {
24995
- if (opt.creationDate !== void 0) {
24996
- if (!(opt.creationDate instanceof Date) || Number.isNaN(opt.creationDate.getTime())) throw Object.assign(new Error("creationDate must be a valid Date"), { status: 400 });
24997
- return opt.creationDate;
24998
- }
24999
- const epoch = globalThis.process?.env?.SOURCE_DATE_EPOCH;
25000
- return epoch && /^\d+$/.test(epoch) ? new Date(Number(epoch) * 1e3) : null;
25001
- }
25002
- async function contentId(model, opt, when) {
25003
- const bytes = new TextEncoder().encode(JSON.stringify([{ ...model, stats: void 0 }, opt.title || "Report", opt.author || "", when.toISOString()]));
25004
- const digest = new Uint8Array(await globalThis.crypto.subtle.digest("SHA-256", bytes));
25005
- return Array.from(digest.subarray(0, 16), (b) => b.toString(16).padStart(2, "0")).join("").toUpperCase();
25006
- }
25007
- function fieldFont(it) {
25008
- for (const d of it.draw) if (d.t === "text") {
25009
- for (const l of d.lines) for (const r of l.runs || []) if (r.font !== it.font && r.text.trim()) return r.font;
25010
- }
25011
- return it.font;
25012
- }
25013
- function drawRun(c, run, x, y, size, pf, color2, spans2, texts) {
25014
- const f4 = pf.embedder.font;
25015
- const per = 1e3 / size;
25016
- const span = (text2) => `/Span <</ActualText ${PDFHexString4.fromText(text2).toString()}>> BDC
25017
- `;
25018
- c.et();
25019
- c.paint(color2, null);
25020
- c.font(pf, size);
25021
- if (!run.rtl) c.s += span(run.text);
25022
- c.s += `BT ${n2(x)} ${n2(y)} Td
25023
- `;
25024
- let arr = "";
25025
- let pen = 0, rise = 0;
25026
- const flush = () => {
25027
- if (arr) c.s += `[${arr}] TJ
25028
- `;
25029
- arr = "";
25030
- };
25031
- const all = run.glyphs;
25032
- const adv = (id) => f4.getGlyph(id).advanceWidth;
25033
- let g = all, quietAt = -1;
25034
- if (run.rtl) {
25035
- const hasBase = /* @__PURE__ */ new Set();
25036
- for (let i = 0; i < all.length; i += 4) if (adv(all[i]) > 0) hasBase.add(all[i + 3]);
25037
- const quiet = (i) => spans2?.has(all[i + 3]) ? adv(all[i]) === 0 && hasBase.has(all[i + 3]) : texts?.get(all[i]) === "";
25038
- g = [];
25039
- for (const late of [false, true]) {
25040
- if (late) quietAt = g.length;
25041
- 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]);
25042
- }
25043
- if (quietAt === g.length) quietAt = -1;
25044
- }
25045
- const starts = run.rtl ? [...new Set(all.filter((_, i) => i % 4 === 3))].sort((a, b) => a - b) : [];
25046
- let inSpan = false;
25047
- for (let i = 0; i < g.length; i += 4) {
25048
- const id = g[i], gx = g[i + 1], gy = g[i + 2], cl = g[i + 3];
25049
- if (i === quietAt) {
25050
- flush();
25051
- c.s += span("");
25052
- inSpan = true;
25053
- } else if (run.rtl && spans2?.has(cl) && (quietAt < 0 || i < quietAt) && (i === 0 || g[i - 1] !== cl)) {
25054
- flush();
25055
- c.s += span(run.text.slice(cl, starts[starts.indexOf(cl) + 1] ?? run.text.length));
25056
- inSpan = true;
25057
- }
25058
- if (gy !== rise) {
25059
- flush();
25060
- c.s += `${n4(gy)} Ts
25061
- `;
25062
- rise = gy;
25063
- }
25064
- const adj = Math.round((pen - gx) * per * 1e3) / 1e3;
25065
- if (id === 0 && c.tagged) pen = gx;
25066
- else {
25067
- arr += (adj ? `${adj}` : "") + `<${hex4(id)}>`;
25068
- pen = gx + adv(id) * size / f4.unitsPerEm;
25069
- }
25070
- if (inSpan && (i + 4 >= g.length || (quietAt < 0 || i + 4 < quietAt) && g[i + 7] !== cl || i + 4 === quietAt)) {
25071
- flush();
25072
- c.s += "EMC\n";
25073
- inSpan = false;
25074
- }
25336
+ return lines.sort((a, b) => a.y - b.y || a.x - b.x).map((l) => l.text.trim()).join(" ");
25337
+ }
25338
+ function fixedDate(opt) {
25339
+ if (opt.creationDate !== void 0) {
25340
+ if (!(opt.creationDate instanceof Date) || Number.isNaN(opt.creationDate.getTime())) throw Object.assign(new Error("creationDate must be a valid Date"), { status: 400 });
25341
+ return opt.creationDate;
25075
25342
  }
25076
- flush();
25077
- if (rise) c.s += "0 Ts\n";
25078
- c.s += "ET\n";
25079
- if (!run.rtl) c.s += "EMC\n";
25343
+ const epoch = globalThis.process?.env?.SOURCE_DATE_EPOCH;
25344
+ return epoch && /^\d+$/.test(epoch) ? new Date(Number(epoch) * 1e3) : null;
25080
25345
  }
25081
- function glyphText(run, font, out, spans2) {
25082
- const g = run.glyphs;
25083
- const starts = [...new Set(g.filter((_, i) => i % 4 === 3))].sort((a, b) => a - b);
25084
- for (let k = 0; k < starts.length; k++) {
25085
- const chars = [...run.text.slice(starts[k], starts[k + 1] ?? run.text.length)];
25086
- const ids = [];
25087
- for (let i = 0; i < g.length; i += 4) if (g[i + 3] === starts[k]) ids.push(g[i]);
25088
- const own = new Map(chars.map((ch) => [font.glyphForCodePoint(ch.codePointAt(0)).id, ch]));
25089
- const rest2 = chars.filter((ch) => !ids.includes(font.glyphForCodePoint(ch.codePointAt(0)).id)).join("");
25090
- const carrier = rest2 ? ids.find((id) => !own.has(id) && font.getGlyph(id).advanceWidth > 0) ?? ids.find((id) => !own.has(id)) : void 0;
25091
- let ok = !rest2 || carrier !== void 0;
25092
- const want = /* @__PURE__ */ new Map();
25093
- for (const id of ids) {
25094
- const t = own.get(id) ?? (id === carrier ? rest2 : "");
25095
- if (want.has(id) && want.get(id) !== t) ok = false;
25096
- want.set(id, t);
25097
- }
25098
- for (const [id, t] of want) {
25099
- if (!out.has(id)) out.set(id, t);
25100
- else if (out.get(id) !== t) ok = false;
25101
- }
25102
- if (!ok && run.rtl && spans2) {
25103
- let s = spans2.get(run);
25104
- if (!s) spans2.set(run, s = /* @__PURE__ */ new Set());
25105
- s.add(starts[k]);
25106
- }
25346
+ async function contentId(model, opt, when) {
25347
+ const bytes = new TextEncoder().encode(JSON.stringify([{ ...model, stats: void 0 }, opt.title || "Report", opt.author || "", when.toISOString()]));
25348
+ const digest = new Uint8Array(await globalThis.crypto.subtle.digest("SHA-256", bytes));
25349
+ return Array.from(digest.subarray(0, 16), (b) => b.toString(16).padStart(2, "0")).join("").toUpperCase();
25350
+ }
25351
+ function fieldFont(it) {
25352
+ for (const d of it.draw) if (d.t === "text") {
25353
+ for (const l of d.lines) for (const r of l.runs || []) if (r.font !== it.font && r.text.trim()) return r.font;
25107
25354
  }
25355
+ return it.font;
25108
25356
  }
25109
25357
  var pdfLiteral = (s) => PDFString4.of(String(s).replace(/[\\()]/g, "\\$&"));
25110
25358
  function plainEncoding(pf) {
@@ -25122,7 +25370,7 @@ function plainEncoding(pf) {
25122
25370
  }
25123
25371
  return hex6;
25124
25372
  };
25125
- e2.encodeText = (text2) => PDFHexString4.of(e2.hexOf(text2));
25373
+ e2.encodeText = (text2) => PDFHexString5.of(e2.hexOf(text2));
25126
25374
  e2.widthOfTextAtSize = (text2, size) => {
25127
25375
  let w = 0;
25128
25376
  for (const ch of text2) w += f4.glyphForCodePoint(
@@ -25213,7 +25461,7 @@ function addOutline(doc, bookmarks, dest) {
25213
25461
  if (!Dest) continue;
25214
25462
  const level = Math.max(0, Math.min(9, Number(b.level) || 0));
25215
25463
  while (stack2[stack2.length - 1].level >= level) stack2.pop();
25216
- const node2 = { ref: ctx.nextRef(), level, kids: [], Title: PDFHexString4.fromText(b.label), Dest };
25464
+ const node2 = { ref: ctx.nextRef(), level, kids: [], Title: PDFHexString5.fromText(b.label), Dest };
25217
25465
  stack2[stack2.length - 1].kids.push(node2);
25218
25466
  stack2.push(node2);
25219
25467
  }
@@ -25244,216 +25492,6 @@ function subsetTag(bytes) {
25244
25492
  }
25245
25493
  return tag4;
25246
25494
  }
25247
- function insideClip(it, m) {
25248
- const k = it.clip, asc = m.asc * it.size, desc = m.desc * it.size;
25249
- 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);
25250
- }
25251
- var Content = class {
25252
- constructor(shared) {
25253
- this.shared = shared;
25254
- this._s = "";
25255
- this.bt = false;
25256
- this.tx = 0;
25257
- this.ty = 0;
25258
- this.st = { fill: "0 0 0", stroke: "0 0 0", lw: 1, dash: "[] 0", ca: 1, CA: 1, font: "", size: 0 };
25259
- this.saved = [];
25260
- this.lines = null;
25261
- this.tagged = false;
25262
- }
25263
- /**
25264
- * The operators so far. Any other drawing reads or appends to it, so the lines waiting are drawn first: the text
25265
- * of a table's cells stays in one text object (relative moves, which compress to little) instead of one per cell.
25266
- */
25267
- get s() {
25268
- this.flushLines();
25269
- return this._s;
25270
- }
25271
- set s(v) {
25272
- this._s = v;
25273
- }
25274
- /**
25275
- * A straight line. Untagged, it waits until something other than text is drawn (table borders between cell
25276
- * texts); collinear segments that touch, in the same stroke, become one (a row's border is one line).
25277
- * ponytail: lines move after the text drawn just after them; both are thin and do not cover each other.
25278
- */
25279
- line(stroke, w, dash, x1, y1, x2, y2) {
25280
- if (this.tagged) {
25281
- this.paint(null, stroke, w, dash);
25282
- this._s += `${n2(x1)} ${n2(y1)} m ${n2(x2)} ${n2(y2)} l S
25283
- `;
25284
- return;
25285
- }
25286
- const key = `${stroke.rgb}|${stroke.opacity}|${w}|${(dash || []).join(" ")}`;
25287
- if (this.lines && this.lines.key !== key) this.flushLines();
25288
- this.lines ||= { key, stroke, w, dash, segs: [] };
25289
- const segs = this.lines.segs, last = segs[segs.length - 1];
25290
- const eq = (a, b) => Math.abs(a - b) < 5e-3;
25291
- if (last && eq(last[1], y1) && eq(last[3], y2) && eq(y1, y2) && eq(last[2], x1)) last[2] = x2;
25292
- else if (last && eq(last[0], x1) && eq(last[2], x2) && eq(x1, x2) && eq(last[3], y1)) last[3] = y2;
25293
- else segs.push([x1, y1, x2, y2]);
25294
- }
25295
- flushLines() {
25296
- const L = this.lines;
25297
- if (!L) return;
25298
- this.lines = null;
25299
- this.et();
25300
- this.paint(null, L.stroke, L.w, L.dash);
25301
- const g = L.segs;
25302
- const dy = g.length > 2 ? Math.round((g[1][1] - g[0][1]) * 100) : 0;
25303
- if (dy && g.every((q3, i) => q3[1] === q3[3] && n2(q3[0]) === n2(g[0][0]) && n2(q3[2]) === n2(g[0][2]) && Math.abs(q3[1] - (g[0][1] + i * dy / 100)) < 0.01)) {
25304
- const one = `${n2(g[0][0])} ${n2(g[0][1])} m ${n2(g[0][2])} ${n2(g[0][1])} l S
25305
- `;
25306
- this._s += `q
25307
- ${one}${`1 0 0 1 0 ${dy / 100} cm ${one}`.repeat(g.length - 1)}Q
25308
- `;
25309
- return;
25310
- }
25311
- this._s += g.map(([a, b, c, d]) => `${n2(a)} ${n2(b)} m ${n2(c)} ${n2(d)} l`).join(" ") + " S\n";
25312
- }
25313
- q() {
25314
- this.et();
25315
- this._s += "q\n";
25316
- this.saved.push({ ...this.st });
25317
- }
25318
- Q() {
25319
- this.et();
25320
- this._s += "Q\n";
25321
- this.st = this.saved.pop();
25322
- }
25323
- /**
25324
- * A line of plain text at (x, y). Lines follow one another in one text object, each placed relative to the
25325
- * last (in whole hundredths, so nothing drifts): most of a table page is these.
25326
- * @param {string} str the glyphs, as a literal string's escaped body (array: a TJ array's body)
25327
- */
25328
- text(pf, size, color2, x, y, str, array = false) {
25329
- this.setPaint(color2, null);
25330
- this.setFont(pf, size);
25331
- const X = Math.round(x * 10) * 10, Y = Math.round(y * 10) * 10;
25332
- if (!this.bt) {
25333
- this._s += "BT\n";
25334
- this.bt = true;
25335
- this.tx = 0;
25336
- this.ty = 0;
25337
- }
25338
- this._s += array ? `${(X - this.tx) / 100} ${(Y - this.ty) / 100} Td [${str}] TJ
25339
- ` : `${(X - this.tx) / 100} ${(Y - this.ty) / 100} Td (${str}) Tj
25340
- `;
25341
- this.tx = X;
25342
- this.ty = Y;
25343
- }
25344
- /** end the open text object, if any: anything but text needs that (and draws the lines waiting) */
25345
- et() {
25346
- if (this.bt) {
25347
- this._s += "ET\n";
25348
- this.bt = false;
25349
- }
25350
- if (this.lines) this.flushLines();
25351
- }
25352
- lineWidth(w) {
25353
- if (this.lines) this.flushLines();
25354
- this.setLineWidth(w);
25355
- }
25356
- setLineWidth(w) {
25357
- if (this.st.lw !== w) {
25358
- this._s += `${n3(w)} w
25359
- `;
25360
- this.st.lw = w;
25361
- }
25362
- }
25363
- /** the graphics state that sets these opacities, or undefined when they are set already */
25364
- gsFor(ca, CA) {
25365
- return ca === this.st.ca && CA === this.st.CA ? void 0 : this.shared.gs(ca, CA);
25366
- }
25367
- alpha(ca, CA) {
25368
- if (this.lines) this.flushLines();
25369
- this.setAlpha(ca, CA);
25370
- }
25371
- setAlpha(ca, CA) {
25372
- const g = this.gsFor(ca, CA);
25373
- if (g) {
25374
- this._s += `/${g} gs
25375
- `;
25376
- this.st.ca = ca;
25377
- this.st.CA = CA;
25378
- }
25379
- }
25380
- /** set up to fill with fill and/or stroke with stroke (width w, dash); the lines waiting are drawn first */
25381
- paint(fill3, stroke, w = 1, dash = null) {
25382
- if (this.lines) this.flushLines();
25383
- this.setPaint(fill3, stroke, w, dash);
25384
- }
25385
- setPaint(fill3, stroke, w = 1, dash = null) {
25386
- const st = this.st;
25387
- if (fill3 && fill3.rgb !== st.fill) {
25388
- this._s += `${fill3.rgb} rg
25389
- `;
25390
- st.fill = fill3.rgb;
25391
- }
25392
- if (stroke) {
25393
- if (stroke.rgb !== st.stroke) {
25394
- this._s += `${stroke.rgb} RG
25395
- `;
25396
- st.stroke = stroke.rgb;
25397
- }
25398
- this.setLineWidth(w);
25399
- const d = `[${(dash || []).map(n3).join(" ")}] 0`;
25400
- if (d !== st.dash) {
25401
- this._s += `${d} d
25402
- `;
25403
- st.dash = d;
25404
- }
25405
- }
25406
- this.setAlpha(fill3 ? fill3.opacity : st.ca, stroke ? stroke.opacity : st.CA);
25407
- }
25408
- font(pf, size) {
25409
- if (this.lines) this.flushLines();
25410
- this.setFont(pf, size);
25411
- }
25412
- setFont(pf, size) {
25413
- const name = this.shared.font(pf);
25414
- if (name !== this.st.font || size !== this.st.size) {
25415
- this._s += `/${name} ${n3(size)} Tf
25416
- `;
25417
- this.st.font = name;
25418
- this.st.size = size;
25419
- }
25420
- }
25421
- };
25422
- function latin1(s) {
25423
- const B = (
25424
- /** @type {any} */
25425
- globalThis.Buffer
25426
- );
25427
- if (B) return B.from(s, "latin1");
25428
- const out = new Uint8Array(s.length);
25429
- for (let i = 0; i < s.length; i++) out[i] = s.charCodeAt(i);
25430
- return out;
25431
- }
25432
- async function deflate(bytes) {
25433
- if (zslots.free > 0) zslots.free--;
25434
- else await new Promise((ok) => zslots.wait.push(ok));
25435
- try {
25436
- return await deflateNow(bytes);
25437
- } finally {
25438
- const next = zslots.wait.shift();
25439
- if (next) next();
25440
- else zslots.free++;
25441
- }
25442
- }
25443
- var zslots = { free: 4, wait: (
25444
- /** @type {(() => void)[]} */
25445
- []
25446
- ) };
25447
- var NODE_ZLIB = (
25448
- /** @type {any} */
25449
- globalThis.process?.getBuiltinModule?.("node:zlib")
25450
- );
25451
- async function deflateNow(bytes) {
25452
- const zlib = NODE_ZLIB;
25453
- if (zlib) return new Promise((ok, fail2) => zlib.deflate(bytes, { level: 9 }, (e2, z) => e2 ? fail2(e2) : ok(z)));
25454
- if (typeof CompressionStream === "undefined") return (await import("fflate")).zlibSync(bytes);
25455
- return new Uint8Array(await new Response(new Blob([bytes]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
25456
- }
25457
25495
  function roundRect(x, y, w, h, r) {
25458
25496
  r = Math.min(r, w / 2, h / 2);
25459
25497
  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`;