@poe-platform/safe-bash 0.1.765 → 0.1.766

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.
@@ -209346,10 +209346,11 @@ function evaluateContentStreamToDisplayList(params) {
209346
209346
  const patArr = params.cosDoc.resolveArray(dArr.items[0]);
209347
209347
  const phaseNode = params.cosDoc.resolve(dArr.items[1]);
209348
209348
  if (patArr) {
209349
- st.dashArray = patArr.items.map((it) => {
209349
+ const dashArray = patArr.items.map((it) => {
209350
209350
  const r = params.cosDoc.resolve(it);
209351
209351
  return r?.kind === "number" ? r.value : 0;
209352
- }).filter((n) => n > 0);
209352
+ }).filter((n) => n >= 0);
209353
+ st.dashArray = dashArray.some((value3) => value3 > 0) ? dashArray : void 0;
209353
209354
  st.dashPhase = phaseNode?.kind === "number" ? phaseNode.value : 0;
209354
209355
  }
209355
209356
  }
@@ -212353,7 +212354,7 @@ function dashSubpath(path2, pattern, phase) {
212353
212354
  while (remaining <= 0) {
212354
212355
  if (++steps > MAX_STROKE_VERTICES) throw new PdfError2("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
212355
212356
  if (index2 % 2 === 0) {
212356
- if (pattern[index2] === 0) result2.push({ points: [point, point], closed: false });
212357
+ if (pattern[index2] === 0) result2.push({ points: [point, point], closed: false, zeroLengthDash: true });
212357
212358
  flush();
212358
212359
  }
212359
212360
  index2 = (index2 + 1) % pattern.length;
@@ -212368,7 +212369,7 @@ function dashSubpath(path2, pattern, phase) {
212368
212369
  throw new PdfError2("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
212369
212370
  }
212370
212371
  let distance2 = 0;
212371
- while (distance2 < length) {
212372
+ while (length - distance2 > 8 * Number.EPSILON * Math.max(1, length)) {
212372
212373
  const point = [start[0] + dx * distance2 / length, start[1] + dy * distance2 / length];
212373
212374
  advance2(point);
212374
212375
  const step = Math.min(remaining, length - distance2);
@@ -212483,7 +212484,15 @@ function strokeOutlines(paths, width2, cap, join3, miterLimit, dashArray = [], d
212483
212484
  let closed = subpath.closed;
212484
212485
  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();
212485
212486
  if (points.length < 3) closed = false;
212486
- if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
212487
+ if (points.length === 1 && cap === 2 && subpath.zeroLengthDash) {
212488
+ contour = [];
212489
+ const [x, y] = points[0];
212490
+ add5(x - half, y - half);
212491
+ add5(x + half, y - half);
212492
+ add5(x + half, y + half);
212493
+ add5(x - half, y + half);
212494
+ contours.push(contour);
212495
+ } else if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
212487
212496
  contour = [];
212488
212497
  const [x, y] = points[0];
212489
212498
  addCap([x, y], [x + 1, y]);
@@ -213275,7 +213284,7 @@ function prepareStroke(path2, scale2) {
213275
213284
  }
213276
213285
  return { matrix: matrix2, width: width2, dashArray, dashPhase };
213277
213286
  }
213278
- function strokeEdges(path2, pageHeight, scale2) {
213287
+ function strokeContours(path2, pageHeight, scale2) {
213279
213288
  const stroke = prepareStroke(path2, scale2);
213280
213289
  if (!stroke) return [];
213281
213290
  const inverse2 = inverseStrokeMatrix(stroke.matrix);
@@ -213299,7 +213308,7 @@ function strokeEdges(path2, pageHeight, scale2) {
213299
213308
  stroke.dashArray?.map((value3) => Math.max(0, value3 * strokeScale)),
213300
213309
  stroke.dashPhase * strokeScale
213301
213310
  );
213302
- return pathsToEdges(contours.map((points) => ({ points: points.map(toScreen), closed: true })));
213311
+ return contours.map((points) => points.map(toScreen));
213303
213312
  }
213304
213313
  function pathsToEdges(paths, closeSubpaths = false) {
213305
213314
  const edges2 = [];
@@ -213552,7 +213561,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
213552
213561
  if (path2.strokeColor) {
213553
213562
  const rawSw = path2.strokeWidth * scale2 * (path2.strokeMatrix ? Math.hypot(path2.strokeMatrix[0], path2.strokeMatrix[1]) : 1);
213554
213563
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path2.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path2.strokeAlpha ?? 1;
213555
- const edges2 = strokeEdges(path2, displayList.height, scale2);
213564
+ const edges2 = pathsToEdges(strokeContours(path2, displayList.height, scale2).map((points) => ({ points, closed: true })));
213556
213565
  const clipScreen = path2.clipRect ? [path2.clipRect[0] * scale2, (displayList.height - path2.clipRect[3]) * scale2, path2.clipRect[2] * scale2, (displayList.height - path2.clipRect[1]) * scale2] : void 0;
213557
213566
  fillEdgesScanline4x4(
213558
213567
  rgba,
@@ -11877,10 +11877,11 @@ function evaluateContentStreamToDisplayList(params) {
11877
11877
  const patArr = params.cosDoc.resolveArray(dArr.items[0]);
11878
11878
  const phaseNode = params.cosDoc.resolve(dArr.items[1]);
11879
11879
  if (patArr) {
11880
- st.dashArray = patArr.items.map((it) => {
11880
+ const dashArray = patArr.items.map((it) => {
11881
11881
  const r = params.cosDoc.resolve(it);
11882
11882
  return r?.kind === "number" ? r.value : 0;
11883
- }).filter((n) => n > 0);
11883
+ }).filter((n) => n >= 0);
11884
+ st.dashArray = dashArray.some((value) => value > 0) ? dashArray : void 0;
11884
11885
  st.dashPhase = phaseNode?.kind === "number" ? phaseNode.value : 0;
11885
11886
  }
11886
11887
  }
@@ -14098,7 +14099,7 @@ function dashSubpath(path, pattern, phase) {
14098
14099
  while (remaining <= 0) {
14099
14100
  if (++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
14100
14101
  if (index % 2 === 0) {
14101
- if (pattern[index] === 0) result.push({ points: [point, point], closed: false });
14102
+ if (pattern[index] === 0) result.push({ points: [point, point], closed: false, zeroLengthDash: true });
14102
14103
  flush();
14103
14104
  }
14104
14105
  index = (index + 1) % pattern.length;
@@ -14113,7 +14114,7 @@ function dashSubpath(path, pattern, phase) {
14113
14114
  throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
14114
14115
  }
14115
14116
  let distance = 0;
14116
- while (distance < length2) {
14117
+ while (length2 - distance > 8 * Number.EPSILON * Math.max(1, length2)) {
14117
14118
  const point = [start[0] + dx * distance / length2, start[1] + dy * distance / length2];
14118
14119
  advance(point);
14119
14120
  const step = Math.min(remaining, length2 - distance);
@@ -14228,7 +14229,15 @@ function strokeOutlines(paths, width, cap, join, miterLimit, dashArray = [], das
14228
14229
  let closed = subpath.closed;
14229
14230
  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();
14230
14231
  if (points.length < 3) closed = false;
14231
- if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
14232
+ if (points.length === 1 && cap === 2 && subpath.zeroLengthDash) {
14233
+ contour = [];
14234
+ const [x, y] = points[0];
14235
+ add(x - half, y - half);
14236
+ add(x + half, y - half);
14237
+ add(x + half, y + half);
14238
+ add(x - half, y + half);
14239
+ contours.push(contour);
14240
+ } else if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
14232
14241
  contour = [];
14233
14242
  const [x, y] = points[0];
14234
14243
  addCap([x, y], [x + 1, y]);
@@ -14708,7 +14717,7 @@ function prepareStroke(path, scale) {
14708
14717
  }
14709
14718
  return { matrix, width, dashArray, dashPhase };
14710
14719
  }
14711
- function strokeEdges(path, pageHeight, scale) {
14720
+ function strokeContours(path, pageHeight, scale) {
14712
14721
  const stroke = prepareStroke(path, scale);
14713
14722
  if (!stroke) return [];
14714
14723
  const inverse = inverseStrokeMatrix(stroke.matrix);
@@ -14732,7 +14741,7 @@ function strokeEdges(path, pageHeight, scale) {
14732
14741
  stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
14733
14742
  stroke.dashPhase * strokeScale
14734
14743
  );
14735
- return pathsToEdges(contours.map((points) => ({ points: points.map(toScreen), closed: true })));
14744
+ return contours.map((points) => points.map(toScreen));
14736
14745
  }
14737
14746
  function pathsToEdges(paths, closeSubpaths = false) {
14738
14747
  const edges = [];
@@ -14985,7 +14994,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
14985
14994
  if (path.strokeColor) {
14986
14995
  const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
14987
14996
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
14988
- const edges = strokeEdges(path, displayList.height, scale);
14997
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
14989
14998
  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;
14990
14999
  fillEdgesScanline4x4(
14991
15000
  rgba,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@poe-platform/safe-bash",
3
- "version": "0.1.765",
3
+ "version": "0.1.766",
4
4
  "description": "Extensible virtual shell with pluggable filesystems and streaming commands",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -841,7 +841,7 @@
841
841
  "access": "public"
842
842
  },
843
843
  "dependencies": {
844
- "@poe-platform/safe-fs": "0.1.765",
844
+ "@poe-platform/safe-fs": "0.1.766",
845
845
  "pdf-lib": "1.17.1",
846
846
  "@noble/hashes": "2.4.0",
847
847
  "pako": "3.0.1",
@@ -222,6 +222,9 @@ permission terms. The adapter uses double-precision arrays, PDFium's
222
222
  `miter_join_revert` bevel fallback, and a one-million-vertex expansion limit.
223
223
  Local dash splitting preserves joins across vertices and closed seams, resets
224
224
  phase per subpath, and handles odd arrays and zero-length round dots.
225
+ Square zero-length dashes follow PDF.js/Canvas user-axis squares. Dash stepping
226
+ ignores a few ULPs of transformed endpoint residue; SVG reuses these contours for
227
+ zero-length patterns so its endpoint behavior and opacity match PDF painting.
225
228
  `src/render/stroke-joins.test.ts` checks native cap/join vectors plus independent
226
229
  PDF.js pixels; Poppler also confirms the final zero-length dash is omitted.
227
230
  The native harness calls unchanged upstream math routines with minimal support