@poe-platform/safe-bash 0.1.761 → 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 (32) hide show
  1. package/dist/image-ast/index.browser.js +255 -62
  2. package/dist/image-ast/index.js +255 -62
  3. package/dist/pdf-ast/ast.d.ts +23 -0
  4. package/dist/pdf-ast/index.js +344 -98
  5. package/dist/safe-bash/command-chunks/{chunk-6VX5ZQL5.js → chunk-4XHONGIU.js} +2 -2
  6. package/dist/safe-bash/command-chunks/{chunk-OSMLVM7P.js → chunk-S3G2B4OX.js} +258 -62
  7. package/dist/safe-bash/command-chunks/{chunk-GR725WRX.js → chunk-S5EX6UP5.js} +1 -1
  8. package/dist/safe-bash/commands/csvcut/index.d.ts +1 -1
  9. package/dist/safe-bash/commands/csvcut/index.js +3 -1
  10. package/dist/safe-bash/commands/csvgrep/index.d.ts +1 -1
  11. package/dist/safe-bash/commands/csvgrep/index.js +3 -1
  12. package/dist/safe-bash/core.browser.js +8 -6
  13. package/dist/safe-bash/shell/runtime.js +5 -5
  14. package/dist/safe-bash-checksum-engine/index.d.ts +1 -1
  15. package/dist/safe-bash-checksum-engine/index.js +5 -1
  16. package/dist/safe-bash-command-ffmpeg/index.js +7942 -7853
  17. package/dist/safe-bash-command-gh/index.js +174 -105
  18. package/dist/safe-bash-command-imagemagick/index.js +2 -2
  19. package/dist/safe-bash-command-pandoc/command.js +3 -3
  20. package/dist/safe-bash-command-pandoc/index.js +3 -3
  21. package/dist/safe-bash-command-pdfimages/index.js +255 -62
  22. package/dist/safe-bash-command-pdfinfo/index.js +342 -98
  23. package/dist/safe-bash-command-pdftk/index.js +255 -62
  24. package/dist/safe-bash-command-pdftoppm/index.js +342 -98
  25. package/dist/safe-bash-command-pdftotext/index.js +255 -62
  26. package/dist/safe-bash-command-qpdf/index.js +255 -62
  27. package/dist/safe-bash-command-sips/index.js +2 -2
  28. package/dist/safe-bash-command-soffice/index.js +1 -1
  29. package/dist/safe-bash-command-ssconvert/index.js +318 -65
  30. package/dist/safe-bash-command-wkhtmltopdf/index.js +255 -62
  31. package/package.json +2 -2
  32. package/third-party/pdf-ast/THIRD_PARTY_NOTICES.md +23 -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);
@@ -39053,6 +39129,47 @@ function flattenCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
39053
39129
  points.push([x4, y4]);
39054
39130
  return points;
39055
39131
  }
39132
+ function sampleImageLinear(image, x, y, out) {
39133
+ x = Math.max(0, Math.min(image.width - 1, x));
39134
+ y = Math.max(0, Math.min(image.height - 1, y));
39135
+ const x0 = Math.floor(x), y0 = Math.floor(y);
39136
+ const fx = x - x0, fy = y - y0;
39137
+ out.fill(0);
39138
+ for (let j = 0; j < 2; j++) {
39139
+ for (let i = 0; i < 2; i++) {
39140
+ const offset = (Math.min(image.height - 1, y0 + j) * image.width + Math.min(image.width - 1, x0 + i)) * 4;
39141
+ const alpha = image.data[offset + 3] * (i ? fx : 1 - fx) * (j ? fy : 1 - fy);
39142
+ out[0] = out[0] + image.data[offset] * alpha;
39143
+ out[1] = out[1] + image.data[offset + 1] * alpha;
39144
+ out[2] = out[2] + image.data[offset + 2] * alpha;
39145
+ out[3] = out[3] + alpha;
39146
+ }
39147
+ }
39148
+ if (out[3] > 0) {
39149
+ out[0] = out[0] / out[3];
39150
+ out[1] = out[1] / out[3];
39151
+ out[2] = out[2] / out[3];
39152
+ }
39153
+ }
39154
+ function downscaleImage(image, widthScale, heightScale) {
39155
+ const sample = new Float64Array(4);
39156
+ while (widthScale > 2 && image.width > 1 || heightScale > 2 && image.height > 1) {
39157
+ const width = widthScale > 2 ? Math.ceil(image.width / 2) : image.width;
39158
+ const height = heightScale > 2 ? Math.ceil(image.height / 2) : image.height;
39159
+ const data = new Uint8Array(width * height * 4);
39160
+ for (let y = 0; y < height; y++) {
39161
+ for (let x = 0; x < width; x++) {
39162
+ sampleImageLinear(image, (x + 0.5) * image.width / width - 0.5, (y + 0.5) * image.height / height - 0.5, sample);
39163
+ const offset = (y * width + x) * 4;
39164
+ for (let c = 0; c < 4; c++) data[offset + c] = Math.round(sample[c]);
39165
+ }
39166
+ }
39167
+ widthScale /= image.width / width;
39168
+ heightScale /= image.height / height;
39169
+ image = { width, height, data };
39170
+ }
39171
+ return image;
39172
+ }
39056
39173
  function encodePng(bitmap) {
39057
39174
  return encodeRgbaToPng(bitmap.width, bitmap.height, bitmap.data);
39058
39175
  }
