@poe-platform/safe-bash 0.1.762 → 0.1.764

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 (35) hide show
  1. package/dist/image-ast/index.browser.js +454 -208
  2. package/dist/image-ast/index.js +454 -208
  3. package/dist/pdf-ast/ast.d.ts +23 -0
  4. package/dist/pdf-ast/index.js +543 -244
  5. package/dist/safe-bash/chunks/{chunk-CRQDMBQA.js → chunk-FSH7QRIC.js} +10 -1
  6. package/dist/safe-bash/command-chunks/{chunk-D4GXXV65.js → chunk-B7YLGJRF.js} +2 -2
  7. package/dist/safe-bash/command-chunks/{chunk-P3Q2QSCA.js → chunk-G3IIEU2N.js} +457 -208
  8. package/dist/safe-bash/command-chunks/{chunk-F7MJRXQ2.js → chunk-RDPJGIQF.js} +1 -1
  9. package/dist/safe-bash/commands/python/index.browser.js +1 -1
  10. package/dist/safe-bash/commands/python/llm-module.js +3 -1
  11. package/dist/safe-bash/commands/python/shell-module.js +7 -0
  12. package/dist/safe-bash/core.browser.js +33 -13
  13. package/dist/safe-bash/shell/runtime.js +44 -12
  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 +7476 -7338
  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 +454 -208
  22. package/dist/safe-bash-command-pdfinfo/index.js +541 -244
  23. package/dist/safe-bash-command-pdftk/index.js +454 -208
  24. package/dist/safe-bash-command-pdftoppm/index.js +541 -244
  25. package/dist/safe-bash-command-pdftotext/index.js +454 -208
  26. package/dist/safe-bash-command-qpdf/index.js +454 -208
  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 +514 -208
  30. package/dist/safe-bash-command-wkhtmltopdf/index.js +455 -208
  31. package/dist/safe-playwright-cloudflare/browser-snapshot-labels.d.ts +14 -0
  32. package/dist/safe-playwright-cloudflare/browser-snapshot-labels.js +62 -0
  33. package/dist/safe-playwright-cloudflare/browser-snapshot-scheduler.js +8 -1
  34. package/package.json +2 -2
  35. package/third-party/pdf-ast/THIRD_PARTY_NOTICES.md +27 -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);
@@ -39094,6 +39170,184 @@ function downscaleImage(image, widthScale, heightScale) {
39094
39170
  }
39095
39171
  return image;
39096
39172
  }
