@poe-platform/safe-bash 0.1.763 → 0.1.765

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/image-ast/index.browser.js +321 -162
  2. package/dist/image-ast/index.js +321 -162
  3. package/dist/pdf-ast/ast.d.ts +2 -0
  4. package/dist/pdf-ast/index.js +340 -173
  5. package/dist/safe-bash/chunks/{chunk-CRQDMBQA.js → chunk-FSH7QRIC.js} +10 -1
  6. package/dist/safe-bash/command-chunks/{chunk-4XHONGIU.js → chunk-DT4MFWV4.js} +2 -2
  7. package/dist/safe-bash/command-chunks/{chunk-S3G2B4OX.js → chunk-KO4PXCNL.js} +324 -162
  8. package/dist/safe-bash/command-chunks/{chunk-S5EX6UP5.js → chunk-SVL6HYQL.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 +32 -12
  13. package/dist/safe-bash/shell/runtime.js +43 -11
  14. package/dist/safe-bash-command-ffmpeg/index.js +5800 -5693
  15. package/dist/safe-bash-command-imagemagick/index.js +2 -2
  16. package/dist/safe-bash-command-pandoc/command.js +3 -3
  17. package/dist/safe-bash-command-pandoc/index.js +3 -3
  18. package/dist/safe-bash-command-pdfimages/index.js +321 -162
  19. package/dist/safe-bash-command-pdfinfo/index.js +338 -173
  20. package/dist/safe-bash-command-pdftk/index.js +321 -162
  21. package/dist/safe-bash-command-pdftoppm/index.js +338 -173
  22. package/dist/safe-bash-command-pdftotext/index.js +321 -162
  23. package/dist/safe-bash-command-qpdf/index.js +321 -162
  24. package/dist/safe-bash-command-sips/index.js +2 -2
  25. package/dist/safe-bash-command-soffice/index.js +1 -1
  26. package/dist/safe-bash-command-ssconvert/index.js +373 -169
  27. package/dist/safe-bash-command-wkhtmltopdf/index.js +322 -162
  28. package/dist/safe-playwright-cloudflare/browser-snapshot-labels.d.ts +14 -0
  29. package/dist/safe-playwright-cloudflare/browser-snapshot-labels.js +62 -0
  30. package/dist/safe-playwright-cloudflare/browser-snapshot-scheduler.js +8 -1
  31. package/package.json +2 -2
  32. package/third-party/pdf-ast/THIRD_PARTY_NOTICES.md +24 -0
@@ -35898,11 +35898,10 @@ function evaluateContentStreamToDisplayList(params) {
35898
35898
  } else if (operator === "d") {
35899
35899
  const arrNode = ops[0]?.kind === "array" ? ops[0] : void 0;
35900
35900
  if (arrNode) {
35901
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
35902
- const nums = arrNode.items.map((it) => it.kind === "number" ? it.value * ctmScale : 0).filter((v) => v >= 0);
35901
+ const nums = arrNode.items.map((it) => it.kind === "number" ? it.value : 0).filter((v) => v >= 0);
35903
35902
  const sum = nums.reduce((a, b) => a + b, 0);
35904
35903
  st.dashArray = sum > 0 ? nums : void 0;
35905
- st.dashPhase = num(1, 0) * ctmScale;
35904
+ st.dashPhase = num(1, 0);
35906
35905
  } else {
35907
35906
  st.dashArray = void 0;
35908
35907
  st.dashPhase = void 0;
@@ -36438,15 +36437,14 @@ function evaluateContentStreamToDisplayList(params) {
36438
36437
  break;
36439
36438
  }
36440
36439
  const fillRule = node.paint.includes("*") ? "evenodd" : "nonzero";
36441
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
36442
- const scaledStrokeWidth = st.strokeWidth === 0 ? 0 : st.strokeWidth * ctmScale;
36443
36440
  emit({ kind: "path", value: {
36444
36441
  segments: transformedSegments,
36445
36442
  fillColor: isFill && !evaluatedFillPattern ? st.fillColor : void 0,
36446
36443
  fillAlpha: isFill && !evaluatedFillPattern ? st.fillAlpha : void 0,
36447
36444
  strokeColor: isStroke ? st.strokeColor : void 0,
36448
36445
  strokeAlpha: isStroke ? st.strokeAlpha : void 0,
36449
- strokeWidth: scaledStrokeWidth,
36446
+ strokeWidth: st.strokeWidth,
36447
+ ...isStroke ? { strokeMatrix: [...st.ctm] } : {},
36450
36448
  ...st.lineCap !== 0 ? { lineCap: st.lineCap } : {},
36451
36449
  ...st.lineJoin !== 0 ? { lineJoin: st.lineJoin } : {},
36452
36450
  ...st.miterLimit !== 10 ? { miterLimit: st.miterLimit } : {},
@@ -36634,14 +36632,14 @@ function evaluateContentStreamToDisplayList(params) {
36634
36632
  if (st.textRenderMode >= 4 && st.textRenderMode <= 7) pendingTextClip.push(...transformedGlyphSegs);
36635
36633
  const isFillGlyph = st.textRenderMode === 0 || st.textRenderMode === 2 || st.textRenderMode === 4 || st.textRenderMode === 6;
36636
36634
  const isStrokeGlyph = st.textRenderMode === 1 || st.textRenderMode === 2 || st.textRenderMode === 5 || st.textRenderMode === 6;
36637
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
36638
36635
  const paint = {
36639
36636
  segments: transformedGlyphSegs,
36640
36637
  fillColor: isFillGlyph ? st.fillColor : void 0,
36641
36638
  fillAlpha: isFillGlyph ? st.fillAlpha : void 0,
36642
36639
  strokeColor: isStrokeGlyph ? st.strokeColor : void 0,
36643
36640
  strokeAlpha: isStrokeGlyph ? st.strokeAlpha : void 0,
36644
- strokeWidth: isStrokeGlyph ? st.strokeWidth * ctmScale : 0,
36641
+ strokeWidth: isStrokeGlyph ? st.strokeWidth : 0,
36642
+ ...isStrokeGlyph ? { strokeMatrix: [...st.ctm] } : {},
36645
36643
  fillRule: "nonzero",
36646
36644
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
36647
36645
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
@@ -39019,6 +39017,184 @@ function downscaleImage(image, widthScale, heightScale) {
39019
39017
  }
39020
39018
  return image;
39021
39019
  }
39020
+ var MAX_STROKE_VERTICES = 1e6;
39021
+ function dashSubpath(path, pattern, phase) {
39022
+ const cycle = pattern.reduce((sum, value) => sum + value, 0);
39023
+ if (!(cycle > 0)) return [path];
39024
+ let offset = (phase % cycle + cycle) % cycle, index = 0;
39025
+ while (offset > 0) {
39026
+ if (offset < pattern[index]) break;
39027
+ offset -= pattern[index];
39028
+ index = (index + 1) % pattern.length;
39029
+ }
39030
+ let remaining = pattern[index] - offset;
39031
+ const points = path.closed ? [...path.points, path.points[0]] : path.points;
39032
+ const result = [];
39033
+ let current = [];
39034
+ let steps = 0;
39035
+ const flush = () => {
39036
+ if (current.length) result.push({ points: current, closed: false });
39037
+ current = [];
39038
+ };
39039
+ const advance = (point) => {
39040
+ while (remaining <= 0) {
39041
+ if (++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39042
+ if (index % 2 === 0) {
39043
+ if (pattern[index] === 0) result.push({ points: [point, point], closed: false });
39044
+ flush();
39045
+ }
39046
+ index = (index + 1) % pattern.length;
39047
+ remaining = pattern[index];
39048
+ }
39049
+ };
39050
+ for (let i = 1; i < points.length; i++) {
39051
+ const start = points[i - 1], end = points[i];
39052
+ const dx = end[0] - start[0], dy = end[1] - start[1];
39053
+ const length = Math.hypot(dx, dy);
39054
+ if (!Number.isFinite(length) || length / cycle * pattern.length > MAX_STROKE_VERTICES) {
39055
+ throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39056
+ }
39057
+ let distance = 0;
39058
+ while (distance < length) {
39059
+ const point = [start[0] + dx * distance / length, start[1] + dy * distance / length];
39060
+ advance(point);
39061
+ const step = Math.min(remaining, length - distance);
39062
+ if (distance + step === distance || ++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39063
+ distance += step;
39064
+ remaining -= step;
39065
+ if (index % 2 === 0) {
39066
+ if (!current.length) current.push(point);
39067
+ current.push([start[0] + dx * distance / length, start[1] + dy * distance / length]);
39068
+ }
39069
+ }
39070
+ }
39071
+ flush();
39072
+ if (path.closed && result.length) {
39073
+ const first = result[0], last = result[result.length - 1];
39074
+ const start = path.points[0];
39075
+ const firstPoint = first.points[0], lastPoint = last.points[last.points.length - 1];
39076
+ if (firstPoint[0] === start[0] && firstPoint[1] === start[1] && lastPoint[0] === start[0] && lastPoint[1] === start[1]) {
39077
+ if (first === last) result[0] = { points: first.points, closed: true };
39078
+ else {
39079
+ result[0] = { points: [...last.points, ...first.points.slice(1)], closed: false };
39080
+ result.pop();
39081
+ }
39082
+ }
39083
+ }
39084
+ return result;
39085
+ }
39086
+ function strokeOutlines(paths, width, cap, join, miterLimit, dashArray = [], dashPhase = 0) {
39087
+ const half = width / 2;
39088
+ const contours = [];
39089
+ const pattern = dashArray.length % 2 ? [...dashArray, ...dashArray] : dashArray;
39090
+ let count = 0;
39091
+ let contour = [];
39092
+ const add = (x, y) => {
39093
+ if (++count > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke outline exceeds the vertex limit");
39094
+ contour.push([x, y]);
39095
+ };
39096
+ const arc = (point, dx1, dy1, dx2, dy2) => {
39097
+ let a1 = Math.atan2(dy1, dx1), a2 = Math.atan2(dy2, dx2);
39098
+ const ccw = a1 - a2 > 0 && a1 - a2 < Math.PI;
39099
+ const step = Math.acos(half / (half + 0.125)) * 2;
39100
+ add(point[0] + dx1, point[1] + dy1);
39101
+ if (step > 0) {
39102
+ if (!ccw) {
39103
+ if (a1 > a2) a2 += 2 * Math.PI;
39104
+ a2 -= step / 4;
39105
+ if ((a2 - a1) / step > MAX_STROKE_VERTICES - count) throw new PdfError("E_LIMIT", "Stroke arc exceeds the vertex limit");
39106
+ for (a1 += step; a1 < a2; a1 += step) add(point[0] + half * Math.cos(a1), point[1] + half * Math.sin(a1));
39107
+ } else {
39108
+ if (a1 < a2) a2 -= 2 * Math.PI;
39109
+ a2 += step / 4;
39110
+ if ((a1 - a2) / step > MAX_STROKE_VERTICES - count) throw new PdfError("E_LIMIT", "Stroke arc exceeds the vertex limit");
39111
+ for (a1 -= step; a1 > a2; a1 -= step) add(point[0] + half * Math.cos(a1), point[1] + half * Math.sin(a1));
39112
+ }
39113
+ }
39114
+ add(point[0] + dx2, point[1] + dy2);
39115
+ };
39116
+ const addCap = (point, next) => {
39117
+ const length = Math.hypot(next[0] - point[0], next[1] - point[1]);
39118
+ const dx = half * (next[1] - point[1]) / length;
39119
+ const dy = half * (next[0] - point[0]) / length;
39120
+ if (cap !== 1) {
39121
+ const sx = cap === 2 ? dy : 0, sy = cap === 2 ? dx : 0;
39122
+ add(point[0] - dx - sx, point[1] + dy - sy);
39123
+ add(point[0] + dx - sx, point[1] - dy - sy);
39124
+ } else {
39125
+ const angle = Math.atan2(dy, -dx);
39126
+ const step = Math.max(1e-3, Math.acos(half / (half + 0.125)) * 2);
39127
+ add(point[0] - dx, point[1] + dy);
39128
+ 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));
39129
+ add(point[0] + dx, point[1] - dy);
39130
+ }
39131
+ };
39132
+ const addJoin = (prev, point, next) => {
39133
+ const len1 = Math.hypot(point[0] - prev[0], point[1] - prev[1]);
39134
+ const len2 = Math.hypot(next[0] - point[0], next[1] - point[1]);
39135
+ const dx1 = half * (point[1] - prev[1]) / len1, dy1 = half * (point[0] - prev[0]) / len1;
39136
+ const dx2 = half * (next[1] - point[1]) / len2, dy2 = half * (next[0] - point[0]) / len2;
39137
+ const inner = (next[0] - point[0]) * (point[1] - prev[1]) - (next[1] - point[1]) * (point[0] - prev[0]) > 0;
39138
+ if (!inner && join === 1) {
39139
+ arc(point, dx1, -dy1, dx2, -dy2);
39140
+ return;
39141
+ }
39142
+ if (inner || join === 0) {
39143
+ const ax = prev[0] + dx1, ay = prev[1] - dy1;
39144
+ const bx = point[0] + dx1, by = point[1] - dy1;
39145
+ const cx = point[0] + dx2, cy = point[1] - dy2;
39146
+ const dx = next[0] + dx2, dy = next[1] - dy2;
39147
+ const den = (bx - ax) * (dy - cy) - (by - ay) * (dx - cx);
39148
+ if (Math.abs(den) >= 1e-30) {
39149
+ const t = ((ay - cy) * (dx - cx) - (ax - cx) * (dy - cy)) / den;
39150
+ const x = ax + (bx - ax) * t, y = ay + (by - ay) * t;
39151
+ if (Math.hypot(x - point[0], y - point[1]) <= half * (inner ? 1.01 : miterLimit)) {
39152
+ add(x, y);
39153
+ return;
39154
+ }
39155
+ } else if ((bx - prev[0]) * dy1 - (prev[1] - by) * dx1 < 0 !== (bx - next[0]) * dy1 - (next[1] - by) * dx1 < 0) {
39156
+ add(bx, by);
39157
+ return;
39158
+ }
39159
+ }
39160
+ add(point[0] + dx1, point[1] - dy1);
39161
+ add(point[0] + dx2, point[1] - dy2);
39162
+ };
39163
+ for (const path of paths) {
39164
+ for (const subpath of pattern.length ? dashSubpath(path, pattern, dashPhase) : [path]) {
39165
+ const points = [];
39166
+ for (const point of subpath.points) {
39167
+ const prev = points[points.length - 1];
39168
+ if (!prev || Math.hypot(prev[0] - point[0], prev[1] - point[1]) > 1e-14) points.push(point);
39169
+ }
39170
+ let closed = subpath.closed;
39171
+ 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();
39172
+ if (points.length < 3) closed = false;
39173
+ if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
39174
+ contour = [];
39175
+ const [x, y] = points[0];
39176
+ addCap([x, y], [x + 1, y]);
39177
+ addCap([x, y], [x - 1, y]);
39178
+ contours.push(contour);
39179
+ } else if (points.length >= 2) {
39180
+ contour = [];
39181
+ if (!closed) addCap(points[0], points[1]);
39182
+ for (let i = closed ? 0 : 1; i < points.length - (closed ? 0 : 1); i++) {
39183
+ addJoin(points[(i + points.length - 1) % points.length], points[i], points[(i + 1) % points.length]);
39184
+ }
39185
+ if (closed) {
39186
+ contours.push(contour);
39187
+ contour = [];
39188
+ } else addCap(points[points.length - 1], points[points.length - 2]);
39189
+ for (let i = points.length - (closed ? 1 : 2); i >= (closed ? 0 : 1); i--) {
39190
+ addJoin(points[(i + 1) % points.length], points[i], points[(i + points.length - 1) % points.length]);
39191
+ }
39192
+ contours.push(contour);
39193
+ }
39194
+ }
39195
+ }
39196
+ return contours;
39197
+ }
39022
39198
  function encodePng(bitmap) {
39023
39199
  return encodeRgbaToPng(bitmap.width, bitmap.height, bitmap.data);
39024
39200
  }
@@ -40109,111 +40285,116 @@ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMa
40109
40285
  rgba[idx + 2] = Math.round((effB * a + cbB * dstA * (1 - a)) / outA * 255);
40110
40286
  rgba[idx + 3] = Math.round(outA * 255);
40111
40287
  }
40112
- function drawAntiAliasedSegment(rgba, width, height, x0, y0, x1, y1, strokeWidth, color, alpha = 1, lineCap = 0, antialias = true, blendMode, clipMask) {
40113
- const halfW = Math.max(0.6, strokeWidth * 0.5);
40114
- const dx = x1 - x0;
40115
- const dy = y1 - y0;
40116
- const lenSq = dx * dx + dy * dy;
40117
- const segLen = Math.sqrt(lenSq);
40118
- const pad = lineCap === 2 ? halfW + 2 : halfW + 1;
40119
- const minX = Math.max(0, Math.floor(Math.min(x0, x1) - pad));
40120
- const maxX = Math.min(width - 1, Math.ceil(Math.max(x0, x1) + pad));
40121
- const minY = Math.max(0, Math.floor(Math.min(y0, y1) - pad));
40122
- const maxY = Math.min(height - 1, Math.ceil(Math.max(y0, y1) + pad));
40123
- for (let py = minY; py <= maxY; py++) {
40124
- for (let px = minX; px <= maxX; px++) {
40125
- const cx = px + 0.5;
40126
- const cy = py + 0.5;
40127
- if (segLen > 1e-6 && (lineCap === 0 || lineCap === 2)) {
40128
- const ux = dx / segLen;
40129
- const uy = dy / segLen;
40130
- const along = (cx - x0) * ux + (cy - y0) * uy;
40131
- const perp = Math.abs(-(cx - x0) * uy + (cy - y0) * ux);
40132
- const minAlong = lineCap === 2 ? -halfW : 0;
40133
- const maxAlong = lineCap === 2 ? segLen + halfW : segLen;
40134
- const overAlong = along < minAlong ? minAlong - along : along > maxAlong ? along - maxAlong : 0;
40135
- const dist2 = overAlong > 0 ? Math.max(perp, halfW + overAlong) : perp;
40136
- if (dist2 <= halfW + 0.75) {
40137
- const cov = antialias ? Math.max(0, Math.min(1, halfW + 0.5 - dist2)) : dist2 <= halfW + 0.25 ? 1 : 0;
40138
- blendPixel(rgba, width, height, px, py, color, cov * alpha, blendMode, clipMask);
40139
- }
40140
- continue;
40141
- }
40142
- let t = lenSq > 1e-6 ? ((cx - x0) * dx + (cy - y0) * dy) / lenSq : 0;
40143
- t = Math.max(0, Math.min(1, t));
40144
- const projX = x0 + t * dx;
40145
- const projY = y0 + t * dy;
40146
- const dist = Math.hypot(cx - projX, cy - projY);
40147
- if (dist <= halfW + 0.75) {
40148
- const cov = antialias ? Math.max(0, Math.min(1, halfW + 0.5 - dist)) : dist <= halfW + 0.25 ? 1 : 0;
40149
- blendPixel(rgba, width, height, px, py, color, cov * alpha, blendMode, clipMask);
40150
- }
40151
- }
40152
- }
40288
+ function segmentsToScreenPaths(segments, pageHeight, scale, toScreen = (x, y) => [x * scale, (pageHeight - y) * scale]) {
40289
+ const paths = [];
40290
+ let points = [];
40291
+ let current = [0, 0];
40292
+ for (const segment of segments) {
40293
+ if (segment.kind === "move") {
40294
+ if (points.length) paths.push({ points, closed: false });
40295
+ current = toScreen(segment.x, segment.y);
40296
+ points = [current];
40297
+ } else if (segment.kind === "line") {
40298
+ if (!points.length) points = [current];
40299
+ current = toScreen(segment.x, segment.y);
40300
+ points.push(current);
40301
+ } else if (segment.kind === "cubic") {
40302
+ if (!points.length) points = [current];
40303
+ const a = toScreen(segment.x1, segment.y1), b = toScreen(segment.x2, segment.y2);
40304
+ const end = toScreen(segment.x, segment.y);
40305
+ const curve = flattenCubic(current[0], current[1], a[0], a[1], b[0], b[1], end[0], end[1]);
40306
+ for (let i = 1; i < curve.length; i++) points.push(curve[i]);
40307
+ current = end;
40308
+ } else if (segment.kind === "close") {
40309
+ if (points.length) {
40310
+ paths.push({ points, closed: true });
40311
+ current = points[0];
40312
+ points = [];
40313
+ }
40314
+ } else if (segment.kind === "rect") {
40315
+ if (points.length) paths.push({ points, closed: false });
40316
+ const first = toScreen(segment.x, segment.y);
40317
+ paths.push({ points: [
40318
+ first,
40319
+ toScreen(segment.x + segment.width, segment.y),
40320
+ toScreen(segment.x + segment.width, segment.y + segment.height),
40321
+ toScreen(segment.x, segment.y + segment.height)
40322
+ ], closed: true });
40323
+ current = first;
40324
+ points = [];
40325
+ }
40326
+ }
40327
+ if (points.length) paths.push({ points, closed: false });
40328
+ return paths;
40329
+ }
40330
+ function inverseStrokeMatrix(matrix) {
40331
+ const [a, b, c, d, e, f] = matrix;
40332
+ const det = a * d - b * c;
40333
+ if (!Number.isFinite(det) || det === 0) return void 0;
40334
+ return [d / det, -b / det, -c / det, a / det, (c * f - d * e) / det, (b * e - a * f) / det];
40335
+ }
40336
+ function prepareStroke(path, scale) {
40337
+ const matrix = path.strokeMatrix ? [...path.strokeMatrix] : [1, 0, 0, 1, 0, 0];
40338
+ const [a, b, c, d] = matrix;
40339
+ const area = Math.abs(a * d - b * c) * scale * scale;
40340
+ if (!(area > 0) || !Number.isFinite(area)) return void 0;
40341
+ const normX = Math.hypot(a, b) * scale, normY = Math.hypot(c, d) * scale;
40342
+ let width = path.strokeWidth || 1;
40343
+ const scaleX = path.strokeWidth === 0 ? normY / area : Math.max(1, normY / (width * area));
40344
+ const scaleY = path.strokeWidth === 0 ? normX / area : Math.max(1, normX / (width * area));
40345
+ let dashArray = path.dashArray, dashPhase = path.dashPhase ?? 0;
40346
+ if (scaleX === scaleY) {
40347
+ width *= scaleX;
40348
+ } else {
40349
+ matrix[0] *= scaleX;
40350
+ matrix[1] *= scaleX;
40351
+ matrix[2] *= scaleY;
40352
+ matrix[3] *= scaleY;
40353
+ if (dashArray?.length) {
40354
+ const dashScale = Math.max(scaleX, scaleY);
40355
+ dashArray = dashArray.map((value) => value / dashScale);
40356
+ dashPhase /= dashScale;
40357
+ }
40358
+ }
40359
+ return { matrix, width, dashArray, dashPhase };
40360
+ }
40361
+ function strokeEdges(path, pageHeight, scale) {
40362
+ const stroke = prepareStroke(path, scale);
40363
+ if (!stroke) return [];
40364
+ const inverse = inverseStrokeMatrix(stroke.matrix);
40365
+ if (!inverse) return [];
40366
+ const [a, b, c, d, e, f] = stroke.matrix;
40367
+ const strokeScale = scale * Math.hypot(a, b, c, d);
40368
+ const project = (x, y) => [
40369
+ (inverse[0] * x + inverse[2] * y + inverse[4]) * strokeScale,
40370
+ (inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
40371
+ ];
40372
+ const toScreen = ([x, y]) => [
40373
+ (a * x / strokeScale + c * y / strokeScale + e) * scale,
40374
+ (pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
40375
+ ];
40376
+ const contours = strokeOutlines(
40377
+ segmentsToScreenPaths(path.segments, pageHeight, scale, project),
40378
+ stroke.width * strokeScale,
40379
+ path.lineCap ?? 0,
40380
+ path.lineJoin ?? 0,
40381
+ path.miterLimit ?? 10,
40382
+ stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
40383
+ stroke.dashPhase * strokeScale
40384
+ );
40385
+ return pathsToEdges(contours.map((points) => ({ points: points.map(toScreen), closed: true })));
40153
40386
  }
40154
- function segmentsToScreenEdges(segments, pageHeight, scale, closeSubpaths = false) {
40387
+ function pathsToEdges(paths, closeSubpaths = false) {
40155
40388
  const edges = [];
40156
- let curX = 0;
40157
- let curY = 0;
40158
- let startX = 0;
40159
- let startY = 0;
40160
- let hasOpenSubpath = false;
40161
- const toScreen = (x, y) => [x * scale, (pageHeight - y) * scale];
40162
- for (const seg of segments) {
40163
- if (seg.kind === "move") {
40164
- if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
40165
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
40166
- }
40167
- [curX, curY] = toScreen(seg.x, seg.y);
40168
- startX = curX;
40169
- startY = curY;
40170
- hasOpenSubpath = false;
40171
- } else if (seg.kind === "line") {
40172
- const [nx, ny] = toScreen(seg.x, seg.y);
40173
- edges.push({ x0: curX, y0: curY, x1: nx, y1: ny });
40174
- curX = nx;
40175
- curY = ny;
40176
- hasOpenSubpath = true;
40177
- } else if (seg.kind === "cubic") {
40178
- const [p1x, p1y] = toScreen(seg.x1, seg.y1);
40179
- const [p2x, p2y] = toScreen(seg.x2, seg.y2);
40180
- const [p3x, p3y] = toScreen(seg.x, seg.y);
40181
- const points = flattenCubic(curX, curY, p1x, p1y, p2x, p2y, p3x, p3y);
40182
- let px = curX;
40183
- let py = curY;
40184
- for (let i = 1; i < points.length; i++) {
40185
- const [qx, qy] = points[i];
40186
- edges.push({ x0: px, y0: py, x1: qx, y1: qy });
40187
- px = qx;
40188
- py = qy;
40189
- }
40190
- curX = p3x;
40191
- curY = p3y;
40192
- hasOpenSubpath = true;
40193
- } else if (seg.kind === "close") {
40194
- if (curX !== startX || curY !== startY) {
40195
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
40196
- curX = startX;
40197
- curY = startY;
40198
- }
40199
- hasOpenSubpath = false;
40200
- } else if (seg.kind === "rect") {
40201
- if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
40202
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
40203
- }
40204
- const [rx0, ry0] = toScreen(seg.x, seg.y);
40205
- const [rx1, ry1] = toScreen(seg.x + seg.width, seg.y + seg.height);
40206
- edges.push(
40207
- { x0: rx0, y0: ry0, x1: rx1, y1: ry0 },
40208
- { x0: rx1, y0: ry0, x1: rx1, y1: ry1 },
40209
- { x0: rx1, y0: ry1, x1: rx0, y1: ry1 },
40210
- { x0: rx0, y0: ry1, x1: rx0, y1: ry0 }
40211
- );
40212
- hasOpenSubpath = false;
40389
+ for (const { points, closed } of paths) {
40390
+ for (let i = 1; i < points.length; i++) {
40391
+ const a = points[i - 1], b = points[i];
40392
+ edges.push({ x0: a[0], y0: a[1], x1: b[0], y1: b[1] });
40393
+ }
40394
+ if ((closed || closeSubpaths) && points.length > 1) {
40395
+ const a = points[points.length - 1], b = points[0];
40396
+ edges.push({ x0: a[0], y0: a[1], x1: b[0], y1: b[1] });
40213
40397
  }
40214
- }
40215
- if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
40216
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
40217
40398
  }
40218
40399
  return edges;
40219
40400
  }
@@ -40400,7 +40581,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40400
40581
  for (const clip of clips) {
40401
40582
  const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
40402
40583
  const layer = new Uint8Array(width * height * 4);
40403
- fillEdgesScanline4x4(layer, width, height, segmentsToScreenEdges(segments, displayList.height, scale, true), { r: 1, g: 1, b: 1 }, 1, fillRule);
40584
+ fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
40404
40585
  for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
40405
40586
  }
40406
40587
  cachedClips = clips;
@@ -40447,62 +40628,28 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40447
40628
  if (operation.kind === "path") {
40448
40629
  const path = operation.value;
40449
40630
  if (path.fillColor) {
40450
- const edges = segmentsToScreenEdges(path.segments, displayList.height, scale, true);
40631
+ const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale), true);
40451
40632
  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;
40452
40633
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
40453
40634
  }
40454
40635
  if (path.strokeColor) {
40455
- const edges = segmentsToScreenEdges(path.segments, displayList.height, scale, false);
40456
- const rawSw = path.strokeWidth * scale;
40457
- const sw = Math.max(1, rawSw);
40636
+ const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
40458
40637
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
40459
- const dashArr = path.dashArray && path.dashArray.length > 0 ? path.dashArray.map((d) => Math.max(0, d * scale)) : void 0;
40460
- const dashCycle = dashArr ? dashArr.reduce((a, b) => a + b, 0) : 0;
40461
- let dashDist = (path.dashPhase ?? 0) * scale % (dashCycle || 1);
40462
- if (dashDist < 0) dashDist += dashCycle;
40463
- for (const e of edges) {
40464
- if (!dashArr || dashCycle <= 1e-4) {
40465
- 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);
40466
- } else {
40467
- const dx = e.x1 - e.x0;
40468
- const dy = e.y1 - e.y0;
40469
- const edgeLen = Math.hypot(dx, dy);
40470
- if (edgeLen <= 1e-4) continue;
40471
- let pos = 0;
40472
- while (pos < edgeLen) {
40473
- let cycleRem = dashDist % dashCycle;
40474
- let dIdx = 0;
40475
- while (dIdx < dashArr.length - 1 && cycleRem >= dashArr[dIdx]) {
40476
- cycleRem -= dashArr[dIdx];
40477
- dIdx++;
40478
- }
40479
- const segRemainInDash = Math.max(1e-4, dashArr[dIdx] - cycleRem);
40480
- const step = Math.min(edgeLen - pos, segRemainInDash);
40481
- if (dIdx % 2 === 0) {
40482
- const t0 = pos / edgeLen;
40483
- const t1 = (pos + step) / edgeLen;
40484
- drawAntiAliasedSegment(
40485
- rgba,
40486
- width,
40487
- height,
40488
- e.x0 + dx * t0,
40489
- e.y0 + dy * t0,
40490
- e.x0 + dx * t1,
40491
- e.y0 + dy * t1,
40492
- sw,
40493
- path.strokeColor,
40494
- strokeAlpha,
40495
- path.lineCap ?? 0,
40496
- original.kind === "glyph" ? aaTxt : aaVec,
40497
- path.blendMode,
40498
- clipMask
40499
- );
40500
- }
40501
- pos += step;
40502
- dashDist = (dashDist + step) % dashCycle;
40503
- }
40504
- }
40505
- }
40638
+ const edges = strokeEdges(path, displayList.height, scale);
40639
+ 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;
40640
+ fillEdgesScanline4x4(
40641
+ rgba,
40642
+ width,
40643
+ height,
40644
+ edges,
40645
+ path.strokeColor,
40646
+ strokeAlpha,
40647
+ "nonzero",
40648
+ clipScreen,
40649
+ original.kind === "glyph" ? aaTxt : aaVec,
40650
+ path.blendMode,
40651
+ clipMask
40652
+ );
40506
40653
  }
40507
40654
  } else if (operation.kind === "image") {
40508
40655
  const img = operation.value;
@@ -40638,17 +40785,19 @@ function svgImage(image, pageHeight) {
40638
40785
  const [a, b, c, d, e, f] = image.matrix;
40639
40786
  return `<image width="1" height="1" preserveAspectRatio="none" transform="matrix(${a} ${-b} ${-c} ${d} ${e + c} ${pageHeight - f - d})" href="data:image/png;base64,${btoa(chunks.join(""))}"/>`;
40640
40787
  }
40641
- function svgPathData(segments, height) {
40788
+ function svgPathData(segments, height, matrix) {
40642
40789
  const dParts = [];
40790
+ const point = (x, y) => matrix ? `${matrix[0] * x + matrix[2] * y + matrix[4]} ${height - matrix[1] * x - matrix[3] * y - matrix[5]}` : `${x} ${height - y}`;
40643
40791
  for (const seg of segments) {
40644
40792
  if (seg.kind === "move") {
40645
- dParts.push(`M ${seg.x} ${height - seg.y}`);
40793
+ dParts.push(`M ${point(seg.x, seg.y)}`);
40646
40794
  } else if (seg.kind === "line") {
40647
- dParts.push(`L ${seg.x} ${height - seg.y}`);
40795
+ dParts.push(`L ${point(seg.x, seg.y)}`);
40648
40796
  } else if (seg.kind === "cubic") {
40649
- dParts.push(`C ${seg.x1} ${height - seg.y1} ${seg.x2} ${height - seg.y2} ${seg.x} ${height - seg.y}`);
40797
+ dParts.push(`C ${point(seg.x1, seg.y1)} ${point(seg.x2, seg.y2)} ${point(seg.x, seg.y)}`);
40650
40798
  } else if (seg.kind === "rect") {
40651
- dParts.push(`M ${seg.x} ${height - seg.y} h ${seg.width} v ${-seg.height} h ${-seg.width} Z`);
40799
+ if (matrix) dParts.push(`M ${point(seg.x, seg.y)} L ${point(seg.x + seg.width, seg.y)} L ${point(seg.x + seg.width, seg.y + seg.height)} L ${point(seg.x, seg.y + seg.height)} Z`);
40800
+ else dParts.push(`M ${seg.x} ${height - seg.y} h ${seg.width} v ${-seg.height} h ${-seg.width} Z`);
40652
40801
  } else if (seg.kind === "close") {
40653
40802
  dParts.push("Z");
40654
40803
  }
@@ -40727,21 +40876,25 @@ function renderDisplayListToSvg(displayList, options = {}) {
40727
40876
  parts.push("</g>");
40728
40877
  } else if (operation.kind === "path") {
40729
40878
  const p = operation.value;
40730
- const pathData = svgPathData(p.segments, displayList.height);
40879
+ const prepared = p.strokeColor ? prepareStroke(p, Math.max(scaleX, scaleY)) : void 0;
40880
+ const matrix = prepared && (prepared.matrix[0] !== 1 || prepared.matrix[1] !== 0 || prepared.matrix[2] !== 0 || prepared.matrix[3] !== 1) ? prepared.matrix : void 0;
40881
+ const inverse = matrix ? inverseStrokeMatrix(matrix) : void 0;
40882
+ const pathData = svgPathData(p.segments, inverse ? 0 : displayList.height, inverse);
40883
+ const transformAttr = inverse && matrix ? ` transform="matrix(${matrix[0]} ${-matrix[1]} ${-matrix[2]} ${matrix[3]} ${matrix[4]} ${displayList.height - matrix[5]})"` : "";
40731
40884
  if (pathData) {
40732
40885
  const fill = p.fillColor ? `rgb(${Math.round(p.fillColor.r * 255)},${Math.round(p.fillColor.g * 255)},${Math.round(p.fillColor.b * 255)})` : "none";
40733
- const stroke = p.strokeColor ? `rgb(${Math.round(p.strokeColor.r * 255)},${Math.round(p.strokeColor.g * 255)},${Math.round(p.strokeColor.b * 255)})` : "none";
40886
+ const stroke = p.strokeColor && prepared ? `rgb(${Math.round(p.strokeColor.r * 255)},${Math.round(p.strokeColor.g * 255)},${Math.round(p.strokeColor.b * 255)})` : "none";
40734
40887
  const fillRuleAttr = p.fillRule === "evenodd" ? ` fill-rule="evenodd"` : "";
40735
40888
  const fillOpacityAttr = p.fillAlpha !== void 0 && p.fillAlpha < 1 ? ` fill-opacity="${p.fillAlpha}"` : "";
40736
40889
  const strokeOpacityAttr = p.strokeAlpha !== void 0 && p.strokeAlpha < 1 ? ` stroke-opacity="${p.strokeAlpha}"` : "";
40737
- const strokeWidthAttr = p.strokeWidth <= 0 ? ` stroke-width="1" vector-effect="non-scaling-stroke"` : ` stroke-width="${p.strokeWidth}"`;
40890
+ const strokeWidthAttr = p.strokeWidth <= 0 && !matrix && !p.dashArray?.length ? ` stroke-width="1" vector-effect="non-scaling-stroke"` : ` stroke-width="${prepared?.width ?? p.strokeWidth}"`;
40738
40891
  const lineCapAttr = p.lineCap === 1 ? ` stroke-linecap="round"` : p.lineCap === 2 ? ` stroke-linecap="square"` : "";
40739
40892
  const lineJoinAttr = p.lineJoin === 1 ? ` stroke-linejoin="round"` : p.lineJoin === 2 ? ` stroke-linejoin="bevel"` : "";
40740
40893
  const miterLimitAttr = p.miterLimit !== void 0 && p.miterLimit !== 10 ? ` stroke-miterlimit="${p.miterLimit}"` : "";
40741
- const dashArrayAttr = p.dashArray && p.dashArray.length > 0 ? ` stroke-dasharray="${p.dashArray.join(" ")}"` : "";
40742
- const dashOffsetAttr = p.dashPhase ? ` stroke-dashoffset="${p.dashPhase}"` : "";
40894
+ const dashArrayAttr = prepared?.dashArray?.length ? ` stroke-dasharray="${prepared.dashArray.join(" ")}"` : "";
40895
+ const dashOffsetAttr = prepared?.dashPhase ? ` stroke-dashoffset="${prepared.dashPhase}"` : "";
40743
40896
  const labelAttr = original.kind === "glyph" ? ` aria-label="${escapeXmlText(original.value.unicode)}"` : "";
40744
- parts.push(` <path${labelAttr} d="${pathData}" fill="${fill}"${fillRuleAttr}${fillOpacityAttr} stroke="${stroke}"${strokeOpacityAttr}${strokeWidthAttr}${lineCapAttr}${lineJoinAttr}${miterLimitAttr}${dashArrayAttr}${dashOffsetAttr}/>`);
40897
+ parts.push(` <path${labelAttr}${transformAttr} d="${pathData}" fill="${fill}"${fillRuleAttr}${fillOpacityAttr} stroke="${stroke}"${strokeOpacityAttr}${strokeWidthAttr}${lineCapAttr}${lineJoinAttr}${miterLimitAttr}${dashArrayAttr}${dashOffsetAttr}/>`);
40745
40898
  }
40746
40899
  } else if (operation.kind === "image") {
40747
40900
  parts.push(` ${svgImage(operation.value, displayList.height)}`);
@@ -42382,3 +42535,15 @@ export {
42382
42535
  * Copyright 2012 Mozilla Foundation. Licensed under Apache-2.0.
42383
42536
  * See THIRD_PARTY_NOTICES.md for the source revision and adaptations.
42384
42537
  */
42538
+ /*!
42539
+ * Anti-Grain Geometry - Version 2.3
42540
+ * Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
42541
+ *
42542
+ * Permission to copy, use, modify, sell and distribute this software
42543
+ * is granted provided this copyright notice appears in all copies.
42544
+ * This software is provided "as is" without express or implied
42545
+ * warranty, and with no claim as to its suitability for any purpose.
42546
+ *
42547
+ * Adapted from PDFium agg_math_stroke.h and agg_vcgen_stroke.cpp.
42548
+ * See THIRD_PARTY_NOTICES.md for the source revision and adaptations.
42549
+ */