@@ -40189,6 +40306,30 @@ function paintOperations(displayList) {
40189
40306
  ...displayList.glyphs.map((value) => ({ kind: "glyph", value }))
40190
40307
  ];
40191
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
+ }
40192
40333
  function renderDisplayListToBitmap(displayList, options = {}) {
40193
40334
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
40194
40335
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
@@ -40212,10 +40353,28 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40212
40353
  const aaTxt = options.antialiasText !== false;
40213
40354
  let cachedClips;
40214
40355
  let cachedClipMask;
40356
+ let cachedSoftMask;
40357
+ let cachedSoftMaskPixels;
40215
40358
  const imageClipMasks = /* @__PURE__ */ new Map();
40216
40359
  for (const original of paintOperations(displayList)) {
40217
40360
  if (original.kind === "glyph" && (original.value.renderMode === 3 || !original.value.outline && !original.value.unicode.trim())) continue;
40218
- 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
+ }
40219
40378
  const clips = original.value.clipPaths;
40220
40379
  let clipMask = clips && clips === cachedClips ? cachedClipMask : void 0;
40221
40380
  if (clips && !clipMask) {
@@ -40229,6 +40388,19 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40229
40388
  cachedClips = clips;
40230
40389
  cachedClipMask = clipMask;
40231
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
+ }
40232
40404
  const imageClips = original.value.clipImages;
40233
40405
  if (imageClips) {
40234
40406
  let imageMask = imageClipMasks.get(imageClips);
@@ -40332,6 +40504,17 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40332
40504
  const maxPx = Math.min(width - 1, clipMaxPx, Math.ceil(Math.max(...cornersPx)) - 1);
40333
40505
  const minPy = Math.max(0, clipMinPy, Math.floor(Math.min(...cornersPy)));
40334
40506
  const maxPy = Math.min(height - 1, clipMaxPy, Math.ceil(Math.max(...cornersPy)) - 1);
40507
+ if (minPx > maxPx || minPy > maxPy) continue;
40508
+ const source = downscaleImage(
40509
+ { width: img.width, height: img.height, data: img.decodedRgba },
40510
+ Math.hypot(d, c) * img.width / Math.abs(det * scale),
40511
+ Math.hypot(b, a) * img.height / Math.abs(det * scale)
40512
+ );
40513
+ const ax = a * scale / img.width, ay = b * scale / img.width;
40514
+ const bx = c * scale / img.height, by = d * scale / img.height;
40515
+ const s1 = ax * ax + ay * ay, s2 = bx * bx + by * by, cross = ax * bx + ay * by;
40516
+ const smooth = Math.fround((s1 + s2 + Math.hypot(s1 - s2, 2 * cross)) / 2) <= 1;
40517
+ const sample = new Float64Array(4);
40335
40518
  for (let py = minPy; py <= maxPy; py++) {
40336
40519
  const yPdf = displayList.height - (py + 0.5) / scale;
40337
40520
  if (img.clipRect && (yPdf < img.clipRect[1] || yPdf > img.clipRect[3])) continue;
@@ -40343,9 +40526,14 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40343
40526
  const u = (d * dxPdf - c * dyPdf) / det;
40344
40527
  const v = (-b * dxPdf + a * dyPdf) / det;
40345
40528
  if (u < 0 || u > 1 || v < 0 || v > 1) continue;
40346
- const sx = Math.min(img.width - 1, Math.max(0, Math.floor(u * img.width)));
40347
- const sy = Math.min(img.height - 1, Math.max(0, Math.floor((1 - v) * img.height)));
40348
- const sIdx = (sy * img.width + sx) * 4;
40529
+ if (smooth) {
40530
+ sampleImageLinear(source, u * source.width - 0.5, (1 - v) * source.height - 0.5, sample);
40531
+ } else {
40532
+ const sx = Math.min(source.width - 1, Math.max(0, Math.floor(u * source.width)));
40533
+ const sy = Math.min(source.height - 1, Math.max(0, Math.floor((1 - v) * source.height)));
40534
+ const sIdx = (sy * source.width + sx) * 4;
40535
+ for (let c2 = 0; c2 < 4; c2++) sample[c2] = source.data[sIdx + c2];
40536
+ }
40349
40537
  blendPixel(
40350
40538
  rgba,
40351
40539
  width,
@@ -40353,11 +40541,11 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40353
40541
  px,
40354
40542
  py,
40355
40543
  {
40356
- r: img.decodedRgba[sIdx] / 255,
40357
- g: img.decodedRgba[sIdx + 1] / 255,
40358
- b: img.decodedRgba[sIdx + 2] / 255
40544
+ r: sample[0] / 255,
40545
+ g: sample[1] / 255,
40546
+ b: sample[2] / 255
40359
40547
  },
40360
- img.decodedRgba[sIdx + 3] / 255,
40548
+ sample[3] / 255,
40361
40549
  img.blendMode,
40362
40550
  clipMask
40363
40551
  );
@@ -42412,3 +42600,8 @@ export {
42412
42600
  * Adapted from PDFium third_party/agg23/agg_curves.cpp, curve4_div.
42413
42601
  * See THIRD_PARTY_NOTICES.md for the pinned revision and adaptations.
42414
42602
  */
42603
+ /*!
42604
+ * Staged image reduction adapted from Mozilla PDF.js CanvasGraphics._scaleImage.
42605
+ * Copyright 2012 Mozilla Foundation. Licensed under Apache-2.0.
42606
+ * See THIRD_PARTY_NOTICES.md for the source revision and adaptations.
42607
+ */