39173
+ var MAX_STROKE_VERTICES = 1e6;
39174
+ function dashSubpath(path, pattern, phase) {
39175
+ const cycle = pattern.reduce((sum, value) => sum + value, 0);
39176
+ if (!(cycle > 0)) return [path];
39177
+ let offset = (phase % cycle + cycle) % cycle, index = 0;
39178
+ while (offset > 0) {
39179
+ if (offset < pattern[index]) break;
39180
+ offset -= pattern[index];
39181
+ index = (index + 1) % pattern.length;
39182
+ }
39183
+ let remaining = pattern[index] - offset;
39184
+ const points = path.closed ? [...path.points, path.points[0]] : path.points;
39185
+ const result = [];
39186
+ let current = [];
39187
+ let steps = 0;
39188
+ const flush = () => {
39189
+ if (current.length) result.push({ points: current, closed: false });
39190
+ current = [];
39191
+ };
39192
+ const advance = (point) => {
39193
+ while (remaining <= 0) {
39194
+ if (++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39195
+ if (index % 2 === 0) {
39196
+ if (pattern[index] === 0) result.push({ points: [point, point], closed: false });
39197
+ flush();
39198
+ }
39199
+ index = (index + 1) % pattern.length;
39200
+ remaining = pattern[index];
39201
+ }
39202
+ };
39203
+ for (let i = 1; i < points.length; i++) {
39204
+ const start = points[i - 1], end = points[i];
39205
+ const dx = end[0] - start[0], dy = end[1] - start[1];
39206
+ const length = Math.hypot(dx, dy);
39207
+ if (!Number.isFinite(length) || length / cycle * pattern.length > MAX_STROKE_VERTICES) {
39208
+ throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39209
+ }
39210
+ let distance = 0;
39211
+ while (distance < length) {
39212
+ const point = [start[0] + dx * distance / length, start[1] + dy * distance / length];
39213
+ advance(point);
39214
+ const step = Math.min(remaining, length - distance);
39215
+ if (distance + step === distance || ++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39216
+ distance += step;
39217
+ remaining -= step;
39218
+ if (index % 2 === 0) {
39219
+ if (!current.length) current.push(point);
39220
+ current.push([start[0] + dx * distance / length, start[1] + dy * distance / length]);
39221
+ }
39222
+ }
39223
+ }
39224
+ flush();
39225
+ if (path.closed && result.length) {
39226
+ const first = result[0], last = result[result.length - 1];
39227
+ const start = path.points[0];
39228
+ const firstPoint = first.points[0], lastPoint = last.points[last.points.length - 1];
39229
+ if (firstPoint[0] === start[0] && firstPoint[1] === start[1] && lastPoint[0] === start[0] && lastPoint[1] === start[1]) {
39230
+ if (first === last) result[0] = { points: first.points, closed: true };
39231
+ else {
39232
+ result[0] = { points: [...last.points, ...first.points.slice(1)], closed: false };
39233
+ result.pop();
39234
+ }
39235
+ }
39236
+ }
39237
+ return result;
39238
+ }
39239
+ function strokeOutlines(paths, width, cap, join, miterLimit, dashArray = [], dashPhase = 0) {
39240
+ const half = width / 2;
39241
+ const contours = [];
39242
+ const pattern = dashArray.length % 2 ? [...dashArray, ...dashArray] : dashArray;
39243
+ let count = 0;
39244
+ let contour = [];
39245
+ const add = (x, y) => {
39246
+ if (++count > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke outline exceeds the vertex limit");
39247
+ contour.push([x, y]);
39248
+ };
39249
+ const arc = (point, dx1, dy1, dx2, dy2) => {
39250
+ let a1 = Math.atan2(dy1, dx1), a2 = Math.atan2(dy2, dx2);
39251
+ const ccw = a1 - a2 > 0 && a1 - a2 < Math.PI;
39252
+ const step = Math.acos(half / (half + 0.125)) * 2;
39253
+ add(point[0] + dx1, point[1] + dy1);
39254
+ if (step > 0) {
39255
+ if (!ccw) {
39256
+ if (a1 > a2) a2 += 2 * Math.PI;
39257
+ a2 -= step / 4;
39258
+ if ((a2 - a1) / step > MAX_STROKE_VERTICES - count) throw new PdfError("E_LIMIT", "Stroke arc exceeds the vertex limit");
39259
+ for (a1 += step; a1 < a2; a1 += step) add(point[0] + half * Math.cos(a1), point[1] + half * Math.sin(a1));
39260
+ } else {
39261
+ if (a1 < a2) a2 -= 2 * Math.PI;
39262
+ a2 += step / 4;
39263
+ if ((a1 - a2) / step > MAX_STROKE_VERTICES - count) throw new PdfError("E_LIMIT", "Stroke arc exceeds the vertex limit");
39264
+ for (a1 -= step; a1 > a2; a1 -= step) add(point[0] + half * Math.cos(a1), point[1] + half * Math.sin(a1));
39265
+ }
39266
+ }
39267
+ add(point[0] + dx2, point[1] + dy2);
39268
+ };
39269
+ const addCap = (point, next) => {
39270
+ const length = Math.hypot(next[0] - point[0], next[1] - point[1]);
39271
+ const dx = half * (next[1] - point[1]) / length;
39272
+ const dy = half * (next[0] - point[0]) / length;
39273
+ if (cap !== 1) {
39274
+ const sx = cap === 2 ? dy : 0, sy = cap === 2 ? dx : 0;
39275
+ add(point[0] - dx - sx, point[1] + dy - sy);
39276
+ add(point[0] + dx - sx, point[1] - dy - sy);
39277
+ } else {
39278
+ const angle = Math.atan2(dy, -dx);
39279
+ const step = Math.max(1e-3, Math.acos(half / (half + 0.125)) * 2);
39280
+ add(point[0] - dx, point[1] + dy);
39281
+ for (let a = angle + step; a < angle + Math.PI - step / 4; a += step) add(point[0] + half * Math.cos(a), point[1] + half * Math.sin(a));
39282
+ add(point[0] + dx, point[1] - dy);
39283
+ }
39284
+ };
39285
+ const addJoin = (prev, point, next) => {
39286
+ const len1 = Math.hypot(point[0] - prev[0], point[1] - prev[1]);
39287
+ const len2 = Math.hypot(next[0] - point[0], next[1] - point[1]);
39288
+ const dx1 = half * (point[1] - prev[1]) / len1, dy1 = half * (point[0] - prev[0]) / len1;
39289
+ const dx2 = half * (next[1] - point[1]) / len2, dy2 = half * (next[0] - point[0]) / len2;
39290
+ const inner = (next[0] - point[0]) * (point[1] - prev[1]) - (next[1] - point[1]) * (point[0] - prev[0]) > 0;
39291
+ if (!inner && join === 1) {
39292
+ arc(point, dx1, -dy1, dx2, -dy2);
39293
+ return;
39294
+ }
39295
+ if (inner || join === 0) {
39296
+ const ax = prev[0] + dx1, ay = prev[1] - dy1;
39297
+ const bx = point[0] + dx1, by = point[1] - dy1;
39298
+ const cx = point[0] + dx2, cy = point[1] - dy2;
39299
+ const dx = next[0] + dx2, dy = next[1] - dy2;
39300
+ const den = (bx - ax) * (dy - cy) - (by - ay) * (dx - cx);
39301
+ if (Math.abs(den) >= 1e-30) {
39302
+ const t = ((ay - cy) * (dx - cx) - (ax - cx) * (dy - cy)) / den;
39303
+ const x = ax + (bx - ax) * t, y = ay + (by - ay) * t;
39304
+ if (Math.hypot(x - point[0], y - point[1]) <= half * (inner ? 1.01 : miterLimit)) {
39305
+ add(x, y);
39306
+ return;
39307
+ }
39308
+ } else if ((bx - prev[0]) * dy1 - (prev[1] - by) * dx1 < 0 !== (bx - next[0]) * dy1 - (next[1] - by) * dx1 < 0) {
39309
+ add(bx, by);
39310
+ return;
39311
+ }
39312
+ }
39313
+ add(point[0] + dx1, point[1] - dy1);
39314
+ add(point[0] + dx2, point[1] - dy2);
39315
+ };
39316
+ for (const path of paths) {
39317
+ for (const subpath of pattern.length ? dashSubpath(path, pattern, dashPhase) : [path]) {
39318
+ const points = [];
39319
+ for (const point of subpath.points) {
39320
+ const prev = points[points.length - 1];
39321
+ if (!prev || Math.hypot(prev[0] - point[0], prev[1] - point[1]) > 1e-14) points.push(point);
39322
+ }
39323
+ let closed = subpath.closed;
39324
+ if (closed && points.length > 1 && Math.hypot(points[0][0] - points[points.length - 1][0], points[0][1] - points[points.length - 1][1]) <= 1e-14) points.pop();
39325
+ if (points.length < 3) closed = false;
39326
+ if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
39327
+ contour = [];
39328
+ const [x, y] = points[0];
39329
+ addCap([x, y], [x + 1, y]);
39330
+ addCap([x, y], [x - 1, y]);
39331
+ contours.push(contour);
39332
+ } else if (points.length >= 2) {
39333
+ contour = [];
39334
+ if (!closed) addCap(points[0], points[1]);
39335
+ for (let i = closed ? 0 : 1; i < points.length - (closed ? 0 : 1); i++) {
39336
+ addJoin(points[(i + points.length - 1) % points.length], points[i], points[(i + 1) % points.length]);
39337
+ }
39338
+ if (closed) {
39339
+ contours.push(contour);
39340
+ contour = [];
39341
+ } else addCap(points[points.length - 1], points[points.length - 2]);
39342
+ for (let i = points.length - (closed ? 1 : 2); i >= (closed ? 0 : 1); i--) {
39343
+ addJoin(points[(i + 1) % points.length], points[i], points[(i + points.length - 1) % points.length]);
39344
+ }
39345
+ contours.push(contour);
39346
+ }
39347
+ }
39348
+ }
39349
+ return contours;
39350
+ }
39097
39351
  function encodePng(bitmap) {
39098
39352
  return encodeRgbaToPng(bitmap.width, bitmap.height, bitmap.data);
39099
39353
  }
@@ -39942,111 +40196,60 @@ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMa
39942
40196
  rgba[idx + 2] = Math.round((effB * a + cbB * dstA * (1 - a)) / outA * 255);
39943
40197
  rgba[idx + 3] = Math.round(outA * 255);
39944
40198
  }
39945
- function drawAntiAliasedSegment(rgba, width, height, x0, y0, x1, y1, strokeWidth, color, alpha = 1, lineCap = 0, antialias = true, blendMode, clipMask) {
39946
- const halfW = Math.max(0.6, strokeWidth * 0.5);
39947
- const dx = x1 - x0;
39948
- const dy = y1 - y0;
39949
- const lenSq = dx * dx + dy * dy;
39950
- const segLen = Math.sqrt(lenSq);
39951
- const pad = lineCap === 2 ? halfW + 2 : halfW + 1;
39952
- const minX = Math.max(0, Math.floor(Math.min(x0, x1) - pad));
39953
- const maxX = Math.min(width - 1, Math.ceil(Math.max(x0, x1) + pad));
39954
- const minY = Math.max(0, Math.floor(Math.min(y0, y1) - pad));
39955
- const maxY = Math.min(height - 1, Math.ceil(Math.max(y0, y1) + pad));
39956
- for (let py = minY; py <= maxY; py++) {
39957
- for (let px = minX; px <= maxX; px++) {
39958
- const cx = px + 0.5;
39959
- const cy = py + 0.5;
39960
- if (segLen > 1e-6 && (lineCap === 0 || lineCap === 2)) {
39961
- const ux = dx / segLen;
39962
- const uy = dy / segLen;
39963
- const along = (cx - x0) * ux + (cy - y0) * uy;
39964
- const perp = Math.abs(-(cx - x0) * uy + (cy - y0) * ux);
39965
- const minAlong = lineCap === 2 ? -halfW : 0;
39966
- const maxAlong = lineCap === 2 ? segLen + halfW : segLen;
39967
- const overAlong = along < minAlong ? minAlong - along : along > maxAlong ? along - maxAlong : 0;
39968
- const dist2 = overAlong > 0 ? Math.max(perp, halfW + overAlong) : perp;
39969
- if (dist2 <= halfW + 0.75) {
39970
- const cov = antialias ? Math.max(0, Math.min(1, halfW + 0.5 - dist2)) : dist2 <= halfW + 0.25 ? 1 : 0;
39971
- blendPixel(rgba, width, height, px, py, color, cov * alpha, blendMode, clipMask);
39972
- }
39973
- continue;
39974
- }
39975
- let t = lenSq > 1e-6 ? ((cx - x0) * dx + (cy - y0) * dy) / lenSq : 0;
39976
- t = Math.max(0, Math.min(1, t));
39977
- const projX = x0 + t * dx;
39978
- const projY = y0 + t * dy;
39979
- const dist = Math.hypot(cx - projX, cy - projY);
39980
- if (dist <= halfW + 0.75) {
39981
- const cov = antialias ? Math.max(0, Math.min(1, halfW + 0.5 - dist)) : dist <= halfW + 0.25 ? 1 : 0;
39982
- blendPixel(rgba, width, height, px, py, color, cov * alpha, blendMode, clipMask);
39983
- }
39984
- }
39985
- }
39986
- }
39987
- function segmentsToScreenEdges(segments, pageHeight, scale, closeSubpaths = false) {
39988
- const edges = [];
39989
- let curX = 0;
39990
- let curY = 0;
39991
- let startX = 0;
39992
- let startY = 0;
39993
- let hasOpenSubpath = false;
40199
+ function segmentsToScreenPaths(segments, pageHeight, scale) {
40200
+ const paths = [];
40201
+ let points = [];
40202
+ let current = [0, 0];
39994
40203
  const toScreen = (x, y) => [x * scale, (pageHeight - y) * scale];
39995
- for (const seg of segments) {
39996
- if (seg.kind === "move") {
39997
- if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
39998
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
39999
- }
40000
- [curX, curY] = toScreen(seg.x, seg.y);
40001
- startX = curX;
40002
- startY = curY;
40003
- hasOpenSubpath = false;
40004
- } else if (seg.kind === "line") {
40005
- const [nx, ny] = toScreen(seg.x, seg.y);
40006
- edges.push({ x0: curX, y0: curY, x1: nx, y1: ny });
40007
- curX = nx;
40008
- curY = ny;
40009
- hasOpenSubpath = true;
40010
- } else if (seg.kind === "cubic") {
40011
- const [p1x, p1y] = toScreen(seg.x1, seg.y1);
40012
- const [p2x, p2y] = toScreen(seg.x2, seg.y2);
40013
- const [p3x, p3y] = toScreen(seg.x, seg.y);
40014
- const points = flattenCubic(curX, curY, p1x, p1y, p2x, p2y, p3x, p3y);
40015
- let px = curX;
40016
- let py = curY;
40017
- for (let i = 1; i < points.length; i++) {
40018
- const [qx, qy] = points[i];
40019
- edges.push({ x0: px, y0: py, x1: qx, y1: qy });
40020
- px = qx;
40021
- py = qy;
40022
- }
40023
- curX = p3x;
40024
- curY = p3y;
40025
- hasOpenSubpath = true;
40026
- } else if (seg.kind === "close") {
40027
- if (curX !== startX || curY !== startY) {
40028
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
40029
- curX = startX;
40030
- curY = startY;
40031
- }
40032
- hasOpenSubpath = false;
40033
- } else if (seg.kind === "rect") {
40034
- if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
40035
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
40036
- }
40037
- const [rx0, ry0] = toScreen(seg.x, seg.y);
40038
- const [rx1, ry1] = toScreen(seg.x + seg.width, seg.y + seg.height);
40039
- edges.push(
40040
- { x0: rx0, y0: ry0, x1: rx1, y1: ry0 },
40041
- { x0: rx1, y0: ry0, x1: rx1, y1: ry1 },
40042
- { x0: rx1, y0: ry1, x1: rx0, y1: ry1 },
40043
- { x0: rx0, y0: ry1, x1: rx0, y1: ry0 }
40044
- );
40045
- hasOpenSubpath = false;
40204
+ for (const segment of segments) {
40205
+ if (segment.kind === "move") {
40206
+ if (points.length) paths.push({ points, closed: false });
40207
+ current = toScreen(segment.x, segment.y);
40208
+ points = [current];
40209
+ } else if (segment.kind === "line") {
40210
+ if (!points.length) points = [current];
40211
+ current = toScreen(segment.x, segment.y);
40212
+ points.push(current);
40213
+ } else if (segment.kind === "cubic") {
40214
+ if (!points.length) points = [current];
40215
+ const a = toScreen(segment.x1, segment.y1), b = toScreen(segment.x2, segment.y2);
40216
+ const end = toScreen(segment.x, segment.y);
40217
+ const curve = flattenCubic(current[0], current[1], a[0], a[1], b[0], b[1], end[0], end[1]);
40218
+ for (let i = 1; i < curve.length; i++) points.push(curve[i]);
40219
+ current = end;
40220
+ } else if (segment.kind === "close") {
40221
+ if (points.length) {
40222
+ paths.push({ points, closed: true });
40223
+ current = points[0];
40224
+ points = [];
40225
+ }
40226
+ } else if (segment.kind === "rect") {
40227
+ if (points.length) paths.push({ points, closed: false });
40228
+ const first = toScreen(segment.x, segment.y);
40229
+ paths.push({ points: [
40230
+ first,
40231
+ toScreen(segment.x + segment.width, segment.y),
40232
+ toScreen(segment.x + segment.width, segment.y + segment.height),
40233
+ toScreen(segment.x, segment.y + segment.height)
40234
+ ], closed: true });
40235
+ current = first;
40236
+ points = [];
40237
+ }
40238
+ }
40239
+ if (points.length) paths.push({ points, closed: false });
40240
+ return paths;
40241
+ }
40242
+ function pathsToEdges(paths, closeSubpaths = false) {
40243
+ const edges = [];
40244
+ for (const { points, closed } of paths) {
40245
+ for (let i = 1; i < points.length; i++) {
40246
+ const a = points[i - 1], b = points[i];
40247
+ edges.push({ x0: a[0], y0: a[1], x1: b[0], y1: b[1] });
40248
+ }
40249
+ if ((closed || closeSubpaths) && points.length > 1) {
40250
+ const a = points[points.length - 1], b = points[0];
40251
+ edges.push({ x0: a[0], y0: a[1], x1: b[0], y1: b[1] });
40046
40252
  }
40047
- }
40048
- if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
40049
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
40050
40253
  }
40051
40254
  return edges;
40052
40255
  }
@@ -40157,6 +40360,30 @@ function paintOperations(displayList) {
40157
40360
  ...displayList.glyphs.map((value) => ({ kind: "glyph", value }))
40158
40361
  ];
40159
40362
  }
