@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.
@@ -209211,11 +209211,10 @@ function evaluateContentStreamToDisplayList(params) {
209211
209211
  } else if (operator === "d") {
209212
209212
  const arrNode = ops[0]?.kind === "array" ? ops[0] : void 0;
209213
209213
  if (arrNode) {
209214
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
209215
- const nums = arrNode.items.map((it) => it.kind === "number" ? it.value * ctmScale : 0).filter((v) => v >= 0);
209214
+ const nums = arrNode.items.map((it) => it.kind === "number" ? it.value : 0).filter((v) => v >= 0);
209216
209215
  const sum2 = nums.reduce((a3, b3) => a3 + b3, 0);
209217
209216
  st.dashArray = sum2 > 0 ? nums : void 0;
209218
- st.dashPhase = num(1, 0) * ctmScale;
209217
+ st.dashPhase = num(1, 0);
209219
209218
  } else {
209220
209219
  st.dashArray = void 0;
209221
209220
  st.dashPhase = void 0;
@@ -209751,15 +209750,14 @@ function evaluateContentStreamToDisplayList(params) {
209751
209750
  break;
209752
209751
  }
209753
209752
  const fillRule = node3.paint.includes("*") ? "evenodd" : "nonzero";
209754
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
209755
- const scaledStrokeWidth = st.strokeWidth === 0 ? 0 : st.strokeWidth * ctmScale;
209756
209753
  emit({ kind: "path", value: {
209757
209754
  segments: transformedSegments,
209758
209755
  fillColor: isFill && !evaluatedFillPattern ? st.fillColor : void 0,
209759
209756
  fillAlpha: isFill && !evaluatedFillPattern ? st.fillAlpha : void 0,
209760
209757
  strokeColor: isStroke ? st.strokeColor : void 0,
209761
209758
  strokeAlpha: isStroke ? st.strokeAlpha : void 0,
209762
- strokeWidth: scaledStrokeWidth,
209759
+ strokeWidth: st.strokeWidth,
209760
+ ...isStroke ? { strokeMatrix: [...st.ctm] } : {},
209763
209761
  ...st.lineCap !== 0 ? { lineCap: st.lineCap } : {},
209764
209762
  ...st.lineJoin !== 0 ? { lineJoin: st.lineJoin } : {},
209765
209763
  ...st.miterLimit !== 10 ? { miterLimit: st.miterLimit } : {},
@@ -209947,14 +209945,14 @@ function evaluateContentStreamToDisplayList(params) {
209947
209945
  if (st.textRenderMode >= 4 && st.textRenderMode <= 7) pendingTextClip.push(...transformedGlyphSegs);
209948
209946
  const isFillGlyph = st.textRenderMode === 0 || st.textRenderMode === 2 || st.textRenderMode === 4 || st.textRenderMode === 6;
209949
209947
  const isStrokeGlyph = st.textRenderMode === 1 || st.textRenderMode === 2 || st.textRenderMode === 5 || st.textRenderMode === 6;
209950
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
209951
209948
  const paint = {
209952
209949
  segments: transformedGlyphSegs,
209953
209950
  fillColor: isFillGlyph ? st.fillColor : void 0,
209954
209951
  fillAlpha: isFillGlyph ? st.fillAlpha : void 0,
209955
209952
  strokeColor: isStrokeGlyph ? st.strokeColor : void 0,
209956
209953
  strokeAlpha: isStrokeGlyph ? st.strokeAlpha : void 0,
209957
- strokeWidth: isStrokeGlyph ? st.strokeWidth * ctmScale : 0,
209954
+ strokeWidth: isStrokeGlyph ? st.strokeWidth : 0,
209955
+ ...isStrokeGlyph ? { strokeMatrix: [...st.ctm] } : {},
209958
209956
  fillRule: "nonzero",
209959
209957
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
209960
209958
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
@@ -213204,11 +213202,10 @@ function blendPixel(rgba, width2, height, px, py, color5, alpha, blendMode, clip
213204
213202
  rgba[idx + 2] = Math.round((effB * a3 + cbB * dstA * (1 - a3)) / outA * 255);
213205
213203
  rgba[idx + 3] = Math.round(outA * 255);
213206
213204
  }
213207
- function segmentsToScreenPaths(segments, pageHeight, scale2) {
213205
+ function segmentsToScreenPaths(segments, pageHeight, scale2, toScreen = (x, y) => [x * scale2, (pageHeight - y) * scale2]) {
213208
213206
  const paths = [];
213209
213207
  let points = [];
213210
213208
  let current = [0, 0];
213211
- const toScreen = (x, y) => [x * scale2, (pageHeight - y) * scale2];
213212
213209
  for (const segment of segments) {
213213
213210
  if (segment.kind === "move") {
213214
213211
  if (points.length) paths.push({ points, closed: false });
@@ -213247,6 +213244,63 @@ function segmentsToScreenPaths(segments, pageHeight, scale2) {
213247
213244
  if (points.length) paths.push({ points, closed: false });
213248
213245
  return paths;
213249
213246
  }
213247
+ function inverseStrokeMatrix(matrix2) {
213248
+ const [a3, b3, c4, d2, e, f2] = matrix2;
213249
+ const det = a3 * d2 - b3 * c4;
213250
+ if (!Number.isFinite(det) || det === 0) return void 0;
213251
+ return [d2 / det, -b3 / det, -c4 / det, a3 / det, (c4 * f2 - d2 * e) / det, (b3 * e - a3 * f2) / det];
213252
+ }
213253
+ function prepareStroke(path2, scale2) {
213254
+ const matrix2 = path2.strokeMatrix ? [...path2.strokeMatrix] : [1, 0, 0, 1, 0, 0];
213255
+ const [a3, b3, c4, d2] = matrix2;
213256
+ const area = Math.abs(a3 * d2 - b3 * c4) * scale2 * scale2;
213257
+ if (!(area > 0) || !Number.isFinite(area)) return void 0;
213258
+ const normX = Math.hypot(a3, b3) * scale2, normY = Math.hypot(c4, d2) * scale2;
213259
+ let width2 = path2.strokeWidth || 1;
213260
+ const scaleX = path2.strokeWidth === 0 ? normY / area : Math.max(1, normY / (width2 * area));
213261
+ const scaleY = path2.strokeWidth === 0 ? normX / area : Math.max(1, normX / (width2 * area));
213262
+ let dashArray = path2.dashArray, dashPhase = path2.dashPhase ?? 0;
213263
+ if (scaleX === scaleY) {
213264
+ width2 *= scaleX;
213265
+ } else {
213266
+ matrix2[0] *= scaleX;
213267
+ matrix2[1] *= scaleX;
213268
+ matrix2[2] *= scaleY;
213269
+ matrix2[3] *= scaleY;
213270
+ if (dashArray?.length) {
213271
+ const dashScale = Math.max(scaleX, scaleY);
213272
+ dashArray = dashArray.map((value3) => value3 / dashScale);
213273
+ dashPhase /= dashScale;
213274
+ }
213275
+ }
213276
+ return { matrix: matrix2, width: width2, dashArray, dashPhase };
213277
+ }
213278
+ function strokeEdges(path2, pageHeight, scale2) {
213279
+ const stroke = prepareStroke(path2, scale2);
213280
+ if (!stroke) return [];
213281
+ const inverse2 = inverseStrokeMatrix(stroke.matrix);
213282
+ if (!inverse2) return [];
213283
+ const [a3, b3, c4, d2, e, f2] = stroke.matrix;
213284
+ const strokeScale = scale2 * Math.hypot(a3, b3, c4, d2);
213285
+ const project = (x, y) => [
213286
+ (inverse2[0] * x + inverse2[2] * y + inverse2[4]) * strokeScale,
213287
+ (inverse2[1] * x + inverse2[3] * y + inverse2[5]) * strokeScale
213288
+ ];
213289
+ const toScreen = ([x, y]) => [
213290
+ (a3 * x / strokeScale + c4 * y / strokeScale + e) * scale2,
213291
+ (pageHeight - b3 * x / strokeScale - d2 * y / strokeScale - f2) * scale2
213292
+ ];
213293
+ const contours = strokeOutlines(
213294
+ segmentsToScreenPaths(path2.segments, pageHeight, scale2, project),
213295
+ stroke.width * strokeScale,
213296
+ path2.lineCap ?? 0,
213297
+ path2.lineJoin ?? 0,
213298
+ path2.miterLimit ?? 10,
213299
+ stroke.dashArray?.map((value3) => Math.max(0, value3 * strokeScale)),
213300
+ stroke.dashPhase * strokeScale
213301
+ );
213302
+ return pathsToEdges(contours.map((points) => ({ points: points.map(toScreen), closed: true })));
213303
+ }
213250
213304
  function pathsToEdges(paths, closeSubpaths = false) {
213251
213305
  const edges2 = [];
213252
213306
  for (const { points, closed } of paths) {
@@ -213496,19 +213550,9 @@ function renderDisplayListToBitmap(displayList, options = {}) {
213496
213550
  fillEdgesScanline4x4(rgba, width2, height, edges2, path2.fillColor, path2.fillAlpha ?? 1, path2.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path2.blendMode, clipMask);
213497
213551
  }
213498
213552
  if (path2.strokeColor) {
213499
- const rawSw = path2.strokeWidth * scale2;
213500
- const sw = Math.max(1, rawSw);
213553
+ const rawSw = path2.strokeWidth * scale2 * (path2.strokeMatrix ? Math.hypot(path2.strokeMatrix[0], path2.strokeMatrix[1]) : 1);
213501
213554
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path2.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path2.strokeAlpha ?? 1;
213502
- const contours = strokeOutlines(
213503
- segmentsToScreenPaths(path2.segments, displayList.height, scale2),
213504
- sw,
213505
- path2.lineCap ?? 0,
213506
- path2.lineJoin ?? 0,
213507
- path2.miterLimit ?? 10,
213508
- path2.dashArray?.map((value3) => Math.max(0, value3 * scale2)),
213509
- (path2.dashPhase ?? 0) * scale2
213510
- );
213511
- const edges2 = pathsToEdges(contours.map((points) => ({ points, closed: true })));
213555
+ const edges2 = strokeEdges(path2, displayList.height, scale2);
213512
213556
  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;
213513
213557
  fillEdgesScanline4x4(
213514
213558
  rgba,
@@ -231908,15 +231952,27 @@ function compile(pattern, host) {
231908
231952
  return value3;
231909
231953
  };
231910
231954
  const literal2 = (byte, mode) => node3({ kind: "char", byte, test: (input) => mode.insensitive ? fold2(input) === fold2(byte) : input === byte });
231955
+ const blanks = () => {
231956
+ while (pattern[at] === " " || pattern[at] === " ") {
231957
+ host.tick();
231958
+ at++;
231959
+ }
231960
+ };
231911
231961
  const identifier = (closing) => {
231962
+ if (closing === "}")
231963
+ blanks();
231912
231964
  let name = "";
231913
231965
  while (at < pattern.length && pattern[at] !== closing) {
231966
+ if (closing === "}" && (pattern[at] === " " || pattern[at] === " "))
231967
+ break;
231914
231968
  host.tick();
231915
231969
  const byte = pattern.charCodeAt(at++);
231916
231970
  if (!word2(byte) || !name && byte >= 48 && byte <= 57)
231917
231971
  return unsupported8();
231918
231972
  name += String.fromCharCode(byte);
231919
231973
  }
231974
+ if (closing === "}")
231975
+ blanks();
231920
231976
  if (!name || pattern[at++] !== closing)
231921
231977
  return unsupported8();
231922
231978
  return name;
@@ -231957,16 +232013,29 @@ function compile(pattern, host) {
231957
232013
  if (!inClass && (char >= "1" && char <= "9" || char === "g")) {
231958
232014
  let index3;
231959
232015
  if (char === "g") {
231960
- if (pattern[at++] !== "{")
231961
- return unsupported8();
231962
- if (pattern[at] !== "-" && !(pattern[at] >= "0" && pattern[at] <= "9"))
231963
- return namedReference(identifier("}"), mode);
232016
+ let end2;
232017
+ if (pattern[at] === "{") {
232018
+ end2 = ++at;
232019
+ while (end2 < pattern.length && pattern[end2] !== "}") {
232020
+ host.tick();
232021
+ end2++;
232022
+ }
232023
+ if (end2 === pattern.length)
232024
+ return unsupported8();
232025
+ blanks();
232026
+ if (pattern[at] !== "-" && !(pattern[at] >= "0" && pattern[at] <= "9"))
232027
+ return namedReference(identifier("}"), mode);
232028
+ }
231964
232029
  const relative = pattern[at] === "-";
231965
232030
  if (relative)
231966
232031
  at++;
232032
+ if (!(pattern[at] >= "1" && pattern[at] <= "9"))
232033
+ return unsupported8();
231967
232034
  const number5 = integer7();
231968
- if (!number5 || pattern[at++] !== "}")
232035
+ if (number5 >= 2147483647)
231969
232036
  return unsupported8();
232037
+ if (end2 !== void 0)
232038
+ at = end2 + 1;
231970
232039
  index3 = relative ? captures - number5 + 1 : number5;
231971
232040
  } else {
231972
232041
  index3 = Number(char);
@@ -232169,8 +232238,25 @@ function compile(pattern, host) {
232169
232238
  let behind = false;
232170
232239
  let atomic = false;
232171
232240
  let resetCaptures = false;
232172
- let capture = pattern[at] === "?" ? void 0 : ++captures;
232173
- if (pattern[at] === "?") {
232241
+ let capture = pattern[at] === "?" || pattern[at] === "*" ? void 0 : ++captures;
232242
+ if (pattern[at] === "*") {
232243
+ at++;
232244
+ const name = identifier(":");
232245
+ if (name === "atomic")
232246
+ atomic = true;
232247
+ else if (name === "pla" || name === "positive_lookahead")
232248
+ assertion = false;
232249
+ else if (name === "nla" || name === "negative_lookahead")
232250
+ assertion = true;
232251
+ else if (name === "plb" || name === "positive_lookbehind") {
232252
+ assertion = false;
232253
+ behind = true;
232254
+ } else if (name === "nlb" || name === "negative_lookbehind") {
232255
+ assertion = true;
232256
+ behind = true;
232257
+ } else
232258
+ return unsupported8();
232259
+ } else if (pattern[at] === "?") {
232174
232260
  at++;
232175
232261
  if (pattern[at] === ":")
232176
232262
  at++;
@@ -232183,8 +232269,11 @@ function compile(pattern, host) {
232183
232269
  } else if (pattern[at] === "(") {
232184
232270
  at++;
232185
232271
  let condition;
232186
- if (pattern[at] === "?" && (pattern[at + 1] === "=" || pattern[at + 1] === "!" || pattern[at + 1] === "<" && (pattern[at + 2] === "=" || pattern[at + 2] === "!"))) {
232187
- condition = { kind: "assertion", node: group({ ...mode }) };
232272
+ if (pattern[at] === "*" || pattern[at] === "?" && (pattern[at + 1] === "=" || pattern[at + 1] === "!" || pattern[at + 1] === "<" && (pattern[at + 2] === "=" || pattern[at + 2] === "!"))) {
232273
+ const assertionNode = group({ ...mode });
232274
+ if (assertionNode.kind !== "assert" && assertionNode.kind !== "behind")
232275
+ return unsupported8();
232276
+ condition = { kind: "assertion", node: assertionNode };
232188
232277
  } else {
232189
232278
  const indices = [];
232190
232279
  if (pattern[at] === "<" || pattern[at] === "'") {
@@ -11742,11 +11742,10 @@ function evaluateContentStreamToDisplayList(params) {
11742
11742
  } else if (operator === "d") {
11743
11743
  const arrNode = ops[0]?.kind === "array" ? ops[0] : void 0;
11744
11744
  if (arrNode) {
11745
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
11746
- const nums = arrNode.items.map((it) => it.kind === "number" ? it.value * ctmScale : 0).filter((v) => v >= 0);
11745
+ const nums = arrNode.items.map((it) => it.kind === "number" ? it.value : 0).filter((v) => v >= 0);
11747
11746
  const sum = nums.reduce((a, b) => a + b, 0);
11748
11747
  st.dashArray = sum > 0 ? nums : void 0;
11749
- st.dashPhase = num(1, 0) * ctmScale;
11748
+ st.dashPhase = num(1, 0);
11750
11749
  } else {
11751
11750
  st.dashArray = void 0;
11752
11751
  st.dashPhase = void 0;
@@ -12282,15 +12281,14 @@ function evaluateContentStreamToDisplayList(params) {
12282
12281
  break;
12283
12282
  }
12284
12283
  const fillRule = node.paint.includes("*") ? "evenodd" : "nonzero";
12285
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
12286
- const scaledStrokeWidth = st.strokeWidth === 0 ? 0 : st.strokeWidth * ctmScale;
12287
12284
  emit({ kind: "path", value: {
12288
12285
  segments: transformedSegments,
12289
12286
  fillColor: isFill && !evaluatedFillPattern ? st.fillColor : void 0,
12290
12287
  fillAlpha: isFill && !evaluatedFillPattern ? st.fillAlpha : void 0,
12291
12288
  strokeColor: isStroke ? st.strokeColor : void 0,
12292
12289
  strokeAlpha: isStroke ? st.strokeAlpha : void 0,
12293
- strokeWidth: scaledStrokeWidth,
12290
+ strokeWidth: st.strokeWidth,
12291
+ ...isStroke ? { strokeMatrix: [...st.ctm] } : {},
12294
12292
  ...st.lineCap !== 0 ? { lineCap: st.lineCap } : {},
12295
12293
  ...st.lineJoin !== 0 ? { lineJoin: st.lineJoin } : {},
12296
12294
  ...st.miterLimit !== 10 ? { miterLimit: st.miterLimit } : {},
@@ -12478,14 +12476,14 @@ function evaluateContentStreamToDisplayList(params) {
12478
12476
  if (st.textRenderMode >= 4 && st.textRenderMode <= 7) pendingTextClip.push(...transformedGlyphSegs);
12479
12477
  const isFillGlyph = st.textRenderMode === 0 || st.textRenderMode === 2 || st.textRenderMode === 4 || st.textRenderMode === 6;
12480
12478
  const isStrokeGlyph = st.textRenderMode === 1 || st.textRenderMode === 2 || st.textRenderMode === 5 || st.textRenderMode === 6;
12481
- const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
12482
12479
  const paint = {
12483
12480
  segments: transformedGlyphSegs,
12484
12481
  fillColor: isFillGlyph ? st.fillColor : void 0,
12485
12482
  fillAlpha: isFillGlyph ? st.fillAlpha : void 0,
12486
12483
  strokeColor: isStrokeGlyph ? st.strokeColor : void 0,
12487
12484
  strokeAlpha: isStrokeGlyph ? st.strokeAlpha : void 0,
12488
- strokeWidth: isStrokeGlyph ? st.strokeWidth * ctmScale : 0,
12485
+ strokeWidth: isStrokeGlyph ? st.strokeWidth : 0,
12486
+ ...isStrokeGlyph ? { strokeMatrix: [...st.ctm] } : {},
12489
12487
  fillRule: "nonzero",
12490
12488
  ...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
12491
12489
  ...st.clipRect ? { clipRect: [...st.clipRect] } : {}
@@ -14637,11 +14635,10 @@ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMa
14637
14635
  rgba[idx + 2] = Math.round((effB * a + cbB * dstA * (1 - a)) / outA * 255);
14638
14636
  rgba[idx + 3] = Math.round(outA * 255);
14639
14637
  }
14640
- function segmentsToScreenPaths(segments, pageHeight, scale) {
14638
+ function segmentsToScreenPaths(segments, pageHeight, scale, toScreen = (x, y) => [x * scale, (pageHeight - y) * scale]) {
14641
14639
  const paths = [];
14642
14640
  let points = [];
14643
14641
  let current = [0, 0];
14644
- const toScreen = (x, y) => [x * scale, (pageHeight - y) * scale];
14645
14642
  for (const segment of segments) {
14646
14643
  if (segment.kind === "move") {
14647
14644
  if (points.length) paths.push({ points, closed: false });
@@ -14680,6 +14677,63 @@ function segmentsToScreenPaths(segments, pageHeight, scale) {
14680
14677
  if (points.length) paths.push({ points, closed: false });
14681
14678
  return paths;
14682
14679
  }
14680
+ function inverseStrokeMatrix(matrix) {
14681
+ const [a, b, c, d, e, f] = matrix;
14682
+ const det = a * d - b * c;
14683
+ if (!Number.isFinite(det) || det === 0) return void 0;
14684
+ return [d / det, -b / det, -c / det, a / det, (c * f - d * e) / det, (b * e - a * f) / det];
14685
+ }
14686
+ function prepareStroke(path, scale) {
14687
+ const matrix = path.strokeMatrix ? [...path.strokeMatrix] : [1, 0, 0, 1, 0, 0];
14688
+ const [a, b, c, d] = matrix;
14689
+ const area = Math.abs(a * d - b * c) * scale * scale;
14690
+ if (!(area > 0) || !Number.isFinite(area)) return void 0;
14691
+ const normX = Math.hypot(a, b) * scale, normY = Math.hypot(c, d) * scale;
14692
+ let width = path.strokeWidth || 1;
14693
+ const scaleX = path.strokeWidth === 0 ? normY / area : Math.max(1, normY / (width * area));
14694
+ const scaleY = path.strokeWidth === 0 ? normX / area : Math.max(1, normX / (width * area));
14695
+ let dashArray = path.dashArray, dashPhase = path.dashPhase ?? 0;
14696
+ if (scaleX === scaleY) {
14697
+ width *= scaleX;
14698
+ } else {
14699
+ matrix[0] *= scaleX;
14700
+ matrix[1] *= scaleX;
14701
+ matrix[2] *= scaleY;
14702
+ matrix[3] *= scaleY;
14703
+ if (dashArray?.length) {
14704
+ const dashScale = Math.max(scaleX, scaleY);
14705
+ dashArray = dashArray.map((value) => value / dashScale);
14706
+ dashPhase /= dashScale;
14707
+ }
14708
+ }
14709
+ return { matrix, width, dashArray, dashPhase };
14710
+ }
14711
+ function strokeEdges(path, pageHeight, scale) {
14712
+ const stroke = prepareStroke(path, scale);
14713
+ if (!stroke) return [];
14714
+ const inverse = inverseStrokeMatrix(stroke.matrix);
14715
+ if (!inverse) return [];
14716
+ const [a, b, c, d, e, f] = stroke.matrix;
14717
+ const strokeScale = scale * Math.hypot(a, b, c, d);
14718
+ const project = (x, y) => [
14719
+ (inverse[0] * x + inverse[2] * y + inverse[4]) * strokeScale,
14720
+ (inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
14721
+ ];
14722
+ const toScreen = ([x, y]) => [
14723
+ (a * x / strokeScale + c * y / strokeScale + e) * scale,
14724
+ (pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
14725
+ ];
14726
+ const contours = strokeOutlines(
14727
+ segmentsToScreenPaths(path.segments, pageHeight, scale, project),
14728
+ stroke.width * strokeScale,
14729
+ path.lineCap ?? 0,
14730
+ path.lineJoin ?? 0,
14731
+ path.miterLimit ?? 10,
14732
+ stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
14733
+ stroke.dashPhase * strokeScale
14734
+ );
14735
+ return pathsToEdges(contours.map((points) => ({ points: points.map(toScreen), closed: true })));
14736
+ }
14683
14737
  function pathsToEdges(paths, closeSubpaths = false) {
14684
14738
  const edges = [];
14685
14739
  for (const { points, closed } of paths) {
@@ -14929,19 +14983,9 @@ function renderDisplayListToBitmap(displayList, options = {}) {
14929
14983
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
14930
14984
  }
14931
14985
  if (path.strokeColor) {
14932
- const rawSw = path.strokeWidth * scale;
14933
- const sw = Math.max(1, rawSw);
14986
+ const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
14934
14987
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
14935
- const contours = strokeOutlines(
14936
- segmentsToScreenPaths(path.segments, displayList.height, scale),
14937
- sw,
14938
- path.lineCap ?? 0,
14939
- path.lineJoin ?? 0,
14940
- path.miterLimit ?? 10,
14941
- path.dashArray?.map((value) => Math.max(0, value * scale)),
14942
- (path.dashPhase ?? 0) * scale
14943
- );
14944
- const edges = pathsToEdges(contours.map((points) => ({ points, closed: true })));
14988
+ const edges = strokeEdges(path, displayList.height, scale);
14945
14989
  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;
14946
14990
  fillEdgesScanline4x4(
14947
14991
  rgba,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@poe-platform/safe-bash",
3
- "version": "0.1.764",
3
+ "version": "0.1.765",
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.764",
844
+ "@poe-platform/safe-fs": "0.1.765",
845
845
  "pdf-lib": "1.17.1",
846
846
  "@noble/hashes": "2.4.0",
847
847
  "pako": "3.0.1",
@@ -229,6 +229,16 @@ headers and local contour assembly; it is not the full upstream generator.
229
229
 
230
230
  Source: https://github.com/chromium/pdfium/blob/a84323421e94f484faca52dd9d027934eba42ab8/third_party/agg23/agg_math_stroke.h
231
231
 
232
+ Stroke preparation in `src/render/raster.ts` adapts PDF.js
233
+ `CanvasGraphics.getScaleForStroking` and `rescaleAndStroke` from
234
+ `src/display/canvas.js` at revision `91041fb94d6744bc2a5bccd9aad28d617faa8195`
235
+ (Mozilla Foundation, Apache-2.0). It preserves paint-time user coordinates for
236
+ width/dashes, applies the per-axis minimum device thickness, and uses PDF.js's
237
+ larger-factor dash correction when the minimum rescales the axes differently.
238
+ The TypeScript adaptation uses arrays rather than Canvas/DOMMatrix objects,
239
+ shares preparation between bitmap and SVG, and suppresses singular strokes.
240
+ Tests compare independent PDF.js pixels, including identical embedded CFF text.
241
+
232
242
 
233
243
  # SVG labels
234
244