@poe-platform/safe-bash 0.1.765 → 0.1.767

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-SVL6HYQL.js";
32
- import "../safe-bash/command-chunks/chunk-KO4PXCNL.js";
31
+ } from "../safe-bash/command-chunks/chunk-A5S6M37L.js";
32
+ import "../safe-bash/command-chunks/chunk-2JQONXIY.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-DT4MFWV4.js";
5
+ } from "../safe-bash/command-chunks/chunk-G55GHZV2.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-SVL6HYQL.js";
9
- import "../safe-bash/command-chunks/chunk-KO4PXCNL.js";
8
+ import "../safe-bash/command-chunks/chunk-A5S6M37L.js";
9
+ import "../safe-bash/command-chunks/chunk-2JQONXIY.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-DT4MFWV4.js";
24
+ } from "../safe-bash/command-chunks/chunk-G55GHZV2.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-SVL6HYQL.js";
28
- import "../safe-bash/command-chunks/chunk-KO4PXCNL.js";
27
+ import "../safe-bash/command-chunks/chunk-A5S6M37L.js";
28
+ import "../safe-bash/command-chunks/chunk-2JQONXIY.js";
29
29
  import {
30
30
  createLuaFilterCapability
31
31
  } from "../safe-bash/command-chunks/chunk-Y2KHC6TZ.js";
@@ -36184,10 +36184,11 @@ function evaluateContentStreamToDisplayList(params) {
36184
36184
  const patArr = params.cosDoc.resolveArray(dArr.items[0]);
36185
36185
  const phaseNode = params.cosDoc.resolve(dArr.items[1]);
36186
36186
  if (patArr) {
36187
- st.dashArray = patArr.items.map((it) => {
36187
+ const dashArray = patArr.items.map((it) => {
36188
36188
  const r = params.cosDoc.resolve(it);
36189
36189
  return r?.kind === "number" ? r.value : 0;
36190
- }).filter((n) => n > 0);
36190
+ }).filter((n) => n >= 0);
36191
+ st.dashArray = dashArray.some((value) => value > 0) ? dashArray : void 0;
36191
36192
  st.dashPhase = phaseNode?.kind === "number" ? phaseNode.value : 0;
36192
36193
  }
36193
36194
  }
