@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
@@ -36049,11 +36049,10 @@ function evaluateContentStreamToDisplayList(params) {
36049
36049
  } else if (operator === "d") {
36050
36050
  const arrNode = ops[0]?.kind === "array" ? ops[0] : void 0;
36051
36051
  if (arrNode) {
36052
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
36053
- const nums = arrNode.items.map((it) => it.kind === "number" ? it.value * ctmScale : 0).filter((v) => v >= 0);
36052
+ const nums = arrNode.items.map((it) => it.kind === "number" ? it.value : 0).filter((v) => v >= 0);
36054
36053
  const sum = nums.reduce((a, b) => a + b, 0);
36055
36054
  st.dashArray = sum > 0 ? nums : void 0;
36056
- st.dashPhase = num(1, 0) * ctmScale;
36055
+ st.dashPhase = num(1, 0);
36057
36056
  } else {
36058
36057
  st.dashArray = void 0;
36059
36058
  st.dashPhase = void 0;
@@ -36589,15 +36588,14 @@ function evaluateContentStreamToDisplayList(params) {
36589
36588
  break;
36590
36589
  }
36591
36590
  const fillRule = node.paint.includes("*") ? "evenodd" : "nonzero";
36592
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
36593
- const scaledStrokeWidth = st.strokeWidth === 0 ? 0 : st.strokeWidth * ctmScale;
36594
36591
  emit({ kind: "path", value: {
36595
36592
  segments: transformedSegments,
36596
36593
  fillColor: isFill && !evaluatedFillPattern ? st.fillColor : void 0,
36597
36594
  fillAlpha: isFill && !evaluatedFillPattern ? st.fillAlpha : void 0,
36598
36595
  strokeColor: isStroke ? st.strokeColor : void 0,
36599
36596
  strokeAlpha: isStroke ? st.strokeAlpha : void 0,
36600
- strokeWidth: scaledStrokeWidth,
36597
+ strokeWidth: st.strokeWidth,
36598
+ ...isStroke ? { strokeMatrix: [...st.ctm] } : {},
36601
36599
  ...st.lineCap !== 0 ? { lineCap: st.lineCap } : {},
36602
36600
  ...st.lineJoin !== 0 ? { lineJoin: st.lineJoin } : {},
36603
36601
  ...st.miterLimit !== 10 ? { miterLimit: st.miterLimit } : {},
@@ -36785,14 +36783,14 @@ function evaluateContentStreamToDisplayList(params) {
36785
36783
  if (st.textRenderMode >= 4 && st.textRenderMode <= 7) pendingTextClip.push(...transformedGlyphSegs);
36786
36784
  const isFillGlyph = st.textRenderMode === 0 || st.textRenderMode === 2 || st.textRenderMode === 4 || st.textRenderMode === 6;
36787
36785
  const isStrokeGlyph = st.textRenderMode === 1 || st.textRenderMode === 2 || st.textRenderMode === 5 || st.textRenderMode === 6;
36788
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
36789
36786
  const paint = {
36790
36787
  segments: transformedGlyphSegs,
36791
36788
  fillColor: isFillGlyph ? st.fillColor : void 0,
36792
36789
  fillAlpha: isFillGlyph ? st.fillAlpha : void 0,
36793
36790
  strokeColor: isStrokeGlyph ? st.strokeColor : void 0,
36794
36791
  strokeAlpha: isStrokeGlyph ? st.strokeAlpha : void 0,
36795
- strokeWidth: isStrokeGlyph ? st.strokeWidth * ctmScale : 0,
36792
+ strokeWidth: isStrokeGlyph ? st.strokeWidth : 0,
36793
+ ...isStrokeGlyph ? { strokeMatrix: [...st.ctm] } : {},
36796
36794
  fillRule: "nonzero",
36797
36795
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
36798
36796
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
@@ -39170,6 +39168,184 @@ function downscaleImage(image, widthScale, heightScale) {
39170
39168
  }
39171
39169
  return image;
39172
39170
  }
39171
+ var MAX_STROKE_VERTICES = 1e6;
39172
+ function dashSubpath(path, pattern, phase) {
39173
+ const cycle = pattern.reduce((sum, value) => sum + value, 0);
39174
+ if (!(cycle > 0)) return [path];
39175
+ let offset = (phase % cycle + cycle) % cycle, index = 0;
39176
+ while (offset > 0) {
39177
+ if (offset < pattern[index]) break;
39178
+ offset -= pattern[index];
39179
+ index = (index + 1) % pattern.length;
39180
+ }
39181
+ let remaining = pattern[index] - offset;
39182
+ const points = path.closed ? [...path.points, path.points[0]] : path.points;
39183
+ const result = [];
39184
+ let current = [];
39185
+ let steps = 0;
39186
+ const flush = () => {
39187
+ if (current.length) result.push({ points: current, closed: false });
39188
+ current = [];
39189
+ };
39190
+ const advance = (point) => {
39191
+ while (remaining <= 0) {
39192
+ if (++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39193
+ if (index % 2 === 0) {
39194
+ if (pattern[index] === 0) result.push({ points: [point, point], closed: false });
39195
+ flush();
39196
+ }
39197
+ index = (index + 1) % pattern.length;
39198
+ remaining = pattern[index];
39199
+ }
39200
+ };
39201
+ for (let i = 1; i < points.length; i++) {
39202
+ const start = points[i - 1], end = points[i];
39203
+ const dx = end[0] - start[0], dy = end[1] - start[1];
39204
+ const length = Math.hypot(dx, dy);
39205
+ if (!Number.isFinite(length) || length / cycle * pattern.length > MAX_STROKE_VERTICES) {
39206
+ throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39207
+ }
39208
+ let distance = 0;
39209
+ while (distance < length) {
39210
+ const point = [start[0] + dx * distance / length, start[1] + dy * distance / length];
39211
+ advance(point);
39212
+ const step = Math.min(remaining, length - distance);
39213
+ if (distance + step === distance || ++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39214
+ distance += step;
39215
+ remaining -= step;
39216
+ if (index % 2 === 0) {
39217
+ if (!current.length) current.push(point);
39218
+ current.push([start[0] + dx * distance / length, start[1] + dy * distance / length]);
39219
+ }
39220
+ }
39221
+ }
39222
+ flush();
39223
+ if (path.closed && result.length) {
39224
+ const first = result[0], last = result[result.length - 1];
39225
+ const start = path.points[0];
39226
+ const firstPoint = first.points[0], lastPoint = last.points[last.points.length - 1];
39227
+ if (firstPoint[0] === start[0] && firstPoint[1] === start[1] && lastPoint[0] === start[0] && lastPoint[1] === start[1]) {
39228
+ if (first === last) result[0] = { points: first.points, closed: true };
39229
+ else {
39230
+ result[0] = { points: [...last.points, ...first.points.slice(1)], closed: false };
39231
+ result.pop();
39232
+ }
39233
+ }
39234
+ }
39235
+ return result;
39236
+ }
39237
+ function strokeOutlines(paths, width, cap, join, miterLimit, dashArray = [], dashPhase = 0) {
39238
+ const half = width / 2;
39239
+ const contours = [];
39240
+ const pattern = dashArray.length % 2 ? [...dashArray, ...dashArray] : dashArray;
39241
+ let count = 0;
39242
+ let contour = [];
39243
+ const add = (x, y) => {
39244
+ if (++count > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke outline exceeds the vertex limit");
39245
+ contour.push([x, y]);
39246
+ };
39247
+ const arc = (point, dx1, dy1, dx2, dy2) => {
39248
+ let a1 = Math.atan2(dy1, dx1), a2 = Math.atan2(dy2, dx2);
39249
+ const ccw = a1 - a2 > 0 && a1 - a2 < Math.PI;
39250
+ const step = Math.acos(half / (half + 0.125)) * 2;
39251
+ add(point[0] + dx1, point[1] + dy1);
39252
+ if (step > 0) {
39253
+ if (!ccw) {
39254
+ if (a1 > a2) a2 += 2 * Math.PI;
39255
+ a2 -= step / 4;
39256
+ if ((a2 - a1) / step > MAX_STROKE_VERTICES - count) throw new PdfError("E_LIMIT", "Stroke arc exceeds the vertex limit");
39257
+ for (a1 += step; a1 < a2; a1 += step) add(point[0] + half * Math.cos(a1), point[1] + half * Math.sin(a1));
39258
+ } else {
39259
+ if (a1 < a2) a2 -= 2 * Math.PI;
39260
+ a2 += step / 4;
39261
+ if ((a1 - a2) / step > MAX_STROKE_VERTICES - count) throw new PdfError("E_LIMIT", "Stroke arc exceeds the vertex limit");
39262
+ for (a1 -= step; a1 > a2; a1 -= step) add(point[0] + half * Math.cos(a1), point[1] + half * Math.sin(a1));
39263
+ }
39264
+ }
39265
+ add(point[0] + dx2, point[1] + dy2);
39266
+ };
39267
+ const addCap = (point, next) => {
39268
+ const length = Math.hypot(next[0] - point[0], next[1] - point[1]);
39269
+ const dx = half * (next[1] - point[1]) / length;
39270
+ const dy = half * (next[0] - point[0]) / length;
39271
+ if (cap !== 1) {
39272
+ const sx = cap === 2 ? dy : 0, sy = cap === 2 ? dx : 0;
39273
+ add(point[0] - dx - sx, point[1] + dy - sy);
39274
+ add(point[0] + dx - sx, point[1] - dy - sy);
39275
+ } else {
39276
+ const angle = Math.atan2(dy, -dx);
39277
+ const step = Math.max(1e-3, Math.acos(half / (half + 0.125)) * 2);
39278
+ add(point[0] - dx, point[1] + dy);
39279
+ 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));
39280
+ add(point[0] + dx, point[1] - dy);
39281
+ }
39282
+ };
39283
+ const addJoin = (prev, point, next) => {
39284
+ const len1 = Math.hypot(point[0] - prev[0], point[1] - prev[1]);
39285
+ const len2 = Math.hypot(next[0] - point[0], next[1] - point[1]);
39286
+ const dx1 = half * (point[1] - prev[1]) / len1, dy1 = half * (point[0] - prev[0]) / len1;
39287
+ const dx2 = half * (next[1] - point[1]) / len2, dy2 = half * (next[0] - point[0]) / len2;
39288
+ const inner = (next[0] - point[0]) * (point[1] - prev[1]) - (next[1] - point[1]) * (point[0] - prev[0]) > 0;
39289
+ if (!inner && join === 1) {
39290
+ arc(point, dx1, -dy1, dx2, -dy2);
39291
+ return;
39292
+ }
39293
+ if (inner || join === 0) {
39294
+ const ax = prev[0] + dx1, ay = prev[1] - dy1;
39295
+ const bx = point[0] + dx1, by = point[1] - dy1;
39296
+ const cx = point[0] + dx2, cy = point[1] - dy2;
39297
+ const dx = next[0] + dx2, dy = next[1] - dy2;
39298
+ const den = (bx - ax) * (dy - cy) - (by - ay) * (dx - cx);
39299
+ if (Math.abs(den) >= 1e-30) {
39300
+ const t = ((ay - cy) * (dx - cx) - (ax - cx) * (dy - cy)) / den;
39301
+ const x = ax + (bx - ax) * t, y = ay + (by - ay) * t;
39302
+ if (Math.hypot(x - point[0], y - point[1]) <= half * (inner ? 1.01 : miterLimit)) {
39303
+ add(x, y);
39304
+ return;
39305
+ }
39306
+ } else if ((bx - prev[0]) * dy1 - (prev[1] - by) * dx1 < 0 !== (bx - next[0]) * dy1 - (next[1] - by) * dx1 < 0) {
39307
+ add(bx, by);
39308
+ return;
39309
+ }
39310
+ }
39311
+ add(point[0] + dx1, point[1] - dy1);
39312
+ add(point[0] + dx2, point[1] - dy2);
39313
+ };
39314
+ for (const path of paths) {
39315
+ for (const subpath of pattern.length ? dashSubpath(path, pattern, dashPhase) : [path]) {
39316
+ const points = [];
39317
+ for (const point of subpath.points) {
39318
+ const prev = points[points.length - 1];
39319
+ if (!prev || Math.hypot(prev[0] - point[0], prev[1] - point[1]) > 1e-14) points.push(point);
39320
+ }
39321
+ let closed = subpath.closed;
39322
+ 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();
39323
+ if (points.length < 3) closed = false;
39324
+ if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
39325
+ contour = [];
39326
+ const [x, y] = points[0];
39327
+ addCap([x, y], [x + 1, y]);
39328
+ addCap([x, y], [x - 1, y]);
39329
+ contours.push(contour);
39330
+ } else if (points.length >= 2) {
39331
+ contour = [];
39332
+ if (!closed) addCap(points[0], points[1]);
39333
+ for (let i = closed ? 0 : 1; i < points.length - (closed ? 0 : 1); i++) {
39334
+ addJoin(points[(i + points.length - 1) % points.length], points[i], points[(i + 1) % points.length]);
39335
+ }
39336
+ if (closed) {
39337
+ contours.push(contour);
39338
+ contour = [];
39339
+ } else addCap(points[points.length - 1], points[points.length - 2]);
39340
+ for (let i = points.length - (closed ? 1 : 2); i >= (closed ? 0 : 1); i--) {
39341
+ addJoin(points[(i + 1) % points.length], points[i], points[(i + points.length - 1) % points.length]);
39342
+ }
39343
+ contours.push(contour);
39344
+ }
39345
+ }
39346
+ }
39347
+ return contours;
39348
+ }
39173
39349
  function encodePng(bitmap) {
39174
39350
  return encodeRgbaToPng(bitmap.width, bitmap.height, bitmap.data);
39175
39351
  }
@@ -40091,111 +40267,116 @@ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMa
40091
40267
  rgba[idx + 2] = Math.round((effB * a + cbB * dstA * (1 - a)) / outA * 255);
40092
40268
  rgba[idx + 3] = Math.round(outA * 255);
40093
40269
  }
40094
- function drawAntiAliasedSegment(rgba, width, height, x0, y0, x1, y1, strokeWidth, color, alpha = 1, lineCap = 0, antialias = true, blendMode, clipMask) {
40095
- const halfW = Math.max(0.6, strokeWidth * 0.5);
40096
- const dx = x1 - x0;
40097
- const dy = y1 - y0;
40098
- const lenSq = dx * dx + dy * dy;
40099
- const segLen = Math.sqrt(lenSq);
40100
- const pad = lineCap === 2 ? halfW + 2 : halfW + 1;
40101
- const minX = Math.max(0, Math.floor(Math.min(x0, x1) - pad));
40102
- const maxX = Math.min(width - 1, Math.ceil(Math.max(x0, x1) + pad));
40103
- const minY = Math.max(0, Math.floor(Math.min(y0, y1) - pad));
40104
- const maxY = Math.min(height - 1, Math.ceil(Math.max(y0, y1) + pad));
40105
- for (let py = minY; py <= maxY; py++) {
40106
- for (let px = minX; px <= maxX; px++) {
40107
- const cx = px + 0.5;
40108
- const cy = py + 0.5;
40109
- if (segLen > 1e-6 && (lineCap === 0 || lineCap === 2)) {
40110
- const ux = dx / segLen;
40111
- const uy = dy / segLen;
40112
- const along = (cx - x0) * ux + (cy - y0) * uy;
40113
- const perp = Math.abs(-(cx - x0) * uy + (cy - y0) * ux);
40114
- const minAlong = lineCap === 2 ? -halfW : 0;
40115
- const maxAlong = lineCap === 2 ? segLen + halfW : segLen;
40116
- const overAlong = along < minAlong ? minAlong - along : along > maxAlong ? along - maxAlong : 0;
40117
- const dist2 = overAlong > 0 ? Math.max(perp, halfW + overAlong) : perp;
40118
- if (dist2 <= halfW + 0.75) {
40119
- const cov = antialias ? Math.max(0, Math.min(1, halfW + 0.5 - dist2)) : dist2 <= halfW + 0.25 ? 1 : 0;
40120
- blendPixel(rgba, width, height, px, py, color, cov * alpha, blendMode, clipMask);
40121
- }
40122
- continue;
40123
- }
40124
- let t = lenSq > 1e-6 ? ((cx - x0) * dx + (cy - y0) * dy) / lenSq : 0;
40125
- t = Math.max(0, Math.min(1, t));
40126
- const projX = x0 + t * dx;
40127
- const projY = y0 + t * dy;
40128
- const dist = Math.hypot(cx - projX, cy - projY);
40129
- if (dist <= halfW + 0.75) {
40130
- const cov = antialias ? Math.max(0, Math.min(1, halfW + 0.5 - dist)) : dist <= halfW + 0.25 ? 1 : 0;
40131
- blendPixel(rgba, width, height, px, py, color, cov * alpha, blendMode, clipMask);
40132
- }
40133
- }
40134
- }
40270
+ function segmentsToScreenPaths(segments, pageHeight, scale, toScreen = (x, y) => [x * scale, (pageHeight - y) * scale]) {
40271
+ const paths = [];
40272
+ let points = [];
40273
+ let current = [0, 0];
40274
+ for (const segment of segments) {
40275
+ if (segment.kind === "move") {
40276
+ if (points.length) paths.push({ points, closed: false });
40277
+ current = toScreen(segment.x, segment.y);
40278
+ points = [current];
40279
+ } else if (segment.kind === "line") {
40280
+ if (!points.length) points = [current];
40281
+ current = toScreen(segment.x, segment.y);
40282
+ points.push(current);
40283
+ } else if (segment.kind === "cubic") {
40284
+ if (!points.length) points = [current];
40285
+ const a = toScreen(segment.x1, segment.y1), b = toScreen(segment.x2, segment.y2);
40286
+ const end = toScreen(segment.x, segment.y);
40287
+ const curve = flattenCubic(current[0], current[1], a[0], a[1], b[0], b[1], end[0], end[1]);
40288
+ for (let i = 1; i < curve.length; i++) points.push(curve[i]);
40289
+ current = end;
40290
+ } else if (segment.kind === "close") {
40291
+ if (points.length) {
40292
+ paths.push({ points, closed: true });
40293
+ current = points[0];
40294
+ points = [];
40295
+ }
40296
+ } else if (segment.kind === "rect") {
40297
+ if (points.length) paths.push({ points, closed: false });
40298
+ const first = toScreen(segment.x, segment.y);
40299
+ paths.push({ points: [
40300
+ first,
40301
+ toScreen(segment.x + segment.width, segment.y),
40302
+ toScreen(segment.x + segment.width, segment.y + segment.height),
40303
+ toScreen(segment.x, segment.y + segment.height)
40304
+ ], closed: true });
40305
+ current = first;
40306
+ points = [];
40307
+ }
40308
+ }
40309
+ if (points.length) paths.push({ points, closed: false });
40310
+ return paths;
40311
+ }
40312
+ function inverseStrokeMatrix(matrix) {
40313
+ const [a, b, c, d, e, f] = matrix;
40314
+ const det = a * d - b * c;
40315
+ if (!Number.isFinite(det) || det === 0) return void 0;
40316
+ return [d / det, -b / det, -c / det, a / det, (c * f - d * e) / det, (b * e - a * f) / det];
40317
+ }
40318
+ function prepareStroke(path, scale) {
40319
+ const matrix = path.strokeMatrix ? [...path.strokeMatrix] : [1, 0, 0, 1, 0, 0];
40320
+ const [a, b, c, d] = matrix;
40321
+ const area = Math.abs(a * d - b * c) * scale * scale;
40322
+ if (!(area > 0) || !Number.isFinite(area)) return void 0;
40323
+ const normX = Math.hypot(a, b) * scale, normY = Math.hypot(c, d) * scale;
40324
+ let width = path.strokeWidth || 1;
40325
+ const scaleX = path.strokeWidth === 0 ? normY / area : Math.max(1, normY / (width * area));
40326
+ const scaleY = path.strokeWidth === 0 ? normX / area : Math.max(1, normX / (width * area));
40327
+ let dashArray = path.dashArray, dashPhase = path.dashPhase ?? 0;
40328
+ if (scaleX === scaleY) {
40329
+ width *= scaleX;
40330
+ } else {
40331
+ matrix[0] *= scaleX;
40332
+ matrix[1] *= scaleX;
40333
+ matrix[2] *= scaleY;
40334
+ matrix[3] *= scaleY;
40335
+ if (dashArray?.length) {
40336
+ const dashScale = Math.max(scaleX, scaleY);
40337
+ dashArray = dashArray.map((value) => value / dashScale);
40338
+ dashPhase /= dashScale;
40339
+ }
40340
+ }
40341
+ return { matrix, width, dashArray, dashPhase };
40342
+ }
40343
+ function strokeEdges(path, pageHeight, scale) {
40344
+ const stroke = prepareStroke(path, scale);
40345
+ if (!stroke) return [];
40346
+ const inverse = inverseStrokeMatrix(stroke.matrix);
40347
+ if (!inverse) return [];
40348
+ const [a, b, c, d, e, f] = stroke.matrix;
40349
+ const strokeScale = scale * Math.hypot(a, b, c, d);
40350
+ const project = (x, y) => [
40351
+ (inverse[0] * x + inverse[2] * y + inverse[4]) * strokeScale,
40352
+ (inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
40353
+ ];
40354
+ const toScreen = ([x, y]) => [
40355
+ (a * x / strokeScale + c * y / strokeScale + e) * scale,
40356
+ (pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
40357
+ ];
40358
+ const contours = strokeOutlines(
40359
+ segmentsToScreenPaths(path.segments, pageHeight, scale, project),
40360
+ stroke.width * strokeScale,
40361
+ path.lineCap ?? 0,
40362
+ path.lineJoin ?? 0,
40363
+ path.miterLimit ?? 10,
40364
+ stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
40365
+ stroke.dashPhase * strokeScale
40366
+ );
40367
+ return pathsToEdges(contours.map((points) => ({ points: points.map(toScreen), closed: true })));
40135
40368
  }
40136
- function segmentsToScreenEdges(segments, pageHeight, scale, closeSubpaths = false) {
40369
+ function pathsToEdges(paths, closeSubpaths = false) {
40137
40370
  const edges = [];
40138
- let curX = 0;
40139
- let curY = 0;
40140
- let startX = 0;
40141
- let startY = 0;
40142
- let hasOpenSubpath = false;
40143
- const toScreen = (x, y) => [x * scale, (pageHeight - y) * scale];
40144
- for (const seg of segments) {
40145
- if (seg.kind === "move") {
40146
- if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
40147
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
40148
- }
40149
- [curX, curY] = toScreen(seg.x, seg.y);
40150
- startX = curX;
40151
- startY = curY;
40152
- hasOpenSubpath = false;
40153
- } else if (seg.kind === "line") {
40154
- const [nx, ny] = toScreen(seg.x, seg.y);
40155
- edges.push({ x0: curX, y0: curY, x1: nx, y1: ny });
40156
- curX = nx;
40157
- curY = ny;
40158
- hasOpenSubpath = true;
40159
- } else if (seg.kind === "cubic") {
40160
- const [p1x, p1y] = toScreen(seg.x1, seg.y1);
40161
- const [p2x, p2y] = toScreen(seg.x2, seg.y2);
40162
- const [p3x, p3y] = toScreen(seg.x, seg.y);
40163
- const points = flattenCubic(curX, curY, p1x, p1y, p2x, p2y, p3x, p3y);
40164
- let px = curX;
40165
- let py = curY;
40166
- for (let i = 1; i < points.length; i++) {
40167
- const [qx, qy] = points[i];
40168
- edges.push({ x0: px, y0: py, x1: qx, y1: qy });
40169
- px = qx;
40170
- py = qy;
40171
- }
40172
- curX = p3x;
40173
- curY = p3y;
40174
- hasOpenSubpath = true;
40175
- } else if (seg.kind === "close") {
40176
- if (curX !== startX || curY !== startY) {
40177
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
40178
- curX = startX;
40179
- curY = startY;
40180
- }
40181
- hasOpenSubpath = false;
40182
- } else if (seg.kind === "rect") {
40183
- if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
40184
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
40185
- }
40186
- const [rx0, ry0] = toScreen(seg.x, seg.y);
40187
- const [rx1, ry1] = toScreen(seg.x + seg.width, seg.y + seg.height);
40188
- edges.push(
40189
- { x0: rx0, y0: ry0, x1: rx1, y1: ry0 },
40190
- { x0: rx1, y0: ry0, x1: rx1, y1: ry1 },
40191
- { x0: rx1, y0: ry1, x1: rx0, y1: ry1 },
40192
- { x0: rx0, y0: ry1, x1: rx0, y1: ry0 }
40193
- );
40194
- hasOpenSubpath = false;
40371
+ for (const { points, closed } of paths) {
40372
+ for (let i = 1; i < points.length; i++) {
40373
+ const a = points[i - 1], b = points[i];
40374
+ edges.push({ x0: a[0], y0: a[1], x1: b[0], y1: b[1] });
40375
+ }
40376
+ if ((closed || closeSubpaths) && points.length > 1) {
40377
+ const a = points[points.length - 1], b = points[0];
40378
+ edges.push({ x0: a[0], y0: a[1], x1: b[0], y1: b[1] });
40195
40379
  }
40196
- }
40197
- if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
40198
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
40199
40380
  }
40200
40381
  return edges;
40201
40382
  }
@@ -40382,7 +40563,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40382
40563
  for (const clip of clips) {
40383
40564
  const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
40384
40565
  const layer = new Uint8Array(width * height * 4);
40385
- fillEdgesScanline4x4(layer, width, height, segmentsToScreenEdges(segments, displayList.height, scale, true), { r: 1, g: 1, b: 1 }, 1, fillRule);
40566
+ fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
40386
40567
  for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
40387
40568
  }
40388
40569
  cachedClips = clips;
@@ -40429,62 +40610,28 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40429
40610
  if (operation.kind === "path") {
40430
40611
  const path = operation.value;
40431
40612
  if (path.fillColor) {
40432
- const edges = segmentsToScreenEdges(path.segments, displayList.height, scale, true);
40613
+ const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale), true);
40433
40614
  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;
40434
40615
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
40435
40616
  }
40436
40617
  if (path.strokeColor) {
40437
- const edges = segmentsToScreenEdges(path.segments, displayList.height, scale, false);
40438
- const rawSw = path.strokeWidth * scale;
40439
- const sw = Math.max(1, rawSw);
40618
+ const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
40440
40619
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
40441
- const dashArr = path.dashArray && path.dashArray.length > 0 ? path.dashArray.map((d) => Math.max(0, d * scale)) : void 0;
40442
- const dashCycle = dashArr ? dashArr.reduce((a, b) => a + b, 0) : 0;
40443
- let dashDist = (path.dashPhase ?? 0) * scale % (dashCycle || 1);
40444
- if (dashDist < 0) dashDist += dashCycle;
40445
- for (const e of edges) {
40446
- if (!dashArr || dashCycle <= 1e-4) {
40447
- 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);
40448
- } else {
40449
- const dx = e.x1 - e.x0;
40450
- const dy = e.y1 - e.y0;
40451
- const edgeLen = Math.hypot(dx, dy);
40452
- if (edgeLen <= 1e-4) continue;
40453
- let pos = 0;
40454
- while (pos < edgeLen) {
40455
- let cycleRem = dashDist % dashCycle;
40456
- let dIdx = 0;
40457
- while (dIdx < dashArr.length - 1 && cycleRem >= dashArr[dIdx]) {
40458
- cycleRem -= dashArr[dIdx];
40459
- dIdx++;
40460
- }
40461
- const segRemainInDash = Math.max(1e-4, dashArr[dIdx] - cycleRem);
40462
- const step = Math.min(edgeLen - pos, segRemainInDash);
40463
- if (dIdx % 2 === 0) {
40464
- const t0 = pos / edgeLen;
40465
- const t1 = (pos + step) / edgeLen;
40466
- drawAntiAliasedSegment(
40467
- rgba,
40468
- width,
40469
- height,
40470
- e.x0 + dx * t0,
40471
- e.y0 + dy * t0,
40472
- e.x0 + dx * t1,
40473
- e.y0 + dy * t1,
40474
- sw,
40475
- path.strokeColor,
40476
- strokeAlpha,
40477
- path.lineCap ?? 0,
40478
- original.kind === "glyph" ? aaTxt : aaVec,
40479
- path.blendMode,
40480
- clipMask
40481
- );
40482
- }
40483
- pos += step;
40484
- dashDist = (dashDist + step) % dashCycle;
40485
- }
40486
- }
40487
- }
40620
+ const edges = strokeEdges(path, displayList.height, scale);
40621
+ 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;
40622
+ fillEdgesScanline4x4(
40623
+ rgba,
40624
+ width,
40625
+ height,
40626
+ edges,
40627
+ path.strokeColor,
40628
+ strokeAlpha,
40629
+ "nonzero",
40630
+ clipScreen,
40631
+ original.kind === "glyph" ? aaTxt : aaVec,
40632
+ path.blendMode,
40633
+ clipMask
40634
+ );
40488
40635
  }
40489
40636
  } else if (operation.kind === "image") {
40490
40637
  const img = operation.value;
@@ -42605,3 +42752,15 @@ export {
42605
42752
  * Copyright 2012 Mozilla Foundation. Licensed under Apache-2.0.
42606
42753
  * See THIRD_PARTY_NOTICES.md for the source revision and adaptations.
42607
42754
  */
42755
+ /*!
42756
+ * Anti-Grain Geometry - Version 2.3
42757
+ * Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
42758
+ *
42759
+ * Permission to copy, use, modify, sell and distribute this software
42760
+ * is granted provided this copyright notice appears in all copies.
42761
+ * This software is provided "as is" without express or implied
42762
+ * warranty, and with no claim as to its suitability for any purpose.
42763
+ *
42764
+ * Adapted from PDFium agg_math_stroke.h and agg_vcgen_stroke.cpp.
42765
+ * See THIRD_PARTY_NOTICES.md for the source revision and adaptations.
42766
+ */