@poe-platform/safe-bash 0.1.764 → 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.
@@ -43703,11 +43703,10 @@ function evaluateContentStreamToDisplayList(params) {
43703
43703
  } else if (operator === "d") {
43704
43704
  const arrNode = ops[0]?.kind === "array" ? ops[0] : void 0;
43705
43705
  if (arrNode) {
43706
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
43707
- const nums = arrNode.items.map((it) => it.kind === "number" ? it.value * ctmScale : 0).filter((v) => v >= 0);
43706
+ const nums = arrNode.items.map((it) => it.kind === "number" ? it.value : 0).filter((v) => v >= 0);
43708
43707
  const sum = nums.reduce((a, b) => a + b, 0);
43709
43708
  st.dashArray = sum > 0 ? nums : void 0;
43710
- st.dashPhase = num(1, 0) * ctmScale;
43709
+ st.dashPhase = num(1, 0);
43711
43710
  } else {
43712
43711
  st.dashArray = void 0;
43713
43712
  st.dashPhase = void 0;
@@ -43839,10 +43838,11 @@ function evaluateContentStreamToDisplayList(params) {
43839
43838
  const patArr = params.cosDoc.resolveArray(dArr.items[0]);
43840
43839
  const phaseNode = params.cosDoc.resolve(dArr.items[1]);
43841
43840
  if (patArr) {
43842
- st.dashArray = patArr.items.map((it) => {
43841
+ const dashArray = patArr.items.map((it) => {
43843
43842
  const r = params.cosDoc.resolve(it);
43844
43843
  return r?.kind === "number" ? r.value : 0;
43845
- }).filter((n) => n > 0);
43844
+ }).filter((n) => n >= 0);
43845
+ st.dashArray = dashArray.some((value) => value > 0) ? dashArray : void 0;
43846
43846
  st.dashPhase = phaseNode?.kind === "number" ? phaseNode.value : 0;
43847
43847
  }
43848
43848
  }
@@ -44243,15 +44243,14 @@ function evaluateContentStreamToDisplayList(params) {
44243
44243
  break;
44244
44244
  }
44245
44245
  const fillRule = node.paint.includes("*") ? "evenodd" : "nonzero";
44246
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
44247
- const scaledStrokeWidth = st.strokeWidth === 0 ? 0 : st.strokeWidth * ctmScale;
44248
44246
  emit({ kind: "path", value: {
44249
44247
  segments: transformedSegments,
44250
44248
  fillColor: isFill && !evaluatedFillPattern ? st.fillColor : void 0,
44251
44249
  fillAlpha: isFill && !evaluatedFillPattern ? st.fillAlpha : void 0,
44252
44250
  strokeColor: isStroke ? st.strokeColor : void 0,
44253
44251
  strokeAlpha: isStroke ? st.strokeAlpha : void 0,
44254
- strokeWidth: scaledStrokeWidth,
44252
+ strokeWidth: st.strokeWidth,
44253
+ ...isStroke ? { strokeMatrix: [...st.ctm] } : {},
44255
44254
  ...st.lineCap !== 0 ? { lineCap: st.lineCap } : {},
44256
44255
  ...st.lineJoin !== 0 ? { lineJoin: st.lineJoin } : {},
44257
44256
  ...st.miterLimit !== 10 ? { miterLimit: st.miterLimit } : {},
@@ -44439,14 +44438,14 @@ function evaluateContentStreamToDisplayList(params) {
44439
44438
  if (st.textRenderMode >= 4 && st.textRenderMode <= 7) pendingTextClip.push(...transformedGlyphSegs);
44440
44439
  const isFillGlyph = st.textRenderMode === 0 || st.textRenderMode === 2 || st.textRenderMode === 4 || st.textRenderMode === 6;
44441
44440
  const isStrokeGlyph = st.textRenderMode === 1 || st.textRenderMode === 2 || st.textRenderMode === 5 || st.textRenderMode === 6;
44442
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
44443
44441
  const paint = {
44444
44442
  segments: transformedGlyphSegs,
44445
44443
  fillColor: isFillGlyph ? st.fillColor : void 0,
44446
44444
  fillAlpha: isFillGlyph ? st.fillAlpha : void 0,
44447
44445
  strokeColor: isStrokeGlyph ? st.strokeColor : void 0,
44448
44446
  strokeAlpha: isStrokeGlyph ? st.strokeAlpha : void 0,
44449
- strokeWidth: isStrokeGlyph ? st.strokeWidth * ctmScale : 0,
44447
+ strokeWidth: isStrokeGlyph ? st.strokeWidth : 0,
44448
+ ...isStrokeGlyph ? { strokeMatrix: [...st.ctm] } : {},
44450
44449
  fillRule: "nonzero",
44451
44450
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
44452
44451
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
@@ -46847,7 +46846,7 @@ function dashSubpath(path, pattern, phase) {
46847
46846
  while (remaining <= 0) {
46848
46847
  if (++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
46849
46848
  if (index % 2 === 0) {
46850
- if (pattern[index] === 0) result.push({ points: [point, point], closed: false });
46849
+ if (pattern[index] === 0) result.push({ points: [point, point], closed: false, zeroLengthDash: true });
46851
46850
  flush();
46852
46851
  }
46853
46852
  index = (index + 1) % pattern.length;
@@ -46862,7 +46861,7 @@ function dashSubpath(path, pattern, phase) {
46862
46861
  throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
46863
46862
  }
46864
46863
  let distance = 0;
46865
- while (distance < length) {
46864
+ while (length - distance > 8 * Number.EPSILON * Math.max(1, length)) {
46866
46865
  const point = [start[0] + dx * distance / length, start[1] + dy * distance / length];
46867
46866
  advance(point);
46868
46867
  const step = Math.min(remaining, length - distance);
@@ -46977,7 +46976,15 @@ function strokeOutlines(paths, width, cap, join, miterLimit, dashArray = [], das
46977
46976
  let closed = subpath.closed;
46978
46977
  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();
46979
46978
  if (points.length < 3) closed = false;
46980
- if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
46979
+ if (points.length === 1 && cap === 2 && subpath.zeroLengthDash) {
46980
+ contour = [];
46981
+ const [x, y] = points[0];
46982
+ add(x - half, y - half);
46983
+ add(x + half, y - half);
46984
+ add(x + half, y + half);
46985
+ add(x - half, y + half);
46986
+ contours.push(contour);
46987
+ } else if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
46981
46988
  contour = [];
46982
46989
  const [x, y] = points[0];
46983
46990
  addCap([x, y], [x + 1, y]);
@@ -47696,11 +47703,10 @@ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMa
47696
47703
  rgba[idx + 2] = Math.round((effB * a + cbB * dstA * (1 - a)) / outA * 255);
47697
47704
  rgba[idx + 3] = Math.round(outA * 255);
47698
47705
  }
47699
- function segmentsToScreenPaths(segments, pageHeight, scale) {
47706
+ function segmentsToScreenPaths(segments, pageHeight, scale, toScreen = (x, y) => [x * scale, (pageHeight - y) * scale]) {
47700
47707
  const paths = [];
47701
47708
  let points = [];
47702
47709
  let current = [0, 0];
47703
- const toScreen = (x, y) => [x * scale, (pageHeight - y) * scale];
47704
47710
  for (const segment of segments) {
47705
47711
  if (segment.kind === "move") {
47706
47712
  if (points.length) paths.push({ points, closed: false });
@@ -47739,6 +47745,63 @@ function segmentsToScreenPaths(segments, pageHeight, scale) {
47739
47745
  if (points.length) paths.push({ points, closed: false });
47740
47746
  return paths;
47741
47747
  }
47748
+ function inverseStrokeMatrix(matrix) {
47749
+ const [a, b, c, d, e, f] = matrix;
47750
+ const det = a * d - b * c;
47751
+ if (!Number.isFinite(det) || det === 0) return void 0;
47752
+ return [d / det, -b / det, -c / det, a / det, (c * f - d * e) / det, (b * e - a * f) / det];
47753
+ }
47754
+ function prepareStroke(path, scale) {
47755
+ const matrix = path.strokeMatrix ? [...path.strokeMatrix] : [1, 0, 0, 1, 0, 0];
47756
+ const [a, b, c, d] = matrix;
47757
+ const area = Math.abs(a * d - b * c) * scale * scale;
47758
+ if (!(area > 0) || !Number.isFinite(area)) return void 0;
47759
+ const normX = Math.hypot(a, b) * scale, normY = Math.hypot(c, d) * scale;
47760
+ let width = path.strokeWidth || 1;
47761
+ const scaleX = path.strokeWidth === 0 ? normY / area : Math.max(1, normY / (width * area));
47762
+ const scaleY = path.strokeWidth === 0 ? normX / area : Math.max(1, normX / (width * area));
47763
+ let dashArray = path.dashArray, dashPhase = path.dashPhase ?? 0;
47764
+ if (scaleX === scaleY) {
47765
+ width *= scaleX;
47766
+ } else {
47767
+ matrix[0] *= scaleX;
47768
+ matrix[1] *= scaleX;
47769
+ matrix[2] *= scaleY;
47770
+ matrix[3] *= scaleY;
47771
+ if (dashArray?.length) {
47772
+ const dashScale = Math.max(scaleX, scaleY);
47773
+ dashArray = dashArray.map((value) => value / dashScale);
47774
+ dashPhase /= dashScale;
47775
+ }
47776
+ }
47777
+ return { matrix, width, dashArray, dashPhase };
47778
+ }
47779
+ function strokeContours(path, pageHeight, scale) {
47780
+ const stroke = prepareStroke(path, scale);
47781
+ if (!stroke) return [];
47782
+ const inverse = inverseStrokeMatrix(stroke.matrix);
47783
+ if (!inverse) return [];
47784
+ const [a, b, c, d, e, f] = stroke.matrix;
47785
+ const strokeScale = scale * Math.hypot(a, b, c, d);
47786
+ const project = (x, y) => [
47787
+ (inverse[0] * x + inverse[2] * y + inverse[4]) * strokeScale,
47788
+ (inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
47789
+ ];
47790
+ const toScreen = ([x, y]) => [
47791
+ (a * x / strokeScale + c * y / strokeScale + e) * scale,
47792
+ (pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
47793
+ ];
47794
+ const contours = strokeOutlines(
47795
+ segmentsToScreenPaths(path.segments, pageHeight, scale, project),
47796
+ stroke.width * strokeScale,
47797
+ path.lineCap ?? 0,
47798
+ path.lineJoin ?? 0,
47799
+ path.miterLimit ?? 10,
47800
+ stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
47801
+ stroke.dashPhase * strokeScale
47802
+ );
47803
+ return contours.map((points) => points.map(toScreen));
47804
+ }
47742
47805
  function pathsToEdges(paths, closeSubpaths = false) {
47743
47806
  const edges = [];
47744
47807
  for (const { points, closed } of paths) {
@@ -47988,19 +48051,9 @@ function renderDisplayListToBitmap(displayList, options = {}) {
47988
48051
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
47989
48052
  }
47990
48053
  if (path.strokeColor) {
47991
- const rawSw = path.strokeWidth * scale;
47992
- const sw = Math.max(1, rawSw);
48054
+ const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
47993
48055
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
47994
- const contours = strokeOutlines(
47995
- segmentsToScreenPaths(path.segments, displayList.height, scale),
47996
- sw,
47997
- path.lineCap ?? 0,
47998
- path.lineJoin ?? 0,
47999
- path.miterLimit ?? 10,
48000
- path.dashArray?.map((value) => Math.max(0, value * scale)),
48001
- (path.dashPhase ?? 0) * scale
48002
- );
48003
- const edges = pathsToEdges(contours.map((points) => ({ points, closed: true })));
48056
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
48004
48057
  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;
48005
48058
  fillEdgesScanline4x4(
48006
48059
  rgba,
@@ -43703,11 +43703,10 @@ function evaluateContentStreamToDisplayList(params) {
43703
43703
  } else if (operator === "d") {
43704
43704
  const arrNode = ops[0]?.kind === "array" ? ops[0] : void 0;
43705
43705
  if (arrNode) {
43706
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
43707
- const nums = arrNode.items.map((it) => it.kind === "number" ? it.value * ctmScale : 0).filter((v) => v >= 0);
43706
+ const nums = arrNode.items.map((it) => it.kind === "number" ? it.value : 0).filter((v) => v >= 0);
43708
43707
  const sum = nums.reduce((a, b) => a + b, 0);
43709
43708
  st.dashArray = sum > 0 ? nums : void 0;
43710
- st.dashPhase = num(1, 0) * ctmScale;
43709
+ st.dashPhase = num(1, 0);
43711
43710
  } else {
43712
43711
  st.dashArray = void 0;
43713
43712
  st.dashPhase = void 0;
@@ -43839,10 +43838,11 @@ function evaluateContentStreamToDisplayList(params) {
43839
43838
  const patArr = params.cosDoc.resolveArray(dArr.items[0]);
43840
43839
  const phaseNode = params.cosDoc.resolve(dArr.items[1]);
43841
43840
  if (patArr) {
43842
- st.dashArray = patArr.items.map((it) => {
43841
+ const dashArray = patArr.items.map((it) => {
43843
43842
  const r = params.cosDoc.resolve(it);
43844
43843
  return r?.kind === "number" ? r.value : 0;
43845
- }).filter((n) => n > 0);
43844
+ }).filter((n) => n >= 0);
43845
+ st.dashArray = dashArray.some((value) => value > 0) ? dashArray : void 0;
43846
43846
  st.dashPhase = phaseNode?.kind === "number" ? phaseNode.value : 0;
43847
43847
  }
43848
43848
  }
@@ -44243,15 +44243,14 @@ function evaluateContentStreamToDisplayList(params) {
44243
44243
  break;
44244
44244
  }
44245
44245
  const fillRule = node.paint.includes("*") ? "evenodd" : "nonzero";
44246
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
44247
- const scaledStrokeWidth = st.strokeWidth === 0 ? 0 : st.strokeWidth * ctmScale;
44248
44246
  emit({ kind: "path", value: {
44249
44247
  segments: transformedSegments,
44250
44248
  fillColor: isFill && !evaluatedFillPattern ? st.fillColor : void 0,
44251
44249
  fillAlpha: isFill && !evaluatedFillPattern ? st.fillAlpha : void 0,
44252
44250
  strokeColor: isStroke ? st.strokeColor : void 0,
44253
44251
  strokeAlpha: isStroke ? st.strokeAlpha : void 0,
44254
- strokeWidth: scaledStrokeWidth,
44252
+ strokeWidth: st.strokeWidth,
44253
+ ...isStroke ? { strokeMatrix: [...st.ctm] } : {},
44255
44254
  ...st.lineCap !== 0 ? { lineCap: st.lineCap } : {},
44256
44255
  ...st.lineJoin !== 0 ? { lineJoin: st.lineJoin } : {},
44257
44256
  ...st.miterLimit !== 10 ? { miterLimit: st.miterLimit } : {},
@@ -44439,14 +44438,14 @@ function evaluateContentStreamToDisplayList(params) {
44439
44438
  if (st.textRenderMode >= 4 && st.textRenderMode <= 7) pendingTextClip.push(...transformedGlyphSegs);
44440
44439
  const isFillGlyph = st.textRenderMode === 0 || st.textRenderMode === 2 || st.textRenderMode === 4 || st.textRenderMode === 6;
44441
44440
  const isStrokeGlyph = st.textRenderMode === 1 || st.textRenderMode === 2 || st.textRenderMode === 5 || st.textRenderMode === 6;
44442
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
44443
44441
  const paint = {
44444
44442
  segments: transformedGlyphSegs,
44445
44443
  fillColor: isFillGlyph ? st.fillColor : void 0,
44446
44444
  fillAlpha: isFillGlyph ? st.fillAlpha : void 0,
44447
44445
  strokeColor: isStrokeGlyph ? st.strokeColor : void 0,
44448
44446
  strokeAlpha: isStrokeGlyph ? st.strokeAlpha : void 0,
44449
- strokeWidth: isStrokeGlyph ? st.strokeWidth * ctmScale : 0,
44447
+ strokeWidth: isStrokeGlyph ? st.strokeWidth : 0,
44448
+ ...isStrokeGlyph ? { strokeMatrix: [...st.ctm] } : {},
44450
44449
  fillRule: "nonzero",
44451
44450
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
44452
44451
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
@@ -46847,7 +46846,7 @@ function dashSubpath(path, pattern, phase) {
46847
46846
  while (remaining <= 0) {
46848
46847
  if (++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
46849
46848
  if (index % 2 === 0) {
46850
- if (pattern[index] === 0) result.push({ points: [point, point], closed: false });
46849
+ if (pattern[index] === 0) result.push({ points: [point, point], closed: false, zeroLengthDash: true });
46851
46850
  flush();
46852
46851
  }
46853
46852
  index = (index + 1) % pattern.length;
@@ -46862,7 +46861,7 @@ function dashSubpath(path, pattern, phase) {
46862
46861
  throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
46863
46862
  }
46864
46863
  let distance = 0;
46865
- while (distance < length) {
46864
+ while (length - distance > 8 * Number.EPSILON * Math.max(1, length)) {
46866
46865
  const point = [start[0] + dx * distance / length, start[1] + dy * distance / length];
46867
46866
  advance(point);
46868
46867
  const step = Math.min(remaining, length - distance);
@@ -46977,7 +46976,15 @@ function strokeOutlines(paths, width, cap, join, miterLimit, dashArray = [], das
46977
46976
  let closed = subpath.closed;
46978
46977
  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();
46979
46978
  if (points.length < 3) closed = false;
46980
- if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
46979
+ if (points.length === 1 && cap === 2 && subpath.zeroLengthDash) {
46980
+ contour = [];
46981
+ const [x, y] = points[0];
46982
+ add(x - half, y - half);
46983
+ add(x + half, y - half);
46984
+ add(x + half, y + half);
46985
+ add(x - half, y + half);
46986
+ contours.push(contour);
46987
+ } else if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
46981
46988
  contour = [];
46982
46989
  const [x, y] = points[0];
46983
46990
  addCap([x, y], [x + 1, y]);
@@ -47696,11 +47703,10 @@ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMa
47696
47703
  rgba[idx + 2] = Math.round((effB * a + cbB * dstA * (1 - a)) / outA * 255);
47697
47704
  rgba[idx + 3] = Math.round(outA * 255);
47698
47705
  }
47699
- function segmentsToScreenPaths(segments, pageHeight, scale) {
47706
+ function segmentsToScreenPaths(segments, pageHeight, scale, toScreen = (x, y) => [x * scale, (pageHeight - y) * scale]) {
47700
47707
  const paths = [];
47701
47708
  let points = [];
47702
47709
  let current = [0, 0];
47703
- const toScreen = (x, y) => [x * scale, (pageHeight - y) * scale];
47704
47710
  for (const segment of segments) {
47705
47711
  if (segment.kind === "move") {
47706
47712
  if (points.length) paths.push({ points, closed: false });
@@ -47739,6 +47745,63 @@ function segmentsToScreenPaths(segments, pageHeight, scale) {
47739
47745
  if (points.length) paths.push({ points, closed: false });
47740
47746
  return paths;
47741
47747
  }
47748
+ function inverseStrokeMatrix(matrix) {
47749
+ const [a, b, c, d, e, f] = matrix;
47750
+ const det = a * d - b * c;
47751
+ if (!Number.isFinite(det) || det === 0) return void 0;
47752
+ return [d / det, -b / det, -c / det, a / det, (c * f - d * e) / det, (b * e - a * f) / det];
47753
+ }
47754
+ function prepareStroke(path, scale) {
47755
+ const matrix = path.strokeMatrix ? [...path.strokeMatrix] : [1, 0, 0, 1, 0, 0];
47756
+ const [a, b, c, d] = matrix;
47757
+ const area = Math.abs(a * d - b * c) * scale * scale;
47758
+ if (!(area > 0) || !Number.isFinite(area)) return void 0;
47759
+ const normX = Math.hypot(a, b) * scale, normY = Math.hypot(c, d) * scale;
47760
+ let width = path.strokeWidth || 1;
47761
+ const scaleX = path.strokeWidth === 0 ? normY / area : Math.max(1, normY / (width * area));
47762
+ const scaleY = path.strokeWidth === 0 ? normX / area : Math.max(1, normX / (width * area));
47763
+ let dashArray = path.dashArray, dashPhase = path.dashPhase ?? 0;
47764
+ if (scaleX === scaleY) {
47765
+ width *= scaleX;
47766
+ } else {
47767
+ matrix[0] *= scaleX;
47768
+ matrix[1] *= scaleX;
47769
+ matrix[2] *= scaleY;
47770
+ matrix[3] *= scaleY;
47771
+ if (dashArray?.length) {
47772
+ const dashScale = Math.max(scaleX, scaleY);
47773
+ dashArray = dashArray.map((value) => value / dashScale);
47774
+ dashPhase /= dashScale;
47775
+ }
47776
+ }
47777
+ return { matrix, width, dashArray, dashPhase };
47778
+ }
47779
+ function strokeContours(path, pageHeight, scale) {
47780
+ const stroke = prepareStroke(path, scale);
47781
+ if (!stroke) return [];
47782
+ const inverse = inverseStrokeMatrix(stroke.matrix);
47783
+ if (!inverse) return [];
47784
+ const [a, b, c, d, e, f] = stroke.matrix;
47785
+ const strokeScale = scale * Math.hypot(a, b, c, d);
47786
+ const project = (x, y) => [
47787
+ (inverse[0] * x + inverse[2] * y + inverse[4]) * strokeScale,
47788
+ (inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
47789
+ ];
47790
+ const toScreen = ([x, y]) => [
47791
+ (a * x / strokeScale + c * y / strokeScale + e) * scale,
47792
+ (pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
47793
+ ];
47794
+ const contours = strokeOutlines(
47795
+ segmentsToScreenPaths(path.segments, pageHeight, scale, project),
47796
+ stroke.width * strokeScale,
47797
+ path.lineCap ?? 0,
47798
+ path.lineJoin ?? 0,
47799
+ path.miterLimit ?? 10,
47800
+ stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
47801
+ stroke.dashPhase * strokeScale
47802
+ );
47803
+ return contours.map((points) => points.map(toScreen));
47804
+ }
47742
47805
  function pathsToEdges(paths, closeSubpaths = false) {
47743
47806
  const edges = [];
47744
47807
  for (const { points, closed } of paths) {
@@ -47988,19 +48051,9 @@ function renderDisplayListToBitmap(displayList, options = {}) {
47988
48051
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
47989
48052
  }
47990
48053
  if (path.strokeColor) {
47991
- const rawSw = path.strokeWidth * scale;
47992
- const sw = Math.max(1, rawSw);
48054
+ const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
47993
48055
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
47994
- const contours = strokeOutlines(
47995
- segmentsToScreenPaths(path.segments, displayList.height, scale),
47996
- sw,
47997
- path.lineCap ?? 0,
47998
- path.lineJoin ?? 0,
47999
- path.miterLimit ?? 10,
48000
- path.dashArray?.map((value) => Math.max(0, value * scale)),
48001
- (path.dashPhase ?? 0) * scale
48002
- );
48003
- const edges = pathsToEdges(contours.map((points) => ({ points, closed: true })));
48056
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
48004
48057
  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;
48005
48058
  fillEdgesScanline4x4(
48006
48059
  rgba,
@@ -246,6 +246,8 @@ export interface PdfEvaluatedPath {
246
246
  readonly fillColor?: PdfRgbColor | undefined;
247
247
  readonly fillAlpha?: number | undefined;
248
248
  readonly strokeWidth: number;
249
+ /** Paint-time user-to-page transform for stroke width/dashes; segments remain in page coordinates. */
250
+ readonly strokeMatrix?: readonly [number, number, number, number, number, number] | undefined;
249
251
  readonly lineCap?: 0 | 1 | 2 | undefined;
250
252
  readonly lineJoin?: 0 | 1 | 2 | undefined;
251
253
  readonly miterLimit?: number | undefined;