@poe-platform/safe-bash 0.1.772 → 0.1.774

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.
Files changed (45) hide show
  1. package/dist/image-ast/index.browser.js +3543 -706
  2. package/dist/image-ast/index.js +3543 -706
  3. package/dist/pdf-ast/ast.d.ts +7 -0
  4. package/dist/pdf-ast/content/evaluator.d.ts +1 -0
  5. package/dist/pdf-ast/index.js +3587 -718
  6. package/dist/pdf-ast/render/raster.d.ts +1 -0
  7. package/dist/pdf-ast/vendor/pdfjs-fonts.d.mts +36 -0
  8. package/dist/pdf-ast/vendor/pdfjs-fonts.mjs +3323 -0
  9. package/dist/safe-bash/command-chunks/{chunk-M2XU2YCK.js → chunk-4ZHDCMQX.js} +2 -2
  10. package/dist/safe-bash/command-chunks/{chunk-NBENXODJ.js → chunk-HH5QPKIN.js} +1 -1
  11. package/dist/safe-bash/command-chunks/{chunk-C4AAJTXF.js → chunk-PM63UJE6.js} +3546 -706
  12. package/dist/safe-bash/core.browser.js +101 -45
  13. package/dist/safe-bash/core.d.ts +1 -1
  14. package/dist/safe-bash/plugins/composition.d.ts +2 -0
  15. package/dist/safe-bash/plugins/composition.js +2 -1
  16. package/dist/safe-bash/shell/runtime.js +17 -9
  17. package/dist/safe-bash/shell/sync-posix-regex.d.ts +3 -0
  18. package/dist/safe-bash/shell/sync-posix-regex.js +48 -0
  19. package/dist/safe-bash-command-ffmpeg/index.js +11032 -9579
  20. package/dist/safe-bash-command-gh/index.d.ts +1 -0
  21. package/dist/safe-bash-command-gh/index.js +43 -13
  22. package/dist/safe-bash-command-gh/types.d.ts +1 -0
  23. package/dist/safe-bash-command-git/git_rust.wasm +0 -0
  24. package/dist/safe-bash-command-git/index.js +22 -15
  25. package/dist/safe-bash-command-git/wasm.generated.js +1 -1
  26. package/dist/safe-bash-command-gpg/index.js +28 -7
  27. package/dist/safe-bash-command-imagemagick/index.js +2 -2
  28. package/dist/safe-bash-command-openssl/index.js +24 -6
  29. package/dist/safe-bash-command-pandoc/command.js +3 -3
  30. package/dist/safe-bash-command-pandoc/index.js +3 -3
  31. package/dist/safe-bash-command-pdfimages/index.js +3542 -660
  32. package/dist/safe-bash-command-pdfinfo/index.js +3584 -718
  33. package/dist/safe-bash-command-pdftk/index.js +3542 -660
  34. package/dist/safe-bash-command-pdftoppm/index.js +3589 -787
  35. package/dist/safe-bash-command-pdftotext/index.js +3542 -660
  36. package/dist/safe-bash-command-qpdf/index.js +3542 -660
  37. package/dist/safe-bash-command-sips/index.js +2 -2
  38. package/dist/safe-bash-command-soffice/index.js +1 -1
  39. package/dist/safe-bash-command-ssconvert/index.js +3553 -716
  40. package/dist/safe-bash-command-ssh/index.js +124 -23
  41. package/dist/safe-bash-command-wkhtmltopdf/index.js +3581 -660
  42. package/dist/safe-bash-mcp/index.d.ts +8 -2
  43. package/dist/safe-bash-mcp/index.js +13 -6
  44. package/package.json +7 -7
  45. package/third-party/pdf-ast/THIRD_PARTY_NOTICES.md +84 -1
@@ -148,6 +148,11 @@ var FONT_IDENTITY_MATRIX = [1e-3, 0, 0, 1e-3, 0, 0];
148
148
  var LINE_FACTOR = 1.35;
149
149
  var LINE_DESCENT_FACTOR = 0.35;
150
150
  var BASELINE_FACTOR = LINE_DESCENT_FACTOR / LINE_FACTOR;
151
+ var MeshFigureType = {
152
+ TRIANGLES: 1,
153
+ LATTICE: 2,
154
+ PATCH: 3
155
+ };
151
156
  var VerbosityLevel = {
152
157
  ERRORS: 0,
153
158
  WARNINGS: 1,
@@ -19072,6 +19077,3308 @@ var getFontBasicMetrics = getLookupTableFactory(function(t) {
19072
19077
  xHeight: Math.NaN
19073
19078
  };
19074
19079
  });