40363
+ function renderSoftMask(mask, displayList, scale) {
40364
+ const bitmap = renderDisplayListToBitmap({
40365
+ ...displayList,
40366
+ rotation: 0,
40367
+ glyphs: [],
40368
+ paths: [],
40369
+ images: [],
40370
+ operations: mask.operations
40371
+ }, { scale, transparent: true });
40372
+ const { data } = bitmap;
40373
+ for (let i = 0; i < data.length; i += 4) {
40374
+ let value = data[i + 3];
40375
+ if (mask.subtype === "Luminosity") {
40376
+ const alpha = value / 255;
40377
+ const r = Math.round(data[i] * alpha + mask.backdrop.r * 255 * (1 - alpha));
40378
+ const g = Math.round(data[i + 1] * alpha + mask.backdrop.g * 255 * (1 - alpha));
40379
+ const b = Math.round(data[i + 2] * alpha + mask.backdrop.b * 255 * (1 - alpha));
40380
+ value = Math.round(pdfLum(r, g, b));
40381
+ }
40382
+ data[i] = data[i + 1] = data[i + 2] = 0;
40383
+ data[i + 3] = mask.transferMap?.[value] ?? value;
40384
+ }
40385
+ return bitmap;
40386
+ }
40160
40387
  function renderDisplayListToBitmap(displayList, options = {}) {
40161
40388
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
40162
40389
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
@@ -40180,10 +40407,28 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40180
40407
  const aaTxt = options.antialiasText !== false;
40181
40408
  let cachedClips;
40182
40409
  let cachedClipMask;
40410
+ let cachedSoftMask;
40411
+ let cachedSoftMaskPixels;
40183
40412
  const imageClipMasks = /* @__PURE__ */ new Map();
40184
40413
  for (const original of paintOperations(displayList)) {
40185
40414
  if (original.kind === "glyph" && (original.value.renderMode === 3 || !original.value.outline && !original.value.unicode.trim())) continue;
40186
- const operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
40415
+ let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
40416
+ if (operation.kind === "group") {
40417
+ const group = operation.value;
40418
+ const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations: group.operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, transparent: true });
40419
+ for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
40420
+ operation = { kind: "image", value: {
40421
+ name: "TransparencyGroup",
40422
+ width: bitmap.width,
40423
+ height: bitmap.height,
40424
+ decodedRgba: bitmap.data,
40425
+ matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, 0, displayList.height - bitmap.height / scale],
40426
+ colorSpace: "DeviceRGB",
40427
+ bitsPerComponent: 8,
40428
+ blendMode: group.blendMode,
40429
+ clipRect: group.clipRect
40430
+ } };
40431
+ }
40187
40432
  const clips = original.value.clipPaths;
