@poe-platform/safe-bash 0.1.780 → 0.1.781

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.
@@ -26760,7 +26760,7 @@ function cosString(value, span) {
26760
26760
  if (typeof value === "string") {
26761
26761
  let needsUtf16 = false;
26762
26762
  for (let i = 0; i < value.length; i++) {
26763
- if (value.charCodeAt(i) > 255) {
26763
+ if (!PDF_DOC_ENCODING_REVERSE.has(value.charCodeAt(i))) {
26764
26764
  needsUtf16 = true;
26765
26765
  break;
26766
26766
  }
@@ -26778,7 +26778,7 @@ function cosString(value, span) {
26778
26778
  }
26779
26779
  const bytes = new Uint8Array(value.length);
26780
26780
  for (let i = 0; i < value.length; i++) {
26781
- bytes[i] = value.charCodeAt(i) & 255;
26781
+ bytes[i] = PDF_DOC_ENCODING_REVERSE.get(value.charCodeAt(i));
26782
26782
  }
26783
26783
  return { kind: "string", format: "literal", bytes, span };
26784
26784
  }
@@ -26925,6 +26925,9 @@ var PDF_DOC_ENCODING_MAP = {
26925
26925
  160: 8364,
26926
26926
  173: 65533
26927
26927
  };
26928
+ var PDF_DOC_ENCODING_REVERSE = new Map(
26929
+ Array.from({ length: 256 }, (_, byte) => [PDF_DOC_ENCODING_MAP[byte] ?? byte, byte])
26930
+ );
26928
26931
  function decodeUtf16UnitsWithSurrogateCheck(units) {
26929
26932
  let out = "";
26930
26933
  for (let i = 0; i < units.length; i++) {
@@ -27216,6 +27219,7 @@ var CosByteLexer = class {
27216
27219
  const start = this.pos;
27217
27220
  this.pos++;
27218
27221
  let depth = 1;
27222
+ let recovery;
27219
27223
  const out = [];
27220
27224
  while (this.pos < this.end && depth > 0) {
27221
27225
  const b = this.bytes[this.pos++];
@@ -27250,7 +27254,15 @@ var CosByteLexer = class {
27250
27254
  out.push(b);
27251
27255
  } else if (b === 41) {
27252
27256
  depth--;
27253
- if (depth > 0) out.push(b);
27257
+ if (depth > 0) {
27258
+ const next = this.bytes[this.pos];
27259
+ const afterLine = next === 13 && this.bytes[this.pos + 1] === 10 ? this.pos + 2 : this.pos + 1;
27260
+ const delimiter = this.bytes[afterLine];
27261
+ if (!recovery && this.pos + 2 < this.end && (next === 10 || next === 13) && (delimiter === 47 || delimiter === 62)) {
27262
+ recovery = { offset: this.pos, length: out.length };
27263
+ }
27264
+ out.push(b);
27265
+ }
27254
27266
  } else if (b === 13) {
27255
27267
  if (this.pos < this.end && this.bytes[this.pos] === 10) this.pos++;
27256
27268
  out.push(10);
@@ -27261,6 +27273,10 @@ var CosByteLexer = class {
27261
27273
  throw new PdfError("E_LIMIT", "PDF literal string exceeds maximum byte length");
27262
27274
  }
27263
27275
  }
27276
+ if (depth > 0 && recovery) {
27277
+ this.pos = recovery.offset;
27278
+ out.length = recovery.length;
27279
+ }
27264
27280
  return {
27265
27281
  kind: "string",
27266
27282
  bytes: Uint8Array.from(out),
@@ -38976,6 +38992,7 @@ function evaluateContentStreamToDisplayList(params) {
38976
38992
  };
38977
38993
  const initialState = {
38978
38994
  ctm: [1, 0, 0, 1, 0, 0],
38995
+ initialCtm: [1, 0, 0, 1, 0, 0],
38979
38996
  strokeColor: { r: 0, g: 0, b: 0 },
38980
38997
  fillColor: { r: 0, g: 0, b: 0 },
38981
38998
  strokeAlpha: 1,
@@ -39273,6 +39290,116 @@ function evaluateContentStreamToDisplayList(params) {
39273
39290
  ] }], void 0, void 0, resources, activeFonts, depth);
39274
39291
  stateStack.pop();
39275
39292
  };
39293
+ const paintPattern = (segments, fillRule, resources, activeFonts, depth, mcid, actualText) => {
39294
+ const st = curState(), doc = params.cosDoc;
39295
+ if (!st.fillPatternName || !doc || !resources) return false;
39296
+ if (depth >= 8) throw new PdfError("E_LIMIT", "Pattern nesting exceeds the form depth limit");
39297
+ const patterns = doc.resolveDict(dictGet(resources, "Pattern"));
39298
+ const pattern = patterns && doc.resolve(dictGet(patterns, st.fillPatternName));
39299
+ const dict = pattern?.kind === "stream" ? pattern.dict : pattern?.kind === "dict" ? pattern : void 0;
39300
+ if (!dict) return false;
39301
+ const nums = (key, fallback) => {
39302
+ const array = doc.resolveArray(dictGet(dict, key));
39303
+ return array ? array.items.map((item, i) => {
39304
+ const value = doc.resolve(item);
39305
+ return value?.kind === "number" ? value.value : fallback[i] ?? 0;
39306
+ }) : fallback;
39307
+ };
39308
+ let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;
39309
+ const include = (x, y) => {
39310
+ x0 = Math.min(x0, x);
39311
+ y0 = Math.min(y0, y);
39312
+ x1 = Math.max(x1, x);
39313
+ y1 = Math.max(y1, y);
39314
+ };
39315
+ for (const segment of segments) {
39316
+ if (segment.kind === "close") continue;
39317
+ include(segment.x, segment.y);
39318
+ if (segment.kind === "cubic") {
39319
+ include(segment.x1, segment.y1);
39320
+ include(segment.x2, segment.y2);
39321
+ }
39322
+ if (segment.kind === "rect") include(segment.x + segment.width, segment.y + segment.height);
39323
+ }
39324
+ const [originX, originY] = params.origin ?? [0, 0];
39325
+ const clip = st.clipRect ?? [originX, originY, originX + params.width, originY + params.height];
39326
+ const bounds = [Math.max(x0, clip[0]), Math.max(y0, clip[1]), Math.min(x1, clip[2]), Math.min(y1, clip[3])];
39327
+ if (!(bounds[2] > bounds[0] && bounds[3] > bounds[1])) return true;
39328
+ const matrix = multiplyMatrices(nums("Matrix", [1, 0, 0, 1, 0, 0]), st.initialCtm);
39329
+ const type = doc.resolve(dictGet(dict, "PatternType"));
39330
+ stateStack.push({ ...st, clipRect: bounds, clipPaths: [...st.clipPaths ?? [], { segments, fillRule }] });
39331
+ try {
39332
+ if (type?.kind === "number" && type.value === 2) {
39333
+ const shading = doc.resolve(dictGet(dict, "Shading"));
39334
+ const shadingDict = shading?.kind === "stream" ? shading.dict : shading?.kind === "dict" ? shading : void 0;
39335
+ if (!shadingDict) return false;
39336
+ const image = renderShadingDictToImage(
39337
+ doc,
39338
+ shadingDict,
39339
+ matrix,
39340
+ bounds,
39341
+ st.fillAlpha,
39342
+ "PatternShading_" + st.fillPatternName,
39343
+ bounds,
39344
+ shading?.kind === "stream" ? shading : void 0,
39345
+ st.blendMode
39346
+ );
39347
+ if (image) emit({ kind: "image", value: image });
39348
+ return !!image;
39349
+ }
39350
+ if (pattern?.kind !== "stream") return false;
39351
+ const xStepNode = doc.resolve(dictGet(dict, "XStep"));
39352
+ const yStepNode = doc.resolve(dictGet(dict, "YStep"));
39353
+ const xStep = xStepNode?.kind === "number" ? Math.abs(xStepNode.value) : 0;
39354
+ const yStep = yStepNode?.kind === "number" ? Math.abs(yStepNode.value) : 0;
39355
+ const determinant = matrix[0] * matrix[3] - matrix[1] * matrix[2];
39356
+ if (!xStep || !yStep || !determinant) return true;
39357
+ const inverse = [
39358
+ matrix[3] / determinant,
39359
+ -matrix[1] / determinant,
39360
+ -matrix[2] / determinant,
39361
+ matrix[0] / determinant,
39362
+ (matrix[2] * matrix[5] - matrix[3] * matrix[4]) / determinant,
39363
+ (matrix[1] * matrix[4] - matrix[0] * matrix[5]) / determinant
39364
+ ];
39365
+ const corners = [[bounds[0], bounds[1]], [bounds[2], bounds[1]], [bounds[2], bounds[3]], [bounds[0], bounds[3]]].map(([x, y]) => transformPoint(inverse, x, y));
39366
+ const box = nums("BBox", [0, 0, xStep, yStep]);
39367
+ const ix0 = Math.floor((Math.min(...corners.map((p) => p[0])) - box[2]) / xStep) + 1;
39368
+ const ix1 = Math.ceil((Math.max(...corners.map((p) => p[0])) - box[0]) / xStep) - 1;
39369
+ const iy0 = Math.floor((Math.min(...corners.map((p) => p[1])) - box[3]) / yStep) + 1;
39370
+ const iy1 = Math.ceil((Math.max(...corners.map((p) => p[1])) - box[1]) / yStep) - 1;
39371
+ if ((ix1 - ix0 + 1) * (iy1 - iy0 + 1) > 2e4) throw new PdfError("E_LIMIT", "Pattern tile count exceeds 20000");
39372
+ const nodes = parseContentStream(doc.decodeStream(pattern));
39373
+ const patternResources = doc.resolveDict(dictGet(dict, "Resources")) ?? resources;
39374
+ const patternFonts = new Map(activeFonts);
39375
+ for (const [key, font] of resolvePageFonts(doc, patternResources)) patternFonts.set(key, font);
39376
+ for (let iy = iy0; iy <= iy1; iy++) {
39377
+ for (let ix = ix0; ix <= ix1; ix++) {
39378
+ const tileCtm = multiplyMatrices([1, 0, 0, 1, ix * xStep, iy * yStep], matrix);
39379
+ const points = [[box[0], box[1]], [box[2], box[1]], [box[2], box[3]], [box[0], box[3]]].map(([x, y]) => transformPoint(tileCtm, x, y));
39380
+ const tileClip = [
39381
+ ...points.map(([x, y], i) => ({ kind: i === 0 ? "move" : "line", x, y })),
39382
+ { kind: "close" }
39383
+ ];
39384
+ stateStack.push({
39385
+ ...curState(),
39386
+ fillPatternName: void 0,
39387
+ ctm: tileCtm,
39388
+ initialCtm: tileCtm,
39389
+ clipPaths: [...curState().clipPaths ?? [], tileClip]
39390
+ });
39391
+ try {
39392
+ walkNodes(nodes, mcid, actualText, patternResources, patternFonts, depth + 1);
39393
+ } finally {
39394
+ stateStack.pop();
39395
+ }
39396
+ }
39397
+ }
39398
+ return true;
39399
+ } finally {
39400
+ stateStack.pop();
39401
+ }
39402
+ };
39276
39403
  const paintForm = (form, activeResources, activeFonts, depth, mcid, actualText, maskGroup = false) => {
39277
39404
  const st = curState();
39278
39405
  const group = params.cosDoc.resolveDict(dictGet(form.dict, "Group"));
@@ -39331,7 +39458,7 @@ function evaluateContentStreamToDisplayList(params) {
39331
39458
  }
39332
39459
  const parentOperations = capturedOperations;
39333
39460
  const children = [];
39334
- const nextState = { ...st, ctm: nextCtm };
39461
+ const nextState = { ...st, ctm: nextCtm, initialCtm: nextCtm };
39335
39462
  if (compositeGroup) {
39336
39463
  capturedOperations = children;
39337
39464
  nextState.fillAlpha = nextState.strokeAlpha = 1;
@@ -39489,136 +39616,15 @@ function evaluateContentStreamToDisplayList(params) {
39489
39616
  }
39490
39617
  const isFill = ["f", "F", "f*", "B", "B*", "b", "b*"].includes(node.paint);
39491
39618
  const isStroke = ["S", "s", "B", "B*", "b", "b*"].includes(node.paint);
39492
- let evaluatedFillPattern = false;
39493
- if (isFill && st.fillPatternName && params.cosDoc && activeResources && depth < 6) {
39494
- const patMap = params.cosDoc.resolveDict(dictGet(activeResources, "Pattern"));
39495
- const patNode = patMap ? params.cosDoc.resolve(dictGet(patMap, st.fillPatternName)) : void 0;
39496
- const patDict = patNode?.kind === "stream" ? patNode.dict : patNode?.kind === "dict" ? patNode : void 0;
39497
- const patTypeNode = patDict && params.cosDoc ? params.cosDoc.resolve(dictGet(patDict, "PatternType")) : void 0;
39498
- const patType = patTypeNode?.kind === "number" ? patTypeNode.value : patNode?.kind === "stream" ? 1 : 0;
39499
- if (patDict && patType === 2 && params.cosDoc) {
39500
- let pMinX = Infinity, pMinY = Infinity, pMaxX = -Infinity, pMaxY = -Infinity;
39501
- for (const s of transformedSegments) {
39502
- if (s.kind === "move" || s.kind === "line") {
39503
- pMinX = Math.min(pMinX, s.x);
39504
- pMinY = Math.min(pMinY, s.y);
39505
- pMaxX = Math.max(pMaxX, s.x);
39506
- pMaxY = Math.max(pMaxY, s.y);
39507
- } else if (s.kind === "cubic") {
39508
- pMinX = Math.min(pMinX, s.x1, s.x2, s.x);
39509
- pMinY = Math.min(pMinY, s.y1, s.y2, s.y);
39510
- pMaxX = Math.max(pMaxX, s.x1, s.x2, s.x);
39511
- pMaxY = Math.max(pMaxY, s.y1, s.y2, s.y);
39512
- } else if (s.kind === "rect") {
39513
- pMinX = Math.min(pMinX, s.x);
39514
- pMinY = Math.min(pMinY, s.y);
39515
- pMaxX = Math.max(pMaxX, s.x + s.width);
39516
- pMaxY = Math.max(pMaxY, s.y + s.height);
39517
- }
39518
- }
39519
- if (Number.isFinite(pMinX) && Number.isFinite(pMinY) && pMaxX > pMinX && pMaxY > pMinY) {
39520
- const shading = params.cosDoc.resolve(dictGet(patDict, "Shading"));
39521
- const shDict = shading?.kind === "stream" ? shading.dict : shading?.kind === "dict" ? shading : void 0;
39522
- if (shDict) {
39523
- let patMatrix = [1, 0, 0, 1, 0, 0];
39524
- const pmArr = params.cosDoc.resolveArray(dictGet(patDict, "Matrix"));
39525
- if (pmArr && pmArr.items.length >= 6) {
39526
- const mn = (idx, fb = 0) => {
39527
- const r = params.cosDoc.resolve(pmArr.items[idx]);
39528
- return r?.kind === "number" ? r.value : fb;
39529
- };
39530
- patMatrix = [mn(0, 1), mn(1, 0), mn(2, 0), mn(3, 1), mn(4, 0), mn(5, 0)];
39531
- }
39532
- const patClip = st.clipRect ? [
39533
- Math.max(st.clipRect[0], pMinX),
39534
- Math.max(st.clipRect[1], pMinY),
39535
- Math.min(st.clipRect[2], pMaxX),
39536
- Math.min(st.clipRect[3], pMaxY)
39537
- ] : [pMinX, pMinY, pMaxX, pMaxY];
39538
- const shImg = renderShadingDictToImage(
39539
- params.cosDoc,
39540
- shDict,
39541
- patMatrix,
39542
- patClip,
39543
- st.fillAlpha,
39544
- "PatternShading_" + st.fillPatternName,
39545
- patClip,
39546
- shading?.kind === "stream" ? shading : void 0,
39547
- st.blendMode
39548
- );
39549
- if (shImg) {
39550
- emit({ kind: "image", value: shImg });
39551
- evaluatedFillPattern = true;
39552
- }
39553
- }
39554
- }
39555
- } else if (patNode?.kind === "stream") {
39556
- let pMinX = Infinity, pMinY = Infinity, pMaxX = -Infinity, pMaxY = -Infinity;
39557
- for (const s of transformedSegments) {
39558
- if (s.kind === "move" || s.kind === "line") {
39559
- pMinX = Math.min(pMinX, s.x);
39560
- pMinY = Math.min(pMinY, s.y);
39561
- pMaxX = Math.max(pMaxX, s.x);
39562
- pMaxY = Math.max(pMaxY, s.y);
39563
- } else if (s.kind === "cubic") {
39564
- pMinX = Math.min(pMinX, s.x1, s.x2, s.x);
39565
- pMinY = Math.min(pMinY, s.y1, s.y2, s.y);
39566
- pMaxX = Math.max(pMaxX, s.x1, s.x2, s.x);
39567
- pMaxY = Math.max(pMaxY, s.y1, s.y2, s.y);
39568
- } else if (s.kind === "rect") {
39569
- pMinX = Math.min(pMinX, s.x);
39570
- pMinY = Math.min(pMinY, s.y);
39571
- pMaxX = Math.max(pMaxX, s.x + s.width);
39572
- pMaxY = Math.max(pMaxY, s.y + s.height);
39573
- }
39574
- }
39575
- if (Number.isFinite(pMinX) && Number.isFinite(pMinY) && pMaxX > pMinX && pMaxY > pMinY) {
39576
- const xsNode = params.cosDoc.resolve(dictGet(patNode.dict, "XStep"));
39577
- const ysNode = params.cosDoc.resolve(dictGet(patNode.dict, "YStep"));
39578
- const xStep = xsNode?.kind === "number" && Math.abs(xsNode.value) > 1e-3 ? Math.abs(xsNode.value) : 40;
39579
- const yStep = ysNode?.kind === "number" && Math.abs(ysNode.value) > 1e-3 ? Math.abs(ysNode.value) : 40;
39580
- let patMatrix = [1, 0, 0, 1, 0, 0];
39581
- const pmArr = params.cosDoc.resolveArray(dictGet(patNode.dict, "Matrix"));
39582
- if (pmArr && pmArr.items.length >= 6) {
39583
- const mn = (idx, fb = 0) => {
39584
- const r = params.cosDoc.resolve(pmArr.items[idx]);
39585
- return r?.kind === "number" ? r.value : fb;
39586
- };
39587
- patMatrix = [mn(0, 1), mn(1, 0), mn(2, 0), mn(3, 1), mn(4, 0), mn(5, 0)];
39588
- }
39589
- const tileClip = st.clipRect ? [
39590
- Math.max(st.clipRect[0], pMinX),
39591
- Math.max(st.clipRect[1], pMinY),
39592
- Math.min(st.clipRect[2], pMaxX),
39593
- Math.min(st.clipRect[3], pMaxY)
39594
- ] : [pMinX, pMinY, pMaxX, pMaxY];
39595
- const patNodes = parseContentStream(params.cosDoc.decodeStream(patNode));
39596
- const patResDict = params.cosDoc.resolveDict(dictGet(patNode.dict, "Resources")) ?? activeResources;
39597
- const patFonts = new Map(activeFonts);
39598
- for (const [fk, fv] of resolvePageFonts(params.cosDoc, patResDict).entries()) {
39599
- patFonts.set(fk, fv);
39600
- }
39601
- const ixStart = Math.floor(pMinX / xStep);
39602
- const ixEnd = Math.min(ixStart + 8, Math.ceil(pMaxX / xStep) - 1);
39603
- const iyStart = Math.floor(pMinY / yStep);
39604
- const iyEnd = Math.min(iyStart + 8, Math.ceil(pMaxY / yStep) - 1);
39605
- for (let iy = iyStart; iy <= iyEnd; iy++) {
39606
- for (let ix = ixStart; ix <= ixEnd; ix++) {
39607
- const tileCtm = multiplyMatrices([1, 0, 0, 1, ix * xStep, iy * yStep], patMatrix);
39608
- stateStack.push({
39609
- ...st,
39610
- fillPatternName: void 0,
39611
- ctm: tileCtm,
39612
- clipRect: tileClip
39613
- });
39614
- walkNodes(patNodes, mcid, actualText, patResDict, patFonts, depth + 1);
39615
- if (stateStack.length > 1) stateStack.pop();
39616
- }
39617
- }
39618
- evaluatedFillPattern = true;
39619
- }
39620
- }
39621
- }
39619
+ const evaluatedFillPattern = isFill && paintPattern(
39620
+ transformedSegments,
39621
+ node.paint.includes("*") ? "evenodd" : "nonzero",
39622
+ activeResources,
39623
+ activeFonts,
39624
+ depth,
39625
+ mcid,
39626
+ actualText
39627
+ );
39622
39628
  if (evaluatedFillPattern && !isStroke) {
39623
39629
  applyClip();
39624
39630
  break;
@@ -39819,10 +39825,19 @@ function evaluateContentStreamToDisplayList(params) {
39819
39825
  if (st.textRenderMode >= 4 && st.textRenderMode <= 7) pendingTextClip.push(...transformedGlyphSegs);
39820
39826
  const isFillGlyph = st.textRenderMode === 0 || st.textRenderMode === 2 || st.textRenderMode === 4 || st.textRenderMode === 6;
39821
39827
  const isStrokeGlyph = st.textRenderMode === 1 || st.textRenderMode === 2 || st.textRenderMode === 5 || st.textRenderMode === 6;
39828
+ const patterned = isFillGlyph && paintPattern(
39829
+ transformedGlyphSegs,
39830
+ "nonzero",
39831
+ activeResources,
39832
+ activeFonts,
39833
+ depth,
39834
+ mcid,
39835
+ actualText
39836
+ );
39822
39837
  const paint = {
39823
39838
  segments: transformedGlyphSegs,
39824
- fillColor: isFillGlyph ? st.fillColor : void 0,
39825
- fillAlpha: isFillGlyph ? st.fillAlpha : void 0,
39839
+ fillColor: isFillGlyph && !patterned ? st.fillColor : void 0,
39840
+ fillAlpha: isFillGlyph && !patterned ? st.fillAlpha : void 0,
39826
39841
  strokeColor: isStrokeGlyph ? st.strokeColor : void 0,
39827
39842
  strokeAlpha: isStrokeGlyph ? st.strokeAlpha : void 0,
39828
39843
  strokeWidth: isStrokeGlyph ? st.strokeWidth : 0,
@@ -43462,10 +43477,14 @@ function computePdfBlendRgb(cbR, cbG, cbB, csR, csG, csB, mode) {
43462
43477
  blendChannelSeparable(cbB, csB, mode)
43463
43478
  ];
43464
43479
  }
43465
- function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMask) {
43480
+ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMask, groupAlpha) {
43466
43481
  if (px < 0 || py < 0 || px >= width || py >= height || alpha <= 0) return;
43467
43482
  const a = Math.min(1, Math.max(0, alpha)) * (clipMask ? clipMask[(py * width + px) * 4 + 3] / 255 : 1);
43468
43483
  const idx = (py * width + px) * 4;
43484
+ if (groupAlpha) {
43485
+ const pixel = py * width + px;
43486
+ groupAlpha[pixel] = a + groupAlpha[pixel] * (1 - a);
43487
+ }
43469
43488
  const csR = Math.min(1, Math.max(0, color.r));
43470
43489
  const csG = Math.min(1, Math.max(0, color.g));
43471
43490
  const csB = Math.min(1, Math.max(0, color.b));
@@ -43597,7 +43616,7 @@ function pathsToEdges(paths, closeSubpaths = false) {
43597
43616
  }
43598
43617
  return edges;
43599
43618
  }
43600
- function fillEdgesScanline4x4(rgba, width, height, edges, color, alpha = 1, fillRule = "nonzero", clipScreen, antialias = true, blendMode, clipMask) {
43619
+ function fillEdgesScanline4x4(rgba, width, height, edges, color, alpha = 1, fillRule = "nonzero", clipScreen, antialias = true, blendMode, clipMask, groupAlpha) {
43601
43620
  if (edges.length === 0) return;
43602
43621
  let minY = Infinity;
43603
43622
  let maxY = -Infinity;
@@ -43663,7 +43682,7 @@ function fillEdgesScanline4x4(rgba, width, height, edges, color, alpha = 1, fill
43663
43682
  const count = rowCounts[px];
43664
43683
  if (count > 0) {
43665
43684
  const cov = antialias ? count / 16 : count >= 8 ? 1 : 0;
43666
- blendPixel(rgba, width, height, px, py, color, cov * alpha, blendMode, clipMask);
43685
+ blendPixel(rgba, width, height, px, py, color, cov * alpha, blendMode, clipMask, groupAlpha);
43667
43686
  }
43668
43687
  }
43669
43688
  }
@@ -43742,22 +43761,19 @@ function hasCompositingEffects(operations, includeSoftMasks = false) {
43742
43761
  return operations.some((operation) => includeSoftMasks && !!operation.value.softMask || !!operation.value.blendMode && operation.value.blendMode !== "Normal" && operation.value.blendMode !== "Compatible" || operation.kind === "group" && hasCompositingEffects(operation.value.operations, includeSoftMasks));
43743
43762
  }
43744
43763
  function needsGroupBackdrop(group) {
43745
- return group.isolated === false && !!group.softMask && hasCompositingEffects(group.operations, true);
43764
+ return group.isolated === false && hasCompositingEffects(group.operations, true);
43746
43765
  }
43747
43766
  function containsBackdropGroup(operations) {
43748
43767
  return operations.some((operation) => operation.kind === "group" && (needsGroupBackdrop(operation.value) || containsBackdropGroup(operation.value.operations)));
43749
43768
  }
43750
- function renderDisplayListToBitmap(displayList, options = {}) {
43751
- const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
43752
- const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
43753
- const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
43754
- const scale = scaleX;
43769
+ function renderDisplayListLayer(displayList, options, scale, backdrop) {
43755
43770
  const [originX, originY] = displayList.origin ?? [0, 0];
43756
43771
  const pageTop = originY + displayList.height;
43757
43772
  const toScreen = (x, y) => [(x - originX) * scale, (pageTop - y) * scale];
43758
43773
  const width = Math.max(1, Math.round(displayList.width * scale));
43759
43774
  const height = Math.max(1, Math.round(displayList.height * scale));
43760
- const rgba = new Uint8Array(width * height * 4);
43775
+ const rgba = backdrop ? backdrop.slice() : new Uint8Array(width * height * 4);
43776
+ const groupAlpha = backdrop ? new Float32Array(width * height) : void 0;
43761
43777
  const deferBackground = !options.transparent && hasCompositingEffects(paintOperations(displayList));
43762
43778
  const transparent = options.transparent || deferBackground;
43763
43779
  const bg = options.background ?? { r: 1, g: 1, b: 1 };
@@ -43765,7 +43781,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
43765
43781
  const bgG = transparent ? 0 : Math.round(bg.g * 255);
43766
43782
  const bgB = transparent ? 0 : Math.round(bg.b * 255);
43767
43783
  const bgA = transparent ? 0 : 255;
43768
- for (let i = 0; i < width * height; i++) {
43784
+ for (let i = 0; !backdrop && i < width * height; i++) {
43769
43785
  rgba[i * 4] = bgR;
43770
43786
  rgba[i * 4 + 1] = bgG;
43771
43787
  rgba[i * 4 + 2] = bgB;
@@ -43783,20 +43799,12 @@ function renderDisplayListToBitmap(displayList, options = {}) {
43783
43799
  let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
43784
43800
  if (operation.kind === "group") {
43785
43801
  const group = operation.value;
43786
- let operations = group.operations;
43787
- if (needsGroupBackdrop(group)) {
43788
- operations = [{ kind: "image", value: {
43789
- name: "GroupBackdrop",
43790
- width,
43791
- height,
43792
- decodedRgba: rgba.slice(),
43793
- matrix: [width / scale, 0, 0, height / scale, originX, pageTop - height / scale],
43794
- colorSpace: "DeviceRGB",
43795
- bitsPerComponent: 8,
43796
- ...group.bboxClip ? { clipPaths: [group.bboxClip] } : {}
43797
- } }, ...operations];
43798
- }
43799
- const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, useCropBox: false, transparent: true });
43802
+ const bitmap = renderDisplayListLayer(
43803
+ { ...displayList, operations: group.operations },
43804
+ { ...options, transparent: true },
43805
+ scale,
43806
+ needsGroupBackdrop(group) ? rgba : void 0
43807
+ );
43800
43808
  for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
43801
43809
  operation = { kind: "image", value: {
43802
43810
  name: "TransparencyGroup",
@@ -43866,7 +43874,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
43866
43874
  if (path.fillColor) {
43867
43875
  const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale, toScreen), true);
43868
43876
  const clipScreen = path.clipRect ? [(path.clipRect[0] - originX) * scale, (pageTop - path.clipRect[3]) * scale, (path.clipRect[2] - originX) * scale, (pageTop - path.clipRect[1]) * scale] : void 0;
43869
- fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
43877
+ fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask, groupAlpha);
43870
43878
  }
43871
43879
  if (path.strokeColor) {
43872
43880
  const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
@@ -43884,7 +43892,8 @@ function renderDisplayListToBitmap(displayList, options = {}) {
43884
43892
  clipScreen,
43885
43893
  original.kind === "glyph" ? aaTxt : aaVec,
43886
43894
  path.blendMode,
43887
- clipMask
43895
+ clipMask,
43896
+ groupAlpha
43888
43897
  );
43889
43898
  }
43890
43899
  } else if (operation.kind === "image") {
@@ -43948,12 +43957,31 @@ function renderDisplayListToBitmap(displayList, options = {}) {
43948
43957
  },
43949
43958
  sample[3] / 255,
43950
43959
  img.blendMode,
43951
- clipMask
43960
+ clipMask,
43961
+ groupAlpha
43952
43962
  );
43953
43963
  }
43954
43964
  }
43955
43965
  }
43956
43966
  }
43967
+ if (backdrop && groupAlpha) {
43968
+ for (let i = 0; i < rgba.length; i += 4) {
43969
+ const alpha = groupAlpha[i / 4];
43970
+ if (alpha === 0) {
43971
+ rgba.fill(0, i, i + 4);
43972
+ continue;
43973
+ }
43974
+ const factor = backdrop[i + 3] / 255 * (1 / alpha - 1);
43975
+ for (let channel = 0; channel < 3; channel++) {
43976
+ const color = rgba[i + channel];
43977
+ rgba[i + channel] = Math.max(0, Math.min(
43978
+ 255,
43979
+ Math.round(color + (color - backdrop[i + channel]) * factor)
43980
+ ));
43981
+ }
43982
+ rgba[i + 3] = Math.round(alpha * 255);
43983
+ }
43984
+ }
43957
43985
  if (deferBackground) {
43958
43986
  for (let i = 0; i < rgba.length; i += 4) {
43959
43987
  const alpha = rgba[i + 3] / 255;
@@ -43963,7 +43991,14 @@ function renderDisplayListToBitmap(displayList, options = {}) {
43963
43991
  rgba[i + 3] = 255;
43964
43992
  }
43965
43993
  }
43966
- let result = { width, height, data: rgba };
43994
+ return { width, height, data: rgba };
43995
+ }
43996
+ function renderDisplayListToBitmap(displayList, options = {}) {
43997
+ const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
43998
+ const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
43999
+ const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
44000
+ let result = renderDisplayListLayer(displayList, options, scaleX);
44001
+ const { width, height, data: rgba } = result;
43967
44002
  if (Math.abs(scaleX - scaleY) > 1e-6) {
43968
44003
  const targetW = Math.max(1, Math.round(displayList.width * scaleX));
43969
44004
  const targetH = Math.max(1, Math.round(displayList.height * scaleY));