@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
@@ -36417,11 +36417,10 @@ function evaluateContentStreamToDisplayList(params) {
36417
36417
  } else if (operator === "d") {
36418
36418
  const arrNode = ops[0]?.kind === "array" ? ops[0] : void 0;
36419
36419
  if (arrNode) {
36420
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
36421
- const nums = arrNode.items.map((it) => it.kind === "number" ? it.value * ctmScale : 0).filter((v) => v >= 0);
36420
+ const nums = arrNode.items.map((it) => it.kind === "number" ? it.value : 0).filter((v) => v >= 0);
36422
36421
  const sum = nums.reduce((a, b) => a + b, 0);
36423
36422
  st.dashArray = sum > 0 ? nums : void 0;
36424
- st.dashPhase = num(1, 0) * ctmScale;
36423
+ st.dashPhase = num(1, 0);
36425
36424
  } else {
36426
36425
  st.dashArray = void 0;
36427
36426
  st.dashPhase = void 0;
@@ -36957,15 +36956,14 @@ function evaluateContentStreamToDisplayList(params) {
36957
36956
  break;
36958
36957
  }
36959
36958
  const fillRule = node.paint.includes("*") ? "evenodd" : "nonzero";
36960
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
36961
- const scaledStrokeWidth = st.strokeWidth === 0 ? 0 : st.strokeWidth * ctmScale;
36962
36959
  emit({ kind: "path", value: {
36963
36960
  segments: transformedSegments,
36964
36961
  fillColor: isFill && !evaluatedFillPattern ? st.fillColor : void 0,
36965
36962
  fillAlpha: isFill && !evaluatedFillPattern ? st.fillAlpha : void 0,
36966
36963
  strokeColor: isStroke ? st.strokeColor : void 0,
36967
36964
  strokeAlpha: isStroke ? st.strokeAlpha : void 0,
36968
- strokeWidth: scaledStrokeWidth,
36965
+ strokeWidth: st.strokeWidth,
36966
+ ...isStroke ? { strokeMatrix: [...st.ctm] } : {},
36969
36967
  ...st.lineCap !== 0 ? { lineCap: st.lineCap } : {},
36970
36968
  ...st.lineJoin !== 0 ? { lineJoin: st.lineJoin } : {},
36971
36969
  ...st.miterLimit !== 10 ? { miterLimit: st.miterLimit } : {},
@@ -37153,14 +37151,14 @@ function evaluateContentStreamToDisplayList(params) {
37153
37151
  if (st.textRenderMode >= 4 && st.textRenderMode <= 7) pendingTextClip.push(...transformedGlyphSegs);
37154
37152
  const isFillGlyph = st.textRenderMode === 0 || st.textRenderMode === 2 || st.textRenderMode === 4 || st.textRenderMode === 6;
37155
37153
  const isStrokeGlyph = st.textRenderMode === 1 || st.textRenderMode === 2 || st.textRenderMode === 5 || st.textRenderMode === 6;
37156
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
37157
37154
  const paint = {
37158
37155
  segments: transformedGlyphSegs,
37159
37156
  fillColor: isFillGlyph ? st.fillColor : void 0,
37160
37157
  fillAlpha: isFillGlyph ? st.fillAlpha : void 0,
37161
37158
  strokeColor: isStrokeGlyph ? st.strokeColor : void 0,
37162
37159
  strokeAlpha: isStrokeGlyph ? st.strokeAlpha : void 0,
37163
- strokeWidth: isStrokeGlyph ? st.strokeWidth * ctmScale : 0,
37160
+ strokeWidth: isStrokeGlyph ? st.strokeWidth : 0,
37161
+ ...isStrokeGlyph ? { strokeMatrix: [...st.ctm] } : {},
37164
37162
  fillRule: "nonzero",
37165
37163
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
37166
37164
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
@@ -40232,6 +40230,186 @@ function downscaleImage(image, widthScale, heightScale) {
40232
40230
  return image;
40233
40231
  }
40234
40232
 
40233
+ // src/render/stroke.ts
40234
+ var MAX_STROKE_VERTICES = 1e6;
40235
+ function dashSubpath(path, pattern, phase) {
40236
+ const cycle = pattern.reduce((sum, value) => sum + value, 0);
40237
+ if (!(cycle > 0)) return [path];
40238
+ let offset = (phase % cycle + cycle) % cycle, index = 0;
40239
+ while (offset > 0) {
40240
+ if (offset < pattern[index]) break;
40241
+ offset -= pattern[index];
40242
+ index = (index + 1) % pattern.length;
40243
+ }
40244
+ let remaining = pattern[index] - offset;
40245
+ const points = path.closed ? [...path.points, path.points[0]] : path.points;
40246
+ const result = [];
40247
+ let current = [];
40248
+ let steps = 0;
40249
+ const flush = () => {
40250
+ if (current.length) result.push({ points: current, closed: false });
40251
+ current = [];
40252
+ };
40253
+ const advance = (point) => {
40254
+ while (remaining <= 0) {
40255
+ if (++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
40256
+ if (index % 2 === 0) {
40257
+ if (pattern[index] === 0) result.push({ points: [point, point], closed: false });
40258
+ flush();
40259
+ }
40260
+ index = (index + 1) % pattern.length;
40261
+ remaining = pattern[index];
40262
+ }
40263
+ };
40264
+ for (let i = 1; i < points.length; i++) {
40265
+ const start = points[i - 1], end = points[i];
40266
+ const dx = end[0] - start[0], dy = end[1] - start[1];
40267
+ const length = Math.hypot(dx, dy);
40268
+ if (!Number.isFinite(length) || length / cycle * pattern.length > MAX_STROKE_VERTICES) {
40269
+ throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
40270
+ }
40271
+ let distance = 0;
40272
+ while (distance < length) {
40273
+ const point = [start[0] + dx * distance / length, start[1] + dy * distance / length];
40274
+ advance(point);
40275
+ const step = Math.min(remaining, length - distance);
40276
+ if (distance + step === distance || ++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
40277
+ distance += step;
40278
+ remaining -= step;
40279
+ if (index % 2 === 0) {
40280
+ if (!current.length) current.push(point);
40281
+ current.push([start[0] + dx * distance / length, start[1] + dy * distance / length]);
40282
+ }
40283
+ }
40284
+ }
40285
+ flush();
40286
+ if (path.closed && result.length) {
40287
+ const first = result[0], last = result[result.length - 1];
40288
+ const start = path.points[0];
40289
+ const firstPoint = first.points[0], lastPoint = last.points[last.points.length - 1];
40290
+ if (firstPoint[0] === start[0] && firstPoint[1] === start[1] && lastPoint[0] === start[0] && lastPoint[1] === start[1]) {
40291
+ if (first === last) result[0] = { points: first.points, closed: true };
40292
+ else {
40293
+ result[0] = { points: [...last.points, ...first.points.slice(1)], closed: false };
40294
+ result.pop();
40295
+ }
40296
+ }
40297
+ }
40298
+ return result;
40299
+ }
40300
+ function strokeOutlines(paths, width, cap, join, miterLimit, dashArray = [], dashPhase = 0) {
40301
+ const half = width / 2;
40302
+ const contours = [];
40303
+ const pattern = dashArray.length % 2 ? [...dashArray, ...dashArray] : dashArray;
40304
+ let count = 0;
40305
+ let contour = [];
40306
+ const add = (x, y) => {
40307
+ if (++count > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke outline exceeds the vertex limit");
40308
+ contour.push([x, y]);
40309
+ };
40310
+ const arc = (point, dx1, dy1, dx2, dy2) => {
40311
+ let a1 = Math.atan2(dy1, dx1), a2 = Math.atan2(dy2, dx2);
40312
+ const ccw = a1 - a2 > 0 && a1 - a2 < Math.PI;
40313
+ const step = Math.acos(half / (half + 0.125)) * 2;
40314
+ add(point[0] + dx1, point[1] + dy1);
40315
+ if (step > 0) {
40316
+ if (!ccw) {
40317
+ if (a1 > a2) a2 += 2 * Math.PI;
40318
+ a2 -= step / 4;
40319
+ if ((a2 - a1) / step > MAX_STROKE_VERTICES - count) throw new PdfError("E_LIMIT", "Stroke arc exceeds the vertex limit");
40320
+ for (a1 += step; a1 < a2; a1 += step) add(point[0] + half * Math.cos(a1), point[1] + half * Math.sin(a1));
40321
+ } else {
40322
+ if (a1 < a2) a2 -= 2 * Math.PI;
40323
+ a2 += step / 4;
40324
+ if ((a1 - a2) / step > MAX_STROKE_VERTICES - count) throw new PdfError("E_LIMIT", "Stroke arc exceeds the vertex limit");
40325
+ for (a1 -= step; a1 > a2; a1 -= step) add(point[0] + half * Math.cos(a1), point[1] + half * Math.sin(a1));
40326
+ }
40327
+ }
40328
+ add(point[0] + dx2, point[1] + dy2);
40329
+ };
40330
+ const addCap = (point, next) => {
40331
+ const length = Math.hypot(next[0] - point[0], next[1] - point[1]);
40332
+ const dx = half * (next[1] - point[1]) / length;
40333
+ const dy = half * (next[0] - point[0]) / length;
40334
+ if (cap !== 1) {
40335
+ const sx = cap === 2 ? dy : 0, sy = cap === 2 ? dx : 0;
40336
+ add(point[0] - dx - sx, point[1] + dy - sy);
40337
+ add(point[0] + dx - sx, point[1] - dy - sy);
40338
+ } else {
40339
+ const angle = Math.atan2(dy, -dx);
40340
+ const step = Math.max(1e-3, Math.acos(half / (half + 0.125)) * 2);
40341
+ add(point[0] - dx, point[1] + dy);
40342
+ 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));
40343
+ add(point[0] + dx, point[1] - dy);
40344
+ }
40345
+ };
40346
+ const addJoin = (prev, point, next) => {
40347
+ const len1 = Math.hypot(point[0] - prev[0], point[1] - prev[1]);
40348
+ const len2 = Math.hypot(next[0] - point[0], next[1] - point[1]);
40349
+ const dx1 = half * (point[1] - prev[1]) / len1, dy1 = half * (point[0] - prev[0]) / len1;
40350
+ const dx2 = half * (next[1] - point[1]) / len2, dy2 = half * (next[0] - point[0]) / len2;
40351
+ const inner = (next[0] - point[0]) * (point[1] - prev[1]) - (next[1] - point[1]) * (point[0] - prev[0]) > 0;
40352
+ if (!inner && join === 1) {
40353
+ arc(point, dx1, -dy1, dx2, -dy2);
40354
+ return;
40355
+ }
40356
+ if (inner || join === 0) {
40357
+ const ax = prev[0] + dx1, ay = prev[1] - dy1;
40358
+ const bx = point[0] + dx1, by = point[1] - dy1;
40359
+ const cx = point[0] + dx2, cy = point[1] - dy2;
40360
+ const dx = next[0] + dx2, dy = next[1] - dy2;
40361
+ const den = (bx - ax) * (dy - cy) - (by - ay) * (dx - cx);
40362
+ if (Math.abs(den) >= 1e-30) {
40363
+ const t = ((ay - cy) * (dx - cx) - (ax - cx) * (dy - cy)) / den;
40364
+ const x = ax + (bx - ax) * t, y = ay + (by - ay) * t;
40365
+ if (Math.hypot(x - point[0], y - point[1]) <= half * (inner ? 1.01 : miterLimit)) {
40366
+ add(x, y);
40367
+ return;
40368
+ }
40369
+ } else if ((bx - prev[0]) * dy1 - (prev[1] - by) * dx1 < 0 !== (bx - next[0]) * dy1 - (next[1] - by) * dx1 < 0) {
40370
+ add(bx, by);
40371
+ return;
40372
+ }
40373
+ }
40374
+ add(point[0] + dx1, point[1] - dy1);
40375
+ add(point[0] + dx2, point[1] - dy2);
40376
+ };
40377
+ for (const path of paths) {
40378
+ for (const subpath of pattern.length ? dashSubpath(path, pattern, dashPhase) : [path]) {
40379
+ const points = [];
40380
+ for (const point of subpath.points) {
40381
+ const prev = points[points.length - 1];
40382
+ if (!prev || Math.hypot(prev[0] - point[0], prev[1] - point[1]) > 1e-14) points.push(point);
40383
+ }
40384
+ let closed = subpath.closed;
40385
+ 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();
40386
+ if (points.length < 3) closed = false;
40387
+ if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
40388
+ contour = [];
40389
+ const [x, y] = points[0];
40390
+ addCap([x, y], [x + 1, y]);
40391
+ addCap([x, y], [x - 1, y]);
40392
+ contours.push(contour);
40393
+ } else if (points.length >= 2) {
40394
+ contour = [];
40395
+ if (!closed) addCap(points[0], points[1]);
40396
+ for (let i = closed ? 0 : 1; i < points.length - (closed ? 0 : 1); i++) {
40397
+ addJoin(points[(i + points.length - 1) % points.length], points[i], points[(i + 1) % points.length]);
40398
+ }
40399
+ if (closed) {
40400
+ contours.push(contour);
40401
+ contour = [];
40402
+ } else addCap(points[points.length - 1], points[points.length - 2]);
40403
+ for (let i = points.length - (closed ? 1 : 2); i >= (closed ? 0 : 1); i--) {
40404
+ addJoin(points[(i + 1) % points.length], points[i], points[(i + points.length - 1) % points.length]);
40405
+ }
40406
+ contours.push(contour);
40407
+ }
40408
+ }
40409
+ }
40410
+ return contours;
40411
+ }
40412
+
40235
40413
  // src/render/raster.ts
40236
40414
  function encodePng(bitmap) {
40237
40415
  return encodeRgbaToPng(bitmap.width, bitmap.height, bitmap.data);
@@ -41323,111 +41501,116 @@ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMa
41323
41501
  rgba[idx + 2] = Math.round((effB * a + cbB * dstA * (1 - a)) / outA * 255);
41324
41502
  rgba[idx + 3] = Math.round(outA * 255);
41325
41503
  }
41326
- function drawAntiAliasedSegment(rgba, width, height, x0, y0, x1, y1, strokeWidth, color, alpha = 1, lineCap = 0, antialias = true, blendMode, clipMask) {
41327
- const halfW = Math.max(0.6, strokeWidth * 0.5);
41328
- const dx = x1 - x0;
41329
- const dy = y1 - y0;
41330
- const lenSq = dx * dx + dy * dy;
41331
- const segLen = Math.sqrt(lenSq);
41332
- const pad = lineCap === 2 ? halfW + 2 : halfW + 1;
41333
- const minX = Math.max(0, Math.floor(Math.min(x0, x1) - pad));
41334
- const maxX = Math.min(width - 1, Math.ceil(Math.max(x0, x1) + pad));
41335
- const minY = Math.max(0, Math.floor(Math.min(y0, y1) - pad));
41336
- const maxY = Math.min(height - 1, Math.ceil(Math.max(y0, y1) + pad));
41337
- for (let py = minY; py <= maxY; py++) {
41338
- for (let px = minX; px <= maxX; px++) {
41339
- const cx = px + 0.5;
41340
- const cy = py + 0.5;
41341
- if (segLen > 1e-6 && (lineCap === 0 || lineCap === 2)) {
41342
- const ux = dx / segLen;
41343
- const uy = dy / segLen;
41344
- const along = (cx - x0) * ux + (cy - y0) * uy;
41345
- const perp = Math.abs(-(cx - x0) * uy + (cy - y0) * ux);
41346
- const minAlong = lineCap === 2 ? -halfW : 0;
41347
- const maxAlong = lineCap === 2 ? segLen + halfW : segLen;
41348
- const overAlong = along < minAlong ? minAlong - along : along > maxAlong ? along - maxAlong : 0;
41349
- const dist2 = overAlong > 0 ? Math.max(perp, halfW + overAlong) : perp;
41350
- if (dist2 <= halfW + 0.75) {
41351
- const cov = antialias ? Math.max(0, Math.min(1, halfW + 0.5 - dist2)) : dist2 <= halfW + 0.25 ? 1 : 0;
41352
- blendPixel(rgba, width, height, px, py, color, cov * alpha, blendMode, clipMask);
41353
- }
41354
- continue;
41355
- }
41356
- let t = lenSq > 1e-6 ? ((cx - x0) * dx + (cy - y0) * dy) / lenSq : 0;
41357
- t = Math.max(0, Math.min(1, t));
41358
- const projX = x0 + t * dx;
41359
- const projY = y0 + t * dy;
41360
- const dist = Math.hypot(cx - projX, cy - projY);
41361
- if (dist <= halfW + 0.75) {
41362
- const cov = antialias ? Math.max(0, Math.min(1, halfW + 0.5 - dist)) : dist <= halfW + 0.25 ? 1 : 0;
41363
- blendPixel(rgba, width, height, px, py, color, cov * alpha, blendMode, clipMask);
41364
- }
41365
- }
41366
- }
41504
+ function segmentsToScreenPaths(segments, pageHeight, scale, toScreen = (x, y) => [x * scale, (pageHeight - y) * scale]) {
41505
+ const paths = [];
41506
+ let points = [];
41507
+ let current = [0, 0];
41508
+ for (const segment of segments) {
41509
+ if (segment.kind === "move") {
41510
+ if (points.length) paths.push({ points, closed: false });
41511
+ current = toScreen(segment.x, segment.y);
41512
+ points = [current];
41513
+ } else if (segment.kind === "line") {
41514
+ if (!points.length) points = [current];
41515
+ current = toScreen(segment.x, segment.y);
41516
+ points.push(current);
41517
+ } else if (segment.kind === "cubic") {
41518
+ if (!points.length) points = [current];
41519
+ const a = toScreen(segment.x1, segment.y1), b = toScreen(segment.x2, segment.y2);
41520
+ const end = toScreen(segment.x, segment.y);
41521
+ const curve = flattenCubic(current[0], current[1], a[0], a[1], b[0], b[1], end[0], end[1]);
41522
+ for (let i = 1; i < curve.length; i++) points.push(curve[i]);
41523
+ current = end;
41524
+ } else if (segment.kind === "close") {
41525
+ if (points.length) {
41526
+ paths.push({ points, closed: true });
41527
+ current = points[0];
41528
+ points = [];
41529
+ }
41530
+ } else if (segment.kind === "rect") {
41531
+ if (points.length) paths.push({ points, closed: false });
41532
+ const first = toScreen(segment.x, segment.y);
41533
+ paths.push({ points: [
41534
+ first,
41535
+ toScreen(segment.x + segment.width, segment.y),
41536
+ toScreen(segment.x + segment.width, segment.y + segment.height),
41537
+ toScreen(segment.x, segment.y + segment.height)
41538
+ ], closed: true });
41539
+ current = first;
41540
+ points = [];
41541
+ }
41542
+ }
41543
+ if (points.length) paths.push({ points, closed: false });
41544
+ return paths;
41545
+ }
41546
+ function inverseStrokeMatrix(matrix) {
41547
+ const [a, b, c, d, e, f] = matrix;
41548
+ const det = a * d - b * c;
41549
+ if (!Number.isFinite(det) || det === 0) return void 0;
41550
+ return [d / det, -b / det, -c / det, a / det, (c * f - d * e) / det, (b * e - a * f) / det];
41551
+ }
41552
+ function prepareStroke(path, scale) {
41553
+ const matrix = path.strokeMatrix ? [...path.strokeMatrix] : [1, 0, 0, 1, 0, 0];
41554
+ const [a, b, c, d] = matrix;
41555
+ const area = Math.abs(a * d - b * c) * scale * scale;
41556
+ if (!(area > 0) || !Number.isFinite(area)) return void 0;
41557
+ const normX = Math.hypot(a, b) * scale, normY = Math.hypot(c, d) * scale;
41558
+ let width = path.strokeWidth || 1;
41559
+ const scaleX = path.strokeWidth === 0 ? normY / area : Math.max(1, normY / (width * area));
41560
+ const scaleY = path.strokeWidth === 0 ? normX / area : Math.max(1, normX / (width * area));
41561
+ let dashArray = path.dashArray, dashPhase = path.dashPhase ?? 0;
41562
+ if (scaleX === scaleY) {
41563
+ width *= scaleX;
41564
+ } else {
41565
+ matrix[0] *= scaleX;
41566
+ matrix[1] *= scaleX;
41567
+ matrix[2] *= scaleY;
41568
+ matrix[3] *= scaleY;
41569
+ if (dashArray?.length) {
41570
+ const dashScale = Math.max(scaleX, scaleY);
41571
+ dashArray = dashArray.map((value) => value / dashScale);
41572
+ dashPhase /= dashScale;
41573
+ }
41574
+ }
41575
+ return { matrix, width, dashArray, dashPhase };
41576
+ }
41577
+ function strokeEdges(path, pageHeight, scale) {
41578
+ const stroke = prepareStroke(path, scale);
41579
+ if (!stroke) return [];
41580
+ const inverse = inverseStrokeMatrix(stroke.matrix);
41581
+ if (!inverse) return [];
41582
+ const [a, b, c, d, e, f] = stroke.matrix;
41583
+ const strokeScale = scale * Math.hypot(a, b, c, d);
41584
+ const project = (x, y) => [
41585
+ (inverse[0] * x + inverse[2] * y + inverse[4]) * strokeScale,
41586
+ (inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
41587
+ ];
41588
+ const toScreen = ([x, y]) => [
41589
+ (a * x / strokeScale + c * y / strokeScale + e) * scale,
41590
+ (pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
41591
+ ];
41592
+ const contours = strokeOutlines(
41593
+ segmentsToScreenPaths(path.segments, pageHeight, scale, project),
41594
+ stroke.width * strokeScale,
41595
+ path.lineCap ?? 0,
41596
+ path.lineJoin ?? 0,
41597
+ path.miterLimit ?? 10,
41598
+ stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
41599
+ stroke.dashPhase * strokeScale
41600
+ );
41601
+ return pathsToEdges(contours.map((points) => ({ points: points.map(toScreen), closed: true })));
41367
41602
  }
41368
- function segmentsToScreenEdges(segments, pageHeight, scale, closeSubpaths = false) {
41603
+ function pathsToEdges(paths, closeSubpaths = false) {
41369
41604
  const edges = [];
41370
- let curX = 0;
41371
- let curY = 0;
41372
- let startX = 0;
41373
- let startY = 0;
41374
- let hasOpenSubpath = false;
41375
- const toScreen = (x, y) => [x * scale, (pageHeight - y) * scale];
41376
- for (const seg of segments) {
41377
- if (seg.kind === "move") {
41378
- if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
41379
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
41380
- }
41381
- [curX, curY] = toScreen(seg.x, seg.y);
41382
- startX = curX;
41383
- startY = curY;
41384
- hasOpenSubpath = false;
41385
- } else if (seg.kind === "line") {
41386
- const [nx, ny] = toScreen(seg.x, seg.y);
41387
- edges.push({ x0: curX, y0: curY, x1: nx, y1: ny });
41388
- curX = nx;
41389
- curY = ny;
41390
- hasOpenSubpath = true;
41391
- } else if (seg.kind === "cubic") {
41392
- const [p1x, p1y] = toScreen(seg.x1, seg.y1);
41393
- const [p2x, p2y] = toScreen(seg.x2, seg.y2);
41394
- const [p3x, p3y] = toScreen(seg.x, seg.y);
41395
- const points = flattenCubic(curX, curY, p1x, p1y, p2x, p2y, p3x, p3y);
41396
- let px = curX;
41397
- let py = curY;
41398
- for (let i = 1; i < points.length; i++) {
41399
- const [qx, qy] = points[i];
41400
- edges.push({ x0: px, y0: py, x1: qx, y1: qy });
41401
- px = qx;
41402
- py = qy;
41403
- }
41404
- curX = p3x;
41405
- curY = p3y;
41406
- hasOpenSubpath = true;
41407
- } else if (seg.kind === "close") {
41408
- if (curX !== startX || curY !== startY) {
41409
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
41410
- curX = startX;
41411
- curY = startY;
41412
- }
41413
- hasOpenSubpath = false;
41414
- } else if (seg.kind === "rect") {
41415
- if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
41416
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
41417
- }
41418
- const [rx0, ry0] = toScreen(seg.x, seg.y);
41419
- const [rx1, ry1] = toScreen(seg.x + seg.width, seg.y + seg.height);
41420
- edges.push(
41421
- { x0: rx0, y0: ry0, x1: rx1, y1: ry0 },
41422
- { x0: rx1, y0: ry0, x1: rx1, y1: ry1 },
41423
- { x0: rx1, y0: ry1, x1: rx0, y1: ry1 },
41424
- { x0: rx0, y0: ry1, x1: rx0, y1: ry0 }
41425
- );
41426
- hasOpenSubpath = false;
41605
+ for (const { points, closed } of paths) {
41606
+ for (let i = 1; i < points.length; i++) {
41607
+ const a = points[i - 1], b = points[i];
41608
+ edges.push({ x0: a[0], y0: a[1], x1: b[0], y1: b[1] });
41609
+ }
41610
+ if ((closed || closeSubpaths) && points.length > 1) {
41611
+ const a = points[points.length - 1], b = points[0];
41612
+ edges.push({ x0: a[0], y0: a[1], x1: b[0], y1: b[1] });
41427
41613
  }
41428
- }
41429
- if (closeSubpaths && hasOpenSubpath && (curX !== startX || curY !== startY)) {
41430
- edges.push({ x0: curX, y0: curY, x1: startX, y1: startY });
41431
41614
  }
41432
41615
  return edges;
41433
41616
  }
@@ -41614,7 +41797,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
41614
41797
  for (const clip of clips) {
41615
41798
  const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
41616
41799
  const layer = new Uint8Array(width * height * 4);
41617
- fillEdgesScanline4x4(layer, width, height, segmentsToScreenEdges(segments, displayList.height, scale, true), { r: 1, g: 1, b: 1 }, 1, fillRule);
41800
+ fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
41618
41801
  for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
41619
41802
  }
41620
41803
  cachedClips = clips;
@@ -41661,62 +41844,28 @@ function renderDisplayListToBitmap(displayList, options = {}) {
41661
41844
  if (operation.kind === "path") {
41662
41845
  const path = operation.value;
41663
41846
  if (path.fillColor) {
41664
- const edges = segmentsToScreenEdges(path.segments, displayList.height, scale, true);
41847
+ const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale), true);
41665
41848
  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;
41666
41849
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
41667
41850
  }
41668
41851
  if (path.strokeColor) {
41669
- const edges = segmentsToScreenEdges(path.segments, displayList.height, scale, false);
41670
- const rawSw = path.strokeWidth * scale;
41671
- const sw = Math.max(1, rawSw);
41852
+ const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
41672
41853
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
41673
- const dashArr = path.dashArray && path.dashArray.length > 0 ? path.dashArray.map((d) => Math.max(0, d * scale)) : void 0;
41674
- const dashCycle = dashArr ? dashArr.reduce((a, b) => a + b, 0) : 0;
41675
- let dashDist = (path.dashPhase ?? 0) * scale % (dashCycle || 1);
41676
- if (dashDist < 0) dashDist += dashCycle;
41677
- for (const e of edges) {
41678
- if (!dashArr || dashCycle <= 1e-4) {
41679
- 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);
41680
- } else {
41681
- const dx = e.x1 - e.x0;
41682
- const dy = e.y1 - e.y0;
41683
- const edgeLen = Math.hypot(dx, dy);
41684
- if (edgeLen <= 1e-4) continue;
41685
- let pos = 0;
41686
- while (pos < edgeLen) {
41687
- let cycleRem = dashDist % dashCycle;
41688
- let dIdx = 0;
41689
- while (dIdx < dashArr.length - 1 && cycleRem >= dashArr[dIdx]) {
41690
- cycleRem -= dashArr[dIdx];
41691
- dIdx++;
41692
- }
41693
- const segRemainInDash = Math.max(1e-4, dashArr[dIdx] - cycleRem);
41694
- const step = Math.min(edgeLen - pos, segRemainInDash);
41695
- if (dIdx % 2 === 0) {
41696
- const t0 = pos / edgeLen;
41697
- const t1 = (pos + step) / edgeLen;
41698
- drawAntiAliasedSegment(
41699
- rgba,
41700
- width,
41701
- height,
41702
- e.x0 + dx * t0,
41703
- e.y0 + dy * t0,
41704
- e.x0 + dx * t1,
41705
- e.y0 + dy * t1,
41706
- sw,
41707
- path.strokeColor,
41708
- strokeAlpha,
41709
- path.lineCap ?? 0,
41710
- original.kind === "glyph" ? aaTxt : aaVec,
41711
- path.blendMode,
41712
- clipMask
41713
- );
41714
- }
41715
- pos += step;
41716
- dashDist = (dashDist + step) % dashCycle;
41717
- }
41718
- }
41719
- }
41854
+ const edges = strokeEdges(path, displayList.height, scale);
41855
+ 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;
41856
+ fillEdgesScanline4x4(
41857
+ rgba,
41858
+ width,
41859
+ height,
41860
+ edges,
41861
+ path.strokeColor,
41862
+ strokeAlpha,
41863
+ "nonzero",
41864
+ clipScreen,
41865
+ original.kind === "glyph" ? aaTxt : aaVec,
41866
+ path.blendMode,
41867
+ clipMask
41868
+ );
41720
41869
  }
41721
41870
  } else if (operation.kind === "image") {
41722
41871
  const img = operation.value;
@@ -41852,17 +42001,19 @@ function svgImage(image, pageHeight) {
41852
42001
  const [a, b, c, d, e, f] = image.matrix;
41853
42002
  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(""))}"/>`;
41854
42003
  }
41855
- function svgPathData(segments, height) {
42004
+ function svgPathData(segments, height, matrix) {
41856
42005
  const dParts = [];
42006
+ 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}`;
41857
42007
  for (const seg of segments) {
41858
42008
  if (seg.kind === "move") {
41859
- dParts.push(`M ${seg.x} ${height - seg.y}`);
42009
+ dParts.push(`M ${point(seg.x, seg.y)}`);
41860
42010
  } else if (seg.kind === "line") {
41861
- dParts.push(`L ${seg.x} ${height - seg.y}`);
42011
+ dParts.push(`L ${point(seg.x, seg.y)}`);
41862
42012
  } else if (seg.kind === "cubic") {
41863
- dParts.push(`C ${seg.x1} ${height - seg.y1} ${seg.x2} ${height - seg.y2} ${seg.x} ${height - seg.y}`);
42013
+ dParts.push(`C ${point(seg.x1, seg.y1)} ${point(seg.x2, seg.y2)} ${point(seg.x, seg.y)}`);
41864
42014
  } else if (seg.kind === "rect") {
41865
- dParts.push(`M ${seg.x} ${height - seg.y} h ${seg.width} v ${-seg.height} h ${-seg.width} Z`);
42015
+ 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`);
42016
+ else dParts.push(`M ${seg.x} ${height - seg.y} h ${seg.width} v ${-seg.height} h ${-seg.width} Z`);
41866
42017
  } else if (seg.kind === "close") {
41867
42018
  dParts.push("Z");
41868
42019
  }
@@ -41941,21 +42092,25 @@ function renderDisplayListToSvg(displayList, options = {}) {
41941
42092
  parts.push("</g>");
41942
42093
  } else if (operation.kind === "path") {
41943
42094
  const p = operation.value;
41944
- const pathData = svgPathData(p.segments, displayList.height);
42095
+ const prepared = p.strokeColor ? prepareStroke(p, Math.max(scaleX, scaleY)) : void 0;
42096
+ const matrix = prepared && (prepared.matrix[0] !== 1 || prepared.matrix[1] !== 0 || prepared.matrix[2] !== 0 || prepared.matrix[3] !== 1) ? prepared.matrix : void 0;
42097
+ const inverse = matrix ? inverseStrokeMatrix(matrix) : void 0;
42098
+ const pathData = svgPathData(p.segments, inverse ? 0 : displayList.height, inverse);
42099
+ const transformAttr = inverse && matrix ? ` transform="matrix(${matrix[0]} ${-matrix[1]} ${-matrix[2]} ${matrix[3]} ${matrix[4]} ${displayList.height - matrix[5]})"` : "";
41945
42100
  if (pathData) {
41946
42101
  const fill = p.fillColor ? `rgb(${Math.round(p.fillColor.r * 255)},${Math.round(p.fillColor.g * 255)},${Math.round(p.fillColor.b * 255)})` : "none";
41947
- const stroke = p.strokeColor ? `rgb(${Math.round(p.strokeColor.r * 255)},${Math.round(p.strokeColor.g * 255)},${Math.round(p.strokeColor.b * 255)})` : "none";
42102
+ 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";
41948
42103
  const fillRuleAttr = p.fillRule === "evenodd" ? ` fill-rule="evenodd"` : "";
41949
42104
  const fillOpacityAttr = p.fillAlpha !== void 0 && p.fillAlpha < 1 ? ` fill-opacity="${p.fillAlpha}"` : "";
41950
42105
  const strokeOpacityAttr = p.strokeAlpha !== void 0 && p.strokeAlpha < 1 ? ` stroke-opacity="${p.strokeAlpha}"` : "";
41951
- const strokeWidthAttr = p.strokeWidth <= 0 ? ` stroke-width="1" vector-effect="non-scaling-stroke"` : ` stroke-width="${p.strokeWidth}"`;
42106
+ const strokeWidthAttr = p.strokeWidth <= 0 && !matrix && !p.dashArray?.length ? ` stroke-width="1" vector-effect="non-scaling-stroke"` : ` stroke-width="${prepared?.width ?? p.strokeWidth}"`;
41952
42107
  const lineCapAttr = p.lineCap === 1 ? ` stroke-linecap="round"` : p.lineCap === 2 ? ` stroke-linecap="square"` : "";
41953
42108
  const lineJoinAttr = p.lineJoin === 1 ? ` stroke-linejoin="round"` : p.lineJoin === 2 ? ` stroke-linejoin="bevel"` : "";
41954
42109
  const miterLimitAttr = p.miterLimit !== void 0 && p.miterLimit !== 10 ? ` stroke-miterlimit="${p.miterLimit}"` : "";
41955
- const dashArrayAttr = p.dashArray && p.dashArray.length > 0 ? ` stroke-dasharray="${p.dashArray.join(" ")}"` : "";
41956
- const dashOffsetAttr = p.dashPhase ? ` stroke-dashoffset="${p.dashPhase}"` : "";
42110
+ const dashArrayAttr = prepared?.dashArray?.length ? ` stroke-dasharray="${prepared.dashArray.join(" ")}"` : "";
42111
+ const dashOffsetAttr = prepared?.dashPhase ? ` stroke-dashoffset="${prepared.dashPhase}"` : "";
41957
42112
  const labelAttr = original.kind === "glyph" ? ` aria-label="${escapeXmlText(original.value.unicode)}"` : "";
41958
- parts.push(` <path${labelAttr} d="${pathData}" fill="${fill}"${fillRuleAttr}${fillOpacityAttr} stroke="${stroke}"${strokeOpacityAttr}${strokeWidthAttr}${lineCapAttr}${lineJoinAttr}${miterLimitAttr}${dashArrayAttr}${dashOffsetAttr}/>`);
42113
+ parts.push(` <path${labelAttr}${transformAttr} d="${pathData}" fill="${fill}"${fillRuleAttr}${fillOpacityAttr} stroke="${stroke}"${strokeOpacityAttr}${strokeWidthAttr}${lineCapAttr}${lineJoinAttr}${miterLimitAttr}${dashArrayAttr}${dashOffsetAttr}/>`);
41959
42114
  }
41960
42115
  } else if (operation.kind === "image") {
41961
42116
  parts.push(` ${svgImage(operation.value, displayList.height)}`);
@@ -42928,3 +43083,15 @@ export {
42928
43083
  * Copyright 2012 Mozilla Foundation. Licensed under Apache-2.0.
42929
43084
  * See THIRD_PARTY_NOTICES.md for the source revision and adaptations.
42930
43085
  */
43086
+ /*!
43087
+ * Anti-Grain Geometry - Version 2.3
43088
+ * Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
43089
+ *
43090
+ * Permission to copy, use, modify, sell and distribute this software
43091
+ * is granted provided this copyright notice appears in all copies.
43092
+ * This software is provided "as is" without express or implied
43093
+ * warranty, and with no claim as to its suitability for any purpose.
43094
+ *
43095
+ * Adapted from PDFium agg_math_stroke.h and agg_vcgen_stroke.cpp.
43096
+ * See THIRD_PARTY_NOTICES.md for the source revision and adaptations.
43097
+ */
@@ -2049,6 +2049,7 @@ import asyncio
2049
2049
  import copy
2050
2050
  import inspect
2051
2051
  import math
2052
+ import os
2052
2053
  from dataclasses import dataclass, field, replace
2053
2054
  from typing import Any, AsyncIterator, Callable, Mapping, Optional, Protocol, Sequence, Union
2054
2055
 
@@ -2091,7 +2092,8 @@ class Attachment:
2091
2092
  def payload(self):
2092
2093
  if not isinstance(self.path, str) or not self.path or "\0" in self.path:
2093
2094
  raise ValueError("Attachment requires an agent filesystem path")
2094
- result = {"path": self.path}
2095
+ path = self.path if os.path.isabs(self.path) else os.path.join(os.getcwd(), self.path)
2096
+ result = {"path": path}
2095
2097
  if self.mime_type is not None:
2096
2098
  result["mimeType"] = self.mime_type
2097
2099
  return result
@@ -2479,6 +2481,7 @@ from __future__ import annotations
2479
2481
  import asyncio
2480
2482
  import math
2481
2483
  import inspect
2484
+ import os
2482
2485
  import subprocess
2483
2486
  from dataclasses import dataclass
2484
2487
 
@@ -2534,6 +2537,12 @@ def _payload(args, *, shell=False, input=None, cwd=None, env=None, timeout=None,
2534
2537
  elif not isinstance(input, (bytes, bytearray, memoryview)):
2535
2538
  raise TypeError('Binary input must be bytes')
2536
2539
  result['input'] = list(input)
2540
+ # The host retains the original shell context; snapshot the current guest state.
2541
+ if cwd is None:
2542
+ cwd = os.getcwd()
2543
+ elif cwd and not os.path.isabs(cwd):
2544
+ cwd = os.path.join(os.getcwd(), cwd)
2545
+ env = dict(os.environ if env is None else env)
2537
2546
  result.update(cwd=cwd, env=env, timeout=timeout, max_output_bytes=max_output_bytes)
2538
2547
  return result
2539
2548