@poe-platform/safe-bash 0.1.764 → 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.
@@ -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;
@@ -44243,15 +44242,14 @@ function evaluateContentStreamToDisplayList(params) {
44243
44242
  break;
44244
44243
  }
44245
44244
  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
44245
  emit({ kind: "path", value: {
44249
44246
  segments: transformedSegments,
44250
44247
  fillColor: isFill && !evaluatedFillPattern ? st.fillColor : void 0,
44251
44248
  fillAlpha: isFill && !evaluatedFillPattern ? st.fillAlpha : void 0,
44252
44249
  strokeColor: isStroke ? st.strokeColor : void 0,
44253
44250
  strokeAlpha: isStroke ? st.strokeAlpha : void 0,
44254
- strokeWidth: scaledStrokeWidth,
44251
+ strokeWidth: st.strokeWidth,
44252
+ ...isStroke ? { strokeMatrix: [...st.ctm] } : {},
44255
44253
  ...st.lineCap !== 0 ? { lineCap: st.lineCap } : {},
44256
44254
  ...st.lineJoin !== 0 ? { lineJoin: st.lineJoin } : {},
44257
44255
  ...st.miterLimit !== 10 ? { miterLimit: st.miterLimit } : {},
@@ -44439,14 +44437,14 @@ function evaluateContentStreamToDisplayList(params) {
44439
44437
  if (st.textRenderMode >= 4 && st.textRenderMode <= 7) pendingTextClip.push(...transformedGlyphSegs);
44440
44438
  const isFillGlyph = st.textRenderMode === 0 || st.textRenderMode === 2 || st.textRenderMode === 4 || st.textRenderMode === 6;
44441
44439
  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
44440
  const paint = {
44444
44441
  segments: transformedGlyphSegs,
44445
44442
  fillColor: isFillGlyph ? st.fillColor : void 0,
44446
44443
  fillAlpha: isFillGlyph ? st.fillAlpha : void 0,
44447
44444
  strokeColor: isStrokeGlyph ? st.strokeColor : void 0,
44448
44445
  strokeAlpha: isStrokeGlyph ? st.strokeAlpha : void 0,
44449
- strokeWidth: isStrokeGlyph ? st.strokeWidth * ctmScale : 0,
44446
+ strokeWidth: isStrokeGlyph ? st.strokeWidth : 0,
44447
+ ...isStrokeGlyph ? { strokeMatrix: [...st.ctm] } : {},
44450
44448
  fillRule: "nonzero",
44451
44449
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
44452
44450
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
@@ -47696,11 +47694,10 @@ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMa
47696
47694
  rgba[idx + 2] = Math.round((effB * a + cbB * dstA * (1 - a)) / outA * 255);
47697
47695
  rgba[idx + 3] = Math.round(outA * 255);
47698
47696
  }
47699
- function segmentsToScreenPaths(segments, pageHeight, scale) {
47697
+ function segmentsToScreenPaths(segments, pageHeight, scale, toScreen = (x, y) => [x * scale, (pageHeight - y) * scale]) {
47700
47698
  const paths = [];
47701
47699
  let points = [];
47702
47700
  let current = [0, 0];
47703
- const toScreen = (x, y) => [x * scale, (pageHeight - y) * scale];
47704
47701
  for (const segment of segments) {
47705
47702
  if (segment.kind === "move") {
47706
47703
  if (points.length) paths.push({ points, closed: false });
@@ -47739,6 +47736,63 @@ function segmentsToScreenPaths(segments, pageHeight, scale) {
47739
47736
  if (points.length) paths.push({ points, closed: false });
47740
47737
  return paths;
47741
47738
  }
47739
+ function inverseStrokeMatrix(matrix) {
47740
+ const [a, b, c, d, e, f] = matrix;
47741
+ const det = a * d - b * c;
47742
+ if (!Number.isFinite(det) || det === 0) return void 0;
47743
+ return [d / det, -b / det, -c / det, a / det, (c * f - d * e) / det, (b * e - a * f) / det];
47744
+ }
47745
+ function prepareStroke(path, scale) {
47746
+ const matrix = path.strokeMatrix ? [...path.strokeMatrix] : [1, 0, 0, 1, 0, 0];
47747
+ const [a, b, c, d] = matrix;
47748
+ const area = Math.abs(a * d - b * c) * scale * scale;
47749
+ if (!(area > 0) || !Number.isFinite(area)) return void 0;
47750
+ const normX = Math.hypot(a, b) * scale, normY = Math.hypot(c, d) * scale;
47751
+ let width = path.strokeWidth || 1;
47752
+ const scaleX = path.strokeWidth === 0 ? normY / area : Math.max(1, normY / (width * area));
47753
+ const scaleY = path.strokeWidth === 0 ? normX / area : Math.max(1, normX / (width * area));
47754
+ let dashArray = path.dashArray, dashPhase = path.dashPhase ?? 0;
47755
+ if (scaleX === scaleY) {
47756
+ width *= scaleX;
47757
+ } else {
47758
+ matrix[0] *= scaleX;
47759
+ matrix[1] *= scaleX;
47760
+ matrix[2] *= scaleY;
47761
+ matrix[3] *= scaleY;
47762
+ if (dashArray?.length) {
47763
+ const dashScale = Math.max(scaleX, scaleY);
47764
+ dashArray = dashArray.map((value) => value / dashScale);
47765
+ dashPhase /= dashScale;
47766
+ }
47767
+ }
47768
+ return { matrix, width, dashArray, dashPhase };
47769
+ }
47770
+ function strokeEdges(path, pageHeight, scale) {
47771
+ const stroke = prepareStroke(path, scale);
47772
+ if (!stroke) return [];
47773
+ const inverse = inverseStrokeMatrix(stroke.matrix);
47774
+ if (!inverse) return [];
47775
+ const [a, b, c, d, e, f] = stroke.matrix;
47776
+ const strokeScale = scale * Math.hypot(a, b, c, d);
47777
+ const project = (x, y) => [
47778
+ (inverse[0] * x + inverse[2] * y + inverse[4]) * strokeScale,
47779
+ (inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
47780
+ ];
47781
+ const toScreen = ([x, y]) => [
47782
+ (a * x / strokeScale + c * y / strokeScale + e) * scale,
47783
+ (pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
47784
+ ];
47785
+ const contours = strokeOutlines(
47786
+ segmentsToScreenPaths(path.segments, pageHeight, scale, project),
47787
+ stroke.width * strokeScale,
47788
+ path.lineCap ?? 0,
47789
+ path.lineJoin ?? 0,
47790
+ path.miterLimit ?? 10,
47791
+ stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
47792
+ stroke.dashPhase * strokeScale
47793
+ );
47794
+ return pathsToEdges(contours.map((points) => ({ points: points.map(toScreen), closed: true })));
47795
+ }
47742
47796
  function pathsToEdges(paths, closeSubpaths = false) {
47743
47797
  const edges = [];
47744
47798
  for (const { points, closed } of paths) {
@@ -47988,19 +48042,9 @@ function renderDisplayListToBitmap(displayList, options = {}) {
47988
48042
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
47989
48043
  }
47990
48044
  if (path.strokeColor) {
47991
- const rawSw = path.strokeWidth * scale;
47992
- const sw = Math.max(1, rawSw);
48045
+ const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
47993
48046
  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 })));
48047
+ const edges = strokeEdges(path, displayList.height, scale);
48004
48048
  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
48049
  fillEdgesScanline4x4(
48006
48050
  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;
@@ -44243,15 +44242,14 @@ function evaluateContentStreamToDisplayList(params) {
44243
44242
  break;
44244
44243
  }
44245
44244
  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
44245
  emit({ kind: "path", value: {
44249
44246
  segments: transformedSegments,
44250
44247
  fillColor: isFill && !evaluatedFillPattern ? st.fillColor : void 0,
44251
44248
  fillAlpha: isFill && !evaluatedFillPattern ? st.fillAlpha : void 0,
44252
44249
  strokeColor: isStroke ? st.strokeColor : void 0,
44253
44250
  strokeAlpha: isStroke ? st.strokeAlpha : void 0,
44254
- strokeWidth: scaledStrokeWidth,
44251
+ strokeWidth: st.strokeWidth,
44252
+ ...isStroke ? { strokeMatrix: [...st.ctm] } : {},
44255
44253
  ...st.lineCap !== 0 ? { lineCap: st.lineCap } : {},
44256
44254
  ...st.lineJoin !== 0 ? { lineJoin: st.lineJoin } : {},
44257
44255
  ...st.miterLimit !== 10 ? { miterLimit: st.miterLimit } : {},
@@ -44439,14 +44437,14 @@ function evaluateContentStreamToDisplayList(params) {
44439
44437
  if (st.textRenderMode >= 4 && st.textRenderMode <= 7) pendingTextClip.push(...transformedGlyphSegs);
44440
44438
  const isFillGlyph = st.textRenderMode === 0 || st.textRenderMode === 2 || st.textRenderMode === 4 || st.textRenderMode === 6;
44441
44439
  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
44440
  const paint = {
44444
44441
  segments: transformedGlyphSegs,
44445
44442
  fillColor: isFillGlyph ? st.fillColor : void 0,
44446
44443
  fillAlpha: isFillGlyph ? st.fillAlpha : void 0,
44447
44444
  strokeColor: isStrokeGlyph ? st.strokeColor : void 0,
44448
44445
  strokeAlpha: isStrokeGlyph ? st.strokeAlpha : void 0,
44449
- strokeWidth: isStrokeGlyph ? st.strokeWidth * ctmScale : 0,
44446
+ strokeWidth: isStrokeGlyph ? st.strokeWidth : 0,
44447
+ ...isStrokeGlyph ? { strokeMatrix: [...st.ctm] } : {},
44450
44448
  fillRule: "nonzero",
44451
44449
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
44452
44450
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
@@ -47696,11 +47694,10 @@ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMa
47696
47694
  rgba[idx + 2] = Math.round((effB * a + cbB * dstA * (1 - a)) / outA * 255);
47697
47695
  rgba[idx + 3] = Math.round(outA * 255);
47698
47696
  }
47699
- function segmentsToScreenPaths(segments, pageHeight, scale) {
47697
+ function segmentsToScreenPaths(segments, pageHeight, scale, toScreen = (x, y) => [x * scale, (pageHeight - y) * scale]) {
47700
47698
  const paths = [];
47701
47699
  let points = [];
47702
47700
  let current = [0, 0];
47703
- const toScreen = (x, y) => [x * scale, (pageHeight - y) * scale];
47704
47701
  for (const segment of segments) {
47705
47702
  if (segment.kind === "move") {
47706
47703
  if (points.length) paths.push({ points, closed: false });
@@ -47739,6 +47736,63 @@ function segmentsToScreenPaths(segments, pageHeight, scale) {
47739
47736
  if (points.length) paths.push({ points, closed: false });
47740
47737
  return paths;
47741
47738
  }
47739
+ function inverseStrokeMatrix(matrix) {
47740
+ const [a, b, c, d, e, f] = matrix;
47741
+ const det = a * d - b * c;
47742
+ if (!Number.isFinite(det) || det === 0) return void 0;
47743
+ return [d / det, -b / det, -c / det, a / det, (c * f - d * e) / det, (b * e - a * f) / det];
47744
+ }
47745
+ function prepareStroke(path, scale) {
47746
+ const matrix = path.strokeMatrix ? [...path.strokeMatrix] : [1, 0, 0, 1, 0, 0];
47747
+ const [a, b, c, d] = matrix;
47748
+ const area = Math.abs(a * d - b * c) * scale * scale;
47749
+ if (!(area > 0) || !Number.isFinite(area)) return void 0;
47750
+ const normX = Math.hypot(a, b) * scale, normY = Math.hypot(c, d) * scale;
47751
+ let width = path.strokeWidth || 1;
47752
+ const scaleX = path.strokeWidth === 0 ? normY / area : Math.max(1, normY / (width * area));
47753
+ const scaleY = path.strokeWidth === 0 ? normX / area : Math.max(1, normX / (width * area));
47754
+ let dashArray = path.dashArray, dashPhase = path.dashPhase ?? 0;
47755
+ if (scaleX === scaleY) {
47756
+ width *= scaleX;
47757
+ } else {
47758
+ matrix[0] *= scaleX;
47759
+ matrix[1] *= scaleX;
47760
+ matrix[2] *= scaleY;
47761
+ matrix[3] *= scaleY;
47762
+ if (dashArray?.length) {
47763
+ const dashScale = Math.max(scaleX, scaleY);
47764
+ dashArray = dashArray.map((value) => value / dashScale);
47765
+ dashPhase /= dashScale;
47766
+ }
47767
+ }
47768
+ return { matrix, width, dashArray, dashPhase };
47769
+ }
47770
+ function strokeEdges(path, pageHeight, scale) {
47771
+ const stroke = prepareStroke(path, scale);
47772
+ if (!stroke) return [];
47773
+ const inverse = inverseStrokeMatrix(stroke.matrix);
47774
+ if (!inverse) return [];
47775
+ const [a, b, c, d, e, f] = stroke.matrix;
47776
+ const strokeScale = scale * Math.hypot(a, b, c, d);
47777
+ const project = (x, y) => [
47778
+ (inverse[0] * x + inverse[2] * y + inverse[4]) * strokeScale,
47779
+ (inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
47780
+ ];
47781
+ const toScreen = ([x, y]) => [
47782
+ (a * x / strokeScale + c * y / strokeScale + e) * scale,
47783
+ (pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
47784
+ ];
47785
+ const contours = strokeOutlines(
47786
+ segmentsToScreenPaths(path.segments, pageHeight, scale, project),
47787
+ stroke.width * strokeScale,
47788
+ path.lineCap ?? 0,
47789
+ path.lineJoin ?? 0,
47790
+ path.miterLimit ?? 10,
47791
+ stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
47792
+ stroke.dashPhase * strokeScale
47793
+ );
47794
+ return pathsToEdges(contours.map((points) => ({ points: points.map(toScreen), closed: true })));
47795
+ }
47742
47796
  function pathsToEdges(paths, closeSubpaths = false) {
47743
47797
  const edges = [];
47744
47798
  for (const { points, closed } of paths) {
@@ -47988,19 +48042,9 @@ function renderDisplayListToBitmap(displayList, options = {}) {
47988
48042
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
47989
48043
  }
47990
48044
  if (path.strokeColor) {
47991
- const rawSw = path.strokeWidth * scale;
47992
- const sw = Math.max(1, rawSw);
48045
+ const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
47993
48046
  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 })));
48047
+ const edges = strokeEdges(path, displayList.height, scale);
48004
48048
  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
48049
  fillEdgesScanline4x4(
48006
48050
  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;
@@ -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] } : {}
@@ -41503,11 +41501,10 @@ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMa
41503
41501
  rgba[idx + 2] = Math.round((effB * a + cbB * dstA * (1 - a)) / outA * 255);
41504
41502
  rgba[idx + 3] = Math.round(outA * 255);
41505
41503
  }
41506
- function segmentsToScreenPaths(segments, pageHeight, scale) {
41504
+ function segmentsToScreenPaths(segments, pageHeight, scale, toScreen = (x, y) => [x * scale, (pageHeight - y) * scale]) {
41507
41505
  const paths = [];
41508
41506
  let points = [];
41509
41507
  let current = [0, 0];
41510
- const toScreen = (x, y) => [x * scale, (pageHeight - y) * scale];
41511
41508
  for (const segment of segments) {
41512
41509
  if (segment.kind === "move") {
41513
41510
  if (points.length) paths.push({ points, closed: false });
@@ -41546,6 +41543,63 @@ function segmentsToScreenPaths(segments, pageHeight, scale) {
41546
41543
  if (points.length) paths.push({ points, closed: false });
41547
41544
  return paths;
41548
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 })));
41602
+ }
41549
41603
  function pathsToEdges(paths, closeSubpaths = false) {
41550
41604
  const edges = [];
41551
41605
  for (const { points, closed } of paths) {
@@ -41795,19 +41849,9 @@ function renderDisplayListToBitmap(displayList, options = {}) {
41795
41849
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
41796
41850
  }
41797
41851
  if (path.strokeColor) {
41798
- const rawSw = path.strokeWidth * scale;
41799
- const sw = Math.max(1, rawSw);
41852
+ const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
41800
41853
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
41801
- const contours = strokeOutlines(
41802
- segmentsToScreenPaths(path.segments, displayList.height, scale),
41803
- sw,
41804
- path.lineCap ?? 0,
41805
- path.lineJoin ?? 0,
41806
- path.miterLimit ?? 10,
41807
- path.dashArray?.map((value) => Math.max(0, value * scale)),
41808
- (path.dashPhase ?? 0) * scale
41809
- );
41810
- const edges = pathsToEdges(contours.map((points) => ({ points, closed: true })));
41854
+ const edges = strokeEdges(path, displayList.height, scale);
41811
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;
41812
41856
  fillEdgesScanline4x4(
41813
41857
  rgba,
@@ -41957,17 +42001,19 @@ function svgImage(image, pageHeight) {
41957
42001
  const [a, b, c, d, e, f] = image.matrix;
41958
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(""))}"/>`;
41959
42003
  }
41960
- function svgPathData(segments, height) {
42004
+ function svgPathData(segments, height, matrix) {
41961
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}`;
41962
42007
  for (const seg of segments) {
41963
42008
  if (seg.kind === "move") {
41964
- dParts.push(`M ${seg.x} ${height - seg.y}`);
42009
+ dParts.push(`M ${point(seg.x, seg.y)}`);
41965
42010
  } else if (seg.kind === "line") {
41966
- dParts.push(`L ${seg.x} ${height - seg.y}`);
42011
+ dParts.push(`L ${point(seg.x, seg.y)}`);
41967
42012
  } else if (seg.kind === "cubic") {
41968
- 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)}`);
41969
42014
  } else if (seg.kind === "rect") {
41970
- 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`);
41971
42017
  } else if (seg.kind === "close") {
41972
42018
  dParts.push("Z");
41973
42019
  }
@@ -42046,21 +42092,25 @@ function renderDisplayListToSvg(displayList, options = {}) {
42046
42092
  parts.push("</g>");
42047
42093
  } else if (operation.kind === "path") {
42048
42094
  const p = operation.value;
42049
- 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]})"` : "";
42050
42100
  if (pathData) {
42051
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";
42052
- 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";
42053
42103
  const fillRuleAttr = p.fillRule === "evenodd" ? ` fill-rule="evenodd"` : "";
42054
42104
  const fillOpacityAttr = p.fillAlpha !== void 0 && p.fillAlpha < 1 ? ` fill-opacity="${p.fillAlpha}"` : "";
42055
42105
  const strokeOpacityAttr = p.strokeAlpha !== void 0 && p.strokeAlpha < 1 ? ` stroke-opacity="${p.strokeAlpha}"` : "";
42056
- 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}"`;
42057
42107
  const lineCapAttr = p.lineCap === 1 ? ` stroke-linecap="round"` : p.lineCap === 2 ? ` stroke-linecap="square"` : "";
42058
42108
  const lineJoinAttr = p.lineJoin === 1 ? ` stroke-linejoin="round"` : p.lineJoin === 2 ? ` stroke-linejoin="bevel"` : "";
42059
42109
  const miterLimitAttr = p.miterLimit !== void 0 && p.miterLimit !== 10 ? ` stroke-miterlimit="${p.miterLimit}"` : "";
42060
- const dashArrayAttr = p.dashArray && p.dashArray.length > 0 ? ` stroke-dasharray="${p.dashArray.join(" ")}"` : "";
42061
- 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}"` : "";
42062
42112
  const labelAttr = original.kind === "glyph" ? ` aria-label="${escapeXmlText(original.value.unicode)}"` : "";
42063
- 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}/>`);
42064
42114
  }
42065
42115
  } else if (operation.kind === "image") {
42066
42116
  parts.push(` ${svgImage(operation.value, displayList.height)}`);
@@ -48,11 +48,11 @@ import {
48
48
  trimImage,
49
49
  unflattenImage,
50
50
  unpremultiplyRgbaImage
51
- } from "./chunk-RDPJGIQF.js";
51
+ } from "./chunk-SVL6HYQL.js";
52
52
  import {
53
53
  PdfDocument,
54
54
  encodePng
55
- } from "./chunk-G3IIEU2N.js";
55
+ } from "./chunk-KO4PXCNL.js";
56
56
  import {
57
57
  createLuaFilterCapability
58
58
  } from "./chunk-Y2KHC6TZ.js";