@poe-platform/safe-bash 0.1.762 → 0.1.763

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 (28) hide show
  1. package/dist/image-ast/index.browser.js +186 -55
  2. package/dist/image-ast/index.js +186 -55
  3. package/dist/pdf-ast/ast.d.ts +23 -0
  4. package/dist/pdf-ast/index.js +273 -91
  5. package/dist/safe-bash/command-chunks/{chunk-D4GXXV65.js → chunk-4XHONGIU.js} +2 -2
  6. package/dist/safe-bash/command-chunks/{chunk-P3Q2QSCA.js → chunk-S3G2B4OX.js} +186 -55
  7. package/dist/safe-bash/command-chunks/{chunk-F7MJRXQ2.js → chunk-S5EX6UP5.js} +1 -1
  8. package/dist/safe-bash/core.browser.js +1 -1
  9. package/dist/safe-bash/shell/runtime.js +1 -1
  10. package/dist/safe-bash-checksum-engine/index.d.ts +1 -1
  11. package/dist/safe-bash-checksum-engine/index.js +5 -1
  12. package/dist/safe-bash-command-ffmpeg/index.js +7486 -7432
  13. package/dist/safe-bash-command-gh/index.js +174 -105
  14. package/dist/safe-bash-command-imagemagick/index.js +2 -2
  15. package/dist/safe-bash-command-pandoc/command.js +3 -3
  16. package/dist/safe-bash-command-pandoc/index.js +3 -3
  17. package/dist/safe-bash-command-pdfimages/index.js +186 -55
  18. package/dist/safe-bash-command-pdfinfo/index.js +273 -91
  19. package/dist/safe-bash-command-pdftk/index.js +186 -55
  20. package/dist/safe-bash-command-pdftoppm/index.js +273 -91
  21. package/dist/safe-bash-command-pdftotext/index.js +186 -55
  22. package/dist/safe-bash-command-qpdf/index.js +186 -55
  23. package/dist/safe-bash-command-sips/index.js +2 -2
  24. package/dist/safe-bash-command-soffice/index.js +1 -1
  25. package/dist/safe-bash-command-ssconvert/index.js +249 -58
  26. package/dist/safe-bash-command-wkhtmltopdf/index.js +186 -55
  27. package/package.json +2 -2
  28. package/third-party/pdf-ast/THIRD_PARTY_NOTICES.md +13 -0
