@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.
@@ -28,8 +28,8 @@ import {
28
28
  thresholdImage,
29
29
  tintImage,
30
30
  trimImage
31
- } from "../safe-bash/command-chunks/chunk-RDPJGIQF.js";
32
- import "../safe-bash/command-chunks/chunk-G3IIEU2N.js";
31
+ } from "../safe-bash/command-chunks/chunk-IOH3F3ZO.js";
32
+ import "../safe-bash/command-chunks/chunk-XFUFHHLU.js";
33
33
  import {
34
34
  init_buffer
35
35
  } from "../safe-bash/command-chunks/chunk-HX3SHTCE.js";
@@ -2,11 +2,11 @@ import {
2
2
  createPandocCommand,
3
3
  createPandocCommands,
4
4
  pandocCommands
5
- } from "../safe-bash/command-chunks/chunk-B7YLGJRF.js";
5
+ } from "../safe-bash/command-chunks/chunk-DKWMTHU3.js";
6
6
  import "../safe-bash/command-chunks/chunk-MKQVQMXO.js";
7
7
  import "../safe-bash/command-chunks/chunk-RDV7UCYZ.js";
8
- import "../safe-bash/command-chunks/chunk-RDPJGIQF.js";
9
- import "../safe-bash/command-chunks/chunk-G3IIEU2N.js";
8
+ import "../safe-bash/command-chunks/chunk-IOH3F3ZO.js";
9
+ import "../safe-bash/command-chunks/chunk-XFUFHHLU.js";
10
10
  import "../safe-bash/command-chunks/chunk-Y2KHC6TZ.js";
11
11
  import "../safe-bash/command-chunks/chunk-YGYOVXTO.js";
12
12
  import "../safe-bash/command-chunks/chunk-I5GLTNVH.js";
@@ -21,11 +21,11 @@ import {
21
21
  readDocument,
22
22
  resolveConversionArgs,
23
23
  writeDocument
24
- } from "../safe-bash/command-chunks/chunk-B7YLGJRF.js";
24
+ } from "../safe-bash/command-chunks/chunk-DKWMTHU3.js";
25
25
  import "../safe-bash/command-chunks/chunk-MKQVQMXO.js";
26
26
  import "../safe-bash/command-chunks/chunk-RDV7UCYZ.js";
27
- import "../safe-bash/command-chunks/chunk-RDPJGIQF.js";
28
- import "../safe-bash/command-chunks/chunk-G3IIEU2N.js";
27
+ import "../safe-bash/command-chunks/chunk-IOH3F3ZO.js";
28
+ import "../safe-bash/command-chunks/chunk-XFUFHHLU.js";
29
29
  import {
30
30
  createLuaFilterCapability
31
31
  } from "../safe-bash/command-chunks/chunk-Y2KHC6TZ.js";
