@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),
@@ -38631,6 +38647,7 @@ function evaluateContentStreamToDisplayList(params) {
38631
38647
  };
38632
38648
  const initialState = {
38633
38649
  ctm: [1, 0, 0, 1, 0, 0],
38650
+ initialCtm: [1, 0, 0, 1, 0, 0],
38634
38651
  strokeColor: { r: 0, g: 0, b: 0 },
38635
38652
  fillColor: { r: 0, g: 0, b: 0 },
38636
38653
  strokeAlpha: 1,
@@ -38928,6 +38945,116 @@ function evaluateContentStreamToDisplayList(params) {
38928
38945
  ] }], void 0, void 0, resources, activeFonts, depth);
38929
38946
  stateStack.pop();
38930
38947
  };
38948
+ const paintPattern = (segments, fillRule, resources, activeFonts, depth, mcid, actualText) => {
38949
+ const st = curState(), doc = params.cosDoc;
38950
+ if (!st.fillPatternName || !doc || !resources) return false;
38951
+ if (depth >= 8) throw new PdfError("E_LIMIT", "Pattern nesting exceeds the form depth limit");
38952
+ const patterns = doc.resolveDict(dictGet(resources, "Pattern"));
38953
+ const pattern = patterns && doc.resolve(dictGet(patterns, st.fillPatternName));
38954
+ const dict = pattern?.kind === "stream" ? pattern.dict : pattern?.kind === "dict" ? pattern : void 0;
38955
+ if (!dict) return false;
38956
+ const nums = (key, fallback) => {
38957
+ const array = doc.resolveArray(dictGet(dict, key));
38958
+ return array ? array.items.map((item, i) => {
38959
+ const value = doc.resolve(item);
38960
+ return value?.kind === "number" ? value.value : fallback[i] ?? 0;
38961
+ }) : fallback;
38962
+ };
38963
+ let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;
38964
+ const include = (x, y) => {
38965
+ x0 = Math.min(x0, x);
38966
+ y0 = Math.min(y0, y);
38967
+ x1 = Math.max(x1, x);
38968
+ y1 = Math.max(y1, y);
38969
+ };
38970
+ for (const segment of segments) {
38971
+ if (segment.kind === "close") continue;
38972
+ include(segment.x, segment.y);
38973
+ if (segment.kind === "cubic") {
38974
+ include(segment.x1, segment.y1);
38975
+ include(segment.x2, segment.y2);
38976
+ }
38977
+ if (segment.kind === "rect") include(segment.x + segment.width, segment.y + segment.height);
38978
+ }
38979
+ const [originX, originY] = params.origin ?? [0, 0];
38980
+ const clip = st.clipRect ?? [originX, originY, originX + params.width, originY + params.height];
38981
+ const bounds = [Math.max(x0, clip[0]), Math.max(y0, clip[1]), Math.min(x1, clip[2]), Math.min(y1, clip[3])];
38982
+ if (!(bounds[2] > bounds[0] && bounds[3] > bounds[1])) return true;
38983
+ const matrix = multiplyMatrices(nums("Matrix", [1, 0, 0, 1, 0, 0]), st.initialCtm);
38984
+ const type = doc.resolve(dictGet(dict, "PatternType"));
38985
+ stateStack.push({ ...st, clipRect: bounds, clipPaths: [...st.clipPaths ?? [], { segments, fillRule }] });
38986
+ try {
38987
+ if (type?.kind === "number" && type.value === 2) {
38988
+ const shading = doc.resolve(dictGet(dict, "Shading"));
38989
+ const shadingDict = shading?.kind === "stream" ? shading.dict : shading?.kind === "dict" ? shading : void 0;
38990
+ if (!shadingDict) return false;
38991
+ const image = renderShadingDictToImage(
38992
+ doc,
38993
+ shadingDict,
38994
+ matrix,
38995
+ bounds,
38996
+ st.fillAlpha,
38997
+ "PatternShading_" + st.fillPatternName,
38998
+ bounds,
38999
+ shading?.kind === "stream" ? shading : void 0,
39000
+ st.blendMode
39001
+ );
39002
+ if (image) emit({ kind: "image", value: image });
39003
+ return !!image;
39004
+ }
39005
+ if (pattern?.kind !== "stream") return false;
39006
+ const xStepNode = doc.resolve(dictGet(dict, "XStep"));
39007
+ const yStepNode = doc.resolve(dictGet(dict, "YStep"));
39008
+ const xStep = xStepNode?.kind === "number" ? Math.abs(xStepNode.value) : 0;
39009
+ const yStep = yStepNode?.kind === "number" ? Math.abs(yStepNode.value) : 0;
39010
+ const determinant = matrix[0] * matrix[3] - matrix[1] * matrix[2];
39011
+ if (!xStep || !yStep || !determinant) return true;
39012
+ const inverse = [
39013
+ matrix[3] / determinant,
39014
+ -matrix[1] / determinant,
39015
+ -matrix[2] / determinant,
39016
+ matrix[0] / determinant,
39017
+ (matrix[2] * matrix[5] - matrix[3] * matrix[4]) / determinant,
39018
+ (matrix[1] * matrix[4] - matrix[0] * matrix[5]) / determinant
39019
+ ];
39020
+ 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));
39021
+ const box = nums("BBox", [0, 0, xStep, yStep]);
39022
+ const ix0 = Math.floor((Math.min(...corners.map((p) => p[0])) - box[2]) / xStep) + 1;
39023
+ const ix1 = Math.ceil((Math.max(...corners.map((p) => p[0])) - box[0]) / xStep) - 1;
39024
+ const iy0 = Math.floor((Math.min(...corners.map((p) => p[1])) - box[3]) / yStep) + 1;
39025
+ const iy1 = Math.ceil((Math.max(...corners.map((p) => p[1])) - box[1]) / yStep) - 1;
39026
+ if ((ix1 - ix0 + 1) * (iy1 - iy0 + 1) > 2e4) throw new PdfError("E_LIMIT", "Pattern tile count exceeds 20000");
39027
+ const nodes = parseContentStream(doc.decodeStream(pattern));
39028
+ const patternResources = doc.resolveDict(dictGet(dict, "Resources")) ?? resources;
39029
+ const patternFonts = new Map(activeFonts);
39030
+ for (const [key, font] of resolvePageFonts(doc, patternResources)) patternFonts.set(key, font);
39031
+ for (let iy = iy0; iy <= iy1; iy++) {
39032
+ for (let ix = ix0; ix <= ix1; ix++) {
39033
+ const tileCtm = multiplyMatrices([1, 0, 0, 1, ix * xStep, iy * yStep], matrix);
39034
+ 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));
39035
+ const tileClip = [
39036
+ ...points.map(([x, y], i) => ({ kind: i === 0 ? "move" : "line", x, y })),
39037
+ { kind: "close" }
39038
+ ];
39039
+ stateStack.push({
39040
+ ...curState(),
39041
+ fillPatternName: void 0,
39042
+ ctm: tileCtm,
39043
+ initialCtm: tileCtm,
39044
+ clipPaths: [...curState().clipPaths ?? [], tileClip]
39045
+ });
39046
+ try {
39047
+ walkNodes(nodes, mcid, actualText, patternResources, patternFonts, depth + 1);
39048
+ } finally {
39049
+ stateStack.pop();
39050
+ }
39051
+ }
39052
+ }
39053
+ return true;
39054
+ } finally {
39055
+ stateStack.pop();
39056
+ }
39057
+ };
38931
39058
  const paintForm = (form, activeResources, activeFonts, depth, mcid, actualText, maskGroup = false) => {
38932
39059
  const st = curState();
38933
39060
  const group = params.cosDoc.resolveDict(dictGet(form.dict, "Group"));
@@ -38986,7 +39113,7 @@ function evaluateContentStreamToDisplayList(params) {
38986
39113
  }
38987
39114
  const parentOperations = capturedOperations;
38988
39115
  const children = [];
38989
- const nextState = { ...st, ctm: nextCtm };
39116
+ const nextState = { ...st, ctm: nextCtm, initialCtm: nextCtm };
38990
39117
  if (compositeGroup) {
38991
39118
  capturedOperations = children;
38992
39119
  nextState.fillAlpha = nextState.strokeAlpha = 1;
@@ -39144,136 +39271,15 @@ function evaluateContentStreamToDisplayList(params) {
39144
39271
  }
39145
39272
  const isFill = ["f", "F", "f*", "B", "B*", "b", "b*"].includes(node.paint);
39146
39273
  const isStroke = ["S", "s", "B", "B*", "b", "b*"].includes(node.paint);
39147
- let evaluatedFillPattern = false;
39148
- if (isFill && st.fillPatternName && params.cosDoc && activeResources && depth < 6) {
39149
- const patMap = params.cosDoc.resolveDict(dictGet(activeResources, "Pattern"));
39150
- const patNode = patMap ? params.cosDoc.resolve(dictGet(patMap, st.fillPatternName)) : void 0;
39151
- const patDict = patNode?.kind === "stream" ? patNode.dict : patNode?.kind === "dict" ? patNode : void 0;
39152
- const patTypeNode = patDict && params.cosDoc ? params.cosDoc.resolve(dictGet(patDict, "PatternType")) : void 0;
39153
- const patType = patTypeNode?.kind === "number" ? patTypeNode.value : patNode?.kind === "stream" ? 1 : 0;
39154
- if (patDict && patType === 2 && params.cosDoc) {
39155
- let pMinX = Infinity, pMinY = Infinity, pMaxX = -Infinity, pMaxY = -Infinity;
39156
- for (const s of transformedSegments) {
39157
- if (s.kind === "move" || s.kind === "line") {
39158
- pMinX = Math.min(pMinX, s.x);
39159
- pMinY = Math.min(pMinY, s.y);
39160
- pMaxX = Math.max(pMaxX, s.x);
39161
- pMaxY = Math.max(pMaxY, s.y);
39162
- } else if (s.kind === "cubic") {
39163
- pMinX = Math.min(pMinX, s.x1, s.x2, s.x);
39164
- pMinY = Math.min(pMinY, s.y1, s.y2, s.y);
39165
- pMaxX = Math.max(pMaxX, s.x1, s.x2, s.x);
39166
- pMaxY = Math.max(pMaxY, s.y1, s.y2, s.y);
39167
- } else if (s.kind === "rect") {
39168
- pMinX = Math.min(pMinX, s.x);
39169
- pMinY = Math.min(pMinY, s.y);
39170
- pMaxX = Math.max(pMaxX, s.x + s.width);
39171
- pMaxY = Math.max(pMaxY, s.y + s.height);
39172
- }
39173
- }
39174
- if (Number.isFinite(pMinX) && Number.isFinite(pMinY) && pMaxX > pMinX && pMaxY > pMinY) {
39175
- const shading = params.cosDoc.resolve(dictGet(patDict, "Shading"));
39176
- const shDict = shading?.kind === "stream" ? shading.dict : shading?.kind === "dict" ? shading : void 0;
39177
- if (shDict) {
39178
- let patMatrix = [1, 0, 0, 1, 0, 0];
39179
- const pmArr = params.cosDoc.resolveArray(dictGet(patDict, "Matrix"));
39180
- if (pmArr && pmArr.items.length >= 6) {
39181
- const mn = (idx, fb = 0) => {
39182
- const r = params.cosDoc.resolve(pmArr.items[idx]);
39183
- return r?.kind === "number" ? r.value : fb;
39184
- };
39185
- patMatrix = [mn(0, 1), mn(1, 0), mn(2, 0), mn(3, 1), mn(4, 0), mn(5, 0)];
39186
- }
39187
- const patClip = st.clipRect ? [
39188
- Math.max(st.clipRect[0], pMinX),
39189
- Math.max(st.clipRect[1], pMinY),
39190
- Math.min(st.clipRect[2], pMaxX),
39191
- Math.min(st.clipRect[3], pMaxY)
39192
- ] : [pMinX, pMinY, pMaxX, pMaxY];
39193
- const shImg = renderShadingDictToImage(
39194
- params.cosDoc,
39195
- shDict,
39196
- patMatrix,
39197
- patClip,
39198
- st.fillAlpha,
39199
- "PatternShading_" + st.fillPatternName,
39200
- patClip,
39201
- shading?.kind === "stream" ? shading : void 0,
39202
- st.blendMode
39203
- );
39204
- if (shImg) {
39205
- emit({ kind: "image", value: shImg });
39206
- evaluatedFillPattern = true;
39207
- }
39208
- }
39209
- }
39210
- } else if (patNode?.kind === "stream") {
39211
- let pMinX = Infinity, pMinY = Infinity, pMaxX = -Infinity, pMaxY = -Infinity;
39212
- for (const s of transformedSegments) {
39213
- if (s.kind === "move" || s.kind === "line") {
39214
- pMinX = Math.min(pMinX, s.x);
39215
- pMinY = Math.min(pMinY, s.y);
39216
- pMaxX = Math.max(pMaxX, s.x);
39217
- pMaxY = Math.max(pMaxY, s.y);
39218
- } else if (s.kind === "cubic") {
39219
- pMinX = Math.min(pMinX, s.x1, s.x2, s.x);
39220
- pMinY = Math.min(pMinY, s.y1, s.y2, s.y);
39221
- pMaxX = Math.max(pMaxX, s.x1, s.x2, s.x);
39222
- pMaxY = Math.max(pMaxY, s.y1, s.y2, s.y);
39223
- } else if (s.kind === "rect") {
39224
- pMinX = Math.min(pMinX, s.x);
39225
- pMinY = Math.min(pMinY, s.y);
39226
- pMaxX = Math.max(pMaxX, s.x + s.width);
39227
- pMaxY = Math.max(pMaxY, s.y + s.height);
39228
- }
39229
- }
39230
- if (Number.isFinite(pMinX) && Number.isFinite(pMinY) && pMaxX > pMinX && pMaxY > pMinY) {
39231
- const xsNode = params.cosDoc.resolve(dictGet(patNode.dict, "XStep"));
39232
- const ysNode = params.cosDoc.resolve(dictGet(patNode.dict, "YStep"));
39233
- const xStep = xsNode?.kind === "number" && Math.abs(xsNode.value) > 1e-3 ? Math.abs(xsNode.value) : 40;
39234
- const yStep = ysNode?.kind === "number" && Math.abs(ysNode.value) > 1e-3 ? Math.abs(ysNode.value) : 40;
39235
- let patMatrix = [1, 0, 0, 1, 0, 0];
39236
- const pmArr = params.cosDoc.resolveArray(dictGet(patNode.dict, "Matrix"));
39237
- if (pmArr && pmArr.items.length >= 6) {
39238
- const mn = (idx, fb = 0) => {
39239
- const r = params.cosDoc.resolve(pmArr.items[idx]);
39240
- return r?.kind === "number" ? r.value : fb;
39241
- };
39242
- patMatrix = [mn(0, 1), mn(1, 0), mn(2, 0), mn(3, 1), mn(4, 0), mn(5, 0)];
39243
- }
39244
- const tileClip = st.clipRect ? [
39245
- Math.max(st.clipRect[0], pMinX),
39246
- Math.max(st.clipRect[1], pMinY),
39247
- Math.min(st.clipRect[2], pMaxX),
39248
- Math.min(st.clipRect[3], pMaxY)
39249
- ] : [pMinX, pMinY, pMaxX, pMaxY];
39250
- const patNodes = parseContentStream(params.cosDoc.decodeStream(patNode));
39251
- const patResDict = params.cosDoc.resolveDict(dictGet(patNode.dict, "Resources")) ?? activeResources;
39252
- const patFonts = new Map(activeFonts);
39253
- for (const [fk, fv] of resolvePageFonts(params.cosDoc, patResDict).entries()) {
39254
- patFonts.set(fk, fv);
39255
- }
39256
- const ixStart = Math.floor(pMinX / xStep);
39257
- const ixEnd = Math.min(ixStart + 8, Math.ceil(pMaxX / xStep) - 1);
39258
- const iyStart = Math.floor(pMinY / yStep);
39259
- const iyEnd = Math.min(iyStart + 8, Math.ceil(pMaxY / yStep) - 1);
39260
- for (let iy = iyStart; iy <= iyEnd; iy++) {
39261
- for (let ix = ixStart; ix <= ixEnd; ix++) {
39262
- const tileCtm = multiplyMatrices([1, 0, 0, 1, ix * xStep, iy * yStep], patMatrix);
39263
- stateStack.push({
39264
- ...st,
39265
- fillPatternName: void 0,
39266
- ctm: tileCtm,
39267
- clipRect: tileClip
39268
- });
39269
- walkNodes(patNodes, mcid, actualText, patResDict, patFonts, depth + 1);
39270
- if (stateStack.length > 1) stateStack.pop();
39271
- }
39272
- }
39273
- evaluatedFillPattern = true;
39274
- }
39275
- }
39276
- }
39274
+ const evaluatedFillPattern = isFill && paintPattern(
39275
+ transformedSegments,
39276
+ node.paint.includes("*") ? "evenodd" : "nonzero",
39277
+ activeResources,
39278
+ activeFonts,
39279
+ depth,
39280
+ mcid,
39281
+ actualText
39282
+ );
39277
39283
  if (evaluatedFillPattern && !isStroke) {
39278
39284
  applyClip();
39279
39285
  break;
@@ -39474,10 +39480,19 @@ function evaluateContentStreamToDisplayList(params) {
39474
39480
  if (st.textRenderMode >= 4 && st.textRenderMode <= 7) pendingTextClip.push(...transformedGlyphSegs);
39475
39481
  const isFillGlyph = st.textRenderMode === 0 || st.textRenderMode === 2 || st.textRenderMode === 4 || st.textRenderMode === 6;
39476
39482
  const isStrokeGlyph = st.textRenderMode === 1 || st.textRenderMode === 2 || st.textRenderMode === 5 || st.textRenderMode === 6;
39483
+ const patterned = isFillGlyph && paintPattern(
39484
+ transformedGlyphSegs,
39485
+ "nonzero",
39486
+ activeResources,
39487
+ activeFonts,
39488
+ depth,
39489
+ mcid,
39490
+ actualText
39491
+ );
39477
39492
  const paint = {
39478
39493
  segments: transformedGlyphSegs,
39479
- fillColor: isFillGlyph ? st.fillColor : void 0,
39480
- fillAlpha: isFillGlyph ? st.fillAlpha : void 0,
39494
+ fillColor: isFillGlyph && !patterned ? st.fillColor : void 0,
39495
+ fillAlpha: isFillGlyph && !patterned ? st.fillAlpha : void 0,
39481
39496
  strokeColor: isStrokeGlyph ? st.strokeColor : void 0,
39482
39497
  strokeAlpha: isStrokeGlyph ? st.strokeAlpha : void 0,
39483
39498
  strokeWidth: isStrokeGlyph ? st.strokeWidth : 0,
@@ -43117,10 +43132,14 @@ function computePdfBlendRgb(cbR, cbG, cbB, csR, csG, csB, mode) {
43117
43132
  blendChannelSeparable(cbB, csB, mode)
43118
43133
  ];
43119
43134
  }
43120
- function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMask) {
43135
+ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMask, groupAlpha) {
43121
43136
  if (px < 0 || py < 0 || px >= width || py >= height || alpha <= 0) return;
43122
43137
  const a = Math.min(1, Math.max(0, alpha)) * (clipMask ? clipMask[(py * width + px) * 4 + 3] / 255 : 1);
43123
43138
  const idx = (py * width + px) * 4;
43139
+ if (groupAlpha) {
43140
+ const pixel = py * width + px;
43141
+ groupAlpha[pixel] = a + groupAlpha[pixel] * (1 - a);
43142
+ }
43124
43143
  const csR = Math.min(1, Math.max(0, color.r));
43125
43144
  const csG = Math.min(1, Math.max(0, color.g));
43126
43145
  const csB = Math.min(1, Math.max(0, color.b));
@@ -43252,7 +43271,7 @@ function pathsToEdges(paths, closeSubpaths = false) {
43252
43271
  }
43253
43272
  return edges;
43254
43273
  }
43255
- function fillEdgesScanline4x4(rgba, width, height, edges, color, alpha = 1, fillRule = "nonzero", clipScreen, antialias = true, blendMode, clipMask) {
43274
+ function fillEdgesScanline4x4(rgba, width, height, edges, color, alpha = 1, fillRule = "nonzero", clipScreen, antialias = true, blendMode, clipMask, groupAlpha) {
43256
43275
  if (edges.length === 0) return;
43257
43276
  let minY = Infinity;
43258
43277
  let maxY = -Infinity;
@@ -43318,7 +43337,7 @@ function fillEdgesScanline4x4(rgba, width, height, edges, color, alpha = 1, fill
43318
43337
  const count = rowCounts[px];
43319
43338
  if (count > 0) {
43320
43339
  const cov = antialias ? count / 16 : count >= 8 ? 1 : 0;
43321
- blendPixel(rgba, width, height, px, py, color, cov * alpha, blendMode, clipMask);
43340
+ blendPixel(rgba, width, height, px, py, color, cov * alpha, blendMode, clipMask, groupAlpha);
43322
43341
  }
43323
43342
  }
43324
43343
  }
@@ -43397,22 +43416,19 @@ function hasCompositingEffects(operations, includeSoftMasks = false) {
43397
43416
  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));
43398
43417
  }
43399
43418
  function needsGroupBackdrop(group) {
43400
- return group.isolated === false && !!group.softMask && hasCompositingEffects(group.operations, true);
43419
+ return group.isolated === false && hasCompositingEffects(group.operations, true);
43401
43420
  }
43402
43421
  function containsBackdropGroup(operations) {
43403
43422
  return operations.some((operation) => operation.kind === "group" && (needsGroupBackdrop(operation.value) || containsBackdropGroup(operation.value.operations)));
43404
43423
  }
43405
- function renderDisplayListToBitmap(displayList, options = {}) {
43406
- const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
43407
- const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
43408
- const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
43409
- const scale = scaleX;
43424
+ function renderDisplayListLayer(displayList, options, scale, backdrop) {
43410
43425
  const [originX, originY] = displayList.origin ?? [0, 0];
43411
43426
  const pageTop = originY + displayList.height;
43412
43427
  const toScreen = (x, y) => [(x - originX) * scale, (pageTop - y) * scale];
43413
43428
  const width = Math.max(1, Math.round(displayList.width * scale));
43414
43429
  const height = Math.max(1, Math.round(displayList.height * scale));
43415
- const rgba = new Uint8Array(width * height * 4);
43430
+ const rgba = backdrop ? backdrop.slice() : new Uint8Array(width * height * 4);
43431
+ const groupAlpha = backdrop ? new Float32Array(width * height) : void 0;
43416
43432
  const deferBackground = !options.transparent && hasCompositingEffects(paintOperations(displayList));
43417
43433
  const transparent = options.transparent || deferBackground;
43418
43434
  const bg = options.background ?? { r: 1, g: 1, b: 1 };
@@ -43420,7 +43436,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
43420
43436
  const bgG = transparent ? 0 : Math.round(bg.g * 255);
43421
43437
  const bgB = transparent ? 0 : Math.round(bg.b * 255);
43422
43438
  const bgA = transparent ? 0 : 255;
43423
- for (let i = 0; i < width * height; i++) {
43439
+ for (let i = 0; !backdrop && i < width * height; i++) {
43424
43440
  rgba[i * 4] = bgR;
43425
43441
  rgba[i * 4 + 1] = bgG;
43426
43442
  rgba[i * 4 + 2] = bgB;
@@ -43438,20 +43454,12 @@ function renderDisplayListToBitmap(displayList, options = {}) {
43438
43454
  let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
43439
43455
  if (operation.kind === "group") {
43440
43456
  const group = operation.value;
43441
- let operations = group.operations;
43442
- if (needsGroupBackdrop(group)) {
43443
- operations = [{ kind: "image", value: {
43444
- name: "GroupBackdrop",
43445
- width,
43446
- height,
43447
- decodedRgba: rgba.slice(),
43448
- matrix: [width / scale, 0, 0, height / scale, originX, pageTop - height / scale],
43449
- colorSpace: "DeviceRGB",
43450
- bitsPerComponent: 8,
43451
- ...group.bboxClip ? { clipPaths: [group.bboxClip] } : {}
43452
- } }, ...operations];
43453
- }
43454
- const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, useCropBox: false, transparent: true });
43457
+ const bitmap = renderDisplayListLayer(
43458
+ { ...displayList, operations: group.operations },
43459
+ { ...options, transparent: true },
43460
+ scale,
43461
+ needsGroupBackdrop(group) ? rgba : void 0
43462
+ );
43455
43463
  for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
43456
43464
  operation = { kind: "image", value: {
43457
43465
  name: "TransparencyGroup",
@@ -43521,7 +43529,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
43521
43529
  if (path.fillColor) {
43522
43530
  const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale, toScreen), true);
43523
43531
  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;
43524
- fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
43532
+ fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask, groupAlpha);
43525
43533
  }
43526
43534
  if (path.strokeColor) {
43527
43535
  const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
@@ -43539,7 +43547,8 @@ function renderDisplayListToBitmap(displayList, options = {}) {
43539
43547
  clipScreen,
43540
43548
  original.kind === "glyph" ? aaTxt : aaVec,
43541
43549
  path.blendMode,
43542
- clipMask
43550
+ clipMask,
43551
+ groupAlpha
43543
43552
  );
43544
43553
  }
43545
43554
  } else if (operation.kind === "image") {
@@ -43603,12 +43612,31 @@ function renderDisplayListToBitmap(displayList, options = {}) {
43603
43612
  },
43604
43613
  sample[3] / 255,
43605
43614
  img.blendMode,
43606
- clipMask
43615
+ clipMask,
43616
+ groupAlpha
43607
43617
  );
43608
43618
  }
43609
43619
  }
43610
43620
  }
43611
43621
  }
