@poe-platform/safe-bash 0.1.756 → 0.1.758

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 (161) hide show
  1. package/dist/image-ast/index.browser.js +76 -23
  2. package/dist/image-ast/index.js +76 -23
  3. package/dist/pdf-ast/ast.d.ts +3 -0
  4. package/dist/pdf-ast/index.js +88 -36
  5. package/dist/safe-bash/chunks/{chunk-LESPJ3OG.js → chunk-WNWIBBJZ.js} +15 -2
  6. package/dist/safe-bash/command-chunks/{chunk-S4J6MSLY.js → chunk-444OTXM7.js} +3 -3
  7. package/dist/safe-bash/command-chunks/{chunk-F3J5ZLKF.js → chunk-522TDVLS.js} +1 -1
  8. package/dist/safe-bash/command-chunks/{chunk-VFS2MDAB.js → chunk-6YLD37NH.js} +2 -2
  9. package/dist/safe-bash/command-chunks/{chunk-YI3GKJ7Q.js → chunk-766IWMTB.js} +2 -2
  10. package/dist/safe-bash/command-chunks/{chunk-6AIOGLZO.js → chunk-CE6Z2ULX.js} +2 -2
  11. package/dist/safe-bash/command-chunks/{chunk-KSH2F6RG.js → chunk-CUFCNL6G.js} +1 -1
  12. package/dist/safe-bash/command-chunks/{chunk-5VSGEE6J.js → chunk-F4IQCXZG.js} +5 -5
  13. package/dist/safe-bash/command-chunks/{chunk-F5MORDSU.js → chunk-FDNCPZQS.js} +32 -1
  14. package/dist/safe-bash/command-chunks/{chunk-SG3ZDZCX.js → chunk-FLMLM7Y4.js} +2 -2
  15. package/dist/safe-bash/command-chunks/{chunk-DVZCHNB5.js → chunk-J2NPH7DO.js} +11 -7
  16. package/dist/safe-bash/command-chunks/{chunk-CT3FB722.js → chunk-J7UMKBRK.js} +1 -1
  17. package/dist/safe-bash/command-chunks/{chunk-QQOAK7JQ.js → chunk-KKJCKPTA.js} +1 -1
  18. package/dist/safe-bash/command-chunks/{chunk-7KS6PX4U.js → chunk-KSIGF4AG.js} +3 -3
  19. package/dist/safe-bash/command-chunks/{chunk-KBBI4CSU.js → chunk-L2C5TIII.js} +2 -2
  20. package/dist/safe-bash/command-chunks/{chunk-4HQ7WYSI.js → chunk-MED2BOOW.js} +30 -5
  21. package/dist/safe-bash/command-chunks/{chunk-JRNLDPLI.js → chunk-OZSWW23M.js} +1 -1
  22. package/dist/safe-bash/command-chunks/{chunk-DKQ5REXF.js → chunk-QDPRSPHQ.js} +1 -1
  23. package/dist/safe-bash/command-chunks/{chunk-WOPU2VWF.js → chunk-RID3B5RE.js} +1 -1
  24. package/dist/safe-bash/command-chunks/{chunk-H2FQA4OU.js → chunk-TCAGGM44.js} +72 -19
  25. package/dist/safe-bash/command-chunks/{chunk-REYTQLLB.js → chunk-TT2DMDBY.js} +1 -1
  26. package/dist/safe-bash/command-chunks/{chunk-UGX6MXDD.js → chunk-UIIT4ULR.js} +3 -3
  27. package/dist/safe-bash/command-chunks/{chunk-A6NFLWZI.js → chunk-WKPOGTZY.js} +22 -6
  28. package/dist/safe-bash/command-chunks/{chunk-WI35236J.js → chunk-XYCWDGOG.js} +1 -1
  29. package/dist/safe-bash/command-chunks/{chunk-3DOHQQJR.js → chunk-Y64PA6IA.js} +8 -8
  30. package/dist/safe-bash/command-chunks/{chunk-4F6PG2OT.js → chunk-YJWWRCIG.js} +8 -8
  31. package/dist/safe-bash/command-chunks/{chunk-6Z7OS3TZ.js → chunk-ZP5KDHB4.js} +7 -7
  32. package/dist/safe-bash/commands/pandoc/index.d.ts +1 -1
  33. package/dist/safe-bash/commands/pandoc/index.js +5 -3
  34. package/dist/safe-bash/commands/python/index.browser.js +1 -1
  35. package/dist/safe-bash/commands/python/index.js +6 -0
  36. package/dist/safe-bash/commands/python/jspi.js +11 -2
  37. package/dist/safe-bash/core.browser.js +6 -4
  38. package/dist/safe-bash-command-column/column.js +3 -3
  39. package/dist/safe-bash-command-column/index.js +3 -3
  40. package/dist/safe-bash-command-column/layout.js +2 -2
  41. package/dist/safe-bash-command-csvkit/index.js +8 -8
  42. package/dist/safe-bash-command-factor/command.js +2 -2
  43. package/dist/safe-bash-command-factor/index.js +2 -2
  44. package/dist/safe-bash-command-ffmpeg/index.js +5923 -5893
  45. package/dist/safe-bash-command-imagemagick/index.js +2 -2
  46. package/dist/safe-bash-command-pandoc/command.js +3 -3
  47. package/dist/safe-bash-command-pandoc/index.js +3 -3
  48. package/dist/safe-bash-command-pdfimages/index.js +72 -19
  49. package/dist/safe-bash-command-pdfinfo/index.js +88 -36
  50. package/dist/safe-bash-command-pdftk/index.js +72 -19
  51. package/dist/safe-bash-command-pdftoppm/index.js +88 -36
  52. package/dist/safe-bash-command-pdftotext/index.js +72 -19
  53. package/dist/safe-bash-command-qpdf/index.js +72 -19
  54. package/dist/safe-bash-command-sips/index.js +2 -2
  55. package/dist/safe-bash-command-soffice/index.js +17 -17
  56. package/dist/safe-bash-command-ssconvert/command-bindings.d.ts +18 -0
  57. package/dist/safe-bash-command-ssconvert/command.d.ts +5 -14
  58. package/dist/safe-bash-command-ssconvert/commands.d.ts +6 -0
  59. package/dist/safe-bash-command-ssconvert/commands.js +871 -0
  60. package/dist/safe-bash-command-ssconvert/core.js +8 -8
  61. package/dist/safe-bash-command-ssconvert/formats/csv.js +9 -9
  62. package/dist/safe-bash-command-ssconvert/formats/ods.js +8 -8
  63. package/dist/safe-bash-command-ssconvert/formats/spreadsheetml.js +1 -1
  64. package/dist/safe-bash-command-ssconvert/formats/xls.js +9 -8
  65. package/dist/safe-bash-command-ssconvert/formats/xlsx.js +8 -8
  66. package/dist/safe-bash-command-ssconvert/index.js +376 -236
  67. package/dist/safe-bash-command-wkhtmltopdf/index.js +72 -19
  68. package/dist/safe-bash-command-yq/index.js +4 -4
  69. package/dist/safe-bash-compression-engine/files.js +2 -2
  70. package/dist/safe-bash-compression-engine/operand.js +4 -4
  71. package/dist/safe-bash-contracts/filesystem-descriptor.js +1 -1
  72. package/dist/safe-bash-contracts/filesystem-output.js +1 -1
  73. package/dist/safe-bash-markdown-engine/commonmark-blocks.js +4 -4
  74. package/dist/safe-bash-markdown-engine/commonmark-inlines.js +4 -4
  75. package/dist/safe-bash-markdown-engine/commonmark-syntax.js +2 -2
  76. package/dist/safe-bash-markdown-engine/gfm-syntax.js +3 -3
  77. package/dist/safe-bash-markdown-engine/index.js +7 -7
  78. package/dist/safe-bash-mcp/index.js +4 -4
  79. package/dist/safe-bash-query-engine/index.js +5 -5
  80. package/dist/safe-bash-query-engine/interpreter.js +4 -4
  81. package/dist/safe-bash-query-engine/query-core.js +5 -5
  82. package/dist/spreadsheet-engine/formulas/ast.d.ts +13 -0
  83. package/dist/spreadsheet-engine/formulas/conventions.js +1 -1
  84. package/dist/spreadsheet-engine/formulas/dependencies.js +2 -2
  85. package/dist/spreadsheet-engine/formulas/evaluator.js +2 -2
  86. package/dist/spreadsheet-engine/formulas/named-expressions.d.ts +2 -2
  87. package/dist/spreadsheet-engine/formulas/named-expressions.js +31 -5
  88. package/dist/spreadsheet-engine/formulas/parser.js +34 -0
  89. package/dist/spreadsheet-engine/formulas/rewriting.js +19 -1
  90. package/dist/spreadsheet-engine/formulas/serialization.js +6 -0
  91. package/dist/spreadsheet-format-xls/biff-write-formulas.js +2 -0
  92. package/dist/xlsx-ast/formula-semantics.js +2 -0
  93. package/package.json +6 -2
  94. package/third-party/pdf-ast/THIRD_PARTY_NOTICES.md +16 -0
  95. package/dist/safe-bash/chunks/browser-ECQX6GMK.js +0 -6766
  96. package/dist/safe-bash/chunks/bz2-4OP3OWW3.js +0 -8
  97. package/dist/safe-bash/chunks/chunk-22XPAAOI.js +0 -173
  98. package/dist/safe-bash/chunks/chunk-44WUNUPV.js +0 -649
  99. package/dist/safe-bash/chunks/chunk-4E3SGG37.js +0 -876
  100. package/dist/safe-bash/chunks/chunk-4QTSSQKP.js +0 -898
  101. package/dist/safe-bash/chunks/chunk-5UVGPVXP.js +0 -410
  102. package/dist/safe-bash/chunks/chunk-64OE6Q6X.js +0 -3487
  103. package/dist/safe-bash/chunks/chunk-6IIFUPN2.js +0 -1526
  104. package/dist/safe-bash/chunks/chunk-BENDLTQD.js +0 -7065
  105. package/dist/safe-bash/chunks/chunk-BMO5LWEX.js +0 -534
  106. package/dist/safe-bash/chunks/chunk-BPMCPTNP.js +0 -1920
  107. package/dist/safe-bash/chunks/chunk-BRJTAWP5.js +0 -2955
  108. package/dist/safe-bash/chunks/chunk-C3GEIN7Q.js +0 -20054
  109. package/dist/safe-bash/chunks/chunk-CBVANNKK.js +0 -174814
  110. package/dist/safe-bash/chunks/chunk-CEWCRI6H.js +0 -2813
  111. package/dist/safe-bash/chunks/chunk-CGL53DQQ.js +0 -37
  112. package/dist/safe-bash/chunks/chunk-CTYJJD4O.js +0 -869
  113. package/dist/safe-bash/chunks/chunk-CWSS4MQA.js +0 -7
  114. package/dist/safe-bash/chunks/chunk-DLIGMTCP.js +0 -3266
  115. package/dist/safe-bash/chunks/chunk-EMAJ7WUW.js +0 -1031
  116. package/dist/safe-bash/chunks/chunk-FDKIZ2IJ.js +0 -1950
  117. package/dist/safe-bash/chunks/chunk-FZWJ2A7V.js +0 -3093
  118. package/dist/safe-bash/chunks/chunk-G2VCIF2J.js +0 -22
  119. package/dist/safe-bash/chunks/chunk-GVKBUQDX.js +0 -2649
  120. package/dist/safe-bash/chunks/chunk-IO2OGW3E.js +0 -28051
  121. package/dist/safe-bash/chunks/chunk-ISCZG7WA.js +0 -2648
  122. package/dist/safe-bash/chunks/chunk-JCN3FXLP.js +0 -38983
  123. package/dist/safe-bash/chunks/chunk-KJHDD4A2.js +0 -759
  124. package/dist/safe-bash/chunks/chunk-LB6HVRXS.js +0 -857
  125. package/dist/safe-bash/chunks/chunk-LLWAJOZH.js +0 -15
  126. package/dist/safe-bash/chunks/chunk-LMUKYZIJ.js +0 -708
  127. package/dist/safe-bash/chunks/chunk-M5SCNKIK.js +0 -2012
  128. package/dist/safe-bash/chunks/chunk-MJPFHANT.js +0 -3350
  129. package/dist/safe-bash/chunks/chunk-MZQW2DOL.js +0 -82
  130. package/dist/safe-bash/chunks/chunk-NB2V7EOY.js +0 -1348
  131. package/dist/safe-bash/chunks/chunk-NJVGOIYN.js +0 -17
  132. package/dist/safe-bash/chunks/chunk-OLNZHDIQ.js +0 -5141
  133. package/dist/safe-bash/chunks/chunk-OSUXMC43.js +0 -2317
  134. package/dist/safe-bash/chunks/chunk-OUUVROTM.js +0 -38
  135. package/dist/safe-bash/chunks/chunk-PA6GYKBQ.js +0 -151
  136. package/dist/safe-bash/chunks/chunk-PEFHZ226.js +0 -6957
  137. package/dist/safe-bash/chunks/chunk-QBB5P5KW.js +0 -4839
  138. package/dist/safe-bash/chunks/chunk-RSAWYAEH.js +0 -973
  139. package/dist/safe-bash/chunks/chunk-UWLYRWT4.js +0 -739
  140. package/dist/safe-bash/chunks/chunk-V463NBQH.js +0 -13
  141. package/dist/safe-bash/chunks/chunk-WPUALYUS.js +0 -843
  142. package/dist/safe-bash/chunks/chunk-XHKFSRGU.js +0 -5747
  143. package/dist/safe-bash/chunks/chunk-XHRCLZ3N.js +0 -13391
  144. package/dist/safe-bash/chunks/chunk-XPF5XHLY.js +0 -15
  145. package/dist/safe-bash/chunks/chunk-ZBFOWARG.js +0 -305
  146. package/dist/safe-bash/chunks/chunk-ZG7GWQ5P.js +0 -1859
  147. package/dist/safe-bash/chunks/model-store-EIY3ZQLZ.js +0 -10
  148. package/dist/safe-bash/chunks/pdf-renderer-CMF3CSVU.js +0 -22
  149. package/dist/safe-bash/chunks/pptx-ZL6L7KP2-O425BFIU.js +0 -30658
  150. package/dist/safe-bash/chunks/src-HHEPGR7U.js +0 -18969
  151. package/dist/safe-bash/chunks/src-MXIKQCIC.js +0 -187
  152. package/dist/safe-bash/chunks/usage-6TGVA2OM.js +0 -35
  153. package/dist/safe-bash/chunks/xz-EGQGQUEI.js +0 -8
  154. package/dist/safe-bash/chunks/xz-K2E2WLM6.js +0 -9
  155. package/dist/safe-bash/chunks/zstd-6JBLP5EF.js +0 -8
  156. package/dist/safe-bash/git_rust-C3QYOAZL.wasm +0 -0
  157. package/dist/safe-bash/command-chunks/{chunk-OQVIJMBY.js → chunk-7HINP7ZK.js} +4 -4
  158. package/dist/safe-bash/command-chunks/{chunk-XAYEDOV5.js → chunk-CG4JSOK2.js} +3 -3
  159. package/dist/safe-bash/command-chunks/{chunk-YIK4ZYQ4.js → chunk-DC52GWRK.js} +9 -9
  160. package/dist/safe-bash/command-chunks/{chunk-TOTZFBDT.js → chunk-TKACIO4X.js} +4 -4
  161. package/dist/safe-bash/command-chunks/{chunk-VTWKS4RM.js → chunk-WF2LSKMI.js} +3 -3