@@ -35913,14 +35913,18 @@ function evaluateContentStreamToDisplayList(params) {
35913
35913
  const paths = [];
35914
35914
  const images = [];
35915
35915
  const operations = [];
35916
+ let capturedOperations;
35917
+ let insideSoftMask = false;
35916
35918
  const emit = (operation) => {
35917
- const { clipPaths, clipImages } = curState();
35918
- if (clipPaths || clipImages) operation = { ...operation, value: {
35919
+ const { clipPaths, clipImages, softMask } = curState();
35920
+ if (clipPaths || clipImages || softMask) operation = { ...operation, value: {
35919
35921
  ...operation.value,
35920
35922
  ...clipPaths ? { clipPaths } : {},
35921
- ...clipImages ? { clipImages } : {}
35923
+ ...clipImages ? { clipImages } : {},
35924
+ ...softMask ? { softMask } : {}
35922
35925
  } };
35923
- operations.push(operation);
35926
+ (capturedOperations ?? operations).push(operation);
35927
+ if (insideSoftMask) return;
35924
35928
  switch (operation.kind) {
35925
35929
  case "path":
35926
35930
  paths.push(operation.value);
@@ -36026,7 +36030,7 @@ function evaluateContentStreamToDisplayList(params) {
36026
36030
  );
36027
36031
  return { r: kClamp(r), g: kClamp(g), b: kClamp(b) };
36028
36032
  };
36029
- const applyStateOperator = (st, operator, ops, activeResources) => {
36033
+ const applyStateOperator = (st, operator, ops, activeResources, activeFonts, depth) => {
36030
36034
  const num = (i, fb = 0) => ops[i]?.kind === "number" ? ops[i].value : fb;
36031
36035
  if (operator === "cm") {
36032
36036
  const m = [num(0, 1), num(1, 0), num(2, 0), num(3, 1), num(4, 0), num(5, 0)];
@@ -36109,6 +36113,46 @@ function evaluateContentStreamToDisplayList(params) {
36109
36113
  const extDict = params.cosDoc.resolveDict(dictGet(activeResources, "ExtGState"));
36110
36114
  const gsDict = extDict ? params.cosDoc.resolveDict(dictGet(extDict, ops[0].decoded)) : void 0;
36111
36115
  if (gsDict) {
36116
+ const mask = params.cosDoc.resolve(dictGet(gsDict, "SMask"));
36117
+ if (mask?.kind === "name" && mask.decoded === "None") {
36118
+ st.softMask = void 0;
36119
+ } else if (mask?.kind === "dict") {
36120
+ const subtype = params.cosDoc.resolve(dictGet(mask, "S"));
36121
+ const form = params.cosDoc.resolve(dictGet(mask, "G"));
36122
+ if (form?.kind === "stream" && subtype?.kind === "name" && (subtype.decoded === "Alpha" || subtype.decoded === "Luminosity")) {
36123
+ if (depth >= 8) throw new PdfError("E_LIMIT", "Soft-mask nesting exceeds the form depth limit");
36124
+ const parentOperations = capturedOperations;
36125
+ const parentInsideSoftMask = insideSoftMask;
36126
+ const savedTextState = { pendingTextClip, hasTextClip, activeTm, activeTlm };
36127
+ const captured = [];
36128
+ capturedOperations = captured;
36129
+ insideSoftMask = true;
36130
+ const maskState = { ...st, softMask: void 0, fillAlpha: 1, strokeAlpha: 1, blendMode: "Normal" };
36131
+ delete maskState.clipPaths;
36132
+ delete maskState.clipImages;
36133
+ delete maskState.clipRect;
36134
+ stateStack.push(maskState);
36135
+ try {
36136
+ paintForm(form, activeResources, activeFonts, depth, void 0, void 0, true);
36137
+ } finally {
36138
+ stateStack.pop();
36139
+ capturedOperations = parentOperations;
36140
+ insideSoftMask = parentInsideSoftMask;
36141
+ ({ pendingTextClip, hasTextClip, activeTm, activeTlm } = savedTextState);
36142
+ }
36143
+ const group = params.cosDoc.resolveDict(dictGet(form.dict, "Group"));
36144
+ const colorSpace = group ? dictGet(group, "CS") : void 0;
36145
+ const bc = params.cosDoc.resolveArray(dictGet(mask, "BC"));
36146
+ const components = bc?.items.map((item) => {
36147
+ const value = params.cosDoc.resolve(item);
36148
+ return value?.kind === "number" ? value.value : 0;
36149
+ });
36150
+ const [r, g, b] = components ? convertColorSpaceComponentsToRgb(params.cosDoc, colorSpace, "DeviceRGB", components, activeResources) : [0, 0, 0];
36151
+ const transfer = params.cosDoc.resolve(dictGet(mask, "TR"));
36152
+ const transferMap = transfer?.kind === "dict" || transfer?.kind === "stream" ? Uint8Array.from({ length: 256 }, (_, i) => Math.floor(kClamp(Math.fround(evalShadingFunctionToComponents(params.cosDoc, transfer, Math.fround(i / 255))[0] ?? 0)) * 255)) : void 0;
36153
+ st.softMask = { subtype: subtype.decoded, operations: captured, backdrop: { r, g, b }, transferMap };
36154
+ }
36155
+ }
36112
36156
  const bmNode = params.cosDoc.resolve(dictGet(gsDict, "BM"));
36113
36157
  if (bmNode?.kind === "name") {
36114
36158
  st.blendMode = bmNode.decoded === "Compatible" ? "Normal" : bmNode.decoded;
@@ -36195,6 +36239,84 @@ function evaluateContentStreamToDisplayList(params) {
36195
36239
  ] }], void 0, void 0, resources, activeFonts, depth);
36196
36240
  stateStack.pop();
36197
36241
  };
36242
+ const paintForm = (form, activeResources, activeFonts, depth, mcid, actualText, maskGroup = false) => {
36243
+ const st = curState();
36244
+ const group = params.cosDoc.resolveDict(dictGet(form.dict, "Group"));
36245
+ const groupType = group ? params.cosDoc.resolve(dictGet(group, "S")) : void 0;
36246
+ const isolated = group ? params.cosDoc.resolve(dictGet(group, "I")) : void 0;
36247
+ const isolate = !maskGroup && groupType?.kind === "name" && groupType.decoded === "Transparency" && isolated?.kind === "boolean" && isolated.value;
36248
+ const formStreamBytes = params.cosDoc.decodeStream(form);
36249
+ const formNodes = parseContentStream(formStreamBytes);
36250
+ const formResDict = params.cosDoc.resolveDict(dictGet(form.dict, "Resources")) ?? activeResources;
36251
+ const formFonts = new Map(activeFonts);
36252
+ for (const [k, v] of resolvePageFonts(params.cosDoc, formResDict).entries()) {
36253
+ formFonts.set(k, v);
36254
+ }
36255
+ let nextCtm = [...st.ctm];
36256
+ const matArr = params.cosDoc.resolveArray(dictGet(form.dict, "Matrix"));
36257
+ if (matArr && matArr.items.length >= 6) {
36258
+ const mn = (idx, fb = 0) => {
36259
+ const resolved = params.cosDoc.resolve(matArr.items[idx]);
36260
+ return resolved?.kind === "number" ? resolved.value : fb;
36261
+ };
36262
+ const formMat = [mn(0, 1), mn(1, 0), mn(2, 0), mn(3, 1), mn(4, 0), mn(5, 0)];
36263
+ nextCtm = multiplyMatrices(formMat, nextCtm);
36264
+ }
36265
+ let nextClip = !isolate && st.clipRect ? [...st.clipRect] : void 0;
36266
+ let nextClipPaths = isolate ? void 0 : st.clipPaths;
36267
+ const bboxArr = params.cosDoc.resolveArray(dictGet(form.dict, "BBox"));
36268
+ if (bboxArr && bboxArr.items.length >= 4) {
36269
+ const bn = (idx, fb = 0) => {
36270
+ const resolved = params.cosDoc.resolve(bboxArr.items[idx]);
36271
+ return resolved?.kind === "number" ? resolved.value : fb;
36272
+ };
36273
+ const bx0 = bn(0, 0), by0 = bn(1, 0), bx1 = bn(2, 0), by1 = bn(3, 0);
36274
+ const pts = [
36275
+ transformPoint(nextCtm, bx0, by0),
36276
+ transformPoint(nextCtm, bx1, by0),
36277
+ transformPoint(nextCtm, bx1, by1),
36278
+ transformPoint(nextCtm, bx0, by1)
36279
+ ];
36280
+ nextClipPaths = [...nextClipPaths ?? [], [
36281
+ ...pts.map(([x, y], index) => ({ kind: index === 0 ? "move" : "line", x, y })),
36282
+ { kind: "close" }
36283
+ ]];
36284
+ const fMinX = Math.min(...pts.map((p) => p[0]));
36285
+ const fMinY = Math.min(...pts.map((p) => p[1]));
36286
+ const fMaxX = Math.max(...pts.map((p) => p[0]));
36287
+ const fMaxY = Math.max(...pts.map((p) => p[1]));
36288
+ if (fMaxX > fMinX && fMaxY > fMinY) {
36289
+ nextClip = nextClip ? [
36290
+ Math.max(nextClip[0], fMinX),
36291
+ Math.max(nextClip[1], fMinY),
36292
+ Math.min(nextClip[2], fMaxX),
36293
+ Math.min(nextClip[3], fMaxY)
36294
+ ] : [fMinX, fMinY, fMaxX, fMaxY];
36295
+ }
36296
+ }
36297
+ const parentOperations = capturedOperations;
36298
+ const children = [];
36299
+ const nextState = { ...st, ctm: nextCtm };
36300
+ if (isolate) {
36301
+ capturedOperations = children;
36302
+ nextState.fillAlpha = nextState.strokeAlpha = 1;
36303
+ nextState.blendMode = "Normal";
36304
+ nextState.softMask = void 0;
36305
+ delete nextState.clipImages;
36306
+ delete nextState.clipPaths;
36307
+ delete nextState.clipRect;
36308
+ }
36309
+ if (nextClip) nextState.clipRect = nextClip;
36310
+ if (nextClipPaths) nextState.clipPaths = nextClipPaths;
36311
+ stateStack.push(nextState);
36312
+ try {
36313
+ walkNodes(formNodes, mcid, actualText, formResDict, formFonts, depth + 1);
36314
+ } finally {
36315
+ stateStack.pop();
36316
+ capturedOperations = parentOperations;
36317
+ }
36318
+ if (isolate) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
36319
+ };
36198
36320
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
36199
36321
  for (const node of nodes) {
36200
36322
  switch (node.kind) {
@@ -36239,7 +36361,7 @@ function evaluateContentStreamToDisplayList(params) {
36239
36361
  break;
36240
36362
  }
36241
36363
  case "state-op": {
36242
- applyStateOperator(curState(), node.operator, node.operands, activeResources);
36364
+ applyStateOperator(curState(), node.operator, node.operands, activeResources, activeFonts, depth);
36243
36365
  break;
36244
36366
  }
36245
36367
  case "path-op": {
@@ -36525,53 +36647,7 @@ function evaluateContentStreamToDisplayList(params) {
36525
36647
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
36526
36648
  }, patternMask, activeResources, activeFonts, depth);
36527
36649
  } else if (sub === "Form" && depth < 8) {
36528
- const formStreamBytes = params.cosDoc.decodeStream(xobjNode);
36529
- const formNodes = parseContentStream(formStreamBytes);
36530
- const formResDict = params.cosDoc.resolveDict(dictGet(xobjNode.dict, "Resources")) ?? activeResources;
36531
- const formFonts = new Map(activeFonts);
36532
- for (const [k, v] of resolvePageFonts(params.cosDoc, formResDict).entries()) {
36533
- formFonts.set(k, v);
36534
- }
36535
- let nextCtm = [...st.ctm];
36536
- const matArr = params.cosDoc.resolveArray(dictGet(xobjNode.dict, "Matrix"));
36537
- if (matArr && matArr.items.length >= 6) {
36538
- const mn = (idx, fb = 0) => {
36539
- const resolved = params.cosDoc.resolve(matArr.items[idx]);
36540
- return resolved?.kind === "number" ? resolved.value : fb;
36541
- };
36542
- const formMat = [mn(0, 1), mn(1, 0), mn(2, 0), mn(3, 1), mn(4, 0), mn(5, 0)];
36543
- nextCtm = multiplyMatrices(formMat, nextCtm);
36544
- }
36545
- let nextClip = st.clipRect ? [...st.clipRect] : void 0;
36546
- const bboxArr = params.cosDoc.resolveArray(dictGet(xobjNode.dict, "BBox"));
36547
- if (bboxArr && bboxArr.items.length >= 4) {
36548
- const bn = (idx, fb = 0) => {
36549
- const resolved = params.cosDoc.resolve(bboxArr.items[idx]);
36550
- return resolved?.kind === "number" ? resolved.value : fb;
36551
- };
36552
- const bx0 = bn(0, 0), by0 = bn(1, 0), bx1 = bn(2, 0), by1 = bn(3, 0);
36553
- const pts = [
36554
- transformPoint(nextCtm, bx0, by0),
36555
- transformPoint(nextCtm, bx1, by0),
36556
- transformPoint(nextCtm, bx0, by1),
36557
- transformPoint(nextCtm, bx1, by1)
36558
- ];
36559
- const fMinX = Math.min(...pts.map((p) => p[0]));
36560
- const fMinY = Math.min(...pts.map((p) => p[1]));
36561
- const fMaxX = Math.max(...pts.map((p) => p[0]));
36562
- const fMaxY = Math.max(...pts.map((p) => p[1]));
36563
- if (fMaxX > fMinX && fMaxY > fMinY) {
36564
- nextClip = nextClip ? [
36565
- Math.max(nextClip[0], fMinX),
36566
- Math.max(nextClip[1], fMinY),
36567
- Math.min(nextClip[2], fMaxX),
36568
- Math.min(nextClip[3], fMaxY)
36569
- ] : [fMinX, fMinY, fMaxX, fMaxY];
36570
- }
36571
- }
36572
- stateStack.push({ ...st, ctm: nextCtm, ...nextClip ? { clipRect: nextClip } : {} });
36573
- walkNodes(formNodes, mcid, actualText, formResDict, formFonts, depth + 1);
36574
- if (stateStack.length > 1) stateStack.pop();
36650
+ paintForm(xobjNode, activeResources, activeFonts, depth, mcid, actualText);
36575
36651
  }
36576
36652
  }
36577
36653
  }
@@ -36790,7 +36866,7 @@ function evaluateContentStreamToDisplayList(params) {
36790
36866
  st.textRenderMode = cmd.mode;
36791
36867
  break;
36792
36868
  case "state-op":
36793
- applyStateOperator(st, cmd.operator, cmd.operands, activeResources);
36869
+ applyStateOperator(st, cmd.operator, cmd.operands, activeResources, activeFonts, depth);
36794
36870
  break;
36795
36871
  case "show-text":
36796
36872
  emitTokenBytes(cmd.token.bytes);
@@ -40230,6 +40306,30 @@ function paintOperations(displayList) {
40230
40306
  ...displayList.glyphs.map((value) => ({ kind: "glyph", value }))
40231
40307
  ];
40232
40308
  }
40309
+ function renderSoftMask(mask, displayList, scale) {
40310
+ const bitmap = renderDisplayListToBitmap({
40311
+ ...displayList,
40312
+ rotation: 0,
40313
+ glyphs: [],
40314
+ paths: [],
40315
+ images: [],
40316
+ operations: mask.operations
40317
+ }, { scale, transparent: true });
40318
+ const { data } = bitmap;
40319
+ for (let i = 0; i < data.length; i += 4) {
40320
+ let value = data[i + 3];
40321
+ if (mask.subtype === "Luminosity") {
40322
+ const alpha = value / 255;
40323
+ const r = Math.round(data[i] * alpha + mask.backdrop.r * 255 * (1 - alpha));
40324
+ const g = Math.round(data[i + 1] * alpha + mask.backdrop.g * 255 * (1 - alpha));
40325
+ const b = Math.round(data[i + 2] * alpha + mask.backdrop.b * 255 * (1 - alpha));
40326
+ value = Math.round(pdfLum(r, g, b));
40327
+ }
40328
+ data[i] = data[i + 1] = data[i + 2] = 0;
40329
+ data[i + 3] = mask.transferMap?.[value] ?? value;
40330
+ }
40331
+ return bitmap;
40332
+ }
40233
40333
  function renderDisplayListToBitmap(displayList, options = {}) {
40234
40334
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
40235
40335
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
@@ -40253,10 +40353,28 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40253
40353
  const aaTxt = options.antialiasText !== false;
40254
40354
  let cachedClips;
40255
40355
  let cachedClipMask;
40356
+ let cachedSoftMask;
40357
+ let cachedSoftMaskPixels;
40256
40358
  const imageClipMasks = /* @__PURE__ */ new Map();
40257
40359
  for (const original of paintOperations(displayList)) {
40258
40360
  if (original.kind === "glyph" && (original.value.renderMode === 3 || !original.value.outline && !original.value.unicode.trim())) continue;
40259
- const operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
40361
+ let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
40362
+ if (operation.kind === "group") {
40363
+ const group = operation.value;
40364
+ const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations: group.operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, transparent: true });
40365
+ for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
40366
+ operation = { kind: "image", value: {
40367
+ name: "TransparencyGroup",
40368
+ width: bitmap.width,
40369
+ height: bitmap.height,
40370
+ decodedRgba: bitmap.data,
40371
+ matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, 0, displayList.height - bitmap.height / scale],
40372
+ colorSpace: "DeviceRGB",
40373
+ bitsPerComponent: 8,
40374
+ blendMode: group.blendMode,
40375
+ clipRect: group.clipRect
40376
+ } };
40377
+ }
40260
40378
  const clips = original.value.clipPaths;
40261
40379
  let clipMask = clips && clips === cachedClips ? cachedClipMask : void 0;
40262
40380
  if (clips && !clipMask) {
@@ -40270,6 +40388,19 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40270
40388
  cachedClips = clips;
40271
40389
  cachedClipMask = clipMask;
40272
40390
  }
40391
+ const softMask = original.value.softMask;
40392
+ if (softMask) {
40393
+ if (softMask !== cachedSoftMask) {
40394
+ cachedSoftMaskPixels = renderSoftMask(softMask, displayList, scale).data;
40395
+ cachedSoftMask = softMask;
40396
+ }
40397
+ if (clipMask) {
40398
+ clipMask = clipMask.slice();
40399
+ for (let i = 3; i < clipMask.length; i += 4) clipMask[i] = Math.round(clipMask[i] * cachedSoftMaskPixels[i] / 255);
40400
+ } else {
40401
+ clipMask = cachedSoftMaskPixels;
40402
+ }
40403
+ }
40273
40404
  const imageClips = original.value.clipImages;
40274
40405
  if (imageClips) {
40275
40406
  let imageMask = imageClipMasks.get(imageClips);
@@ -35568,14 +35568,18 @@ function evaluateContentStreamToDisplayList(params) {
35568
35568
  const paths = [];
35569
35569
  const images = [];
35570
35570
  const operations = [];
35571
+ let capturedOperations;
35572
+ let insideSoftMask = false;
35571
35573
  const emit = (operation) => {
35572
- const { clipPaths, clipImages } = curState();
35573
- if (clipPaths || clipImages) operation = { ...operation, value: {
35574
+ const { clipPaths, clipImages, softMask } = curState();
35575
+ if (clipPaths || clipImages || softMask) operation = { ...operation, value: {
35574
35576
  ...operation.value,
35575
35577
  ...clipPaths ? { clipPaths } : {},
35576
- ...clipImages ? { clipImages } : {}
35578
+ ...clipImages ? { clipImages } : {},
35579
+ ...softMask ? { softMask } : {}
35577
35580
  } };
35578
- operations.push(operation);
35581
+ (capturedOperations ?? operations).push(operation);
35582
+ if (insideSoftMask) return;
35579
35583
  switch (operation.kind) {
35580
35584
  case "path":
35581
35585
  paths.push(operation.value);
@@ -35681,7 +35685,7 @@ function evaluateContentStreamToDisplayList(params) {
35681
35685
  );
35682
35686
  return { r: kClamp(r), g: kClamp(g), b: kClamp(b) };
35683
35687
  };
35684
- const applyStateOperator = (st, operator, ops, activeResources) => {
35688
+ const applyStateOperator = (st, operator, ops, activeResources, activeFonts, depth) => {
35685
35689
  const num = (i, fb = 0) => ops[i]?.kind === "number" ? ops[i].value : fb;
35686
35690
  if (operator === "cm") {
35687
35691
  const m = [num(0, 1), num(1, 0), num(2, 0), num(3, 1), num(4, 0), num(5, 0)];
@@ -35764,6 +35768,46 @@ function evaluateContentStreamToDisplayList(params) {
35764
35768
  const extDict = params.cosDoc.resolveDict(dictGet(activeResources, "ExtGState"));
35765
35769
  const gsDict = extDict ? params.cosDoc.resolveDict(dictGet(extDict, ops[0].decoded)) : void 0;
35766
35770
  if (gsDict) {
35771
+ const mask = params.cosDoc.resolve(dictGet(gsDict, "SMask"));
35772
+ if (mask?.kind === "name" && mask.decoded === "None") {
35773
+ st.softMask = void 0;
35774
+ } else if (mask?.kind === "dict") {
35775
+ const subtype = params.cosDoc.resolve(dictGet(mask, "S"));
35776
+ const form = params.cosDoc.resolve(dictGet(mask, "G"));
35777
+ if (form?.kind === "stream" && subtype?.kind === "name" && (subtype.decoded === "Alpha" || subtype.decoded === "Luminosity")) {
35778
+ if (depth >= 8) throw new PdfError("E_LIMIT", "Soft-mask nesting exceeds the form depth limit");
35779
+ const parentOperations = capturedOperations;
35780
+ const parentInsideSoftMask = insideSoftMask;
35781
+ const savedTextState = { pendingTextClip, hasTextClip, activeTm, activeTlm };
35782
+ const captured = [];
35783
+ capturedOperations = captured;
35784
+ insideSoftMask = true;
35785
+ const maskState = { ...st, softMask: void 0, fillAlpha: 1, strokeAlpha: 1, blendMode: "Normal" };
35786
+ delete maskState.clipPaths;
35787
+ delete maskState.clipImages;
35788
+ delete maskState.clipRect;
35789
+ stateStack.push(maskState);
35790
+ try {
35791
+ paintForm(form, activeResources, activeFonts, depth, void 0, void 0, true);
35792
+ } finally {
35793
+ stateStack.pop();
35794
+ capturedOperations = parentOperations;
35795
+ insideSoftMask = parentInsideSoftMask;
35796
+ ({ pendingTextClip, hasTextClip, activeTm, activeTlm } = savedTextState);
35797
+ }
35798
+ const group = params.cosDoc.resolveDict(dictGet(form.dict, "Group"));
35799
+ const colorSpace = group ? dictGet(group, "CS") : void 0;
35800
+ const bc = params.cosDoc.resolveArray(dictGet(mask, "BC"));
35801
+ const components = bc?.items.map((item) => {
35802
+ const value = params.cosDoc.resolve(item);
35803
+ return value?.kind === "number" ? value.value : 0;
35804
+ });
35805
+ const [r, g, b] = components ? convertColorSpaceComponentsToRgb(params.cosDoc, colorSpace, "DeviceRGB", components, activeResources) : [0, 0, 0];
35806
+ const transfer = params.cosDoc.resolve(dictGet(mask, "TR"));
35807
+ const transferMap = transfer?.kind === "dict" || transfer?.kind === "stream" ? Uint8Array.from({ length: 256 }, (_, i) => Math.floor(kClamp(Math.fround(evalShadingFunctionToComponents(params.cosDoc, transfer, Math.fround(i / 255))[0] ?? 0)) * 255)) : void 0;
35808
+ st.softMask = { subtype: subtype.decoded, operations: captured, backdrop: { r, g, b }, transferMap };
35809
+ }
35810
+ }
35767
35811
  const bmNode = params.cosDoc.resolve(dictGet(gsDict, "BM"));
35768
35812
  if (bmNode?.kind === "name") {
35769
35813
  st.blendMode = bmNode.decoded === "Compatible" ? "Normal" : bmNode.decoded;
@@ -35850,6 +35894,84 @@ function evaluateContentStreamToDisplayList(params) {
35850
35894
  ] }], void 0, void 0, resources, activeFonts, depth);
35851
35895
  stateStack.pop();
35852
35896
  };
35897
+ const paintForm = (form, activeResources, activeFonts, depth, mcid, actualText, maskGroup = false) => {
35898
+ const st = curState();
35899
+ const group = params.cosDoc.resolveDict(dictGet(form.dict, "Group"));
35900
+ const groupType = group ? params.cosDoc.resolve(dictGet(group, "S")) : void 0;
35901
+ const isolated = group ? params.cosDoc.resolve(dictGet(group, "I")) : void 0;
35902
+ const isolate = !maskGroup && groupType?.kind === "name" && groupType.decoded === "Transparency" && isolated?.kind === "boolean" && isolated.value;
35903
+ const formStreamBytes = params.cosDoc.decodeStream(form);
35904
+ const formNodes = parseContentStream(formStreamBytes);
35905
+ const formResDict = params.cosDoc.resolveDict(dictGet(form.dict, "Resources")) ?? activeResources;
35906
+ const formFonts = new Map(activeFonts);
35907
+ for (const [k, v] of resolvePageFonts(params.cosDoc, formResDict).entries()) {
35908
+ formFonts.set(k, v);
35909
+ }
35910
+ let nextCtm = [...st.ctm];
35911
+ const matArr = params.cosDoc.resolveArray(dictGet(form.dict, "Matrix"));
35912
+ if (matArr && matArr.items.length >= 6) {
35913
+ const mn = (idx, fb = 0) => {
35914
+ const resolved = params.cosDoc.resolve(matArr.items[idx]);
35915
+ return resolved?.kind === "number" ? resolved.value : fb;
35916
+ };
35917
+ const formMat = [mn(0, 1), mn(1, 0), mn(2, 0), mn(3, 1), mn(4, 0), mn(5, 0)];
35918
+ nextCtm = multiplyMatrices(formMat, nextCtm);
35919
+ }
35920
+ let nextClip = !isolate && st.clipRect ? [...st.clipRect] : void 0;
35921
+ let nextClipPaths = isolate ? void 0 : st.clipPaths;
35922
+ const bboxArr = params.cosDoc.resolveArray(dictGet(form.dict, "BBox"));
35923
+ if (bboxArr && bboxArr.items.length >= 4) {
35924
+ const bn = (idx, fb = 0) => {
35925
+ const resolved = params.cosDoc.resolve(bboxArr.items[idx]);
35926
+ return resolved?.kind === "number" ? resolved.value : fb;
35927
+ };
35928
+ const bx0 = bn(0, 0), by0 = bn(1, 0), bx1 = bn(2, 0), by1 = bn(3, 0);
35929
+ const pts = [
35930
+ transformPoint(nextCtm, bx0, by0),
35931
+ transformPoint(nextCtm, bx1, by0),
35932
+ transformPoint(nextCtm, bx1, by1),
35933
+ transformPoint(nextCtm, bx0, by1)
35934
+ ];
35935
+ nextClipPaths = [...nextClipPaths ?? [], [
35936
+ ...pts.map(([x, y], index) => ({ kind: index === 0 ? "move" : "line", x, y })),
35937
+ { kind: "close" }
35938
+ ]];
35939
+ const fMinX = Math.min(...pts.map((p) => p[0]));
35940
+ const fMinY = Math.min(...pts.map((p) => p[1]));
35941
+ const fMaxX = Math.max(...pts.map((p) => p[0]));
35942
+ const fMaxY = Math.max(...pts.map((p) => p[1]));
35943
+ if (fMaxX > fMinX && fMaxY > fMinY) {
35944
+ nextClip = nextClip ? [
35945
+ Math.max(nextClip[0], fMinX),
35946
+ Math.max(nextClip[1], fMinY),
35947
+ Math.min(nextClip[2], fMaxX),
35948
+ Math.min(nextClip[3], fMaxY)
35949
+ ] : [fMinX, fMinY, fMaxX, fMaxY];
35950
+ }
35951
+ }
35952
+ const parentOperations = capturedOperations;
35953
+ const children = [];
35954
+ const nextState = { ...st, ctm: nextCtm };
35955
+ if (isolate) {
35956
+ capturedOperations = children;
35957
+ nextState.fillAlpha = nextState.strokeAlpha = 1;
35958
+ nextState.blendMode = "Normal";
35959
+ nextState.softMask = void 0;
35960
+ delete nextState.clipImages;
35961
+ delete nextState.clipPaths;
35962
+ delete nextState.clipRect;
35963
+ }
35964
+ if (nextClip) nextState.clipRect = nextClip;
35965
+ if (nextClipPaths) nextState.clipPaths = nextClipPaths;
35966
+ stateStack.push(nextState);
35967
+ try {
35968
+ walkNodes(formNodes, mcid, actualText, formResDict, formFonts, depth + 1);
35969
+ } finally {
35970
+ stateStack.pop();
35971
+ capturedOperations = parentOperations;
35972
+ }
35973
+ if (isolate) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
35974
+ };
35853
35975
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
35854
35976
  for (const node of nodes) {
35855
35977
  switch (node.kind) {
@@ -35894,7 +36016,7 @@ function evaluateContentStreamToDisplayList(params) {
35894
36016
  break;
35895
36017
  }
35896
36018
  case "state-op": {
35897
- applyStateOperator(curState(), node.operator, node.operands, activeResources);
36019
+ applyStateOperator(curState(), node.operator, node.operands, activeResources, activeFonts, depth);
35898
36020
  break;
35899
36021
  }
35900
36022
  case "path-op": {
@@ -36180,53 +36302,7 @@ function evaluateContentStreamToDisplayList(params) {
36180
36302
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
36181
36303
  }, patternMask, activeResources, activeFonts, depth);
36182
36304
  } else if (sub === "Form" && depth < 8) {
36183
- const formStreamBytes = params.cosDoc.decodeStream(xobjNode);
36184
- const formNodes = parseContentStream(formStreamBytes);
36185
- const formResDict = params.cosDoc.resolveDict(dictGet(xobjNode.dict, "Resources")) ?? activeResources;
36186
- const formFonts = new Map(activeFonts);
36187
- for (const [k, v] of resolvePageFonts(params.cosDoc, formResDict).entries()) {
36188
- formFonts.set(k, v);
36189
- }
36190
- let nextCtm = [...st.ctm];
36191
- const matArr = params.cosDoc.resolveArray(dictGet(xobjNode.dict, "Matrix"));
36192
- if (matArr && matArr.items.length >= 6) {
36193
- const mn = (idx, fb = 0) => {
36194
- const resolved = params.cosDoc.resolve(matArr.items[idx]);
36195
- return resolved?.kind === "number" ? resolved.value : fb;
36196
- };
36197
- const formMat = [mn(0, 1), mn(1, 0), mn(2, 0), mn(3, 1), mn(4, 0), mn(5, 0)];
36198
- nextCtm = multiplyMatrices(formMat, nextCtm);
36199
- }
36200
- let nextClip = st.clipRect ? [...st.clipRect] : void 0;
36201
- const bboxArr = params.cosDoc.resolveArray(dictGet(xobjNode.dict, "BBox"));
36202
- if (bboxArr && bboxArr.items.length >= 4) {
36203
- const bn = (idx, fb = 0) => {
36204
- const resolved = params.cosDoc.resolve(bboxArr.items[idx]);
36205
- return resolved?.kind === "number" ? resolved.value : fb;
36206
- };
36207
- const bx0 = bn(0, 0), by0 = bn(1, 0), bx1 = bn(2, 0), by1 = bn(3, 0);
36208
- const pts = [
36209
- transformPoint(nextCtm, bx0, by0),
36210
- transformPoint(nextCtm, bx1, by0),
36211
- transformPoint(nextCtm, bx0, by1),
36212
- transformPoint(nextCtm, bx1, by1)
36213
- ];
36214
- const fMinX = Math.min(...pts.map((p) => p[0]));
36215
- const fMinY = Math.min(...pts.map((p) => p[1]));
36216
- const fMaxX = Math.max(...pts.map((p) => p[0]));
36217
- const fMaxY = Math.max(...pts.map((p) => p[1]));
36218
- if (fMaxX > fMinX && fMaxY > fMinY) {
36219
- nextClip = nextClip ? [
36220
- Math.max(nextClip[0], fMinX),
36221
- Math.max(nextClip[1], fMinY),
36222
- Math.min(nextClip[2], fMaxX),
36223
- Math.min(nextClip[3], fMaxY)
36224
- ] : [fMinX, fMinY, fMaxX, fMaxY];
36225
- }
36226
- }
36227
- stateStack.push({ ...st, ctm: nextCtm, ...nextClip ? { clipRect: nextClip } : {} });
36228
- walkNodes(formNodes, mcid, actualText, formResDict, formFonts, depth + 1);
36229
- if (stateStack.length > 1) stateStack.pop();
36305
+ paintForm(xobjNode, activeResources, activeFonts, depth, mcid, actualText);
36230
36306
  }
36231
36307
  }
36232
36308
  }
@@ -36445,7 +36521,7 @@ function evaluateContentStreamToDisplayList(params) {
36445
36521
  st.textRenderMode = cmd.mode;
36446
36522
  break;
36447
36523
  case "state-op":
36448
- applyStateOperator(st, cmd.operator, cmd.operands, activeResources);
36524
+ applyStateOperator(st, cmd.operator, cmd.operands, activeResources, activeFonts, depth);
36449
36525
  break;
36450
36526
  case "show-text":
36451
36527
  emitTokenBytes(cmd.token.bytes);
@@ -39768,6 +39844,30 @@ function paintOperations(displayList) {
39768
39844
  ...displayList.glyphs.map((value) => ({ kind: "glyph", value }))
39769
39845
  ];
39770
39846
  }
39847
+ function renderSoftMask(mask, displayList, scale) {
39848
+ const bitmap = renderDisplayListToBitmap({
39849
+ ...displayList,
39850
+ rotation: 0,
39851
+ glyphs: [],
39852
+ paths: [],
39853
+ images: [],
39854
+ operations: mask.operations
39855
+ }, { scale, transparent: true });
39856
+ const { data } = bitmap;
39857
+ for (let i = 0; i < data.length; i += 4) {
39858
+ let value = data[i + 3];
39859
+ if (mask.subtype === "Luminosity") {
39860
+ const alpha = value / 255;
39861
+ const r = Math.round(data[i] * alpha + mask.backdrop.r * 255 * (1 - alpha));
39862
+ const g = Math.round(data[i + 1] * alpha + mask.backdrop.g * 255 * (1 - alpha));
39863
+ const b = Math.round(data[i + 2] * alpha + mask.backdrop.b * 255 * (1 - alpha));
39864
+ value = Math.round(pdfLum(r, g, b));
39865
+ }
39866
+ data[i] = data[i + 1] = data[i + 2] = 0;
39867
+ data[i + 3] = mask.transferMap?.[value] ?? value;
39868
+ }
39869
+ return bitmap;
39870
+ }
39771
39871
  function renderDisplayListToBitmap(displayList, options = {}) {
39772
39872
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
39773
39873
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
@@ -39791,10 +39891,28 @@ function renderDisplayListToBitmap(displayList, options = {}) {
39791
39891
  const aaTxt = options.antialiasText !== false;
39792
39892
  let cachedClips;
39793
39893
  let cachedClipMask;
39894
+ let cachedSoftMask;
39895
+ let cachedSoftMaskPixels;
39794
39896
  const imageClipMasks = /* @__PURE__ */ new Map();
39795
39897
  for (const original of paintOperations(displayList)) {
39796
39898
  if (original.kind === "glyph" && (original.value.renderMode === 3 || !original.value.outline && !original.value.unicode.trim())) continue;
39797
- const operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
39899
+ let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
39900
+ if (operation.kind === "group") {
39901
+ const group = operation.value;
39902
+ const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations: group.operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, transparent: true });
39903
+ for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
39904
+ operation = { kind: "image", value: {
39905
+ name: "TransparencyGroup",
39906
+ width: bitmap.width,
39907
+ height: bitmap.height,
39908
+ decodedRgba: bitmap.data,
39909
+ matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, 0, displayList.height - bitmap.height / scale],
39910
+ colorSpace: "DeviceRGB",
39911
+ bitsPerComponent: 8,
39912
+ blendMode: group.blendMode,
39913
+ clipRect: group.clipRect
39914
+ } };
39915
+ }
39798
39916
  const clips = original.value.clipPaths;
39799
39917
  let clipMask = clips && clips === cachedClips ? cachedClipMask : void 0;
39800
39918
  if (clips && !clipMask) {
@@ -39808,6 +39926,19 @@ function renderDisplayListToBitmap(displayList, options = {}) {
39808
39926
  cachedClips = clips;
39809
39927
  cachedClipMask = clipMask;
39810
39928
  }
39929
+ const softMask = original.value.softMask;
39930
+ if (softMask) {
39931
+ if (softMask !== cachedSoftMask) {
39932
+ cachedSoftMaskPixels = renderSoftMask(softMask, displayList, scale).data;
39933
+ cachedSoftMask = softMask;
39934
+ }
39935
+ if (clipMask) {
39936
+ clipMask = clipMask.slice();
39937
+ for (let i = 3; i < clipMask.length; i += 4) clipMask[i] = Math.round(clipMask[i] * cachedSoftMaskPixels[i] / 255);
39938
+ } else {
39939
+ clipMask = cachedSoftMaskPixels;
39940
+ }
39941
+ }
39811
39942
  const imageClips = original.value.clipImages;
39812
39943
  if (imageClips) {
39813
39944
  let imageMask = imageClipMasks.get(imageClips);
@@ -11,8 +11,8 @@ import {
11
11
  readImageMetadata,
12
12
  resizeImage,
13
13
  rotateImage
14
- } from "../safe-bash/command-chunks/chunk-F7MJRXQ2.js";
15
- import "../safe-bash/command-chunks/chunk-P3Q2QSCA.js";
14
+ } from "../safe-bash/command-chunks/chunk-S5EX6UP5.js";
15
+ import "../safe-bash/command-chunks/chunk-S3G2B4OX.js";
16
16
  import {
17
17
  init_buffer
18
18
  } from "../safe-bash/command-chunks/chunk-HX3SHTCE.js";
@@ -31,7 +31,7 @@ import {
31
31
  PdfDocument,
32
32
  decodeFlate,
33
33
  rgb
34
- } from "../safe-bash/command-chunks/chunk-P3Q2QSCA.js";
34
+ } from "../safe-bash/command-chunks/chunk-S3G2B4OX.js";
35
35
  import {
36
36
  init_buffer
37
37
  } from "../safe-bash/command-chunks/chunk-HX3SHTCE.js";