@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.
@@ -36033,10 +36033,11 @@ function evaluateContentStreamToDisplayList(params) {
36033
36033
  const patArr = params.cosDoc.resolveArray(dArr.items[0]);
36034
36034
  const phaseNode = params.cosDoc.resolve(dArr.items[1]);
36035
36035
  if (patArr) {
36036
- st.dashArray = patArr.items.map((it) => {
36036
+ const dashArray = patArr.items.map((it) => {
36037
36037
  const r = params.cosDoc.resolve(it);
36038
36038
  return r?.kind === "number" ? r.value : 0;
36039
- }).filter((n) => n > 0);
36039
+ }).filter((n) => n >= 0);
36040
+ st.dashArray = dashArray.some((value) => value > 0) ? dashArray : void 0;
36040
36041
  st.dashPhase = phaseNode?.kind === "number" ? phaseNode.value : 0;
36041
36042
  }
36042
36043
  }
@@ -36091,8 +36092,9 @@ function evaluateContentStreamToDisplayList(params) {
36091
36092
  const st = curState();
36092
36093
  const group = params.cosDoc.resolveDict(dictGet(form.dict, "Group"));
36093
36094
  const groupType = group ? params.cosDoc.resolve(dictGet(group, "S")) : void 0;
36094
- const isolated = group ? params.cosDoc.resolve(dictGet(group, "I")) : void 0;
36095
- const isolate = !maskGroup && groupType?.kind === "name" && groupType.decoded === "Transparency" && isolated?.kind === "boolean" && isolated.value;
36095
+ const isolation = group ? params.cosDoc.resolve(dictGet(group, "I")) : void 0;
36096
+ const isolated = isolation?.kind === "boolean" && isolation.value;
36097
+ const compositeGroup = !maskGroup && groupType?.kind === "name" && groupType.decoded === "Transparency" && (isolated || st.fillAlpha !== 1 || !!st.softMask || st.blendMode !== "Normal" && st.blendMode !== "Compatible");
36096
36098
  const formStreamBytes = params.cosDoc.decodeStream(form);
36097
36099
  const formNodes = parseContentStream(formStreamBytes);
36098
36100
  const formResDict = params.cosDoc.resolveDict(dictGet(form.dict, "Resources")) ?? activeResources;
@@ -36110,8 +36112,8 @@ function evaluateContentStreamToDisplayList(params) {
36110
36112
  const formMat = [mn(0, 1), mn(1, 0), mn(2, 0), mn(3, 1), mn(4, 0), mn(5, 0)];
36111
36113
  nextCtm = multiplyMatrices(formMat, nextCtm);
36112
36114
  }
36113
- let nextClip = !isolate && st.clipRect ? [...st.clipRect] : void 0;
36114
- let nextClipPaths = isolate ? void 0 : st.clipPaths;
36115
+ let nextClip = !compositeGroup && st.clipRect ? [...st.clipRect] : void 0;
36116
+ let nextClipPaths = compositeGroup ? void 0 : st.clipPaths;
36115
36117
  const bboxArr = params.cosDoc.resolveArray(dictGet(form.dict, "BBox"));
36116
36118
  if (bboxArr && bboxArr.items.length >= 4) {
36117
36119
  const bn = (idx, fb = 0) => {
@@ -36145,7 +36147,7 @@ function evaluateContentStreamToDisplayList(params) {
36145
36147
  const parentOperations = capturedOperations;
36146
36148
  const children = [];
36147
36149
  const nextState = { ...st, ctm: nextCtm };
36148
- if (isolate) {
36150
+ if (compositeGroup) {
36149
36151
  capturedOperations = children;
36150
36152
  nextState.fillAlpha = nextState.strokeAlpha = 1;
36151
36153
  nextState.blendMode = "Normal";
@@ -36163,7 +36165,7 @@ function evaluateContentStreamToDisplayList(params) {
36163
36165
  stateStack.pop();
36164
36166
  capturedOperations = parentOperations;
36165
36167
  }
36166
- if (isolate) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
36168
+ if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
36167
36169
  };
36168
36170
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
36169
36171
  for (const node of nodes) {
@@ -39040,7 +39042,7 @@ function dashSubpath(path, pattern, phase) {
39040
39042
  while (remaining <= 0) {
39041
39043
  if (++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39042
39044
  if (index % 2 === 0) {
39043
- if (pattern[index] === 0) result.push({ points: [point, point], closed: false });
39045
+ if (pattern[index] === 0) result.push({ points: [point, point], closed: false, zeroLengthDash: true });
39044
39046
  flush();
39045
39047
  }
39046
39048
  index = (index + 1) % pattern.length;
@@ -39055,7 +39057,7 @@ function dashSubpath(path, pattern, phase) {
39055
39057
  throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
39056
39058
  }
39057
39059
  let distance = 0;
39058
- while (distance < length) {
39060
+ while (length - distance > 8 * Number.EPSILON * Math.max(1, length)) {
39059
39061
  const point = [start[0] + dx * distance / length, start[1] + dy * distance / length];
39060
39062
  advance(point);
39061
39063
  const step = Math.min(remaining, length - distance);
@@ -39170,7 +39172,15 @@ function strokeOutlines(paths, width, cap, join, miterLimit, dashArray = [], das
39170
39172
  let closed = subpath.closed;
39171
39173
  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();
39172
39174
  if (points.length < 3) closed = false;
39173
- if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
39175
+ if (points.length === 1 && cap === 2 && subpath.zeroLengthDash) {
39176
+ contour = [];
39177
+ const [x, y] = points[0];
39178
+ add(x - half, y - half);
39179
+ add(x + half, y - half);
39180
+ add(x + half, y + half);
39181
+ add(x - half, y + half);
39182
+ contours.push(contour);
39183
+ } else if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
39174
39184
  contour = [];
39175
39185
  const [x, y] = points[0];
39176
39186
  addCap([x, y], [x + 1, y]);
@@ -40358,7 +40368,7 @@ function prepareStroke(path, scale) {
40358
40368
  }
40359
40369
  return { matrix, width, dashArray, dashPhase };
40360
40370
  }
40361
- function strokeEdges(path, pageHeight, scale) {
40371
+ function strokeContours(path, pageHeight, scale) {
40362
40372
  const stroke = prepareStroke(path, scale);
40363
40373
  if (!stroke) return [];
40364
40374
  const inverse = inverseStrokeMatrix(stroke.matrix);
@@ -40382,7 +40392,7 @@ function strokeEdges(path, pageHeight, scale) {
40382
40392
  stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
40383
40393
  stroke.dashPhase * strokeScale
40384
40394
  );
40385
- return pathsToEdges(contours.map((points) => ({ points: points.map(toScreen), closed: true })));
40395
+ return contours.map((points) => points.map(toScreen));
40386
40396
  }
40387
40397
  function pathsToEdges(paths, closeSubpaths = false) {
40388
40398
  const edges = [];
@@ -40529,6 +40539,9 @@ function renderSoftMask(mask, displayList, scale) {
40529
40539
  }
40530
40540
  return bitmap;
40531
40541
  }
40542
+ function hasBlendModes(operations) {
40543
+ return operations.some((operation) => !!operation.value.blendMode && operation.value.blendMode !== "Normal" && operation.value.blendMode !== "Compatible" || operation.kind === "group" && hasBlendModes(operation.value.operations));
40544
+ }
40532
40545
  function renderDisplayListToBitmap(displayList, options = {}) {
40533
40546
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
40534
40547
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
@@ -40537,11 +40550,13 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40537
40550
  const width = Math.max(1, Math.round(displayList.width * scale));
40538
40551
  const height = Math.max(1, Math.round(displayList.height * scale));
40539
40552
  const rgba = new Uint8Array(width * height * 4);
40553
+ const deferBackground = !options.transparent && hasBlendModes(paintOperations(displayList));
40554
+ const transparent = options.transparent || deferBackground;
40540
40555
  const bg = options.background ?? { r: 1, g: 1, b: 1 };
40541
- const bgR = options.transparent ? 0 : Math.round(bg.r * 255);
40542
- const bgG = options.transparent ? 0 : Math.round(bg.g * 255);
40543
- const bgB = options.transparent ? 0 : Math.round(bg.b * 255);
40544
- const bgA = options.transparent ? 0 : 255;
40556
+ const bgR = transparent ? 0 : Math.round(bg.r * 255);
40557
+ const bgG = transparent ? 0 : Math.round(bg.g * 255);
40558
+ const bgB = transparent ? 0 : Math.round(bg.b * 255);
40559
+ const bgA = transparent ? 0 : 255;
40545
40560
  for (let i = 0; i < width * height; i++) {
40546
40561
  rgba[i * 4] = bgR;
40547
40562
  rgba[i * 4 + 1] = bgG;
@@ -40635,7 +40650,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40635
40650
  if (path.strokeColor) {
40636
40651
  const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
40637
40652
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
40638
- const edges = strokeEdges(path, displayList.height, scale);
40653
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
40639
40654
  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;
40640
40655
  fillEdgesScanline4x4(
40641
40656
  rgba,
@@ -40718,6 +40733,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40718
40733
  }
40719
40734
  }
40720
40735
  }
40736
+ if (deferBackground) {
40737
+ for (let i = 0; i < rgba.length; i += 4) {
40738
+ const alpha = rgba[i + 3] / 255;
40739
+ rgba[i] = Math.round(rgba[i] * alpha + bg.r * 255 * (1 - alpha));
40740
+ rgba[i + 1] = Math.round(rgba[i + 1] * alpha + bg.g * 255 * (1 - alpha));
40741
+ rgba[i + 2] = Math.round(rgba[i + 2] * alpha + bg.b * 255 * (1 - alpha));
40742
+ rgba[i + 3] = 255;
40743
+ }
40744
+ }
40721
40745
  let result = { width, height, data: rgba };
40722
40746
  if (Math.abs(scaleX - scaleY) > 1e-6) {
40723
40747
  const targetW = Math.max(1, Math.round(displayList.width * scaleX));
@@ -40826,6 +40850,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
40826
40850
  if (!options.transparent) {
40827
40851
  parts.push(` <rect x="${vbX}" y="${vbY}" width="${vbW}" height="${vbH}" fill="#ffffff"/>`);
40828
40852
  }
40853
+ parts.push('<g style="isolation:isolate">');
40829
40854
  if (displayList.rotation) {
40830
40855
  const [a, b, c, d, e, f] = viewport.transform;
40831
40856
  parts.push(`<g transform="matrix(${a} ${b} ${-c} ${-d} ${e + c * displayList.height} ${f + d * displayList.height})">`);
@@ -40877,6 +40902,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
40877
40902
  } else if (operation.kind === "path") {
40878
40903
  const p = operation.value;
40879
40904
  const prepared = p.strokeColor ? prepareStroke(p, Math.max(scaleX, scaleY)) : void 0;
40905
+ const outlineStroke = prepared && p.dashArray?.includes(0);
40880
40906
  const matrix = prepared && (prepared.matrix[0] !== 1 || prepared.matrix[1] !== 0 || prepared.matrix[2] !== 0 || prepared.matrix[3] !== 1) ? prepared.matrix : void 0;
40881
40907
  const inverse = matrix ? inverseStrokeMatrix(matrix) : void 0;
40882
40908
  const pathData = svgPathData(p.segments, inverse ? 0 : displayList.height, inverse);
@@ -40891,10 +40917,18 @@ function renderDisplayListToSvg(displayList, options = {}) {
40891
40917
  const lineCapAttr = p.lineCap === 1 ? ` stroke-linecap="round"` : p.lineCap === 2 ? ` stroke-linecap="square"` : "";
40892
40918
  const lineJoinAttr = p.lineJoin === 1 ? ` stroke-linejoin="round"` : p.lineJoin === 2 ? ` stroke-linejoin="bevel"` : "";
40893
40919
  const miterLimitAttr = p.miterLimit !== void 0 && p.miterLimit !== 10 ? ` stroke-miterlimit="${p.miterLimit}"` : "";
40894
- const dashArrayAttr = prepared?.dashArray?.length ? ` stroke-dasharray="${prepared.dashArray.join(" ")}"` : "";
40895
- const dashOffsetAttr = prepared?.dashPhase ? ` stroke-dashoffset="${prepared.dashPhase}"` : "";
40920
+ const dashArrayAttr = !outlineStroke && prepared?.dashArray?.length ? ` stroke-dasharray="${prepared.dashArray.join(" ")}"` : "";
40921
+ const dashOffsetAttr = !outlineStroke && prepared?.dashPhase ? ` stroke-dashoffset="${prepared.dashPhase}"` : "";
40896
40922
  const labelAttr = original.kind === "glyph" ? ` aria-label="${escapeXmlText(original.value.unicode)}"` : "";
40897
- parts.push(` <path${labelAttr}${transformAttr} d="${pathData}" fill="${fill}"${fillRuleAttr}${fillOpacityAttr} stroke="${stroke}"${strokeOpacityAttr}${strokeWidthAttr}${lineCapAttr}${lineJoinAttr}${miterLimitAttr}${dashArrayAttr}${dashOffsetAttr}/>`);
40923
+ if (!outlineStroke || p.fillColor) {
40924
+ parts.push(` <path${labelAttr}${transformAttr} d="${pathData}" fill="${fill}"${fillRuleAttr}${fillOpacityAttr} stroke="${outlineStroke ? "none" : stroke}"${strokeOpacityAttr}${strokeWidthAttr}${lineCapAttr}${lineJoinAttr}${miterLimitAttr}${dashArrayAttr}${dashOffsetAttr}/>`);
40925
+ }
40926
+ if (outlineStroke) {
40927
+ const outlineScale = Math.max(scaleX, scaleY);
40928
+ const contours = strokeContours(p, displayList.height, outlineScale);
40929
+ const outlineData = contours.map((points) => points.map(([x, y], i) => `${i === 0 ? "M" : "L"} ${x / outlineScale} ${y / outlineScale}`).join(" ") + " Z").join(" ");
40930
+ if (outlineData) parts.push(` <path${labelAttr} d="${outlineData}" fill="${stroke}" fill-opacity="${p.strokeAlpha ?? 1}"/>`);
40931
+ }
40898
40932
  }
40899
40933
  } else if (operation.kind === "image") {
40900
40934
  parts.push(` ${svgImage(operation.value, displayList.height)}`);
@@ -40904,6 +40938,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
40904
40938
  };
40905
40939
  appendOperations(paintOperations(displayList));
40906
40940
  if (displayList.rotation) parts.push("</g>");
40941
+ parts.push("</g>");
40907
40942
  parts.push("</svg>\n");
40908
40943
  return parts.join("\n");
40909
40944
  }
@@ -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]);
@@ -40340,7 +40350,7 @@ function prepareStroke(path, scale) {
40340
40350
  }
40341
40351
  return { matrix, width, dashArray, dashPhase };
40342
40352
  }
40343
- function strokeEdges(path, pageHeight, scale) {
40353
+ function strokeContours(path, pageHeight, scale) {
40344
40354
  const stroke = prepareStroke(path, scale);
40345
40355
  if (!stroke) return [];
40346
40356
  const inverse = inverseStrokeMatrix(stroke.matrix);
@@ -40364,7 +40374,7 @@ function strokeEdges(path, pageHeight, scale) {
40364
40374
  stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
40365
40375
  stroke.dashPhase * strokeScale
40366
40376
  );
40367
- return pathsToEdges(contours.map((points) => ({ points: points.map(toScreen), closed: true })));
40377
+ return contours.map((points) => points.map(toScreen));
40368
40378
  }
40369
40379
  function pathsToEdges(paths, closeSubpaths = false) {
40370
40380
  const edges = [];
@@ -40511,6 +40521,9 @@ function renderSoftMask(mask, displayList, scale) {
40511
40521
  }
40512
40522
  return bitmap;
40513
40523
  }
40524
+ function hasBlendModes(operations) {
40525
+ return operations.some((operation) => !!operation.value.blendMode && operation.value.blendMode !== "Normal" && operation.value.blendMode !== "Compatible" || operation.kind === "group" && hasBlendModes(operation.value.operations));
40526
+ }
40514
40527
  function renderDisplayListToBitmap(displayList, options = {}) {
40515
40528
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
40516
40529
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
@@ -40519,11 +40532,13 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40519
40532
  const width = Math.max(1, Math.round(displayList.width * scale));
40520
40533
  const height = Math.max(1, Math.round(displayList.height * scale));
40521
40534
  const rgba = new Uint8Array(width * height * 4);
40535
+ const deferBackground = !options.transparent && hasBlendModes(paintOperations(displayList));
40536
+ const transparent = options.transparent || deferBackground;
40522
40537
  const bg = options.background ?? { r: 1, g: 1, b: 1 };
40523
- const bgR = options.transparent ? 0 : Math.round(bg.r * 255);
40524
- const bgG = options.transparent ? 0 : Math.round(bg.g * 255);
40525
- const bgB = options.transparent ? 0 : Math.round(bg.b * 255);
40526
- const bgA = options.transparent ? 0 : 255;
40538
+ const bgR = transparent ? 0 : Math.round(bg.r * 255);
40539
+ const bgG = transparent ? 0 : Math.round(bg.g * 255);
40540
+ const bgB = transparent ? 0 : Math.round(bg.b * 255);
40541
+ const bgA = transparent ? 0 : 255;
40527
40542
  for (let i = 0; i < width * height; i++) {
40528
40543
  rgba[i * 4] = bgR;
40529
40544
  rgba[i * 4 + 1] = bgG;
@@ -40617,7 +40632,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40617
40632
  if (path.strokeColor) {
40618
40633
  const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
40619
40634
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
40620
- const edges = strokeEdges(path, displayList.height, scale);
40635
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
40621
40636
  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;
40622
40637
  fillEdgesScanline4x4(
40623
40638
  rgba,
@@ -40700,6 +40715,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40700
40715
  }
40701
40716
  }
40702
40717
  }
40718
+ if (deferBackground) {
40719
+ for (let i = 0; i < rgba.length; i += 4) {
40720
+ const alpha = rgba[i + 3] / 255;
40721
+ rgba[i] = Math.round(rgba[i] * alpha + bg.r * 255 * (1 - alpha));
40722
+ rgba[i + 1] = Math.round(rgba[i + 1] * alpha + bg.g * 255 * (1 - alpha));
40723
+ rgba[i + 2] = Math.round(rgba[i + 2] * alpha + bg.b * 255 * (1 - alpha));
40724
+ rgba[i + 3] = 255;
40725
+ }
40726
+ }
40703
40727
  let result = { width, height, data: rgba };
40704
40728
  if (Math.abs(scaleX - scaleY) > 1e-6) {
40705
40729
  const targetW = Math.max(1, Math.round(displayList.width * scaleX));
@@ -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) {
@@ -38956,7 +38958,7 @@ function dashSubpath(path, pattern, phase) {
38956
38958
  while (remaining <= 0) {
38957
38959
  if (++steps > MAX_STROKE_VERTICES) throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
38958
38960
  if (index % 2 === 0) {
38959
- if (pattern[index] === 0) result.push({ points: [point, point], closed: false });
38961
+ if (pattern[index] === 0) result.push({ points: [point, point], closed: false, zeroLengthDash: true });
38960
38962
  flush();
38961
38963
  }
38962
38964
  index = (index + 1) % pattern.length;
@@ -38971,7 +38973,7 @@ function dashSubpath(path, pattern, phase) {
38971
38973
  throw new PdfError("E_LIMIT", "Stroke dash expansion exceeds the vertex limit");
38972
38974
  }
38973
38975
  let distance = 0;
38974
- while (distance < length) {
38976
+ while (length - distance > 8 * Number.EPSILON * Math.max(1, length)) {
38975
38977
  const point = [start[0] + dx * distance / length, start[1] + dy * distance / length];
38976
38978
  advance(point);
38977
38979
  const step = Math.min(remaining, length - distance);
@@ -39086,7 +39088,15 @@ function strokeOutlines(paths, width, cap, join, miterLimit, dashArray = [], das
39086
39088
  let closed = subpath.closed;
39087
39089
  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();
39088
39090
  if (points.length < 3) closed = false;
39089
- if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
39091
+ if (points.length === 1 && cap === 2 && subpath.zeroLengthDash) {
39092
+ contour = [];
39093
+ const [x, y] = points[0];
39094
+ add(x - half, y - half);
39095
+ add(x + half, y - half);
39096
+ add(x + half, y + half);
39097
+ add(x - half, y + half);
39098
+ contours.push(contour);
39099
+ } else if (points.length === 1 && subpath.points.length > 1 && cap === 1) {
39090
39100
  contour = [];
39091
39101
  const [x, y] = points[0];
39092
39102
  addCap([x, y], [x + 1, y]);
@@ -39878,7 +39888,7 @@ function prepareStroke(path, scale) {
39878
39888
  }
39879
39889
  return { matrix, width, dashArray, dashPhase };
39880
39890
  }
39881
- function strokeEdges(path, pageHeight, scale) {
39891
+ function strokeContours(path, pageHeight, scale) {
39882
39892
  const stroke = prepareStroke(path, scale);
39883
39893
  if (!stroke) return [];
39884
39894
  const inverse = inverseStrokeMatrix(stroke.matrix);
@@ -39902,7 +39912,7 @@ function strokeEdges(path, pageHeight, scale) {
39902
39912
  stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
39903
39913
  stroke.dashPhase * strokeScale
39904
39914
  );
39905
- return pathsToEdges(contours.map((points) => ({ points: points.map(toScreen), closed: true })));
39915
+ return contours.map((points) => points.map(toScreen));
39906
39916
  }
39907
39917
  function pathsToEdges(paths, closeSubpaths = false) {
39908
39918
  const edges = [];
@@ -40049,6 +40059,9 @@ function renderSoftMask(mask, displayList, scale) {
40049
40059
  }
40050
40060
  return bitmap;
40051
40061
  }
40062
+ function hasBlendModes(operations) {
40063
+ return operations.some((operation) => !!operation.value.blendMode && operation.value.blendMode !== "Normal" && operation.value.blendMode !== "Compatible" || operation.kind === "group" && hasBlendModes(operation.value.operations));
40064
+ }
40052
40065
  function renderDisplayListToBitmap(displayList, options = {}) {
40053
40066
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
40054
40067
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
@@ -40057,11 +40070,13 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40057
40070
  const width = Math.max(1, Math.round(displayList.width * scale));
40058
40071
  const height = Math.max(1, Math.round(displayList.height * scale));
40059
40072
  const rgba = new Uint8Array(width * height * 4);
40073
+ const deferBackground = !options.transparent && hasBlendModes(paintOperations(displayList));
40074
+ const transparent = options.transparent || deferBackground;
40060
40075
  const bg = options.background ?? { r: 1, g: 1, b: 1 };
40061
- const bgR = options.transparent ? 0 : Math.round(bg.r * 255);
40062
- const bgG = options.transparent ? 0 : Math.round(bg.g * 255);
40063
- const bgB = options.transparent ? 0 : Math.round(bg.b * 255);
40064
- const bgA = options.transparent ? 0 : 255;
40076
+ const bgR = transparent ? 0 : Math.round(bg.r * 255);
40077
+ const bgG = transparent ? 0 : Math.round(bg.g * 255);
40078
+ const bgB = transparent ? 0 : Math.round(bg.b * 255);
40079
+ const bgA = transparent ? 0 : 255;
40065
40080
  for (let i = 0; i < width * height; i++) {
40066
40081
  rgba[i * 4] = bgR;
40067
40082
  rgba[i * 4 + 1] = bgG;
@@ -40155,7 +40170,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40155
40170
  if (path.strokeColor) {
40156
40171
  const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
40157
40172
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
40158
- const edges = strokeEdges(path, displayList.height, scale);
40173
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
40159
40174
  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;
40160
40175
  fillEdgesScanline4x4(
40161
40176
  rgba,
@@ -40238,6 +40253,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40238
40253
  }
40239
40254
  }
40240
40255
  }
40256
+ if (deferBackground) {
40257
+ for (let i = 0; i < rgba.length; i += 4) {
40258
+ const alpha = rgba[i + 3] / 255;
40259
+ rgba[i] = Math.round(rgba[i] * alpha + bg.r * 255 * (1 - alpha));
40260
+ rgba[i + 1] = Math.round(rgba[i + 1] * alpha + bg.g * 255 * (1 - alpha));
40261
+ rgba[i + 2] = Math.round(rgba[i + 2] * alpha + bg.b * 255 * (1 - alpha));
40262
+ rgba[i + 3] = 255;
40263
+ }
40264
+ }
40241
40265
  let result = { width, height, data: rgba };
40242
40266
  if (Math.abs(scaleX - scaleY) > 1e-6) {
40243
40267
  const targetW = Math.max(1, Math.round(displayList.width * scaleX));
@@ -11,8 +11,8 @@ import {
11
11
  readImageMetadata,
12
12
  resizeImage,
13
13
  rotateImage
14
- } from "../safe-bash/command-chunks/chunk-SVL6HYQL.js";
15
- import "../safe-bash/command-chunks/chunk-KO4PXCNL.js";
14
+ } from "../safe-bash/command-chunks/chunk-A5S6M37L.js";
15
+ import "../safe-bash/command-chunks/chunk-2JQONXIY.js";
16
16
  import {
17
17
  init_buffer
18
18
  } from "../safe-bash/command-chunks/chunk-HX3SHTCE.js";
@@ -31,7 +31,7 @@ import {
31
31
  PdfDocument,
32
32
  decodeFlate,
33
33
  rgb
34
- } from "../safe-bash/command-chunks/chunk-KO4PXCNL.js";
34
+ } from "../safe-bash/command-chunks/chunk-2JQONXIY.js";
35
35
  import {
36
36
  init_buffer
37
37
  } from "../safe-bash/command-chunks/chunk-HX3SHTCE.js";