@@ -28,8 +28,8 @@ import {
28
28
  thresholdImage,
29
29
  tintImage,
30
30
  trimImage
31
- } from "../safe-bash/command-chunks/chunk-WI35236J.js";
32
- import "../safe-bash/command-chunks/chunk-H2FQA4OU.js";
31
+ } from "../safe-bash/command-chunks/chunk-XYCWDGOG.js";
32
+ import "../safe-bash/command-chunks/chunk-TCAGGM44.js";
33
33
  import {
34
34
  init_buffer
35
35
  } from "../safe-bash/command-chunks/chunk-HX3SHTCE.js";
@@ -2,11 +2,11 @@ import {
2
2
  createPandocCommand,
3
3
  createPandocCommands,
4
4
  pandocCommands
5
- } from "../safe-bash/command-chunks/chunk-KBBI4CSU.js";
5
+ } from "../safe-bash/command-chunks/chunk-L2C5TIII.js";
6
6
  import "../safe-bash/command-chunks/chunk-MKQVQMXO.js";
7
7
  import "../safe-bash/command-chunks/chunk-RDV7UCYZ.js";
8
- import "../safe-bash/command-chunks/chunk-WI35236J.js";
9
- import "../safe-bash/command-chunks/chunk-H2FQA4OU.js";
8
+ import "../safe-bash/command-chunks/chunk-XYCWDGOG.js";
9
+ import "../safe-bash/command-chunks/chunk-TCAGGM44.js";
10
10
  import "../safe-bash/command-chunks/chunk-Y2KHC6TZ.js";