43622
+ if (backdrop && groupAlpha) {
43623
+ for (let i = 0; i < rgba.length; i += 4) {
43624
+ const alpha = groupAlpha[i / 4];
43625
+ if (alpha === 0) {
43626
+ rgba.fill(0, i, i + 4);
43627
+ continue;
43628
+ }
43629
+ const factor = backdrop[i + 3] / 255 * (1 / alpha - 1);
43630
+ for (let channel = 0; channel < 3; channel++) {
43631
+ const color = rgba[i + channel];
43632
+ rgba[i + channel] = Math.max(0, Math.min(
43633
+ 255,
43634
+ Math.round(color + (color - backdrop[i + channel]) * factor)
43635
+ ));
43636
+ }
43637
+ rgba[i + 3] = Math.round(alpha * 255);
43638
+ }
43639
+ }
43612
43640
  if (deferBackground) {
43613
43641
  for (let i = 0; i < rgba.length; i += 4) {
43614
43642
  const alpha = rgba[i + 3] / 255;
@@ -43618,7 +43646,14 @@ function renderDisplayListToBitmap(displayList, options = {}) {
43618
43646
  rgba[i + 3] = 255;
43619
43647
  }
43620
43648
  }
43621
- let result = { width, height, data: rgba };
43649
+ return { width, height, data: rgba };
43650
+ }
43651
+ function renderDisplayListToBitmap(displayList, options = {}) {
43652
+ const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
43653
+ const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
43654
+ const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
43655
+ let result = renderDisplayListLayer(displayList, options, scaleX);
43656
+ const { width, height, data: rgba } = result;
43622
43657
  if (Math.abs(scaleX - scaleY) > 1e-6) {
43623
43658
  const targetW = Math.max(1, Math.round(displayList.width * scaleX));
43624
43659
  const targetH = Math.max(1, Math.round(displayList.height * scaleY));