@@ -36242,8 +36243,9 @@ function evaluateContentStreamToDisplayList(params) {
36242
36243
  const st = curState();
36243
36244
  const group = params.cosDoc.resolveDict(dictGet(form.dict, "Group"));
36244
36245
  const groupType = group ? params.cosDoc.resolve(dictGet(group, "S")) : void 0;
36245
- const isolated = group ? params.cosDoc.resolve(dictGet(group, "I")) : void 0;
36246
- const isolate = !maskGroup && groupType?.kind === "name" && groupType.decoded === "Transparency" && isolated?.kind === "boolean" && isolated.value;
36246
+ const isolation = group ? params.cosDoc.resolve(dictGet(group, "I")) : void 0;
36247
+ const isolated = isolation?.kind === "boolean" && isolation.value;
36248
+ const compositeGroup = !maskGroup && groupType?.kind === "name" && groupType.decoded === "Transparency" && (isolated || st.fillAlpha !== 1 || !!st.softMask || st.blendMode !== "Normal" && st.blendMode !== "Compatible");
36247
36249
  const formStreamBytes = params.cosDoc.decodeStream(form);
36248
36250
  const formNodes = parseContentStream(formStreamBytes);
36249
36251
  const formResDict = params.cosDoc.resolveDict(dictGet(form.dict, "Resources")) ?? activeResources;
@@ -36261,8 +36263,8 @@ function evaluateContentStreamToDisplayList(params) {
36261
36263
  const formMat = [mn(0, 1), mn(1, 0), mn(2, 0), mn(3, 1), mn(4, 0), mn(5, 0)];
36262
36264
  nextCtm = multiplyMatrices(formMat, nextCtm);
36263
36265
  }
36264
- let nextClip = !isolate && st.clipRect ? [...st.clipRect] : void 0;
36265
- let nextClipPaths = isolate ? void 0 : st.clipPaths;
36266
+ let nextClip = !compositeGroup && st.clipRect ? [...st.clipRect] : void 0;
36267
+ let nextClipPaths = compositeGroup ? void 0 : st.clipPaths;
36266
36268
  const bboxArr = params.cosDoc.resolveArray(dictGet(form.dict, "BBox"));
36267
36269
  if (bboxArr && bboxArr.items.length >= 4) {
36268
36270
  const bn = (idx, fb = 0) => {
@@ -36296,7 +36298,7 @@ function evaluateContentStreamToDisplayList(params) {
36296
36298
  const parentOperations = capturedOperations;
36297
36299
  const children = [];
36298
36300
  const nextState = { ...st, ctm: nextCtm };
36299
- if (isolate) {
36301
+ if (compositeGroup) {
36300
36302
  capturedOperations = children;
36301
36303
  nextState.fillAlpha = nextState.strokeAlpha = 1;
36302
36304
  nextState.blendMode = "Normal";
@@ -36314,7 +36316,7 @@ function evaluateContentStreamToDisplayList(params) {
36314
36316
  stateStack.pop();
36315
36317
  capturedOperations = parentOperations;
36316
36318
  }
36317
- if (isolate) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
36319
+ if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
36318
36320
  };
36319
36321
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
36320
36322
  for (const node of nodes) {
@@ -39191,7 +39193,7 @@ function dashSubpath(path, pattern, phase) {
39191
39193
  while (remaining <= 0) {
39192
39194
  if (++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39193
39195
  if (index % 2 === 0) {
39194
- if (pattern[index] === 0) result.push({ points: [point, point], closed: false });
39196
+ if (pattern[index] === 0) result.push({ points: [point, point], closed: false, zeroLengthDash: true });
39195
39197
  flush();
39196
39198
  }
39197
39199
  index = (index + 1) % pattern.length;
@@ -39206,7 +39208,7 @@ function dashSubpath(path, pattern, phase) {
39206
39208
  throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39207
39209
  }
39208
39210
  let distance = 0;
39209
- while (distance < length) {
39211
+ while (length - distance > 8 * Number.EPSILON * Math.max(1, length)) {
39210
39212
  const point = [start[0] + dx * distance / length, start[1] + dy * distance / length];
39211
39213
  advance(point);
39212
39214
  const step = Math.min(remaining, length - distance);
@@ -39321,7 +39323,15 @@ function strokeOutlines(paths, width, cap, join, miterLimit, dashArray = [], das
39321
39323
  let closed = subpath.closed;
39322
39324
  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();
39323
39325
  if (points.length < 3) closed = false;
39324
- if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
39326
+ if (points.length === 1 && cap === 2 && subpath.zeroLengthDash) {
39327
+ contour = [];
39328
+ const [x, y] = points[0];
39329
+ add(x - half, y - half);
39330
+ add(x + half, y - half);
39331
+ add(x + half, y + half);
39332
+ add(x - half, y + half);
39333
+ contours.push(contour);
39334
+ } else if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
39325
39335
  contour = [];
39326
39336
  const [x, y] = points[0];
39327
39337
  addCap([x, y], [x + 1, y]);
@@ -40267,7 +40277,7 @@ function prepareStroke(path, scale) {
40267
40277
  }
40268
40278
  return { matrix, width, dashArray, dashPhase };
40269
40279
  }
40270
- function strokeEdges(path, pageHeight, scale) {
40280
+ function strokeContours(path, pageHeight, scale) {
40271
40281
  const stroke = prepareStroke(path, scale);
40272
40282
  if (!stroke) return [];
40273
40283
  const inverse = inverseStrokeMatrix(stroke.matrix);
@@ -40291,7 +40301,7 @@ function strokeEdges(path, pageHeight, scale) {
40291
40301
  stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
40292
40302
  stroke.dashPhase * strokeScale
40293
40303
  );
40294
- return pathsToEdges(contours.map((points) => ({ points: points.map(toScreen), closed: true })));
40304
+ return contours.map((points) => points.map(toScreen));
40295
40305
  }
40296
40306
  function pathsToEdges(paths, closeSubpaths = false) {
40297
40307
  const edges = [];
@@ -40438,6 +40448,9 @@ function renderSoftMask(mask, displayList, scale) {
40438
40448
  }
40439
40449
  return bitmap;
40440
40450
  }
40451
+ function hasBlendModes(operations) {
40452
+ return operations.some((operation) => !!operation.value.blendMode && operation.value.blendMode !== "Normal" && operation.value.blendMode !== "Compatible" || operation.kind === "group" && hasBlendModes(operation.value.operations));
40453
+ }
40441
40454
  function renderDisplayListToBitmap(displayList, options = {}) {
40442
40455
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
40443
40456
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
@@ -40446,11 +40459,13 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40446
40459
  const width = Math.max(1, Math.round(displayList.width * scale));
40447
40460
  const height = Math.max(1, Math.round(displayList.height * scale));
40448
40461
  const rgba = new Uint8Array(width * height * 4);
40462
+ const deferBackground = !options.transparent && hasBlendModes(paintOperations(displayList));
40463
+ const transparent = options.transparent || deferBackground;
40449
40464
  const bg = options.background ?? { r: 1, g: 1, b: 1 };
40450
- const bgR = options.transparent ? 0 : Math.round(bg.r * 255);
40451
- const bgG = options.transparent ? 0 : Math.round(bg.g * 255);
40452
- const bgB = options.transparent ? 0 : Math.round(bg.b * 255);
40453
- const bgA = options.transparent ? 0 : 255;
40465
+ const bgR = transparent ? 0 : Math.round(bg.r * 255);
40466
+ const bgG = transparent ? 0 : Math.round(bg.g * 255);
40467
+ const bgB = transparent ? 0 : Math.round(bg.b * 255);
40468
+ const bgA = transparent ? 0 : 255;
40454
40469
  for (let i = 0; i < width * height; i++) {
40455
40470
  rgba[i * 4] = bgR;
40456
40471
  rgba[i * 4 + 1] = bgG;
@@ -40544,7 +40559,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40544
40559
  if (path.strokeColor) {
40545
40560
  const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
40546
40561
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
40547
- const edges = strokeEdges(path, displayList.height, scale);
40562
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
40548
40563
  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;
40549
40564
  fillEdgesScanline4x4(
40550
40565
  rgba,
@@ -40627,6 +40642,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40627
40642
  }
40628
40643
  }
40629
40644
  }
40645
+ if (deferBackground) {
40646
+ for (let i = 0; i < rgba.length; i += 4) {
40647
+ const alpha = rgba[i + 3] / 255;
40648
+ rgba[i] = Math.round(rgba[i] * alpha + bg.r * 255 * (1 - alpha));
40649
+ rgba[i + 1] = Math.round(rgba[i + 1] * alpha + bg.g * 255 * (1 - alpha));
40650
+ rgba[i + 2] = Math.round(rgba[i + 2] * alpha + bg.b * 255 * (1 - alpha));
40651
+ rgba[i + 3] = 255;
40652
+ }
40653
+ }
40630
40654
  let result = { width, height, data: rgba };
40631
40655
  if (Math.abs(scaleX - scaleY) > 1e-6) {
40632
40656
  const targetW = Math.max(1, Math.round(displayList.width * scaleX));
@@ -36378,10 +36378,11 @@ function evaluateContentStreamToDisplayList(params) {
36378
36378
  const patArr = params.cosDoc.resolveArray(dArr.items[0]);
36379
36379
  const phaseNode = params.cosDoc.resolve(dArr.items[1]);
36380
36380
  if (patArr) {
36381
- st.dashArray = patArr.items.map((it) => {
36381
+ const dashArray = patArr.items.map((it) => {
36382
36382
  const r = params.cosDoc.resolve(it);
36383
36383
  return r?.kind === "number" ? r.value : 0;
36384
- }).filter((n) => n > 0);
36384
+ }).filter((n) => n >= 0);
36385
+ st.dashArray = dashArray.some((value) => value > 0) ? dashArray : void 0;
36385
36386
  st.dashPhase = phaseNode?.kind === "number" ? phaseNode.value : 0;
36386
36387
  }
36387
36388
  }
@@ -36436,8 +36437,9 @@ function evaluateContentStreamToDisplayList(params) {
36436
36437
  const st = curState();
36437
36438
  const group = params.cosDoc.resolveDict(dictGet(form.dict, "Group"));
36438
36439
  const groupType = group ? params.cosDoc.resolve(dictGet(group, "S")) : void 0;
36439
- const isolated = group ? params.cosDoc.resolve(dictGet(group, "I")) : void 0;
36440
- const isolate = !maskGroup && groupType?.kind === "name" && groupType.decoded === "Transparency" && isolated?.kind === "boolean" && isolated.value;
36440
+ const isolation = group ? params.cosDoc.resolve(dictGet(group, "I")) : void 0;
36441
+ const isolated = isolation?.kind === "boolean" && isolation.value;
36442
+ const compositeGroup = !maskGroup && groupType?.kind === "name" && groupType.decoded === "Transparency" && (isolated || st.fillAlpha !== 1 || !!st.softMask || st.blendMode !== "Normal" && st.blendMode !== "Compatible");
36441
36443
  const formStreamBytes = params.cosDoc.decodeStream(form);
36442
36444
  const formNodes = parseContentStream(formStreamBytes);
36443
36445
  const formResDict = params.cosDoc.resolveDict(dictGet(form.dict, "Resources")) ?? activeResources;
@@ -36455,8 +36457,8 @@ function evaluateContentStreamToDisplayList(params) {
36455
36457
  const formMat = [mn(0, 1), mn(1, 0), mn(2, 0), mn(3, 1), mn(4, 0), mn(5, 0)];
36456
36458
  nextCtm = multiplyMatrices(formMat, nextCtm);
36457
36459
  }
36458
- let nextClip = !isolate && st.clipRect ? [...st.clipRect] : void 0;
36459
- let nextClipPaths = isolate ? void 0 : st.clipPaths;
36460
+ let nextClip = !compositeGroup && st.clipRect ? [...st.clipRect] : void 0;
36461
+ let nextClipPaths = compositeGroup ? void 0 : st.clipPaths;
36460
36462
  const bboxArr = params.cosDoc.resolveArray(dictGet(form.dict, "BBox"));
36461
36463
  if (bboxArr && bboxArr.items.length >= 4) {
36462
36464
  const bn = (idx, fb = 0) => {
@@ -36490,7 +36492,7 @@ function evaluateContentStreamToDisplayList(params) {
36490
36492
  const parentOperations = capturedOperations;
36491
36493
  const children = [];
36492
36494
  const nextState = { ...st, ctm: nextCtm };
36493
- if (isolate) {
36495
+ if (compositeGroup) {
36494
36496
  capturedOperations = children;
36495
36497
  nextState.fillAlpha = nextState.strokeAlpha = 1;
36496
36498
  nextState.blendMode = "Normal";
@@ -36508,7 +36510,7 @@ function evaluateContentStreamToDisplayList(params) {
36508
36510
  stateStack.pop();
36509
36511
  capturedOperations = parentOperations;
36510
36512
  }
36511
- if (isolate) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
36513
+ if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
36512
36514
  };
36513
36515
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
36514
36516
  for (const node of nodes) {
@@ -39385,7 +39387,7 @@ function dashSubpath(path, pattern, phase) {
39385
39387
  while (remaining <= 0) {
39386
39388
  if (++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39387
39389
  if (index % 2 === 0) {
39388
- if (pattern[index] === 0) result.push({ points: [point, point], closed: false });
39390
+ if (pattern[index] === 0) result.push({ points: [point, point], closed: false, zeroLengthDash: true });
39389
39391
  flush();
39390
39392
  }
39391
39393
  index = (index + 1) % pattern.length;
@@ -39400,7 +39402,7 @@ function dashSubpath(path, pattern, phase) {
39400
39402
  throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39401
39403
  }
39402
39404
  let distance = 0;
39403
- while (distance < length) {
39405
+ while (length - distance > 8 * Number.EPSILON * Math.max(1, length)) {
39404
39406
  const point = [start[0] + dx * distance / length, start[1] + dy * distance / length];
39405
39407
  advance(point);
39406
39408
  const step = Math.min(remaining, length - distance);
@@ -39515,7 +39517,15 @@ function strokeOutlines(paths, width, cap, join, miterLimit, dashArray = [], das
39515
39517
  let closed = subpath.closed;
39516
39518
  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();
39517
39519
  if (points.length < 3) closed = false;
39518
- if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
39520
+ if (points.length === 1 && cap === 2 && subpath.zeroLengthDash) {
39521
+ contour = [];
39522
+ const [x, y] = points[0];
39523
+ add(x - half, y - half);
39524
+ add(x + half, y - half);
39525
+ add(x + half, y + half);
39526
+ add(x - half, y + half);
39527
+ contours.push(contour);
39528
+ } else if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
39519
39529
  contour = [];
39520
39530
  const [x, y] = points[0];
39521
39531
  addCap([x, y], [x + 1, y]);
@@ -40703,7 +40713,7 @@ function prepareStroke(path, scale) {
40703
40713
  }
40704
40714
  return { matrix, width, dashArray, dashPhase };
40705
40715
  }
40706
- function strokeEdges(path, pageHeight, scale) {
40716
+ function strokeContours(path, pageHeight, scale) {
40707
40717
  const stroke = prepareStroke(path, scale);
40708
40718
  if (!stroke) return [];
40709
40719
  const inverse = inverseStrokeMatrix(stroke.matrix);
@@ -40727,7 +40737,7 @@ function strokeEdges(path, pageHeight, scale) {
40727
40737
  stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
40728
40738
  stroke.dashPhase * strokeScale
40729
40739
  );
40730
- return pathsToEdges(contours.map((points) => ({ points: points.map(toScreen), closed: true })));
40740
+ return contours.map((points) => points.map(toScreen));
40731
40741
  }
40732
40742
  function pathsToEdges(paths, closeSubpaths = false) {
40733
40743
  const edges = [];
@@ -40874,6 +40884,9 @@ function renderSoftMask(mask, displayList, scale) {
40874
40884
  }
40875
40885
  return bitmap;
40876
40886
  }
40887
+ function hasBlendModes(operations) {
40888
+ return operations.some((operation) => !!operation.value.blendMode && operation.value.blendMode !== "Normal" && operation.value.blendMode !== "Compatible" || operation.kind === "group" && hasBlendModes(operation.value.operations));
40889
+ }
40877
40890
  function renderDisplayListToBitmap(displayList, options = {}) {
40878
40891
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
40879
40892
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
@@ -40882,11 +40895,13 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40882
40895
  const width = Math.max(1, Math.round(displayList.width * scale));
40883
40896
  const height = Math.max(1, Math.round(displayList.height * scale));
40884
40897
  const rgba = new Uint8Array(width * height * 4);
40898
+ const deferBackground = !options.transparent && hasBlendModes(paintOperations(displayList));
40899
+ const transparent = options.transparent || deferBackground;
40885
40900
  const bg = options.background ?? { r: 1, g: 1, b: 1 };
40886
- const bgR = options.transparent ? 0 : Math.round(bg.r * 255);
40887
- const bgG = options.transparent ? 0 : Math.round(bg.g * 255);
40888
- const bgB = options.transparent ? 0 : Math.round(bg.b * 255);
40889
- const bgA = options.transparent ? 0 : 255;
40901
+ const bgR = transparent ? 0 : Math.round(bg.r * 255);
40902
+ const bgG = transparent ? 0 : Math.round(bg.g * 255);
40903
+ const bgB = transparent ? 0 : Math.round(bg.b * 255);
40904
+ const bgA = transparent ? 0 : 255;
40890
40905
  for (let i = 0; i < width * height; i++) {
40891
40906
  rgba[i * 4] = bgR;
40892
40907
  rgba[i * 4 + 1] = bgG;
@@ -40980,7 +40995,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40980
40995
  if (path.strokeColor) {
40981
40996
  const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
40982
40997
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
40983
- const edges = strokeEdges(path, displayList.height, scale);
40998
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
40984
40999
  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;
40985
41000
  fillEdgesScanline4x4(
40986
41001
  rgba,
@@ -41063,6 +41078,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
41063
41078
  }
41064
41079
  }
41065
41080
  }
41081
+ if (deferBackground) {
41082
+ for (let i = 0; i < rgba.length; i += 4) {
41083
+ const alpha = rgba[i + 3] / 255;
41084
+ rgba[i] = Math.round(rgba[i] * alpha + bg.r * 255 * (1 - alpha));
41085
+ rgba[i + 1] = Math.round(rgba[i + 1] * alpha + bg.g * 255 * (1 - alpha));
41086
+ rgba[i + 2] = Math.round(rgba[i + 2] * alpha + bg.b * 255 * (1 - alpha));
41087
+ rgba[i + 3] = 255;
41088
+ }
41089
+ }
41066
41090
  let result = { width, height, data: rgba };
41067
41091
  if (Math.abs(scaleX - scaleY) > 1e-6) {
41068
41092
  const targetW = Math.max(1, Math.round(displayList.width * scaleX));
@@ -41171,6 +41195,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
41171
41195
  if (!options.transparent) {
41172
41196
  parts.push(` <rect x="${vbX}" y="${vbY}" width="${vbW}" height="${vbH}" fill="#ffffff"/>`);
41173
41197
  }
41198
+ parts.push('<g style="isolation:isolate">');
41174
41199
  if (displayList.rotation) {
41175
41200
  const [a, b, c, d, e, f] = viewport.transform;
41176
41201
  parts.push(`<g transform="matrix(${a} ${b} ${-c} ${-d} ${e + c * displayList.height} ${f + d * displayList.height})">`);
@@ -41222,6 +41247,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
41222
41247
  } else if (operation.kind === "path") {
41223
41248
  const p = operation.value;
41224
41249
  const prepared = p.strokeColor ? prepareStroke(p, Math.max(scaleX, scaleY)) : void 0;
41250
+ const outlineStroke = prepared && p.dashArray?.includes(0);
41225
41251
  const matrix = prepared && (prepared.matrix[0] !== 1 || prepared.matrix[1] !== 0 || prepared.matrix[2] !== 0 || prepared.matrix[3] !== 1) ? prepared.matrix : void 0;
41226
41252
  const inverse = matrix ? inverseStrokeMatrix(matrix) : void 0;
41227
41253
  const pathData = svgPathData(p.segments, inverse ? 0 : displayList.height, inverse);
@@ -41236,10 +41262,18 @@ function renderDisplayListToSvg(displayList, options = {}) {
41236
41262
  const lineCapAttr = p.lineCap === 1 ? ` stroke-linecap="round"` : p.lineCap === 2 ? ` stroke-linecap="square"` : "";
41237
41263
  const lineJoinAttr = p.lineJoin === 1 ? ` stroke-linejoin="round"` : p.lineJoin === 2 ? ` stroke-linejoin="bevel"` : "";
41238
41264
  const miterLimitAttr = p.miterLimit !== void 0 && p.miterLimit !== 10 ? ` stroke-miterlimit="${p.miterLimit}"` : "";
41239
- const dashArrayAttr = prepared?.dashArray?.length ? ` stroke-dasharray="${prepared.dashArray.join(" ")}"` : "";
41240
- const dashOffsetAttr = prepared?.dashPhase ? ` stroke-dashoffset="${prepared.dashPhase}"` : "";
41265
+ const dashArrayAttr = !outlineStroke && prepared?.dashArray?.length ? ` stroke-dasharray="${prepared.dashArray.join(" ")}"` : "";
41266
+ const dashOffsetAttr = !outlineStroke && prepared?.dashPhase ? ` stroke-dashoffset="${prepared.dashPhase}"` : "";
41241
41267
  const labelAttr = original.kind === "glyph" ? ` aria-label="${escapeXmlText(original.value.unicode)}"` : "";
41242
- parts.push(` <path${labelAttr}${transformAttr} d="${pathData}" fill="${fill}"${fillRuleAttr}${fillOpacityAttr} stroke="${stroke}"${strokeOpacityAttr}${strokeWidthAttr}${lineCapAttr}${lineJoinAttr}${miterLimitAttr}${dashArrayAttr}${dashOffsetAttr}/>`);
41268
+ if (!outlineStroke || p.fillColor) {
41269
+ parts.push(` <path${labelAttr}${transformAttr} d="${pathData}" fill="${fill}"${fillRuleAttr}${fillOpacityAttr} stroke="${outlineStroke ? "none" : stroke}"${strokeOpacityAttr}${strokeWidthAttr}${lineCapAttr}${lineJoinAttr}${miterLimitAttr}${dashArrayAttr}${dashOffsetAttr}/>`);
41270
+ }
41271
+ if (outlineStroke) {
41272
+ const outlineScale = Math.max(scaleX, scaleY);
41273
+ const contours = strokeContours(p, displayList.height, outlineScale);
41274
+ const outlineData = contours.map((points) => points.map(([x, y], i) => `${i === 0 ? "M" : "L"} ${x / outlineScale} ${y / outlineScale}`).join(" ") + " Z").join(" ");
41275
+ if (outlineData) parts.push(` <path${labelAttr} d="${outlineData}" fill="${stroke}" fill-opacity="${p.strokeAlpha ?? 1}"/>`);
41276
+ }
41243
41277
  }
41244
41278
  } else if (operation.kind === "image") {
41245
41279
  parts.push(` ${svgImage(operation.value, displayList.height)}`);
@@ -41249,6 +41283,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
41249
41283
  };
41250
41284
  appendOperations(paintOperations(displayList));
41251
41285
  if (displayList.rotation) parts.push("</g>");
41286
+ parts.push("</g>");
41252
41287
  parts.push("</svg>\n");
41253
41288
  return parts.join("\n");
41254
41289
  }
@@ -35839,10 +35839,11 @@ function evaluateContentStreamToDisplayList(params) {
35839
35839
  const patArr = params.cosDoc.resolveArray(dArr.items[0]);
35840
35840
  const phaseNode = params.cosDoc.resolve(dArr.items[1]);
35841
35841
  if (patArr) {
35842
- st.dashArray = patArr.items.map((it) => {
35842
+ const dashArray = patArr.items.map((it) => {
35843
35843
  const r = params.cosDoc.resolve(it);
35844
35844
  return r?.kind === "number" ? r.value : 0;
35845
- }).filter((n) => n > 0);
35845
+ }).filter((n) => n >= 0);
35846
+ st.dashArray = dashArray.some((value) => value > 0) ? dashArray : void 0;
35846
35847
  st.dashPhase = phaseNode?.kind === "number" ? phaseNode.value : 0;
35847
35848
  }
35848
35849
  }
@@ -35897,8 +35898,9 @@ function evaluateContentStreamToDisplayList(params) {
35897
35898
  const st = curState();
35898
35899
  const group = params.cosDoc.resolveDict(dictGet(form.dict, "Group"));
35899
35900
  const groupType = group ? params.cosDoc.resolve(dictGet(group, "S")) : void 0;
35900
- const isolated = group ? params.cosDoc.resolve(dictGet(group, "I")) : void 0;
35901
- const isolate = !maskGroup && groupType?.kind === "name" && groupType.decoded === "Transparency" && isolated?.kind === "boolean" && isolated.value;
35901
+ const isolation = group ? params.cosDoc.resolve(dictGet(group, "I")) : void 0;
35902
+ const isolated = isolation?.kind === "boolean" && isolation.value;
35903
+ const compositeGroup = !maskGroup && groupType?.kind === "name" && groupType.decoded === "Transparency" && (isolated || st.fillAlpha !== 1 || !!st.softMask || st.blendMode !== "Normal" && st.blendMode !== "Compatible");
35902
35904
  const formStreamBytes = params.cosDoc.decodeStream(form);
35903
35905
  const formNodes = parseContentStream(formStreamBytes);
35904
35906
  const formResDict = params.cosDoc.resolveDict(dictGet(form.dict, "Resources")) ?? activeResources;
@@ -35916,8 +35918,8 @@ function evaluateContentStreamToDisplayList(params) {
35916
35918
  const formMat = [mn(0, 1), mn(1, 0), mn(2, 0), mn(3, 1), mn(4, 0), mn(5, 0)];
35917
35919
  nextCtm = multiplyMatrices(formMat, nextCtm);
35918
35920
  }
35919
- let nextClip = !isolate && st.clipRect ? [...st.clipRect] : void 0;
35920
- let nextClipPaths = isolate ? void 0 : st.clipPaths;
35921
+ let nextClip = !compositeGroup && st.clipRect ? [...st.clipRect] : void 0;
35922
+ let nextClipPaths = compositeGroup ? void 0 : st.clipPaths;
35921
35923
  const bboxArr = params.cosDoc.resolveArray(dictGet(form.dict, "BBox"));
35922
35924
  if (bboxArr && bboxArr.items.length >= 4) {
35923
35925
  const bn = (idx, fb = 0) => {
@@ -35951,7 +35953,7 @@ function evaluateContentStreamToDisplayList(params) {
35951
35953
  const parentOperations = capturedOperations;
35952
35954
  const children = [];
35953
35955
  const nextState = { ...st, ctm: nextCtm };
35954
- if (isolate) {
35956
+ if (compositeGroup) {
35955
35957
  capturedOperations = children;
35956
35958
  nextState.fillAlpha = nextState.strokeAlpha = 1;
35957
35959
  nextState.blendMode = "Normal";
@@ -35969,7 +35971,7 @@ function evaluateContentStreamToDisplayList(params) {
35969
35971
  stateStack.pop();
35970
35972
  capturedOperations = parentOperations;
35971
35973
  }
35972
- if (isolate) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
35974
+ if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
35973
35975
  };
35974
35976
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
35975
35977
  for (const node of nodes) {
@@ -39410,7 +39412,7 @@ function dashSubpath(path, pattern, phase) {
39410
39412
  while (remaining <= 0) {
39411
39413
  if (++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39412
39414
  if (index % 2 === 0) {
39413
- if (pattern[index] === 0) result.push({ points: [point, point], closed: false });
39415
+ if (pattern[index] === 0) result.push({ points: [point, point], closed: false, zeroLengthDash: true });
39414
39416
  flush();
39415
39417
  }
39416
39418
  index = (index + 1) % pattern.length;
@@ -39425,7 +39427,7 @@ function dashSubpath(path, pattern, phase) {
39425
39427
  throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39426
39428
  }
39427
39429
  let distance = 0;
39428
- while (distance < length) {
39430
+ while (length - distance > 8 * Number.EPSILON * Math.max(1, length)) {
39429
39431
  const point = [start[0] + dx * distance / length, start[1] + dy * distance / length];
39430
39432
  advance(point);
39431
39433
  const step = Math.min(remaining, length - distance);
@@ -39540,7 +39542,15 @@ function strokeOutlines(paths, width, cap, join, miterLimit, dashArray = [], das
39540
39542
  let closed = subpath.closed;
39541
39543
  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();
39542
39544
  if (points.length < 3) closed = false;
39543
- if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
39545
+ if (points.length === 1 && cap === 2 && subpath.zeroLengthDash) {
39546
+ contour = [];
39547
+ const [x, y] = points[0];
39548
+ add(x - half, y - half);
39549
+ add(x + half, y - half);
39550
+ add(x + half, y + half);
39551
+ add(x - half, y + half);
39552
+ contours.push(contour);
39553
+ } else if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
39544
39554
  contour = [];
39545
39555
  const [x, y] = points[0];
39546
39556
  addCap([x, y], [x + 1, y]);
@@ -40332,7 +40342,7 @@ function prepareStroke(path, scale) {
40332
40342
  }
40333
40343
  return { matrix, width, dashArray, dashPhase };
40334
40344
  }
40335
- function strokeEdges(path, pageHeight, scale) {
40345
+ function strokeContours(path, pageHeight, scale) {
40336
40346
  const stroke = prepareStroke(path, scale);
40337
40347
  if (!stroke) return [];
40338
40348
  const inverse = inverseStrokeMatrix(stroke.matrix);
@@ -40356,7 +40366,7 @@ function strokeEdges(path, pageHeight, scale) {
40356
40366
  stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
40357
40367
  stroke.dashPhase * strokeScale
40358
40368
  );
40359
- return pathsToEdges(contours.map((points) => ({ points: points.map(toScreen), closed: true })));
40369
+ return contours.map((points) => points.map(toScreen));
40360
40370
  }
40361
40371
  function pathsToEdges(paths, closeSubpaths = false) {
40362
40372
  const edges = [];
@@ -40503,6 +40513,9 @@ function renderSoftMask(mask, displayList, scale) {
40503
40513
  }
40504
40514
  return bitmap;
40505
40515
  }
40516
+ function hasBlendModes(operations) {
40517
+ return operations.some((operation) => !!operation.value.blendMode && operation.value.blendMode !== "Normal" && operation.value.blendMode !== "Compatible" || operation.kind === "group" && hasBlendModes(operation.value.operations));
40518
+ }
40506
40519
  function renderDisplayListToBitmap(displayList, options = {}) {
40507
40520
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
40508
40521
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
@@ -40511,11 +40524,13 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40511
40524
  const width = Math.max(1, Math.round(displayList.width * scale));
40512
40525
  const height = Math.max(1, Math.round(displayList.height * scale));
40513
40526
  const rgba = new Uint8Array(width * height * 4);
40527
+ const deferBackground = !options.transparent && hasBlendModes(paintOperations(displayList));
40528
+ const transparent = options.transparent || deferBackground;
40514
40529
  const bg = options.background ?? { r: 1, g: 1, b: 1 };
40515
- const bgR = options.transparent ? 0 : Math.round(bg.r * 255);
40516
- const bgG = options.transparent ? 0 : Math.round(bg.g * 255);
40517
- const bgB = options.transparent ? 0 : Math.round(bg.b * 255);
40518
- const bgA = options.transparent ? 0 : 255;
40530
+ const bgR = transparent ? 0 : Math.round(bg.r * 255);
40531
+ const bgG = transparent ? 0 : Math.round(bg.g * 255);
40532
+ const bgB = transparent ? 0 : Math.round(bg.b * 255);
40533
+ const bgA = transparent ? 0 : 255;
40519
40534
  for (let i = 0; i < width * height; i++) {
40520
40535
  rgba[i * 4] = bgR;
40521
40536
  rgba[i * 4 + 1] = bgG;
@@ -40609,7 +40624,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40609
40624
  if (path.strokeColor) {
40610
40625
  const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
40611
40626
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
40612
- const edges = strokeEdges(path, displayList.height, scale);
40627
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
40613
40628
  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;
40614
40629
  fillEdgesScanline4x4(
40615
40630
  rgba,
@@ -40692,6 +40707,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40692
40707
  }
40693
40708
  }
40694
40709
  }
40710
+ if (deferBackground) {
40711
+ for (let i = 0; i < rgba.length; i += 4) {
40712
+ const alpha = rgba[i + 3] / 255;
40713
+ rgba[i] = Math.round(rgba[i] * alpha + bg.r * 255 * (1 - alpha));
40714
+ rgba[i + 1] = Math.round(rgba[i + 1] * alpha + bg.g * 255 * (1 - alpha));
40715
+ rgba[i + 2] = Math.round(rgba[i + 2] * alpha + bg.b * 255 * (1 - alpha));
40716
+ rgba[i + 3] = 255;
40717
+ }
40718
+ }
40695
40719
  let result = { width, height, data: rgba };
40696
40720
  if (Math.abs(scaleX - scaleY) > 1e-6) {
40697
40721
  const targetW = Math.max(1, Math.round(displayList.width * scaleX));