@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
@@ -35568,14 +35568,18 @@ function evaluateContentStreamToDisplayList(params) {
35568
35568
  const paths = [];
35569
35569
  const images = [];
35570
35570
  const operations = [];
35571
+ let capturedOperations;
35572
+ let insideSoftMask = false;
35571
35573
  const emit = (operation) => {
35572
- const { clipPaths, clipImages } = curState();
35573
- if (clipPaths || clipImages) operation = { ...operation, value: {
35574
+ const { clipPaths, clipImages, softMask } = curState();
35575
+ if (clipPaths || clipImages || softMask) operation = { ...operation, value: {
35574
35576
  ...operation.value,
35575
35577
  ...clipPaths ? { clipPaths } : {},
35576
- ...clipImages ? { clipImages } : {}
35578
+ ...clipImages ? { clipImages } : {},
35579
+ ...softMask ? { softMask } : {}
35577
35580
  } };
35578
- operations.push(operation);
35581
+ (capturedOperations ?? operations).push(operation);
35582
+ if (insideSoftMask) return;
35579
35583
  switch (operation.kind) {
35580
35584
  case "path":
35581
35585
  paths.push(operation.value);
@@ -35681,7 +35685,7 @@ function evaluateContentStreamToDisplayList(params) {
35681
35685
  );
35682
35686
  return { r: kClamp(r), g: kClamp(g), b: kClamp(b) };
35683
35687
  };
35684
- const applyStateOperator = (st, operator, ops, activeResources) => {
35688
+ const applyStateOperator = (st, operator, ops, activeResources, activeFonts, depth) => {
35685
35689
  const num = (i, fb = 0) => ops[i]?.kind === "number" ? ops[i].value : fb;
35686
35690
  if (operator === "cm") {
35687
35691
  const m = [num(0, 1), num(1, 0), num(2, 0), num(3, 1), num(4, 0), num(5, 0)];
@@ -35764,6 +35768,46 @@ function evaluateContentStreamToDisplayList(params) {
35764
35768
  const extDict = params.cosDoc.resolveDict(dictGet(activeResources, "ExtGState"));
35765
35769
  const gsDict = extDict ? params.cosDoc.resolveDict(dictGet(extDict, ops[0].decoded)) : void 0;
35766
35770
  if (gsDict) {
35771
+ const mask = params.cosDoc.resolve(dictGet(gsDict, "SMask"));
35772
+ if (mask?.kind === "name" && mask.decoded === "None") {
35773
+ st.softMask = void 0;
35774
+ } else if (mask?.kind === "dict") {
35775
+ const subtype = params.cosDoc.resolve(dictGet(mask, "S"));
35776
+ const form = params.cosDoc.resolve(dictGet(mask, "G"));
35777
+ if (form?.kind === "stream" && subtype?.kind === "name" && (subtype.decoded === "Alpha" || subtype.decoded === "Luminosity")) {
35778
+ if (depth >= 8) throw new PdfError("E_LIMIT", "Soft-mask nesting exceeds the form depth limit");
35779
+ const parentOperations = capturedOperations;
35780
+ const parentInsideSoftMask = insideSoftMask;
35781
+ const savedTextState = { pendingTextClip, hasTextClip, activeTm, activeTlm };
35782
+ const captured = [];
35783
+ capturedOperations = captured;
35784
+ insideSoftMask = true;
35785
+ const maskState = { ...st, softMask: void 0, fillAlpha: 1, strokeAlpha: 1, blendMode: "Normal" };
35786
+ delete maskState.clipPaths;
35787
+ delete maskState.clipImages;
35788
+ delete maskState.clipRect;
35789
+ stateStack.push(maskState);
35790
+ try {
35791
+ paintForm(form, activeResources, activeFonts, depth, void 0, void 0, true);
35792
+ } finally {
35793
+ stateStack.pop();
35794
+ capturedOperations = parentOperations;
35795
+ insideSoftMask = parentInsideSoftMask;
35796
+ ({ pendingTextClip, hasTextClip, activeTm, activeTlm } = savedTextState);
35797
+ }
35798
+ const group = params.cosDoc.resolveDict(dictGet(form.dict, "Group"));
35799
+ const colorSpace = group ? dictGet(group, "CS") : void 0;
35800
+ const bc = params.cosDoc.resolveArray(dictGet(mask, "BC"));
35801
+ const components = bc?.items.map((item) => {
35802
+ const value = params.cosDoc.resolve(item);
35803
+ return value?.kind === "number" ? value.value : 0;
35804
+ });
35805
+ const [r, g, b] = components ? convertColorSpaceComponentsToRgb(params.cosDoc, colorSpace, "DeviceRGB", components, activeResources) : [0, 0, 0];
35806
+ const transfer = params.cosDoc.resolve(dictGet(mask, "TR"));
35807
+ const transferMap = transfer?.kind === "dict" || transfer?.kind === "stream" ? Uint8Array.from({ length: 256 }, (_, i) => Math.floor(kClamp(Math.fround(evalShadingFunctionToComponents(params.cosDoc, transfer, Math.fround(i / 255))[0] ?? 0)) * 255)) : void 0;
35808
+ st.softMask = { subtype: subtype.decoded, operations: captured, backdrop: { r, g, b }, transferMap };
35809
+ }
35810
+ }
35767
35811
  const bmNode = params.cosDoc.resolve(dictGet(gsDict, "BM"));
35768
35812
  if (bmNode?.kind === "name") {
35769
35813
  st.blendMode = bmNode.decoded === "Compatible" ? "Normal" : bmNode.decoded;
@@ -35850,6 +35894,84 @@ function evaluateContentStreamToDisplayList(params) {
35850
35894
  ] }], void 0, void 0, resources, activeFonts, depth);
35851
35895
  stateStack.pop();
35852
35896
  };
35897
+ const paintForm = (form, activeResources, activeFonts, depth, mcid, actualText, maskGroup = false) => {
35898
+ const st = curState();
35899
+ const group = params.cosDoc.resolveDict(dictGet(form.dict, "Group"));
35900
+ const groupType = group ? params.cosDoc.resolve(dictGet(group, "S")) : void 0;
35901
+ const isolated = group ? params.cosDoc.resolve(dictGet(group, "I")) : void 0;
35902
+ const isolate = !maskGroup && groupType?.kind === "name" && groupType.decoded === "Transparency" && isolated?.kind === "boolean" && isolated.value;
35903
+ const formStreamBytes = params.cosDoc.decodeStream(form);
35904
+ const formNodes = parseContentStream(formStreamBytes);
35905
+ const formResDict = params.cosDoc.resolveDict(dictGet(form.dict, "Resources")) ?? activeResources;
35906
+ const formFonts = new Map(activeFonts);
35907
+ for (const [k, v] of resolvePageFonts(params.cosDoc, formResDict).entries()) {
35908
+ formFonts.set(k, v);
35909
+ }
35910
+ let nextCtm = [...st.ctm];
35911
+ const matArr = params.cosDoc.resolveArray(dictGet(form.dict, "Matrix"));
35912
+ if (matArr && matArr.items.length >= 6) {
35913
+ const mn = (idx, fb = 0) => {
35914
+ const resolved = params.cosDoc.resolve(matArr.items[idx]);
35915
+ return resolved?.kind === "number" ? resolved.value : fb;
35916
+ };
35917
+ const formMat = [mn(0, 1), mn(1, 0), mn(2, 0), mn(3, 1), mn(4, 0), mn(5, 0)];
35918
+ nextCtm = multiplyMatrices(formMat, nextCtm);
35919
+ }
35920
+ let nextClip = !isolate && st.clipRect ? [...st.clipRect] : void 0;
35921
+ let nextClipPaths = isolate ? void 0 : st.clipPaths;
35922
+ const bboxArr = params.cosDoc.resolveArray(dictGet(form.dict, "BBox"));
35923
+ if (bboxArr && bboxArr.items.length >= 4) {
35924
+ const bn = (idx, fb = 0) => {
35925
+ const resolved = params.cosDoc.resolve(bboxArr.items[idx]);
35926
+ return resolved?.kind === "number" ? resolved.value : fb;
35927
+ };
35928
+ const bx0 = bn(0, 0), by0 = bn(1, 0), bx1 = bn(2, 0), by1 = bn(3, 0);
35929
+ const pts = [
35930
+ transformPoint(nextCtm, bx0, by0),
35931
+ transformPoint(nextCtm, bx1, by0),
35932
+ transformPoint(nextCtm, bx1, by1),
35933
+ transformPoint(nextCtm, bx0, by1)
35934
+ ];
35935
+ nextClipPaths = [...nextClipPaths ?? [], [
35936
+ ...pts.map(([x, y], index) => ({ kind: index === 0 ? "move" : "line", x, y })),
35937
+ { kind: "close" }
35938
+ ]];
35939
+ const fMinX = Math.min(...pts.map((p) => p[0]));
35940
+ const fMinY = Math.min(...pts.map((p) => p[1]));
35941
+ const fMaxX = Math.max(...pts.map((p) => p[0]));
35942
+ const fMaxY = Math.max(...pts.map((p) => p[1]));
35943
+ if (fMaxX > fMinX && fMaxY > fMinY) {
35944
+ nextClip = nextClip ? [
35945
+ Math.max(nextClip[0], fMinX),
35946
+ Math.max(nextClip[1], fMinY),
35947
+ Math.min(nextClip[2], fMaxX),
35948
+ Math.min(nextClip[3], fMaxY)
35949
+ ] : [fMinX, fMinY, fMaxX, fMaxY];
35950
+ }
35951
+ }
35952
+ const parentOperations = capturedOperations;
35953
+ const children = [];
35954
+ const nextState = { ...st, ctm: nextCtm };
35955
+ if (isolate) {
35956
+ capturedOperations = children;
35957
+ nextState.fillAlpha = nextState.strokeAlpha = 1;
35958
+ nextState.blendMode = "Normal";
35959
+ nextState.softMask = void 0;
35960
+ delete nextState.clipImages;
35961
+ delete nextState.clipPaths;
35962
+ delete nextState.clipRect;
35963
+ }
35964
+ if (nextClip) nextState.clipRect = nextClip;
35965
+ if (nextClipPaths) nextState.clipPaths = nextClipPaths;
35966
+ stateStack.push(nextState);
35967
+ try {
35968
+ walkNodes(formNodes, mcid, actualText, formResDict, formFonts, depth + 1);
35969
+ } finally {
35970
+ stateStack.pop();
35971
+ capturedOperations = parentOperations;
35972
+ }
35973
+ if (isolate) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
35974
+ };
35853
35975
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
35854
35976
  for (const node of nodes) {
35855
35977
  switch (node.kind) {
@@ -35894,7 +36016,7 @@ function evaluateContentStreamToDisplayList(params) {
35894
36016
  break;
35895
36017
  }
35896
36018
  case "state-op": {
35897
- applyStateOperator(curState(), node.operator, node.operands, activeResources);
36019
+ applyStateOperator(curState(), node.operator, node.operands, activeResources, activeFonts, depth);
35898
36020
  break;
35899
36021
  }
35900
36022
  case "path-op": {
@@ -36180,53 +36302,7 @@ function evaluateContentStreamToDisplayList(params) {
36180
36302
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
36181
36303
  }, patternMask, activeResources, activeFonts, depth);
36182
36304
  } else if (sub === "Form" && depth < 8) {
36183
- const formStreamBytes = params.cosDoc.decodeStream(xobjNode);
36184
- const formNodes = parseContentStream(formStreamBytes);
36185
- const formResDict = params.cosDoc.resolveDict(dictGet(xobjNode.dict, "Resources")) ?? activeResources;
36186
- const formFonts = new Map(activeFonts);
36187
- for (const [k, v] of resolvePageFonts(params.cosDoc, formResDict).entries()) {
36188
- formFonts.set(k, v);
36189
- }
36190
- let nextCtm = [...st.ctm];
36191
- const matArr = params.cosDoc.resolveArray(dictGet(xobjNode.dict, "Matrix"));
36192
- if (matArr && matArr.items.length >= 6) {
36193
- const mn = (idx, fb = 0) => {
36194
- const resolved = params.cosDoc.resolve(matArr.items[idx]);
36195
- return resolved?.kind === "number" ? resolved.value : fb;
36196
- };
36197
- const formMat = [mn(0, 1), mn(1, 0), mn(2, 0), mn(3, 1), mn(4, 0), mn(5, 0)];
36198
- nextCtm = multiplyMatrices(formMat, nextCtm);
36199
- }
36200
- let nextClip = st.clipRect ? [...st.clipRect] : void 0;
36201
- const bboxArr = params.cosDoc.resolveArray(dictGet(xobjNode.dict, "BBox"));
36202
- if (bboxArr && bboxArr.items.length >= 4) {
36203
- const bn = (idx, fb = 0) => {
36204
- const resolved = params.cosDoc.resolve(bboxArr.items[idx]);
36205
- return resolved?.kind === "number" ? resolved.value : fb;
36206
- };
36207
- const bx0 = bn(0, 0), by0 = bn(1, 0), bx1 = bn(2, 0), by1 = bn(3, 0);
36208
- const pts = [
36209
- transformPoint(nextCtm, bx0, by0),
36210
- transformPoint(nextCtm, bx1, by0),
36211
- transformPoint(nextCtm, bx0, by1),
36212
- transformPoint(nextCtm, bx1, by1)
36213
- ];
36214
- const fMinX = Math.min(...pts.map((p) => p[0]));
36215
- const fMinY = Math.min(...pts.map((p) => p[1]));
36216
- const fMaxX = Math.max(...pts.map((p) => p[0]));
36217
- const fMaxY = Math.max(...pts.map((p) => p[1]));
36218
- if (fMaxX > fMinX && fMaxY > fMinY) {
36219
- nextClip = nextClip ? [
36220
- Math.max(nextClip[0], fMinX),
36221
- Math.max(nextClip[1], fMinY),
36222
- Math.min(nextClip[2], fMaxX),
36223
- Math.min(nextClip[3], fMaxY)
36224
- ] : [fMinX, fMinY, fMaxX, fMaxY];
36225
- }
36226
- }
36227
- stateStack.push({ ...st, ctm: nextCtm, ...nextClip ? { clipRect: nextClip } : {} });
36228
- walkNodes(formNodes, mcid, actualText, formResDict, formFonts, depth + 1);
36229
- if (stateStack.length > 1) stateStack.pop();
36305
+ paintForm(xobjNode, activeResources, activeFonts, depth, mcid, actualText);
36230
36306
  }
36231
36307
  }
36232
36308
  }
@@ -36445,7 +36521,7 @@ function evaluateContentStreamToDisplayList(params) {
36445
36521
  st.textRenderMode = cmd.mode;
36446
36522
  break;
36447
36523
  case "state-op":
36448
- applyStateOperator(st, cmd.operator, cmd.operands, activeResources);
36524
+ applyStateOperator(st, cmd.operator, cmd.operands, activeResources, activeFonts, depth);
36449
36525
  break;
36450
36526
  case "show-text":
36451
36527
  emitTokenBytes(cmd.token.bytes);
@@ -39313,6 +39389,184 @@ function downscaleImage(image, widthScale, heightScale) {
39313
39389
  }
39314
39390
  return image;
39315
39391
  }
39392
+ var MAX_STROKE_VERTICES = 1e6;
39393
+ function dashSubpath(path, pattern, phase) {
39394
+ const cycle = pattern.reduce((sum, value) => sum + value, 0);
39395
+ if (!(cycle > 0)) return [path];
39396
+ let offset = (phase % cycle + cycle) % cycle, index = 0;
39397
+ while (offset > 0) {
39398
+ if (offset < pattern[index]) break;
39399
+ offset -= pattern[index];
39400
+ index = (index + 1) % pattern.length;
39401
+ }
39402
+ let remaining = pattern[index] - offset;
39403
+ const points = path.closed ? [...path.points, path.points[0]] : path.points;
39404
+ const result = [];
39405
+ let current = [];
39406
+ let steps = 0;
39407
+ const flush = () => {
39408
+ if (current.length) result.push({ points: current, closed: false });
39409
+ current = [];
39410
+ };
39411
+ const advance = (point) => {
39412
+ while (remaining <= 0) {
39413
+ if (++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39414
+ if (index % 2 === 0) {
39415
+ if (pattern[index] === 0) result.push({ points: [point, point], closed: false });
39416
+ flush();
39417
+ }
39418
+ index = (index + 1) % pattern.length;
39419
+ remaining = pattern[index];
39420
+ }
39421
+ };
39422
+ for (let i = 1; i < points.length; i++) {
39423
+ const start = points[i - 1], end = points[i];
39424
+ const dx = end[0] - start[0], dy = end[1] - start[1];
39425
+ const length = Math.hypot(dx, dy);
39426
+ if (!Number.isFinite(length) || length / cycle * pattern.length > MAX_STROKE_VERTICES) {
39427
+ throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39428
+ }
39429
+ let distance = 0;
39430
+ while (distance < length) {
39431
+ const point = [start[0] + dx * distance / length, start[1] + dy * distance / length];
39432
+ advance(point);
39433
+ const step = Math.min(remaining, length - distance);
39434
+ if (distance + step === distance || ++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39435
+ distance += step;
39436
+ remaining -= step;
39437
+ if (index % 2 === 0) {
39438
+ if (!current.length) current.push(point);
39439
+ current.push([start[0] + dx * distance / length, start[1] + dy * distance / length]);
39440
+ }
39441
+ }
39442
+ }
39443
+ flush();
39444
+ if (path.closed && result.length) {
39445
+ const first = result[0], last = result[result.length - 1];
39446
+ const start = path.points[0];
39447
+ const firstPoint = first.points[0], lastPoint = last.points[last.points.length - 1];
39448
+ if (firstPoint[0] === start[0] && firstPoint[1] === start[1] && lastPoint[0] === start[0] && lastPoint[1] === start[1]) {
39449
+ if (first === last) result[0] = { points: first.points, closed: true };
39450
+ else {
39451
+ result[0] = { points: [...last.points, ...first.points.slice(1)], closed: false };
39452
+ result.pop();
39453
+ }
39454
+ }
39455
+ }
39456
+ return result;
39457
+ }
39458
+ function strokeOutlines(paths, width, cap, join, miterLimit, dashArray = [], dashPhase = 0) {
39459
+ const half = width / 2;
39460
+ const contours = [];
39461
+ const pattern = dashArray.length % 2 ? [...dashArray, ...dashArray] : dashArray;
39462
+ let count = 0;
39463
+ let contour = [];
39464
+ const add = (x, y) => {
39465
+ if (++count > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke outline exceeds the vertex limit");
39466
+ contour.push([x, y]);
39467
+ };
39468
+ const arc = (point, dx1, dy1, dx2, dy2) => {
39469
+ let a1 = Math.atan2(dy1, dx1), a2 = Math.atan2(dy2, dx2);
39470
+ const ccw = a1 - a2 > 0 && a1 - a2 < Math.PI;
39471
+ const step = Math.acos(half / (half + 0.125)) * 2;
39472
+ add(point[0] + dx1, point[1] + dy1);
39473
+ if (step > 0) {
39474
+ if (!ccw) {
39475
+ if (a1 > a2) a2 += 2 * Math.PI;
39476
+ a2 -= step / 4;
39477
+ if ((a2 - a1) / step > MAX_STROKE_VERTICES - count) throw new PdfError("E_LIMIT", "Stroke arc exceeds the vertex limit");
39478
+ for (a1 += step; a1 < a2; a1 += step) add(point[0] + half * Math.cos(a1), point[1] + half * Math.sin(a1));
39479
+ } else {
39480
+ if (a1 < a2) a2 -= 2 * Math.PI;
39481
+ a2 += step / 4;
39482
+ if ((a1 - a2) / step > MAX_STROKE_VERTICES - count) throw new PdfError("E_LIMIT", "Stroke arc exceeds the vertex limit");
39483
+ for (a1 -= step; a1 > a2; a1 -= step) add(point[0] + half * Math.cos(a1), point[1] + half * Math.sin(a1));
39484
+ }
39485
+ }
39486
+ add(point[0] + dx2, point[1] + dy2);
39487
+ };
39488
+ const addCap = (point, next) => {
39489
+ const length = Math.hypot(next[0] - point[0], next[1] - point[1]);
39490
+ const dx = half * (next[1] - point[1]) / length;
39491
+ const dy = half * (next[0] - point[0]) / length;
39492
+ if (cap !== 1) {
39493
+ const sx = cap === 2 ? dy : 0, sy = cap === 2 ? dx : 0;
39494
+ add(point[0] - dx - sx, point[1] + dy - sy);
39495
+ add(point[0] + dx - sx, point[1] - dy - sy);
39496
+ } else {
39497
+ const angle = Math.atan2(dy, -dx);
39498
+ const step = Math.max(1e-3, Math.acos(half / (half + 0.125)) * 2);
39499
+ add(point[0] - dx, point[1] + dy);
39500
+ 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));
39501
+ add(point[0] + dx, point[1] - dy);
39502
+ }
39503
+ };
39504
+ const addJoin = (prev, point, next) => {
39505
+ const len1 = Math.hypot(point[0] - prev[0], point[1] - prev[1]);
39506
+ const len2 = Math.hypot(next[0] - point[0], next[1] - point[1]);
39507
+ const dx1 = half * (point[1] - prev[1]) / len1, dy1 = half * (point[0] - prev[0]) / len1;
39508
+ const dx2 = half * (next[1] - point[1]) / len2, dy2 = half * (next[0] - point[0]) / len2;
39509
+ const inner = (next[0] - point[0]) * (point[1] - prev[1]) - (next[1] - point[1]) * (point[0] - prev[0]) > 0;
39510
+ if (!inner && join === 1) {
39511
+ arc(point, dx1, -dy1, dx2, -dy2);
39512
+ return;
39513
+ }
39514
+ if (inner || join === 0) {
39515
+ const ax = prev[0] + dx1, ay = prev[1] - dy1;
39516
+ const bx = point[0] + dx1, by = point[1] - dy1;
39517
+ const cx = point[0] + dx2, cy = point[1] - dy2;
39518
+ const dx = next[0] + dx2, dy = next[1] - dy2;
39519
+ const den = (bx - ax) * (dy - cy) - (by - ay) * (dx - cx);
39520
+ if (Math.abs(den) >= 1e-30) {
39521
+ const t = ((ay - cy) * (dx - cx) - (ax - cx) * (dy - cy)) / den;
39522
+ const x = ax + (bx - ax) * t, y = ay + (by - ay) * t;
39523
+ if (Math.hypot(x - point[0], y - point[1]) <= half * (inner ? 1.01 : miterLimit)) {
39524
+ add(x, y);
39525
+ return;
39526
+ }
39527
+ } else if ((bx - prev[0]) * dy1 - (prev[1] - by) * dx1 < 0 !== (bx - next[0]) * dy1 - (next[1] - by) * dx1 < 0) {
39528
+ add(bx, by);
39529
+ return;
39530
+ }
39531
+ }
39532
+ add(point[0] + dx1, point[1] - dy1);
39533
+ add(point[0] + dx2, point[1] - dy2);
39534
+ };
39535
+ for (const path of paths) {
39536
+ for (const subpath of pattern.length ? dashSubpath(path, pattern, dashPhase) : [path]) {
39537
+ const points = [];
39538
+ for (const point of subpath.points) {
39539
+ const prev = points[points.length - 1];
39540
+ if (!prev || Math.hypot(prev[0] - point[0], prev[1] - point[1]) > 1e-14) points.push(point);
39541
+ }
39542
+ let closed = subpath.closed;
39543
+ 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();
39544
+ if (points.length < 3) closed = false;
39545
+ if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
39546
+ contour = [];
39547
+ const [x, y] = points[0];
39548
+ addCap([x, y], [x + 1, y]);
39549
+ addCap([x, y], [x - 1, y]);
39550
+ contours.push(contour);
39551
+ } else if (points.length >= 2) {
39552
+ contour = [];
39553
+ if (!closed) addCap(points[0], points[1]);
39554
+ for (let i = closed ? 0 : 1; i < points.length - (closed ? 0 : 1); i++) {
39555
+ addJoin(points[(i + points.length - 1) % points.length], points[i], points[(i + 1) % points.length]);
39556
+ }
39557
+ if (closed) {
39558
+ contours.push(contour);
39559
+ contour = [];
39560
+ } else addCap(points[points.length - 1], points[points.length - 2]);
39561
+ for (let i = points.length - (closed ? 1 : 2); i >= (closed ? 0 : 1); i--) {
39562
+ addJoin(points[(i + 1) % points.length], points[i], points[(i + points.length - 1) % points.length]);
39563
+ }
39564
+ contours.push(contour);
39565
+ }
39566
+ }
39567
+ }
39568
+ return contours;
39569
+ }
39316
39570
  function decodePng(pngBytes) {
39317
39571
  if (pngBytes.length < 24 || pngBytes[0] !== 137 || pngBytes[1] !== 80 || pngBytes[2] !== 78 || pngBytes[3] !== 71) {
39318
39572
  throw new Error("Invalid PNG signature");
@@ -40007,111 +40261,60 @@ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMa
40007
40261
  rgba[idx + 2] = Math.round((effB * a + cbB * dstA * (1 - a)) / outA * 255);
40008
40262
  rgba[idx + 3] = Math.round(outA * 255);
40009
40263
  }
40010
- function drawAntiAliasedSegment(rgba, width, height, x0, y0, x1, y1, strokeWidth, color, alpha = 1, lineCap = 0, antialias = true, blendMode, clipMask) {
40011
- const halfW = Math.max(0.6, strokeWidth * 0.5);
40012
- const dx = x1 - x0;
40013
- const dy = y1 - y0;
40014
- const lenSq = dx * dx + dy * dy;
40015
- const segLen = Math.sqrt(lenSq);
40016
- const pad = lineCap === 2 ? halfW + 2 : halfW + 1;
40017
- const minX = Math.max(0, Math.floor(Math.min(x0, x1) - pad));
40018
- const maxX = Math.min(width - 1, Math.ceil(Math.max(x0, x1) + pad));
40019
- const minY = Math.max(0, Math.floor(Math.min(y0, y1) - pad));
40020
- const maxY = Math.min(height - 1, Math.ceil(Math.max(y0, y1) + pad));
40021
- for (let py = minY; py <= maxY; py++) {
40022
- for (let px = minX; px <= maxX; px++) {
40023
- const cx = px + 0.5;
40024
- const cy = py + 0.5;
40025
- if (segLen > 1e-6 && (lineCap === 0 || lineCap === 2)) {
40026
- const ux = dx / segLen;
40027
- const uy = dy / segLen;
40028
- const along = (cx - x0) * ux + (cy - y0) * uy;
40029
- const perp = Math.abs(-(cx - x0) * uy + (cy - y0) * ux);
40030
- const minAlong = lineCap === 2 ? -halfW : 0;
40031
- const maxAlong = lineCap === 2 ? segLen + halfW : segLen;
40032
- const overAlong = along < minAlong ? minAlong - along : along > maxAlong ? along - maxAlong : 0;
40033
- const dist2 = overAlong > 0 ? Math.max(perp, halfW + overAlong) : perp;
40034
- if (dist2 <= halfW + 0.75) {
40035
- const cov = antialias ? Math.max(0, Math.min(1, halfW + 0.5 - dist2)) : dist2 <= halfW + 0.25 ? 1 : 0;
40036
- blendPixel(rgba, width, height, px, py, color, cov * alpha, blendMode, clipMask);
40037
- }
40038
- continue;
40039
- }
40040
- let t = lenSq > 1e-6 ? ((cx - x0) * dx + (cy - y0) * dy) / lenSq : 0;
40041
- t = Math.max(0, Math.min(1, t));
40042
- const projX = x0 + t * dx;
40043
- const projY = y0 + t * dy;
40044
- const dist = Math.hypot(cx - projX, cy - projY);
40045
- if (dist <= halfW + 0.75) {
40046
- const cov = antialias ? Math.max(0, Math.min(1, halfW + 0.5 - dist)) : dist <= halfW + 0.25 ? 1 : 0;
40047
- blendPixel(rgba, width, height, px, py, color, cov * alpha, blendMode, clipMask);
40048
- }
40049
- }
40050
- }
40051
- }
40052
- function segmentsToScreenEdges(segments, pageHeight, scale, closeSubpaths = false) {
40053
- const edges = [];
40054
- let curX = 0;
40055
- let curY = 0;
40056
- let startX = 0;
40057
- let startY = 0;
40058
- let hasOpenSubpath = false;
40264
+ function segmentsToScreenPaths(segments, pageHeight, scale) {
40265
+ const paths = [];
40266
+ let points = [];
40267
+ let current = [0, 0];
40059
40268
  const toScreen = (x, y) => [x * scale, (pageHeight - y) * scale];
40060
- for (const seg of segments) {
40061
- if (seg.kind === "move") {
40062
- if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
40063
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
40064
- }
40065
- [curX, curY] = toScreen(seg.x, seg.y);
40066
- startX = curX;
40067
- startY = curY;
40068
- hasOpenSubpath = false;
40069
- } else if (seg.kind === "line") {
40070
- const [nx, ny] = toScreen(seg.x, seg.y);
40071
- edges.push({ x0: curX, y0: curY, x1: nx, y1: ny });
40072
- curX = nx;
40073
- curY = ny;
40074
- hasOpenSubpath = true;
40075
- } else if (seg.kind === "cubic") {
40076
- const [p1x, p1y] = toScreen(seg.x1, seg.y1);
40077
- const [p2x, p2y] = toScreen(seg.x2, seg.y2);
40078
- const [p3x, p3y] = toScreen(seg.x, seg.y);
40079
- const points = flattenCubic(curX, curY, p1x, p1y, p2x, p2y, p3x, p3y);
40080
- let px = curX;
40081
- let py = curY;
40082
- for (let i = 1; i < points.length; i++) {
40083
- const [qx, qy] = points[i];
40084
- edges.push({ x0: px, y0: py, x1: qx, y1: qy });
40085
- px = qx;
40086
- py = qy;
40087
- }
40088
- curX = p3x;
40089
- curY = p3y;
40090
- hasOpenSubpath = true;
40091
- } else if (seg.kind === "close") {
40092
- if (curX !== startX || curY !== startY) {
40093
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
40094
- curX = startX;
40095
- curY = startY;
40096
- }
40097
- hasOpenSubpath = false;
40098
- } else if (seg.kind === "rect") {
40099
- if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
40100
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
40101
- }
40102
- const [rx0, ry0] = toScreen(seg.x, seg.y);
40103
- const [rx1, ry1] = toScreen(seg.x + seg.width, seg.y + seg.height);
40104
- edges.push(
40105
- { x0: rx0, y0: ry0, x1: rx1, y1: ry0 },
40106
- { x0: rx1, y0: ry0, x1: rx1, y1: ry1 },
40107
- { x0: rx1, y0: ry1, x1: rx0, y1: ry1 },
40108
- { x0: rx0, y0: ry1, x1: rx0, y1: ry0 }
40109
- );
40110
- hasOpenSubpath = false;
40269
+ for (const segment of segments) {
40270
+ if (segment.kind === "move") {
40271
+ if (points.length) paths.push({ points, closed: false });
40272
+ current = toScreen(segment.x, segment.y);
40273
+ points = [current];
40274
+ } else if (segment.kind === "line") {
40275
+ if (!points.length) points = [current];
40276
+ current = toScreen(segment.x, segment.y);
40277
+ points.push(current);
40278
+ } else if (segment.kind === "cubic") {
40279
+ if (!points.length) points = [current];
40280
+ const a = toScreen(segment.x1, segment.y1), b = toScreen(segment.x2, segment.y2);
40281
+ const end = toScreen(segment.x, segment.y);
40282
+ const curve = flattenCubic(current[0], current[1], a[0], a[1], b[0], b[1], end[0], end[1]);
40283
+ for (let i = 1; i < curve.length; i++) points.push(curve[i]);
40284
+ current = end;
40285
+ } else if (segment.kind === "close") {
40286
+ if (points.length) {
40287
+ paths.push({ points, closed: true });
40288
+ current = points[0];
40289
+ points = [];
40290
+ }
40291
+ } else if (segment.kind === "rect") {
40292
+ if (points.length) paths.push({ points, closed: false });
40293
+ const first = toScreen(segment.x, segment.y);
40294
+ paths.push({ points: [
40295
+ first,
40296
+ toScreen(segment.x + segment.width, segment.y),
40297
+ toScreen(segment.x + segment.width, segment.y + segment.height),
40298
+ toScreen(segment.x, segment.y + segment.height)
40299
+ ], closed: true });
40300
+ current = first;
40301
+ points = [];
40302
+ }
40303
+ }
40304
+ if (points.length) paths.push({ points, closed: false });
40305
+ return paths;
40306
+ }
40307
+ function pathsToEdges(paths, closeSubpaths = false) {
40308
+ const edges = [];
40309
+ for (const { points, closed } of paths) {
40310
+ for (let i = 1; i < points.length; i++) {
40311
+ const a = points[i - 1], b = points[i];
40312
+ edges.push({ x0: a[0], y0: a[1], x1: b[0], y1: b[1] });
40313
+ }
40314
+ if ((closed || closeSubpaths) && points.length > 1) {
40315
+ const a = points[points.length - 1], b = points[0];
40316
+ edges.push({ x0: a[0], y0: a[1], x1: b[0], y1: b[1] });
40111
40317
  }
40112
- }
40113
- if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
40114
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
40115
40318
  }
40116
40319
  return edges;
40117
40320
  }
@@ -40222,6 +40425,30 @@ function paintOperations(displayList) {
40222
40425
  ...displayList.glyphs.map((value) => ({ kind: "glyph", value }))
40223
40426
  ];
40224
40427
  }
40428
+ function renderSoftMask(mask, displayList, scale) {
40429
+ const bitmap = renderDisplayListToBitmap({
40430
+ ...displayList,
40431
+ rotation: 0,
40432
+ glyphs: [],
40433
+ paths: [],
40434
+ images: [],
40435
+ operations: mask.operations
40436
+ }, { scale, transparent: true });
40437
+ const { data } = bitmap;
40438
+ for (let i = 0; i < data.length; i += 4) {
40439
+ let value = data[i + 3];
40440
+ if (mask.subtype === "Luminosity") {
40441
+ const alpha = value / 255;
40442
+ const r = Math.round(data[i] * alpha + mask.backdrop.r * 255 * (1 - alpha));
40443
+ const g = Math.round(data[i + 1] * alpha + mask.backdrop.g * 255 * (1 - alpha));
40444
+ const b = Math.round(data[i + 2] * alpha + mask.backdrop.b * 255 * (1 - alpha));
40445
+ value = Math.round(pdfLum(r, g, b));
40446
+ }
40447
+ data[i] = data[i + 1] = data[i + 2] = 0;
40448
+ data[i + 3] = mask.transferMap?.[value] ?? value;
40449
+ }
40450
+ return bitmap;
40451
+ }
40225
40452
  function renderDisplayListToBitmap(displayList, options = {}) {
40226
40453
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
40227
40454
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
@@ -40245,10 +40472,28 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40245
40472
  const aaTxt = options.antialiasText !== false;
40246
40473
  let cachedClips;
40247
40474
  let cachedClipMask;
40475
+ let cachedSoftMask;
40476
+ let cachedSoftMaskPixels;
40248
40477
  const imageClipMasks = /* @__PURE__ */ new Map();
40249
40478
  for (const original of paintOperations(displayList)) {
40250
40479
  if (original.kind === "glyph" && (original.value.renderMode === 3 || !original.value.outline && !original.value.unicode.trim())) continue;
40251
- const operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
40480
+ let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
40481
+ if (operation.kind === "group") {
40482
+ const group = operation.value;
40483
+ const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations: group.operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, transparent: true });
40484
+ for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
40485
+ operation = { kind: "image", value: {
40486
+ name: "TransparencyGroup",
40487
+ width: bitmap.width,
40488
+ height: bitmap.height,
40489
+ decodedRgba: bitmap.data,
40490
+ matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, 0, displayList.height - bitmap.height / scale],
40491
+ colorSpace: "DeviceRGB",
40492
+ bitsPerComponent: 8,
40493
+ blendMode: group.blendMode,
40494
+ clipRect: group.clipRect
40495
+ } };
40496
+ }
40252
40497
  const clips = original.value.clipPaths;
40253
40498
  let clipMask = clips && clips === cachedClips ? cachedClipMask : void 0;
40254
40499
  if (clips && !clipMask) {
@@ -40256,12 +40501,25 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40256
40501
  for (const clip of clips) {
40257
40502
  const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
40258
40503
  const layer = new Uint8Array(width * height * 4);
40259
- fillEdgesScanline4x4(layer, width, height, segmentsToScreenEdges(segments, displayList.height, scale, true), { r: 1, g: 1, b: 1 }, 1, fillRule);
40504
+ fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
40260
40505
  for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
40261
40506
  }
40262
40507
  cachedClips = clips;
40263
40508
  cachedClipMask = clipMask;
40264
40509
  }
40510
+ const softMask = original.value.softMask;
40511
+ if (softMask) {
40512
+ if (softMask !== cachedSoftMask) {
40513
+ cachedSoftMaskPixels = renderSoftMask(softMask, displayList, scale).data;
40514
+ cachedSoftMask = softMask;
40515
+ }
40516
+ if (clipMask) {
40517
+ clipMask = clipMask.slice();
40518
+ for (let i = 3; i < clipMask.length; i += 4) clipMask[i] = Math.round(clipMask[i] * cachedSoftMaskPixels[i] / 255);
40519
+ } else {
40520
+ clipMask = cachedSoftMaskPixels;
40521
+ }
40522
+ }
40265
40523
  const imageClips = original.value.clipImages;
40266
40524
  if (imageClips) {
40267
40525
  let imageMask = imageClipMasks.get(imageClips);
@@ -40290,62 +40548,38 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40290
40548
  if (operation.kind === "path") {
40291
40549
  const path = operation.value;
40292
40550
  if (path.fillColor) {
40293
- const edges = segmentsToScreenEdges(path.segments, displayList.height, scale, true);
40551
+ const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale), true);
40294
40552
  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;
40295
40553
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
40296
40554
  }
40297
40555
  if (path.strokeColor) {
40298
- const edges = segmentsToScreenEdges(path.segments, displayList.height, scale, false);
40299
40556
  const rawSw = path.strokeWidth * scale;
40300
40557
  const sw = Math.max(1, rawSw);
40301
40558
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
40302
- const dashArr = path.dashArray && path.dashArray.length > 0 ? path.dashArray.map((d) => Math.max(0, d * scale)) : void 0;
40303
- const dashCycle = dashArr ? dashArr.reduce((a, b) => a + b, 0) : 0;
40304
- let dashDist = (path.dashPhase ?? 0) * scale % (dashCycle || 1);
40305
- if (dashDist < 0) dashDist += dashCycle;
40306
- for (const e of edges) {
40307
- if (!dashArr || dashCycle <= 1e-4) {
40308
- 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);
40309
- } else {
40310
- const dx = e.x1 - e.x0;
40311
- const dy = e.y1 - e.y0;
40312
- const edgeLen = Math.hypot(dx, dy);
40313
- if (edgeLen <= 1e-4) continue;
40314
- let pos = 0;
40315
- while (pos < edgeLen) {
40316
- let cycleRem = dashDist % dashCycle;
40317
- let dIdx = 0;
40318
- while (dIdx < dashArr.length - 1 && cycleRem >= dashArr[dIdx]) {
40319
- cycleRem -= dashArr[dIdx];
40320
- dIdx++;
40321
- }
40322
- const segRemainInDash = Math.max(1e-4, dashArr[dIdx] - cycleRem);
40323
- const step = Math.min(edgeLen - pos, segRemainInDash);
40324
- if (dIdx % 2 === 0) {
40325
- const t0 = pos / edgeLen;
40326
- const t1 = (pos + step) / edgeLen;
40327
- drawAntiAliasedSegment(
40328
- rgba,
40329
- width,
40330
- height,
40331
- e.x0 + dx * t0,
40332
- e.y0 + dy * t0,
40333
- e.x0 + dx * t1,
40334
- e.y0 + dy * t1,
40335
- sw,
40336
- path.strokeColor,
40337
- strokeAlpha,
40338
- path.lineCap ?? 0,
40339
- original.kind === "glyph" ? aaTxt : aaVec,
40340
- path.blendMode,
40341
- clipMask
40342
- );
40343
- }
40344
- pos += step;
40345
- dashDist = (dashDist + step) % dashCycle;
40346
- }
40347
- }
40348
- }
40559
+ const contours = strokeOutlines(
40560
+ segmentsToScreenPaths(path.segments, displayList.height, scale),
40561
+ sw,
40562
+ path.lineCap ?? 0,
40563
+ path.lineJoin ?? 0,
40564
+ path.miterLimit ?? 10,
40565
+ path.dashArray?.map((value) => Math.max(0, value * scale)),
40566
+ (path.dashPhase ?? 0) * scale
40567
+ );
40568
+ const edges = pathsToEdges(contours.map((points) => ({ points, closed: true })));
40569
+ 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;
40570
+ fillEdgesScanline4x4(
40571
+ rgba,
40572
+ width,
40573
+ height,
40574
+ edges,
40575
+ path.strokeColor,
40576
+ strokeAlpha,
40577
+ "nonzero",
40578
+ clipScreen,
40579
+ original.kind === "glyph" ? aaTxt : aaVec,
40580
+ path.blendMode,
40581
+ clipMask
40582
+ );
40349
40583
  }
40350
40584
  } else if (operation.kind === "image") {
40351
40585
  const img = operation.value;
@@ -43018,3 +43252,15 @@ export {
43018
43252
  * Copyright 2012 Mozilla Foundation. Licensed under Apache-2.0.
43019
43253
  * See THIRD_PARTY_NOTICES.md for the source revision and adaptations.
43020
43254
  */
43255
+ /*!
43256
+ * Anti-Grain Geometry - Version 2.3
43257
+ * Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
43258
+ *
43259
+ * Permission to copy, use, modify, sell and distribute this software
43260
+ * is granted provided this copyright notice appears in all copies.
43261
+ * This software is provided "as is" without express or implied
43262
+ * warranty, and with no claim as to its suitability for any purpose.
43263
+ *
43264
+ * Adapted from PDFium agg_math_stroke.h and agg_vcgen_stroke.cpp.
43265
+ * See THIRD_PARTY_NOTICES.md for the source revision and adaptations.
43266
+ */