@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
@@ -43567,14 +43567,18 @@ function evaluateContentStreamToDisplayList(params) {
43567
43567
  const paths = [];
43568
43568
  const images = [];
43569
43569
  const operations = [];
43570
+ let capturedOperations;
43571
+ let insideSoftMask = false;
43570
43572
  const emit = (operation) => {
43571
- const { clipPaths, clipImages } = curState();
43572
- if (clipPaths || clipImages) operation = { ...operation, value: {
43573
+ const { clipPaths, clipImages, softMask } = curState();
43574
+ if (clipPaths || clipImages || softMask) operation = { ...operation, value: {
43573
43575
  ...operation.value,
43574
43576
  ...clipPaths ? { clipPaths } : {},
43575
- ...clipImages ? { clipImages } : {}
43577
+ ...clipImages ? { clipImages } : {},
43578
+ ...softMask ? { softMask } : {}
43576
43579
  } };
43577
- operations.push(operation);
43580
+ (capturedOperations ?? operations).push(operation);
43581
+ if (insideSoftMask) return;
43578
43582
  switch (operation.kind) {
43579
43583
  case "path":
43580
43584
  paths.push(operation.value);
@@ -43680,7 +43684,7 @@ function evaluateContentStreamToDisplayList(params) {
43680
43684
  );
43681
43685
  return { r: kClamp(r), g: kClamp(g), b: kClamp(b) };
43682
43686
  };
43683
- const applyStateOperator = (st, operator, ops, activeResources) => {
43687
+ const applyStateOperator = (st, operator, ops, activeResources, activeFonts, depth) => {
43684
43688
  const num = (i, fb = 0) => ops[i]?.kind === "number" ? ops[i].value : fb;
43685
43689
  if (operator === "cm") {
43686
43690
  const m = [num(0, 1), num(1, 0), num(2, 0), num(3, 1), num(4, 0), num(5, 0)];
@@ -43763,6 +43767,46 @@ function evaluateContentStreamToDisplayList(params) {
43763
43767
  const extDict = params.cosDoc.resolveDict(dictGet(activeResources, "ExtGState"));
43764
43768
  const gsDict = extDict ? params.cosDoc.resolveDict(dictGet(extDict, ops[0].decoded)) : void 0;
43765
43769
  if (gsDict) {
43770
+ const mask = params.cosDoc.resolve(dictGet(gsDict, "SMask"));
43771
+ if (mask?.kind === "name" && mask.decoded === "None") {
43772
+ st.softMask = void 0;
43773
+ } else if (mask?.kind === "dict") {
43774
+ const subtype = params.cosDoc.resolve(dictGet(mask, "S"));
43775
+ const form = params.cosDoc.resolve(dictGet(mask, "G"));
43776
+ if (form?.kind === "stream" && subtype?.kind === "name" && (subtype.decoded === "Alpha" || subtype.decoded === "Luminosity")) {
43777
+ if (depth >= 8) throw new PdfError("E_LIMIT", "Soft-mask nesting exceeds the form depth limit");
43778
+ const parentOperations = capturedOperations;
43779
+ const parentInsideSoftMask = insideSoftMask;
43780
+ const savedTextState = { pendingTextClip, hasTextClip, activeTm, activeTlm };
43781
+ const captured = [];
43782
+ capturedOperations = captured;
43783
+ insideSoftMask = true;
43784
+ const maskState = { ...st, softMask: void 0, fillAlpha: 1, strokeAlpha: 1, blendMode: "Normal" };
43785
+ delete maskState.clipPaths;
43786
+ delete maskState.clipImages;
43787
+ delete maskState.clipRect;
43788
+ stateStack.push(maskState);
43789
+ try {
43790
+ paintForm(form, activeResources, activeFonts, depth, void 0, void 0, true);
43791
+ } finally {
43792
+ stateStack.pop();
43793
+ capturedOperations = parentOperations;
43794
+ insideSoftMask = parentInsideSoftMask;
43795
+ ({ pendingTextClip, hasTextClip, activeTm, activeTlm } = savedTextState);
43796
+ }
43797
+ const group = params.cosDoc.resolveDict(dictGet(form.dict, "Group"));
43798
+ const colorSpace = group ? dictGet(group, "CS") : void 0;
43799
+ const bc = params.cosDoc.resolveArray(dictGet(mask, "BC"));
43800
+ const components2 = bc?.items.map((item) => {
43801
+ const value = params.cosDoc.resolve(item);
43802
+ return value?.kind === "number" ? value.value : 0;
43803
+ });
43804
+ const [r, g, b] = components2 ? convertColorSpaceComponentsToRgb(params.cosDoc, colorSpace, "DeviceRGB", components2, activeResources) : [0, 0, 0];
43805
+ const transfer = params.cosDoc.resolve(dictGet(mask, "TR"));
43806
+ 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;
43807
+ st.softMask = { subtype: subtype.decoded, operations: captured, backdrop: { r, g, b }, transferMap };
43808
+ }
43809
+ }
43766
43810
  const bmNode = params.cosDoc.resolve(dictGet(gsDict, "BM"));
43767
43811
  if (bmNode?.kind === "name") {
43768
43812
  st.blendMode = bmNode.decoded === "Compatible" ? "Normal" : bmNode.decoded;
@@ -43849,6 +43893,84 @@ function evaluateContentStreamToDisplayList(params) {
43849
43893
  ] }], void 0, void 0, resources, activeFonts, depth);
43850
43894
  stateStack.pop();
43851
43895
  };
43896
+ const paintForm = (form, activeResources, activeFonts, depth, mcid, actualText, maskGroup = false) => {
43897
+ const st = curState();
43898
+ const group = params.cosDoc.resolveDict(dictGet(form.dict, "Group"));
43899
+ const groupType = group ? params.cosDoc.resolve(dictGet(group, "S")) : void 0;
43900
+ const isolated = group ? params.cosDoc.resolve(dictGet(group, "I")) : void 0;
43901
+ const isolate = !maskGroup && groupType?.kind === "name" && groupType.decoded === "Transparency" && isolated?.kind === "boolean" && isolated.value;
43902
+ const formStreamBytes = params.cosDoc.decodeStream(form);
43903
+ const formNodes = parseContentStream(formStreamBytes);
43904
+ const formResDict = params.cosDoc.resolveDict(dictGet(form.dict, "Resources")) ?? activeResources;
43905
+ const formFonts = new Map(activeFonts);
43906
+ for (const [k, v] of resolvePageFonts(params.cosDoc, formResDict).entries()) {
43907
+ formFonts.set(k, v);
43908
+ }
43909
+ let nextCtm = [...st.ctm];
43910
+ const matArr = params.cosDoc.resolveArray(dictGet(form.dict, "Matrix"));
43911
+ if (matArr && matArr.items.length >= 6) {
43912
+ const mn = (idx, fb = 0) => {
43913
+ const resolved = params.cosDoc.resolve(matArr.items[idx]);
43914
+ return resolved?.kind === "number" ? resolved.value : fb;
43915
+ };
43916
+ const formMat = [mn(0, 1), mn(1, 0), mn(2, 0), mn(3, 1), mn(4, 0), mn(5, 0)];
43917
+ nextCtm = multiplyMatrices(formMat, nextCtm);
43918
+ }
43919
+ let nextClip = !isolate && st.clipRect ? [...st.clipRect] : void 0;
43920
+ let nextClipPaths = isolate ? void 0 : st.clipPaths;
43921
+ const bboxArr = params.cosDoc.resolveArray(dictGet(form.dict, "BBox"));
43922
+ if (bboxArr && bboxArr.items.length >= 4) {
43923
+ const bn = (idx, fb = 0) => {
43924
+ const resolved = params.cosDoc.resolve(bboxArr.items[idx]);
43925
+ return resolved?.kind === "number" ? resolved.value : fb;
43926
+ };
43927
+ const bx0 = bn(0, 0), by0 = bn(1, 0), bx1 = bn(2, 0), by1 = bn(3, 0);
43928
+ const pts = [
43929
+ transformPoint(nextCtm, bx0, by0),
43930
+ transformPoint(nextCtm, bx1, by0),
43931
+ transformPoint(nextCtm, bx1, by1),
43932
+ transformPoint(nextCtm, bx0, by1)
43933
+ ];
43934
+ nextClipPaths = [...nextClipPaths ?? [], [
43935
+ ...pts.map(([x, y], index) => ({ kind: index === 0 ? "move" : "line", x, y })),
43936
+ { kind: "close" }
43937
+ ]];
43938
+ const fMinX = Math.min(...pts.map((p) => p[0]));
43939
+ const fMinY = Math.min(...pts.map((p) => p[1]));
43940
+ const fMaxX = Math.max(...pts.map((p) => p[0]));
43941
+ const fMaxY = Math.max(...pts.map((p) => p[1]));
43942
+ if (fMaxX > fMinX && fMaxY > fMinY) {
43943
+ nextClip = nextClip ? [
43944
+ Math.max(nextClip[0], fMinX),
43945
+ Math.max(nextClip[1], fMinY),
43946
+ Math.min(nextClip[2], fMaxX),
43947
+ Math.min(nextClip[3], fMaxY)
43948
+ ] : [fMinX, fMinY, fMaxX, fMaxY];
43949
+ }
43950
+ }
43951
+ const parentOperations = capturedOperations;
43952
+ const children = [];
43953
+ const nextState = { ...st, ctm: nextCtm };
43954
+ if (isolate) {
43955
+ capturedOperations = children;
43956
+ nextState.fillAlpha = nextState.strokeAlpha = 1;
43957
+ nextState.blendMode = "Normal";
43958
+ nextState.softMask = void 0;
43959
+ delete nextState.clipImages;
43960
+ delete nextState.clipPaths;
43961
+ delete nextState.clipRect;
43962
+ }
43963
+ if (nextClip) nextState.clipRect = nextClip;
43964
+ if (nextClipPaths) nextState.clipPaths = nextClipPaths;
43965
+ stateStack.push(nextState);
43966
+ try {
43967
+ walkNodes(formNodes, mcid, actualText, formResDict, formFonts, depth + 1);
43968
+ } finally {
43969
+ stateStack.pop();
43970
+ capturedOperations = parentOperations;
43971
+ }
43972
+ if (isolate) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
43973
+ };
43852
43974
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
43853
43975
  for (const node of nodes) {
43854
43976
  switch (node.kind) {
@@ -43893,7 +44015,7 @@ function evaluateContentStreamToDisplayList(params) {
43893
44015
  break;
43894
44016
  }
43895
44017
  case "state-op": {
43896
- applyStateOperator(curState(), node.operator, node.operands, activeResources);
44018
+ applyStateOperator(curState(), node.operator, node.operands, activeResources, activeFonts, depth);
43897
44019
  break;
43898
44020
  }
43899
44021
  case "path-op": {
@@ -44179,53 +44301,7 @@ function evaluateContentStreamToDisplayList(params) {
44179
44301
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
44180
44302
  }, patternMask, activeResources, activeFonts, depth);
44181
44303
  } else if (sub === "Form" && depth < 8) {
44182
- const formStreamBytes = params.cosDoc.decodeStream(xobjNode);
44183
- const formNodes = parseContentStream(formStreamBytes);
44184
- const formResDict = params.cosDoc.resolveDict(dictGet(xobjNode.dict, "Resources")) ?? activeResources;
44185
- const formFonts = new Map(activeFonts);
44186
- for (const [k, v] of resolvePageFonts(params.cosDoc, formResDict).entries()) {
44187
- formFonts.set(k, v);
44188
- }
44189
- let nextCtm = [...st.ctm];
44190
- const matArr = params.cosDoc.resolveArray(dictGet(xobjNode.dict, "Matrix"));
44191
- if (matArr && matArr.items.length >= 6) {
44192
- const mn = (idx, fb = 0) => {
44193
- const resolved = params.cosDoc.resolve(matArr.items[idx]);
44194
- return resolved?.kind === "number" ? resolved.value : fb;
44195
- };
44196
- const formMat = [mn(0, 1), mn(1, 0), mn(2, 0), mn(3, 1), mn(4, 0), mn(5, 0)];
44197
- nextCtm = multiplyMatrices(formMat, nextCtm);
44198
- }
44199
- let nextClip = st.clipRect ? [...st.clipRect] : void 0;
44200
- const bboxArr = params.cosDoc.resolveArray(dictGet(xobjNode.dict, "BBox"));
44201
- if (bboxArr && bboxArr.items.length >= 4) {
44202
- const bn = (idx, fb = 0) => {
44203
- const resolved = params.cosDoc.resolve(bboxArr.items[idx]);
44204
- return resolved?.kind === "number" ? resolved.value : fb;
44205
- };
44206
- const bx0 = bn(0, 0), by0 = bn(1, 0), bx1 = bn(2, 0), by1 = bn(3, 0);
44207
- const pts = [
44208
- transformPoint(nextCtm, bx0, by0),
44209
- transformPoint(nextCtm, bx1, by0),
44210
- transformPoint(nextCtm, bx0, by1),
44211
- transformPoint(nextCtm, bx1, by1)
44212
- ];
44213
- const fMinX = Math.min(...pts.map((p) => p[0]));
44214
- const fMinY = Math.min(...pts.map((p) => p[1]));
44215
- const fMaxX = Math.max(...pts.map((p) => p[0]));
44216
- const fMaxY = Math.max(...pts.map((p) => p[1]));
44217
- if (fMaxX > fMinX && fMaxY > fMinY) {
44218
- nextClip = nextClip ? [
44219
- Math.max(nextClip[0], fMinX),
44220
- Math.max(nextClip[1], fMinY),
44221
- Math.min(nextClip[2], fMaxX),
44222
- Math.min(nextClip[3], fMaxY)
44223
- ] : [fMinX, fMinY, fMaxX, fMaxY];
44224
- }
44225
- }
44226
- stateStack.push({ ...st, ctm: nextCtm, ...nextClip ? { clipRect: nextClip } : {} });
44227
- walkNodes(formNodes, mcid, actualText, formResDict, formFonts, depth + 1);
44228
- if (stateStack.length > 1) stateStack.pop();
44304
+ paintForm(xobjNode, activeResources, activeFonts, depth, mcid, actualText);
44229
44305
  }
44230
44306
  }
44231
44307
  }
@@ -44444,7 +44520,7 @@ function evaluateContentStreamToDisplayList(params) {
44444
44520
  st.textRenderMode = cmd.mode;
44445
44521
  break;
44446
44522
  case "state-op":
44447
- applyStateOperator(st, cmd.operator, cmd.operands, activeResources);
44523
+ applyStateOperator(st, cmd.operator, cmd.operands, activeResources, activeFonts, depth);
44448
44524
  break;
44449
44525
  case "show-text":
44450
44526
  emitTokenBytes(cmd.token.bytes);
@@ -46748,6 +46824,184 @@ function downscaleImage(image, widthScale, heightScale) {
46748
46824
  }
46749
46825
  return image;
46750
46826
  }
46827
+ var MAX_STROKE_VERTICES = 1e6;
46828
+ function dashSubpath(path, pattern, phase) {
46829
+ const cycle = pattern.reduce((sum, value) => sum + value, 0);
46830
+ if (!(cycle > 0)) return [path];
46831
+ let offset = (phase % cycle + cycle) % cycle, index = 0;
46832
+ while (offset > 0) {
46833
+ if (offset < pattern[index]) break;
46834
+ offset -= pattern[index];
46835
+ index = (index + 1) % pattern.length;
46836
+ }
46837
+ let remaining = pattern[index] - offset;
46838
+ const points = path.closed ? [...path.points, path.points[0]] : path.points;
46839
+ const result = [];
46840
+ let current = [];
46841
+ let steps = 0;
46842
+ const flush = () => {
46843
+ if (current.length) result.push({ points: current, closed: false });
46844
+ current = [];
46845
+ };
46846
+ const advance = (point) => {
46847
+ while (remaining <= 0) {
46848
+ if (++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
46849
+ if (index % 2 === 0) {
46850
+ if (pattern[index] === 0) result.push({ points: [point, point], closed: false });
46851
+ flush();
46852
+ }
46853
+ index = (index + 1) % pattern.length;
46854
+ remaining = pattern[index];
46855
+ }
46856
+ };
46857
+ for (let i = 1; i < points.length; i++) {
46858
+ const start = points[i - 1], end = points[i];
46859
+ const dx = end[0] - start[0], dy = end[1] - start[1];
46860
+ const length = Math.hypot(dx, dy);
46861
+ if (!Number.isFinite(length) || length / cycle * pattern.length > MAX_STROKE_VERTICES) {
46862
+ throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
46863
+ }
46864
+ let distance = 0;
46865
+ while (distance < length) {
46866
+ const point = [start[0] + dx * distance / length, start[1] + dy * distance / length];
46867
+ advance(point);
46868
+ const step = Math.min(remaining, length - distance);
46869
+ if (distance + step === distance || ++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
46870
+ distance += step;
46871
+ remaining -= step;
46872
+ if (index % 2 === 0) {
46873
+ if (!current.length) current.push(point);
46874
+ current.push([start[0] + dx * distance / length, start[1] + dy * distance / length]);
46875
+ }
46876
+ }
46877
+ }
46878
+ flush();
46879
+ if (path.closed && result.length) {
46880
+ const first = result[0], last = result[result.length - 1];
46881
+ const start = path.points[0];
46882
+ const firstPoint = first.points[0], lastPoint = last.points[last.points.length - 1];
46883
+ if (firstPoint[0] === start[0] && firstPoint[1] === start[1] && lastPoint[0] === start[0] && lastPoint[1] === start[1]) {
46884
+ if (first === last) result[0] = { points: first.points, closed: true };
46885
+ else {
46886
+ result[0] = { points: [...last.points, ...first.points.slice(1)], closed: false };
46887
+ result.pop();
46888
+ }
46889
+ }
46890
+ }
46891
+ return result;
46892
+ }
46893
+ function strokeOutlines(paths, width, cap, join, miterLimit, dashArray = [], dashPhase = 0) {
46894
+ const half = width / 2;
46895
+ const contours = [];
46896
+ const pattern = dashArray.length % 2 ? [...dashArray, ...dashArray] : dashArray;
46897
+ let count = 0;
46898
+ let contour = [];
46899
+ const add = (x, y) => {
46900
+ if (++count > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke outline exceeds the vertex limit");
46901
+ contour.push([x, y]);
46902
+ };
46903
+ const arc = (point, dx1, dy1, dx2, dy2) => {
46904
+ let a1 = Math.atan2(dy1, dx1), a2 = Math.atan2(dy2, dx2);
46905
+ const ccw = a1 - a2 > 0 && a1 - a2 < Math.PI;
46906
+ const step = Math.acos(half / (half + 0.125)) * 2;
46907
+ add(point[0] + dx1, point[1] + dy1);
46908
+ if (step > 0) {
46909
+ if (!ccw) {
46910
+ if (a1 > a2) a2 += 2 * Math.PI;
46911
+ a2 -= step / 4;
46912
+ if ((a2 - a1) / step > MAX_STROKE_VERTICES - count) throw new PdfError("E_LIMIT", "Stroke arc exceeds the vertex limit");
46913
+ for (a1 += step; a1 < a2; a1 += step) add(point[0] + half * Math.cos(a1), point[1] + half * Math.sin(a1));
46914
+ } else {
46915
+ if (a1 < a2) a2 -= 2 * Math.PI;
46916
+ a2 += step / 4;
46917
+ if ((a1 - a2) / step > MAX_STROKE_VERTICES - count) throw new PdfError("E_LIMIT", "Stroke arc exceeds the vertex limit");
46918
+ for (a1 -= step; a1 > a2; a1 -= step) add(point[0] + half * Math.cos(a1), point[1] + half * Math.sin(a1));
46919
+ }
46920
+ }
46921
+ add(point[0] + dx2, point[1] + dy2);
46922
+ };
46923
+ const addCap = (point, next) => {
46924
+ const length = Math.hypot(next[0] - point[0], next[1] - point[1]);
46925
+ const dx = half * (next[1] - point[1]) / length;
46926
+ const dy = half * (next[0] - point[0]) / length;
46927
+ if (cap !== 1) {
46928
+ const sx = cap === 2 ? dy : 0, sy = cap === 2 ? dx : 0;
46929
+ add(point[0] - dx - sx, point[1] + dy - sy);
46930
+ add(point[0] + dx - sx, point[1] - dy - sy);
46931
+ } else {
46932
+ const angle = Math.atan2(dy, -dx);
46933
+ const step = Math.max(1e-3, Math.acos(half / (half + 0.125)) * 2);
46934
+ add(point[0] - dx, point[1] + dy);
46935
+ 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));
46936
+ add(point[0] + dx, point[1] - dy);
46937
+ }
46938
+ };
46939
+ const addJoin = (prev, point, next) => {
46940
+ const len1 = Math.hypot(point[0] - prev[0], point[1] - prev[1]);
46941
+ const len2 = Math.hypot(next[0] - point[0], next[1] - point[1]);
46942
+ const dx1 = half * (point[1] - prev[1]) / len1, dy1 = half * (point[0] - prev[0]) / len1;
46943
+ const dx2 = half * (next[1] - point[1]) / len2, dy2 = half * (next[0] - point[0]) / len2;
46944
+ const inner = (next[0] - point[0]) * (point[1] - prev[1]) - (next[1] - point[1]) * (point[0] - prev[0]) > 0;
46945
+ if (!inner && join === 1) {
46946
+ arc(point, dx1, -dy1, dx2, -dy2);
46947
+ return;
46948
+ }
46949
+ if (inner || join === 0) {
46950
+ const ax = prev[0] + dx1, ay = prev[1] - dy1;
46951
+ const bx = point[0] + dx1, by = point[1] - dy1;
46952
+ const cx = point[0] + dx2, cy = point[1] - dy2;
46953
+ const dx = next[0] + dx2, dy = next[1] - dy2;
46954
+ const den = (bx - ax) * (dy - cy) - (by - ay) * (dx - cx);
46955
+ if (Math.abs(den) >= 1e-30) {
46956
+ const t = ((ay - cy) * (dx - cx) - (ax - cx) * (dy - cy)) / den;
46957
+ const x = ax + (bx - ax) * t, y = ay + (by - ay) * t;
46958
+ if (Math.hypot(x - point[0], y - point[1]) <= half * (inner ? 1.01 : miterLimit)) {
46959
+ add(x, y);
46960
+ return;
46961
+ }
46962
+ } else if ((bx - prev[0]) * dy1 - (prev[1] - by) * dx1 < 0 !== (bx - next[0]) * dy1 - (next[1] - by) * dx1 < 0) {
46963
+ add(bx, by);
46964
+ return;
46965
+ }
46966
+ }
46967
+ add(point[0] + dx1, point[1] - dy1);
46968
+ add(point[0] + dx2, point[1] - dy2);
46969
+ };
46970
+ for (const path of paths) {
46971
+ for (const subpath of pattern.length ? dashSubpath(path, pattern, dashPhase) : [path]) {
46972
+ const points = [];
46973
+ for (const point of subpath.points) {
46974
+ const prev = points[points.length - 1];
46975
+ if (!prev || Math.hypot(prev[0] - point[0], prev[1] - point[1]) > 1e-14) points.push(point);
46976
+ }
46977
+ let closed = subpath.closed;
46978
+ 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();
46979
+ if (points.length < 3) closed = false;
46980
+ if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
46981
+ contour = [];
46982
+ const [x, y] = points[0];
46983
+ addCap([x, y], [x + 1, y]);
46984
+ addCap([x, y], [x - 1, y]);
46985
+ contours.push(contour);
46986
+ } else if (points.length >= 2) {
46987
+ contour = [];
46988
+ if (!closed) addCap(points[0], points[1]);
46989
+ for (let i = closed ? 0 : 1; i < points.length - (closed ? 0 : 1); i++) {
46990
+ addJoin(points[(i + points.length - 1) % points.length], points[i], points[(i + 1) % points.length]);
46991
+ }
46992
+ if (closed) {
46993
+ contours.push(contour);
46994
+ contour = [];
46995
+ } else addCap(points[points.length - 1], points[points.length - 2]);
46996
+ for (let i = points.length - (closed ? 1 : 2); i >= (closed ? 0 : 1); i--) {
46997
+ addJoin(points[(i + 1) % points.length], points[i], points[(i + points.length - 1) % points.length]);
46998
+ }
46999
+ contours.push(contour);
47000
+ }
47001
+ }
47002
+ }
47003
+ return contours;
47004
+ }
46751
47005
  function decodePng(pngBytes) {
46752
47006
  if (pngBytes.length < 24 || pngBytes[0] !== 137 || pngBytes[1] !== 80 || pngBytes[2] !== 78 || pngBytes[3] !== 71) {
46753
47007
  throw new Error("Invalid PNG signature");
@@ -47442,111 +47696,60 @@ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMa
47442
47696
  rgba[idx + 2] = Math.round((effB * a + cbB * dstA * (1 - a)) / outA * 255);
47443
47697
  rgba[idx + 3] = Math.round(outA * 255);
47444
47698
  }
47445
- function drawAntiAliasedSegment(rgba, width, height, x0, y0, x1, y1, strokeWidth, color, alpha = 1, lineCap = 0, antialias = true, blendMode, clipMask) {
47446
- const halfW = Math.max(0.6, strokeWidth * 0.5);
47447
- const dx = x1 - x0;
47448
- const dy = y1 - y0;
47449
- const lenSq = dx * dx + dy * dy;
47450
- const segLen = Math.sqrt(lenSq);
47451
- const pad = lineCap === 2 ? halfW + 2 : halfW + 1;
47452
- const minX = Math.max(0, Math.floor(Math.min(x0, x1) - pad));
47453
- const maxX = Math.min(width - 1, Math.ceil(Math.max(x0, x1) + pad));
47454
- const minY = Math.max(0, Math.floor(Math.min(y0, y1) - pad));
47455
- const maxY = Math.min(height - 1, Math.ceil(Math.max(y0, y1) + pad));
47456
- for (let py = minY; py <= maxY; py++) {
47457
- for (let px = minX; px <= maxX; px++) {
47458
- const cx = px + 0.5;
47459
- const cy = py + 0.5;
47460
- if (segLen > 1e-6 && (lineCap === 0 || lineCap === 2)) {
47461
- const ux = dx / segLen;
47462
- const uy = dy / segLen;
47463
- const along = (cx - x0) * ux + (cy - y0) * uy;
47464
- const perp = Math.abs(-(cx - x0) * uy + (cy - y0) * ux);
47465
- const minAlong = lineCap === 2 ? -halfW : 0;
47466
- const maxAlong = lineCap === 2 ? segLen + halfW : segLen;
47467
- const overAlong = along < minAlong ? minAlong - along : along > maxAlong ? along - maxAlong : 0;
47468
- const dist2 = overAlong > 0 ? Math.max(perp, halfW + overAlong) : perp;
47469
- if (dist2 <= halfW + 0.75) {
47470
- const cov = antialias ? Math.max(0, Math.min(1, halfW + 0.5 - dist2)) : dist2 <= halfW + 0.25 ? 1 : 0;
47471
- blendPixel(rgba, width, height, px, py, color, cov * alpha, blendMode, clipMask);
47472
- }
47473
- continue;
47474
- }
47475
- let t = lenSq > 1e-6 ? ((cx - x0) * dx + (cy - y0) * dy) / lenSq : 0;
47476
- t = Math.max(0, Math.min(1, t));
47477
- const projX = x0 + t * dx;
47478
- const projY = y0 + t * dy;
47479
- const dist = Math.hypot(cx - projX, cy - projY);
47480
- if (dist <= halfW + 0.75) {
47481
- const cov = antialias ? Math.max(0, Math.min(1, halfW + 0.5 - dist)) : dist <= halfW + 0.25 ? 1 : 0;
47482
- blendPixel(rgba, width, height, px, py, color, cov * alpha, blendMode, clipMask);
47483
- }
47484
- }
47485
- }
47486
- }
47487
- function segmentsToScreenEdges(segments, pageHeight, scale, closeSubpaths = false) {
47488
- const edges = [];
47489
- let curX = 0;
47490
- let curY = 0;
47491
- let startX = 0;
47492
- let startY = 0;
47493
- let hasOpenSubpath = false;
47699
+ function segmentsToScreenPaths(segments, pageHeight, scale) {
47700
+ const paths = [];
47701
+ let points = [];
47702
+ let current = [0, 0];
47494
47703
  const toScreen = (x, y) => [x * scale, (pageHeight - y) * scale];
47495
- for (const seg of segments) {
47496
- if (seg.kind === "move") {
47497
- if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
47498
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
47499
- }
47500
- [curX, curY] = toScreen(seg.x, seg.y);
47501
- startX = curX;
47502
- startY = curY;
47503
- hasOpenSubpath = false;
47504
- } else if (seg.kind === "line") {
47505
- const [nx, ny] = toScreen(seg.x, seg.y);
47506
- edges.push({ x0: curX, y0: curY, x1: nx, y1: ny });
47507
- curX = nx;
47508
- curY = ny;
47509
- hasOpenSubpath = true;
47510
- } else if (seg.kind === "cubic") {
47511
- const [p1x, p1y] = toScreen(seg.x1, seg.y1);
47512
- const [p2x, p2y] = toScreen(seg.x2, seg.y2);
47513
- const [p3x, p3y] = toScreen(seg.x, seg.y);
47514
- const points = flattenCubic(curX, curY, p1x, p1y, p2x, p2y, p3x, p3y);
47515
- let px = curX;
47516
- let py = curY;
47517
- for (let i = 1; i < points.length; i++) {
47518
- const [qx, qy] = points[i];
47519
- edges.push({ x0: px, y0: py, x1: qx, y1: qy });
47520
- px = qx;
47521
- py = qy;
47522
- }
47523
- curX = p3x;
47524
- curY = p3y;
47525
- hasOpenSubpath = true;
47526
- } else if (seg.kind === "close") {
47527
- if (curX !== startX || curY !== startY) {
47528
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
47529
- curX = startX;
47530
- curY = startY;
47531
- }
47532
- hasOpenSubpath = false;
47533
- } else if (seg.kind === "rect") {
47534
- if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
47535
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
47536
- }
47537
- const [rx0, ry0] = toScreen(seg.x, seg.y);
47538
- const [rx1, ry1] = toScreen(seg.x + seg.width, seg.y + seg.height);
47539
- edges.push(
47540
- { x0: rx0, y0: ry0, x1: rx1, y1: ry0 },
47541
- { x0: rx1, y0: ry0, x1: rx1, y1: ry1 },
47542
- { x0: rx1, y0: ry1, x1: rx0, y1: ry1 },
47543
- { x0: rx0, y0: ry1, x1: rx0, y1: ry0 }
47544
- );
47545
- hasOpenSubpath = false;
47704
+ for (const segment of segments) {
47705
+ if (segment.kind === "move") {
47706
+ if (points.length) paths.push({ points, closed: false });
47707
+ current = toScreen(segment.x, segment.y);
47708
+ points = [current];
47709
+ } else if (segment.kind === "line") {
47710
+ if (!points.length) points = [current];
47711
+ current = toScreen(segment.x, segment.y);
47712
+ points.push(current);
47713
+ } else if (segment.kind === "cubic") {
47714
+ if (!points.length) points = [current];
47715
+ const a = toScreen(segment.x1, segment.y1), b = toScreen(segment.x2, segment.y2);
47716
+ const end = toScreen(segment.x, segment.y);
47717
+ const curve = flattenCubic(current[0], current[1], a[0], a[1], b[0], b[1], end[0], end[1]);
47718
+ for (let i = 1; i < curve.length; i++) points.push(curve[i]);
47719
+ current = end;
47720
+ } else if (segment.kind === "close") {
47721
+ if (points.length) {
47722
+ paths.push({ points, closed: true });
47723
+ current = points[0];
47724
+ points = [];
47725
+ }
47726
+ } else if (segment.kind === "rect") {
47727
+ if (points.length) paths.push({ points, closed: false });
47728
+ const first = toScreen(segment.x, segment.y);
47729
+ paths.push({ points: [
47730
+ first,
47731
+ toScreen(segment.x + segment.width, segment.y),
47732
+ toScreen(segment.x + segment.width, segment.y + segment.height),
47733
+ toScreen(segment.x, segment.y + segment.height)
47734
+ ], closed: true });
47735
+ current = first;
47736
+ points = [];
47737
+ }
47738
+ }
47739
+ if (points.length) paths.push({ points, closed: false });
47740
+ return paths;
47741
+ }
47742
+ function pathsToEdges(paths, closeSubpaths = false) {
47743
+ const edges = [];
47744
+ for (const { points, closed } of paths) {
47745
+ for (let i = 1; i < points.length; i++) {
47746
+ const a = points[i - 1], b = points[i];
47747
+ edges.push({ x0: a[0], y0: a[1], x1: b[0], y1: b[1] });
47748
+ }
47749
+ if ((closed || closeSubpaths) && points.length > 1) {
47750
+ const a = points[points.length - 1], b = points[0];
47751
+ edges.push({ x0: a[0], y0: a[1], x1: b[0], y1: b[1] });
47546
47752
  }
47547
- }
47548
- if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
47549
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
47550
47753
  }
47551
47754
  return edges;
47552
47755
  }
@@ -47657,6 +47860,30 @@ function paintOperations(displayList) {
47657
47860
  ...displayList.glyphs.map((value) => ({ kind: "glyph", value }))
47658
47861
  ];
47659
47862
  }
47863
+ function renderSoftMask(mask, displayList, scale) {
47864
+ const bitmap = renderDisplayListToBitmap({
47865
+ ...displayList,
47866
+ rotation: 0,
47867
+ glyphs: [],
47868
+ paths: [],
47869
+ images: [],
47870
+ operations: mask.operations
47871
+ }, { scale, transparent: true });
47872
+ const { data } = bitmap;
47873
+ for (let i = 0; i < data.length; i += 4) {
47874
+ let value = data[i + 3];
47875
+ if (mask.subtype === "Luminosity") {
47876
+ const alpha = value / 255;
47877
+ const r = Math.round(data[i] * alpha + mask.backdrop.r * 255 * (1 - alpha));
47878
+ const g = Math.round(data[i + 1] * alpha + mask.backdrop.g * 255 * (1 - alpha));
47879
+ const b = Math.round(data[i + 2] * alpha + mask.backdrop.b * 255 * (1 - alpha));
47880
+ value = Math.round(pdfLum(r, g, b));
47881
+ }
47882
+ data[i] = data[i + 1] = data[i + 2] = 0;
47883
+ data[i + 3] = mask.transferMap?.[value] ?? value;
47884
+ }
47885
+ return bitmap;
47886
+ }
47660
47887
  function renderDisplayListToBitmap(displayList, options = {}) {
47661
47888
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
47662
47889
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
@@ -47680,10 +47907,28 @@ function renderDisplayListToBitmap(displayList, options = {}) {
47680
47907
  const aaTxt = options.antialiasText !== false;
47681
47908
  let cachedClips;
47682
47909
  let cachedClipMask;
47910
+ let cachedSoftMask;
47911
+ let cachedSoftMaskPixels;
47683
47912
  const imageClipMasks = /* @__PURE__ */ new Map();
47684
47913
  for (const original of paintOperations(displayList)) {
47685
47914
  if (original.kind === "glyph" && (original.value.renderMode === 3 || !original.value.outline && !original.value.unicode.trim())) continue;
47686
- const operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
47915
+ let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
47916
+ if (operation.kind === "group") {
47917
+ const group = operation.value;
47918
+ const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations: group.operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, transparent: true });
47919
+ for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
47920
+ operation = { kind: "image", value: {
47921
+ name: "TransparencyGroup",
47922
+ width: bitmap.width,
47923
+ height: bitmap.height,
47924
+ decodedRgba: bitmap.data,
47925
+ matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, 0, displayList.height - bitmap.height / scale],
47926
+ colorSpace: "DeviceRGB",
47927
+ bitsPerComponent: 8,
47928
+ blendMode: group.blendMode,
47929
+ clipRect: group.clipRect
47930
+ } };
47931
+ }
47687
47932
  const clips = original.value.clipPaths;
47688
47933
  let clipMask = clips && clips === cachedClips ? cachedClipMask : void 0;
47689
47934
  if (clips && !clipMask) {
@@ -47691,12 +47936,25 @@ function renderDisplayListToBitmap(displayList, options = {}) {
47691
47936
  for (const clip of clips) {
47692
47937
  const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
47693
47938
  const layer = new Uint8Array(width * height * 4);
47694
- fillEdgesScanline4x4(layer, width, height, segmentsToScreenEdges(segments, displayList.height, scale, true), { r: 1, g: 1, b: 1 }, 1, fillRule);
47939
+ fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
47695
47940
  for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
47696
47941
  }
47697
47942
  cachedClips = clips;
47698
47943
  cachedClipMask = clipMask;
47699
47944
  }
47945
+ const softMask = original.value.softMask;
47946
+ if (softMask) {
47947
+ if (softMask !== cachedSoftMask) {
47948
+ cachedSoftMaskPixels = renderSoftMask(softMask, displayList, scale).data;
47949
+ cachedSoftMask = softMask;
47950
+ }
47951
+ if (clipMask) {
47952
+ clipMask = clipMask.slice();
47953
+ for (let i = 3; i < clipMask.length; i += 4) clipMask[i] = Math.round(clipMask[i] * cachedSoftMaskPixels[i] / 255);
47954
+ } else {
47955
+ clipMask = cachedSoftMaskPixels;
47956
+ }
47957
+ }
47700
47958
  const imageClips = original.value.clipImages;
47701
47959
  if (imageClips) {
47702
47960
  let imageMask = imageClipMasks.get(imageClips);
@@ -47725,62 +47983,38 @@ function renderDisplayListToBitmap(displayList, options = {}) {
47725
47983
  if (operation.kind === "path") {
47726
47984
  const path = operation.value;
47727
47985
  if (path.fillColor) {
47728
- const edges = segmentsToScreenEdges(path.segments, displayList.height, scale, true);
47986
+ const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale), true);
47729
47987
  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;
47730
47988
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
47731
47989
  }
47732
47990
  if (path.strokeColor) {
47733
- const edges = segmentsToScreenEdges(path.segments, displayList.height, scale, false);
47734
47991
  const rawSw = path.strokeWidth * scale;
47735
47992
  const sw = Math.max(1, rawSw);
47736
47993
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
47737
- const dashArr = path.dashArray && path.dashArray.length > 0 ? path.dashArray.map((d) => Math.max(0, d * scale)) : void 0;
47738
- const dashCycle = dashArr ? dashArr.reduce((a, b) => a + b, 0) : 0;
47739
- let dashDist = (path.dashPhase ?? 0) * scale % (dashCycle || 1);
47740
- if (dashDist < 0) dashDist += dashCycle;
47741
- for (const e of edges) {
47742
- if (!dashArr || dashCycle <= 1e-4) {
47743
- 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);
47744
- } else {
47745
- const dx = e.x1 - e.x0;
47746
- const dy = e.y1 - e.y0;
47747
- const edgeLen = Math.hypot(dx, dy);
47748
- if (edgeLen <= 1e-4) continue;
47749
- let pos = 0;
47750
- while (pos < edgeLen) {
47751
- let cycleRem = dashDist % dashCycle;
47752
- let dIdx = 0;
47753
- while (dIdx < dashArr.length - 1 && cycleRem >= dashArr[dIdx]) {
47754
- cycleRem -= dashArr[dIdx];
47755
- dIdx++;
47756
- }
47757
- const segRemainInDash = Math.max(1e-4, dashArr[dIdx] - cycleRem);
47758
- const step = Math.min(edgeLen - pos, segRemainInDash);
47759
- if (dIdx % 2 === 0) {
47760
- const t0 = pos / edgeLen;
47761
- const t1 = (pos + step) / edgeLen;
47762
- drawAntiAliasedSegment(
47763
- rgba,
47764
- width,
47765
- height,
47766
- e.x0 + dx * t0,
47767
- e.y0 + dy * t0,
47768
- e.x0 + dx * t1,
47769
- e.y0 + dy * t1,
47770
- sw,
47771
- path.strokeColor,
47772
- strokeAlpha,
47773
- path.lineCap ?? 0,
47774
- original.kind === "glyph" ? aaTxt : aaVec,
47775
- path.blendMode,
47776
- clipMask
47777
- );
47778
- }
47779
- pos += step;
47780
- dashDist = (dashDist + step) % dashCycle;
47781
- }
47782
- }
47783
- }
47994
+ const contours = strokeOutlines(
47995
+ segmentsToScreenPaths(path.segments, displayList.height, scale),
47996
+ sw,
47997
+ path.lineCap ?? 0,
47998
+ path.lineJoin ?? 0,
47999
+ path.miterLimit ?? 10,
48000
+ path.dashArray?.map((value) => Math.max(0, value * scale)),
48001
+ (path.dashPhase ?? 0) * scale
48002
+ );
48003
+ const edges = pathsToEdges(contours.map((points) => ({ points, closed: true })));
48004
+ 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;
48005
+ fillEdgesScanline4x4(
48006
+ rgba,
48007
+ width,
48008
+ height,
48009
+ edges,
48010
+ path.strokeColor,
48011
+ strokeAlpha,
48012
+ "nonzero",
48013
+ clipScreen,
48014
+ original.kind === "glyph" ? aaTxt : aaVec,
48015
+ path.blendMode,
48016
+ clipMask
48017
+ );
47784
48018
  }
47785
48019
  } else if (operation.kind === "image") {
47786
48020
  const img = operation.value;
@@ -62570,3 +62804,15 @@ export {
62570
62804
  * Copyright 2012 Mozilla Foundation. Licensed under Apache-2.0.
62571
62805
  * See THIRD_PARTY_NOTICES.md for the source revision and adaptations.
62572
62806
  */
62807
+ /*!
62808
+ * Anti-Grain Geometry - Version 2.3
62809
+ * Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
62810
+ *
62811
+ * Permission to copy, use, modify, sell and distribute this software
62812
+ * is granted provided this copyright notice appears in all copies.
62813
+ * This software is provided "as is" without express or implied
62814
+ * warranty, and with no claim as to its suitability for any purpose.
62815
+ *
62816
+ * Adapted from PDFium agg_math_stroke.h and agg_vcgen_stroke.cpp.
62817
+ * See THIRD_PARTY_NOTICES.md for the source revision and adaptations.
62818
+ */