40188
40433
  let clipMask = clips && clips === cachedClips ? cachedClipMask : void 0;
40189
40434
  if (clips && !clipMask) {
@@ -40191,12 +40436,25 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40191
40436
  for (const clip of clips) {
40192
40437
  const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
40193
40438
  const layer = new Uint8Array(width * height * 4);
40194
- fillEdgesScanline4x4(layer, width, height, segmentsToScreenEdges(segments, displayList.height, scale, true), { r: 1, g: 1, b: 1 }, 1, fillRule);
40439
+ fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
40195
40440
  for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
40196
40441
  }
40197
40442
  cachedClips = clips;
40198
40443
  cachedClipMask = clipMask;
40199
40444
  }
40445
+ const softMask = original.value.softMask;
40446
+ if (softMask) {
40447
+ if (softMask !== cachedSoftMask) {
40448
+ cachedSoftMaskPixels = renderSoftMask(softMask, displayList, scale).data;
40449
+ cachedSoftMask = softMask;
40450
+ }
40451
+ if (clipMask) {
40452
+ clipMask = clipMask.slice();
40453
+ for (let i = 3; i < clipMask.length; i += 4) clipMask[i] = Math.round(clipMask[i] * cachedSoftMaskPixels[i] / 255);
40454
+ } else {
40455
+ clipMask = cachedSoftMaskPixels;
40456
+ }
40457
+ }
40200
40458
  const imageClips = original.value.clipImages;