@@ -36049,11 +36049,10 @@ function evaluateContentStreamToDisplayList(params) {
36049
36049
  } else if (operator === "d") {
36050
36050
  const arrNode = ops[0]?.kind === "array" ? ops[0] : void 0;
36051
36051
  if (arrNode) {
36052
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
36053
- const nums = arrNode.items.map((it) => it.kind === "number" ? it.value * ctmScale : 0).filter((v) => v >= 0);
36052
+ const nums = arrNode.items.map((it) => it.kind === "number" ? it.value : 0).filter((v) => v >= 0);
36054
36053
  const sum = nums.reduce((a, b) => a + b, 0);
36055
36054
  st.dashArray = sum > 0 ? nums : void 0;
36056
- st.dashPhase = num(1, 0) * ctmScale;
36055
+ st.dashPhase = num(1, 0);
36057
36056
  } else {
36058
36057
  st.dashArray = void 0;
36059
36058
  st.dashPhase = void 0;
@@ -36185,10 +36184,11 @@ function evaluateContentStreamToDisplayList(params) {
36185
36184
  const patArr = params.cosDoc.resolveArray(dArr.items[0]);
36186
36185
  const phaseNode = params.cosDoc.resolve(dArr.items[1]);
36187
36186
  if (patArr) {
36188
- st.dashArray = patArr.items.map((it) => {
36187
+ const dashArray = patArr.items.map((it) => {
36189
36188
  const r = params.cosDoc.resolve(it);
36190
36189
  return r?.kind === "number" ? r.value : 0;
36191
- }).filter((n) => n > 0);
36190
+ }).filter((n) => n >= 0);
36191
+ st.dashArray = dashArray.some((value) => value > 0) ? dashArray : void 0;
36192
36192
  st.dashPhase = phaseNode?.kind === "number" ? phaseNode.value : 0;
36193
36193
  }
36194
36194
  }
@@ -36589,15 +36589,14 @@ function evaluateContentStreamToDisplayList(params) {
36589
36589
  break;
36590
36590
  }
36591
36591
  const fillRule = node.paint.includes("*") ? "evenodd" : "nonzero";
36592
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
36593
- const scaledStrokeWidth = st.strokeWidth === 0 ? 0 : st.strokeWidth * ctmScale;
36594
36592
  emit({ kind: "path", value: {
36595
36593
  segments: transformedSegments,
36596
36594
  fillColor: isFill && !evaluatedFillPattern ? st.fillColor : void 0,
36597
36595
  fillAlpha: isFill && !evaluatedFillPattern ? st.fillAlpha : void 0,
36598
36596
  strokeColor: isStroke ? st.strokeColor : void 0,
36599
36597
  strokeAlpha: isStroke ? st.strokeAlpha : void 0,
36600
- strokeWidth: scaledStrokeWidth,
36598
+ strokeWidth: st.strokeWidth,
36599
+ ...isStroke ? { strokeMatrix: [...st.ctm] } : {},
36601
36600
  ...st.lineCap !== 0 ? { lineCap: st.lineCap } : {},
36602
36601
  ...st.lineJoin !== 0 ? { lineJoin: st.lineJoin } : {},
36603
36602
  ...st.miterLimit !== 10 ? { miterLimit: st.miterLimit } : {},
@@ -36785,14 +36784,14 @@ function evaluateContentStreamToDisplayList(params) {
36785
36784
  if (st.textRenderMode >= 4 && st.textRenderMode <= 7) pendingTextClip.push(...transformedGlyphSegs);
36786
36785
  const isFillGlyph = st.textRenderMode === 0 || st.textRenderMode === 2 || st.textRenderMode === 4 || st.textRenderMode === 6;
36787
36786
  const isStrokeGlyph = st.textRenderMode === 1 || st.textRenderMode === 2 || st.textRenderMode === 5 || st.textRenderMode === 6;
36788
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
36789
36787
  const paint = {
36790
36788
  segments: transformedGlyphSegs,
36791
36789
  fillColor: isFillGlyph ? st.fillColor : void 0,
36792
36790
  fillAlpha: isFillGlyph ? st.fillAlpha : void 0,
36793
36791
  strokeColor: isStrokeGlyph ? st.strokeColor : void 0,
36794
36792
  strokeAlpha: isStrokeGlyph ? st.strokeAlpha : void 0,
36795
- strokeWidth: isStrokeGlyph ? st.strokeWidth * ctmScale : 0,
36793
+ strokeWidth: isStrokeGlyph ? st.strokeWidth : 0,
36794
+ ...isStrokeGlyph ? { strokeMatrix: [...st.ctm] } : {},
36796
36795
  fillRule: "nonzero",
36797
36796
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
36798
36797
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
@@ -39193,7 +39192,7 @@ function dashSubpath(path, pattern, phase) {
39193
39192
  while (remaining <= 0) {
39194
39193
  if (++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39195
39194
  if (index % 2 === 0) {
39196
- if (pattern[index] === 0) result.push({ points: [point, point], closed: false });
39195
+ if (pattern[index] === 0) result.push({ points: [point, point], closed: false, zeroLengthDash: true });
39197
39196
  flush();
39198
39197
  }
39199
39198
  index = (index + 1) % pattern.length;
@@ -39208,7 +39207,7 @@ function dashSubpath(path, pattern, phase) {
39208
39207
  throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39209
39208
  }
39210
39209
  let distance = 0;
39211
- while (distance < length) {
39210
+ while (length - distance > 8 * Number.EPSILON * Math.max(1, length)) {
39212
39211
  const point = [start[0] + dx * distance / length, start[1] + dy * distance / length];
39213
39212
  advance(point);
39214
39213
  const step = Math.min(remaining, length - distance);
@@ -39323,7 +39322,15 @@ function strokeOutlines(paths, width, cap, join, miterLimit, dashArray = [], das
39323
39322
  let closed = subpath.closed;
39324
39323
  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();
39325
39324
  if (points.length < 3) closed = false;
39326
- if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
39325
+ if (points.length === 1 && cap === 2 && subpath.zeroLengthDash) {
39326
+ contour = [];
39327
+ const [x, y] = points[0];
39328
+ add(x - half, y - half);
39329
+ add(x + half, y - half);
39330
+ add(x + half, y + half);
39331
+ add(x - half, y + half);
39332
+ contours.push(contour);
39333
+ } else if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
39327
39334
  contour = [];
39328
39335
  const [x, y] = points[0];
39329
39336
  addCap([x, y], [x + 1, y]);
@@ -40196,11 +40203,10 @@ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMa
40196
40203
  rgba[idx + 2] = Math.round((effB * a + cbB * dstA * (1 - a)) / outA * 255);
40197
40204
  rgba[idx + 3] = Math.round(outA * 255);
40198
40205
  }
40199
- function segmentsToScreenPaths(segments, pageHeight, scale) {
40206
+ function segmentsToScreenPaths(segments, pageHeight, scale, toScreen = (x, y) => [x * scale, (pageHeight - y) * scale]) {
40200
40207
  const paths = [];
40201
40208
  let points = [];
40202
40209
  let current = [0, 0];
40203
- const toScreen = (x, y) => [x * scale, (pageHeight - y) * scale];
40204
40210
  for (const segment of segments) {
40205
40211
  if (segment.kind === "move") {
40206
40212
  if (points.length) paths.push({ points, closed: false });
@@ -40239,6 +40245,63 @@ function segmentsToScreenPaths(segments, pageHeight, scale) {
40239
40245
  if (points.length) paths.push({ points, closed: false });
40240
40246
  return paths;
40241
40247
  }
40248
+ function inverseStrokeMatrix(matrix) {
40249
+ const [a, b, c, d, e, f] = matrix;
40250
+ const det = a * d - b * c;
40251
+ if (!Number.isFinite(det) || det === 0) return void 0;
40252
+ return [d / det, -b / det, -c / det, a / det, (c * f - d * e) / det, (b * e - a * f) / det];
40253
+ }
40254
+ function prepareStroke(path, scale) {
40255
+ const matrix = path.strokeMatrix ? [...path.strokeMatrix] : [1, 0, 0, 1, 0, 0];
40256
+ const [a, b, c, d] = matrix;
40257
+ const area = Math.abs(a * d - b * c) * scale * scale;
40258
+ if (!(area > 0) || !Number.isFinite(area)) return void 0;
40259
+ const normX = Math.hypot(a, b) * scale, normY = Math.hypot(c, d) * scale;
40260
+ let width = path.strokeWidth || 1;
40261
+ const scaleX = path.strokeWidth === 0 ? normY / area : Math.max(1, normY / (width * area));
40262
+ const scaleY = path.strokeWidth === 0 ? normX / area : Math.max(1, normX / (width * area));
40263
+ let dashArray = path.dashArray, dashPhase = path.dashPhase ?? 0;
40264
+ if (scaleX === scaleY) {
40265
+ width *= scaleX;
40266
+ } else {
40267
+ matrix[0] *= scaleX;
40268
+ matrix[1] *= scaleX;
40269
+ matrix[2] *= scaleY;
40270
+ matrix[3] *= scaleY;
40271
+ if (dashArray?.length) {
40272
+ const dashScale = Math.max(scaleX, scaleY);
40273
+ dashArray = dashArray.map((value) => value / dashScale);
40274
+ dashPhase /= dashScale;
40275
+ }
40276
+ }
40277
+ return { matrix, width, dashArray, dashPhase };
40278
+ }
40279
+ function strokeContours(path, pageHeight, scale) {
40280
+ const stroke = prepareStroke(path, scale);
40281
+ if (!stroke) return [];
40282
+ const inverse = inverseStrokeMatrix(stroke.matrix);
40283
+ if (!inverse) return [];
40284
+ const [a, b, c, d, e, f] = stroke.matrix;
40285
+ const strokeScale = scale * Math.hypot(a, b, c, d);
40286
+ const project = (x, y) => [
40287
+ (inverse[0] * x + inverse[2] * y + inverse[4]) * strokeScale,
40288
+ (inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
40289
+ ];
40290
+ const toScreen = ([x, y]) => [
40291
+ (a * x / strokeScale + c * y / strokeScale + e) * scale,
40292
+ (pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
40293
+ ];
40294
+ const contours = strokeOutlines(
40295
+ segmentsToScreenPaths(path.segments, pageHeight, scale, project),
40296
+ stroke.width * strokeScale,
40297
+ path.lineCap ?? 0,
40298
+ path.lineJoin ?? 0,
40299
+ path.miterLimit ?? 10,
40300
+ stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
40301
+ stroke.dashPhase * strokeScale
40302
+ );
40303
+ return contours.map((points) => points.map(toScreen));
40304
+ }
40242
40305
  function pathsToEdges(paths, closeSubpaths = false) {
40243
40306
  const edges = [];
40244
40307
  for (const { points, closed } of paths) {
@@ -40488,19 +40551,9 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40488
40551
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
40489
40552
  }
40490
40553
  if (path.strokeColor) {
40491
- const rawSw = path.strokeWidth * scale;
40492
- const sw = Math.max(1, rawSw);
40554
+ const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
40493
40555
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
40494
- const contours = strokeOutlines(
40495
- segmentsToScreenPaths(path.segments, displayList.height, scale),
40496
- sw,
40497
- path.lineCap ?? 0,
40498
- path.lineJoin ?? 0,
40499
- path.miterLimit ?? 10,
40500
- path.dashArray?.map((value) => Math.max(0, value * scale)),
40501
- (path.dashPhase ?? 0) * scale
40502
- );
40503
- const edges = pathsToEdges(contours.map((points) => ({ points, closed: true })));
40556
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
40504
40557
  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;
40505
40558
  fillEdgesScanline4x4(
40506
40559
  rgba,
@@ -36243,11 +36243,10 @@ function evaluateContentStreamToDisplayList(params) {
36243
36243
  } else if (operator === "d") {
36244
36244
  const arrNode = ops[0]?.kind === "array" ? ops[0] : void 0;
36245
36245
  if (arrNode) {
36246
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
36247
- const nums = arrNode.items.map((it) => it.kind === "number" ? it.value * ctmScale : 0).filter((v) => v >= 0);
36246
+ const nums = arrNode.items.map((it) => it.kind === "number" ? it.value : 0).filter((v) => v >= 0);
36248
36247
  const sum = nums.reduce((a, b) => a + b, 0);
36249
36248
  st.dashArray = sum > 0 ? nums : void 0;
36250
- st.dashPhase = num(1, 0) * ctmScale;
36249
+ st.dashPhase = num(1, 0);
36251
36250
  } else {
36252
36251
  st.dashArray = void 0;
36253
36252
  st.dashPhase = void 0;
@@ -36379,10 +36378,11 @@ function evaluateContentStreamToDisplayList(params) {
36379
36378
  const patArr = params.cosDoc.resolveArray(dArr.items[0]);
36380
36379
  const phaseNode = params.cosDoc.resolve(dArr.items[1]);
36381
36380
  if (patArr) {
36382
- st.dashArray = patArr.items.map((it) => {
36381
+ const dashArray = patArr.items.map((it) => {
36383
36382
  const r = params.cosDoc.resolve(it);
36384
36383
  return r?.kind === "number" ? r.value : 0;
36385
- }).filter((n) => n > 0);
36384
+ }).filter((n) => n >= 0);
36385
+ st.dashArray = dashArray.some((value) => value > 0) ? dashArray : void 0;
36386
36386
  st.dashPhase = phaseNode?.kind === "number" ? phaseNode.value : 0;
36387
36387
  }
36388
36388
  }
@@ -36783,15 +36783,14 @@ function evaluateContentStreamToDisplayList(params) {
36783
36783
  break;
36784
36784
  }
36785
36785
  const fillRule = node.paint.includes("*") ? "evenodd" : "nonzero";
36786
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
36787
- const scaledStrokeWidth = st.strokeWidth === 0 ? 0 : st.strokeWidth * ctmScale;
36788
36786
  emit({ kind: "path", value: {
36789
36787
  segments: transformedSegments,
36790
36788
  fillColor: isFill && !evaluatedFillPattern ? st.fillColor : void 0,
36791
36789
  fillAlpha: isFill && !evaluatedFillPattern ? st.fillAlpha : void 0,
36792
36790
  strokeColor: isStroke ? st.strokeColor : void 0,
36793
36791
  strokeAlpha: isStroke ? st.strokeAlpha : void 0,
36794
- strokeWidth: scaledStrokeWidth,
36792
+ strokeWidth: st.strokeWidth,
36793
+ ...isStroke ? { strokeMatrix: [...st.ctm] } : {},
36795
36794
  ...st.lineCap !== 0 ? { lineCap: st.lineCap } : {},
36796
36795
  ...st.lineJoin !== 0 ? { lineJoin: st.lineJoin } : {},
36797
36796
  ...st.miterLimit !== 10 ? { miterLimit: st.miterLimit } : {},
@@ -36979,14 +36978,14 @@ function evaluateContentStreamToDisplayList(params) {
36979
36978
  if (st.textRenderMode >= 4 && st.textRenderMode <= 7) pendingTextClip.push(...transformedGlyphSegs);
36980
36979
  const isFillGlyph = st.textRenderMode === 0 || st.textRenderMode === 2 || st.textRenderMode === 4 || st.textRenderMode === 6;
36981
36980
  const isStrokeGlyph = st.textRenderMode === 1 || st.textRenderMode === 2 || st.textRenderMode === 5 || st.textRenderMode === 6;
36982
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
36983
36981
  const paint = {
36984
36982
  segments: transformedGlyphSegs,
36985
36983
  fillColor: isFillGlyph ? st.fillColor : void 0,
36986
36984
  fillAlpha: isFillGlyph ? st.fillAlpha : void 0,
36987
36985
  strokeColor: isStrokeGlyph ? st.strokeColor : void 0,
36988
36986
  strokeAlpha: isStrokeGlyph ? st.strokeAlpha : void 0,
36989
- strokeWidth: isStrokeGlyph ? st.strokeWidth * ctmScale : 0,
36987
+ strokeWidth: isStrokeGlyph ? st.strokeWidth : 0,
36988
+ ...isStrokeGlyph ? { strokeMatrix: [...st.ctm] } : {},
36990
36989
  fillRule: "nonzero",
36991
36990
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
36992
36991
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
@@ -39387,7 +39386,7 @@ function dashSubpath(path, pattern, phase) {
39387
39386
  while (remaining <= 0) {
39388
39387
  if (++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39389
39388
  if (index % 2 === 0) {
39390
- if (pattern[index] === 0) result.push({ points: [point, point], closed: false });
39389
+ if (pattern[index] === 0) result.push({ points: [point, point], closed: false, zeroLengthDash: true });
39391
39390
  flush();
39392
39391
  }
39393
39392
  index = (index + 1) % pattern.length;
@@ -39402,7 +39401,7 @@ function dashSubpath(path, pattern, phase) {
39402
39401
  throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39403
39402
  }
39404
39403
  let distance = 0;
39405
- while (distance < length) {
39404
+ while (length - distance > 8 * Number.EPSILON * Math.max(1, length)) {
39406
39405
  const point = [start[0] + dx * distance / length, start[1] + dy * distance / length];
39407
39406
  advance(point);
39408
39407
  const step = Math.min(remaining, length - distance);
@@ -39517,7 +39516,15 @@ function strokeOutlines(paths, width, cap, join, miterLimit, dashArray = [], das
39517
39516
  let closed = subpath.closed;
39518
39517
  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();
39519
39518
  if (points.length < 3) closed = false;
39520
- if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
39519
+ if (points.length === 1 && cap === 2 && subpath.zeroLengthDash) {
39520
+ contour = [];
39521
+ const [x, y] = points[0];
39522
+ add(x - half, y - half);
39523
+ add(x + half, y - half);
39524
+ add(x + half, y + half);
39525
+ add(x - half, y + half);
39526
+ contours.push(contour);
39527
+ } else if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
39521
39528
  contour = [];
39522
39529
  const [x, y] = points[0];
39523
39530
  addCap([x, y], [x + 1, y]);
@@ -40632,11 +40639,10 @@ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMa
40632
40639
  rgba[idx + 2] = Math.round((effB * a + cbB * dstA * (1 - a)) / outA * 255);
40633
40640
  rgba[idx + 3] = Math.round(outA * 255);
40634
40641
  }
40635
- function segmentsToScreenPaths(segments, pageHeight, scale) {
40642
+ function segmentsToScreenPaths(segments, pageHeight, scale, toScreen = (x, y) => [x * scale, (pageHeight - y) * scale]) {
40636
40643
  const paths = [];
40637
40644
  let points = [];
40638
40645
  let current = [0, 0];
40639
- const toScreen = (x, y) => [x * scale, (pageHeight - y) * scale];
40640
40646
  for (const segment of segments) {
40641
40647
  if (segment.kind === "move") {
40642
40648
  if (points.length) paths.push({ points, closed: false });
@@ -40675,6 +40681,63 @@ function segmentsToScreenPaths(segments, pageHeight, scale) {
40675
40681
  if (points.length) paths.push({ points, closed: false });
40676
40682
  return paths;
40677
40683
  }
40684
+ function inverseStrokeMatrix(matrix) {
40685
+ const [a, b, c, d, e, f] = matrix;
40686
+ const det = a * d - b * c;
40687
+ if (!Number.isFinite(det) || det === 0) return void 0;
40688
+ return [d / det, -b / det, -c / det, a / det, (c * f - d * e) / det, (b * e - a * f) / det];
40689
+ }
40690
+ function prepareStroke(path, scale) {
40691
+ const matrix = path.strokeMatrix ? [...path.strokeMatrix] : [1, 0, 0, 1, 0, 0];
40692
+ const [a, b, c, d] = matrix;
40693
+ const area = Math.abs(a * d - b * c) * scale * scale;
40694
+ if (!(area > 0) || !Number.isFinite(area)) return void 0;
40695
+ const normX = Math.hypot(a, b) * scale, normY = Math.hypot(c, d) * scale;
40696
+ let width = path.strokeWidth || 1;
40697
+ const scaleX = path.strokeWidth === 0 ? normY / area : Math.max(1, normY / (width * area));
40698
+ const scaleY = path.strokeWidth === 0 ? normX / area : Math.max(1, normX / (width * area));
40699
+ let dashArray = path.dashArray, dashPhase = path.dashPhase ?? 0;
40700
+ if (scaleX === scaleY) {
40701
+ width *= scaleX;
40702
+ } else {
40703
+ matrix[0] *= scaleX;
40704
+ matrix[1] *= scaleX;
40705
+ matrix[2] *= scaleY;
40706
+ matrix[3] *= scaleY;
40707
+ if (dashArray?.length) {
40708
+ const dashScale = Math.max(scaleX, scaleY);
40709
+ dashArray = dashArray.map((value) => value / dashScale);
40710
+ dashPhase /= dashScale;
40711
+ }
40712
+ }
40713
+ return { matrix, width, dashArray, dashPhase };
40714
+ }
40715
+ function strokeContours(path, pageHeight, scale) {
40716
+ const stroke = prepareStroke(path, scale);
40717
+ if (!stroke) return [];
40718
+ const inverse = inverseStrokeMatrix(stroke.matrix);
40719
+ if (!inverse) return [];
40720
+ const [a, b, c, d, e, f] = stroke.matrix;
40721
+ const strokeScale = scale * Math.hypot(a, b, c, d);
40722
+ const project = (x, y) => [
40723
+ (inverse[0] * x + inverse[2] * y + inverse[4]) * strokeScale,
40724
+ (inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
40725
+ ];
40726
+ const toScreen = ([x, y]) => [
40727
+ (a * x / strokeScale + c * y / strokeScale + e) * scale,
40728
+ (pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
40729
+ ];
40730
+ const contours = strokeOutlines(
40731
+ segmentsToScreenPaths(path.segments, pageHeight, scale, project),
40732
+ stroke.width * strokeScale,
40733
+ path.lineCap ?? 0,
40734
+ path.lineJoin ?? 0,
40735
+ path.miterLimit ?? 10,
40736
+ stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
40737
+ stroke.dashPhase * strokeScale
40738
+ );
40739
+ return contours.map((points) => points.map(toScreen));
40740
+ }
40678
40741
  function pathsToEdges(paths, closeSubpaths = false) {
40679
40742
  const edges = [];
40680
40743
  for (const { points, closed } of paths) {
@@ -40924,19 +40987,9 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40924
40987
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
40925
40988
  }
40926
40989
  if (path.strokeColor) {
40927
- const rawSw = path.strokeWidth * scale;
40928
- const sw = Math.max(1, rawSw);
40990
+ const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
40929
40991
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
40930
- const contours = strokeOutlines(
40931
- segmentsToScreenPaths(path.segments, displayList.height, scale),
40932
- sw,
40933
- path.lineCap ?? 0,
40934
- path.lineJoin ?? 0,
40935
- path.miterLimit ?? 10,
40936
- path.dashArray?.map((value) => Math.max(0, value * scale)),
40937
- (path.dashPhase ?? 0) * scale
40938
- );
40939
- const edges = pathsToEdges(contours.map((points) => ({ points, closed: true })));
40992
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
40940
40993
  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;
40941
40994
  fillEdgesScanline4x4(
40942
40995
  rgba,
@@ -41086,17 +41139,19 @@ function svgImage(image, pageHeight) {
41086
41139
  const [a, b, c, d, e, f] = image.matrix;
41087
41140
  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(""))}"/>`;
41088
41141
  }
41089
- function svgPathData(segments, height) {
41142
+ function svgPathData(segments, height, matrix) {
41090
41143
  const dParts = [];
41144
+ 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}`;
41091
41145
  for (const seg of segments) {
41092
41146
  if (seg.kind === "move") {
41093
- dParts.push(`M ${seg.x} ${height - seg.y}`);
41147
+ dParts.push(`M ${point(seg.x, seg.y)}`);
41094
41148
  } else if (seg.kind === "line") {
41095
- dParts.push(`L ${seg.x} ${height - seg.y}`);
41149
+ dParts.push(`L ${point(seg.x, seg.y)}`);
41096
41150
  } else if (seg.kind === "cubic") {
41097
- dParts.push(`C ${seg.x1} ${height - seg.y1} ${seg.x2} ${height - seg.y2} ${seg.x} ${height - seg.y}`);
41151
+ dParts.push(`C ${point(seg.x1, seg.y1)} ${point(seg.x2, seg.y2)} ${point(seg.x, seg.y)}`);
41098
41152
  } else if (seg.kind === "rect") {
41099
- dParts.push(`M ${seg.x} ${height - seg.y} h ${seg.width} v ${-seg.height} h ${-seg.width} Z`);
41153
+ 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`);
41154
+ else dParts.push(`M ${seg.x} ${height - seg.y} h ${seg.width} v ${-seg.height} h ${-seg.width} Z`);
41100
41155
  } else if (seg.kind === "close") {
41101
41156
  dParts.push("Z");
41102
41157
  }
@@ -41175,21 +41230,34 @@ function renderDisplayListToSvg(displayList, options = {}) {
41175
41230
  parts.push("</g>");
41176
41231
  } else if (operation.kind === "path") {
41177
41232
  const p = operation.value;
41178
- const pathData = svgPathData(p.segments, displayList.height);
41233
+ const prepared = p.strokeColor ? prepareStroke(p, Math.max(scaleX, scaleY)) : void 0;
41234
+ const outlineStroke = prepared && p.dashArray?.includes(0);
41235
+ const matrix = prepared && (prepared.matrix[0] !== 1 || prepared.matrix[1] !== 0 || prepared.matrix[2] !== 0 || prepared.matrix[3] !== 1) ? prepared.matrix : void 0;
41236
+ const inverse = matrix ? inverseStrokeMatrix(matrix) : void 0;
41237
+ const pathData = svgPathData(p.segments, inverse ? 0 : displayList.height, inverse);
41238
+ const transformAttr = inverse && matrix ? ` transform="matrix(${matrix[0]} ${-matrix[1]} ${-matrix[2]} ${matrix[3]} ${matrix[4]} ${displayList.height - matrix[5]})"` : "";
41179
41239
  if (pathData) {
41180
41240
  const fill = p.fillColor ? `rgb(${Math.round(p.fillColor.r * 255)},${Math.round(p.fillColor.g * 255)},${Math.round(p.fillColor.b * 255)})` : "none";
41181
- const stroke = p.strokeColor ? `rgb(${Math.round(p.strokeColor.r * 255)},${Math.round(p.strokeColor.g * 255)},${Math.round(p.strokeColor.b * 255)})` : "none";
41241
+ 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";
41182
41242
  const fillRuleAttr = p.fillRule === "evenodd" ? ` fill-rule="evenodd"` : "";
41183
41243
  const fillOpacityAttr = p.fillAlpha !== void 0 && p.fillAlpha < 1 ? ` fill-opacity="${p.fillAlpha}"` : "";
41184
41244
  const strokeOpacityAttr = p.strokeAlpha !== void 0 && p.strokeAlpha < 1 ? ` stroke-opacity="${p.strokeAlpha}"` : "";
41185
- const strokeWidthAttr = p.strokeWidth <= 0 ? ` stroke-width="1" vector-effect="non-scaling-stroke"` : ` stroke-width="${p.strokeWidth}"`;
41245
+ const strokeWidthAttr = p.strokeWidth <= 0 && !matrix && !p.dashArray?.length ? ` stroke-width="1" vector-effect="non-scaling-stroke"` : ` stroke-width="${prepared?.width ?? p.strokeWidth}"`;
41186
41246
  const lineCapAttr = p.lineCap === 1 ? ` stroke-linecap="round"` : p.lineCap === 2 ? ` stroke-linecap="square"` : "";
41187
41247
  const lineJoinAttr = p.lineJoin === 1 ? ` stroke-linejoin="round"` : p.lineJoin === 2 ? ` stroke-linejoin="bevel"` : "";
41188
41248
  const miterLimitAttr = p.miterLimit !== void 0 && p.miterLimit !== 10 ? ` stroke-miterlimit="${p.miterLimit}"` : "";
41189
- const dashArrayAttr = p.dashArray && p.dashArray.length > 0 ? ` stroke-dasharray="${p.dashArray.join(" ")}"` : "";
41190
- const dashOffsetAttr = p.dashPhase ? ` stroke-dashoffset="${p.dashPhase}"` : "";
41249
+ const dashArrayAttr = !outlineStroke && prepared?.dashArray?.length ? ` stroke-dasharray="${prepared.dashArray.join(" ")}"` : "";
41250
+ const dashOffsetAttr = !outlineStroke && prepared?.dashPhase ? ` stroke-dashoffset="${prepared.dashPhase}"` : "";
41191
41251
  const labelAttr = original.kind === "glyph" ? ` aria-label="${escapeXmlText(original.value.unicode)}"` : "";
41192
- parts.push(` <path${labelAttr} d="${pathData}" fill="${fill}"${fillRuleAttr}${fillOpacityAttr} stroke="${stroke}"${strokeOpacityAttr}${strokeWidthAttr}${lineCapAttr}${lineJoinAttr}${miterLimitAttr}${dashArrayAttr}${dashOffsetAttr}/>`);
41252
+ if (!outlineStroke || p.fillColor) {
41253
+ parts.push(` <path${labelAttr}${transformAttr} d="${pathData}" fill="${fill}"${fillRuleAttr}${fillOpacityAttr} stroke="${outlineStroke ? "none" : stroke}"${strokeOpacityAttr}${strokeWidthAttr}${lineCapAttr}${lineJoinAttr}${miterLimitAttr}${dashArrayAttr}${dashOffsetAttr}/>`);
41254
+ }
41255
+ if (outlineStroke) {
41256
+ const outlineScale = Math.max(scaleX, scaleY);
41257
+ const contours = strokeContours(p, displayList.height, outlineScale);
41258
+ const outlineData = contours.map((points) => points.map(([x, y], i) => `${i === 0 ? "M" : "L"} ${x / outlineScale} ${y / outlineScale}`).join(" ") + " Z").join(" ");
41259
+ if (outlineData) parts.push(` <path${labelAttr} d="${outlineData}" fill="${stroke}" fill-opacity="${p.strokeAlpha ?? 1}"/>`);
41260
+ }
41193
41261
  }
41194
41262
  } else if (operation.kind === "image") {
41195
41263
  parts.push(` ${svgImage(operation.value, displayList.height)}`);