11
11
  import "../safe-bash/command-chunks/chunk-YGYOVXTO.js";
12
12
  import "../safe-bash/command-chunks/chunk-I5GLTNVH.js";
@@ -21,11 +21,11 @@ import {
21
21
  readDocument,
22
22
  resolveConversionArgs,
23
23
  writeDocument
24
- } from "../safe-bash/command-chunks/chunk-KBBI4CSU.js";
24
+ } from "../safe-bash/command-chunks/chunk-L2C5TIII.js";
25
25
  import "../safe-bash/command-chunks/chunk-MKQVQMXO.js";
26
26
  import "../safe-bash/command-chunks/chunk-RDV7UCYZ.js";
27
- import "../safe-bash/command-chunks/chunk-WI35236J.js";
28
- import "../safe-bash/command-chunks/chunk-H2FQA4OU.js";
27
+ import "../safe-bash/command-chunks/chunk-XYCWDGOG.js";
28
+ import "../safe-bash/command-chunks/chunk-TCAGGM44.js";
29
29
  import {
30
30
  createLuaFilterCapability
31
31
  } from "../safe-bash/command-chunks/chunk-Y2KHC6TZ.js";
@@ -25274,7 +25274,7 @@ var ParsedCosDocument = class {
25274
25274
  return void 0;
25275
25275
  }
25276
25276
  };