19080
+ function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
19081
+ const COMPONENTS = 3;
19082
+ alpha01 = alpha01 !== 1 ? 0 : alpha01;
19083
+ const xRatio = w1 / w2;
19084
+ const yRatio = h1 / h2;
19085
+ let newIndex = 0, oldIndex;
19086
+ const xScaled = new Uint16Array(w2);
19087
+ const w1Scanline = w1 * COMPONENTS;
19088
+ for (let i = 0; i < w2; i++) {
19089
+ xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
19090
+ }
19091
+ for (let i = 0; i < h2; i++) {
19092
+ const py = Math.floor(i * yRatio) * w1Scanline;
19093
+ for (let j = 0; j < w2; j++) {
19094
+ oldIndex = py + xScaled[j];
19095
+ dest[newIndex++] = src[oldIndex++];
19096
+ dest[newIndex++] = src[oldIndex++];
19097
+ dest[newIndex++] = src[oldIndex++];
19098
+ newIndex += alpha01;
19099
+ }
19100
+ }
19101
+ }
19102
+ function isDefaultDecodeHelper(decode, expectedLen) {
19103
+ if (!Array.isArray(decode)) {
19104
+ return true;
19105
+ }
19106
+ const decodeLen = decode.length;
19107
+ if (decodeLen < expectedLen) {
19108
+ warn2("Decode map length is too short.");
19109
+ return true;
19110
+ }
19111
+ if (decodeLen > expectedLen) {
19112
+ info("Truncating too long decode map.");
19113
+ decode.length = expectedLen;
19114
+ }
19115
+ return false;
19116
+ }
19117
+ var ColorSpace = class _ColorSpace {
19118
+ static #rgbBuf = new Uint8ClampedArray(3);
19119
+ constructor(name, numComps) {
19120
+ if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _ColorSpace) {
19121
+ unreachable2("Cannot initialize ColorSpace.");
19122
+ }
19123
+ this.name = name;
19124
+ this.numComps = numComps;
19125
+ }
19126
+ /**
19127
+ * Converts the color value to the RGB color. The color components are
19128
+ * located in the src array starting from the srcOffset. Returns the array
19129
+ * of the rgb components, each value ranging from [0,255].
19130
+ */
19131
+ getRgb(src, srcOffset, output = new Uint8ClampedArray(3)) {
19132
+ this.getRgbItem(src, srcOffset, output, 0);
19133
+ return output;
19134
+ }
19135
+ getRgbHex(src, srcOffset) {
19136
+ const buffer = this.getRgb(src, srcOffset, _ColorSpace.#rgbBuf);
19137
+ return Util.makeHexColor(buffer[0], buffer[1], buffer[2]);
19138
+ }
19139
+ /**
19140
+ * Converts the color value to the RGB color, similar to the getRgb method.
19141
+ * The result placed into the dest array starting from the destOffset.
19142
+ */
19143
+ getRgbItem(src, srcOffset, dest, destOffset) {
19144
+ unreachable2("Should not call ColorSpace.getRgbItem");
19145
+ }
19146
+ /**
19147
+ * Converts the specified number of the color values to the RGB colors.
19148
+ * The colors are located in the src array starting from the srcOffset.
19149
+ * The result is placed into the dest array starting from the destOffset.
19150
+ * The src array items shall be in [0,2^bits) range, the dest array items
19151
+ * will be in [0,255] range. alpha01 indicates how many alpha components
19152
+ * there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
19153
+ * array).
19154
+ */
19155
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
19156
+ unreachable2("Should not call ColorSpace.getRgbBuffer");
19157
+ }
19158
+ /**
19159
+ * Converts `count` unscaled colors to RGB, starting at `destOffset`.
19160
+ * Components use the native color-space ranges expected by `getRgbItem`,
19161
+ * and each output has a `3 + alpha01` byte stride.
19162
+ * Subclasses may override this to batch expensive conversions.
19163
+ */
19164
+ getRgbItems(src, count, dest, destOffset, alpha01) {
19165
+ const { numComps } = this;
19166
+ for (let i = 0, srcOffset = 0; i < count; i++, srcOffset += numComps) {
19167
+ this.getRgbItem(src, srcOffset, dest, destOffset);
19168
+ destOffset += 3 + alpha01;
19169
+ }
19170
+ }
19171
+ /**
19172
+ * Returns true if source data will be equal the result/output data.
19173
+ */
19174
+ isPassthrough(bits) {
19175
+ return false;
19176
+ }
19177
+ /**
19178
+ * Refer to the static `ColorSpace.isDefaultDecode` method below.
19179
+ */
19180
+ isDefaultDecode(decode, bpc) {
19181
+ return _ColorSpace.isDefaultDecode(decode, this.numComps);
19182
+ }
19183
+ /**
19184
+ * Fills in the RGB colors in the destination buffer. alpha01 indicates
19185
+ * how many alpha components there are in the dest array; it will be either
19186
+ * 0 (RGB array) or 1 (RGBA array).
19187
+ */
19188
+ fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {
19189
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19190
+ assert2(
19191
+ dest instanceof Uint8ClampedArray,
19192
+ 'ColorSpace.fillRgb: Unsupported "dest" type.'
19193
+ );
19194
+ }
19195
+ const count = originalWidth * originalHeight;
19196
+ let rgbBuf = null;
19197
+ const numComponentColors = 1 << bpc;
19198
+ const needsResizing = originalHeight !== height || originalWidth !== width;
19199
+ if (this.isPassthrough(bpc)) {
19200
+ rgbBuf = comps;
19201
+ } else if (this.numComps === 1 && count > numComponentColors && this.name !== "DeviceGray" && this.name !== "DeviceRGB") {
19202
+ const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);
19203
+ for (let i = 0; i < numComponentColors; i++) {
19204
+ allColors[i] = i;
19205
+ }
19206
+ const colorMap = new Uint8ClampedArray(numComponentColors * 3);
19207
+ this.getRgbBuffer(
19208
+ allColors,
19209
+ 0,
19210
+ numComponentColors,
19211
+ colorMap,
19212
+ 0,
19213
+ bpc,
19214
+ /* alpha01 = */
19215
+ 0
19216
+ );
19217
+ if (!needsResizing) {
19218
+ let destPos = 0;
19219
+ for (let i = 0; i < count; ++i) {
19220
+ const key = comps[i] * 3;
19221
+ dest[destPos++] = colorMap[key];
19222
+ dest[destPos++] = colorMap[key + 1];
19223
+ dest[destPos++] = colorMap[key + 2];
19224
+ destPos += alpha01;
19225
+ }
19226
+ } else {
19227
+ rgbBuf = new Uint8Array(count * 3);
19228
+ let rgbPos = 0;
19229
+ for (let i = 0; i < count; ++i) {
19230
+ const key = comps[i] * 3;
19231
+ rgbBuf[rgbPos++] = colorMap[key];
19232
+ rgbBuf[rgbPos++] = colorMap[key + 1];
19233
+ rgbBuf[rgbPos++] = colorMap[key + 2];
19234
+ }
19235
+ }
19236
+ } else if (!needsResizing) {
19237
+ this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);
19238
+ } else {
19239
+ rgbBuf = new Uint8ClampedArray(count * 3);
19240
+ this.getRgbBuffer(
19241
+ comps,
19242
+ 0,
19243
+ count,
19244
+ rgbBuf,
19245
+ 0,
19246
+ bpc,
19247
+ /* alpha01 = */
19248
+ 0
19249
+ );
19250
+ }
19251
+ if (rgbBuf) {
19252
+ if (needsResizing) {
19253
+ resizeRgbImage(
19254
+ rgbBuf,
19255
+ dest,
19256
+ originalWidth,
19257
+ originalHeight,
19258
+ width,
19259
+ height,
19260
+ alpha01
19261
+ );
19262
+ } else {
19263
+ let destPos = 0, rgbPos = 0;
19264
+ for (let i = 0, ii = width * actualHeight; i < ii; i++) {
19265
+ dest[destPos++] = rgbBuf[rgbPos++];
19266
+ dest[destPos++] = rgbBuf[rgbPos++];
19267
+ dest[destPos++] = rgbBuf[rgbPos++];
19268
+ destPos += alpha01;
19269
+ }
19270
+ }
19271
+ }
19272
+ }
19273
+ /**
19274
+ * True if the colorspace has components in the default range of [0, 1].
19275
+ * This should be true for all colorspaces except for lab color spaces
19276
+ * which are [0,100], [-128, 127], [-128, 127].
19277
+ */
19278
+ get usesZeroToOneRange() {
19279
+ return shadow2(this, "usesZeroToOneRange", true);
19280
+ }
19281
+ /**
19282
+ * Checks if a decode map matches the default decode map for a color space.
19283
+ * This handles the general decode maps where there are two values per
19284
+ * component, e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
19285
+ * This does not handle Lab, Indexed, or Pattern decode maps since they are
19286
+ * slightly different.
19287
+ * @param {Array} decode - Decode map (usually from an image).
19288
+ * @param {number} numComps - Number of components the color space has.
19289
+ */
19290
+ static isDefaultDecode(decode, numComps) {
19291
+ if (isDefaultDecodeHelper(decode, numComps * 2)) {
19292
+ return true;
19293
+ }
19294
+ for (let i = 0, ii = decode.length; i < ii; i += 2) {
19295
+ if (decode[i] !== 0 || decode[i + 1] !== 1) {
19296
+ return false;
19297
+ }
19298
+ }
19299
+ return true;
19300
+ }
19301
+ };
19302
+ var DeviceCmykCS = class extends ColorSpace {
19303
+ constructor() {
19304
+ super("DeviceCMYK", 4);
19305
+ }
19306
+ // The coefficients below was found using numerical analysis: the method of
19307
+ // steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
19308
+ // where color_value is the tabular value from the table of sampled RGB colors
19309
+ // from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
19310
+ // CMYK color conversion using the estimation below:
19311
+ // f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
19312
+ #toRgb(src, srcOffset, srcScale, dest, destOffset) {
19313
+ const c = src[srcOffset] * srcScale;
19314
+ const m = src[srcOffset + 1] * srcScale;
19315
+ const y = src[srcOffset + 2] * srcScale;
19316
+ const k = src[srcOffset + 3] * srcScale;
19317
+ dest[destOffset] = 255 + c * (-4.387332384609988 * c + 54.48615194189176 * m + 18.82290502165302 * y + 212.25662451639585 * k + -285.2331026137004) + m * (1.7149763477362134 * m - 5.6096736904047315 * y + -17.873870861415444 * k - 5.497006427196366) + y * (-2.5217340131683033 * y - 21.248923337353073 * k + 17.5119270841813) + k * (-21.86122147463605 * k - 189.48180835922747);
19318
+ dest[destOffset + 1] = 255 + c * (8.841041422036149 * c + 60.118027045597366 * m + 6.871425592049007 * y + 31.159100130055922 * k + -79.2970844816548) + m * (-15.310361306967817 * m + 17.575251261109482 * y + 131.35250912493976 * k - 190.9453302588951) + y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) + k * (-20.737325471181034 * k - 187.80453709719578);
19319
+ dest[destOffset + 2] = 255 + c * (0.8842522430003296 * c + 8.078677503112928 * m + 30.89978309703729 * y - 0.23883238689178934 * k + -14.183576799673286) + m * (10.49593273432072 * m + 63.02378494754052 * y + 50.606957656360734 * k - 112.23884253719248) + y * (0.03296041114873217 * y + 115.60384449646641 * k + -193.58209356861505) + k * (-22.33816807309886 * k - 180.12613974708367);
19320
+ }
19321
+ getRgbItem(src, srcOffset, dest, destOffset) {
19322
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19323
+ assert2(
19324
+ dest instanceof Uint8ClampedArray,
19325
+ 'DeviceCmykCS.getRgbItem: Unsupported "dest" type.'
19326
+ );
19327
+ }
19328
+ this.#toRgb(src, srcOffset, 1, dest, destOffset);
19329
+ }
19330
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
19331
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19332
+ assert2(
19333
+ dest instanceof Uint8ClampedArray,
19334
+ 'DeviceCmykCS.getRgbBuffer: Unsupported "dest" type.'
19335
+ );
19336
+ }
19337
+ const scale = 1 / ((1 << bits) - 1);
19338
+ for (let i = 0; i < count; i++) {
19339
+ this.#toRgb(src, srcOffset, scale, dest, destOffset);
19340
+ srcOffset += 4;
19341
+ destOffset += 3 + alpha01;
19342
+ }
19343
+ }
19344
+ };
19345
+ var CalGrayCS = class extends ColorSpace {
19346
+ constructor(whitePoint, blackPoint, gamma) {
19347
+ super("CalGray", 1);
19348
+ if (!whitePoint) {
19349
+ throw new FormatError(
19350
+ "WhitePoint missing - required for color space CalGray"
19351
+ );
19352
+ }
19353
+ [this.XW, this.YW, this.ZW] = whitePoint;
19354
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
19355
+ this.G = gamma || 1;
19356
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
19357
+ throw new FormatError(
19358
+ `Invalid WhitePoint components for ${this.name}, no fallback available`
19359
+ );
19360
+ }
19361
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
19362
+ info(`Invalid BlackPoint for ${this.name}, falling back to default.`);
19363
+ this.XB = this.YB = this.ZB = 0;
19364
+ }
19365
+ if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
19366
+ warn2(
19367
+ `${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ZB: ${this.ZB}, only default values are supported.`
19368
+ );
19369
+ }
19370
+ if (this.G < 1) {
19371
+ info(
19372
+ `Invalid Gamma: ${this.G} for ${this.name}, falling back to default.`
19373
+ );
19374
+ this.G = 1;
19375
+ }
19376
+ }
19377
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
19378
+ const A = src[srcOffset] * scale;
19379
+ const AG = A ** this.G;
19380
+ const L = this.YW * AG;
19381
+ const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0);
19382
+ dest[destOffset] = val;
19383
+ dest[destOffset + 1] = val;
19384
+ dest[destOffset + 2] = val;
19385
+ }
19386
+ getRgbItem(src, srcOffset, dest, destOffset) {
19387
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19388
+ assert2(
19389
+ dest instanceof Uint8ClampedArray,
19390
+ 'CalGrayCS.getRgbItem: Unsupported "dest" type.'
19391
+ );
19392
+ }
19393
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
19394
+ }
19395
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
19396
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19397
+ assert2(
19398
+ dest instanceof Uint8ClampedArray,
19399
+ 'CalGrayCS.getRgbBuffer: Unsupported "dest" type.'
19400
+ );
19401
+ }
19402
+ const scale = 1 / ((1 << bits) - 1);
19403
+ for (let i = 0; i < count; ++i) {
19404
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
19405
+ srcOffset += 1;
19406
+ destOffset += 3 + alpha01;
19407
+ }
19408
+ }
19409
+ };
19410
+ var CalRGBCS = class _CalRGBCS extends ColorSpace {
19411
+ // See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these
19412
+ // matrices.
19413
+ // prettier-ignore
19414
+ static #BRADFORD_SCALE_MATRIX = new Float32Array([
19415
+ 0.8951,
19416
+ 0.2664,
19417
+ -0.1614,
19418
+ -0.7502,
19419
+ 1.7135,
19420
+ 0.0367,
19421
+ 0.0389,
19422
+ -0.0685,
19423
+ 1.0296
19424
+ ]);
19425
+ // prettier-ignore
19426
+ static #BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([
19427
+ 0.9869929,
19428
+ -0.1470543,
19429
+ 0.1599627,
19430
+ 0.4323053,
19431
+ 0.5183603,
19432
+ 0.0492912,
19433
+ -85287e-7,
19434
+ 0.0400428,
19435
+ 0.9684867
19436
+ ]);
19437
+ // See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html.
19438
+ // prettier-ignore
19439
+ static #SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([
19440
+ 3.2404542,
19441
+ -1.5371385,
19442
+ -0.4985314,
19443
+ -0.969266,
19444
+ 1.8760108,
19445
+ 0.041556,
19446
+ 0.0556434,
19447
+ -0.2040259,
19448
+ 1.0572252
19449
+ ]);
19450
+ static #FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);
19451
+ static #tempNormalizeMatrix = new Float32Array(3);
19452
+ static #tempConvertMatrix1 = new Float32Array(3);
19453
+ static #tempConvertMatrix2 = new Float32Array(3);
19454
+ static #DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8;
19455
+ constructor(whitePoint, blackPoint, gamma, matrix) {
19456
+ super("CalRGB", 3);
19457
+ if (!whitePoint) {
19458
+ throw new FormatError(
19459
+ "WhitePoint missing - required for color space CalRGB"
19460
+ );
19461
+ }
19462
+ const [XW, YW, ZW] = this.whitePoint = whitePoint;
19463
+ const [XB, YB, ZB] = this.blackPoint = blackPoint || new Float32Array(3);
19464
+ [this.GR, this.GG, this.GB] = gamma || new Float32Array([1, 1, 1]);
19465
+ [
19466
+ this.MXA,
19467
+ this.MYA,
19468
+ this.MZA,
19469
+ this.MXB,
19470
+ this.MYB,
19471
+ this.MZB,
19472
+ this.MXC,
19473
+ this.MYC,
19474
+ this.MZC
19475
+ ] = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
19476
+ if (XW < 0 || ZW < 0 || YW !== 1) {
19477
+ throw new FormatError(
19478
+ `Invalid WhitePoint components for ${this.name}, no fallback available`
19479
+ );
19480
+ }
19481
+ if (XB < 0 || YB < 0 || ZB < 0) {
19482
+ info(
19483
+ `Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], falling back to default.`
19484
+ );
19485
+ this.blackPoint = new Float32Array(3);
19486
+ }
19487
+ if (this.GR < 0 || this.GG < 0 || this.GB < 0) {
19488
+ info(
19489
+ `Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ${this.name}, falling back to default.`
19490
+ );
19491
+ this.GR = this.GG = this.GB = 1;
19492
+ }
19493
+ }
19494
+ #matrixProduct(a, b, result) {
19495
+ result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
19496
+ result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
19497
+ result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
19498
+ }
19499
+ #toFlat(sourceWhitePoint, LMS, result) {
19500
+ result[0] = LMS[0] * 1 / sourceWhitePoint[0];
19501
+ result[1] = LMS[1] * 1 / sourceWhitePoint[1];
19502
+ result[2] = LMS[2] * 1 / sourceWhitePoint[2];
19503
+ }
19504
+ #toD65(sourceWhitePoint, LMS, result) {
19505
+ const D65X = 0.95047;
19506
+ const D65Y = 1;
19507
+ const D65Z = 1.08883;
19508
+ result[0] = LMS[0] * D65X / sourceWhitePoint[0];
19509
+ result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
19510
+ result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
19511
+ }
19512
+ #sRGBTransferFunction(color) {
19513
+ if (color <= 31308e-7) {
19514
+ return MathClamp(12.92 * color, 0, 1);
19515
+ }
19516
+ return color >= 0.99554525 ? 1 : MathClamp((1 + 0.055) * color ** (1 / 2.4) - 0.055, 0, 1);
19517
+ }
19518
+ #decodeL(L) {
19519
+ if (L < 0) {
19520
+ return -this.#decodeL(-L);
19521
+ }
19522
+ return L > 8 ? ((L + 16) / 116) ** 3 : L * _CalRGBCS.#DECODE_L_CONSTANT;
19523
+ }
19524
+ #compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
19525
+ if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {
19526
+ result[0] = XYZ_Flat[0];
19527
+ result[1] = XYZ_Flat[1];
19528
+ result[2] = XYZ_Flat[2];
19529
+ return;
19530
+ }
19531
+ const zeroDecodeL = this.#decodeL(0);
19532
+ const X_DST = zeroDecodeL;
19533
+ const X_SRC = this.#decodeL(sourceBlackPoint[0]);
19534
+ const Y_DST = zeroDecodeL;
19535
+ const Y_SRC = this.#decodeL(sourceBlackPoint[1]);
19536
+ const Z_DST = zeroDecodeL;
19537
+ const Z_SRC = this.#decodeL(sourceBlackPoint[2]);
19538
+ const X_Scale = (1 - X_DST) / (1 - X_SRC);
19539
+ const X_Offset = 1 - X_Scale;
19540
+ const Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
19541
+ const Y_Offset = 1 - Y_Scale;
19542
+ const Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
19543
+ const Z_Offset = 1 - Z_Scale;
19544
+ result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
19545
+ result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
19546
+ result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
19547
+ }
19548
+ #normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
19549
+ if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
19550
+ result[0] = XYZ_In[0];
19551
+ result[1] = XYZ_In[1];
19552
+ result[2] = XYZ_In[2];
19553
+ return;
19554
+ }
19555
+ const LMS = result;
19556
+ this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
19557
+ const LMS_Flat = _CalRGBCS.#tempNormalizeMatrix;
19558
+ this.#toFlat(sourceWhitePoint, LMS, LMS_Flat);
19559
+ this.#matrixProduct(
19560
+ _CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
19561
+ LMS_Flat,
19562
+ result
19563
+ );
19564
+ }
19565
+ #normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
19566
+ const LMS = result;
19567
+ this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
19568
+ const LMS_D65 = _CalRGBCS.#tempNormalizeMatrix;
19569
+ this.#toD65(sourceWhitePoint, LMS, LMS_D65);
19570
+ this.#matrixProduct(
19571
+ _CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
19572
+ LMS_D65,
19573
+ result
19574
+ );
19575
+ }
19576
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
19577
+ const A = MathClamp(src[srcOffset] * scale, 0, 1);
19578
+ const B = MathClamp(src[srcOffset + 1] * scale, 0, 1);
19579
+ const C = MathClamp(src[srcOffset + 2] * scale, 0, 1);
19580
+ const AGR = A === 1 ? 1 : A ** this.GR;
19581
+ const BGG = B === 1 ? 1 : B ** this.GG;
19582
+ const CGB = C === 1 ? 1 : C ** this.GB;
19583
+ const X = this.MXA * AGR + this.MXB * BGG + this.MXC * CGB;
19584
+ const Y = this.MYA * AGR + this.MYB * BGG + this.MYC * CGB;
19585
+ const Z = this.MZA * AGR + this.MZB * BGG + this.MZC * CGB;
19586
+ const XYZ = _CalRGBCS.#tempConvertMatrix1;
19587
+ XYZ[0] = X;
19588
+ XYZ[1] = Y;
19589
+ XYZ[2] = Z;
19590
+ const XYZ_Flat = _CalRGBCS.#tempConvertMatrix2;
19591
+ this.#normalizeWhitePointToFlat(this.whitePoint, XYZ, XYZ_Flat);
19592
+ const XYZ_Black = _CalRGBCS.#tempConvertMatrix1;
19593
+ this.#compensateBlackPoint(this.blackPoint, XYZ_Flat, XYZ_Black);
19594
+ const XYZ_D65 = _CalRGBCS.#tempConvertMatrix2;
19595
+ this.#normalizeWhitePointToD65(
19596
+ _CalRGBCS.#FLAT_WHITEPOINT_MATRIX,
19597
+ XYZ_Black,
19598
+ XYZ_D65
19599
+ );
19600
+ const SRGB = _CalRGBCS.#tempConvertMatrix1;
19601
+ this.#matrixProduct(_CalRGBCS.#SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
19602
+ dest[destOffset] = this.#sRGBTransferFunction(SRGB[0]) * 255;
19603
+ dest[destOffset + 1] = this.#sRGBTransferFunction(SRGB[1]) * 255;
19604
+ dest[destOffset + 2] = this.#sRGBTransferFunction(SRGB[2]) * 255;
19605
+ }
19606
+ getRgbItem(src, srcOffset, dest, destOffset) {
19607
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19608
+ assert2(
19609
+ dest instanceof Uint8ClampedArray,
19610
+ 'CalRGBCS.getRgbItem: Unsupported "dest" type.'
19611
+ );
19612
+ }
19613
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
19614
+ }
19615
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
19616
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19617
+ assert2(
19618
+ dest instanceof Uint8ClampedArray,
19619
+ 'CalRGBCS.getRgbBuffer: Unsupported "dest" type.'
19620
+ );
19621
+ }
19622
+ const scale = 1 / ((1 << bits) - 1);
19623
+ for (let i = 0; i < count; ++i) {
19624
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
19625
+ srcOffset += 3;
19626
+ destOffset += 3 + alpha01;
19627
+ }
19628
+ }
19629
+ };
19630
+ var LabCS = class extends ColorSpace {
19631
+ constructor(whitePoint, blackPoint, range) {
19632
+ super("Lab", 3);
19633
+ if (!whitePoint) {
19634
+ throw new FormatError(
19635
+ "WhitePoint missing - required for color space Lab"
19636
+ );
19637
+ }
19638
+ [this.XW, this.YW, this.ZW] = whitePoint;
19639
+ [this.amin, this.amax, this.bmin, this.bmax] = range || [
19640
+ -100,
19641
+ 100,
19642
+ -100,
19643
+ 100
19644
+ ];
19645
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
19646
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
19647
+ throw new FormatError(
19648
+ "Invalid WhitePoint components, no fallback available"
19649
+ );
19650
+ }
19651
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
19652
+ info("Invalid BlackPoint, falling back to default");
19653
+ this.XB = this.YB = this.ZB = 0;
19654
+ }
19655
+ if (this.amin > this.amax || this.bmin > this.bmax) {
19656
+ info("Invalid Range, falling back to defaults");
19657
+ this.amin = -100;
19658
+ this.amax = 100;
19659
+ this.bmin = -100;
19660
+ this.bmax = 100;
19661
+ }
19662
+ }
19663
+ // Function g(x) from spec
19664
+ #fn_g(x) {
19665
+ return x >= 6 / 29 ? x ** 3 : 108 / 841 * (x - 4 / 29);
19666
+ }
19667
+ #decode(value, high1, low2, high2) {
19668
+ return low2 + value * (high2 - low2) / high1;
19669
+ }
19670
+ // If decoding is needed maxVal should be 2^bits per component - 1.
19671
+ #toRgb(src, srcOffset, maxVal, dest, destOffset) {
19672
+ let Ls = src[srcOffset];
19673
+ let as = src[srcOffset + 1];
19674
+ let bs = src[srcOffset + 2];
19675
+ if (maxVal !== false) {
19676
+ Ls = this.#decode(Ls, maxVal, 0, 100);
19677
+ as = this.#decode(as, maxVal, this.amin, this.amax);
19678
+ bs = this.#decode(bs, maxVal, this.bmin, this.bmax);
19679
+ }
19680
+ if (as > this.amax) {
19681
+ as = this.amax;
19682
+ } else if (as < this.amin) {
19683
+ as = this.amin;
19684
+ }
19685
+ if (bs > this.bmax) {
19686
+ bs = this.bmax;
19687
+ } else if (bs < this.bmin) {
19688
+ bs = this.bmin;
19689
+ }
19690
+ const M = (Ls + 16) / 116;
19691
+ const L = M + as / 500;
19692
+ const N = M - bs / 200;
19693
+ const X = this.XW * this.#fn_g(L);
19694
+ const Y = this.YW * this.#fn_g(M);
19695
+ const Z = this.ZW * this.#fn_g(N);
19696
+ let r, g, b;
19697
+ if (this.ZW < 1) {
19698
+ r = X * 3.1339 + Y * -1.617 + Z * -0.4906;
19699
+ g = X * -0.9785 + Y * 1.916 + Z * 0.0333;
19700
+ b = X * 0.072 + Y * -0.229 + Z * 1.4057;
19701
+ } else {
19702
+ r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
19703
+ g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
19704
+ b = X * 0.0557 + Y * -0.204 + Z * 1.057;
19705
+ }
19706
+ dest[destOffset] = Math.sqrt(r) * 255;
19707
+ dest[destOffset + 1] = Math.sqrt(g) * 255;
19708
+ dest[destOffset + 2] = Math.sqrt(b) * 255;
19709
+ }
19710
+ getRgbItem(src, srcOffset, dest, destOffset) {
19711
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19712
+ assert2(
19713
+ dest instanceof Uint8ClampedArray,
19714
+ 'LabCS.getRgbItem: Unsupported "dest" type.'
19715
+ );
19716
+ }
19717
+ this.#toRgb(src, srcOffset, false, dest, destOffset);
19718
+ }
19719
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
19720
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19721
+ assert2(
19722
+ dest instanceof Uint8ClampedArray,
19723
+ 'LabCS.getRgbBuffer: Unsupported "dest" type.'
19724
+ );
19725
+ }
19726
+ const maxVal = (1 << bits) - 1;
19727
+ for (let i = 0; i < count; i++) {
19728
+ this.#toRgb(src, srcOffset, maxVal, dest, destOffset);
19729
+ srcOffset += 3;
19730
+ destOffset += 3 + alpha01;
19731
+ }
19732
+ }
19733
+ isDefaultDecode(decode, bpc) {
19734
+ return true;
19735
+ }
19736
+ get usesZeroToOneRange() {
19737
+ return shadow2(this, "usesZeroToOneRange", false);
19738
+ }
19739
+ };
19740
+ var TOKEN = {
19741
+ // Structural tokens — not keyword operators
19742
+ number: 0,
19743
+ lbrace: 1,
19744
+ rbrace: 2,
19745
+ // Boolean literals
19746
+ true: 3,
19747
+ false: 4,
19748
+ // Arithmetic binary operators
19749
+ add: 5,
19750
+ sub: 6,
19751
+ mul: 7,
19752
+ div: 8,
19753
+ idiv: 9,
19754
+ mod: 10,
19755
+ exp: 11,
19756
+ // Comparison binary operators
19757
+ eq: 12,
19758
+ ne: 13,
19759
+ gt: 14,
19760
+ ge: 15,
19761
+ lt: 16,
19762
+ le: 17,
19763
+ // Bitwise / boolean binary operators
19764
+ and: 18,
19765
+ or: 19,
19766
+ xor: 20,
19767
+ bitshift: 21,
19768
+ // Unary arithmetic operators
19769
+ abs: 22,
19770
+ neg: 23,
19771
+ ceiling: 24,
19772
+ floor: 25,
19773
+ round: 26,
19774
+ truncate: 27,
19775
+ // Unary boolean / bitwise operator
19776
+ not: 28,
19777
+ // Mathematical functions — unary
19778
+ sqrt: 29,
19779
+ sin: 30,
19780
+ cos: 31,
19781
+ ln: 32,
19782
+ log: 33,
19783
+ // Mathematical function — binary
19784
+ atan: 34,
19785
+ // Type conversion operators
19786
+ cvi: 35,
19787
+ cvr: 36,
19788
+ // Stack operators
19789
+ dup: 37,
19790
+ exch: 38,
19791
+ pop: 39,
19792
+ copy: 40,
19793
+ index: 41,
19794
+ roll: 42,
19795
+ // Control flow
19796
+ if: 43,
19797
+ ifelse: 44,
19798
+ // End of input
19799
+ eof: 45,
19800
+ // Synthetic: produced by the optimizer, never emitted by the lexer.
19801
+ min: 46,
19802
+ max: 47
19803
+ };
19804
+ var Token = class {
19805
+ constructor(id, value = null) {
19806
+ this.id = id;
19807
+ this.value = value;
19808
+ }
19809
+ };
19810
+ var Lexer = class _Lexer {
19811
+ // Singletons for every non-number token, built lazily on first construction.
19812
+ // Keyword operator tokens carry their name as `value`; structural tokens
19813
+ // (lbrace, rbrace, eof) carry null.
19814
+ static #singletons = null;
19815
+ static #operatorSingletons = null;
19816
+ static #initSingletons() {
19817
+ const singletons = /* @__PURE__ */ Object.create(null);
19818
+ const operatorSingletons = /* @__PURE__ */ Object.create(null);
19819
+ for (const [name, id] of Object.entries(TOKEN)) {
19820
+ if (name === "number") {
19821
+ continue;
19822
+ }
19823
+ const isOperator = id >= TOKEN.true && id <= TOKEN.ifelse;
19824
+ const token = new Token(id, isOperator ? name : null);
19825
+ singletons[name] = token;
19826
+ if (isOperator) {
19827
+ operatorSingletons[name] = token;
19828
+ }
19829
+ }
19830
+ this.#singletons = singletons;
19831
+ this.#operatorSingletons = operatorSingletons;
19832
+ }
19833
+ constructor(data) {
19834
+ if (!_Lexer.#singletons) {
19835
+ _Lexer.#initSingletons();
19836
+ }
19837
+ this.data = data;
19838
+ this.pos = 0;
19839
+ this.len = data.length;
19840
+ this._numberPattern = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/iy;
19841
+ this._identifierPattern = /[a-z]+/y;
19842
+ }
19843
+ // Skip a % comment, advancing past the next \n or \r (or to EOF).
19844
+ _skipComment() {
19845
+ const lf = this.data.indexOf("\n", this.pos);
19846
+ const cr = this.data.indexOf("\r", this.pos);
19847
+ const eol = Math.min(lf < 0 ? this.len : lf, cr < 0 ? this.len : cr);
19848
+ this.pos = Math.min(eol + 1, this.len);
19849
+ }
19850
+ _getNumber() {
19851
+ this._numberPattern.lastIndex = this.pos;
19852
+ const match = this._numberPattern.exec(this.data);
19853
+ if (!match) {
19854
+ return new Token(TOKEN.number, 0);
19855
+ }
19856
+ const number = parseFloat(match[0]);
19857
+ if (!Number.isFinite(number)) {
19858
+ return new Token(TOKEN.number, 0);
19859
+ }
19860
+ this.pos = this._numberPattern.lastIndex;
19861
+ return new Token(TOKEN.number, number);
19862
+ }
19863
+ _getOperator() {
19864
+ this._identifierPattern.lastIndex = this.pos;
19865
+ const match = this._identifierPattern.exec(this.data);
19866
+ if (!match) {
19867
+ return new Token(TOKEN.number, 0);
19868
+ }
19869
+ this.pos = this._identifierPattern.lastIndex;
19870
+ const op = match[0];
19871
+ const token = _Lexer.#operatorSingletons[op];
19872
+ return token ?? new Token(TOKEN.number, 0);
19873
+ }
19874
+ // Return the next token, or Lexer.#singletons.eof at end of input.
19875
+ next() {
19876
+ while (this.pos < this.len) {
19877
+ const ch3 = this.data.charCodeAt(this.pos++);
19878
+ switch (ch3) {
19879
+ // PostScript white-space characters (PDF32000 §7.2.2)
19880
+ case 0:
19881
+ case 9:
19882
+ case 10:
19883
+ case 12:
19884
+ case 13:
19885
+ case 32:
19886
+ break;
19887
+ case 37:
19888
+ this._skipComment();
19889
+ break;
19890
+ case 123:
19891
+ return _Lexer.#singletons.lbrace;
19892
+ case 125:
19893
+ return _Lexer.#singletons.rbrace;
19894
+ case 43:
19895
+ case 45:
19896
+ this.pos--;
19897
+ return this._getNumber();
19898
+ case 46:
19899
+ this.pos--;
19900
+ return this._getNumber();
19901
+ default:
19902
+ if (ch3 >= 48 && ch3 <= 57) {
19903
+ this.pos--;
19904
+ return this._getNumber();
19905
+ }
19906
+ if (ch3 >= 97 && ch3 <= 122) {
19907
+ this.pos--;
19908
+ return this._getOperator();
19909
+ }
19910
+ return new Token(TOKEN.number, 0);
19911
+ }
19912
+ }
19913
+ return _Lexer.#singletons.eof;
19914
+ }
19915
+ };
19916
+ var PS_VALUE_TYPE = {
19917
+ numeric: 0,
19918
+ // known to be a number (f64 in Wasm)
19919
+ boolean: 1,
19920
+ // known to be a boolean (0.0 = false, 1.0 = true in f64)
19921
+ unknown: 2
19922
+ // indeterminate at compile time
19923
+ };
19924
+ var PS_NODE = {
19925
+ // Parser AST node types (produced by Parser / parsePostScriptFunction)
19926
+ program: 0,
19927
+ block: 1,
19928
+ number: 2,
19929
+ operator: 3,
19930
+ if: 4,
19931
+ ifelse: 5,
19932
+ // Tree AST node types (produced by PSStackToTree)
19933
+ arg: 6,
19934
+ const: 7,
19935
+ unary: 8,
19936
+ binary: 9,
19937
+ ternary: 10
19938
+ };
19939
+ var PsNode = class {
19940
+ constructor(type) {
19941
+ this.type = type;
19942
+ }
19943
+ };
19944
+ var PsProgram = class extends PsNode {
19945
+ constructor(body) {
19946
+ super(PS_NODE.program);
19947
+ this.body = body;
19948
+ }
19949
+ };
19950
+ var PsBlock = class extends PsNode {
19951
+ constructor(instructions) {
19952
+ super(PS_NODE.block);
19953
+ this.instructions = instructions;
19954
+ }
19955
+ };
19956
+ var PsNumber = class extends PsNode {
19957
+ /** @param {number} value */
19958
+ constructor(value) {
19959
+ super(PS_NODE.number);
19960
+ this.value = value;
19961
+ }
19962
+ };
19963
+ var PsOperator = class extends PsNode {
19964
+ /** @param {number} op — one of the TOKEN.* constants from lexer.js */
19965
+ constructor(op) {
19966
+ super(PS_NODE.operator);
19967
+ this.op = op;
19968
+ }
19969
+ };
19970
+ var PsIf = class extends PsNode {
19971
+ /** @param {PsBlock} then */
19972
+ constructor(then) {
19973
+ super(PS_NODE.if);
19974
+ this.then = then;
19975
+ }
19976
+ };
19977
+ var PsIfElse = class extends PsNode {
19978
+ /**
19979
+ * @param {PsBlock} then
19980
+ * @param {PsBlock} otherwise
19981
+ */
19982
+ constructor(then, otherwise) {
19983
+ super(PS_NODE.ifelse);
19984
+ this.then = then;
19985
+ this.otherwise = otherwise;
19986
+ }
19987
+ };
19988
+ var PsArgNode = class extends PsNode {
19989
+ /** @param {number} index */
19990
+ constructor(index) {
19991
+ super(PS_NODE.arg);
19992
+ this.index = index;
19993
+ this.valueType = PS_VALUE_TYPE.numeric;
19994
+ }
19995
+ };
19996
+ var PsConstNode = class extends PsNode {
19997
+ /** @param {number|boolean} value */
19998
+ constructor(value) {
19999
+ super(PS_NODE.const);
20000
+ this.value = value;
20001
+ this.valueType = typeof value === "boolean" ? PS_VALUE_TYPE.boolean : PS_VALUE_TYPE.numeric;
20002
+ }
20003
+ };
20004
+ var PsUnaryNode = class extends PsNode {
20005
+ /**
20006
+ * @param {number} op — TOKEN.* constant
20007
+ * @param {PsNode} operand
20008
+ * @param {number} [valueType]
20009
+ */
20010
+ constructor(op, operand, valueType = PS_VALUE_TYPE.unknown) {
20011
+ super(PS_NODE.unary);
20012
+ this.op = op;
20013
+ this.operand = operand;
20014
+ this.valueType = valueType;
20015
+ }
20016
+ };
20017
+ var PsBinaryNode = class extends PsNode {
20018
+ /**
20019
+ * @param {number} op — TOKEN.* constant
20020
+ * @param {PsNode} first — was on top of stack
20021
+ * @param {PsNode} second — was below top
20022
+ * @param {number} [valueType]
20023
+ */
20024
+ constructor(op, first, second, valueType = PS_VALUE_TYPE.unknown) {
20025
+ super(PS_NODE.binary);
20026
+ this.op = op;
20027
+ this.first = first;
20028
+ this.second = second;
20029
+ this.valueType = valueType;
20030
+ }
20031
+ };
20032
+ var PsTernaryNode = class extends PsNode {
20033
+ /**
20034
+ * @param {PsNode} cond
20035
+ * @param {PsNode} then
20036
+ * @param {PsNode} otherwise
20037
+ * @param {number} [valueType]
20038
+ */
20039
+ constructor(cond, then, otherwise, valueType = PS_VALUE_TYPE.unknown) {
20040
+ super(PS_NODE.ternary);
20041
+ this.cond = cond;
20042
+ this.then = then;
20043
+ this.otherwise = otherwise;
20044
+ this.valueType = valueType;
20045
+ }
20046
+ };
20047
+ var Parser = class _Parser {
20048
+ constructor(lexer) {
20049
+ this.lexer = lexer;
20050
+ this._token = null;
20051
+ }
20052
+ static _isRegularOperator(id) {
20053
+ return id >= TOKEN.true && id < TOKEN.if;
20054
+ }
20055
+ // Fetch the next token from the lexer.
20056
+ _advance() {
20057
+ this._token = this.lexer.next();
20058
+ }
20059
+ // Assert that the current token has the given id, consume it, and return it.
20060
+ _expect(id) {
20061
+ if (this._token.id !== id) {
20062
+ throw new FormatError(
20063
+ `PostScript function: expected token id ${id}, got ${this._token.id}.`
20064
+ );
20065
+ }
20066
+ const tok = this._token;
20067
+ this._advance();
20068
+ return tok;
20069
+ }
20070
+ /**
20071
+ * Parse the full Type 4 function body.
20072
+ *
20073
+ * Grammar (simplified):
20074
+ * program ::= '{' block '}'
20075
+ * block ::= instruction*
20076
+ * instruction ::= number
20077
+ * | operator (any PS_OPERATOR except if / ifelse)
20078
+ * | '{' block '}' 'if'
20079
+ * | '{' block '}' '{' block '}' 'ifelse'
20080
+ * @returns {PsProgram}
20081
+ */
20082
+ parse() {
20083
+ this._advance();
20084
+ this._expect(TOKEN.lbrace);
20085
+ const block = this._parseBlock();
20086
+ this._expect(TOKEN.rbrace);
20087
+ if (this._token.id !== TOKEN.eof) {
20088
+ warn2("PostScript function: unexpected content after closing brace.");
20089
+ }
20090
+ return new PsProgram(block);
20091
+ }
20092
+ _parseBlock() {
20093
+ const instructions = [];
20094
+ while (true) {
20095
+ const tok = this._token;
20096
+ switch (tok.id) {
20097
+ case TOKEN.number:
20098
+ instructions.push(new PsNumber(tok.value));
20099
+ this._advance();
20100
+ break;
20101
+ case TOKEN.lbrace: {
20102
+ this._advance();
20103
+ const thenBlock = this._parseBlock();
20104
+ this._expect(TOKEN.rbrace);
20105
+ if (this._token.id === TOKEN.if) {
20106
+ this._advance();
20107
+ instructions.push(new PsIf(thenBlock));
20108
+ } else if (this._token.id === TOKEN.lbrace) {
20109
+ this._advance();
20110
+ const elseBlock = this._parseBlock();
20111
+ this._expect(TOKEN.rbrace);
20112
+ this._expect(TOKEN.ifelse);
20113
+ instructions.push(new PsIfElse(thenBlock, elseBlock));
20114
+ } else {
20115
+ throw new FormatError(
20116
+ "PostScript function: a procedure block must be followed by 'if' or '{\u2026} ifelse'."
20117
+ );
20118
+ }
20119
+ break;
20120
+ }
20121
+ case TOKEN.rbrace:
20122
+ case TOKEN.eof:
20123
+ return new PsBlock(instructions);
20124
+ case TOKEN.if:
20125
+ case TOKEN.ifelse:
20126
+ throw new FormatError(
20127
+ `PostScript function: unexpected '${tok.value}' operator.`
20128
+ );
20129
+ default:
20130
+ if (_Parser._isRegularOperator(tok.id)) {
20131
+ instructions.push(new PsOperator(tok.id));
20132
+ this._advance();
20133
+ break;
20134
+ }
20135
+ throw new FormatError(
20136
+ `PostScript function: unexpected token id ${tok.id}.`
20137
+ );
20138
+ }
20139
+ }
20140
+ }
20141
+ };
20142
+ function parsePostScriptFunction(source) {
20143
+ return new Parser(new Lexer(source)).parse();
20144
+ }
20145
+ function _nodesEqual(a, b) {
20146
+ if (a === b) {
20147
+ return true;
20148
+ }
20149
+ if (a.type !== b.type) {
20150
+ return false;
20151
+ }
20152
+ switch (a.type) {
20153
+ case PS_NODE.arg:
20154
+ return a.index === b.index;
20155
+ case PS_NODE.const:
20156
+ return a.value === b.value;
20157
+ case PS_NODE.unary:
20158
+ return a.op === b.op && _nodesEqual(a.operand, b.operand);
20159
+ case PS_NODE.binary:
20160
+ return a.op === b.op && _nodesEqual(a.first, b.first) && _nodesEqual(a.second, b.second);
20161
+ case PS_NODE.ternary:
20162
+ return _nodesEqual(a.cond, b.cond) && _nodesEqual(a.then, b.then) && _nodesEqual(a.otherwise, b.otherwise);
20163
+ default:
20164
+ return false;
20165
+ }
20166
+ }
20167
+ function _evalBinaryConst(op, a, b) {
20168
+ switch (op) {
20169
+ case TOKEN.add:
20170
+ return a + b;
20171
+ case TOKEN.sub:
20172
+ return a - b;
20173
+ case TOKEN.mul:
20174
+ return a * b;
20175
+ case TOKEN.div:
20176
+ return b !== 0 ? a / b : 0;
20177
+ // div by zero → 0
20178
+ case TOKEN.idiv:
20179
+ return b !== 0 ? Math.trunc(a / b) : 0;
20180
+ // div by zero → 0
20181
+ case TOKEN.mod:
20182
+ return b !== 0 ? a - Math.trunc(a / b) * b : 0;
20183
+ // div by zero → 0
20184
+ case TOKEN.exp: {
20185
+ const r = a ** b;
20186
+ return Number.isFinite(r) ? r : void 0;
20187
+ }
20188
+ case TOKEN.atan: {
20189
+ let deg = Math.atan2(a, b) * (180 / Math.PI);
20190
+ if (deg < 0) {
20191
+ deg += 360;
20192
+ }
20193
+ return deg;
20194
+ }
20195
+ case TOKEN.eq:
20196
+ return a === b;
20197
+ case TOKEN.ne:
20198
+ return a !== b;
20199
+ case TOKEN.gt:
20200
+ return a > b;
20201
+ case TOKEN.ge:
20202
+ return a >= b;
20203
+ case TOKEN.lt:
20204
+ return a < b;
20205
+ case TOKEN.le:
20206
+ return a <= b;
20207
+ case TOKEN.and:
20208
+ return typeof a === "boolean" ? a && b : a & b | 0;
20209
+ case TOKEN.or:
20210
+ return typeof a === "boolean" ? a || b : a | b | 0;
20211
+ case TOKEN.xor:
20212
+ return typeof a === "boolean" ? a !== b : a ^ b | 0;
20213
+ case TOKEN.bitshift:
20214
+ return b >= 0 ? a << b | 0 : a >> -b | 0;
20215
+ case TOKEN.min:
20216
+ return Math.min(a, b);
20217
+ case TOKEN.max:
20218
+ return Math.max(a, b);
20219
+ default:
20220
+ return void 0;
20221
+ }
20222
+ }
20223
+ function _evalUnaryConst(op, v) {
20224
+ switch (op) {
20225
+ case TOKEN.abs:
20226
+ return Math.abs(v);
20227
+ case TOKEN.neg:
20228
+ return -v;
20229
+ case TOKEN.ceiling:
20230
+ return Math.ceil(v);
20231
+ case TOKEN.floor:
20232
+ return Math.floor(v);
20233
+ case TOKEN.round:
20234
+ return Math.round(v);
20235
+ case TOKEN.truncate:
20236
+ return Math.trunc(v);
20237
+ case TOKEN.sqrt: {
20238
+ const r = Math.sqrt(v);
20239
+ return Number.isFinite(r) ? r : void 0;
20240
+ }
20241
+ case TOKEN.sin:
20242
+ return Math.sin(v % 360 * Math.PI / 180);
20243
+ case TOKEN.cos:
20244
+ return Math.cos(v % 360 * Math.PI / 180);
20245
+ case TOKEN.ln: {
20246
+ const r = Math.log(v);
20247
+ return Number.isFinite(r) ? r : void 0;
20248
+ }
20249
+ case TOKEN.log: {
20250
+ const r = Math.log10(v);
20251
+ return Number.isFinite(r) ? r : void 0;
20252
+ }
20253
+ case TOKEN.cvi:
20254
+ return Math.trunc(v);
20255
+ case TOKEN.cvr:
20256
+ return v;
20257
+ case TOKEN.not:
20258
+ return typeof v === "boolean" ? !v : ~v;
20259
+ default:
20260
+ return void 0;
20261
+ }
20262
+ }
20263
+ var MAX_STACK_SIZE = 100;
20264
+ function _unaryValueType(op, operandType) {
20265
+ return op === TOKEN.not ? operandType : PS_VALUE_TYPE.numeric;
20266
+ }
20267
+ function _binaryValueType(op, firstType, secondType) {
20268
+ switch (op) {
20269
+ // Comparison operators always produce a boolean.
20270
+ case TOKEN.eq:
20271
+ case TOKEN.ne:
20272
+ case TOKEN.gt:
20273
+ case TOKEN.ge:
20274
+ case TOKEN.lt:
20275
+ case TOKEN.le:
20276
+ return PS_VALUE_TYPE.boolean;
20277
+ // and / or / xor preserve the type when both operands are the same known
20278
+ // type (both boolean or both numeric); otherwise the type is unknown.
20279
+ case TOKEN.and:
20280
+ case TOKEN.or:
20281
+ case TOKEN.xor:
20282
+ return firstType === secondType && firstType !== PS_VALUE_TYPE.unknown ? firstType : PS_VALUE_TYPE.unknown;
20283
+ // All arithmetic / bitshift operators produce a numeric result.
20284
+ default:
20285
+ return PS_VALUE_TYPE.numeric;
20286
+ }
20287
+ }
20288
+ var PSStackToTree = class _PSStackToTree {
20289
+ static #binaryOps = null;
20290
+ static #unaryOps = null;
20291
+ static #idempotentUnary = null;
20292
+ static #negatedComparison = null;
20293
+ static #init() {
20294
+ this.#binaryOps = /* @__PURE__ */ new Set([
20295
+ TOKEN.add,
20296
+ TOKEN.sub,
20297
+ TOKEN.mul,
20298
+ TOKEN.div,
20299
+ TOKEN.idiv,
20300
+ TOKEN.mod,
20301
+ TOKEN.exp,
20302
+ TOKEN.atan,
20303
+ TOKEN.eq,
20304
+ TOKEN.ne,
20305
+ TOKEN.gt,
20306
+ TOKEN.ge,
20307
+ TOKEN.lt,
20308
+ TOKEN.le,
20309
+ TOKEN.and,
20310
+ TOKEN.or,
20311
+ TOKEN.xor,
20312
+ TOKEN.bitshift
20313
+ ]);
20314
+ this.#unaryOps = /* @__PURE__ */ new Set([
20315
+ TOKEN.abs,
20316
+ TOKEN.neg,
20317
+ TOKEN.ceiling,
20318
+ TOKEN.floor,
20319
+ TOKEN.round,
20320
+ TOKEN.truncate,
20321
+ TOKEN.sqrt,
20322
+ TOKEN.sin,
20323
+ TOKEN.cos,
20324
+ TOKEN.ln,
20325
+ TOKEN.log,
20326
+ TOKEN.cvi,
20327
+ TOKEN.cvr,
20328
+ TOKEN.not
20329
+ ]);
20330
+ this.#idempotentUnary = /* @__PURE__ */ new Set([
20331
+ TOKEN.abs,
20332
+ TOKEN.ceiling,
20333
+ TOKEN.cvi,
20334
+ TOKEN.cvr,
20335
+ TOKEN.floor,
20336
+ TOKEN.round,
20337
+ TOKEN.truncate
20338
+ ]);
20339
+ this.#negatedComparison = /* @__PURE__ */ new Map([
20340
+ [TOKEN.eq, TOKEN.ne],
20341
+ [TOKEN.ne, TOKEN.eq],
20342
+ [TOKEN.lt, TOKEN.ge],
20343
+ [TOKEN.le, TOKEN.gt],
20344
+ [TOKEN.gt, TOKEN.le],
20345
+ [TOKEN.ge, TOKEN.lt]
20346
+ ]);
20347
+ }
20348
+ /**
20349
+ * @param {PsProgram} program
20350
+ * @param {number} numInputs — number of domain values placed on the stack
20351
+ * before the program runs (i.e. the length of the domain array / 2).
20352
+ * @returns {Array<PsNode>} — one tree node per output value.
20353
+ */
20354
+ evaluate(program, numInputs) {
20355
+ if (!_PSStackToTree.#binaryOps) {
20356
+ _PSStackToTree.#init();
20357
+ }
20358
+ this._failed = false;
20359
+ if (numInputs > MAX_STACK_SIZE) {
20360
+ return null;
20361
+ }
20362
+ const stack = [];
20363
+ for (let i = 0; i < numInputs; i++) {
20364
+ stack.push(new PsArgNode(i));
20365
+ }
20366
+ this._evalBlock(program.body, stack);
20367
+ if (this._failed) {
20368
+ return null;
20369
+ }
20370
+ _PSStackToTree.#markShared(stack);
20371
+ return stack;
20372
+ }
20373
+ // Set node.shared / sharedCount on non-atomic nodes referenced more than
20374
+ // once. arg/const are excluded — they are cheap to re-emit inline.
20375
+ static #markShared(outputs) {
20376
+ const refCount = /* @__PURE__ */ new Map();
20377
+ const visit = (node) => {
20378
+ if (!node || node.type === PS_NODE.arg || node.type === PS_NODE.const) {
20379
+ return;
20380
+ }
20381
+ const prev = refCount.get(node) ?? 0;
20382
+ refCount.set(node, prev + 1);
20383
+ if (prev > 0) {
20384
+ return;
20385
+ }
20386
+ switch (node.type) {
20387
+ case PS_NODE.unary:
20388
+ visit(node.operand);
20389
+ break;
20390
+ case PS_NODE.binary:
20391
+ visit(node.first);
20392
+ visit(node.second);
20393
+ break;
20394
+ case PS_NODE.ternary:
20395
+ visit(node.cond);
20396
+ visit(node.then);
20397
+ visit(node.otherwise);
20398
+ break;
20399
+ }
20400
+ };
20401
+ for (const output of outputs) {
20402
+ visit(output);
20403
+ }
20404
+ for (const [node, count] of refCount) {
20405
+ if (count > 1) {
20406
+ node.shared = true;
20407
+ node.sharedCount = count;
20408
+ }
20409
+ }
20410
+ }
20411
+ _evalBlock(block, stack) {
20412
+ this._evalBlockFrom(block.instructions, 0, stack);
20413
+ }
20414
+ /**
20415
+ * Core evaluation loop. Processes `instructions[startIdx…]` in order,
20416
+ * mutating `stack` as each instruction executes.
20417
+ *
20418
+ * When a `{ body } if` instruction grows the stack (the PostScript "early
20419
+ * exit / guard" idiom), the remaining instructions in the current array are
20420
+ * evaluated on **both** the true-branch stack and the false-branch stack,
20421
+ * then the two results are merged into PsTernaryNodes. This handles
20422
+ * patterns like:
20423
+ *
20424
+ * cond { pop R G B sentinel } if
20425
+ * … more guards …
20426
+ * sentinel 0 gt { defaultR defaultG defaultB } if
20427
+ */
20428
+ _evalBlockFrom(instructions, startIdx, stack) {
20429
+ for (let idx = startIdx; idx < instructions.length; idx++) {
20430
+ if (this._failed) {
20431
+ break;
20432
+ }
20433
+ const instr = instructions[idx];
20434
+ switch (instr.type) {
20435
+ case PS_NODE.number:
20436
+ stack.push(new PsConstNode(instr.value));
20437
+ if (stack.length > MAX_STACK_SIZE) {
20438
+ this._failed = true;
20439
+ }
20440
+ break;
20441
+ case PS_NODE.operator:
20442
+ this._evalOp(instr.op, stack);
20443
+ break;
20444
+ case PS_NODE.if: {
20445
+ if (stack.length < 1) {
20446
+ this._failed = true;
20447
+ break;
20448
+ }
20449
+ const cond = stack.pop();
20450
+ const saved = stack.slice();
20451
+ this._evalBlock(instr.then, stack);
20452
+ if (this._failed) {
20453
+ break;
20454
+ }
20455
+ if (stack.length === saved.length) {
20456
+ for (let i = 0; i < stack.length; i++) {
20457
+ if (stack[i] !== saved[i]) {
20458
+ stack[i] = this._makeTernary(cond, stack[i], saved[i]);
20459
+ }
20460
+ }
20461
+ } else if (stack.length > saved.length) {
20462
+ if (cond.type === PS_NODE.const) {
20463
+ if (!cond.value) {
20464
+ stack.length = 0;
20465
+ stack.push(...saved);
20466
+ }
20467
+ break;
20468
+ }
20469
+ const trueStack = stack.slice();
20470
+ this._evalBlockFrom(instructions, idx + 1, trueStack);
20471
+ if (this._failed) {
20472
+ break;
20473
+ }
20474
+ const falseStack = saved;
20475
+ this._evalBlockFrom(instructions, idx + 1, falseStack);
20476
+ if (this._failed) {
20477
+ break;
20478
+ }
20479
+ if (trueStack.length !== falseStack.length) {
20480
+ const zero = new PsConstNode(0);
20481
+ while (trueStack.length < falseStack.length) {
20482
+ trueStack.push(zero);
20483
+ }
20484
+ while (falseStack.length < trueStack.length) {
20485
+ falseStack.push(zero);
20486
+ }
20487
+ }
20488
+ stack.length = 0;
20489
+ for (let i = 0; i < trueStack.length; i++) {
20490
+ stack.push(this._makeTernary(cond, trueStack[i], falseStack[i]));
20491
+ }
20492
+ return;
20493
+ } else {
20494
+ this._failed = true;
20495
+ }
20496
+ break;
20497
+ }
20498
+ case PS_NODE.ifelse: {
20499
+ if (stack.length < 1) {
20500
+ this._failed = true;
20501
+ break;
20502
+ }
20503
+ const cond = stack.pop();
20504
+ const snapshot = stack.slice();
20505
+ const thenStack = snapshot.slice();
20506
+ this._evalBlock(instr.then, thenStack);
20507
+ if (this._failed) {
20508
+ break;
20509
+ }
20510
+ const elseStack = snapshot.slice();
20511
+ this._evalBlock(instr.otherwise, elseStack);
20512
+ if (this._failed) {
20513
+ break;
20514
+ }
20515
+ if (thenStack.length !== elseStack.length) {
20516
+ const zero = new PsConstNode(0);
20517
+ while (thenStack.length < elseStack.length) {
20518
+ thenStack.push(zero);
20519
+ }
20520
+ while (elseStack.length < thenStack.length) {
20521
+ elseStack.push(zero);
20522
+ }
20523
+ }
20524
+ stack.length = 0;
20525
+ for (let i = 0; i < thenStack.length; i++) {
20526
+ stack.push(this._makeTernary(cond, thenStack[i], elseStack[i]));
20527
+ }
20528
+ break;
20529
+ }
20530
+ }
20531
+ }
20532
+ }
20533
+ _evalOp(op, stack) {
20534
+ if (_PSStackToTree.#binaryOps.has(op)) {
20535
+ if (stack.length < 2) {
20536
+ this._failed = true;
20537
+ return;
20538
+ }
20539
+ const first = stack.pop();
20540
+ const second = stack.pop();
20541
+ stack.push(this._makeBinary(op, first, second));
20542
+ return;
20543
+ }
20544
+ if (_PSStackToTree.#unaryOps.has(op)) {
20545
+ if (stack.length < 1) {
20546
+ this._failed = true;
20547
+ return;
20548
+ }
20549
+ stack.push(this._makeUnary(op, stack.pop()));
20550
+ return;
20551
+ }
20552
+ switch (op) {
20553
+ case TOKEN.true:
20554
+ stack.push(new PsConstNode(true));
20555
+ if (stack.length > MAX_STACK_SIZE) {
20556
+ this._failed = true;
20557
+ }
20558
+ break;
20559
+ case TOKEN.false:
20560
+ stack.push(new PsConstNode(false));
20561
+ if (stack.length > MAX_STACK_SIZE) {
20562
+ this._failed = true;
20563
+ }
20564
+ break;
20565
+ case TOKEN.dup:
20566
+ if (stack.length < 1) {
20567
+ this._failed = true;
20568
+ break;
20569
+ }
20570
+ stack.push(stack.at(-1));
20571
+ if (stack.length > MAX_STACK_SIZE) {
20572
+ this._failed = true;
20573
+ }
20574
+ break;
20575
+ case TOKEN.exch: {
20576
+ if (stack.length < 2) {
20577
+ this._failed = true;
20578
+ break;
20579
+ }
20580
+ const a = stack.pop();
20581
+ const b = stack.pop();
20582
+ stack.push(a, b);
20583
+ break;
20584
+ }
20585
+ case TOKEN.pop:
20586
+ if (stack.length < 1) {
20587
+ this._failed = true;
20588
+ break;
20589
+ }
20590
+ stack.pop();
20591
+ break;
20592
+ case TOKEN.copy: {
20593
+ if (stack.length < 1) {
20594
+ this._failed = true;
20595
+ break;
20596
+ }
20597
+ const nNode = stack.pop();
20598
+ if (nNode.type === PS_NODE.const) {
20599
+ const n = nNode.value | 0;
20600
+ if (n === 0) {
20601
+ } else if (n < 0 || n > stack.length) {
20602
+ this._failed = true;
20603
+ } else {
20604
+ stack.push(...stack.slice(-n));
20605
+ if (stack.length > MAX_STACK_SIZE) {
20606
+ this._failed = true;
20607
+ }
20608
+ }
20609
+ } else {
20610
+ this._failed = true;
20611
+ }
20612
+ break;
20613
+ }
20614
+ case TOKEN.index: {
20615
+ if (stack.length < 1) {
20616
+ this._failed = true;
20617
+ break;
20618
+ }
20619
+ const nNode = stack.pop();
20620
+ if (nNode.type === PS_NODE.const) {
20621
+ const n = nNode.value | 0;
20622
+ if (n < 0 || n >= stack.length) {
20623
+ this._failed = true;
20624
+ } else {
20625
+ stack.push(stack.at(-n - 1));
20626
+ }
20627
+ } else {
20628
+ this._failed = true;
20629
+ }
20630
+ break;
20631
+ }
20632
+ case TOKEN.roll: {
20633
+ if (stack.length < 2) {
20634
+ this._failed = true;
20635
+ break;
20636
+ }
20637
+ const jNode = stack.pop();
20638
+ const nNode = stack.pop();
20639
+ if (nNode.type === PS_NODE.const && jNode.type === PS_NODE.const) {
20640
+ const n = nNode.value | 0;
20641
+ if (n === 0) {
20642
+ } else if (n < 0 || n > stack.length) {
20643
+ this._failed = true;
20644
+ } else {
20645
+ const j = ((jNode.value | 0) % n + n) % n;
20646
+ if (j > 0) {
20647
+ const slice = stack.splice(-n, n);
20648
+ stack.push(...slice.slice(n - j), ...slice.slice(0, n - j));
20649
+ }
20650
+ }
20651
+ } else {
20652
+ this._failed = true;
20653
+ }
20654
+ break;
20655
+ }
20656
+ default:
20657
+ this._failed = true;
20658
+ break;
20659
+ }
20660
+ }
20661
+ /**
20662
+ * Create a binary tree node, applying optimizations eagerly:
20663
+ *
20664
+ * 1. Constant folding — both operands are PsConstNode → fold to PsConstNode.
20665
+ * 2. Reflexive simplifications — x−x→0, x xor x→0, x eq x→true, etc.
20666
+ * 3. Algebraic simplifications with one known operand — identity elements
20667
+ * (x+0→x, x*1→x, …), absorbing elements (x*0→0, x and false→false, …),
20668
+ * and strength reductions (x*-1→neg(x), x^0.5→sqrt(x), x^2→x*x, …).
20669
+ *
20670
+ * Recall: `first` was on top of the stack (right operand for non-commutative
20671
+ * ops), `second` was below (left operand). So `a b sub` → second=a, first=b
20672
+ * → a − b.
20673
+ */
20674
+ _makeBinary(op, first, second) {
20675
+ if (first.type === PS_NODE.const && second.type === PS_NODE.const) {
20676
+ const v = _evalBinaryConst(op, second.value, first.value);
20677
+ if (v !== void 0) {
20678
+ return new PsConstNode(v);
20679
+ }
20680
+ }
20681
+ if (_nodesEqual(first, second)) {
20682
+ switch (op) {
20683
+ case TOKEN.sub:
20684
+ return new PsConstNode(0);
20685
+ // x − x → 0
20686
+ case TOKEN.xor:
20687
+ return new PsConstNode(
20688
+ /* eslint-disable unicorn/prefer-logical-operator-over-ternary */
20689
+ first.valueType === PS_VALUE_TYPE.boolean ? false : 0
20690
+ /* eslint-enable unicorn/prefer-logical-operator-over-ternary */
20691
+ );
20692
+ // TOKEN.mod, TOKEN.div, TOKEN.idiv are NOT simplified here:
20693
+ // x op x is undefined when x = 0, so we cannot fold without knowing
20694
+ // that x is non-zero.
20695
+ case TOKEN.and:
20696
+ case TOKEN.or:
20697
+ return first;
20698
+ // x and x → x; x or x → x
20699
+ case TOKEN.min:
20700
+ case TOKEN.max:
20701
+ return first;
20702
+ // min(x,x) → x; max(x,x) → x
20703
+ case TOKEN.eq:
20704
+ case TOKEN.ge:
20705
+ case TOKEN.le:
20706
+ return new PsConstNode(true);
20707
+ case TOKEN.ne:
20708
+ case TOKEN.gt:
20709
+ case TOKEN.lt:
20710
+ return new PsConstNode(false);
20711
+ }
20712
+ }
20713
+ if (first.type === PS_NODE.const) {
20714
+ const b = first.value;
20715
+ switch (op) {
20716
+ case TOKEN.add:
20717
+ if (b === 0) {
20718
+ return second;
20719
+ }
20720
+ break;
20721
+ case TOKEN.sub:
20722
+ if (b === 0) {
20723
+ return second;
20724
+ }
20725
+ break;
20726
+ case TOKEN.mul:
20727
+ if (b === 1) {
20728
+ return second;
20729
+ }
20730
+ if (b === 0) {
20731
+ return first;
20732
+ }
20733
+ if (b === -1) {
20734
+ return this._makeUnary(TOKEN.neg, second);
20735
+ }
20736
+ break;
20737
+ case TOKEN.div:
20738
+ if (b !== 0) {
20739
+ return this._makeBinary(TOKEN.mul, new PsConstNode(1 / b), second);
20740
+ }
20741
+ break;
20742
+ case TOKEN.idiv:
20743
+ if (b === 1) {
20744
+ return second;
20745
+ }
20746
+ break;
20747
+ case TOKEN.exp:
20748
+ if (b === 1) {
20749
+ return second;
20750
+ }
20751
+ if (b === -1) {
20752
+ return this._makeBinary(TOKEN.div, second, new PsConstNode(1));
20753
+ }
20754
+ if (b === 0.5) {
20755
+ return this._makeUnary(TOKEN.sqrt, second);
20756
+ }
20757
+ if (b === 0.25) {
20758
+ const sqrtOnce = this._makeUnary(TOKEN.sqrt, second);
20759
+ return this._makeUnary(TOKEN.sqrt, sqrtOnce);
20760
+ }
20761
+ if (b === 2) {
20762
+ return this._makeBinary(TOKEN.mul, second, second);
20763
+ }
20764
+ if (b === 3) {
20765
+ return this._makeBinary(
20766
+ TOKEN.mul,
20767
+ this._makeBinary(TOKEN.mul, second, second),
20768
+ second
20769
+ );
20770
+ }
20771
+ if (b === 4) {
20772
+ const square = this._makeBinary(TOKEN.mul, second, second);
20773
+ return this._makeBinary(TOKEN.mul, square, square);
20774
+ }
20775
+ if (b === 0) {
20776
+ return new PsConstNode(1);
20777
+ }
20778
+ break;
20779
+ case TOKEN.and:
20780
+ if (b === true) {
20781
+ return second;
20782
+ }
20783
+ if (b === false) {
20784
+ return first;
20785
+ }
20786
+ break;
20787
+ case TOKEN.or:
20788
+ if (b === false) {
20789
+ return second;
20790
+ }
20791
+ if (b === true) {
20792
+ return first;
20793
+ }
20794
+ break;
20795
+ case TOKEN.min:
20796
+ if (second.type === PS_NODE.binary && second.op === TOKEN.max && second.first.type === PS_NODE.const && second.first.value >= b) {
20797
+ return first;
20798
+ }
20799
+ break;
20800
+ case TOKEN.max:
20801
+ if (second.type === PS_NODE.binary && second.op === TOKEN.min && second.first.type === PS_NODE.const && second.first.value <= b) {
20802
+ return first;
20803
+ }
20804
+ break;
20805
+ }
20806
+ }
20807
+ if (second.type === PS_NODE.const) {
20808
+ const a = second.value;
20809
+ switch (op) {
20810
+ case TOKEN.add:
20811
+ if (a === 0) {
20812
+ return first;
20813
+ }
20814
+ break;
20815
+ case TOKEN.sub:
20816
+ if (a === 0) {
20817
+ return this._makeUnary(TOKEN.neg, first);
20818
+ }
20819
+ break;
20820
+ case TOKEN.mul:
20821
+ if (a === 1) {
20822
+ return first;
20823
+ }
20824
+ if (a === 0) {
20825
+ return second;
20826
+ }
20827
+ if (a === -1) {
20828
+ return this._makeUnary(TOKEN.neg, first);
20829
+ }
20830
+ break;
20831
+ case TOKEN.and:
20832
+ if (a === true) {
20833
+ return first;
20834
+ }
20835
+ if (a === false) {
20836
+ return second;
20837
+ }
20838
+ break;
20839
+ case TOKEN.or:
20840
+ if (a === false) {
20841
+ return first;
20842
+ }
20843
+ if (a === true) {
20844
+ return second;
20845
+ }
20846
+ break;
20847
+ }
20848
+ }
20849
+ return new PsBinaryNode(
20850
+ op,
20851
+ first,
20852
+ second,
20853
+ _binaryValueType(op, first.valueType, second.valueType)
20854
+ );
20855
+ }
20856
+ /**
20857
+ * Create a unary tree node, applying optimizations eagerly:
20858
+ *
20859
+ * 1. Constant folding.
20860
+ * 2. not(comparison) → negated comparison: not(a eq b) → a ne b, etc.
20861
+ * 3. neg(a − b) → b − a.
20862
+ * 4. Double-negation: neg(neg(x)) → x, not(not(x)) → x.
20863
+ * 5. abs(neg(x)) → abs(x).
20864
+ * 6. Idempotent: f(f(x)) → f(x) for abs, ceiling, floor, round, etc.
20865
+ */
20866
+ _makeUnary(op, operand) {
20867
+ if (operand.type === PS_NODE.const) {
20868
+ const v = _evalUnaryConst(op, operand.value);
20869
+ if (v !== void 0) {
20870
+ return new PsConstNode(v);
20871
+ }
20872
+ }
20873
+ if (op === TOKEN.not && operand.type === PS_NODE.binary) {
20874
+ const negated = _PSStackToTree.#negatedComparison.get(operand.op);
20875
+ if (negated !== void 0) {
20876
+ return new PsBinaryNode(
20877
+ negated,
20878
+ operand.first,
20879
+ operand.second,
20880
+ PS_VALUE_TYPE.boolean
20881
+ );
20882
+ }
20883
+ }
20884
+ if (op === TOKEN.neg && operand.type === PS_NODE.binary && operand.op === TOKEN.sub) {
20885
+ return this._makeBinary(TOKEN.sub, operand.second, operand.first);
20886
+ }
20887
+ if (operand.type === PS_NODE.unary) {
20888
+ if (op === TOKEN.neg && operand.op === TOKEN.neg || op === TOKEN.not && operand.op === TOKEN.not) {
20889
+ return operand.operand;
20890
+ }
20891
+ if (op === TOKEN.abs && operand.op === TOKEN.neg) {
20892
+ return this._makeUnary(TOKEN.abs, operand.operand);
20893
+ }
20894
+ if (_PSStackToTree.#idempotentUnary.has(op) && op === operand.op) {
20895
+ return operand;
20896
+ }
20897
+ }
20898
+ return new PsUnaryNode(op, operand, _unaryValueType(op, operand.valueType));
20899
+ }
20900
+ /**
20901
+ * Create a ternary node, applying optimizations eagerly:
20902
+ *
20903
+ * 1. Constant condition — fold to the live branch.
20904
+ * 2. Identical branches — the condition is irrelevant, return either branch.
20905
+ * 3. Boolean branch constants — `cond ? true : false` → cond,
20906
+ * `cond ? false : true` → not(cond).
20907
+ * 4. Ternary → branchless min/max when the condition compares two numeric
20908
+ * expressions that are also the two branches.
20909
+ */
20910
+ _makeTernary(cond, then, otherwise) {
20911
+ if (cond.type === PS_NODE.const) {
20912
+ return cond.value ? then : otherwise;
20913
+ }
20914
+ if (_nodesEqual(then, otherwise)) {
20915
+ return then;
20916
+ }
20917
+ if (then.type === PS_NODE.const && otherwise.type === PS_NODE.const) {
20918
+ if (then.value === true && otherwise.value === false) {
20919
+ return cond;
20920
+ }
20921
+ if (then.value === false && otherwise.value === true) {
20922
+ return this._makeUnary(TOKEN.not, cond);
20923
+ }
20924
+ }
20925
+ if (cond.type === PS_NODE.binary) {
20926
+ const { op: cop, first: cf, second: cs } = cond;
20927
+ if (cop === TOKEN.gt || cop === TOKEN.ge) {
20928
+ if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
20929
+ return this._makeBinary(TOKEN.min, cf, cs);
20930
+ }
20931
+ if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
20932
+ return this._makeBinary(TOKEN.max, cf, cs);
20933
+ }
20934
+ } else if (cop === TOKEN.lt || cop === TOKEN.le) {
20935
+ if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
20936
+ return this._makeBinary(TOKEN.max, cf, cs);
20937
+ }
20938
+ if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
20939
+ return this._makeBinary(TOKEN.min, cf, cs);
20940
+ }
20941
+ }
20942
+ }
20943
+ return new PsTernaryNode(
20944
+ cond,
20945
+ then,
20946
+ otherwise,
20947
+ then.valueType === otherwise.valueType ? then.valueType : PS_VALUE_TYPE.unknown
20948
+ );
20949
+ }
20950
+ };
20951
+ var OP = {
20952
+ ARG: 0,
20953
+ // [ARG, idx]
20954
+ CONST: 1,
20955
+ // [CONST, val]
20956
+ STORE: 2,
20957
+ // [STORE, slot, min, max] clamp(pop()) → mem[slot]
20958
+ IF: 3,
20959
+ // [IF, target] jump when top-of-stack === 0
20960
+ JUMP: 4,
20961
+ // [JUMP, target] unconditional
20962
+ ABS: 5,
20963
+ NEG: 6,
20964
+ CEIL: 7,
20965
+ FLOOR: 8,
20966
+ ROUND: 9,
20967
+ // floor(x + 0.5)
20968
+ TRUNC: 10,
20969
+ NOT_B: 11,
20970
+ // boolean NOT
20971
+ NOT_N: 12,
20972
+ // bitwise NOT
20973
+ SQRT: 13,
20974
+ SIN: 14,
20975
+ // degrees in/out
20976
+ COS: 15,
20977
+ LN: 16,
20978
+ LOG10: 17,
20979
+ CVI: 18,
20980
+ SHIFT: 19,
20981
+ // [SHIFT, amount] +ve = left, −ve = right
20982
+ // Binary ops: second below, first on top; result = second OP first.
20983
+ ADD: 20,
20984
+ SUB: 21,
20985
+ MUL: 22,
20986
+ DIV: 23,
20987
+ // 0 when divisor is 0
20988
+ IDIV: 24,
20989
+ // 0 when divisor is 0
20990
+ MOD: 25,
20991
+ // 0 when divisor is 0
20992
+ POW: 26,
20993
+ EQ: 27,
20994
+ NE: 28,
20995
+ GT: 29,
20996
+ GE: 30,
20997
+ LT: 31,
20998
+ LE: 32,
20999
+ AND: 33,
21000
+ OR: 34,
21001
+ XOR: 35,
21002
+ ATAN: 36,
21003
+ // atan2(second, first) → degrees [0, 360)
21004
+ MIN: 37,
21005
+ MAX: 38,
21006
+ TEE_TMP: 39,
21007
+ // [TEE_TMP, slot] peek top of stack → tmp[slot], leave on stack
21008
+ LOAD_TMP: 40
21009
+ // [LOAD_TMP, slot] push tmp[slot]
21010
+ };
21011
+ var _DEG_TO_RAD = Math.PI / 180;
21012
+ var _RAD_TO_DEG = 180 / Math.PI;
21013
+ var PsJsCompiler = class {
21014
+ // Safe because JS is single-threaded.
21015
+ static #stack = new Float64Array(64);
21016
+ static #tmp = new Float64Array(64);
21017
+ constructor(domain, range) {
21018
+ this.nIn = domain.length >> 1;
21019
+ this.nOut = range.length >> 1;
21020
+ this.range = range;
21021
+ this.ir = [];
21022
+ this._tmpMap = /* @__PURE__ */ new Map();
21023
+ this._nextTmp = 0;
21024
+ }
21025
+ _compileNode(node) {
21026
+ if (node.shared) {
21027
+ const cached = this._tmpMap.get(node);
21028
+ if (cached !== void 0) {
21029
+ this.ir.push(OP.LOAD_TMP, cached);
21030
+ return true;
21031
+ }
21032
+ if (!this._compileNodeImpl(node)) {
21033
+ return false;
21034
+ }
21035
+ const slot = this._nextTmp++;
21036
+ this._tmpMap.set(node, slot);
21037
+ this.ir.push(OP.TEE_TMP, slot);
21038
+ return true;
21039
+ }
21040
+ return this._compileNodeImpl(node);
21041
+ }
21042
+ _compileNodeImpl(node) {
21043
+ switch (node.type) {
21044
+ case PS_NODE.arg:
21045
+ this.ir.push(OP.ARG, node.index);
21046
+ return true;
21047
+ case PS_NODE.const: {
21048
+ const v = node.value;
21049
+ this.ir.push(OP.CONST, typeof v === "boolean" ? Number(v) : v);
21050
+ return true;
21051
+ }
21052
+ case PS_NODE.unary:
21053
+ return this._compileUnary(node);
21054
+ case PS_NODE.binary:
21055
+ return this._compileBinary(node);
21056
+ case PS_NODE.ternary:
21057
+ return this._compileTernary(node);
21058
+ default:
21059
+ return false;
21060
+ }
21061
+ }
21062
+ _compileUnary(node) {
21063
+ const { op, operand, valueType } = node;
21064
+ if (op === TOKEN.cvr) {
21065
+ return this._compileNode(operand);
21066
+ }
21067
+ if (!this._compileNode(operand)) {
21068
+ return false;
21069
+ }
21070
+ switch (op) {
21071
+ case TOKEN.abs:
21072
+ this.ir.push(OP.ABS);
21073
+ break;
21074
+ case TOKEN.neg:
21075
+ this.ir.push(OP.NEG);
21076
+ break;
21077
+ case TOKEN.ceiling:
21078
+ this.ir.push(OP.CEIL);
21079
+ break;
21080
+ case TOKEN.floor:
21081
+ this.ir.push(OP.FLOOR);
21082
+ break;
21083
+ case TOKEN.round:
21084
+ this.ir.push(OP.ROUND);
21085
+ break;
21086
+ case TOKEN.truncate:
21087
+ this.ir.push(OP.TRUNC);
21088
+ break;
21089
+ case TOKEN.sqrt:
21090
+ this.ir.push(OP.SQRT);
21091
+ break;
21092
+ case TOKEN.sin:
21093
+ this.ir.push(OP.SIN);
21094
+ break;
21095
+ case TOKEN.cos:
21096
+ this.ir.push(OP.COS);
21097
+ break;
21098
+ case TOKEN.ln:
21099
+ this.ir.push(OP.LN);
21100
+ break;
21101
+ case TOKEN.log:
21102
+ this.ir.push(OP.LOG10);
21103
+ break;
21104
+ case TOKEN.cvi:
21105
+ this.ir.push(OP.CVI);
21106
+ break;
21107
+ case TOKEN.not:
21108
+ if (valueType === PS_VALUE_TYPE.boolean) {
21109
+ this.ir.push(OP.NOT_B);
21110
+ } else if (valueType === PS_VALUE_TYPE.numeric) {
21111
+ this.ir.push(OP.NOT_N);
21112
+ } else {
21113
+ return false;
21114
+ }
21115
+ break;
21116
+ default:
21117
+ return false;
21118
+ }
21119
+ return true;
21120
+ }
21121
+ _compileBinary(node) {
21122
+ const { op, first, second } = node;
21123
+ if (op === TOKEN.bitshift) {
21124
+ if (first.type !== PS_NODE.const || !Number.isInteger(first.value) || !this._compileNode(second)) {
21125
+ return false;
21126
+ }
21127
+ this.ir.push(OP.SHIFT, first.value);
21128
+ return true;
21129
+ }
21130
+ if (!this._compileNode(second) || !this._compileNode(first)) {
21131
+ return false;
21132
+ }
21133
+ switch (op) {
21134
+ case TOKEN.add:
21135
+ this.ir.push(OP.ADD);
21136
+ break;
21137
+ case TOKEN.sub:
21138
+ this.ir.push(OP.SUB);
21139
+ break;
21140
+ case TOKEN.mul:
21141
+ this.ir.push(OP.MUL);
21142
+ break;
21143
+ case TOKEN.div:
21144
+ this.ir.push(OP.DIV);
21145
+ break;
21146
+ case TOKEN.idiv:
21147
+ this.ir.push(OP.IDIV);
21148
+ break;
21149
+ case TOKEN.mod:
21150
+ this.ir.push(OP.MOD);
21151
+ break;
21152
+ case TOKEN.exp:
21153
+ this.ir.push(OP.POW);
21154
+ break;
21155
+ case TOKEN.eq:
21156
+ this.ir.push(OP.EQ);
21157
+ break;
21158
+ case TOKEN.ne:
21159
+ this.ir.push(OP.NE);
21160
+ break;
21161
+ case TOKEN.gt:
21162
+ this.ir.push(OP.GT);
21163
+ break;
21164
+ case TOKEN.ge:
21165
+ this.ir.push(OP.GE);
21166
+ break;
21167
+ case TOKEN.lt:
21168
+ this.ir.push(OP.LT);
21169
+ break;
21170
+ case TOKEN.le:
21171
+ this.ir.push(OP.LE);
21172
+ break;
21173
+ case TOKEN.and:
21174
+ this.ir.push(OP.AND);
21175
+ break;
21176
+ case TOKEN.or:
21177
+ this.ir.push(OP.OR);
21178
+ break;
21179
+ case TOKEN.xor:
21180
+ this.ir.push(OP.XOR);
21181
+ break;
21182
+ case TOKEN.atan:
21183
+ this.ir.push(OP.ATAN);
21184
+ break;
21185
+ case TOKEN.min:
21186
+ this.ir.push(OP.MIN);
21187
+ break;
21188
+ case TOKEN.max:
21189
+ this.ir.push(OP.MAX);
21190
+ break;
21191
+ default:
21192
+ return false;
21193
+ }
21194
+ return true;
21195
+ }
21196
+ _compileTernary(node) {
21197
+ if (!this._compileNode(node.cond)) {
21198
+ return false;
21199
+ }
21200
+ this.ir.push(OP.IF, 0);
21201
+ const ifPatch = this.ir.length - 1;
21202
+ if (!this._compileNode(node.then)) {
21203
+ return false;
21204
+ }
21205
+ this.ir.push(OP.JUMP, 0);
21206
+ const jumpPatch = this.ir.length - 1;
21207
+ this.ir[ifPatch] = this.ir.length;
21208
+ if (!this._compileNode(node.otherwise)) {
21209
+ return false;
21210
+ }
21211
+ this.ir[jumpPatch] = this.ir.length;
21212
+ return true;
21213
+ }
21214
+ compile(program) {
21215
+ const outputs = new PSStackToTree().evaluate(program, this.nIn);
21216
+ if (!outputs || outputs.length < this.nOut) {
21217
+ return null;
21218
+ }
21219
+ for (let i = 0; i < this.nOut; i++) {
21220
+ if (!this._compileNode(outputs[i])) {
21221
+ return null;
21222
+ }
21223
+ const min = this.range[i * 2];
21224
+ const max = this.range[i * 2 + 1];
21225
+ this.ir.push(OP.STORE, i, min, max);
21226
+ }
21227
+ return new Float64Array(this.ir);
21228
+ }
21229
+ static execute(ir, src, srcOffset, dest, destOffset) {
21230
+ let ip = 0, sp = 0;
21231
+ const n = ir.length;
21232
+ const stack = this.#stack;
21233
+ const tmp = this.#tmp;
21234
+ while (ip < n) {
21235
+ switch (ir[ip++] | 0) {
21236
+ case OP.ARG:
21237
+ stack[sp++] = src[srcOffset + (ir[ip++] | 0)];
21238
+ break;
21239
+ case OP.CONST:
21240
+ stack[sp++] = ir[ip++];
21241
+ break;
21242
+ case OP.STORE: {
21243
+ const slot = ir[ip++] | 0;
21244
+ const min = ir[ip++];
21245
+ const max = ir[ip++];
21246
+ dest[destOffset + slot] = MathClamp(stack[--sp], min, max);
21247
+ break;
21248
+ }
21249
+ case OP.IF: {
21250
+ const tgt = ir[ip++];
21251
+ if (stack[--sp] === 0) {
21252
+ ip = tgt;
21253
+ }
21254
+ break;
21255
+ }
21256
+ case OP.JUMP:
21257
+ ip = ir[ip];
21258
+ break;
21259
+ case OP.ABS:
21260
+ stack[sp - 1] = Math.abs(stack[sp - 1]);
21261
+ break;
21262
+ case OP.NEG:
21263
+ stack[sp - 1] = -stack[sp - 1];
21264
+ break;
21265
+ case OP.CEIL:
21266
+ stack[sp - 1] = Math.ceil(stack[sp - 1]);
21267
+ break;
21268
+ case OP.FLOOR:
21269
+ stack[sp - 1] = Math.floor(stack[sp - 1]);
21270
+ break;
21271
+ case OP.ROUND:
21272
+ stack[sp - 1] = Math.floor(stack[sp - 1] + 0.5);
21273
+ break;
21274
+ case OP.TRUNC:
21275
+ stack[sp - 1] = Math.trunc(stack[sp - 1]);
21276
+ break;
21277
+ case OP.NOT_B:
21278
+ stack[sp - 1] = stack[sp - 1] !== 0 ? 0 : 1;
21279
+ break;
21280
+ case OP.NOT_N:
21281
+ stack[sp - 1] = ~(stack[sp - 1] | 0);
21282
+ break;
21283
+ case OP.SQRT:
21284
+ stack[sp - 1] = Math.sqrt(stack[sp - 1]);
21285
+ break;
21286
+ case OP.SIN:
21287
+ stack[sp - 1] = Math.sin(stack[sp - 1] % 360 * _DEG_TO_RAD);
21288
+ break;
21289
+ case OP.COS:
21290
+ stack[sp - 1] = Math.cos(stack[sp - 1] % 360 * _DEG_TO_RAD);
21291
+ break;
21292
+ case OP.LN:
21293
+ stack[sp - 1] = Math.log(stack[sp - 1]);
21294
+ break;
21295
+ case OP.LOG10:
21296
+ stack[sp - 1] = Math.log10(stack[sp - 1]);
21297
+ break;
21298
+ case OP.CVI:
21299
+ stack[sp - 1] = Math.trunc(stack[sp - 1]) | 0;
21300
+ break;
21301
+ case OP.SHIFT: {
21302
+ const amt = ir[ip++];
21303
+ const v = stack[sp - 1] | 0;
21304
+ if (amt > 0) {
21305
+ stack[sp - 1] = v << amt;
21306
+ } else if (amt < 0) {
21307
+ stack[sp - 1] = v >> -amt;
21308
+ } else {
21309
+ stack[sp - 1] = v;
21310
+ }
21311
+ break;
21312
+ }
21313
+ case OP.ADD: {
21314
+ const b = stack[--sp];
21315
+ stack[sp - 1] += b;
21316
+ break;
21317
+ }
21318
+ case OP.SUB: {
21319
+ const b = stack[--sp];
21320
+ stack[sp - 1] -= b;
21321
+ break;
21322
+ }
21323
+ case OP.MUL: {
21324
+ const b = stack[--sp];
21325
+ stack[sp - 1] *= b;
21326
+ break;
21327
+ }
21328
+ case OP.DIV: {
21329
+ const b = stack[--sp];
21330
+ stack[sp - 1] = b !== 0 ? stack[sp - 1] / b : 0;
21331
+ break;
21332
+ }
21333
+ case OP.IDIV: {
21334
+ const b = stack[--sp];
21335
+ stack[sp - 1] = b !== 0 ? Math.trunc(stack[sp - 1] / b) : 0;
21336
+ break;
21337
+ }
21338
+ case OP.MOD: {
21339
+ const b = stack[--sp];
21340
+ stack[sp - 1] = b !== 0 ? stack[sp - 1] % b : 0;
21341
+ break;
21342
+ }
21343
+ case OP.POW: {
21344
+ const b = stack[--sp];
21345
+ stack[sp - 1] **= b;
21346
+ break;
21347
+ }
21348
+ case OP.EQ: {
21349
+ const b = stack[--sp];
21350
+ stack[sp - 1] = stack[sp - 1] === b ? 1 : 0;
21351
+ break;
21352
+ }
21353
+ case OP.NE: {
21354
+ const b = stack[--sp];
21355
+ stack[sp - 1] = stack[sp - 1] !== b ? 1 : 0;
21356
+ break;
21357
+ }
21358
+ case OP.GT: {
21359
+ const b = stack[--sp];
21360
+ stack[sp - 1] = stack[sp - 1] > b ? 1 : 0;
21361
+ break;
21362
+ }
21363
+ case OP.GE: {
21364
+ const b = stack[--sp];
21365
+ stack[sp - 1] = stack[sp - 1] >= b ? 1 : 0;
21366
+ break;
21367
+ }
21368
+ case OP.LT: {
21369
+ const b = stack[--sp];
21370
+ stack[sp - 1] = stack[sp - 1] < b ? 1 : 0;
21371
+ break;
21372
+ }
21373
+ case OP.LE: {
21374
+ const b = stack[--sp];
21375
+ stack[sp - 1] = stack[sp - 1] <= b ? 1 : 0;
21376
+ break;
21377
+ }
21378
+ case OP.AND: {
21379
+ const b = stack[--sp] | 0;
21380
+ stack[sp - 1] = (stack[sp - 1] | 0) & b;
21381
+ break;
21382
+ }
21383
+ case OP.OR: {
21384
+ const b = stack[--sp] | 0;
21385
+ stack[sp - 1] = stack[sp - 1] | 0 | b;
21386
+ break;
21387
+ }
21388
+ case OP.XOR: {
21389
+ const b = stack[--sp] | 0;
21390
+ stack[sp - 1] = (stack[sp - 1] | 0) ^ b;
21391
+ break;
21392
+ }
21393
+ case OP.ATAN: {
21394
+ const b = stack[--sp];
21395
+ const deg = Math.atan2(stack[sp - 1], b) * _RAD_TO_DEG;
21396
+ stack[sp - 1] = deg < 0 ? deg + 360 : deg;
21397
+ break;
21398
+ }
21399
+ case OP.MIN: {
21400
+ const b = stack[--sp];
21401
+ stack[sp - 1] = Math.min(stack[sp - 1], b);
21402
+ break;
21403
+ }
21404
+ case OP.MAX: {
21405
+ const b = stack[--sp];
21406
+ stack[sp - 1] = Math.max(stack[sp - 1], b);
21407
+ break;
21408
+ }
21409
+ case OP.TEE_TMP:
21410
+ tmp[ir[ip++] | 0] = stack[sp - 1];
21411
+ break;
21412
+ case OP.LOAD_TMP:
21413
+ stack[sp++] = tmp[ir[ip++] | 0];
21414
+ break;
21415
+ }
21416
+ }
21417
+ }
21418
+ };
21419
+ var PSStackBasedInterpreter = class {
21420
+ // Safe: JS is single-threaded.
21421
+ static #stack = new Float64Array(100);
21422
+ static #sp = 0;
21423
+ static #push(v) {
21424
+ if (this.#sp < this.#stack.length) {
21425
+ this.#stack[this.#sp++] = v;
21426
+ }
21427
+ }
21428
+ static #execOp(op) {
21429
+ const stack = this.#stack;
21430
+ switch (op) {
21431
+ case TOKEN.true:
21432
+ this.#push(1);
21433
+ break;
21434
+ case TOKEN.false:
21435
+ this.#push(0);
21436
+ break;
21437
+ case TOKEN.abs:
21438
+ stack[this.#sp - 1] = Math.abs(stack[this.#sp - 1]);
21439
+ break;
21440
+ case TOKEN.neg:
21441
+ stack[this.#sp - 1] = -stack[this.#sp - 1];
21442
+ break;
21443
+ case TOKEN.ceiling:
21444
+ stack[this.#sp - 1] = Math.ceil(stack[this.#sp - 1]);
21445
+ break;
21446
+ case TOKEN.floor:
21447
+ stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1]);
21448
+ break;
21449
+ case TOKEN.round:
21450
+ stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1] + 0.5);
21451
+ break;
21452
+ case TOKEN.truncate:
21453
+ stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]);
21454
+ break;
21455
+ case TOKEN.sqrt:
21456
+ stack[this.#sp - 1] = Math.sqrt(stack[this.#sp - 1]);
21457
+ break;
21458
+ case TOKEN.sin:
21459
+ stack[this.#sp - 1] = Math.sin(
21460
+ stack[this.#sp - 1] % 360 * _DEG_TO_RAD
21461
+ );
21462
+ break;
21463
+ case TOKEN.cos:
21464
+ stack[this.#sp - 1] = Math.cos(
21465
+ stack[this.#sp - 1] % 360 * _DEG_TO_RAD
21466
+ );
21467
+ break;
21468
+ case TOKEN.ln:
21469
+ stack[this.#sp - 1] = Math.log(stack[this.#sp - 1]);
21470
+ break;
21471
+ case TOKEN.log:
21472
+ stack[this.#sp - 1] = Math.log10(stack[this.#sp - 1]);
21473
+ break;
21474
+ case TOKEN.cvi:
21475
+ stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]) | 0;
21476
+ break;
21477
+ case TOKEN.cvr:
21478
+ break;
21479
+ // values are already f64
21480
+ case TOKEN.not: {
21481
+ const v = stack[this.#sp - 1];
21482
+ stack[this.#sp - 1] = v === 0 || v === 1 ? 1 - v : ~(v | 0);
21483
+ break;
21484
+ }
21485
+ case TOKEN.add: {
21486
+ const b = stack[--this.#sp];
21487
+ stack[this.#sp - 1] += b;
21488
+ break;
21489
+ }
21490
+ case TOKEN.sub: {
21491
+ const b = stack[--this.#sp];
21492
+ stack[this.#sp - 1] -= b;
21493
+ break;
21494
+ }
21495
+ case TOKEN.mul: {
21496
+ const b = stack[--this.#sp];
21497
+ stack[this.#sp - 1] *= b;
21498
+ break;
21499
+ }
21500
+ case TOKEN.div: {
21501
+ const b = stack[--this.#sp];
21502
+ stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] / b : 0;
21503
+ break;
21504
+ }
21505
+ case TOKEN.idiv: {
21506
+ const b = stack[--this.#sp];
21507
+ stack[this.#sp - 1] = b !== 0 ? Math.trunc(stack[this.#sp - 1] / b) : 0;
21508
+ break;
21509
+ }
21510
+ case TOKEN.mod: {
21511
+ const b = stack[--this.#sp];
21512
+ stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] % b : 0;
21513
+ break;
21514
+ }
21515
+ case TOKEN.exp: {
21516
+ const b = stack[--this.#sp];
21517
+ stack[this.#sp - 1] **= b;
21518
+ break;
21519
+ }
21520
+ case TOKEN.atan: {
21521
+ const dx = stack[--this.#sp];
21522
+ const deg = Math.atan2(stack[this.#sp - 1], dx) * _RAD_TO_DEG;
21523
+ stack[this.#sp - 1] = deg < 0 ? deg + 360 : deg;
21524
+ break;
21525
+ }
21526
+ case TOKEN.eq: {
21527
+ const b = stack[--this.#sp];
21528
+ stack[this.#sp - 1] = stack[this.#sp - 1] === b ? 1 : 0;
21529
+ break;
21530
+ }
21531
+ case TOKEN.ne: {
21532
+ const b = stack[--this.#sp];
21533
+ stack[this.#sp - 1] = stack[this.#sp - 1] !== b ? 1 : 0;
21534
+ break;
21535
+ }
21536
+ case TOKEN.gt: {
21537
+ const b = stack[--this.#sp];
21538
+ stack[this.#sp - 1] = stack[this.#sp - 1] > b ? 1 : 0;
21539
+ break;
21540
+ }
21541
+ case TOKEN.ge: {
21542
+ const b = stack[--this.#sp];
21543
+ stack[this.#sp - 1] = stack[this.#sp - 1] >= b ? 1 : 0;
21544
+ break;
21545
+ }
21546
+ case TOKEN.lt: {
21547
+ const b = stack[--this.#sp];
21548
+ stack[this.#sp - 1] = stack[this.#sp - 1] < b ? 1 : 0;
21549
+ break;
21550
+ }
21551
+ case TOKEN.le: {
21552
+ const b = stack[--this.#sp];
21553
+ stack[this.#sp - 1] = stack[this.#sp - 1] <= b ? 1 : 0;
21554
+ break;
21555
+ }
21556
+ case TOKEN.and: {
21557
+ const b = stack[--this.#sp] | 0;
21558
+ stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) & b;
21559
+ break;
21560
+ }
21561
+ case TOKEN.or: {
21562
+ const b = stack[--this.#sp] | 0;
21563
+ stack[this.#sp - 1] = stack[this.#sp - 1] | 0 | b;
21564
+ break;
21565
+ }
21566
+ case TOKEN.xor: {
21567
+ const b = stack[--this.#sp] | 0;
21568
+ stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) ^ b;
21569
+ break;
21570
+ }
21571
+ case TOKEN.bitshift: {
21572
+ const amt = stack[--this.#sp] | 0;
21573
+ const v = stack[this.#sp - 1] | 0;
21574
+ stack[this.#sp - 1] = amt > 0 ? v << amt : v >> -amt;
21575
+ break;
21576
+ }
21577
+ case TOKEN.min: {
21578
+ const b = stack[--this.#sp];
21579
+ stack[this.#sp - 1] = Math.min(stack[this.#sp - 1], b);
21580
+ break;
21581
+ }
21582
+ case TOKEN.max: {
21583
+ const b = stack[--this.#sp];
21584
+ stack[this.#sp - 1] = Math.max(stack[this.#sp - 1], b);
21585
+ break;
21586
+ }
21587
+ case TOKEN.dup:
21588
+ this.#push(stack[this.#sp - 1]);
21589
+ break;
21590
+ case TOKEN.exch: {
21591
+ const a = stack[--this.#sp];
21592
+ const b = stack[--this.#sp];
21593
+ this.#push(a);
21594
+ this.#push(b);
21595
+ break;
21596
+ }
21597
+ case TOKEN.pop:
21598
+ this.#sp--;
21599
+ break;
21600
+ case TOKEN.copy: {
21601
+ const n = Math.trunc(stack[--this.#sp]);
21602
+ const base = this.#sp - n;
21603
+ for (let k = 0; k < n; k++) {
21604
+ this.#push(stack[base + k]);
21605
+ }
21606
+ break;
21607
+ }
21608
+ case TOKEN.index: {
21609
+ const i = Math.trunc(stack[--this.#sp]);
21610
+ this.#push(stack[this.#sp - 1 - i]);
21611
+ break;
21612
+ }
21613
+ case TOKEN.roll: {
21614
+ const j = Math.trunc(stack[--this.#sp]);
21615
+ const n = Math.trunc(stack[--this.#sp]);
21616
+ if (n > 1 && j !== 0) {
21617
+ const mod = (j % n + n) % n;
21618
+ if (mod !== 0) {
21619
+ const base = this.#sp - n;
21620
+ const sub = stack.slice(base, this.#sp);
21621
+ for (let k = 0; k < n; k++) {
21622
+ stack[base + k] = sub[(k - mod + n) % n];
21623
+ }
21624
+ }
21625
+ }
21626
+ break;
21627
+ }
21628
+ }
21629
+ }
21630
+ static #execBlock(instructions) {
21631
+ for (const instr of instructions) {
21632
+ switch (instr.type) {
21633
+ case PS_NODE.number:
21634
+ this.#push(instr.value);
21635
+ break;
21636
+ case PS_NODE.operator:
21637
+ this.#execOp(instr.op);
21638
+ break;
21639
+ case PS_NODE.if:
21640
+ if (this.#stack[--this.#sp] !== 0) {
21641
+ this.#execBlock(instr.then.instructions);
21642
+ }
21643
+ break;
21644
+ case PS_NODE.ifelse:
21645
+ if (this.#stack[--this.#sp] !== 0) {
21646
+ this.#execBlock(instr.then.instructions);
21647
+ } else {
21648
+ this.#execBlock(instr.otherwise.instructions);
21649
+ }
21650
+ break;
21651
+ }
21652
+ }
21653
+ }
21654
+ /**
21655
+ * @param {import("./ast.js").PsProgram} program
21656
+ * @param {number[]} domain – flat [min0,max0, …]
21657
+ * @param {number[]} range – flat [min0,max0, …]
21658
+ * @returns {Function} – `(src, srcOffset, dest, destOffset) => void`
21659
+ */
21660
+ static build(program, domain, range) {
21661
+ const nIn = domain.length >> 1;
21662
+ const nOut = range.length >> 1;
21663
+ const { instructions } = program.body;
21664
+ return (src, srcOffset, dest, destOffset) => {
21665
+ this.#sp = 0;
21666
+ for (let i = 0; i < nIn; i++) {
21667
+ this.#push(src[srcOffset + i]);
21668
+ }
21669
+ this.#execBlock(instructions);
21670
+ const base = this.#sp - nOut;
21671
+ for (let i = 0; i < nOut; i++) {
21672
+ const v = base + i >= 0 ? this.#stack[base + i] : 0;
21673
+ dest[destOffset + i] = MathClamp(v, range[i * 2], range[i * 2 + 1]);
21674
+ }
21675
+ };
21676
+ }
21677
+ };
21678
+ function buildPostScriptJsFunction(source, domain, range, forceInterpreter = false) {
21679
+ const program = parsePostScriptFunction(source);
21680
+ const ir = !forceInterpreter && new PsJsCompiler(domain, range).compile(program);
21681
+ if (ir) {
21682
+ return (src, srcOffset, dest, destOffset) => {
21683
+ PsJsCompiler.execute(ir, src, srcOffset, dest, destOffset);
21684
+ };
21685
+ }
21686
+ return PSStackBasedInterpreter.build(program, domain, range);
21687
+ }
21688
+ var ShadingType = {
21689
+ FUNCTION_BASED: 1,
21690
+ AXIAL: 2,
21691
+ RADIAL: 3,
21692
+ FREE_FORM_MESH: 4,
21693
+ LATTICE_FORM_MESH: 5,
21694
+ COONS_PATCH_MESH: 6,
21695
+ TENSOR_PATCH_MESH: 7
21696
+ };
21697
+ var BaseShading = class _BaseShading {
21698
+ // A small number to offset the first/last color stops so we can insert ones
21699
+ // to support extend. Number.MIN_VALUE is too small and breaks the extend.
21700
+ static SMALL_NUMBER = 1e-6;
21701
+ constructor() {
21702
+ if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _BaseShading) {
21703
+ unreachable2("Cannot initialize BaseShading.");
21704
+ }
21705
+ }
21706
+ getIR() {
21707
+ unreachable2("Abstract method `getIR` called.");
21708
+ }
21709
+ };
21710
+ function meshUpdateBounds(self) {
21711
+ let minX = self.coords[0][0], minY = self.coords[0][1], maxX = minX, maxY = minY;
21712
+ for (let i = 1, ii = self.coords.length; i < ii; i++) {
21713
+ const x = self.coords[i][0], y = self.coords[i][1];
21714
+ minX = minX > x ? x : minX;
21715
+ minY = minY > y ? y : minY;
21716
+ maxX = maxX < x ? x : maxX;
21717
+ maxY = maxY < y ? y : maxY;
21718
+ }
21719
+ self.bounds = [minX, minY, maxX, maxY];
21720
+ }
21721
+ function meshPackData(self) {
21722
+ let i, j, ii;
21723
+ const coords = self.coords;
21724
+ const coordsPacked = new Float32Array(coords.length * 2);
21725
+ for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
21726
+ const xy = coords[i];
21727
+ coordsPacked[j++] = xy[0];
21728
+ coordsPacked[j++] = xy[1];
21729
+ }
21730
+ self.coords = coordsPacked;
21731
+ const colors = self.colors;
21732
+ const colorsPacked = new Uint8Array(colors.length * 4);
21733
+ for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
21734
+ const c = colors[i];
21735
+ colorsPacked[j++] = c[0];
21736
+ colorsPacked[j++] = c[1];
21737
+ colorsPacked[j++] = c[2];
21738
+ j++;
21739
+ }
21740
+ self.colors = colorsPacked;
21741
+ for (const figure of self.figures) {
21742
+ figure.coords = new Uint32Array(figure.coords);
21743
+ figure.colors = new Uint32Array(figure.colors);
21744
+ }
21745
+ }
21746
+ function buildMeshVertexData(coords, colors, figures) {
21747
+ let vertexCount = 0;
21748
+ for (const figure of figures) {
21749
+ if (figure.type === MeshFigureType.TRIANGLES) {
21750
+ vertexCount += figure.coords.length;
21751
+ } else if (figure.type === MeshFigureType.LATTICE) {
21752
+ const vpr = figure.verticesPerRow;
21753
+ vertexCount += (Math.floor(figure.coords.length / vpr) - 1) * (vpr - 1) * 6;
21754
+ }
21755
+ }
21756
+ const posData = new Float32Array(vertexCount * 2);
21757
+ const colData = new Uint8Array(vertexCount * 4);
21758
+ let pOff = 0, cOff = 0;
21759
+ const addVertex = (pi, ci) => {
21760
+ posData[pOff++] = coords[pi * 2];
21761
+ posData[pOff++] = coords[pi * 2 + 1];
21762
+ colData[cOff++] = colors[ci * 4];
21763
+ colData[cOff++] = colors[ci * 4 + 1];
21764
+ colData[cOff++] = colors[ci * 4 + 2];
21765
+ cOff++;
21766
+ };
21767
+ for (const figure of figures) {
21768
+ const ps = figure.coords;
21769
+ const cs = figure.colors;
21770
+ if (figure.type === MeshFigureType.TRIANGLES) {
21771
+ for (let i = 0, ii = ps.length; i < ii; i++) {
21772
+ addVertex(ps[i], cs[i]);
21773
+ }
21774
+ } else if (figure.type === MeshFigureType.LATTICE) {
21775
+ const vpr = figure.verticesPerRow;
21776
+ const rows = Math.floor(ps.length / vpr) - 1;
21777
+ const cols = vpr - 1;
21778
+ for (let i = 0; i < rows; i++) {
21779
+ let q = i * vpr;
21780
+ for (let j = 0; j < cols; j++, q++) {
21781
+ addVertex(ps[q], cs[q]);
21782
+ addVertex(ps[q + 1], cs[q + 1]);
21783
+ addVertex(ps[q + vpr], cs[q + vpr]);
21784
+ addVertex(ps[q + vpr + 1], cs[q + vpr + 1]);
21785
+ addVertex(ps[q + 1], cs[q + 1]);
21786
+ addVertex(ps[q + vpr], cs[q + vpr]);
21787
+ }
21788
+ }
21789
+ }
21790
+ }
21791
+ return { posData, colData, vertexCount };
21792
+ }
21793
+ var MeshStreamReader = class {
21794
+ constructor(stream, context) {
21795
+ this.stream = stream;
21796
+ this.context = context;
21797
+ this.buffer = 0;
21798
+ this.bufferLength = 0;
21799
+ const numComps = context.numComps;
21800
+ this.tmpCompsBuf = new Float32Array(numComps);
21801
+ const csNumComps = context.colorSpace.numComps;
21802
+ this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf;
21803
+ }
21804
+ get hasData() {
21805
+ if (this.stream.end) {
21806
+ return this.stream.pos < this.stream.end;
21807
+ }
21808
+ if (this.bufferLength > 0) {
21809
+ return true;
21810
+ }
21811
+ const nextByte = this.stream.getByte();
21812
+ if (nextByte < 0) {
21813
+ return false;
21814
+ }
21815
+ this.buffer = nextByte;
21816
+ this.bufferLength = 8;
21817
+ return true;
21818
+ }
21819
+ readBits(n) {
21820
+ const { stream } = this;
21821
+ let { buffer, bufferLength } = this;
21822
+ if (n === 32) {
21823
+ if (bufferLength === 0) {
21824
+ return stream.getInt32() >>> 0;
21825
+ }
21826
+ buffer = buffer << 24 | stream.getByte() << 16 | stream.getByte() << 8 | stream.getByte();
21827
+ const nextByte = stream.getByte();
21828
+ this.buffer = nextByte & (1 << bufferLength) - 1;
21829
+ return (buffer << 8 - bufferLength | (nextByte & 255) >> bufferLength) >>> 0;
21830
+ }
21831
+ if (n === 8 && bufferLength === 0) {
21832
+ return stream.getByte();
21833
+ }
21834
+ while (bufferLength < n) {
21835
+ buffer = buffer << 8 | stream.getByte();
21836
+ bufferLength += 8;
21837
+ }
21838
+ bufferLength -= n;
21839
+ this.bufferLength = bufferLength;
21840
+ this.buffer = buffer & (1 << bufferLength) - 1;
21841
+ return buffer >> bufferLength;
21842
+ }
21843
+ align() {
21844
+ this.buffer = 0;
21845
+ this.bufferLength = 0;
21846
+ }
21847
+ readFlag() {
21848
+ return this.readBits(this.context.bitsPerFlag);
21849
+ }
21850
+ readCoordinate() {
21851
+ const { bitsPerCoordinate, decode } = this.context;
21852
+ const xi = this.readBits(bitsPerCoordinate);
21853
+ const yi = this.readBits(bitsPerCoordinate);
21854
+ const scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 23283064365386963e-26;
21855
+ return [
21856
+ xi * scale * (decode[1] - decode[0]) + decode[0],
21857
+ yi * scale * (decode[3] - decode[2]) + decode[2]
21858
+ ];
21859
+ }
21860
+ readComponents() {
21861
+ const { bitsPerComponent, colorFn, colorSpace, decode, numComps } = this.context;
21862
+ const scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 23283064365386963e-26;
21863
+ const components = this.tmpCompsBuf;
21864
+ for (let i = 0, j = 4; i < numComps; i++, j += 2) {
21865
+ const ci = this.readBits(bitsPerComponent);
21866
+ components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j];
21867
+ }
21868
+ const color = this.tmpCsCompsBuf;
21869
+ colorFn?.(components, 0, color, 0);
21870
+ return colorSpace.getRgb(color, 0);
21871
+ }
21872
+ };
21873
+ var bCache = null;
21874
+ function getB(count) {
21875
+ if (bCache?.has(count)) return bCache.get(count);
21876
+ const values = Array.from({ length: count + 1 }, (_, i) => {
21877
+ const t = i / count, t_ = 1 - t;
21878
+ return new Float32Array([
21879
+ t_ ** 3,
21880
+ 3 * t * t_ ** 2,
21881
+ 3 * t ** 2 * t_,
21882
+ t ** 3
21883
+ ]);
21884
+ });
21885
+ (bCache ??= /* @__PURE__ */ new Map()).set(count, values);
21886
+ return values;
21887
+ }
21888
+ var MeshShading = class _MeshShading extends BaseShading {
21889
+ static MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;
21890
+ static MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;
21891
+ // Count of triangles per entire mesh bounds.
21892
+ static TRIANGLE_DENSITY = 20;
21893
+ constructor(shadingType, stream, context, rowVertices) {
21894
+ super();
21895
+ this.shadingType = shadingType;
21896
+ this.bbox = this.background = null;
21897
+ this.coords = [];
21898
+ this.colors = [];
21899
+ this.figures = [];
21900
+ const reader = new MeshStreamReader(stream, context);
21901
+ let patchMesh = false;
21902
+ switch (this.shadingType) {
21903
+ case ShadingType.FREE_FORM_MESH:
21904
+ this._decodeType4Shading(reader);
21905
+ break;
21906
+ case ShadingType.LATTICE_FORM_MESH:
21907
+ const verticesPerRow = rowVertices | 0;
21908
+ if (verticesPerRow < 2) {
21909
+ throw new FormatError("Invalid VerticesPerRow");
21910
+ }
21911
+ this._decodeType5Shading(reader, verticesPerRow);
21912
+ break;
21913
+ case ShadingType.COONS_PATCH_MESH:
21914
+ this._decodeType6Shading(reader);
21915
+ patchMesh = true;
21916
+ break;
21917
+ case ShadingType.TENSOR_PATCH_MESH:
21918
+ this._decodeType7Shading(reader);
21919
+ patchMesh = true;
21920
+ break;
21921
+ default:
21922
+ unreachable2("Unsupported mesh type.");
21923
+ break;
21924
+ }
21925
+ if (patchMesh) {
21926
+ this._updateBounds();
21927
+ for (let i = 0, ii = this.figures.length; i < ii; i++) {
21928
+ this._buildFigureFromPatch(i);
21929
+ }
21930
+ }
21931
+ this._updateBounds();
21932
+ this._packData();
21933
+ }
21934
+ _decodeType4Shading(reader) {
21935
+ const coords = this.coords;
21936
+ const colors = this.colors;
21937
+ const operators = [];
21938
+ const ps = [];
21939
+ let verticesLeft = 0;
21940
+ while (reader.hasData) {
21941
+ const f = reader.readFlag();
21942
+ const coord = reader.readCoordinate();
21943
+ const color = reader.readComponents();
21944
+ if (verticesLeft === 0) {
21945
+ if (!(0 <= f && f <= 2)) {
21946
+ throw new FormatError("Unknown type4 flag");
21947
+ }
21948
+ switch (f) {
21949
+ case 0:
21950
+ verticesLeft = 3;
21951
+ break;
21952
+ case 1:
21953
+ ps.push(ps.at(-2), ps.at(-1));
21954
+ verticesLeft = 1;
21955
+ break;
21956
+ case 2:
21957
+ ps.push(ps.at(-3), ps.at(-1));
21958
+ verticesLeft = 1;
21959
+ break;
21960
+ }
21961
+ operators.push(f);
21962
+ }
21963
+ ps.push(coords.length);
21964
+ coords.push(coord);
21965
+ colors.push(color);
21966
+ verticesLeft--;
21967
+ reader.align();
21968
+ }
21969
+ this.figures.push({
21970
+ type: MeshFigureType.TRIANGLES,
21971
+ coords: new Int32Array(ps),
21972
+ colors: new Int32Array(ps)
21973
+ });
21974
+ }
21975
+ _decodeType5Shading(reader, verticesPerRow) {
21976
+ const coords = this.coords;
21977
+ const colors = this.colors;
21978
+ const ps = [];
21979
+ while (reader.hasData) {
21980
+ const coord = reader.readCoordinate();
21981
+ const color = reader.readComponents();
21982
+ ps.push(coords.length);
21983
+ coords.push(coord);
21984
+ colors.push(color);
21985
+ }
21986
+ this.figures.push({
21987
+ type: MeshFigureType.LATTICE,
21988
+ coords: new Int32Array(ps),
21989
+ colors: new Int32Array(ps),
21990
+ verticesPerRow
21991
+ });
21992
+ }
21993
+ _decodeType6Shading(reader) {
21994
+ const coords = this.coords;
21995
+ const colors = this.colors;
21996
+ const ps = new Int32Array(16);
21997
+ const cs = new Int32Array(4);
21998
+ while (reader.hasData) {
21999
+ const f = reader.readFlag();
22000
+ if (!(0 <= f && f <= 3)) {
22001
+ throw new FormatError("Unknown type6 flag");
22002
+ }
22003
+ const pi = coords.length;
22004
+ for (let i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) {
22005
+ coords.push(reader.readCoordinate());
22006
+ }
22007
+ const ci = colors.length;
22008
+ for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
22009
+ colors.push(reader.readComponents());
22010
+ }
22011
+ let tmp1, tmp2, tmp3, tmp4;
22012
+ switch (f) {
22013
+ // prettier-ignore
22014
+ case 0:
22015
+ ps[12] = pi + 3;
22016
+ ps[13] = pi + 4;
22017
+ ps[14] = pi + 5;
22018
+ ps[15] = pi + 6;
22019
+ ps[8] = pi + 2;
22020
+ ps[11] = pi + 7;
22021
+ ps[4] = pi + 1;
22022
+ ps[7] = pi + 8;
22023
+ ps[0] = pi;
22024
+ ps[1] = pi + 11;
22025
+ ps[2] = pi + 10;
22026
+ ps[3] = pi + 9;
22027
+ cs[2] = ci + 1;
22028
+ cs[3] = ci + 2;
22029
+ cs[0] = ci;
22030
+ cs[1] = ci + 3;
22031
+ break;
22032
+ // prettier-ignore
22033
+ case 1:
22034
+ tmp1 = ps[12];
22035
+ tmp2 = ps[13];
22036
+ tmp3 = ps[14];
22037
+ tmp4 = ps[15];
22038
+ ps[12] = tmp4;
22039
+ ps[13] = pi + 0;
22040
+ ps[14] = pi + 1;
22041
+ ps[15] = pi + 2;
22042
+ ps[8] = tmp3;
22043
+ ps[11] = pi + 3;
22044
+ ps[4] = tmp2;
22045
+ ps[7] = pi + 4;
22046
+ ps[0] = tmp1;
22047
+ ps[1] = pi + 7;
22048
+ ps[2] = pi + 6;
22049
+ ps[3] = pi + 5;
22050
+ tmp1 = cs[2];
22051
+ tmp2 = cs[3];
22052
+ cs[2] = tmp2;
22053
+ cs[3] = ci;
22054
+ cs[0] = tmp1;
22055
+ cs[1] = ci + 1;
22056
+ break;
22057
+ // prettier-ignore
22058
+ case 2:
22059
+ tmp1 = ps[15];
22060
+ tmp2 = ps[11];
22061
+ ps[12] = ps[3];
22062
+ ps[13] = pi + 0;
22063
+ ps[14] = pi + 1;
22064
+ ps[15] = pi + 2;
22065
+ ps[8] = ps[7];
22066
+ ps[11] = pi + 3;
22067
+ ps[4] = tmp2;
22068
+ ps[7] = pi + 4;
22069
+ ps[0] = tmp1;
22070
+ ps[1] = pi + 7;
22071
+ ps[2] = pi + 6;
22072
+ ps[3] = pi + 5;
22073
+ tmp1 = cs[3];
22074
+ cs[2] = cs[1];
22075
+ cs[3] = ci;
22076
+ cs[0] = tmp1;
22077
+ cs[1] = ci + 1;
22078
+ break;
22079
+ // prettier-ignore
22080
+ case 3:
22081
+ ps[12] = ps[0];
22082
+ ps[13] = pi + 0;
22083
+ ps[14] = pi + 1;
22084
+ ps[15] = pi + 2;
22085
+ ps[8] = ps[1];
22086
+ ps[11] = pi + 3;
22087
+ ps[4] = ps[2];
22088
+ ps[7] = pi + 4;
22089
+ ps[0] = ps[3];
22090
+ ps[1] = pi + 7;
22091
+ ps[2] = pi + 6;
22092
+ ps[3] = pi + 5;
22093
+ cs[2] = cs[0];
22094
+ cs[3] = ci;
22095
+ cs[0] = cs[1];
22096
+ cs[1] = ci + 1;
22097
+ break;
22098
+ }
22099
+ ps[5] = coords.length;
22100
+ coords.push([
22101
+ (-4 * coords[ps[0]][0] - coords[ps[15]][0] + 6 * (coords[ps[4]][0] + coords[ps[1]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9,
22102
+ (-4 * coords[ps[0]][1] - coords[ps[15]][1] + 6 * (coords[ps[4]][1] + coords[ps[1]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9
22103
+ ]);
22104
+ ps[6] = coords.length;
22105
+ coords.push([
22106
+ (-4 * coords[ps[3]][0] - coords[ps[12]][0] + 6 * (coords[ps[2]][0] + coords[ps[7]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9,
22107
+ (-4 * coords[ps[3]][1] - coords[ps[12]][1] + 6 * (coords[ps[2]][1] + coords[ps[7]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9
22108
+ ]);
22109
+ ps[9] = coords.length;
22110
+ coords.push([
22111
+ (-4 * coords[ps[12]][0] - coords[ps[3]][0] + 6 * (coords[ps[8]][0] + coords[ps[13]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9,
22112
+ (-4 * coords[ps[12]][1] - coords[ps[3]][1] + 6 * (coords[ps[8]][1] + coords[ps[13]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9
22113
+ ]);
22114
+ ps[10] = coords.length;
22115
+ coords.push([
22116
+ (-4 * coords[ps[15]][0] - coords[ps[0]][0] + 6 * (coords[ps[11]][0] + coords[ps[14]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9,
22117
+ (-4 * coords[ps[15]][1] - coords[ps[0]][1] + 6 * (coords[ps[11]][1] + coords[ps[14]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9
22118
+ ]);
22119
+ this.figures.push({
22120
+ type: MeshFigureType.PATCH,
22121
+ coords: new Int32Array(ps),
22122
+ // making copies of ps and cs
22123
+ colors: new Int32Array(cs)
22124
+ });
22125
+ }
22126
+ }
22127
+ _decodeType7Shading(reader) {
22128
+ const coords = this.coords;
22129
+ const colors = this.colors;
22130
+ const ps = new Int32Array(16);
22131
+ const cs = new Int32Array(4);
22132
+ while (reader.hasData) {
22133
+ const f = reader.readFlag();
22134
+ if (!(0 <= f && f <= 3)) {
22135
+ throw new FormatError("Unknown type7 flag");
22136
+ }
22137
+ const pi = coords.length;
22138
+ for (let i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) {
22139
+ coords.push(reader.readCoordinate());
22140
+ }
22141
+ const ci = colors.length;
22142
+ for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
22143
+ colors.push(reader.readComponents());
22144
+ }
22145
+ let tmp1, tmp2, tmp3, tmp4;
22146
+ switch (f) {
22147
+ // prettier-ignore
22148
+ case 0:
22149
+ ps[12] = pi + 3;
22150
+ ps[13] = pi + 4;
22151
+ ps[14] = pi + 5;
22152
+ ps[15] = pi + 6;
22153
+ ps[8] = pi + 2;
22154
+ ps[9] = pi + 13;
22155
+ ps[10] = pi + 14;
22156
+ ps[11] = pi + 7;
22157
+ ps[4] = pi + 1;
22158
+ ps[5] = pi + 12;
22159
+ ps[6] = pi + 15;
22160
+ ps[7] = pi + 8;
22161
+ ps[0] = pi;
22162
+ ps[1] = pi + 11;
22163
+ ps[2] = pi + 10;
22164
+ ps[3] = pi + 9;
22165
+ cs[2] = ci + 1;
22166
+ cs[3] = ci + 2;
22167
+ cs[0] = ci;
22168
+ cs[1] = ci + 3;
22169
+ break;
22170
+ // prettier-ignore
22171
+ case 1:
22172
+ tmp1 = ps[12];
22173
+ tmp2 = ps[13];
22174
+ tmp3 = ps[14];
22175
+ tmp4 = ps[15];
22176
+ ps[12] = tmp4;
22177
+ ps[13] = pi + 0;
22178
+ ps[14] = pi + 1;
22179
+ ps[15] = pi + 2;
22180
+ ps[8] = tmp3;
22181
+ ps[9] = pi + 9;
22182
+ ps[10] = pi + 10;
22183
+ ps[11] = pi + 3;
22184
+ ps[4] = tmp2;
22185
+ ps[5] = pi + 8;
22186
+ ps[6] = pi + 11;
22187
+ ps[7] = pi + 4;
22188
+ ps[0] = tmp1;
22189
+ ps[1] = pi + 7;
22190
+ ps[2] = pi + 6;
22191
+ ps[3] = pi + 5;
22192
+ tmp1 = cs[2];
22193
+ tmp2 = cs[3];
22194
+ cs[2] = tmp2;
22195
+ cs[3] = ci;
22196
+ cs[0] = tmp1;
22197
+ cs[1] = ci + 1;
22198
+ break;
22199
+ // prettier-ignore
22200
+ case 2:
22201
+ tmp1 = ps[15];
22202
+ tmp2 = ps[11];
22203
+ ps[12] = ps[3];
22204
+ ps[13] = pi + 0;
22205
+ ps[14] = pi + 1;
22206
+ ps[15] = pi + 2;
22207
+ ps[8] = ps[7];
22208
+ ps[9] = pi + 9;
22209
+ ps[10] = pi + 10;
22210
+ ps[11] = pi + 3;
22211
+ ps[4] = tmp2;
22212
+ ps[5] = pi + 8;
22213
+ ps[6] = pi + 11;
22214
+ ps[7] = pi + 4;
22215
+ ps[0] = tmp1;
22216
+ ps[1] = pi + 7;
22217
+ ps[2] = pi + 6;
22218
+ ps[3] = pi + 5;
22219
+ tmp1 = cs[3];
22220
+ cs[2] = cs[1];
22221
+ cs[3] = ci;
22222
+ cs[0] = tmp1;
22223
+ cs[1] = ci + 1;
22224
+ break;
22225
+ // prettier-ignore
22226
+ case 3:
22227
+ ps[12] = ps[0];
22228
+ ps[13] = pi + 0;
22229
+ ps[14] = pi + 1;
22230
+ ps[15] = pi + 2;
22231
+ ps[8] = ps[1];
22232
+ ps[9] = pi + 9;
22233
+ ps[10] = pi + 10;
22234
+ ps[11] = pi + 3;
22235
+ ps[4] = ps[2];
22236
+ ps[5] = pi + 8;
22237
+ ps[6] = pi + 11;
22238
+ ps[7] = pi + 4;
22239
+ ps[0] = ps[3];
22240
+ ps[1] = pi + 7;
22241
+ ps[2] = pi + 6;
22242
+ ps[3] = pi + 5;
22243
+ cs[2] = cs[0];
22244
+ cs[3] = ci;
22245
+ cs[0] = cs[1];
22246
+ cs[1] = ci + 1;
22247
+ break;
22248
+ }
22249
+ this.figures.push({
22250
+ type: MeshFigureType.PATCH,
22251
+ coords: new Int32Array(ps),
22252
+ // making copies of ps and cs
22253
+ colors: new Int32Array(cs)
22254
+ });
22255
+ }
22256
+ }
22257
+ _buildFigureFromPatch(index) {
22258
+ const figure = this.figures[index];
22259
+ assert2(
22260
+ figure.type === MeshFigureType.PATCH,
22261
+ "Unexpected patch mesh figure"
22262
+ );
22263
+ const coords = this.coords, colors = this.colors;
22264
+ const pi = figure.coords;
22265
+ const ci = figure.colors;
22266
+ const figureMinX = Math.min(
22267
+ coords[pi[0]][0],
22268
+ coords[pi[3]][0],
22269
+ coords[pi[12]][0],
22270
+ coords[pi[15]][0]
22271
+ );
22272
+ const figureMinY = Math.min(
22273
+ coords[pi[0]][1],
22274
+ coords[pi[3]][1],
22275
+ coords[pi[12]][1],
22276
+ coords[pi[15]][1]
22277
+ );
22278
+ const figureMaxX = Math.max(
22279
+ coords[pi[0]][0],
22280
+ coords[pi[3]][0],
22281
+ coords[pi[12]][0],
22282
+ coords[pi[15]][0]
22283
+ );
22284
+ const figureMaxY = Math.max(
22285
+ coords[pi[0]][1],
22286
+ coords[pi[3]][1],
22287
+ coords[pi[12]][1],
22288
+ coords[pi[15]][1]
22289
+ );
22290
+ let splitXBy = Math.ceil(
22291
+ (figureMaxX - figureMinX) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[2] - this.bounds[0])
22292
+ );
22293
+ splitXBy = MathClamp(
22294
+ splitXBy,
22295
+ _MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
22296
+ _MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT
22297
+ );
22298
+ let splitYBy = Math.ceil(
22299
+ (figureMaxY - figureMinY) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[3] - this.bounds[1])
22300
+ );
22301
+ splitYBy = MathClamp(
22302
+ splitYBy,
22303
+ _MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
22304
+ _MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT
22305
+ );
22306
+ const verticesPerRow = splitXBy + 1;
22307
+ const figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
22308
+ const figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
22309
+ let k = 0;
22310
+ const cl = new Uint8Array(3), cr = new Uint8Array(3);
22311
+ const c0 = colors[ci[0]], c1 = colors[ci[1]], c2 = colors[ci[2]], c3 = colors[ci[3]];
22312
+ const bRow = getB(splitYBy), bCol = getB(splitXBy);
22313
+ for (let row = 0; row <= splitYBy; row++) {
22314
+ cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0;
22315
+ cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0;
22316
+ cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0;
22317
+ cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0;
22318
+ cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0;
22319
+ cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0;
22320
+ for (let col = 0; col <= splitXBy; col++, k++) {
22321
+ if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) {
22322
+ continue;
22323
+ }
22324
+ let x = 0, y = 0;
22325
+ let q = 0;
22326
+ for (let i = 0; i <= 3; i++) {
22327
+ for (let j = 0; j <= 3; j++, q++) {
22328
+ const m = bRow[row][i] * bCol[col][j];
22329
+ x += coords[pi[q]][0] * m;
22330
+ y += coords[pi[q]][1] * m;
22331
+ }
22332
+ }
22333
+ figureCoords[k] = coords.length;
22334
+ coords.push([x, y]);
22335
+ figureColors[k] = colors.length;
22336
+ const newColor = new Uint8Array(3);
22337
+ newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0;
22338
+ newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0;
22339
+ newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0;
22340
+ colors.push(newColor);
22341
+ }
22342
+ }
22343
+ figureCoords[0] = pi[0];
22344
+ figureColors[0] = ci[0];
22345
+ figureCoords[splitXBy] = pi[3];
22346
+ figureColors[splitXBy] = ci[1];
22347
+ figureCoords[verticesPerRow * splitYBy] = pi[12];
22348
+ figureColors[verticesPerRow * splitYBy] = ci[2];
22349
+ figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15];
22350
+ figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
22351
+ this.figures[index] = {
22352
+ type: MeshFigureType.LATTICE,
22353
+ coords: figureCoords,
22354
+ colors: figureColors,
22355
+ verticesPerRow
22356
+ };
22357
+ }
22358
+ _updateBounds() {
22359
+ meshUpdateBounds(this);
22360
+ }
22361
+ _packData() {
22362
+ meshPackData(this);
22363
+ }
22364
+ getIR() {
22365
+ const { posData, colData, vertexCount } = buildMeshVertexData(
22366
+ this.coords,
22367
+ this.colors,
22368
+ this.figures
22369
+ );
22370
+ return [
22371
+ "Mesh",
22372
+ this.shadingType,
22373
+ posData,
22374
+ colData,
22375
+ vertexCount,
22376
+ this.bounds,
22377
+ this.bbox,
22378
+ this.background
22379
+ ];
22380
+ }
22381
+ };
19075
22382
 
19076
22383
  // packages/pdf-ast/src/ast.ts
19077
22384
  init_buffer();
@@ -26356,6 +29663,27 @@ var __webpack_exports__VerbosityLevel = __webpack_exports__.VerbosityLevel;
26356
29663
  var __webpack_exports__getVerbosityLevel = __webpack_exports__.getVerbosityLevel;
26357
29664
  var __webpack_exports__setVerbosityLevel = __webpack_exports__.setVerbosityLevel;
26358
29665
 
29666
+ // packages/pdf-ast/src/content/calibrated-color.ts
29667
+ init_buffer();
29668
+ function createCalibratedColorSpace(doc, family, parameters) {
29669
+ const dict = doc.resolveDict(parameters);
29670
+ const array = (key) => {
29671
+ const value = dict ? doc.resolveArray(dictGet(dict, key)) : void 0;
29672
+ return value?.items.map((item) => {
29673
+ const number = doc.resolve(item);
29674
+ return number?.kind === "number" ? number.value : 0;
29675
+ });
29676
+ };
29677
+ const whitePoint = array("WhitePoint") ?? [0.95047, 1, 1.08883];
29678
+ const blackPoint = array("BlackPoint");
29679
+ if (family === "CalGray") {
29680
+ const gamma = dict ? doc.resolve(dictGet(dict, "Gamma")) : void 0;
29681
+ return new CalGrayCS(whitePoint, blackPoint, gamma?.kind === "number" ? gamma.value : void 0);
29682
+ }
29683
+ if (family === "CalRGB") return new CalRGBCS(whitePoint, blackPoint, array("Gamma"), array("Matrix"));
29684
+ return new LabCS(whitePoint, blackPoint, array("Range"));
29685
+ }
29686
+
26359
29687
  // packages/pdf-ast/src/content/parser.ts
26360
29688
  init_buffer();
26361
29689
 
@@ -28889,11 +32217,16 @@ function parseDictionaryStream(dictNode, lexer, bytes) {
28889
32217
  let streamEnd = streamStart;
28890
32218
  if (resolvedLength !== void 0 && resolvedLength >= 0 && streamStart + resolvedLength <= bytes.length) {
28891
32219
  const candidateEnd = streamStart + resolvedLength;
28892
- const tailSlice = bytes.subarray(candidateEnd, Math.min(bytes.length, candidateEnd + 32));
28893
- const tailStr = new TextDecoder("latin1").decode(tailSlice);
28894
- if (tailStr.includes("endstream")) {
32220
+ const tailLexer = new CosByteLexer(bytes, candidateEnd);
32221
+ let endToken;
32222
+ try {
32223
+ endToken = tailLexer.nextToken();
32224
+ } catch (error) {
32225
+ if (!(error instanceof PdfError) || error.code !== "E_PARSE") throw error;
32226
+ }
32227
+ if (endToken?.kind === "keyword" && endToken.value === "endstream") {
28895
32228
  rawStreamBytes = bytes.subarray(streamStart, candidateEnd);
28896
- streamEnd = candidateEnd + tailStr.indexOf("endstream") + "endstream".length;
32229
+ streamEnd = tailLexer.offset;
28897
32230
  }
28898
32231
  }
28899
32232
  if (!rawStreamBytes) {
@@ -29460,6 +32793,7 @@ function parseCosDocument(bytes, options = {}) {
29460
32793
  }
29461
32794
 
29462
32795
  // packages/pdf-ast/src/extract/images.ts
32796
+ var cmykColorSpace = new DeviceCmykCS();
29463
32797
  function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
29464
32798
  if (!csNode) return { colorSpace: "rgb", colorSpaceLabel: "rgb", components: 3 };
29465
32799
  const resolved = doc.resolve(csNode);
@@ -29500,7 +32834,7 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
29500
32834
  palette = lookupNode.bytes;
29501
32835
  }
29502
32836
  let resolvedBaseComp = baseInfo.components;
29503
- if (palette && (baseInfo.isLab || baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calRgbGamma !== void 0 || baseInfo.calGrayGamma !== void 0)) {
32837
+ if (palette && (baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calibrated !== void 0)) {
29504
32838
  const numEntries = Math.max(1, Math.min(hival + 1, Math.floor(palette.length / Math.max(1, baseInfo.components))));
29505
32839
  const rgbaPal = decodeSamplesToRgba(palette, numEntries, 1, 8, baseInfo);
29506
32840
  const rgbPal = new Uint8Array(numEntries * 3);
@@ -29530,74 +32864,21 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
29530
32864
  }
29531
32865
  return { colorSpace: "rgb", colorSpaceLabel: "icc", components: 3 };
29532
32866
  }
29533
- if (kindName === "CalGray") {
29534
- const calDict = doc.resolveDict(resolved.items[1]);
29535
- const gammaNode = calDict ? doc.resolve(dictGet(calDict, "Gamma")) : void 0;
29536
- const gamma = gammaNode?.kind === "number" && gammaNode.value > 0 ? gammaNode.value : 1;
29537
- return { colorSpace: "gray", colorSpaceLabel: "cal-gray", components: 1, calGrayGamma: gamma };
29538
- }
29539
- if (kindName === "CalRGB") {
29540
- const calDict = doc.resolveDict(resolved.items[1]);
29541
- const gammaArr = calDict ? doc.resolveArray(dictGet(calDict, "Gamma")) : void 0;
29542
- let calRgbGamma = [1, 1, 1];
29543
- if (gammaArr && gammaArr.items.length >= 3) {
29544
- const gNums = gammaArr.items.slice(0, 3).map((it) => {
29545
- const r = doc.resolve(it);
29546
- return r?.kind === "number" && r.value > 0 ? r.value : 1;
29547
- });
29548
- calRgbGamma = [gNums[0], gNums[1], gNums[2]];
29549
- }
29550
- const matArr = calDict ? doc.resolveArray(dictGet(calDict, "Matrix")) : void 0;
29551
- let calRgbMatrix;
29552
- if (matArr && matArr.items.length >= 9) {
29553
- calRgbMatrix = matArr.items.slice(0, 9).map((it) => {
29554
- const r = doc.resolve(it);
29555
- return r?.kind === "number" ? r.value : 0;
29556
- });
29557
- }
32867
+ if (kindName === "CalGray" || kindName === "CalRGB" || kindName === "Lab") {
32868
+ const calibrated = createCalibratedColorSpace(doc, kindName, resolved.items[1]);
29558
32869
  return {
29559
- colorSpace: "rgb",
29560
- colorSpaceLabel: "cal-rgb",
29561
- components: 3,
29562
- calRgbGamma,
29563
- calRgbMatrix
32870
+ colorSpace: kindName === "CalGray" ? "gray" : "rgb",
32871
+ colorSpaceLabel: kindName === "CalGray" ? "cal-gray" : kindName === "CalRGB" ? "cal-rgb" : "lab",
32872
+ components: kindName === "CalGray" ? 1 : 3,
32873
+ calibrated
29564
32874
  };
29565
32875
  }
29566
- if (kindName === "Lab") {
29567
- const labDict = doc.resolveDict(resolved.items[1]);
29568
- const rangeArr = labDict ? doc.resolveArray(dictGet(labDict, "Range")) : void 0;
29569
- let labRange = [-100, 100, -100, 100];
29570
- if (rangeArr && rangeArr.items.length >= 4) {
29571
- const nums = rangeArr.items.slice(0, 4).map((it) => {
29572
- const r = doc.resolve(it);
29573
- return r?.kind === "number" ? r.value : 0;
29574
- });
29575
- labRange = [nums[0], nums[1], nums[2], nums[3]];
29576
- }
29577
- return { colorSpace: "rgb", colorSpaceLabel: "lab", components: 3, isLab: true, labRange };
29578
- }
29579
32876
  if (kindName === "Separation" || kindName === "DeviceN") {
29580
32877
  const isDevN = kindName === "DeviceN";
29581
32878
  const namesArr = isDevN ? doc.resolveArray(resolved.items[1]) : void 0;
29582
32879
  const devNComponents = isDevN && namesArr ? Math.max(1, namesArr.items.length) : 1;
29583
32880
  const altInfo = resolveColorSpaceInfo(doc, resolved.items[2], resourcesDict);
29584
32881
  const altSpace = altInfo.colorSpace === "cmyk" ? "cmyk" : altInfo.colorSpace === "gray" ? "gray" : "rgb";
29585
- const fnResolved = doc.resolve(resolved.items[3]);
29586
- const fnDict = fnResolved?.kind === "stream" ? fnResolved.dict : fnResolved?.kind === "dict" ? fnResolved : void 0;
29587
- const ftNode = fnDict ? doc.resolve(dictGet(fnDict, "FunctionType")) : void 0;
29588
- const tintFunctionType = ftNode?.kind === "number" ? ftNode.value : 2;
29589
- const c0Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C0")) : void 0;
29590
- const c1Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C1")) : void 0;
29591
- const nNode = fnDict ? doc.resolve(dictGet(fnDict, "N")) : void 0;
29592
- const c0 = c0Arr ? c0Arr.items.map((it) => {
29593
- const r = doc.resolve(it);
29594
- return r?.kind === "number" ? r.value : 0;
29595
- }) : altSpace === "cmyk" ? [0, 0, 0, 0] : altSpace === "gray" ? [1] : [1, 1, 1];
29596
- const c1 = c1Arr ? c1Arr.items.map((it) => {
29597
- const r = doc.resolve(it);
29598
- return r?.kind === "number" ? r.value : 0;
29599
- }) : altSpace === "cmyk" ? [0, 0, 0, 1] : altSpace === "gray" ? [0] : [0, 0, 0];
29600
- const sepN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
29601
32882
  return {
29602
32883
  colorSpace: altSpace,
29603
32884
  colorSpaceLabel: isDevN ? "devn" : "sep",
@@ -29605,12 +32886,9 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
29605
32886
  isSeparation: !isDevN,
29606
32887
  isDeviceN: isDevN,
29607
32888
  separationAltSpace: altSpace,
29608
- separationC0: c0,
29609
- separationC1: c1,
29610
- separationN: sepN,
32889
+ alternateCalibrated: altInfo.calibrated,
29611
32890
  tintFunctionDoc: doc,
29612
- tintFunctionNode: resolved.items[3],
29613
- tintFunctionType
32891
+ tintFunctionNode: resolved.items[3]
29614
32892
  };
29615
32893
  }
29616
32894
  }
@@ -29760,141 +33038,55 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
29760
33038
  const rgba = new Uint8Array(width * height * 4);
29761
33039
  const pixelCount = width * height;
29762
33040
  if (csInfo.isSeparation || csInfo.isDeviceN) {
29763
- const c0 = csInfo.separationC0 ?? [1, 1, 1];
29764
- const c1 = csInfo.separationC1 ?? [0, 0, 0];
29765
- const expN = csInfo.separationN ?? 1;
29766
33041
  const alt = csInfo.separationAltSpace ?? "rgb";
29767
33042
  const numCh = Math.max(1, csInfo.components);
29768
33043
  const step = bpc === 16 ? 2 : 1;
29769
- const useGenericTintFn = csInfo.tintFunctionDoc !== void 0 && csInfo.tintFunctionNode !== void 0 && (csInfo.tintFunctionType === 0 || csInfo.tintFunctionType === 3 || csInfo.tintFunctionType === 4);
29770
33044
  for (let p = 0; p < pixelCount; p++) {
29771
33045
  const chVals = [];
29772
- let wSum = 0;
29773
33046
  for (let ch3 = 0; ch3 < numCh; ch3++) {
29774
33047
  const sRaw = (rawSamples[(p * numCh + ch3) * step] ?? 0) / 255;
29775
- const tRemapped = remapUnitSampleWithDecode(sRaw, ch3, decodePairs);
29776
- chVals.push(tRemapped);
29777
- wSum += Math.pow(Math.max(0, Math.min(1, tRemapped)), expN);
29778
- }
29779
- if (useGenericTintFn) {
29780
- const outComps = evalShadingFunctionToComponents(
29781
- csInfo.tintFunctionDoc,
29782
- csInfo.tintFunctionNode,
29783
- chVals
29784
- );
29785
- if (alt === "cmyk") {
29786
- const c = outComps[0] ?? 0;
29787
- const m = outComps[1] ?? 0;
29788
- const y = outComps[2] ?? 0;
29789
- const k = outComps[3] ?? 0;
29790
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, (1 - c) * (1 - k))) * 255);
29791
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, (1 - m) * (1 - k))) * 255);
29792
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, (1 - y) * (1 - k))) * 255);
29793
- } else if (alt === "gray") {
29794
- const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
29795
- rgba[p * 4] = gByte;
29796
- rgba[p * 4 + 1] = gByte;
29797
- rgba[p * 4 + 2] = gByte;
29798
- } else {
29799
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
29800
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
29801
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
29802
- }
29803
- rgba[p * 4 + 3] = 255;
29804
- continue;
33048
+ chVals.push(remapUnitSampleWithDecode(sRaw, ch3, decodePairs));
29805
33049
  }
29806
- const w = Math.max(0, Math.min(1, wSum));
29807
- if (alt === "cmyk") {
29808
- const c = (c0[0] ?? 0) + w * ((c1[0] ?? 0) - (c0[0] ?? 0));
29809
- const m = (c0[1] ?? 0) + w * ((c1[1] ?? 0) - (c0[1] ?? 0));
29810
- const y = (c0[2] ?? 0) + w * ((c1[2] ?? 0) - (c0[2] ?? 0));
29811
- const k = (c0[3] ?? 0) + w * ((c1[3] ?? 1) - (c0[3] ?? 0));
29812
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, (1 - c) * (1 - k))) * 255);
29813
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, (1 - m) * (1 - k))) * 255);
29814
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, (1 - y) * (1 - k))) * 255);
33050
+ const outComps = evalShadingFunctionToComponents(
33051
+ csInfo.tintFunctionDoc,
33052
+ csInfo.tintFunctionNode,
33053
+ chVals
33054
+ );
33055
+ if (csInfo.alternateCalibrated) {
33056
+ rgba.set(csInfo.alternateCalibrated.getRgb(outComps, 0), p * 4);
33057
+ } else if (alt === "cmyk") {
33058
+ rgba.set(cmykColorSpace.getRgb([outComps[0] ?? 0, outComps[1] ?? 0, outComps[2] ?? 0, outComps[3] ?? 0], 0), p * 4);
29815
33059
  } else if (alt === "gray") {
29816
- const gVal = (c0[0] ?? 1) + w * ((c1[0] ?? 0) - (c0[0] ?? 1));
29817
- const gByte = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
33060
+ const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
29818
33061
  rgba[p * 4] = gByte;
29819
33062
  rgba[p * 4 + 1] = gByte;
29820
33063
  rgba[p * 4 + 2] = gByte;
29821
33064
  } else {
29822
- const rVal = (c0[0] ?? 1) + w * ((c1[0] ?? 0) - (c0[0] ?? 1));
29823
- const gVal = (c0[1] ?? 1) + w * ((c1[1] ?? 0) - (c0[1] ?? 1));
29824
- const bVal = (c0[2] ?? 1) + w * ((c1[2] ?? 0) - (c0[2] ?? 1));
29825
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, rVal)) * 255);
29826
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
29827
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, bVal)) * 255);
33065
+ rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
33066
+ rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
33067
+ rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
29828
33068
  }
29829
33069
  rgba[p * 4 + 3] = 255;
29830
33070
  }
29831
- } else if (csInfo.isLab) {
29832
- const [amin, amax, bmin, bmax] = csInfo.labRange ?? [-100, 100, -100, 100];
29833
- const invF = (t) => t > 6 / 29 ? t * t * t : 3 * (6 / 29) * (6 / 29) * (t - 4 / 29);
29834
- const toSrgb = (u) => {
29835
- const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
29836
- return Math.round(Math.max(0, Math.min(1, c)) * 255);
29837
- };
33071
+ } else if (csInfo.calibrated?.name === "Lab") {
33072
+ const { amin, amax, bmin, bmax } = csInfo.calibrated;
33073
+ const step = bpc === 16 ? 2 : 1;
29838
33074
  for (let p = 0; p < pixelCount; p++) {
29839
- const s0 = (rawSamples[p * 3] ?? 0) / 255;
29840
- const s1 = (rawSamples[p * 3 + 1] ?? 128) / 255;
29841
- const s2 = (rawSamples[p * 3 + 2] ?? 128) / 255;
29842
- const L = s0 * 100;
29843
- if (L <= 0.01) {
29844
- rgba[p * 4] = 0;
29845
- rgba[p * 4 + 1] = 0;
29846
- rgba[p * 4 + 2] = 0;
29847
- rgba[p * 4 + 3] = 255;
29848
- continue;
29849
- }
29850
- const a = amin + s1 * (amax - amin);
29851
- const b = bmin + s2 * (bmax - bmin);
29852
- const fy = (L + 16) / 116;
29853
- const fx = fy + a / 500;
29854
- const fz = fy - b / 200;
29855
- const X = 0.95047 * invF(fx);
29856
- const Y = 1 * invF(fy);
29857
- const Z = 1.08883 * invF(fz);
29858
- const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
29859
- const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
29860
- const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
29861
- rgba[p * 4] = toSrgb(linR);
29862
- rgba[p * 4 + 1] = toSrgb(linG);
29863
- rgba[p * 4 + 2] = toSrgb(linB);
33075
+ const L = (rawSamples[p * 3 * step] ?? 0) / 255 * 100;
33076
+ const a = amin + (rawSamples[(p * 3 + 1) * step] ?? 128) / 255 * (amax - amin);
33077
+ const b = bmin + (rawSamples[(p * 3 + 2) * step] ?? 128) / 255 * (bmax - bmin);
33078
+ rgba.set(csInfo.calibrated.getRgb([L, a, b], 0), p * 4);
29864
33079
  rgba[p * 4 + 3] = 255;
29865
33080
  }
29866
33081
  } else if (csInfo.colorSpace === "rgb") {
29867
- const hasCalRgb = Boolean(csInfo.calRgbGamma || csInfo.calRgbMatrix);
29868
- const toSrgbByte = (u) => {
29869
- const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
29870
- return Math.round(Math.max(0, Math.min(1, c)) * 255);
29871
- };
29872
33082
  const writeRgbPixel = (p, rByte, gByte, bByte) => {
29873
- let rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
29874
- let gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
29875
- let bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
29876
- if (hasCalRgb) {
29877
- const [gr, gg, gb] = csInfo.calRgbGamma ?? [1, 1, 1];
29878
- const ag = Math.pow(rU, gr);
29879
- const bg = Math.pow(gU, gg);
29880
- const cg = Math.pow(bU, gb);
29881
- if (csInfo.calRgbMatrix && csInfo.calRgbMatrix.length >= 9) {
29882
- const m = csInfo.calRgbMatrix;
29883
- const X = m[0] * ag + m[3] * bg + m[6] * cg;
29884
- const Y = m[1] * ag + m[4] * bg + m[7] * cg;
29885
- const Z = m[2] * ag + m[5] * bg + m[8] * cg;
29886
- const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
29887
- const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
29888
- const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
29889
- rgba[p * 4] = toSrgbByte(linR);
29890
- rgba[p * 4 + 1] = toSrgbByte(linG);
29891
- rgba[p * 4 + 2] = toSrgbByte(linB);
29892
- rgba[p * 4 + 3] = 255;
29893
- return;
29894
- }
29895
- rU = ag;
29896
- gU = bg;
29897
- bU = cg;
33083
+ const rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
33084
+ const gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
33085
+ const bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
33086
+ if (csInfo.calibrated) {
33087
+ rgba.set(csInfo.calibrated.getRgb([rU, gU, bU], 0), p * 4);
33088
+ rgba[p * 4 + 3] = 255;
33089
+ return;
29898
33090
  }
29899
33091
  rgba[p * 4] = Math.round(rU * 255);
29900
33092
  rgba[p * 4 + 1] = Math.round(gU * 255);
@@ -29914,10 +33106,11 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
29914
33106
  }
29915
33107
  } else if (csInfo.colorSpace === "gray") {
29916
33108
  const writeGrayPixel = (p, gByte) => {
29917
- let gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
29918
- if (csInfo.calGrayGamma && csInfo.calGrayGamma !== 1) {
29919
- const lin = Math.pow(gU, csInfo.calGrayGamma);
29920
- gU = lin <= 31308e-7 ? 12.92 * lin : 1.055 * Math.pow(lin, 1 / 2.4) - 0.055;
33109
+ const gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
33110
+ if (csInfo.calibrated) {
33111
+ rgba.set(csInfo.calibrated.getRgb([gU], 0), p * 4);
33112
+ rgba[p * 4 + 3] = 255;
33113
+ return;
29921
33114
  }
29922
33115
  const outG = Math.round(Math.max(0, Math.min(1, gU)) * 255);
29923
33116
  rgba[p * 4] = outG;
@@ -29973,9 +33166,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
29973
33166
  const m = remapUnitSampleWithDecode((rawSamples[p * stride + chStep] ?? 0) / 255, 1, decodePairs);
29974
33167
  const y = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 2] ?? 0) / 255, 2, decodePairs);
29975
33168
  const k = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 3] ?? 0) / 255, 3, decodePairs);
29976
- rgba[p * 4] = Math.round((1 - c) * (1 - k) * 255);
29977
- rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
29978
- rgba[p * 4 + 2] = Math.round((1 - y) * (1 - k) * 255);
33169
+ rgba.set(cmykColorSpace.getRgb([c, m, y, k], 0), p * 4);
29979
33170
  rgba[p * 4 + 3] = 255;
29980
33171
  }
29981
33172
  } else if (csInfo.colorSpace === "index") {
@@ -30013,9 +33204,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
30013
33204
  const m = pal[idx * 4 + 1] / 255;
30014
33205
  const yel = pal[idx * 4 + 2] / 255;
30015
33206
  const k = pal[idx * 4 + 3] / 255;
30016
- rgba[p * 4] = Math.round((1 - c) * (1 - k) * 255);
30017
- rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
30018
- rgba[p * 4 + 2] = Math.round((1 - yel) * (1 - k) * 255);
33207
+ rgba.set(cmykColorSpace.getRgb([c, m, yel, k], 0), p * 4);
30019
33208
  } else {
30020
33209
  rgba[p * 4] = pal[idx * baseComp];
30021
33210
  rgba[p * 4 + 1] = pal[idx * baseComp + 1];
@@ -30909,6 +34098,7 @@ function embedTrueTypeFontInCos(doc, font, usedGlyphs) {
30909
34098
  }
30910
34099
 
30911
34100
  // packages/pdf-ast/src/content/evaluator.ts
34101
+ var cmykColorSpace2 = new DeviceCmykCS();
30912
34102
  function multiplyMatrices(m1, m2) {
30913
34103
  return [
30914
34104
  m1[0] * m2[0] + m1[1] * m2[2],
@@ -31125,193 +34315,7 @@ function resolvePageFonts(doc, resourcesDict) {
31125
34315
  }
31126
34316
  return fonts;
31127
34317
  }
31128
- function evaluateType4PostScriptTokens(tokens, initialStack) {
31129
- const stack = [...initialStack];
31130
- const runRange = (start, end) => {
31131
- let i = start;
31132
- while (i < end) {
31133
- const tok = tokens[i];
31134
- if (tok === "{") {
31135
- let depth = 1;
31136
- let j = i + 1;
31137
- while (j < end && depth > 0) {
31138
- if (tokens[j] === "{") depth++;
31139
- else if (tokens[j] === "}") depth--;
31140
- j++;
31141
- }
31142
- const blockStart = i + 1;
31143
- const blockEnd = j - 1;
31144
- if (j < end && tokens[j] === "{") {
31145
- let depth2 = 1;
31146
- let k = j + 1;
31147
- while (k < end && depth2 > 0) {
31148
- if (tokens[k] === "{") depth2++;
31149
- else if (tokens[k] === "}") depth2--;
31150
- k++;
31151
- }
31152
- if (k < end && tokens[k] === "ifelse") {
31153
- const cond = stack.pop() ?? 0;
31154
- if (cond !== 0) runRange(blockStart, blockEnd);
31155
- else runRange(j + 1, k - 1);
31156
- i = k + 1;
31157
- continue;
31158
- }
31159
- }
31160
- if (j < end && tokens[j] === "if") {
31161
- const cond = stack.pop() ?? 0;
31162
- if (cond !== 0) runRange(blockStart, blockEnd);
31163
- i = j + 1;
31164
- continue;
31165
- }
31166
- runRange(blockStart, blockEnd);
31167
- i = j;
31168
- continue;
31169
- }
31170
- if (tok === "}") {
31171
- i++;
31172
- continue;
31173
- }
31174
- const numVal2 = Number(tok);
31175
- if (tok.length > 0 && !Number.isNaN(numVal2)) {
31176
- stack.push(numVal2);
31177
- } else if (tok === "true") {
31178
- stack.push(1);
31179
- } else if (tok === "false") {
31180
- stack.push(0);
31181
- } else if (tok === "add") {
31182
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
31183
- stack.push(a + b);
31184
- } else if (tok === "sub") {
31185
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
31186
- stack.push(a - b);
31187
- } else if (tok === "mul") {
31188
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
31189
- stack.push(a * b);
31190
- } else if (tok === "div") {
31191
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
31192
- stack.push(Math.abs(b) > 1e-12 ? a / b : 0);
31193
- } else if (tok === "idiv") {
31194
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
31195
- stack.push(Math.abs(b) > 1e-12 ? Math.trunc(a / b) : 0);
31196
- } else if (tok === "mod") {
31197
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
31198
- stack.push(Math.abs(b) > 1e-12 ? a % b : 0);
31199
- } else if (tok === "neg") {
31200
- stack.push(-(stack.pop() ?? 0));
31201
- } else if (tok === "abs") {
31202
- stack.push(Math.abs(stack.pop() ?? 0));
31203
- } else if (tok === "ceiling") {
31204
- stack.push(Math.ceil(stack.pop() ?? 0));
31205
- } else if (tok === "floor") {
31206
- stack.push(Math.floor(stack.pop() ?? 0));
31207
- } else if (tok === "round") {
31208
- stack.push(Math.round(stack.pop() ?? 0));
31209
- } else if (tok === "truncate" || tok === "cvi") {
31210
- stack.push(Math.trunc(stack.pop() ?? 0));
31211
- } else if (tok === "sqrt") {
31212
- stack.push(Math.sqrt(Math.max(0, stack.pop() ?? 0)));
31213
- } else if (tok === "sin") {
31214
- stack.push(Math.sin((stack.pop() ?? 0) * Math.PI / 180));
31215
- } else if (tok === "cos") {
31216
- stack.push(Math.cos((stack.pop() ?? 0) * Math.PI / 180));
31217
- } else if (tok === "atan") {
31218
- const dx = stack.pop() ?? 1, dy = stack.pop() ?? 0;
31219
- let deg = Math.atan2(dy, dx) * 180 / Math.PI;
31220
- if (deg < 0) deg += 360;
31221
- stack.push(deg);
31222
- } else if (tok === "exp") {
31223
- const exp = stack.pop() ?? 1, base = stack.pop() ?? 0;
31224
- stack.push(Math.pow(base, exp));
31225
- } else if (tok === "ln") {
31226
- stack.push(Math.log(Math.max(1e-12, stack.pop() ?? 1)));
31227
- } else if (tok === "log") {
31228
- stack.push(Math.log10(Math.max(1e-12, stack.pop() ?? 1)));
31229
- } else if (tok === "dup") {
31230
- if (stack.length > 0) stack.push(stack[stack.length - 1]);
31231
- } else if (tok === "exch") {
31232
- if (stack.length >= 2) {
31233
- const b = stack.pop(), a = stack.pop();
31234
- stack.push(b, a);
31235
- }
31236
- } else if (tok === "pop") {
31237
- stack.pop();
31238
- } else if (tok === "copy") {
31239
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
31240
- const slice = stack.slice(Math.max(0, stack.length - n));
31241
- stack.push(...slice);
31242
- } else if (tok === "index") {
31243
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
31244
- const idx = stack.length - 1 - n;
31245
- if (idx >= 0 && idx < stack.length) stack.push(stack[idx]);
31246
- } else if (tok === "roll") {
31247
- const jShift = Math.trunc(stack.pop() ?? 0);
31248
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
31249
- if (n > 0 && stack.length >= n) {
31250
- const sub = stack.splice(stack.length - n, n);
31251
- const modShift = (jShift % n + n) % n;
31252
- const rolled = [...sub.slice(n - modShift), ...sub.slice(0, n - modShift)];
31253
- stack.push(...rolled);
31254
- }
31255
- } else if (tok === "eq") {
31256
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
31257
- stack.push(Math.abs(a - b) < 1e-9 ? 1 : 0);
31258
- } else if (tok === "ne") {
31259
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
31260
- stack.push(Math.abs(a - b) >= 1e-9 ? 1 : 0);
31261
- } else if (tok === "gt") {
31262
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
31263
- stack.push(a > b ? 1 : 0);
31264
- } else if (tok === "ge") {
31265
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
31266
- stack.push(a >= b ? 1 : 0);
31267
- } else if (tok === "lt") {
31268
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
31269
- stack.push(a < b ? 1 : 0);
31270
- } else if (tok === "le") {
31271
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
31272
- stack.push(a <= b ? 1 : 0);
31273
- } else if (tok === "and") {
31274
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
31275
- stack.push(a !== 0 && b !== 0 ? 1 : 0);
31276
- } else if (tok === "or") {
31277
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
31278
- stack.push(a !== 0 || b !== 0 ? 1 : 0);
31279
- } else if (tok === "not") {
31280
- const a = stack.pop() ?? 0;
31281
- stack.push(a === 0 ? 1 : 0);
31282
- }
31283
- i++;
31284
- }
31285
- };
31286
- runRange(0, tokens.length);
31287
- return stack;
31288
- }
31289
- function tokenizePostScriptCode(bytes) {
31290
- const tokens = [];
31291
- let cur = "";
31292
- for (let i = 0; i < bytes.length; i++) {
31293
- const ch3 = String.fromCharCode(bytes[i]);
31294
- if (ch3 === "{" || ch3 === "}") {
31295
- if (cur.length > 0) {
31296
- tokens.push(cur);
31297
- cur = "";
31298
- }
31299
- tokens.push(ch3);
31300
- } else if (ch3 === " " || ch3 === " " || ch3 === "\n" || ch3 === "\r") {
31301
- if (cur.length > 0) {
31302
- tokens.push(cur);
31303
- cur = "";
31304
- }
31305
- } else {
31306
- cur += ch3;
31307
- }
31308
- }
31309
- if (cur.length > 0) tokens.push(cur);
31310
- if (tokens[0] === "{" && tokens[tokens.length - 1] === "}") {
31311
- return tokens.slice(1, -1);
31312
- }
31313
- return tokens;
31314
- }
34318
+ var postScriptFunctions = /* @__PURE__ */ new WeakMap();
31315
34319
  function evalShadingFunctionToComponents(doc, fnNode, inputs) {
31316
34320
  const inArr = typeof inputs === "number" ? [inputs] : inputs;
31317
34321
  const t = inArr[0] ?? 0;
@@ -31358,35 +34362,50 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
31358
34362
  const decode = getNums("Decode", range);
31359
34363
  const nOut = Math.max(1, Math.floor((decode.length || range.length || 6) / 2));
31360
34364
  const mIn = Math.max(1, size.length);
31361
- let flatGridIndex = 0;
34365
+ const streamBytes = doc.decodeStream(resolved);
34366
+ let vertices = [{ index: 0, weight: 1 }];
31362
34367
  let stride = 1;
31363
34368
  for (let i = 0; i < mIn; i++) {
31364
34369
  const d02 = dom[i * 2] ?? 0;
31365
34370
  const d12 = dom[i * 2 + 1] ?? 1;
31366
- const sMax = Math.max(1, (size[i] ?? 2) - 1);
34371
+ const sMax = Math.max(0, (size[i] ?? 2) - 1);
31367
34372
  const e0 = encode[i * 2] ?? 0;
31368
34373
  const e1 = encode[i * 2 + 1] ?? sMax;
31369
34374
  const x = Math.max(d02, Math.min(d12, inArr[i] ?? 0));
31370
- const u = Math.abs(d12 - d02) > 1e-8 ? (x - d02) / (d12 - d02) : 0;
31371
- const idx = Math.round(Math.max(0, Math.min(sMax, e0 + u * (e1 - e0))));
31372
- flatGridIndex += idx * stride;
34375
+ const u = d12 === d02 ? 0 : (x - d02) / (d12 - d02);
34376
+ const e = Math.max(0, Math.min(sMax, e0 + u * (e1 - e0)));
34377
+ const low = Math.floor(e), fraction = e - low;
34378
+ const next = [];
34379
+ for (const vertex of vertices) {
34380
+ const index = vertex.index + low * stride;
34381
+ if (index * nOut * bps < streamBytes.length * 8) next.push({ index, weight: vertex.weight * (1 - fraction) });
34382
+ if (fraction && (index + stride) * nOut * bps < streamBytes.length * 8) {
34383
+ next.push({ index: index + stride, weight: vertex.weight * fraction });
34384
+ }
34385
+ }
34386
+ vertices = next;
31373
34387
  stride *= size[i] ?? 2;
31374
34388
  }
31375
- const streamBytes = doc.decodeStream(resolved);
34389
+ const maxSample = 2 ** bps - 1;
34390
+ const readSample = (index) => {
34391
+ let bitOffset = index * bps, remaining = bps, value = 0;
34392
+ while (remaining > 0) {
34393
+ const bitInByte = bitOffset % 8;
34394
+ const take = Math.min(remaining, 8 - bitInByte);
34395
+ const byte = streamBytes[Math.floor(bitOffset / 8)] ?? 0;
34396
+ value = value * 2 ** take + (byte >> 8 - bitInByte - take & (1 << take) - 1);
34397
+ bitOffset += take;
34398
+ remaining -= take;
34399
+ }
34400
+ return value / maxSample;
34401
+ };
31376
34402
  const out2 = [];
31377
- const maxSample = bps === 16 ? 65535 : 255;
31378
34403
  for (let j = 0; j < nOut; j++) {
31379
- const sampleIdx = flatGridIndex * nOut + j;
31380
- let rawVal = 0;
31381
- if (bps === 16) {
31382
- rawVal = (streamBytes[sampleIdx * 2] ?? 0) << 8 | (streamBytes[sampleIdx * 2 + 1] ?? 0);
31383
- } else {
31384
- rawVal = streamBytes[sampleIdx] ?? 0;
31385
- }
31386
- const frac = rawVal / maxSample;
34404
+ let value = 0;
34405
+ for (const vertex of vertices) value += readSample(vertex.index * nOut + j) * vertex.weight;
31387
34406
  const dec0 = decode[j * 2] ?? 0;
31388
34407
  const dec1 = decode[j * 2 + 1] ?? 1;
31389
- out2.push(dec0 + frac * (dec1 - dec0));
34408
+ out2.push(dec0 + value * (dec1 - dec0));
31390
34409
  }
31391
34410
  return clampRange(out2);
31392
34411
  }
@@ -31396,34 +34415,40 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
31396
34415
  const d12 = dom[i * 2 + 1] ?? 1;
31397
34416
  return Math.max(d02, Math.min(d12, v));
31398
34417
  });
31399
- const tokens = tokenizePostScriptCode(doc.decodeStream(resolved));
31400
- const stackOut = evaluateType4PostScriptTokens(tokens, clampedInputs);
31401
- return clampRange(stackOut);
34418
+ const source = bytesToString3(doc.decodeStream(resolved));
34419
+ let cached = postScriptFunctions.get(resolved);
34420
+ if (!cached || cached.source !== source || cached.domain.length !== dom.length || cached.domain.some((value, index) => value !== dom[index]) || cached.range.length !== range.length || cached.range.some((value, index) => value !== range[index])) {
34421
+ cached = { source, domain: dom, range, evaluate: buildPostScriptJsFunction(source, dom, range) };
34422
+ postScriptFunctions.set(resolved, cached);
34423
+ }
34424
+ const output = [];
34425
+ cached.evaluate(clampedInputs, 0, output, 0);
34426
+ return output;
31402
34427
  }
31403
34428
  if (ft === 3) {
31404
34429
  const fnsArr = doc.resolveArray(dictGet(fnDict, "Functions"));
31405
34430
  const bounds = getNums("Bounds", []);
31406
34431
  const encode = getNums("Encode", []);
31407
34432
  if (fnsArr && fnsArr.items.length > 0) {
34433
+ const input = Math.max(dom[0] ?? 0, Math.min(dom[1] ?? 1, t));
31408
34434
  let segIdx = 0;
31409
- while (segIdx < bounds.length && t >= bounds[segIdx]) segIdx++;
34435
+ while (segIdx < bounds.length && input >= bounds[segIdx]) segIdx++;
31410
34436
  segIdx = Math.min(fnsArr.items.length - 1, segIdx);
31411
34437
  const b0 = segIdx === 0 ? dom[0] ?? 0 : bounds[segIdx - 1];
31412
34438
  const b1 = segIdx < bounds.length ? bounds[segIdx] : dom[1] ?? 1;
31413
34439
  const e0 = encode[segIdx * 2] ?? 0;
31414
34440
  const e1 = encode[segIdx * 2 + 1] ?? 1;
31415
- const localT = Math.abs(b1 - b0) > 1e-8 ? e0 + (t - b0) / (b1 - b0) * (e1 - e0) : e0;
31416
- return evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], Math.max(0, Math.min(1, localT)));
34441
+ const localT = b1 !== b0 ? e0 + (input - b0) / (b1 - b0) * (e1 - e0) : e0;
34442
+ return clampRange(evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], localT));
31417
34443
  }
31418
34444
  }
31419
- const c0 = getNums("C0", [0, 0, 0]);
31420
- const c1 = getNums("C1", [1, 1, 1]);
34445
+ const c0 = getNums("C0", [0]);
34446
+ const c1 = getNums("C1", [1]);
31421
34447
  const nNode = doc.resolve(dictGet(fnDict, "N"));
31422
- const expN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
34448
+ const expN = nNode?.kind === "number" ? nNode.value : 1;
31423
34449
  const d0 = dom[0] ?? 0;
31424
34450
  const d1 = dom[1] ?? 1;
31425
- const normT = Math.abs(d1 - d0) > 1e-8 ? (t - d0) / (d1 - d0) : t;
31426
- const w = Math.pow(Math.max(0, Math.min(1, normT)), expN);
34451
+ const w = Math.pow(Math.max(d0, Math.min(d1, t)), expN);
31427
34452
  const len = Math.max(c0.length, c1.length);
31428
34453
  const out = [];
31429
34454
  for (let i = 0; i < len; i++) {
@@ -31439,30 +34464,14 @@ function shadingComponentsToRgb(csName, comps) {
31439
34464
  return [v, v, v];
31440
34465
  }
31441
34466
  if (csName === "DeviceCMYK" || csName === "CMYK" || comps.length >= 4) {
31442
- const cc = comps[0] ?? 0, cm = comps[1] ?? 0, cy = comps[2] ?? 0, ck = comps[3] ?? 0;
31443
- return [(1 - cc) * (1 - ck), (1 - cm) * (1 - kClamp(ck)), (1 - cy) * (1 - kClamp(ck))];
34467
+ const rgb2 = cmykColorSpace2.getRgb([comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0, comps[3] ?? 0], 0);
34468
+ return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
31444
34469
  }
31445
34470
  return [comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0];
31446
34471
  }
31447
34472
  function kClamp(v) {
31448
34473
  return Math.max(0, Math.min(1, v));
31449
34474
  }
31450
- function xyzToSrgb(X, Y, Z, Xw = 0.95047, Yw = 1, Zw = 1.08883) {
31451
- const scaleX = Xw > 1e-6 ? 0.95047 / Xw : 1;
31452
- const scaleY = Yw > 1e-6 ? 1 / Yw : 1;
31453
- const scaleZ = Zw > 1e-6 ? 1.08883 / Zw : 1;
31454
- const x = X * scaleX;
31455
- const y = Y * scaleY;
31456
- const z = Z * scaleZ;
31457
- const rl = 3.2404542 * x - 1.5371385 * y - 0.4985314 * z;
31458
- const gl = -0.969266 * x + 1.8760108 * y + 0.041556 * z;
31459
- const bl = 0.0556434 * x - 0.2040259 * y + 1.0572252 * z;
31460
- const toGamma = (u) => {
31461
- const c = Math.max(0, Math.min(1, u));
31462
- return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
31463
- };
31464
- return [toGamma(rl), toGamma(gl), toGamma(bl)];
31465
- }
31466
34475
  function getColorSpaceComponentCount(doc, csNode, activeResources, depth = 0) {
31467
34476
  if (!csNode || depth > 4) return 3;
31468
34477
  const resolved = doc ? doc.resolve(csNode) : csNode;
@@ -31519,63 +34528,10 @@ function convertColorSpaceComponentsToRgb(doc, csNode, csNameFallback, comps, ac
31519
34528
  if (resolved.kind === "array" && resolved.items.length > 0 && doc) {
31520
34529
  const familyNode = doc.resolve(resolved.items[0]);
31521
34530
  const family = familyNode?.kind === "name" ? familyNode.decoded : "";
31522
- if (family === "CalGray") {
31523
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
31524
- const gNode = paramDict ? doc.resolve(dictGet(paramDict, "Gamma")) : void 0;
31525
- const gamma = gNode?.kind === "number" && gNode.value > 0 ? gNode.value : 1;
31526
- const a = Math.pow(kClamp(comps[0] ?? 0), gamma);
31527
- return [a, a, a];
31528
- }
31529
- if (family === "CalRGB") {
31530
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
31531
- const gammaArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Gamma")) : void 0;
31532
- const getArrNum = (arr, idx, fb) => {
31533
- const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
31534
- return r?.kind === "number" ? r.value : fb;
31535
- };
31536
- const gr = getArrNum(gammaArr, 0, 1);
31537
- const gg = getArrNum(gammaArr, 1, 1);
31538
- const gb = getArrNum(gammaArr, 2, 1);
31539
- const ag = Math.pow(kClamp(comps[0] ?? 0), gr > 0 ? gr : 1);
31540
- const bg = Math.pow(kClamp(comps[1] ?? 0), gg > 0 ? gg : 1);
31541
- const cg = Math.pow(kClamp(comps[2] ?? 0), gb > 0 ? gb : 1);
31542
- const matArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Matrix")) : void 0;
31543
- if (matArr && matArr.items.length >= 9) {
31544
- const m = (i) => getArrNum(matArr, i, 0);
31545
- const X = m(0) * ag + m(3) * bg + m(6) * cg;
31546
- const Y = m(1) * ag + m(4) * bg + m(7) * cg;
31547
- const Z = m(2) * ag + m(5) * bg + m(8) * cg;
31548
- const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
31549
- const Xw = getArrNum(wpArr, 0, 0.95047);
31550
- const Yw = getArrNum(wpArr, 1, 1);
31551
- const Zw = getArrNum(wpArr, 2, 1.08883);
31552
- return xyzToSrgb(X, Y, Z, Xw, Yw, Zw);
31553
- }
31554
- return [ag, bg, cg];
31555
- }
31556
- if (family === "Lab") {
31557
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
31558
- const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
31559
- const rangeArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Range")) : void 0;
31560
- const getNum = (arr, idx, fb) => {
31561
- const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
31562
- return r?.kind === "number" ? r.value : fb;
31563
- };
31564
- const Xw = getNum(wpArr, 0, 0.95047);
31565
- const Yw = getNum(wpArr, 1, 1);
31566
- const Zw = getNum(wpArr, 2, 1.08883);
31567
- const amin = getNum(rangeArr, 0, -100);
31568
- const amax = getNum(rangeArr, 1, 100);
31569
- const bmin = getNum(rangeArr, 2, -100);
31570
- const bmax = getNum(rangeArr, 3, 100);
31571
- const Lstar = Math.max(0, Math.min(100, comps[0] ?? 0));
31572
- const astar = Math.max(amin, Math.min(amax, comps[1] ?? 0));
31573
- const bstar = Math.max(bmin, Math.min(bmax, comps[2] ?? 0));
31574
- const M = (Lstar + 16) / 116;
31575
- const L = M + astar / 500;
31576
- const N = M - bstar / 200;
31577
- const gFn = (x) => x >= 6 / 29 ? x * x * x : 108 / 841 * (x - 4 / 29);
31578
- return xyzToSrgb(Xw * gFn(L), Yw * gFn(M), Zw * gFn(N), Xw, Yw, Zw);
34531
+ if (family === "CalGray" || family === "CalRGB" || family === "Lab") {
34532
+ const colorSpace = createCalibratedColorSpace(doc, family, resolved.items[1]);
34533
+ const rgb2 = colorSpace.getRgb(comps, 0);
34534
+ return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
31579
34535
  }
31580
34536
  if (family === "ICCBased" && resolved.items[1]) {
31581
34537
  const iccNode = doc.resolve(resolved.items[1]);
@@ -31656,143 +34612,28 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
31656
34612
  const r = doc.resolve(it);
31657
34613
  return r?.kind === "number" ? r.value : 0;
31658
34614
  });
31659
- const xmin = decodeNums[0], xmax = decodeNums[1], ymin = decodeNums[2], ymax = decodeNums[3];
31660
- const numColorParams = Math.max(1, Math.floor((decodeNums.length - 4) / 2));
31661
34615
  const fnNode = dictGet(shDict, "Function");
31662
34616
  const csNode = doc.resolve(dictGet(shDict, "ColorSpace"));
31663
34617
  const csName = csNode?.kind === "name" ? csNode.decoded : "DeviceRGB";
31664
- let bitPos = 0;
31665
- const totalBits = bytes.length * 8;
31666
- const readBits = (n) => {
31667
- let val = 0;
31668
- for (let i = 0; i < n; i++) {
31669
- if (bitPos >= totalBits) return val;
31670
- const byteIdx = bitPos >> 3;
31671
- const bitIdx = 7 - (bitPos & 7);
31672
- val = val * 2 + (bytes[byteIdx] >> bitIdx & 1);
31673
- bitPos++;
31674
- }
31675
- return val;
31676
- };
31677
- const coordMax = Math.pow(2, bpcCoord) - 1 || 1;
31678
- const compMax = Math.pow(2, bpcComp) - 1 || 1;
31679
- const readCoord = () => {
31680
- const rx = readBits(bpcCoord) / coordMax;
31681
- const ry = readBits(bpcCoord) / coordMax;
31682
- return [xmin + rx * (xmax - xmin), ymin + ry * (ymax - ymin)];
31683
- };
31684
- const readColorRgb = () => {
31685
- const params = [];
31686
- for (let c = 0; c < numColorParams; c++) {
31687
- const rc = readBits(bpcComp) / compMax;
31688
- const cMin = decodeNums[4 + c * 2] ?? 0;
31689
- const cMax = decodeNums[4 + c * 2 + 1] ?? 1;
31690
- params.push(cMin + rc * (cMax - cMin));
31691
- }
31692
- const comps = fnNode ? evalShadingFunctionToComponents(doc, fnNode, params) : params;
31693
- return convertColorSpaceComponentsToRgb(doc, csNode, csName, comps);
31694
- };
31695
- const triangles = [];
31696
- if (shType === 4) {
31697
- const minBitsPerVert = bpcFlag + 2 * bpcCoord + numColorParams * bpcComp;
31698
- let triVerts;
31699
- while (bitPos + minBitsPerVert <= totalBits) {
31700
- const flag = readBits(bpcFlag) & 3;
31701
- const [x, y] = readCoord();
31702
- const rgb2 = readColorRgb();
31703
- const vNew = { x, y, rgb: rgb2 };
31704
- if (flag === 0 || !triVerts) {
31705
- if (bitPos + 2 * minBitsPerVert > totalBits) break;
31706
- readBits(bpcFlag);
31707
- const [x1, y1] = readCoord();
31708
- const rgb1 = readColorRgb();
31709
- readBits(bpcFlag);
31710
- const [x2, y2] = readCoord();
31711
- const rgb22 = readColorRgb();
31712
- triVerts = [vNew, { x: x1, y: y1, rgb: rgb1 }, { x: x2, y: y2, rgb: rgb22 }];
31713
- triangles.push(triVerts);
31714
- } else if (flag === 1) {
31715
- triVerts = [triVerts[1], triVerts[2], vNew];
31716
- triangles.push(triVerts);
31717
- } else if (flag === 2) {
31718
- triVerts = [triVerts[0], triVerts[2], vNew];
31719
- triangles.push(triVerts);
31720
- }
31721
- }
31722
- } else if (shType === 5) {
31723
- const minBitsPerVert = 2 * bpcCoord + numColorParams * bpcComp;
31724
- const verts = [];
31725
- while (bitPos + minBitsPerVert <= totalBits) {
31726
- const [x, y] = readCoord();
31727
- const rgb2 = readColorRgb();
31728
- verts.push({ x, y, rgb: rgb2 });
31729
- }
31730
- const numRows = Math.floor(verts.length / vPerRow);
31731
- for (let r = 0; r + 1 < numRows; r++) {
31732
- for (let c = 0; c + 1 < vPerRow; c++) {
31733
- const v00 = verts[r * vPerRow + c];
31734
- const v01 = verts[r * vPerRow + c + 1];
31735
- const v11 = verts[(r + 1) * vPerRow + c + 1];
31736
- const v10 = verts[(r + 1) * vPerRow + c];
31737
- triangles.push([v00, v01, v11], [v00, v11, v10]);
31738
- }
31739
- }
31740
- } else if (shType === 6 || shType === 7) {
31741
- const numCtrl = shType === 6 ? 12 : 16;
31742
- const minBitsPatch = bpcFlag + (numCtrl - 4) * 2 * bpcCoord + 2 * numColorParams * bpcComp;
31743
- let prevPts;
31744
- let prevColors;
31745
- while (bitPos + minBitsPatch <= totalBits) {
31746
- const flag = readBits(bpcFlag) & 3;
31747
- let pts = [];
31748
- let cols = [];
31749
- if (flag === 0 || !prevPts || !prevColors) {
31750
- for (let i = 0; i < numCtrl; i++) pts.push(readCoord());
31751
- for (let i = 0; i < 4; i++) cols.push(readColorRgb());
31752
- } else {
31753
- const extraCtrl = numCtrl - 4;
31754
- const readExtra = [];
31755
- for (let i = 0; i < extraCtrl; i++) readExtra.push(readCoord());
31756
- const c2 = readColorRgb();
31757
- const c3 = readColorRgb();
31758
- pts = [prevPts[3], prevPts[4], prevPts[5], prevPts[6], ...readExtra];
31759
- cols = [prevColors[1], prevColors[2], c2, c3];
31760
- }
31761
- prevPts = pts;
31762
- prevColors = cols;
31763
- const p00 = pts[0];
31764
- const p03 = pts[3];
31765
- const p33 = pts[6];
31766
- const p30 = pts[9];
31767
- const c00 = cols[0], c03 = cols[1], c33 = cols[2], c30 = cols[3];
31768
- const steps = 4;
31769
- const grid = [];
31770
- for (let iu = 0; iu <= steps; iu++) {
31771
- const u = iu / steps;
31772
- const row = [];
31773
- for (let iv = 0; iv <= steps; iv++) {
31774
- const v = iv / steps;
31775
- const x = (1 - u) * (1 - v) * p00[0] + (1 - u) * v * p03[0] + u * v * p33[0] + u * (1 - v) * p30[0];
31776
- const y = (1 - u) * (1 - v) * p00[1] + (1 - u) * v * p03[1] + u * v * p33[1] + u * (1 - v) * p30[1];
31777
- const r = (1 - u) * (1 - v) * c00[0] + (1 - u) * v * c03[0] + u * v * c33[0] + u * (1 - v) * c30[0];
31778
- const g = (1 - u) * (1 - v) * c00[1] + (1 - u) * v * c03[1] + u * v * c33[1] + u * (1 - v) * c30[1];
31779
- const b = (1 - u) * (1 - v) * c00[2] + (1 - u) * v * c03[2] + u * v * c33[2] + u * (1 - v) * c30[2];
31780
- row.push({ x, y, rgb: [r, g, b] });
31781
- }
31782
- grid.push(row);
31783
- }
31784
- for (let iu = 0; iu < steps; iu++) {
31785
- for (let iv = 0; iv < steps; iv++) {
31786
- const g00 = grid[iu][iv];
31787
- const g01 = grid[iu][iv + 1];
31788
- const g11 = grid[iu + 1][iv + 1];
31789
- const g10 = grid[iu + 1][iv];
31790
- triangles.push([g00, g01, g11], [g00, g11, g10]);
31791
- }
31792
- }
31793
- }
31794
- }
31795
- if (triangles.length === 0) return void 0;
34618
+ const numComps = fnNode ? 1 : getColorSpaceComponentCount(doc, csNode);
34619
+ const mesh = new MeshShading(shType, new Stream(bytes), {
34620
+ bitsPerCoordinate: bpcCoord,
34621
+ bitsPerComponent: bpcComp,
34622
+ bitsPerFlag: bpcFlag,
34623
+ decode: decodeNums,
34624
+ numComps,
34625
+ colorFn: null,
34626
+ colorSpace: {
34627
+ numComps,
34628
+ getRgb(components) {
34629
+ const params = Array.from(components);
34630
+ const values = fnNode ? evalShadingFunctionToComponents(doc, fnNode, params) : params;
34631
+ return new Uint8Array(convertColorSpaceComponentsToRgb(doc, csNode, csName, values).map((value) => Math.round(Math.max(0, Math.min(1, value)) * 255)));
34632
+ }
34633
+ }
34634
+ }, vPerRow);
34635
+ const [, , positions, colors, vertexCount] = mesh.getIR();
34636
+ if (vertexCount === 0) return void 0;
31796
34637
  const [bx0, by0, bx1, by1] = targetBox;
31797
34638
  const boxW = Math.max(1, bx1 - bx0);
31798
34639
  const boxH = Math.max(1, by1 - by0);
@@ -31804,10 +34645,10 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
31804
34645
  const [px, py] = transformPoint(effectiveCtm, vx, vy);
31805
34646
  return [(px - bx0) / boxW * imgW, (by1 - py) / boxH * imgH];
31806
34647
  };
31807
- for (const [v0, v1, v2] of triangles) {
31808
- const [x0, y0] = toImgCoords(v0.x, v0.y);
31809
- const [x1, y1] = toImgCoords(v1.x, v1.y);
31810
- const [x2, y2] = toImgCoords(v2.x, v2.y);
34648
+ for (let vertex = 0; vertex < vertexCount; vertex += 3) {
34649
+ const [x0, y0] = toImgCoords(positions[vertex * 2], positions[vertex * 2 + 1]);
34650
+ const [x1, y1] = toImgCoords(positions[vertex * 2 + 2], positions[vertex * 2 + 3]);
34651
+ const [x2, y2] = toImgCoords(positions[vertex * 2 + 4], positions[vertex * 2 + 5]);
31811
34652
  const denom = (y1 - y2) * (x0 - x2) + (x2 - x1) * (y0 - y2);
31812
34653
  if (Math.abs(denom) < 1e-6) continue;
31813
34654
  const minX = Math.max(0, Math.floor(Math.min(x0, x1, x2)));
@@ -31822,13 +34663,12 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
31822
34663
  const w1 = ((y2 - y0) * (px - x2) + (x0 - x2) * (py - y2)) / denom;
31823
34664
  const w2 = 1 - w0 - w1;
31824
34665
  if (w0 >= -1e-4 && w1 >= -1e-4 && w2 >= -1e-4) {
31825
- const r = w0 * v0.rgb[0] + w1 * v1.rgb[0] + w2 * v2.rgb[0];
31826
- const g = w0 * v0.rgb[1] + w1 * v1.rgb[1] + w2 * v2.rgb[1];
31827
- const b = w0 * v0.rgb[2] + w1 * v1.rgb[2] + w2 * v2.rgb[2];
31828
34666
  const pIdx = (iy * imgW + ix) * 4;
31829
- rgba[pIdx] = Math.round(Math.max(0, Math.min(1, r)) * 255);
31830
- rgba[pIdx + 1] = Math.round(Math.max(0, Math.min(1, g)) * 255);
31831
- rgba[pIdx + 2] = Math.round(Math.max(0, Math.min(1, b)) * 255);
34667
+ for (let channel = 0; channel < 3; channel++) {
34668
+ rgba[pIdx + channel] = Math.round(
34669
+ w0 * colors[vertex * 4 + channel] + w1 * colors[vertex * 4 + 4 + channel] + w2 * colors[vertex * 4 + 8 + channel]
34670
+ );
34671
+ }
31832
34672
  rgba[pIdx + 3] = a8;
31833
34673
  }
31834
34674
  }
@@ -31915,6 +34755,8 @@ function renderShadingDictToImage(doc, shDict, shadingCtm, targetBox, fillAlpha,
31915
34755
  const [a, b, c, d, e, f] = effectiveCtm;
31916
34756
  const det = a * d - b * c;
31917
34757
  if (Math.abs(det) <= 1e-8) return void 0;
34758
+ const [sa, sb, sc, sd, se, sf] = shadingCtm;
34759
+ const shadingDet = sa * sd - sb * sc;
31918
34760
  const t0Dom = shDomain[0] ?? 0;
31919
34761
  const t1Dom = shDomain[1] ?? 1;
31920
34762
  for (let iy = 0; iy < imgH; iy++) {
@@ -31925,8 +34767,10 @@ function renderShadingDictToImage(doc, shDict, shadingCtm, targetBox, fillAlpha,
31925
34767
  const dxPdf = xPdf - e;
31926
34768
  const xs = (d * dxPdf - c * dyPdf) / det;
31927
34769
  const ys = (-b * dxPdf + a * dyPdf) / det;
31928
- if (shBBox && (xs < shBBox[0] || xs > shBBox[2] || ys < shBBox[1] || ys > shBBox[3])) {
31929
- continue;
34770
+ if (shBBox) {
34771
+ const bboxX = (sd * (xPdf - se) - sc * (yPdf - sf)) / shadingDet;
34772
+ const bboxY = (-sb * (xPdf - se) + sa * (yPdf - sf)) / shadingDet;
34773
+ if (bboxX < shBBox[0] || bboxX > shBBox[2] || bboxY < shBBox[1] || bboxY > shBBox[3]) continue;
31930
34774
  }
31931
34775
  let comps;
31932
34776
  if (shType === 1) {
@@ -32226,7 +35070,8 @@ function evaluateContentStreamToDisplayList(params) {
32226
35070
  const shDict = shNode?.kind === "dict" ? shNode : shNode?.kind === "stream" ? shNode.dict : void 0;
32227
35071
  const shStream = shNode?.kind === "stream" ? shNode : void 0;
32228
35072
  if (shDict) {
32229
- const targetBox = st.clipRect ?? [0, 0, params.width, params.height];
35073
+ const [originX, originY] = params.origin ?? [0, 0];
35074
+ const targetBox = st.clipRect ?? [originX, originY, originX + params.width, originY + params.height];
32230
35075
  const img = renderShadingDictToImage(
32231
35076
  params.cosDoc,
32232
35077
  shDict,
@@ -32265,12 +35110,10 @@ function evaluateContentStreamToDisplayList(params) {
32265
35110
  } else if (operator === "RG" || operator === "SC" || operator === "SCN") {
32266
35111
  st.strokeColor = resolveScColorOperands(operator === "RG" ? "DeviceRGB" : st.strokeColorSpaceName, ops, activeResources);
32267
35112
  } else if (operator === "k") {
32268
- const c = num(0), m = num(1), y = num(2), k = num(3);
32269
- st.fillColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
35113
+ st.fillColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
32270
35114
  st.fillPatternName = void 0;
32271
35115
  } else if (operator === "K") {
32272
- const c = num(0), m = num(1), y = num(2), k = num(3);
32273
- st.strokeColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
35116
+ st.strokeColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
32274
35117
  } else if (operator === "gs" && params.cosDoc && activeResources && ops[0]?.kind === "name") {
32275
35118
  const extDict = params.cosDoc.resolveDict(dictGet(activeResources, "ExtGState"));
32276
35119
  const gsDict = extDict ? params.cosDoc.resolveDict(dictGet(extDict, ops[0].decoded)) : void 0;
@@ -32479,7 +35322,7 @@ function evaluateContentStreamToDisplayList(params) {
32479
35322
  stateStack.pop();
32480
35323
  capturedOperations = parentOperations;
32481
35324
  }
32482
- if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
35325
+ if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, isolated, bboxClip: nextClipPaths?.[0], blendMode: st.blendMode, clipRect: st.clipRect } });
32483
35326
  };
32484
35327
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
32485
35328
  for (const node of nodes) {
@@ -33063,6 +35906,7 @@ function evaluateContentStreamToDisplayList(params) {
33063
35906
  pageIndex: params.pageIndex,
33064
35907
  width: params.width,
33065
35908
  height: params.height,
35909
+ ...params.origin ? { origin: params.origin } : {},
33066
35910
  rotation: params.rotation ?? 0,
33067
35911
  glyphs,
33068
35912
  paths,
@@ -35082,7 +37926,7 @@ function prepareStroke(path, scale) {
35082
37926
  }
35083
37927
  return { matrix, width, dashArray, dashPhase };
35084
37928
  }
35085
- function strokeContours(path, pageHeight, scale) {
37929
+ function strokeContours(path, pageHeight, scale, originX = 0, originY = 0) {
35086
37930
  const stroke = prepareStroke(path, scale);
35087
37931
  if (!stroke) return [];
35088
37932
  const inverse = inverseStrokeMatrix(stroke.matrix);
@@ -35094,8 +37938,8 @@ function strokeContours(path, pageHeight, scale) {
35094
37938
  (inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
35095
37939
  ];
35096
37940
  const toScreen = ([x, y]) => [
35097
- (a * x / strokeScale + c * y / strokeScale + e) * scale,
35098
- (pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
37941
+ (a * x / strokeScale + c * y / strokeScale + e - originX) * scale,
37942
+ (pageHeight + originY - b * x / strokeScale - d * y / strokeScale - f) * scale
35099
37943
  ];
35100
37944
  const contours = strokeOutlines(
35101
37945
  segmentsToScreenPaths(path.segments, pageHeight, scale, project),
@@ -35253,18 +38097,34 @@ function renderSoftMask(mask, displayList, scale) {
35253
38097
  }
35254
38098
  return bitmap;
35255
38099
  }
35256
- function hasBlendModes(operations) {
35257
- return operations.some((operation) => !!operation.value.blendMode && operation.value.blendMode !== "Normal" && operation.value.blendMode !== "Compatible" || operation.kind === "group" && hasBlendModes(operation.value.operations));
38100
+ function getDisplayListCropBox(list) {
38101
+ const full = [0, 0, list.width, list.height];
38102
+ const box = list.cropBox;
38103
+ if (!box || !box.every(Number.isFinite)) return full;
38104
+ const x0 = Math.max(0, Math.min(box[0], box[2]));
38105
+ const y0 = Math.max(0, Math.min(box[1], box[3]));
38106
+ const x1 = Math.min(list.width, Math.max(box[0], box[2]));
38107
+ const y1 = Math.min(list.height, Math.max(box[1], box[3]));
38108
+ return x1 > x0 && y1 > y0 ? [x0, y0, x1, y1] : full;
38109
+ }
38110
+ function hasCompositingEffects(operations, includeSoftMasks = false) {
38111
+ 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));
38112
+ }
38113
+ function needsGroupBackdrop(group) {
38114
+ return group.isolated === false && !!group.softMask && hasCompositingEffects(group.operations, true);
35258
38115
  }
35259
38116
  function renderDisplayListToBitmap(displayList, options = {}) {
35260
38117
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
35261
38118
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
35262
38119
  const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
35263
38120
  const scale = scaleX;
38121
+ const [originX, originY] = displayList.origin ?? [0, 0];
38122
+ const pageTop = originY + displayList.height;
38123
+ const toScreen = (x, y) => [(x - originX) * scale, (pageTop - y) * scale];
35264
38124
  const width = Math.max(1, Math.round(displayList.width * scale));
35265
38125
  const height = Math.max(1, Math.round(displayList.height * scale));
35266
38126
  const rgba = new Uint8Array(width * height * 4);
35267
- const deferBackground = !options.transparent && hasBlendModes(paintOperations(displayList));
38127
+ const deferBackground = !options.transparent && hasCompositingEffects(paintOperations(displayList));
35268
38128
  const transparent = options.transparent || deferBackground;
35269
38129
  const bg = options.background ?? { r: 1, g: 1, b: 1 };
35270
38130
  const bgR = transparent ? 0 : Math.round(bg.r * 255);
@@ -35289,14 +38149,27 @@ function renderDisplayListToBitmap(displayList, options = {}) {
35289
38149
  let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
35290
38150
  if (operation.kind === "group") {
35291
38151
  const group = operation.value;
35292
- const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations: group.operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, transparent: true });
38152
+ let operations = group.operations;
38153
+ if (needsGroupBackdrop(group)) {
38154
+ operations = [{ kind: "image", value: {
38155
+ name: "GroupBackdrop",
38156
+ width,
38157
+ height,
38158
+ decodedRgba: rgba.slice(),
38159
+ matrix: [width / scale, 0, 0, height / scale, originX, pageTop - height / scale],
38160
+ colorSpace: "DeviceRGB",
38161
+ bitsPerComponent: 8,
38162
+ ...group.bboxClip ? { clipPaths: [group.bboxClip] } : {}
38163
+ } }, ...operations];
38164
+ }
38165
+ const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, useCropBox: false, transparent: true });
35293
38166
  for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
35294
38167
  operation = { kind: "image", value: {
35295
38168
  name: "TransparencyGroup",
35296
38169
  width: bitmap.width,
35297
38170
  height: bitmap.height,
35298
38171
  decodedRgba: bitmap.data,
35299
- matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, 0, displayList.height - bitmap.height / scale],
38172
+ matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, originX, pageTop - bitmap.height / scale],
35300
38173
  colorSpace: "DeviceRGB",
35301
38174
  bitsPerComponent: 8,
35302
38175
  blendMode: group.blendMode,
@@ -35310,7 +38183,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
35310
38183
  for (const clip of clips) {
35311
38184
  const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
35312
38185
  const layer = new Uint8Array(width * height * 4);
35313
- fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
38186
+ fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale, toScreen), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
35314
38187
  for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
35315
38188
  }
35316
38189
  cachedClips = clips;
@@ -35357,15 +38230,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
35357
38230
  if (operation.kind === "path") {
35358
38231
  const path = operation.value;
35359
38232
  if (path.fillColor) {
35360
- const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale), true);
35361
- 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;
38233
+ const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale, toScreen), true);
38234
+ 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;
35362
38235
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
35363
38236
  }
35364
38237
  if (path.strokeColor) {
35365
38238
  const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
35366
38239
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
35367
- const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
35368
- 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;
38240
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale, originX, originY).map((points) => ({ points, closed: true })));
38241
+ 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;
35369
38242
  fillEdgesScanline4x4(
35370
38243
  rgba,
35371
38244
  width,
@@ -35388,12 +38261,12 @@ function renderDisplayListToBitmap(displayList, options = {}) {
35388
38261
  if (Math.abs(det) <= 1e-8) continue;
35389
38262
  const cornersPdfX = [e, a + e, a + c + e, c + e];
35390
38263
  const cornersPdfY = [f, b + f, b + d + f, d + f];
35391
- const cornersPx = cornersPdfX.map((cx) => cx * scale);
35392
- const cornersPy = cornersPdfY.map((cy) => (displayList.height - cy) * scale);
35393
- const clipMinPx = img.clipRect ? Math.floor(img.clipRect[0] * scale) : 0;
35394
- const clipMaxPx = img.clipRect ? Math.ceil(img.clipRect[2] * scale) - 1 : width - 1;
35395
- const clipMinPy = img.clipRect ? Math.floor((displayList.height - img.clipRect[3]) * scale) : 0;
35396
- const clipMaxPy = img.clipRect ? Math.ceil((displayList.height - img.clipRect[1]) * scale) - 1 : height - 1;
38264
+ const cornersPx = cornersPdfX.map((cx) => (cx - originX) * scale);
38265
+ const cornersPy = cornersPdfY.map((cy) => (pageTop - cy) * scale);
38266
+ const clipMinPx = img.clipRect ? Math.floor((img.clipRect[0] - originX) * scale) : 0;
38267
+ const clipMaxPx = img.clipRect ? Math.ceil((img.clipRect[2] - originX) * scale) - 1 : width - 1;
38268
+ const clipMinPy = img.clipRect ? Math.floor((pageTop - img.clipRect[3]) * scale) : 0;
38269
+ const clipMaxPy = img.clipRect ? Math.ceil((pageTop - img.clipRect[1]) * scale) - 1 : height - 1;
35397
38270
  const minPx = Math.max(0, clipMinPx, Math.floor(Math.min(...cornersPx)));
35398
38271
  const maxPx = Math.min(width - 1, clipMaxPx, Math.ceil(Math.max(...cornersPx)) - 1);
35399
38272
  const minPy = Math.max(0, clipMinPy, Math.floor(Math.min(...cornersPy)));
@@ -35410,11 +38283,11 @@ function renderDisplayListToBitmap(displayList, options = {}) {
35410
38283
  const smooth = Math.fround((s1 + s2 + Math.hypot(s1 - s2, 2 * cross)) / 2) <= 1;
35411
38284
  const sample = new Float64Array(4);
35412
38285
  for (let py = minPy; py <= maxPy; py++) {
35413
- const yPdf = displayList.height - (py + 0.5) / scale;
38286
+ const yPdf = pageTop - (py + 0.5) / scale;
35414
38287
  if (img.clipRect && (yPdf < img.clipRect[1] || yPdf > img.clipRect[3])) continue;
35415
38288
  const dyPdf = yPdf - f;
35416
38289
  for (let px = minPx; px <= maxPx; px++) {
35417
- const xPdf = (px + 0.5) / scale;
38290
+ const xPdf = originX + (px + 0.5) / scale;
35418
38291
  if (img.clipRect && (xPdf < img.clipRect[0] || xPdf > img.clipRect[2])) continue;
35419
38292
  const dxPdf = xPdf - e;
35420
38293
  const u = (d * dxPdf - c * dyPdf) / det;
@@ -35475,6 +38348,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
35475
38348
  }
35476
38349
  result = { width: targetW, height: targetH, data: resampled };
35477
38350
  }
38351
+ if (options.useCropBox) {
38352
+ const box = getDisplayListCropBox(displayList);
38353
+ result = cropRgbaBitmap(result, {
38354
+ x: box[0] * scaleX,
38355
+ y: (displayList.height - box[3]) * scaleY,
38356
+ width: (box[2] - box[0]) * scaleX,
38357
+ height: (box[3] - box[1]) * scaleY
38358
+ });
38359
+ }
35478
38360
  result = rotateRgbaBitmapQuarterTurns(result, displayList.rotation ?? 0);
35479
38361
  if (options.cropRect) {
35480
38362
  result = cropRgbaBitmap(result, options.cropRect);
@@ -35503,23 +38385,6 @@ function collectLeavesForRaster(cosDoc, node, out = [], visited = /* @__PURE__ *
35503
38385
  }
35504
38386
  return out;
35505
38387
  }
35506
- function extractBoxArray(cosDoc, dict, key) {
35507
- let cur = dict;
35508
- const visited = /* @__PURE__ */ new Set();
35509
- while (cur && !visited.has(cur)) {
35510
- visited.add(cur);
35511
- const arr = cosDoc.resolveArray(dictGet(cur, key));
35512
- if (arr && arr.items.length >= 4) {
35513
- const nums = arr.items.slice(0, 4).map((item) => {
35514
- const r = cosDoc.resolve(item);
35515
- return r?.kind === "number" ? r.value : 0;
35516
- });
35517
- return [nums[0], nums[1], nums[2], nums[3]];
35518
- }
35519
- cur = cosDoc.resolveDict(dictGet(cur, "Parent"));
35520
- }
35521
- return void 0;
35522
- }
35523
38388
  function renderPdfPageToBitmap(pdfBytes, pageIndex = 0, options) {
35524
38389
  const cos = pdfBytes instanceof Uint8Array ? parseCosDocument(pdfBytes) : pdfBytes;
35525
38390
  const catalog = cos.resolveDict(cos.rootRef);
@@ -35528,35 +38393,7 @@ function renderPdfPageToBitmap(pdfBytes, pageIndex = 0, options) {
35528
38393
  if (!leaf) throw new Error(`Page index ${pageIndex} out of bounds`);
35529
38394
  const resolvedIndex = leaves.indexOf(leaf);
35530
38395
  const page = new PdfPage(cos, leaf.ref, leaf.dict, resolvedIndex);
35531
- const { cropRect, ...restOptions } = options ?? {};
35532
- let bitmap = renderDisplayListToBitmap(
35533
- // CropBox is in unrotated page coordinates. Apply page rotation after it.
35534
- { ...page.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), rotation: 0 },
35535
- restOptions
35536
- );
35537
- if (options?.useCropBox) {
35538
- const cropBox = extractBoxArray(cos, leaf.dict, "CropBox");
35539
- if (cropBox) {
35540
- const mediaBox = extractBoxArray(cos, leaf.dict, "MediaBox") ?? [0, 0, page.getSize().width, page.getSize().height];
35541
- const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
35542
- const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
35543
- const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
35544
- const mediaH = mediaBox[3] - mediaBox[1];
35545
- const bx = Math.round((cropBox[0] - mediaBox[0]) * scaleX);
35546
- const by = Math.round((mediaH - (cropBox[3] - mediaBox[1])) * scaleY);
35547
- const bw = Math.max(1, Math.round(Math.abs(cropBox[2] - cropBox[0]) * scaleX));
35548
- const bh = Math.max(1, Math.round(Math.abs(cropBox[3] - cropBox[1]) * scaleY));
35549
- bitmap = cropRgbaBitmap(bitmap, { x: bx, y: by, width: bw, height: bh });
35550
- }
35551
- }
35552
- const rotation = page.getRotation();
35553
- if (rotation === 90 || rotation === 180 || rotation === 270) {
35554
- bitmap = rotateRgbaBitmapQuarterTurns(bitmap, rotation);
35555
- }
35556
- if (cropRect) {
35557
- bitmap = cropRgbaBitmap(bitmap, cropRect);
35558
- }
35559
- return bitmap;
38396
+ return page.renderToBitmap(options);
35560
38397
  }
35561
38398
  function renderPdfPageToPng(pdfBytes, pageIndex = 0, options) {
35562
38399
  const bmp = renderPdfPageToBitmap(pdfBytes, pageIndex, options);
@@ -35630,7 +38467,7 @@ var PdfPage = class {
35630
38467
  return [n0.value, n1.value, n2.value, n3.value];
35631
38468
  }
35632
38469
  }
35633
- return [0, 0, 612, 792];
38470
+ return key === "MediaBox" ? [0, 0, 612, 792] : this.resolveBox("MediaBox");
35634
38471
  }
35635
38472
  getMediaBox() {
35636
38473
  return this.resolveBox("MediaBox");
@@ -36303,16 +39140,19 @@ var PdfPage = class {
36303
39140
  });
36304
39141
  }
36305
39142
  }
36306
- return evaluateContentStreamToDisplayList({
39143
+ const mediaBox = this.getMediaBox(), cropBox = this.getCropBox();
39144
+ const originX = Math.min(mediaBox[0], mediaBox[2]), originY = Math.min(mediaBox[1], mediaBox[3]);
39145
+ return { ...evaluateContentStreamToDisplayList({
36307
39146
  pageIndex: this.index,
36308
39147
  width,
36309
39148
  height,
39149
+ origin: [originX, originY],
36310
39150
  rotation: this.getRotation(),
36311
39151
  nodes: baseNodes,
36312
39152
  cosDoc: this.cosDoc,
36313
39153
  resourcesDict: evalResourcesDict,
36314
39154
  annotations: extractPageAnnotations(this.cosDoc, this.pageDict)
36315
- });
39155
+ }), cropBox: [cropBox[0] - originX, cropBox[1] - originY, cropBox[2] - originX, cropBox[3] - originY] };
36316
39156
  }
36317
39157
  extractPage(options) {
36318
39158
  const dl = this.evaluateDisplayList();
@@ -36330,10 +39170,10 @@ var PdfPage = class {
36330
39170
  return extractTablesFromDisplayList(this.evaluateDisplayList());
36331
39171
  }
36332
39172
  renderToBitmap(options) {
36333
- return renderDisplayListToBitmap(this.evaluateDisplayList(), options);
39173
+ return renderDisplayListToBitmap(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
36334
39174
  }
36335
39175
  renderToPng(options) {
36336
- return renderDisplayListToPng(this.evaluateDisplayList(), options);
39176
+ return renderDisplayListToPng(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
36337
39177
  }
36338
39178
  };
36339
39179
  function createStandardFontHandle(standardName) {