40201
40459
  if (imageClips) {
40202
40460
  let imageMask = imageClipMasks.get(imageClips);
@@ -40225,62 +40483,38 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40225
40483
  if (operation.kind === "path") {
40226
40484
  const path = operation.value;
40227
40485
  if (path.fillColor) {
40228
- const edges = segmentsToScreenEdges(path.segments, displayList.height, scale, true);
40486
+ const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale), true);
40229
40487
  const clipScreen = path.clipRect ? [path.clipRect[0] * scale, (displayList.height - path.clipRect[3]) * scale, path.clipRect[2] * scale, (displayList.height - path.clipRect[1]) * scale] : void 0;
40230
40488
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
40231
40489
  }
40232
40490
  if (path.strokeColor) {
40233
- const edges = segmentsToScreenEdges(path.segments, displayList.height, scale, false);
40234
40491
  const rawSw = path.strokeWidth * scale;
40235
40492
  const sw = Math.max(1, rawSw);
40236
40493
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
40237
- const dashArr = path.dashArray && path.dashArray.length > 0 ? path.dashArray.map((d) => Math.max(0, d * scale)) : void 0;
40238
- const dashCycle = dashArr ? dashArr.reduce((a, b) => a + b, 0) : 0;
40239
- let dashDist = (path.dashPhase ?? 0) * scale % (dashCycle || 1);
40240
- if (dashDist < 0) dashDist += dashCycle;
40241
- for (const e of edges) {
40242
- if (!dashArr || dashCycle <= 1e-4) {
40243
- drawAntiAliasedSegment(rgba, width, height, e.x0, e.y0, e.x1, e.y1, sw, path.strokeColor, strokeAlpha, path.lineCap ?? 0, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
40244
- } else {
40245
- const dx = e.x1 - e.x0;
40246
- const dy = e.y1 - e.y0;
40247
- const edgeLen = Math.hypot(dx, dy);
40248
- if (edgeLen <= 1e-4) continue;
40249
- let pos = 0;
40250
- while (pos < edgeLen) {
40251
- let cycleRem = dashDist % dashCycle;
40252
- let dIdx = 0;
40253
- while (dIdx < dashArr.length - 1 && cycleRem >= dashArr[dIdx]) {
40254
- cycleRem -= dashArr[dIdx];
40255
- dIdx++;
40256
- }
40257
- const segRemainInDash = Math.max(1e-4, dashArr[dIdx] - cycleRem);
40258
- const step = Math.min(edgeLen - pos, segRemainInDash);
40259
- if (dIdx % 2 === 0) {
40260
- const t0 = pos / edgeLen;
40261
- const t1 = (pos + step) / edgeLen;
40262
- drawAntiAliasedSegment(
40263
- rgba,
40264
- width,
40265
- height,
40266
- e.x0 + dx * t0,
40267
- e.y0 + dy * t0,
40268
- e.x0 + dx * t1,
40269
- e.y0 + dy * t1,
40270
- sw,
40271
- path.strokeColor,
40272
- strokeAlpha,
40273
- path.lineCap ?? 0,
40274
- original.kind === "glyph" ? aaTxt : aaVec,
40275
- path.blendMode,
40276
- clipMask
40277
- );
40278
- }
40279
- pos += step;
40280
- dashDist = (dashDist + step) % dashCycle;
40281
- }
40282
- }
40283
- }
40494
+ const contours = strokeOutlines(
40495
+ segmentsToScreenPaths(path.segments, displayList.height, scale),
40496
+ sw,
40497
+ path.lineCap ?? 0,
40498
+ path.lineJoin ?? 0,
40499
+ path.miterLimit ?? 10,
40500
+ path.dashArray?.map((value) => Math.max(0, value * scale)),
40501
+ (path.dashPhase ?? 0) * scale
40502
+ );
40503
+ const edges = pathsToEdges(contours.map((points) => ({ points, closed: true })));
40504
+ const clipScreen = path.clipRect ? [path.clipRect[0] * scale, (displayList.height - path.clipRect[3]) * scale, path.clipRect[2] * scale, (displayList.height - path.clipRect[1]) * scale] : void 0;
40505
+ fillEdgesScanline4x4(
40506
+ rgba,
40507
+ width,
40508
+ height,
40509
+ edges,
40510
+ path.strokeColor,
40511
+ strokeAlpha,
40512
+ "nonzero",
40513
+ clipScreen,
40514
+ original.kind === "glyph" ? aaTxt : aaVec,
40515
+ path.blendMode,
40516
+ clipMask
40517
+ );
40284
40518
  }
40285
40519
  } else if (operation.kind === "image") {
40286
40520
  const img = operation.value;
@@ -41377,3 +41611,15 @@ export {
41377
41611
  * Copyright 2012 Mozilla Foundation. Licensed under Apache-2.0.
41378
41612
  * See THIRD_PARTY_NOTICES.md for the source revision and adaptations.
41379
41613
  */
41614
+ /*!
41615
+ * Anti-Grain Geometry - Version 2.3
41616
+ * Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
41617
+ *
41618
+ * Permission to copy, use, modify, sell and distribute this software
41619
+ * is granted provided this copyright notice appears in all copies.
41620
+ * This software is provided "as is" without express or implied
41621
+ * warranty, and with no claim as to its suitability for any purpose.
41622
+ *
41623
+ * Adapted from PDFium agg_math_stroke.h and agg_vcgen_stroke.cpp.
41624
+ * See THIRD_PARTY_NOTICES.md for the source revision and adaptations.
41625
+ */