25277
- function parseNodeFromLexer(lexer, bytes, maxDepth, recoverEmptyObject = false) {
25277
+ function parseNodeFromLexer(lexer, bytes, maxDepth, repair = false) {
25278
25278
  const stack = [];
25279
25279
  while (true) {
25280
25280
  const tok = lexer.nextToken();
@@ -25283,7 +25283,7 @@ function parseNodeFromLexer(lexer, bytes, maxDepth, recoverEmptyObject = false)
25283
25283
  if (!parent) return void 0;
25284
25284
  throw new PdfError("E_PARSE", parent.kind === "array" ? "Unterminated PDF array" : "Unterminated PDF dictionary");
25285
25285
  }
25286
- if (!parent && recoverEmptyObject && tok.kind === "keyword" && tok.value === "endobj") {
25286
+ if (!parent && repair && tok.kind === "keyword" && tok.value === "endobj") {
25287
25287
  return { kind: "null", span: tok.span };
25288
25288
  }
25289
25289
  let node;
@@ -25298,6 +25298,7 @@ function parseNodeFromLexer(lexer, bytes, maxDepth, recoverEmptyObject = false)
25298
25298
  parent.key = { kind: "name", rawBytes: tok.rawBytes, decoded: tok.decoded, span: tok.span };
25299
25299
  continue;
25300
25300
  } else {
25301
+ if (repair) continue;
25301
25302
  throw new PdfError("E_PARSE", `Expected dictionary key /Name, got ${tok.kind}`);
25302
25303
  }
25303
25304
  } else {
@@ -25466,7 +25467,7 @@ function parseHeaderVersion(bytes) {
25466
25467
  }
25467
25468
  return head.slice(idx + 5, idx + 8);
25468
25469
  }
25469
- function parseObjectAtOffset(bytes, offset, maxRecursionDepth, recoverEmptyObject = false) {
25470
+ function parseObjectAtOffset(bytes, offset, maxRecursionDepth, repair = false) {
25470
25471
  const lexer = new CosByteLexer(bytes, offset);
25471
25472
  const objNumTok = lexer.nextToken();
25472
25473
  const genNumTok = lexer.nextToken();
@@ -25474,7 +25475,7 @@ function parseObjectAtOffset(bytes, offset, maxRecursionDepth, recoverEmptyObjec
25474
25475
  if (objNumTok?.kind !== "number" || genNumTok?.kind !== "number" || objKwTok?.kind !== "keyword" || objKwTok.value !== "obj") {
25475
25476
  throw new PdfError("E_PARSE", `Malformed indirect object header at byte offset ${offset}`);
25476
25477
  }
25477
- const value = parseNodeFromLexer(lexer, bytes, maxRecursionDepth, recoverEmptyObject);
25478
+ const value = parseNodeFromLexer(lexer, bytes, maxRecursionDepth, repair);
25478
25479
  if (!value) {
25479
25480
  throw new PdfError("E_PARSE", `Empty indirect object ${objNumTok.value} at offset ${offset}`);
25480
25481
  }
@@ -25663,7 +25664,7 @@ function repairScanCosDocument(bytes, maxObjects, maxRecursionDepth) {
25663
25664
  try {
25664
25665
  const token = lexer.nextToken();
25665
25666
  if (token?.kind === "keyword" && token.value === "trailer") {
25666
- const trailer = parseNodeFromLexer(lexer, bytes, maxRecursionDepth);
25667
+ const trailer = parseNodeFromLexer(lexer, bytes, maxRecursionDepth, true);
25667
25668
  if (trailer?.kind === "dict") trailers.push(trailer);
25668
25669
  pos = lexer.offset;
25669
25670
  continue;
@@ -25719,7 +25720,7 @@ function unpackRecoveredObjects(objects, maxObjects, maxDecompressedBytes, maxRe
25719
25720
  const t = dictGet(obj.value.dict, "Type");
25720
25721
  if (t?.kind === "name" && t.decoded === "ObjStm") {
25721
25722
  try {
25722
- for (const [unpackedNum, unpackedVal] of unpackObjectStream(obj.value, maxDecompressedBytes, maxRecursionDepth).entries()) {
25723
+ for (const [unpackedNum, unpackedVal] of unpackObjectStream(obj.value, maxDecompressedBytes, maxRecursionDepth, true).entries()) {
25723
25724
  if (!objects.has(unpackedNum)) {
25724
25725
  objects.set(unpackedNum, {
25725
25726
  objectNumber: unpackedNum,
@@ -25755,7 +25756,7 @@ function recoveredReferences(objects) {
25755
25756
  }
25756
25757
  return { ...rootRef ? { rootRef } : {}, ...infoRef ? { infoRef } : {} };
25757
25758
  }
25758
- function unpackObjectStream(streamObj, maxDecompressedBytes, maxRecursionDepth) {
25759
+ function unpackObjectStream(streamObj, maxDecompressedBytes, maxRecursionDepth, repair = false) {
25759
25760
  const nNode = dictGet(streamObj.dict, "N");
25760
25761
  const firstNode = dictGet(streamObj.dict, "First");
25761
25762
  if (nNode?.kind !== "number" || firstNode?.kind !== "number") {
@@ -25775,7 +25776,7 @@ function unpackObjectStream(streamObj, maxDecompressedBytes, maxRecursionDepth)
25775
25776
  for (const pair of pairs) {
25776
25777
  try {
25777
25778
  const valLexer = new CosByteLexer(decoded, firstNode.value + pair.relativeOffset);
25778
- const node = parseNodeFromLexer(valLexer, decoded, maxRecursionDepth);
25779
+ const node = parseNodeFromLexer(valLexer, decoded, maxRecursionDepth, repair);
25779
25780
  if (node) {
25780
25781
  result.set(pair.objectNumber, node);
25781
25782
  }
@@ -25958,7 +25959,7 @@ function parseCosDocument(bytes, options = {}) {
25958
25959
  if (!unpacked) {
25959
25960
  const stmObj = objects.get(entry.objectStreamNumber)?.value;
25960
25961
  if (stmObj?.kind === "stream") {
25961
- unpacked = unpackObjectStream(stmObj, maxDecompressedBytes, maxRecursionDepth);
25962
+ unpacked = unpackObjectStream(stmObj, maxDecompressedBytes, maxRecursionDepth, recovery === "repair");
25962
25963
  objStmCache.set(entry.objectStreamNumber, unpacked);
25963
25964
  }
25964
25965
  }
@@ -34775,7 +34776,11 @@ function resolvePageFonts(doc, resourcesDict) {
34775
34776
  let cmap;
34776
34777
  const toUniNode = doc.resolve(dictGet(fObj, "ToUnicode"));
34777
34778
  if (toUniNode?.kind === "stream") {
34778
- cmap = parseToUnicodeCMap(doc.decodeStream(toUniNode));
34779
+ try {
34780
+ cmap = parseToUnicodeCMap(doc.decodeStream(toUniNode));
34781
+ } catch (error) {
34782
+ if (error instanceof PdfError && error.code === "E_LIMIT") throw error;
34783
+ }
34779
34784
  }
34780
34785
  const encNode = doc.resolve(dictGet(fObj, "Encoding"));
34781
34786
  if (encNode?.kind === "dict") {
@@ -35899,8 +35904,12 @@ function evaluateContentStreamToDisplayList(params) {
35899
35904
  const images = [];
35900
35905
  const operations = [];
35901
35906
  const emit = (operation) => {
35902
- const clipPaths = curState().clipPaths;
35903
- if (clipPaths) operation = { ...operation, value: { ...operation.value, clipPaths } };
35907
+ const { clipPaths, clipImages } = curState();
35908
+ if (clipPaths || clipImages) operation = { ...operation, value: {
35909
+ ...operation.value,
35910
+ ...clipPaths ? { clipPaths } : {},
35911
+ ...clipImages ? { clipImages } : {}
35912
+ } };
35904
35913
  operations.push(operation);
35905
35914
  switch (operation.kind) {
35906
35915
  case "path":
@@ -36164,6 +36173,18 @@ function evaluateContentStreamToDisplayList(params) {
36164
36173
  let hasTextClip = false;
36165
36174
  let activeTm = [1, 0, 0, 1, 0, 0];
36166
36175
  let activeTlm = [1, 0, 0, 1, 0, 0];
36176
+ const paintImage = (image, patternMask, resources, activeFonts, depth) => {
36177
+ if (!patternMask) {
36178
+ emit({ kind: "image", value: image });
36179
+ return;
36180
+ }
36181
+ const st = curState();
36182
+ stateStack.push({ ...st, clipImages: [...st.clipImages ?? [], image] });
36183
+ walkNodes([{ kind: "path-op", paint: "f", segments: [
36184
+ { kind: "rect", x: 0, y: 0, width: 1, height: 1 }
36185
+ ] }], void 0, void 0, resources, activeFonts, depth);
36186
+ stateStack.pop();
36187
+ };
36167
36188
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
36168
36189
  for (const node of nodes) {
36169
36190
  switch (node.kind) {
@@ -36347,7 +36368,8 @@ function evaluateContentStreamToDisplayList(params) {
36347
36368
  st.fillAlpha,
36348
36369
  "PatternShading_" + st.fillPatternName,
36349
36370
  patClip,
36350
- shading?.kind === "stream" ? shading : void 0
36371
+ shading?.kind === "stream" ? shading : void 0,
36372
+ st.blendMode
36351
36373
  );
36352
36374
  if (shImg) {
36353
36375
  emit({ kind: "image", value: shImg });
@@ -36456,18 +36478,20 @@ function evaluateContentStreamToDisplayList(params) {
36456
36478
  const subNode = params.cosDoc.resolve(dictGet(xobjNode.dict, "Subtype"));
36457
36479
  const sub = subNode?.kind === "name" ? subNode.decoded : "";
36458
36480
  if (sub === "Image") {
36481
+ const maskNode = params.cosDoc.resolve(dictGet(xobjNode.dict, "ImageMask"));
36482
+ const patternMask = !!st.fillPatternName && maskNode?.kind === "boolean" && maskNode.value;
36459
36483
  const decoded = decodeXObjectImageToRgba(
36460
36484
  params.cosDoc,
36461
36485
  xobjNode,
36462
36486
  activeResources,
36463
- {
36487
+ patternMask ? { r: 1, g: 1, b: 1, alpha: 1 } : {
36464
36488
  r: st.fillColor.r,
36465
36489
  g: st.fillColor.g,
36466
36490
  b: st.fillColor.b,
36467
36491
  alpha: st.fillAlpha
36468
36492
  }
36469
36493
  );
36470
- emit({ kind: "image", value: {
36494
+ paintImage({
36471
36495
  name: node.name,
36472
36496
  matrix: [...st.ctm],
36473
36497
  width: decoded.width,
@@ -36477,7 +36501,7 @@ function evaluateContentStreamToDisplayList(params) {
36477
36501
  decodedRgba: decoded.rgba,
36478
36502
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
36479
36503
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
36480
- } });
36504
+ }, patternMask, activeResources, activeFonts, depth);
36481
36505
  } else if (sub === "Form" && depth < 8) {
36482
36506
  const formStreamBytes = params.cosDoc.decodeStream(xobjNode);
36483
36507
  const formNodes = parseContentStream(formStreamBytes);
@@ -36533,19 +36557,22 @@ function evaluateContentStreamToDisplayList(params) {
36533
36557
  }
36534
36558
  case "inline-image": {
36535
36559
  const st = curState();
36560
+ const maskEntry = dictGet(node.dict, "ImageMask") ?? dictGet(node.dict, "IM");
36561
+ const maskNode = params.cosDoc ? params.cosDoc.resolve(maskEntry) : maskEntry;
36562
+ const patternMask = !!st.fillPatternName && maskNode?.kind === "boolean" && maskNode.value;
36536
36563
  const decoded = decodeInlineImageNodeToRgba(
36537
36564
  params.cosDoc,
36538
36565
  node.dict,
36539
36566
  node.data,
36540
36567
  activeResources,
36541
- {
36568
+ patternMask ? { r: 1, g: 1, b: 1, alpha: 1 } : {
36542
36569
  r: st.fillColor.r,
36543
36570
  g: st.fillColor.g,
36544
36571
  b: st.fillColor.b,
36545
36572
  alpha: st.fillAlpha
36546
36573
  }
36547
36574
  );
36548
- emit({ kind: "image", value: {
36575
+ paintImage({
36549
36576
  name: "InlineImage",
36550
36577
  matrix: [...st.ctm],
36551
36578
  width: decoded.width,
@@ -36555,7 +36582,7 @@ function evaluateContentStreamToDisplayList(params) {
36555
36582
  decodedRgba: decoded.rgba,
36556
36583
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
36557
36584
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
36558
- } });
36585
+ }, patternMask, activeResources, activeFonts, depth);
36559
36586
  break;
36560
36587
  }
36561
36588
  case "text-object": {
@@ -40059,6 +40086,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40059
40086
  const aaVec = options.antialiasVector !== false;
40060
40087
  const aaTxt = options.antialiasText !== false;
40061
40088
  const clipMasks = /* @__PURE__ */ new Map();
40089
+ const imageClipMasks = /* @__PURE__ */ new Map();
40062
40090
  for (const original of paintOperations(displayList)) {
40063
40091
  if (original.kind === "glyph" && (original.value.renderMode === 3 || !original.value.outline && !original.value.unicode.trim())) continue;
40064
40092
  const operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
@@ -40073,6 +40101,31 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40073
40101
  }
40074
40102
  clipMasks.set(clips, clipMask);
40075
40103
  }
40104
+ const imageClips = original.value.clipImages;
40105
+ if (imageClips) {
40106
+ let imageMask = imageClipMasks.get(imageClips);
40107
+ if (!imageMask) {
40108
+ imageMask = new Uint8Array(width * height * 4).fill(255);
40109
+ for (const image of imageClips) {
40110
+ const layer = renderDisplayListToBitmap({
40111
+ ...displayList,
40112
+ rotation: 0,
40113
+ paths: [],
40114
+ glyphs: [],
40115
+ images: [image],
40116
+ operations: [{ kind: "image", value: image }]
40117
+ }, { scale, transparent: true }).data;
40118
+ for (let i = 3; i < layer.length; i += 4) imageMask[i] = Math.round(imageMask[i] * layer[i] / 255);
40119
+ }
40120
+ imageClipMasks.set(imageClips, imageMask);
40121
+ }
40122
+ if (clipMask) {
40123
+ clipMask = clipMask.slice();
40124
+ for (let i = 3; i < clipMask.length; i += 4) clipMask[i] = Math.round(clipMask[i] * imageMask[i] / 255);
40125
+ } else {
40126
+ clipMask = imageMask;
40127
+ }
40128
+ }
40076
40129
  if (operation.kind === "path") {
40077
40130
  const path = operation.value;
40078
40131
  if (path.fillColor) {
@@ -25468,7 +25468,7 @@ var ParsedCosDocument = class {
25468
25468
  return void 0;
25469
25469
  }
25470
25470
  };
25471
- function parseNodeFromLexer(lexer, bytes, maxDepth, recoverEmptyObject = false) {
25471
+ function parseNodeFromLexer(lexer, bytes, maxDepth, repair = false) {
25472
25472
  const stack = [];
25473
25473
  while (true) {
25474
25474
  const tok = lexer.nextToken();
@@ -25477,7 +25477,7 @@ function parseNodeFromLexer(lexer, bytes, maxDepth, recoverEmptyObject = false)
25477
25477
  if (!parent) return void 0;
25478
25478
  throw new PdfError("E_PARSE", parent.kind === "array" ? "Unterminated PDF array" : "Unterminated PDF dictionary");
25479
25479
  }
25480
- if (!parent && recoverEmptyObject && tok.kind === "keyword" && tok.value === "endobj") {
25480
+ if (!parent && repair && tok.kind === "keyword" && tok.value === "endobj") {
25481
25481
  return { kind: "null", span: tok.span };
25482
25482
  }
25483
25483
  let node;
@@ -25492,6 +25492,7 @@ function parseNodeFromLexer(lexer, bytes, maxDepth, recoverEmptyObject = false)
25492
25492
  parent.key = { kind: "name", rawBytes: tok.rawBytes, decoded: tok.decoded, span: tok.span };
25493
25493
  continue;
25494
25494
  } else {
25495
+ if (repair) continue;
25495
25496
  throw new PdfError("E_PARSE", `Expected dictionary key /Name, got ${tok.kind}`);
25496
25497
  }
25497
25498
  } else {
@@ -25660,7 +25661,7 @@ function parseHeaderVersion(bytes) {
25660
25661
  }
25661
25662
  return head.slice(idx + 5, idx + 8);
25662
25663
  }
25663
- function parseObjectAtOffset(bytes, offset, maxRecursionDepth, recoverEmptyObject = false) {
25664
+ function parseObjectAtOffset(bytes, offset, maxRecursionDepth, repair = false) {
25664
25665
  const lexer = new CosByteLexer(bytes, offset);
25665
25666
  const objNumTok = lexer.nextToken();
25666
25667
  const genNumTok = lexer.nextToken();
@@ -25668,7 +25669,7 @@ function parseObjectAtOffset(bytes, offset, maxRecursionDepth, recoverEmptyObjec
25668
25669
  if (objNumTok?.kind !== "number" || genNumTok?.kind !== "number" || objKwTok?.kind !== "keyword" || objKwTok.value !== "obj") {
25669
25670
  throw new PdfError("E_PARSE", `Malformed indirect object header at byte offset ${offset}`);
25670
25671
  }
25671
- const value = parseNodeFromLexer(lexer, bytes, maxRecursionDepth, recoverEmptyObject);
25672
+ const value = parseNodeFromLexer(lexer, bytes, maxRecursionDepth, repair);
25672
25673
  if (!value) {
25673
25674
  throw new PdfError("E_PARSE", `Empty indirect object ${objNumTok.value} at offset ${offset}`);
25674
25675
  }
@@ -25857,7 +25858,7 @@ function repairScanCosDocument(bytes, maxObjects, maxRecursionDepth) {
25857
25858
  try {
25858
25859
  const token = lexer.nextToken();
25859
25860
  if (token?.kind === "keyword" && token.value === "trailer") {
25860
- const trailer = parseNodeFromLexer(lexer, bytes, maxRecursionDepth);
25861
+ const trailer = parseNodeFromLexer(lexer, bytes, maxRecursionDepth, true);
25861
25862
  if (trailer?.kind === "dict") trailers.push(trailer);
25862
25863
  pos = lexer.offset;
25863
25864
  continue;
@@ -25913,7 +25914,7 @@ function unpackRecoveredObjects(objects, maxObjects, maxDecompressedBytes, maxRe
25913
25914
  const t = dictGet(obj.value.dict, "Type");
25914
25915
  if (t?.kind === "name" && t.decoded === "ObjStm") {
25915
25916
  try {
25916
- for (const [unpackedNum, unpackedVal] of unpackObjectStream(obj.value, maxDecompressedBytes, maxRecursionDepth).entries()) {
25917
+ for (const [unpackedNum, unpackedVal] of unpackObjectStream(obj.value, maxDecompressedBytes, maxRecursionDepth, true).entries()) {
25917
25918
  if (!objects.has(unpackedNum)) {
25918
25919
  objects.set(unpackedNum, {
25919
25920
  objectNumber: unpackedNum,
@@ -25949,7 +25950,7 @@ function recoveredReferences(objects) {
25949
25950
  }
25950
25951
  return { ...rootRef ? { rootRef } : {}, ...infoRef ? { infoRef } : {} };
25951
25952
  }
25952
- function unpackObjectStream(streamObj, maxDecompressedBytes, maxRecursionDepth) {
25953
+ function unpackObjectStream(streamObj, maxDecompressedBytes, maxRecursionDepth, repair = false) {
25953
25954
  const nNode = dictGet(streamObj.dict, "N");
25954
25955
  const firstNode = dictGet(streamObj.dict, "First");
25955
25956
  if (nNode?.kind !== "number" || firstNode?.kind !== "number") {
@@ -25969,7 +25970,7 @@ function unpackObjectStream(streamObj, maxDecompressedBytes, maxRecursionDepth)
25969
25970
  for (const pair of pairs) {
25970
25971
  try {
25971
25972
  const valLexer = new CosByteLexer(decoded, firstNode.value + pair.relativeOffset);
25972
- const node = parseNodeFromLexer(valLexer, decoded, maxRecursionDepth);
25973
+ const node = parseNodeFromLexer(valLexer, decoded, maxRecursionDepth, repair);
25973
25974
  if (node) {
25974
25975
  result.set(pair.objectNumber, node);
25975
25976
  }
@@ -26152,7 +26153,7 @@ function parseCosDocument(bytes, options = {}) {
26152
26153
  if (!unpacked) {
26153
26154
  const stmObj = objects.get(entry.objectStreamNumber)?.value;
26154
26155
  if (stmObj?.kind === "stream") {
26155
- unpacked = unpackObjectStream(stmObj, maxDecompressedBytes, maxRecursionDepth);
26156
+ unpacked = unpackObjectStream(stmObj, maxDecompressedBytes, maxRecursionDepth, recovery === "repair");
26156
26157
  objStmCache.set(entry.objectStreamNumber, unpacked);
26157
26158
  }
26158
26159
  }
@@ -34969,7 +34970,11 @@ function resolvePageFonts(doc, resourcesDict) {
34969
34970
  let cmap;
34970
34971
  const toUniNode = doc.resolve(dictGet(fObj, "ToUnicode"));
34971
34972
  if (toUniNode?.kind === "stream") {
34972
- cmap = parseToUnicodeCMap(doc.decodeStream(toUniNode));
34973
+ try {
34974
+ cmap = parseToUnicodeCMap(doc.decodeStream(toUniNode));
34975
+ } catch (error) {
34976
+ if (error instanceof PdfError && error.code === "E_LIMIT") throw error;
34977
+ }
34973
34978
  }
34974
34979
  const encNode = doc.resolve(dictGet(fObj, "Encoding"));
34975
34980
  if (encNode?.kind === "dict") {
@@ -36093,8 +36098,12 @@ function evaluateContentStreamToDisplayList(params) {
36093
36098
  const images = [];
36094
36099
  const operations = [];
36095
36100
  const emit = (operation) => {
36096
- const clipPaths = curState().clipPaths;
36097
- if (clipPaths) operation = { ...operation, value: { ...operation.value, clipPaths } };
36101
+ const { clipPaths, clipImages } = curState();
36102
+ if (clipPaths || clipImages) operation = { ...operation, value: {
36103
+ ...operation.value,
36104
+ ...clipPaths ? { clipPaths } : {},
36105
+ ...clipImages ? { clipImages } : {}
36106
+ } };
36098
36107
  operations.push(operation);
36099
36108
  switch (operation.kind) {
36100
36109
  case "path":
@@ -36358,6 +36367,18 @@ function evaluateContentStreamToDisplayList(params) {
36358
36367
  let hasTextClip = false;
36359
36368
  let activeTm = [1, 0, 0, 1, 0, 0];
36360
36369
  let activeTlm = [1, 0, 0, 1, 0, 0];
36370
+ const paintImage = (image, patternMask, resources, activeFonts, depth) => {
36371
+ if (!patternMask) {
36372
+ emit({ kind: "image", value: image });
36373
+ return;
36374
+ }
36375
+ const st = curState();
36376
+ stateStack.push({ ...st, clipImages: [...st.clipImages ?? [], image] });
36377
+ walkNodes([{ kind: "path-op", paint: "f", segments: [
36378
+ { kind: "rect", x: 0, y: 0, width: 1, height: 1 }
36379
+ ] }], void 0, void 0, resources, activeFonts, depth);
36380
+ stateStack.pop();
36381
+ };
36361
36382
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
36362
36383
  for (const node of nodes) {
36363
36384
  switch (node.kind) {
@@ -36541,7 +36562,8 @@ function evaluateContentStreamToDisplayList(params) {
36541
36562
  st.fillAlpha,
36542
36563
  "PatternShading_" + st.fillPatternName,
36543
36564
  patClip,
36544
- shading?.kind === "stream" ? shading : void 0
36565
+ shading?.kind === "stream" ? shading : void 0,
36566
+ st.blendMode
36545
36567
  );
36546
36568
  if (shImg) {
36547
36569
  emit({ kind: "image", value: shImg });
@@ -36650,18 +36672,20 @@ function evaluateContentStreamToDisplayList(params) {
36650
36672
  const subNode = params.cosDoc.resolve(dictGet(xobjNode.dict, "Subtype"));
36651
36673
  const sub = subNode?.kind === "name" ? subNode.decoded : "";
36652
36674
  if (sub === "Image") {
36675
+ const maskNode = params.cosDoc.resolve(dictGet(xobjNode.dict, "ImageMask"));
36676
+ const patternMask = !!st.fillPatternName && maskNode?.kind === "boolean" && maskNode.value;
36653
36677
  const decoded = decodeXObjectImageToRgba(
36654
36678
  params.cosDoc,
36655
36679
  xobjNode,
36656
36680
  activeResources,
36657
- {
36681
+ patternMask ? { r: 1, g: 1, b: 1, alpha: 1 } : {
36658
36682
  r: st.fillColor.r,
36659
36683
  g: st.fillColor.g,
36660
36684
  b: st.fillColor.b,
36661
36685
  alpha: st.fillAlpha
36662
36686
  }
36663
36687
  );
36664
- emit({ kind: "image", value: {
36688
+ paintImage({
36665
36689
  name: node.name,
36666
36690
  matrix: [...st.ctm],
36667
36691
  width: decoded.width,
@@ -36671,7 +36695,7 @@ function evaluateContentStreamToDisplayList(params) {
36671
36695
  decodedRgba: decoded.rgba,
36672
36696
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
36673
36697
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
36674
- } });
36698
+ }, patternMask, activeResources, activeFonts, depth);
36675
36699
  } else if (sub === "Form" && depth < 8) {
36676
36700
  const formStreamBytes = params.cosDoc.decodeStream(xobjNode);
36677
36701
  const formNodes = parseContentStream(formStreamBytes);
@@ -36727,19 +36751,22 @@ function evaluateContentStreamToDisplayList(params) {
36727
36751
  }
36728
36752
  case "inline-image": {
36729
36753
  const st = curState();
36754
+ const maskEntry = dictGet(node.dict, "ImageMask") ?? dictGet(node.dict, "IM");
36755
+ const maskNode = params.cosDoc ? params.cosDoc.resolve(maskEntry) : maskEntry;
36756
+ const patternMask = !!st.fillPatternName && maskNode?.kind === "boolean" && maskNode.value;
36730
36757
  const decoded = decodeInlineImageNodeToRgba(
36731
36758
  params.cosDoc,
36732
36759
  node.dict,
36733
36760
  node.data,
36734
36761
  activeResources,
36735
- {
36762
+ patternMask ? { r: 1, g: 1, b: 1, alpha: 1 } : {
36736
36763
  r: st.fillColor.r,
36737
36764
  g: st.fillColor.g,
36738
36765
  b: st.fillColor.b,
36739
36766
  alpha: st.fillAlpha
36740
36767
  }
36741
36768
  );
36742
- emit({ kind: "image", value: {
36769
+ paintImage({
36743
36770
  name: "InlineImage",
36744
36771
  matrix: [...st.ctm],
36745
36772
  width: decoded.width,
@@ -36749,7 +36776,7 @@ function evaluateContentStreamToDisplayList(params) {
36749
36776
  decodedRgba: decoded.rgba,
36750
36777
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
36751
36778
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
36752
- } });
36779
+ }, patternMask, activeResources, activeFonts, depth);
36753
36780
  break;
36754
36781
  }
36755
36782
  case "text-object": {
@@ -40495,6 +40522,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40495
40522
  const aaVec = options.antialiasVector !== false;
40496
40523
  const aaTxt = options.antialiasText !== false;
40497
40524
  const clipMasks = /* @__PURE__ */ new Map();
40525
+ const imageClipMasks = /* @__PURE__ */ new Map();
40498
40526
  for (const original of paintOperations(displayList)) {
40499
40527
  if (original.kind === "glyph" && (original.value.renderMode === 3 || !original.value.outline && !original.value.unicode.trim())) continue;
40500
40528
  const operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
@@ -40509,6 +40537,31 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40509
40537
  }
40510
40538
  clipMasks.set(clips, clipMask);
40511
40539
  }
40540
+ const imageClips = original.value.clipImages;
40541
+ if (imageClips) {
40542
+ let imageMask = imageClipMasks.get(imageClips);
40543
+ if (!imageMask) {
40544
+ imageMask = new Uint8Array(width * height * 4).fill(255);
40545
+ for (const image of imageClips) {
40546
+ const layer = renderDisplayListToBitmap({
40547
+ ...displayList,
40548
+ rotation: 0,
40549
+ paths: [],
40550
+ glyphs: [],
40551
+ images: [image],
40552
+ operations: [{ kind: "image", value: image }]
40553
+ }, { scale, transparent: true }).data;
40554
+ for (let i = 3; i < layer.length; i += 4) imageMask[i] = Math.round(imageMask[i] * layer[i] / 255);
40555
+ }
40556
+ imageClipMasks.set(imageClips, imageMask);
40557
+ }
40558
+ if (clipMask) {
40559
+ clipMask = clipMask.slice();
40560
+ for (let i = 3; i < clipMask.length; i += 4) clipMask[i] = Math.round(clipMask[i] * imageMask[i] / 255);
40561
+ } else {
40562
+ clipMask = imageMask;
40563
+ }
40564
+ }
40512
40565
  if (operation.kind === "path") {
40513
40566
  const path = operation.value;
40514
40567
  if (path.fillColor) {
@@ -40657,6 +40710,15 @@ function escapeXmlText(str) {
40657
40710
  }
40658
40711
  return encodeToXmlString(valid);
40659
40712
  }
40713
+ function svgImage(image, pageHeight) {
40714
+ if (!image.decodedRgba) return "";
40715
+ const png = encodeRgbaToPng(image.width, image.height, image.decodedRgba);
40716
+ const chunks = [];
40717
+ for (let offset = 0; offset < png.length; offset += 8192)
40718
+ chunks.push(String.fromCharCode(...png.subarray(offset, offset + 8192)));
40719
+ const [a, b, c, d, e, f] = image.matrix;
40720
+ return `<image width="1" height="1" preserveAspectRatio="none" transform="matrix(${a} ${-b} ${-c} ${d} ${e + c} ${pageHeight - f - d})" href="data:image/png;base64,${btoa(chunks.join(""))}"/>`;
40721
+ }
40660
40722
  function svgPathData(segments, height) {
40661
40723
  const dParts = [];
40662
40724
  for (const seg of segments) {
@@ -40705,11 +40767,16 @@ function renderDisplayListToSvg(displayList, options = {}) {
40705
40767
  if (original.kind === "glyph" && (original.value.renderMode === 3 || !original.value.outline && !original.value.unicode.trim())) continue;
40706
40768
  const operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
40707
40769
  const clips = original.value.clipPaths ?? [];
40770
+ const imageClips = original.value.clipImages ?? [];
40708
40771
  for (const segments of clips) {
40709
40772
  const id = `text-clip-${clipId++}`;
40710
40773
  const path = `<path d="${svgPathData(segments, displayList.height)}"/>`;
40711
40774
  parts.push(`<defs><clipPath id="${id}" clipPathUnits="userSpaceOnUse">${path}</clipPath></defs><g clip-path="url(#${id})">`);
40712
40775
  }
40776
+ for (const image of imageClips) {
40777
+ const id = `image-clip-${clipId++}`;
40778
+ parts.push(`<defs><mask id="${id}" maskUnits="userSpaceOnUse" x="0" y="0" width="${displayList.width}" height="${displayList.height}" style="mask-type:alpha">${svgImage(image, displayList.height)}</mask></defs><g mask="url(#${id})">`);
40779
+ }
40713
40780
  if (operation.kind === "path") {
40714
40781
  const p = operation.value;
40715
40782
  const pathData = svgPathData(p.segments, displayList.height);
@@ -40729,24 +40796,9 @@ function renderDisplayListToSvg(displayList, options = {}) {
40729
40796
  parts.push(` <path${labelAttr} d="${pathData}" fill="${fill}"${fillRuleAttr}${fillOpacityAttr} stroke="${stroke}"${strokeOpacityAttr}${strokeWidthAttr}${lineCapAttr}${lineJoinAttr}${miterLimitAttr}${dashArrayAttr}${dashOffsetAttr}/>`);
40730
40797
  }
40731
40798
  } else if (operation.kind === "image") {
40732
- const img = operation.value;
40733
- if (!img.decodedRgba) {
40734
- for (let i = 0; i < clips.length; i++) parts.push("</g>");
40735
- continue;
40736
- }
40737
- const pngBytes = encodeRgbaToPng(img.width, img.height, img.decodedRgba);
40738
- const chunks = [];
40739
- for (let offset = 0; offset < pngBytes.length; offset += 8192)
40740
- chunks.push(String.fromCharCode(...pngBytes.subarray(offset, offset + 8192)));
40741
- const b64 = btoa(chunks.join(""));
40742
- const [a, b, c, d, e, f] = img.matrix;
40743
- const svgTx = e + c;
40744
- const svgTy = displayList.height - f - d;
40745
- parts.push(
40746
- ` <image width="1" height="1" preserveAspectRatio="none" transform="matrix(${a} ${-b} ${-c} ${d} ${svgTx} ${svgTy})" href="data:image/png;base64,${b64}"/>`
40747
- );
40799
+ parts.push(` ${svgImage(operation.value, displayList.height)}`);
40748
40800
  }
40749
- for (let i = 0; i < clips.length; i++) parts.push("</g>");
40801
+ for (let i = 0; i < clips.length + imageClips.length; i++) parts.push("</g>");
40750
40802
  }
40751
40803
  if (displayList.rotation) parts.push("</g>");
40752
40804
  parts.push("</svg>\n");