@poe-platform/safe-bash 0.1.771 → 0.1.773

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 (42) hide show
  1. package/dist/image-ast/index.browser.js +2801 -556
  2. package/dist/image-ast/index.js +2801 -556
  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 +2845 -568
  6. package/dist/pdf-ast/render/raster.d.ts +1 -0
  7. package/dist/pdf-ast/vendor/pdfjs-fonts.d.mts +24 -0
  8. package/dist/pdf-ast/vendor/pdfjs-fonts.mjs +2621 -0
  9. package/dist/safe-bash/chunks/{chunk-FSH7QRIC.js → chunk-Z3HX3ZBA.js} +10 -4
  10. package/dist/safe-bash/command-chunks/{chunk-M2XU2YCK.js → chunk-5VXZSNM2.js} +2 -2
  11. package/dist/safe-bash/command-chunks/{chunk-C4AAJTXF.js → chunk-B2MM5DIT.js} +2804 -556
  12. package/dist/safe-bash/command-chunks/{chunk-NBENXODJ.js → chunk-G3NVK25P.js} +1 -1
  13. package/dist/safe-bash/commands/python/host-capabilities.js +15 -6
  14. package/dist/safe-bash/commands/python/index.browser.js +1 -1
  15. package/dist/safe-bash/core.browser.js +39 -39
  16. package/dist/safe-bash/core.d.ts +1 -1
  17. package/dist/safe-bash/plugins/composition.d.ts +2 -0
  18. package/dist/safe-bash/plugins/composition.js +2 -1
  19. package/dist/safe-bash-command-ffmpeg/index.js +10968 -9719
  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-imagemagick/index.js +2 -2
  27. package/dist/safe-bash-command-pandoc/command.js +3 -3
  28. package/dist/safe-bash-command-pandoc/index.js +3 -3
  29. package/dist/safe-bash-command-pdfimages/index.js +2800 -510
  30. package/dist/safe-bash-command-pdfinfo/index.js +2842 -568
  31. package/dist/safe-bash-command-pdftk/index.js +2800 -510
  32. package/dist/safe-bash-command-pdftoppm/index.js +2847 -637
  33. package/dist/safe-bash-command-pdftotext/index.js +2800 -510
  34. package/dist/safe-bash-command-qpdf/index.js +2800 -510
  35. package/dist/safe-bash-command-sips/index.js +2 -2
  36. package/dist/safe-bash-command-soffice/index.js +1 -1
  37. package/dist/safe-bash-command-ssconvert/index.js +2811 -566
  38. package/dist/safe-bash-command-wkhtmltopdf/index.js +2833 -510
  39. package/dist/safe-bash-mcp/index.d.ts +8 -2
  40. package/dist/safe-bash-mcp/index.js +13 -6
  41. package/package.json +7 -7
  42. package/third-party/pdf-ast/THIRD_PARTY_NOTICES.md +62 -1
@@ -19072,6 +19072,2614 @@ var getFontBasicMetrics = getLookupTableFactory(function(t) {
19072
19072
  xHeight: Math.NaN
19073
19073
  };
19074
19074
  });
19075
+ function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
19076
+ const COMPONENTS = 3;
19077
+ alpha01 = alpha01 !== 1 ? 0 : alpha01;
19078
+ const xRatio = w1 / w2;
19079
+ const yRatio = h1 / h2;
19080
+ let newIndex = 0, oldIndex;
19081
+ const xScaled = new Uint16Array(w2);
19082
+ const w1Scanline = w1 * COMPONENTS;
19083
+ for (let i = 0; i < w2; i++) {
19084
+ xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
19085
+ }
19086
+ for (let i = 0; i < h2; i++) {
19087
+ const py = Math.floor(i * yRatio) * w1Scanline;
19088
+ for (let j = 0; j < w2; j++) {
19089
+ oldIndex = py + xScaled[j];
19090
+ dest[newIndex++] = src[oldIndex++];
19091
+ dest[newIndex++] = src[oldIndex++];
19092
+ dest[newIndex++] = src[oldIndex++];
19093
+ newIndex += alpha01;
19094
+ }
19095
+ }
19096
+ }
19097
+ function isDefaultDecodeHelper(decode, expectedLen) {
19098
+ if (!Array.isArray(decode)) {
19099
+ return true;
19100
+ }
19101
+ const decodeLen = decode.length;
19102
+ if (decodeLen < expectedLen) {
19103
+ warn2("Decode map length is too short.");
19104
+ return true;
19105
+ }
19106
+ if (decodeLen > expectedLen) {
19107
+ info("Truncating too long decode map.");
19108
+ decode.length = expectedLen;
19109
+ }
19110
+ return false;
19111
+ }
19112
+ var ColorSpace = class _ColorSpace {
19113
+ static #rgbBuf = new Uint8ClampedArray(3);
19114
+ constructor(name, numComps) {
19115
+ if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _ColorSpace) {
19116
+ unreachable2("Cannot initialize ColorSpace.");
19117
+ }
19118
+ this.name = name;
19119
+ this.numComps = numComps;
19120
+ }
19121
+ /**
19122
+ * Converts the color value to the RGB color. The color components are
19123
+ * located in the src array starting from the srcOffset. Returns the array
19124
+ * of the rgb components, each value ranging from [0,255].
19125
+ */
19126
+ getRgb(src, srcOffset, output = new Uint8ClampedArray(3)) {
19127
+ this.getRgbItem(src, srcOffset, output, 0);
19128
+ return output;
19129
+ }
19130
+ getRgbHex(src, srcOffset) {
19131
+ const buffer = this.getRgb(src, srcOffset, _ColorSpace.#rgbBuf);
19132
+ return Util.makeHexColor(buffer[0], buffer[1], buffer[2]);
19133
+ }
19134
+ /**
19135
+ * Converts the color value to the RGB color, similar to the getRgb method.
19136
+ * The result placed into the dest array starting from the destOffset.
19137
+ */
19138
+ getRgbItem(src, srcOffset, dest, destOffset) {
19139
+ unreachable2("Should not call ColorSpace.getRgbItem");
19140
+ }
19141
+ /**
19142
+ * Converts the specified number of the color values to the RGB colors.
19143
+ * The colors are located in the src array starting from the srcOffset.
19144
+ * The result is placed into the dest array starting from the destOffset.
19145
+ * The src array items shall be in [0,2^bits) range, the dest array items
19146
+ * will be in [0,255] range. alpha01 indicates how many alpha components
19147
+ * there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
19148
+ * array).
19149
+ */
19150
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
19151
+ unreachable2("Should not call ColorSpace.getRgbBuffer");
19152
+ }
19153
+ /**
19154
+ * Converts `count` unscaled colors to RGB, starting at `destOffset`.
19155
+ * Components use the native color-space ranges expected by `getRgbItem`,
19156
+ * and each output has a `3 + alpha01` byte stride.
19157
+ * Subclasses may override this to batch expensive conversions.
19158
+ */
19159
+ getRgbItems(src, count, dest, destOffset, alpha01) {
19160
+ const { numComps } = this;
19161
+ for (let i = 0, srcOffset = 0; i < count; i++, srcOffset += numComps) {
19162
+ this.getRgbItem(src, srcOffset, dest, destOffset);
19163
+ destOffset += 3 + alpha01;
19164
+ }
19165
+ }
19166
+ /**
19167
+ * Returns true if source data will be equal the result/output data.
19168
+ */
19169
+ isPassthrough(bits) {
19170
+ return false;
19171
+ }
19172
+ /**
19173
+ * Refer to the static `ColorSpace.isDefaultDecode` method below.
19174
+ */
19175
+ isDefaultDecode(decode, bpc) {
19176
+ return _ColorSpace.isDefaultDecode(decode, this.numComps);
19177
+ }
19178
+ /**
19179
+ * Fills in the RGB colors in the destination buffer. alpha01 indicates
19180
+ * how many alpha components there are in the dest array; it will be either
19181
+ * 0 (RGB array) or 1 (RGBA array).
19182
+ */
19183
+ fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {
19184
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19185
+ assert2(
19186
+ dest instanceof Uint8ClampedArray,
19187
+ 'ColorSpace.fillRgb: Unsupported "dest" type.'
19188
+ );
19189
+ }
19190
+ const count = originalWidth * originalHeight;
19191
+ let rgbBuf = null;
19192
+ const numComponentColors = 1 << bpc;
19193
+ const needsResizing = originalHeight !== height || originalWidth !== width;
19194
+ if (this.isPassthrough(bpc)) {
19195
+ rgbBuf = comps;
19196
+ } else if (this.numComps === 1 && count > numComponentColors && this.name !== "DeviceGray" && this.name !== "DeviceRGB") {
19197
+ const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);
19198
+ for (let i = 0; i < numComponentColors; i++) {
19199
+ allColors[i] = i;
19200
+ }
19201
+ const colorMap = new Uint8ClampedArray(numComponentColors * 3);
19202
+ this.getRgbBuffer(
19203
+ allColors,
19204
+ 0,
19205
+ numComponentColors,
19206
+ colorMap,
19207
+ 0,
19208
+ bpc,
19209
+ /* alpha01 = */
19210
+ 0
19211
+ );
19212
+ if (!needsResizing) {
19213
+ let destPos = 0;
19214
+ for (let i = 0; i < count; ++i) {
19215
+ const key = comps[i] * 3;
19216
+ dest[destPos++] = colorMap[key];
19217
+ dest[destPos++] = colorMap[key + 1];
19218
+ dest[destPos++] = colorMap[key + 2];
19219
+ destPos += alpha01;
19220
+ }
19221
+ } else {
19222
+ rgbBuf = new Uint8Array(count * 3);
19223
+ let rgbPos = 0;
19224
+ for (let i = 0; i < count; ++i) {
19225
+ const key = comps[i] * 3;
19226
+ rgbBuf[rgbPos++] = colorMap[key];
19227
+ rgbBuf[rgbPos++] = colorMap[key + 1];
19228
+ rgbBuf[rgbPos++] = colorMap[key + 2];
19229
+ }
19230
+ }
19231
+ } else if (!needsResizing) {
19232
+ this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);
19233
+ } else {
19234
+ rgbBuf = new Uint8ClampedArray(count * 3);
19235
+ this.getRgbBuffer(
19236
+ comps,
19237
+ 0,
19238
+ count,
19239
+ rgbBuf,
19240
+ 0,
19241
+ bpc,
19242
+ /* alpha01 = */
19243
+ 0
19244
+ );
19245
+ }
19246
+ if (rgbBuf) {
19247
+ if (needsResizing) {
19248
+ resizeRgbImage(
19249
+ rgbBuf,
19250
+ dest,
19251
+ originalWidth,
19252
+ originalHeight,
19253
+ width,
19254
+ height,
19255
+ alpha01
19256
+ );
19257
+ } else {
19258
+ let destPos = 0, rgbPos = 0;
19259
+ for (let i = 0, ii = width * actualHeight; i < ii; i++) {
19260
+ dest[destPos++] = rgbBuf[rgbPos++];
19261
+ dest[destPos++] = rgbBuf[rgbPos++];
19262
+ dest[destPos++] = rgbBuf[rgbPos++];
19263
+ destPos += alpha01;
19264
+ }
19265
+ }
19266
+ }
19267
+ }
19268
+ /**
19269
+ * True if the colorspace has components in the default range of [0, 1].
19270
+ * This should be true for all colorspaces except for lab color spaces
19271
+ * which are [0,100], [-128, 127], [-128, 127].
19272
+ */
19273
+ get usesZeroToOneRange() {
19274
+ return shadow2(this, "usesZeroToOneRange", true);
19275
+ }
19276
+ /**
19277
+ * Checks if a decode map matches the default decode map for a color space.
19278
+ * This handles the general decode maps where there are two values per
19279
+ * component, e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
19280
+ * This does not handle Lab, Indexed, or Pattern decode maps since they are
19281
+ * slightly different.
19282
+ * @param {Array} decode - Decode map (usually from an image).
19283
+ * @param {number} numComps - Number of components the color space has.
19284
+ */
19285
+ static isDefaultDecode(decode, numComps) {
19286
+ if (isDefaultDecodeHelper(decode, numComps * 2)) {
19287
+ return true;
19288
+ }
19289
+ for (let i = 0, ii = decode.length; i < ii; i += 2) {
19290
+ if (decode[i] !== 0 || decode[i + 1] !== 1) {
19291
+ return false;
19292
+ }
19293
+ }
19294
+ return true;
19295
+ }
19296
+ };
19297
+ var DeviceCmykCS = class extends ColorSpace {
19298
+ constructor() {
19299
+ super("DeviceCMYK", 4);
19300
+ }
19301
+ // The coefficients below was found using numerical analysis: the method of
19302
+ // steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
19303
+ // where color_value is the tabular value from the table of sampled RGB colors
19304
+ // from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
19305
+ // CMYK color conversion using the estimation below:
19306
+ // f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
19307
+ #toRgb(src, srcOffset, srcScale, dest, destOffset) {
19308
+ const c = src[srcOffset] * srcScale;
19309
+ const m = src[srcOffset + 1] * srcScale;
19310
+ const y = src[srcOffset + 2] * srcScale;
19311
+ const k = src[srcOffset + 3] * srcScale;
19312
+ 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);
19313
+ 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);
19314
+ 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);
19315
+ }
19316
+ getRgbItem(src, srcOffset, dest, destOffset) {
19317
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19318
+ assert2(
19319
+ dest instanceof Uint8ClampedArray,
19320
+ 'DeviceCmykCS.getRgbItem: Unsupported "dest" type.'
19321
+ );
19322
+ }
19323
+ this.#toRgb(src, srcOffset, 1, dest, destOffset);
19324
+ }
19325
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
19326
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19327
+ assert2(
19328
+ dest instanceof Uint8ClampedArray,
19329
+ 'DeviceCmykCS.getRgbBuffer: Unsupported "dest" type.'
19330
+ );
19331
+ }
19332
+ const scale = 1 / ((1 << bits) - 1);
19333
+ for (let i = 0; i < count; i++) {
19334
+ this.#toRgb(src, srcOffset, scale, dest, destOffset);
19335
+ srcOffset += 4;
19336
+ destOffset += 3 + alpha01;
19337
+ }
19338
+ }
19339
+ };
19340
+ var CalGrayCS = class extends ColorSpace {
19341
+ constructor(whitePoint, blackPoint, gamma) {
19342
+ super("CalGray", 1);
19343
+ if (!whitePoint) {
19344
+ throw new FormatError(
19345
+ "WhitePoint missing - required for color space CalGray"
19346
+ );
19347
+ }
19348
+ [this.XW, this.YW, this.ZW] = whitePoint;
19349
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
19350
+ this.G = gamma || 1;
19351
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
19352
+ throw new FormatError(
19353
+ `Invalid WhitePoint components for ${this.name}, no fallback available`
19354
+ );
19355
+ }
19356
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
19357
+ info(`Invalid BlackPoint for ${this.name}, falling back to default.`);
19358
+ this.XB = this.YB = this.ZB = 0;
19359
+ }
19360
+ if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
19361
+ warn2(
19362
+ `${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ZB: ${this.ZB}, only default values are supported.`
19363
+ );
19364
+ }
19365
+ if (this.G < 1) {
19366
+ info(
19367
+ `Invalid Gamma: ${this.G} for ${this.name}, falling back to default.`
19368
+ );
19369
+ this.G = 1;
19370
+ }
19371
+ }
19372
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
19373
+ const A = src[srcOffset] * scale;
19374
+ const AG = A ** this.G;
19375
+ const L = this.YW * AG;
19376
+ const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0);
19377
+ dest[destOffset] = val;
19378
+ dest[destOffset + 1] = val;
19379
+ dest[destOffset + 2] = val;
19380
+ }
19381
+ getRgbItem(src, srcOffset, dest, destOffset) {
19382
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19383
+ assert2(
19384
+ dest instanceof Uint8ClampedArray,
19385
+ 'CalGrayCS.getRgbItem: Unsupported "dest" type.'
19386
+ );
19387
+ }
19388
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
19389
+ }
19390
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
19391
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19392
+ assert2(
19393
+ dest instanceof Uint8ClampedArray,
19394
+ 'CalGrayCS.getRgbBuffer: Unsupported "dest" type.'
19395
+ );
19396
+ }
19397
+ const scale = 1 / ((1 << bits) - 1);
19398
+ for (let i = 0; i < count; ++i) {
19399
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
19400
+ srcOffset += 1;
19401
+ destOffset += 3 + alpha01;
19402
+ }
19403
+ }
19404
+ };
19405
+ var CalRGBCS = class _CalRGBCS extends ColorSpace {
19406
+ // See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these
19407
+ // matrices.
19408
+ // prettier-ignore
19409
+ static #BRADFORD_SCALE_MATRIX = new Float32Array([
19410
+ 0.8951,
19411
+ 0.2664,
19412
+ -0.1614,
19413
+ -0.7502,
19414
+ 1.7135,
19415
+ 0.0367,
19416
+ 0.0389,
19417
+ -0.0685,
19418
+ 1.0296
19419
+ ]);
19420
+ // prettier-ignore
19421
+ static #BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([
19422
+ 0.9869929,
19423
+ -0.1470543,
19424
+ 0.1599627,
19425
+ 0.4323053,
19426
+ 0.5183603,
19427
+ 0.0492912,
19428
+ -85287e-7,
19429
+ 0.0400428,
19430
+ 0.9684867
19431
+ ]);
19432
+ // See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html.
19433
+ // prettier-ignore
19434
+ static #SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([
19435
+ 3.2404542,
19436
+ -1.5371385,
19437
+ -0.4985314,
19438
+ -0.969266,
19439
+ 1.8760108,
19440
+ 0.041556,
19441
+ 0.0556434,
19442
+ -0.2040259,
19443
+ 1.0572252
19444
+ ]);
19445
+ static #FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);
19446
+ static #tempNormalizeMatrix = new Float32Array(3);
19447
+ static #tempConvertMatrix1 = new Float32Array(3);
19448
+ static #tempConvertMatrix2 = new Float32Array(3);
19449
+ static #DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8;
19450
+ constructor(whitePoint, blackPoint, gamma, matrix) {
19451
+ super("CalRGB", 3);
19452
+ if (!whitePoint) {
19453
+ throw new FormatError(
19454
+ "WhitePoint missing - required for color space CalRGB"
19455
+ );
19456
+ }
19457
+ const [XW, YW, ZW] = this.whitePoint = whitePoint;
19458
+ const [XB, YB, ZB] = this.blackPoint = blackPoint || new Float32Array(3);
19459
+ [this.GR, this.GG, this.GB] = gamma || new Float32Array([1, 1, 1]);
19460
+ [
19461
+ this.MXA,
19462
+ this.MYA,
19463
+ this.MZA,
19464
+ this.MXB,
19465
+ this.MYB,
19466
+ this.MZB,
19467
+ this.MXC,
19468
+ this.MYC,
19469
+ this.MZC
19470
+ ] = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
19471
+ if (XW < 0 || ZW < 0 || YW !== 1) {
19472
+ throw new FormatError(
19473
+ `Invalid WhitePoint components for ${this.name}, no fallback available`
19474
+ );
19475
+ }
19476
+ if (XB < 0 || YB < 0 || ZB < 0) {
19477
+ info(
19478
+ `Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], falling back to default.`
19479
+ );
19480
+ this.blackPoint = new Float32Array(3);
19481
+ }
19482
+ if (this.GR < 0 || this.GG < 0 || this.GB < 0) {
19483
+ info(
19484
+ `Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ${this.name}, falling back to default.`
19485
+ );
19486
+ this.GR = this.GG = this.GB = 1;
19487
+ }
19488
+ }
19489
+ #matrixProduct(a, b, result) {
19490
+ result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
19491
+ result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
19492
+ result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
19493
+ }
19494
+ #toFlat(sourceWhitePoint, LMS, result) {
19495
+ result[0] = LMS[0] * 1 / sourceWhitePoint[0];
19496
+ result[1] = LMS[1] * 1 / sourceWhitePoint[1];
19497
+ result[2] = LMS[2] * 1 / sourceWhitePoint[2];
19498
+ }
19499
+ #toD65(sourceWhitePoint, LMS, result) {
19500
+ const D65X = 0.95047;
19501
+ const D65Y = 1;
19502
+ const D65Z = 1.08883;
19503
+ result[0] = LMS[0] * D65X / sourceWhitePoint[0];
19504
+ result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
19505
+ result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
19506
+ }
19507
+ #sRGBTransferFunction(color) {
19508
+ if (color <= 31308e-7) {
19509
+ return MathClamp(12.92 * color, 0, 1);
19510
+ }
19511
+ return color >= 0.99554525 ? 1 : MathClamp((1 + 0.055) * color ** (1 / 2.4) - 0.055, 0, 1);
19512
+ }
19513
+ #decodeL(L) {
19514
+ if (L < 0) {
19515
+ return -this.#decodeL(-L);
19516
+ }
19517
+ return L > 8 ? ((L + 16) / 116) ** 3 : L * _CalRGBCS.#DECODE_L_CONSTANT;
19518
+ }
19519
+ #compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
19520
+ if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {
19521
+ result[0] = XYZ_Flat[0];
19522
+ result[1] = XYZ_Flat[1];
19523
+ result[2] = XYZ_Flat[2];
19524
+ return;
19525
+ }
19526
+ const zeroDecodeL = this.#decodeL(0);
19527
+ const X_DST = zeroDecodeL;
19528
+ const X_SRC = this.#decodeL(sourceBlackPoint[0]);
19529
+ const Y_DST = zeroDecodeL;
19530
+ const Y_SRC = this.#decodeL(sourceBlackPoint[1]);
19531
+ const Z_DST = zeroDecodeL;
19532
+ const Z_SRC = this.#decodeL(sourceBlackPoint[2]);
19533
+ const X_Scale = (1 - X_DST) / (1 - X_SRC);
19534
+ const X_Offset = 1 - X_Scale;
19535
+ const Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
19536
+ const Y_Offset = 1 - Y_Scale;
19537
+ const Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
19538
+ const Z_Offset = 1 - Z_Scale;
19539
+ result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
19540
+ result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
19541
+ result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
19542
+ }
19543
+ #normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
19544
+ if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
19545
+ result[0] = XYZ_In[0];
19546
+ result[1] = XYZ_In[1];
19547
+ result[2] = XYZ_In[2];
19548
+ return;
19549
+ }
19550
+ const LMS = result;
19551
+ this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
19552
+ const LMS_Flat = _CalRGBCS.#tempNormalizeMatrix;
19553
+ this.#toFlat(sourceWhitePoint, LMS, LMS_Flat);
19554
+ this.#matrixProduct(
19555
+ _CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
19556
+ LMS_Flat,
19557
+ result
19558
+ );
19559
+ }
19560
+ #normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
19561
+ const LMS = result;
19562
+ this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
19563
+ const LMS_D65 = _CalRGBCS.#tempNormalizeMatrix;
19564
+ this.#toD65(sourceWhitePoint, LMS, LMS_D65);
19565
+ this.#matrixProduct(
19566
+ _CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
19567
+ LMS_D65,
19568
+ result
19569
+ );
19570
+ }
19571
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
19572
+ const A = MathClamp(src[srcOffset] * scale, 0, 1);
19573
+ const B = MathClamp(src[srcOffset + 1] * scale, 0, 1);
19574
+ const C = MathClamp(src[srcOffset + 2] * scale, 0, 1);
19575
+ const AGR = A === 1 ? 1 : A ** this.GR;
19576
+ const BGG = B === 1 ? 1 : B ** this.GG;
19577
+ const CGB = C === 1 ? 1 : C ** this.GB;
19578
+ const X = this.MXA * AGR + this.MXB * BGG + this.MXC * CGB;
19579
+ const Y = this.MYA * AGR + this.MYB * BGG + this.MYC * CGB;
19580
+ const Z = this.MZA * AGR + this.MZB * BGG + this.MZC * CGB;
19581
+ const XYZ = _CalRGBCS.#tempConvertMatrix1;
19582
+ XYZ[0] = X;
19583
+ XYZ[1] = Y;
19584
+ XYZ[2] = Z;
19585
+ const XYZ_Flat = _CalRGBCS.#tempConvertMatrix2;
19586
+ this.#normalizeWhitePointToFlat(this.whitePoint, XYZ, XYZ_Flat);
19587
+ const XYZ_Black = _CalRGBCS.#tempConvertMatrix1;
19588
+ this.#compensateBlackPoint(this.blackPoint, XYZ_Flat, XYZ_Black);
19589
+ const XYZ_D65 = _CalRGBCS.#tempConvertMatrix2;
19590
+ this.#normalizeWhitePointToD65(
19591
+ _CalRGBCS.#FLAT_WHITEPOINT_MATRIX,
19592
+ XYZ_Black,
19593
+ XYZ_D65
19594
+ );
19595
+ const SRGB = _CalRGBCS.#tempConvertMatrix1;
19596
+ this.#matrixProduct(_CalRGBCS.#SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
19597
+ dest[destOffset] = this.#sRGBTransferFunction(SRGB[0]) * 255;
19598
+ dest[destOffset + 1] = this.#sRGBTransferFunction(SRGB[1]) * 255;
19599
+ dest[destOffset + 2] = this.#sRGBTransferFunction(SRGB[2]) * 255;
19600
+ }
19601
+ getRgbItem(src, srcOffset, dest, destOffset) {
19602
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19603
+ assert2(
19604
+ dest instanceof Uint8ClampedArray,
19605
+ 'CalRGBCS.getRgbItem: Unsupported "dest" type.'
19606
+ );
19607
+ }
19608
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
19609
+ }
19610
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
19611
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19612
+ assert2(
19613
+ dest instanceof Uint8ClampedArray,
19614
+ 'CalRGBCS.getRgbBuffer: Unsupported "dest" type.'
19615
+ );
19616
+ }
19617
+ const scale = 1 / ((1 << bits) - 1);
19618
+ for (let i = 0; i < count; ++i) {
19619
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
19620
+ srcOffset += 3;
19621
+ destOffset += 3 + alpha01;
19622
+ }
19623
+ }
19624
+ };
19625
+ var LabCS = class extends ColorSpace {
19626
+ constructor(whitePoint, blackPoint, range) {
19627
+ super("Lab", 3);
19628
+ if (!whitePoint) {
19629
+ throw new FormatError(
19630
+ "WhitePoint missing - required for color space Lab"
19631
+ );
19632
+ }
19633
+ [this.XW, this.YW, this.ZW] = whitePoint;
19634
+ [this.amin, this.amax, this.bmin, this.bmax] = range || [
19635
+ -100,
19636
+ 100,
19637
+ -100,
19638
+ 100
19639
+ ];
19640
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
19641
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
19642
+ throw new FormatError(
19643
+ "Invalid WhitePoint components, no fallback available"
19644
+ );
19645
+ }
19646
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
19647
+ info("Invalid BlackPoint, falling back to default");
19648
+ this.XB = this.YB = this.ZB = 0;
19649
+ }
19650
+ if (this.amin > this.amax || this.bmin > this.bmax) {
19651
+ info("Invalid Range, falling back to defaults");
19652
+ this.amin = -100;
19653
+ this.amax = 100;
19654
+ this.bmin = -100;
19655
+ this.bmax = 100;
19656
+ }
19657
+ }
19658
+ // Function g(x) from spec
19659
+ #fn_g(x) {
19660
+ return x >= 6 / 29 ? x ** 3 : 108 / 841 * (x - 4 / 29);
19661
+ }
19662
+ #decode(value, high1, low2, high2) {
19663
+ return low2 + value * (high2 - low2) / high1;
19664
+ }
19665
+ // If decoding is needed maxVal should be 2^bits per component - 1.
19666
+ #toRgb(src, srcOffset, maxVal, dest, destOffset) {
19667
+ let Ls = src[srcOffset];
19668
+ let as = src[srcOffset + 1];
19669
+ let bs = src[srcOffset + 2];
19670
+ if (maxVal !== false) {
19671
+ Ls = this.#decode(Ls, maxVal, 0, 100);
19672
+ as = this.#decode(as, maxVal, this.amin, this.amax);
19673
+ bs = this.#decode(bs, maxVal, this.bmin, this.bmax);
19674
+ }
19675
+ if (as > this.amax) {
19676
+ as = this.amax;
19677
+ } else if (as < this.amin) {
19678
+ as = this.amin;
19679
+ }
19680
+ if (bs > this.bmax) {
19681
+ bs = this.bmax;
19682
+ } else if (bs < this.bmin) {
19683
+ bs = this.bmin;
19684
+ }
19685
+ const M = (Ls + 16) / 116;
19686
+ const L = M + as / 500;
19687
+ const N = M - bs / 200;
19688
+ const X = this.XW * this.#fn_g(L);
19689
+ const Y = this.YW * this.#fn_g(M);
19690
+ const Z = this.ZW * this.#fn_g(N);
19691
+ let r, g, b;
19692
+ if (this.ZW < 1) {
19693
+ r = X * 3.1339 + Y * -1.617 + Z * -0.4906;
19694
+ g = X * -0.9785 + Y * 1.916 + Z * 0.0333;
19695
+ b = X * 0.072 + Y * -0.229 + Z * 1.4057;
19696
+ } else {
19697
+ r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
19698
+ g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
19699
+ b = X * 0.0557 + Y * -0.204 + Z * 1.057;
19700
+ }
19701
+ dest[destOffset] = Math.sqrt(r) * 255;
19702
+ dest[destOffset + 1] = Math.sqrt(g) * 255;
19703
+ dest[destOffset + 2] = Math.sqrt(b) * 255;
19704
+ }
19705
+ getRgbItem(src, srcOffset, dest, destOffset) {
19706
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19707
+ assert2(
19708
+ dest instanceof Uint8ClampedArray,
19709
+ 'LabCS.getRgbItem: Unsupported "dest" type.'
19710
+ );
19711
+ }
19712
+ this.#toRgb(src, srcOffset, false, dest, destOffset);
19713
+ }
19714
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
19715
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19716
+ assert2(
19717
+ dest instanceof Uint8ClampedArray,
19718
+ 'LabCS.getRgbBuffer: Unsupported "dest" type.'
19719
+ );
19720
+ }
19721
+ const maxVal = (1 << bits) - 1;
19722
+ for (let i = 0; i < count; i++) {
19723
+ this.#toRgb(src, srcOffset, maxVal, dest, destOffset);
19724
+ srcOffset += 3;
19725
+ destOffset += 3 + alpha01;
19726
+ }
19727
+ }
19728
+ isDefaultDecode(decode, bpc) {
19729
+ return true;
19730
+ }
19731
+ get usesZeroToOneRange() {
19732
+ return shadow2(this, "usesZeroToOneRange", false);
19733
+ }
19734
+ };
19735
+ var TOKEN = {
19736
+ // Structural tokens — not keyword operators
19737
+ number: 0,
19738
+ lbrace: 1,
19739
+ rbrace: 2,
19740
+ // Boolean literals
19741
+ true: 3,
19742
+ false: 4,
19743
+ // Arithmetic binary operators
19744
+ add: 5,
19745
+ sub: 6,
19746
+ mul: 7,
19747
+ div: 8,
19748
+ idiv: 9,
19749
+ mod: 10,
19750
+ exp: 11,
19751
+ // Comparison binary operators
19752
+ eq: 12,
19753
+ ne: 13,
19754
+ gt: 14,
19755
+ ge: 15,
19756
+ lt: 16,
19757
+ le: 17,
19758
+ // Bitwise / boolean binary operators
19759
+ and: 18,
19760
+ or: 19,
19761
+ xor: 20,
19762
+ bitshift: 21,
19763
+ // Unary arithmetic operators
19764
+ abs: 22,
19765
+ neg: 23,
19766
+ ceiling: 24,
19767
+ floor: 25,
19768
+ round: 26,
19769
+ truncate: 27,
19770
+ // Unary boolean / bitwise operator
19771
+ not: 28,
19772
+ // Mathematical functions — unary
19773
+ sqrt: 29,
19774
+ sin: 30,
19775
+ cos: 31,
19776
+ ln: 32,
19777
+ log: 33,
19778
+ // Mathematical function — binary
19779
+ atan: 34,
19780
+ // Type conversion operators
19781
+ cvi: 35,
19782
+ cvr: 36,
19783
+ // Stack operators
19784
+ dup: 37,
19785
+ exch: 38,
19786
+ pop: 39,
19787
+ copy: 40,
19788
+ index: 41,
19789
+ roll: 42,
19790
+ // Control flow
19791
+ if: 43,
19792
+ ifelse: 44,
19793
+ // End of input
19794
+ eof: 45,
19795
+ // Synthetic: produced by the optimizer, never emitted by the lexer.
19796
+ min: 46,
19797
+ max: 47
19798
+ };
19799
+ var Token = class {
19800
+ constructor(id, value = null) {
19801
+ this.id = id;
19802
+ this.value = value;
19803
+ }
19804
+ };
19805
+ var Lexer = class _Lexer {
19806
+ // Singletons for every non-number token, built lazily on first construction.
19807
+ // Keyword operator tokens carry their name as `value`; structural tokens
19808
+ // (lbrace, rbrace, eof) carry null.
19809
+ static #singletons = null;
19810
+ static #operatorSingletons = null;
19811
+ static #initSingletons() {
19812
+ const singletons = /* @__PURE__ */ Object.create(null);
19813
+ const operatorSingletons = /* @__PURE__ */ Object.create(null);
19814
+ for (const [name, id] of Object.entries(TOKEN)) {
19815
+ if (name === "number") {
19816
+ continue;
19817
+ }
19818
+ const isOperator = id >= TOKEN.true && id <= TOKEN.ifelse;
19819
+ const token = new Token(id, isOperator ? name : null);
19820
+ singletons[name] = token;
19821
+ if (isOperator) {
19822
+ operatorSingletons[name] = token;
19823
+ }
19824
+ }
19825
+ this.#singletons = singletons;
19826
+ this.#operatorSingletons = operatorSingletons;
19827
+ }
19828
+ constructor(data) {
19829
+ if (!_Lexer.#singletons) {
19830
+ _Lexer.#initSingletons();
19831
+ }
19832
+ this.data = data;
19833
+ this.pos = 0;
19834
+ this.len = data.length;
19835
+ this._numberPattern = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/iy;
19836
+ this._identifierPattern = /[a-z]+/y;
19837
+ }
19838
+ // Skip a % comment, advancing past the next \n or \r (or to EOF).
19839
+ _skipComment() {
19840
+ const lf = this.data.indexOf("\n", this.pos);
19841
+ const cr = this.data.indexOf("\r", this.pos);
19842
+ const eol = Math.min(lf < 0 ? this.len : lf, cr < 0 ? this.len : cr);
19843
+ this.pos = Math.min(eol + 1, this.len);
19844
+ }
19845
+ _getNumber() {
19846
+ this._numberPattern.lastIndex = this.pos;
19847
+ const match = this._numberPattern.exec(this.data);
19848
+ if (!match) {
19849
+ return new Token(TOKEN.number, 0);
19850
+ }
19851
+ const number = parseFloat(match[0]);
19852
+ if (!Number.isFinite(number)) {
19853
+ return new Token(TOKEN.number, 0);
19854
+ }
19855
+ this.pos = this._numberPattern.lastIndex;
19856
+ return new Token(TOKEN.number, number);
19857
+ }
19858
+ _getOperator() {
19859
+ this._identifierPattern.lastIndex = this.pos;
19860
+ const match = this._identifierPattern.exec(this.data);
19861
+ if (!match) {
19862
+ return new Token(TOKEN.number, 0);
19863
+ }
19864
+ this.pos = this._identifierPattern.lastIndex;
19865
+ const op = match[0];
19866
+ const token = _Lexer.#operatorSingletons[op];
19867
+ return token ?? new Token(TOKEN.number, 0);
19868
+ }
19869
+ // Return the next token, or Lexer.#singletons.eof at end of input.
19870
+ next() {
19871
+ while (this.pos < this.len) {
19872
+ const ch3 = this.data.charCodeAt(this.pos++);
19873
+ switch (ch3) {
19874
+ // PostScript white-space characters (PDF32000 §7.2.2)
19875
+ case 0:
19876
+ case 9:
19877
+ case 10:
19878
+ case 12:
19879
+ case 13:
19880
+ case 32:
19881
+ break;
19882
+ case 37:
19883
+ this._skipComment();
19884
+ break;
19885
+ case 123:
19886
+ return _Lexer.#singletons.lbrace;
19887
+ case 125:
19888
+ return _Lexer.#singletons.rbrace;
19889
+ case 43:
19890
+ case 45:
19891
+ this.pos--;
19892
+ return this._getNumber();
19893
+ case 46:
19894
+ this.pos--;
19895
+ return this._getNumber();
19896
+ default:
19897
+ if (ch3 >= 48 && ch3 <= 57) {
19898
+ this.pos--;
19899
+ return this._getNumber();
19900
+ }
19901
+ if (ch3 >= 97 && ch3 <= 122) {
19902
+ this.pos--;
19903
+ return this._getOperator();
19904
+ }
19905
+ return new Token(TOKEN.number, 0);
19906
+ }
19907
+ }
19908
+ return _Lexer.#singletons.eof;
19909
+ }
19910
+ };
19911
+ var PS_VALUE_TYPE = {
19912
+ numeric: 0,
19913
+ // known to be a number (f64 in Wasm)
19914
+ boolean: 1,
19915
+ // known to be a boolean (0.0 = false, 1.0 = true in f64)
19916
+ unknown: 2
19917
+ // indeterminate at compile time
19918
+ };
19919
+ var PS_NODE = {
19920
+ // Parser AST node types (produced by Parser / parsePostScriptFunction)
19921
+ program: 0,
19922
+ block: 1,
19923
+ number: 2,
19924
+ operator: 3,
19925
+ if: 4,
19926
+ ifelse: 5,
19927
+ // Tree AST node types (produced by PSStackToTree)
19928
+ arg: 6,
19929
+ const: 7,
19930
+ unary: 8,
19931
+ binary: 9,
19932
+ ternary: 10
19933
+ };
19934
+ var PsNode = class {
19935
+ constructor(type) {
19936
+ this.type = type;
19937
+ }
19938
+ };
19939
+ var PsProgram = class extends PsNode {
19940
+ constructor(body) {
19941
+ super(PS_NODE.program);
19942
+ this.body = body;
19943
+ }
19944
+ };
19945
+ var PsBlock = class extends PsNode {
19946
+ constructor(instructions) {
19947
+ super(PS_NODE.block);
19948
+ this.instructions = instructions;
19949
+ }
19950
+ };
19951
+ var PsNumber = class extends PsNode {
19952
+ /** @param {number} value */
19953
+ constructor(value) {
19954
+ super(PS_NODE.number);
19955
+ this.value = value;
19956
+ }
19957
+ };
19958
+ var PsOperator = class extends PsNode {
19959
+ /** @param {number} op — one of the TOKEN.* constants from lexer.js */
19960
+ constructor(op) {
19961
+ super(PS_NODE.operator);
19962
+ this.op = op;
19963
+ }
19964
+ };
19965
+ var PsIf = class extends PsNode {
19966
+ /** @param {PsBlock} then */
19967
+ constructor(then) {
19968
+ super(PS_NODE.if);
19969
+ this.then = then;
19970
+ }
19971
+ };
19972
+ var PsIfElse = class extends PsNode {
19973
+ /**
19974
+ * @param {PsBlock} then
19975
+ * @param {PsBlock} otherwise
19976
+ */
19977
+ constructor(then, otherwise) {
19978
+ super(PS_NODE.ifelse);
19979
+ this.then = then;
19980
+ this.otherwise = otherwise;
19981
+ }
19982
+ };
19983
+ var PsArgNode = class extends PsNode {
19984
+ /** @param {number} index */
19985
+ constructor(index) {
19986
+ super(PS_NODE.arg);
19987
+ this.index = index;
19988
+ this.valueType = PS_VALUE_TYPE.numeric;
19989
+ }
19990
+ };
19991
+ var PsConstNode = class extends PsNode {
19992
+ /** @param {number|boolean} value */
19993
+ constructor(value) {
19994
+ super(PS_NODE.const);
19995
+ this.value = value;
19996
+ this.valueType = typeof value === "boolean" ? PS_VALUE_TYPE.boolean : PS_VALUE_TYPE.numeric;
19997
+ }
19998
+ };
19999
+ var PsUnaryNode = class extends PsNode {
20000
+ /**
20001
+ * @param {number} op — TOKEN.* constant
20002
+ * @param {PsNode} operand
20003
+ * @param {number} [valueType]
20004
+ */
20005
+ constructor(op, operand, valueType = PS_VALUE_TYPE.unknown) {
20006
+ super(PS_NODE.unary);
20007
+ this.op = op;
20008
+ this.operand = operand;
20009
+ this.valueType = valueType;
20010
+ }
20011
+ };
20012
+ var PsBinaryNode = class extends PsNode {
20013
+ /**
20014
+ * @param {number} op — TOKEN.* constant
20015
+ * @param {PsNode} first — was on top of stack
20016
+ * @param {PsNode} second — was below top
20017
+ * @param {number} [valueType]
20018
+ */
20019
+ constructor(op, first, second, valueType = PS_VALUE_TYPE.unknown) {
20020
+ super(PS_NODE.binary);
20021
+ this.op = op;
20022
+ this.first = first;
20023
+ this.second = second;
20024
+ this.valueType = valueType;
20025
+ }
20026
+ };
20027
+ var PsTernaryNode = class extends PsNode {
20028
+ /**
20029
+ * @param {PsNode} cond
20030
+ * @param {PsNode} then
20031
+ * @param {PsNode} otherwise
20032
+ * @param {number} [valueType]
20033
+ */
20034
+ constructor(cond, then, otherwise, valueType = PS_VALUE_TYPE.unknown) {
20035
+ super(PS_NODE.ternary);
20036
+ this.cond = cond;
20037
+ this.then = then;
20038
+ this.otherwise = otherwise;
20039
+ this.valueType = valueType;
20040
+ }
20041
+ };
20042
+ var Parser = class _Parser {
20043
+ constructor(lexer) {
20044
+ this.lexer = lexer;
20045
+ this._token = null;
20046
+ }
20047
+ static _isRegularOperator(id) {
20048
+ return id >= TOKEN.true && id < TOKEN.if;
20049
+ }
20050
+ // Fetch the next token from the lexer.
20051
+ _advance() {
20052
+ this._token = this.lexer.next();
20053
+ }
20054
+ // Assert that the current token has the given id, consume it, and return it.
20055
+ _expect(id) {
20056
+ if (this._token.id !== id) {
20057
+ throw new FormatError(
20058
+ `PostScript function: expected token id ${id}, got ${this._token.id}.`
20059
+ );
20060
+ }
20061
+ const tok = this._token;
20062
+ this._advance();
20063
+ return tok;
20064
+ }
20065
+ /**
20066
+ * Parse the full Type 4 function body.
20067
+ *
20068
+ * Grammar (simplified):
20069
+ * program ::= '{' block '}'
20070
+ * block ::= instruction*
20071
+ * instruction ::= number
20072
+ * | operator (any PS_OPERATOR except if / ifelse)
20073
+ * | '{' block '}' 'if'
20074
+ * | '{' block '}' '{' block '}' 'ifelse'
20075
+ * @returns {PsProgram}
20076
+ */
20077
+ parse() {
20078
+ this._advance();
20079
+ this._expect(TOKEN.lbrace);
20080
+ const block = this._parseBlock();
20081
+ this._expect(TOKEN.rbrace);
20082
+ if (this._token.id !== TOKEN.eof) {
20083
+ warn2("PostScript function: unexpected content after closing brace.");
20084
+ }
20085
+ return new PsProgram(block);
20086
+ }
20087
+ _parseBlock() {
20088
+ const instructions = [];
20089
+ while (true) {
20090
+ const tok = this._token;
20091
+ switch (tok.id) {
20092
+ case TOKEN.number:
20093
+ instructions.push(new PsNumber(tok.value));
20094
+ this._advance();
20095
+ break;
20096
+ case TOKEN.lbrace: {
20097
+ this._advance();
20098
+ const thenBlock = this._parseBlock();
20099
+ this._expect(TOKEN.rbrace);
20100
+ if (this._token.id === TOKEN.if) {
20101
+ this._advance();
20102
+ instructions.push(new PsIf(thenBlock));
20103
+ } else if (this._token.id === TOKEN.lbrace) {
20104
+ this._advance();
20105
+ const elseBlock = this._parseBlock();
20106
+ this._expect(TOKEN.rbrace);
20107
+ this._expect(TOKEN.ifelse);
20108
+ instructions.push(new PsIfElse(thenBlock, elseBlock));
20109
+ } else {
20110
+ throw new FormatError(
20111
+ "PostScript function: a procedure block must be followed by 'if' or '{\u2026} ifelse'."
20112
+ );
20113
+ }
20114
+ break;
20115
+ }
20116
+ case TOKEN.rbrace:
20117
+ case TOKEN.eof:
20118
+ return new PsBlock(instructions);
20119
+ case TOKEN.if:
20120
+ case TOKEN.ifelse:
20121
+ throw new FormatError(
20122
+ `PostScript function: unexpected '${tok.value}' operator.`
20123
+ );
20124
+ default:
20125
+ if (_Parser._isRegularOperator(tok.id)) {
20126
+ instructions.push(new PsOperator(tok.id));
20127
+ this._advance();
20128
+ break;
20129
+ }
20130
+ throw new FormatError(
20131
+ `PostScript function: unexpected token id ${tok.id}.`
20132
+ );
20133
+ }
20134
+ }
20135
+ }
20136
+ };
20137
+ function parsePostScriptFunction(source) {
20138
+ return new Parser(new Lexer(source)).parse();
20139
+ }
20140
+ function _nodesEqual(a, b) {
20141
+ if (a === b) {
20142
+ return true;
20143
+ }
20144
+ if (a.type !== b.type) {
20145
+ return false;
20146
+ }
20147
+ switch (a.type) {
20148
+ case PS_NODE.arg:
20149
+ return a.index === b.index;
20150
+ case PS_NODE.const:
20151
+ return a.value === b.value;
20152
+ case PS_NODE.unary:
20153
+ return a.op === b.op && _nodesEqual(a.operand, b.operand);
20154
+ case PS_NODE.binary:
20155
+ return a.op === b.op && _nodesEqual(a.first, b.first) && _nodesEqual(a.second, b.second);
20156
+ case PS_NODE.ternary:
20157
+ return _nodesEqual(a.cond, b.cond) && _nodesEqual(a.then, b.then) && _nodesEqual(a.otherwise, b.otherwise);
20158
+ default:
20159
+ return false;
20160
+ }
20161
+ }
20162
+ function _evalBinaryConst(op, a, b) {
20163
+ switch (op) {
20164
+ case TOKEN.add:
20165
+ return a + b;
20166
+ case TOKEN.sub:
20167
+ return a - b;
20168
+ case TOKEN.mul:
20169
+ return a * b;
20170
+ case TOKEN.div:
20171
+ return b !== 0 ? a / b : 0;
20172
+ // div by zero → 0
20173
+ case TOKEN.idiv:
20174
+ return b !== 0 ? Math.trunc(a / b) : 0;
20175
+ // div by zero → 0
20176
+ case TOKEN.mod:
20177
+ return b !== 0 ? a - Math.trunc(a / b) * b : 0;
20178
+ // div by zero → 0
20179
+ case TOKEN.exp: {
20180
+ const r = a ** b;
20181
+ return Number.isFinite(r) ? r : void 0;
20182
+ }
20183
+ case TOKEN.atan: {
20184
+ let deg = Math.atan2(a, b) * (180 / Math.PI);
20185
+ if (deg < 0) {
20186
+ deg += 360;
20187
+ }
20188
+ return deg;
20189
+ }
20190
+ case TOKEN.eq:
20191
+ return a === b;
20192
+ case TOKEN.ne:
20193
+ return a !== b;
20194
+ case TOKEN.gt:
20195
+ return a > b;
20196
+ case TOKEN.ge:
20197
+ return a >= b;
20198
+ case TOKEN.lt:
20199
+ return a < b;
20200
+ case TOKEN.le:
20201
+ return a <= b;
20202
+ case TOKEN.and:
20203
+ return typeof a === "boolean" ? a && b : a & b | 0;
20204
+ case TOKEN.or:
20205
+ return typeof a === "boolean" ? a || b : a | b | 0;
20206
+ case TOKEN.xor:
20207
+ return typeof a === "boolean" ? a !== b : a ^ b | 0;
20208
+ case TOKEN.bitshift:
20209
+ return b >= 0 ? a << b | 0 : a >> -b | 0;
20210
+ case TOKEN.min:
20211
+ return Math.min(a, b);
20212
+ case TOKEN.max:
20213
+ return Math.max(a, b);
20214
+ default:
20215
+ return void 0;
20216
+ }
20217
+ }
20218
+ function _evalUnaryConst(op, v) {
20219
+ switch (op) {
20220
+ case TOKEN.abs:
20221
+ return Math.abs(v);
20222
+ case TOKEN.neg:
20223
+ return -v;
20224
+ case TOKEN.ceiling:
20225
+ return Math.ceil(v);
20226
+ case TOKEN.floor:
20227
+ return Math.floor(v);
20228
+ case TOKEN.round:
20229
+ return Math.round(v);
20230
+ case TOKEN.truncate:
20231
+ return Math.trunc(v);
20232
+ case TOKEN.sqrt: {
20233
+ const r = Math.sqrt(v);
20234
+ return Number.isFinite(r) ? r : void 0;
20235
+ }
20236
+ case TOKEN.sin:
20237
+ return Math.sin(v % 360 * Math.PI / 180);
20238
+ case TOKEN.cos:
20239
+ return Math.cos(v % 360 * Math.PI / 180);
20240
+ case TOKEN.ln: {
20241
+ const r = Math.log(v);
20242
+ return Number.isFinite(r) ? r : void 0;
20243
+ }
20244
+ case TOKEN.log: {
20245
+ const r = Math.log10(v);
20246
+ return Number.isFinite(r) ? r : void 0;
20247
+ }
20248
+ case TOKEN.cvi:
20249
+ return Math.trunc(v);
20250
+ case TOKEN.cvr:
20251
+ return v;
20252
+ case TOKEN.not:
20253
+ return typeof v === "boolean" ? !v : ~v;
20254
+ default:
20255
+ return void 0;
20256
+ }
20257
+ }
20258
+ var MAX_STACK_SIZE = 100;
20259
+ function _unaryValueType(op, operandType) {
20260
+ return op === TOKEN.not ? operandType : PS_VALUE_TYPE.numeric;
20261
+ }
20262
+ function _binaryValueType(op, firstType, secondType) {
20263
+ switch (op) {
20264
+ // Comparison operators always produce a boolean.
20265
+ case TOKEN.eq:
20266
+ case TOKEN.ne:
20267
+ case TOKEN.gt:
20268
+ case TOKEN.ge:
20269
+ case TOKEN.lt:
20270
+ case TOKEN.le:
20271
+ return PS_VALUE_TYPE.boolean;
20272
+ // and / or / xor preserve the type when both operands are the same known
20273
+ // type (both boolean or both numeric); otherwise the type is unknown.
20274
+ case TOKEN.and:
20275
+ case TOKEN.or:
20276
+ case TOKEN.xor:
20277
+ return firstType === secondType && firstType !== PS_VALUE_TYPE.unknown ? firstType : PS_VALUE_TYPE.unknown;
20278
+ // All arithmetic / bitshift operators produce a numeric result.
20279
+ default:
20280
+ return PS_VALUE_TYPE.numeric;
20281
+ }
20282
+ }
20283
+ var PSStackToTree = class _PSStackToTree {
20284
+ static #binaryOps = null;
20285
+ static #unaryOps = null;
20286
+ static #idempotentUnary = null;
20287
+ static #negatedComparison = null;
20288
+ static #init() {
20289
+ this.#binaryOps = /* @__PURE__ */ new Set([
20290
+ TOKEN.add,
20291
+ TOKEN.sub,
20292
+ TOKEN.mul,
20293
+ TOKEN.div,
20294
+ TOKEN.idiv,
20295
+ TOKEN.mod,
20296
+ TOKEN.exp,
20297
+ TOKEN.atan,
20298
+ TOKEN.eq,
20299
+ TOKEN.ne,
20300
+ TOKEN.gt,
20301
+ TOKEN.ge,
20302
+ TOKEN.lt,
20303
+ TOKEN.le,
20304
+ TOKEN.and,
20305
+ TOKEN.or,
20306
+ TOKEN.xor,
20307
+ TOKEN.bitshift
20308
+ ]);
20309
+ this.#unaryOps = /* @__PURE__ */ new Set([
20310
+ TOKEN.abs,
20311
+ TOKEN.neg,
20312
+ TOKEN.ceiling,
20313
+ TOKEN.floor,
20314
+ TOKEN.round,
20315
+ TOKEN.truncate,
20316
+ TOKEN.sqrt,
20317
+ TOKEN.sin,
20318
+ TOKEN.cos,
20319
+ TOKEN.ln,
20320
+ TOKEN.log,
20321
+ TOKEN.cvi,
20322
+ TOKEN.cvr,
20323
+ TOKEN.not
20324
+ ]);
20325
+ this.#idempotentUnary = /* @__PURE__ */ new Set([
20326
+ TOKEN.abs,
20327
+ TOKEN.ceiling,
20328
+ TOKEN.cvi,
20329
+ TOKEN.cvr,
20330
+ TOKEN.floor,
20331
+ TOKEN.round,
20332
+ TOKEN.truncate
20333
+ ]);
20334
+ this.#negatedComparison = /* @__PURE__ */ new Map([
20335
+ [TOKEN.eq, TOKEN.ne],
20336
+ [TOKEN.ne, TOKEN.eq],
20337
+ [TOKEN.lt, TOKEN.ge],
20338
+ [TOKEN.le, TOKEN.gt],
20339
+ [TOKEN.gt, TOKEN.le],
20340
+ [TOKEN.ge, TOKEN.lt]
20341
+ ]);
20342
+ }
20343
+ /**
20344
+ * @param {PsProgram} program
20345
+ * @param {number} numInputs — number of domain values placed on the stack
20346
+ * before the program runs (i.e. the length of the domain array / 2).
20347
+ * @returns {Array<PsNode>} — one tree node per output value.
20348
+ */
20349
+ evaluate(program, numInputs) {
20350
+ if (!_PSStackToTree.#binaryOps) {
20351
+ _PSStackToTree.#init();
20352
+ }
20353
+ this._failed = false;
20354
+ if (numInputs > MAX_STACK_SIZE) {
20355
+ return null;
20356
+ }
20357
+ const stack = [];
20358
+ for (let i = 0; i < numInputs; i++) {
20359
+ stack.push(new PsArgNode(i));
20360
+ }
20361
+ this._evalBlock(program.body, stack);
20362
+ if (this._failed) {
20363
+ return null;
20364
+ }
20365
+ _PSStackToTree.#markShared(stack);
20366
+ return stack;
20367
+ }
20368
+ // Set node.shared / sharedCount on non-atomic nodes referenced more than
20369
+ // once. arg/const are excluded — they are cheap to re-emit inline.
20370
+ static #markShared(outputs) {
20371
+ const refCount = /* @__PURE__ */ new Map();
20372
+ const visit = (node) => {
20373
+ if (!node || node.type === PS_NODE.arg || node.type === PS_NODE.const) {
20374
+ return;
20375
+ }
20376
+ const prev = refCount.get(node) ?? 0;
20377
+ refCount.set(node, prev + 1);
20378
+ if (prev > 0) {
20379
+ return;
20380
+ }
20381
+ switch (node.type) {
20382
+ case PS_NODE.unary:
20383
+ visit(node.operand);
20384
+ break;
20385
+ case PS_NODE.binary:
20386
+ visit(node.first);
20387
+ visit(node.second);
20388
+ break;
20389
+ case PS_NODE.ternary:
20390
+ visit(node.cond);
20391
+ visit(node.then);
20392
+ visit(node.otherwise);
20393
+ break;
20394
+ }
20395
+ };
20396
+ for (const output of outputs) {
20397
+ visit(output);
20398
+ }
20399
+ for (const [node, count] of refCount) {
20400
+ if (count > 1) {
20401
+ node.shared = true;
20402
+ node.sharedCount = count;
20403
+ }
20404
+ }
20405
+ }
20406
+ _evalBlock(block, stack) {
20407
+ this._evalBlockFrom(block.instructions, 0, stack);
20408
+ }
20409
+ /**
20410
+ * Core evaluation loop. Processes `instructions[startIdx…]` in order,
20411
+ * mutating `stack` as each instruction executes.
20412
+ *
20413
+ * When a `{ body } if` instruction grows the stack (the PostScript "early
20414
+ * exit / guard" idiom), the remaining instructions in the current array are
20415
+ * evaluated on **both** the true-branch stack and the false-branch stack,
20416
+ * then the two results are merged into PsTernaryNodes. This handles
20417
+ * patterns like:
20418
+ *
20419
+ * cond { pop R G B sentinel } if
20420
+ * … more guards …
20421
+ * sentinel 0 gt { defaultR defaultG defaultB } if
20422
+ */
20423
+ _evalBlockFrom(instructions, startIdx, stack) {
20424
+ for (let idx = startIdx; idx < instructions.length; idx++) {
20425
+ if (this._failed) {
20426
+ break;
20427
+ }
20428
+ const instr = instructions[idx];
20429
+ switch (instr.type) {
20430
+ case PS_NODE.number:
20431
+ stack.push(new PsConstNode(instr.value));
20432
+ if (stack.length > MAX_STACK_SIZE) {
20433
+ this._failed = true;
20434
+ }
20435
+ break;
20436
+ case PS_NODE.operator:
20437
+ this._evalOp(instr.op, stack);
20438
+ break;
20439
+ case PS_NODE.if: {
20440
+ if (stack.length < 1) {
20441
+ this._failed = true;
20442
+ break;
20443
+ }
20444
+ const cond = stack.pop();
20445
+ const saved = stack.slice();
20446
+ this._evalBlock(instr.then, stack);
20447
+ if (this._failed) {
20448
+ break;
20449
+ }
20450
+ if (stack.length === saved.length) {
20451
+ for (let i = 0; i < stack.length; i++) {
20452
+ if (stack[i] !== saved[i]) {
20453
+ stack[i] = this._makeTernary(cond, stack[i], saved[i]);
20454
+ }
20455
+ }
20456
+ } else if (stack.length > saved.length) {
20457
+ if (cond.type === PS_NODE.const) {
20458
+ if (!cond.value) {
20459
+ stack.length = 0;
20460
+ stack.push(...saved);
20461
+ }
20462
+ break;
20463
+ }
20464
+ const trueStack = stack.slice();
20465
+ this._evalBlockFrom(instructions, idx + 1, trueStack);
20466
+ if (this._failed) {
20467
+ break;
20468
+ }
20469
+ const falseStack = saved;
20470
+ this._evalBlockFrom(instructions, idx + 1, falseStack);
20471
+ if (this._failed) {
20472
+ break;
20473
+ }
20474
+ if (trueStack.length !== falseStack.length) {
20475
+ const zero = new PsConstNode(0);
20476
+ while (trueStack.length < falseStack.length) {
20477
+ trueStack.push(zero);
20478
+ }
20479
+ while (falseStack.length < trueStack.length) {
20480
+ falseStack.push(zero);
20481
+ }
20482
+ }
20483
+ stack.length = 0;
20484
+ for (let i = 0; i < trueStack.length; i++) {
20485
+ stack.push(this._makeTernary(cond, trueStack[i], falseStack[i]));
20486
+ }
20487
+ return;
20488
+ } else {
20489
+ this._failed = true;
20490
+ }
20491
+ break;
20492
+ }
20493
+ case PS_NODE.ifelse: {
20494
+ if (stack.length < 1) {
20495
+ this._failed = true;
20496
+ break;
20497
+ }
20498
+ const cond = stack.pop();
20499
+ const snapshot = stack.slice();
20500
+ const thenStack = snapshot.slice();
20501
+ this._evalBlock(instr.then, thenStack);
20502
+ if (this._failed) {
20503
+ break;
20504
+ }
20505
+ const elseStack = snapshot.slice();
20506
+ this._evalBlock(instr.otherwise, elseStack);
20507
+ if (this._failed) {
20508
+ break;
20509
+ }
20510
+ if (thenStack.length !== elseStack.length) {
20511
+ const zero = new PsConstNode(0);
20512
+ while (thenStack.length < elseStack.length) {
20513
+ thenStack.push(zero);
20514
+ }
20515
+ while (elseStack.length < thenStack.length) {
20516
+ elseStack.push(zero);
20517
+ }
20518
+ }
20519
+ stack.length = 0;
20520
+ for (let i = 0; i < thenStack.length; i++) {
20521
+ stack.push(this._makeTernary(cond, thenStack[i], elseStack[i]));
20522
+ }
20523
+ break;
20524
+ }
20525
+ }
20526
+ }
20527
+ }
20528
+ _evalOp(op, stack) {
20529
+ if (_PSStackToTree.#binaryOps.has(op)) {
20530
+ if (stack.length < 2) {
20531
+ this._failed = true;
20532
+ return;
20533
+ }
20534
+ const first = stack.pop();
20535
+ const second = stack.pop();
20536
+ stack.push(this._makeBinary(op, first, second));
20537
+ return;
20538
+ }
20539
+ if (_PSStackToTree.#unaryOps.has(op)) {
20540
+ if (stack.length < 1) {
20541
+ this._failed = true;
20542
+ return;
20543
+ }
20544
+ stack.push(this._makeUnary(op, stack.pop()));
20545
+ return;
20546
+ }
20547
+ switch (op) {
20548
+ case TOKEN.true:
20549
+ stack.push(new PsConstNode(true));
20550
+ if (stack.length > MAX_STACK_SIZE) {
20551
+ this._failed = true;
20552
+ }
20553
+ break;
20554
+ case TOKEN.false:
20555
+ stack.push(new PsConstNode(false));
20556
+ if (stack.length > MAX_STACK_SIZE) {
20557
+ this._failed = true;
20558
+ }
20559
+ break;
20560
+ case TOKEN.dup:
20561
+ if (stack.length < 1) {
20562
+ this._failed = true;
20563
+ break;
20564
+ }
20565
+ stack.push(stack.at(-1));
20566
+ if (stack.length > MAX_STACK_SIZE) {
20567
+ this._failed = true;
20568
+ }
20569
+ break;
20570
+ case TOKEN.exch: {
20571
+ if (stack.length < 2) {
20572
+ this._failed = true;
20573
+ break;
20574
+ }
20575
+ const a = stack.pop();
20576
+ const b = stack.pop();
20577
+ stack.push(a, b);
20578
+ break;
20579
+ }
20580
+ case TOKEN.pop:
20581
+ if (stack.length < 1) {
20582
+ this._failed = true;
20583
+ break;
20584
+ }
20585
+ stack.pop();
20586
+ break;
20587
+ case TOKEN.copy: {
20588
+ if (stack.length < 1) {
20589
+ this._failed = true;
20590
+ break;
20591
+ }
20592
+ const nNode = stack.pop();
20593
+ if (nNode.type === PS_NODE.const) {
20594
+ const n = nNode.value | 0;
20595
+ if (n === 0) {
20596
+ } else if (n < 0 || n > stack.length) {
20597
+ this._failed = true;
20598
+ } else {
20599
+ stack.push(...stack.slice(-n));
20600
+ if (stack.length > MAX_STACK_SIZE) {
20601
+ this._failed = true;
20602
+ }
20603
+ }
20604
+ } else {
20605
+ this._failed = true;
20606
+ }
20607
+ break;
20608
+ }
20609
+ case TOKEN.index: {
20610
+ if (stack.length < 1) {
20611
+ this._failed = true;
20612
+ break;
20613
+ }
20614
+ const nNode = stack.pop();
20615
+ if (nNode.type === PS_NODE.const) {
20616
+ const n = nNode.value | 0;
20617
+ if (n < 0 || n >= stack.length) {
20618
+ this._failed = true;
20619
+ } else {
20620
+ stack.push(stack.at(-n - 1));
20621
+ }
20622
+ } else {
20623
+ this._failed = true;
20624
+ }
20625
+ break;
20626
+ }
20627
+ case TOKEN.roll: {
20628
+ if (stack.length < 2) {
20629
+ this._failed = true;
20630
+ break;
20631
+ }
20632
+ const jNode = stack.pop();
20633
+ const nNode = stack.pop();
20634
+ if (nNode.type === PS_NODE.const && jNode.type === PS_NODE.const) {
20635
+ const n = nNode.value | 0;
20636
+ if (n === 0) {
20637
+ } else if (n < 0 || n > stack.length) {
20638
+ this._failed = true;
20639
+ } else {
20640
+ const j = ((jNode.value | 0) % n + n) % n;
20641
+ if (j > 0) {
20642
+ const slice = stack.splice(-n, n);
20643
+ stack.push(...slice.slice(n - j), ...slice.slice(0, n - j));
20644
+ }
20645
+ }
20646
+ } else {
20647
+ this._failed = true;
20648
+ }
20649
+ break;
20650
+ }
20651
+ default:
20652
+ this._failed = true;
20653
+ break;
20654
+ }
20655
+ }
20656
+ /**
20657
+ * Create a binary tree node, applying optimizations eagerly:
20658
+ *
20659
+ * 1. Constant folding — both operands are PsConstNode → fold to PsConstNode.
20660
+ * 2. Reflexive simplifications — x−x→0, x xor x→0, x eq x→true, etc.
20661
+ * 3. Algebraic simplifications with one known operand — identity elements
20662
+ * (x+0→x, x*1→x, …), absorbing elements (x*0→0, x and false→false, …),
20663
+ * and strength reductions (x*-1→neg(x), x^0.5→sqrt(x), x^2→x*x, …).
20664
+ *
20665
+ * Recall: `first` was on top of the stack (right operand for non-commutative
20666
+ * ops), `second` was below (left operand). So `a b sub` → second=a, first=b
20667
+ * → a − b.
20668
+ */
20669
+ _makeBinary(op, first, second) {
20670
+ if (first.type === PS_NODE.const && second.type === PS_NODE.const) {
20671
+ const v = _evalBinaryConst(op, second.value, first.value);
20672
+ if (v !== void 0) {
20673
+ return new PsConstNode(v);
20674
+ }
20675
+ }
20676
+ if (_nodesEqual(first, second)) {
20677
+ switch (op) {
20678
+ case TOKEN.sub:
20679
+ return new PsConstNode(0);
20680
+ // x − x → 0
20681
+ case TOKEN.xor:
20682
+ return new PsConstNode(
20683
+ /* eslint-disable unicorn/prefer-logical-operator-over-ternary */
20684
+ first.valueType === PS_VALUE_TYPE.boolean ? false : 0
20685
+ /* eslint-enable unicorn/prefer-logical-operator-over-ternary */
20686
+ );
20687
+ // TOKEN.mod, TOKEN.div, TOKEN.idiv are NOT simplified here:
20688
+ // x op x is undefined when x = 0, so we cannot fold without knowing
20689
+ // that x is non-zero.
20690
+ case TOKEN.and:
20691
+ case TOKEN.or:
20692
+ return first;
20693
+ // x and x → x; x or x → x
20694
+ case TOKEN.min:
20695
+ case TOKEN.max:
20696
+ return first;
20697
+ // min(x,x) → x; max(x,x) → x
20698
+ case TOKEN.eq:
20699
+ case TOKEN.ge:
20700
+ case TOKEN.le:
20701
+ return new PsConstNode(true);
20702
+ case TOKEN.ne:
20703
+ case TOKEN.gt:
20704
+ case TOKEN.lt:
20705
+ return new PsConstNode(false);
20706
+ }
20707
+ }
20708
+ if (first.type === PS_NODE.const) {
20709
+ const b = first.value;
20710
+ switch (op) {
20711
+ case TOKEN.add:
20712
+ if (b === 0) {
20713
+ return second;
20714
+ }
20715
+ break;
20716
+ case TOKEN.sub:
20717
+ if (b === 0) {
20718
+ return second;
20719
+ }
20720
+ break;
20721
+ case TOKEN.mul:
20722
+ if (b === 1) {
20723
+ return second;
20724
+ }
20725
+ if (b === 0) {
20726
+ return first;
20727
+ }
20728
+ if (b === -1) {
20729
+ return this._makeUnary(TOKEN.neg, second);
20730
+ }
20731
+ break;
20732
+ case TOKEN.div:
20733
+ if (b !== 0) {
20734
+ return this._makeBinary(TOKEN.mul, new PsConstNode(1 / b), second);
20735
+ }
20736
+ break;
20737
+ case TOKEN.idiv:
20738
+ if (b === 1) {
20739
+ return second;
20740
+ }
20741
+ break;
20742
+ case TOKEN.exp:
20743
+ if (b === 1) {
20744
+ return second;
20745
+ }
20746
+ if (b === -1) {
20747
+ return this._makeBinary(TOKEN.div, second, new PsConstNode(1));
20748
+ }
20749
+ if (b === 0.5) {
20750
+ return this._makeUnary(TOKEN.sqrt, second);
20751
+ }
20752
+ if (b === 0.25) {
20753
+ const sqrtOnce = this._makeUnary(TOKEN.sqrt, second);
20754
+ return this._makeUnary(TOKEN.sqrt, sqrtOnce);
20755
+ }
20756
+ if (b === 2) {
20757
+ return this._makeBinary(TOKEN.mul, second, second);
20758
+ }
20759
+ if (b === 3) {
20760
+ return this._makeBinary(
20761
+ TOKEN.mul,
20762
+ this._makeBinary(TOKEN.mul, second, second),
20763
+ second
20764
+ );
20765
+ }
20766
+ if (b === 4) {
20767
+ const square = this._makeBinary(TOKEN.mul, second, second);
20768
+ return this._makeBinary(TOKEN.mul, square, square);
20769
+ }
20770
+ if (b === 0) {
20771
+ return new PsConstNode(1);
20772
+ }
20773
+ break;
20774
+ case TOKEN.and:
20775
+ if (b === true) {
20776
+ return second;
20777
+ }
20778
+ if (b === false) {
20779
+ return first;
20780
+ }
20781
+ break;
20782
+ case TOKEN.or:
20783
+ if (b === false) {
20784
+ return second;
20785
+ }
20786
+ if (b === true) {
20787
+ return first;
20788
+ }
20789
+ break;
20790
+ case TOKEN.min:
20791
+ if (second.type === PS_NODE.binary && second.op === TOKEN.max && second.first.type === PS_NODE.const && second.first.value >= b) {
20792
+ return first;
20793
+ }
20794
+ break;
20795
+ case TOKEN.max:
20796
+ if (second.type === PS_NODE.binary && second.op === TOKEN.min && second.first.type === PS_NODE.const && second.first.value <= b) {
20797
+ return first;
20798
+ }
20799
+ break;
20800
+ }
20801
+ }
20802
+ if (second.type === PS_NODE.const) {
20803
+ const a = second.value;
20804
+ switch (op) {
20805
+ case TOKEN.add:
20806
+ if (a === 0) {
20807
+ return first;
20808
+ }
20809
+ break;
20810
+ case TOKEN.sub:
20811
+ if (a === 0) {
20812
+ return this._makeUnary(TOKEN.neg, first);
20813
+ }
20814
+ break;
20815
+ case TOKEN.mul:
20816
+ if (a === 1) {
20817
+ return first;
20818
+ }
20819
+ if (a === 0) {
20820
+ return second;
20821
+ }
20822
+ if (a === -1) {
20823
+ return this._makeUnary(TOKEN.neg, first);
20824
+ }
20825
+ break;
20826
+ case TOKEN.and:
20827
+ if (a === true) {
20828
+ return first;
20829
+ }
20830
+ if (a === false) {
20831
+ return second;
20832
+ }
20833
+ break;
20834
+ case TOKEN.or:
20835
+ if (a === false) {
20836
+ return first;
20837
+ }
20838
+ if (a === true) {
20839
+ return second;
20840
+ }
20841
+ break;
20842
+ }
20843
+ }
20844
+ return new PsBinaryNode(
20845
+ op,
20846
+ first,
20847
+ second,
20848
+ _binaryValueType(op, first.valueType, second.valueType)
20849
+ );
20850
+ }
20851
+ /**
20852
+ * Create a unary tree node, applying optimizations eagerly:
20853
+ *
20854
+ * 1. Constant folding.
20855
+ * 2. not(comparison) → negated comparison: not(a eq b) → a ne b, etc.
20856
+ * 3. neg(a − b) → b − a.
20857
+ * 4. Double-negation: neg(neg(x)) → x, not(not(x)) → x.
20858
+ * 5. abs(neg(x)) → abs(x).
20859
+ * 6. Idempotent: f(f(x)) → f(x) for abs, ceiling, floor, round, etc.
20860
+ */
20861
+ _makeUnary(op, operand) {
20862
+ if (operand.type === PS_NODE.const) {
20863
+ const v = _evalUnaryConst(op, operand.value);
20864
+ if (v !== void 0) {
20865
+ return new PsConstNode(v);
20866
+ }
20867
+ }
20868
+ if (op === TOKEN.not && operand.type === PS_NODE.binary) {
20869
+ const negated = _PSStackToTree.#negatedComparison.get(operand.op);
20870
+ if (negated !== void 0) {
20871
+ return new PsBinaryNode(
20872
+ negated,
20873
+ operand.first,
20874
+ operand.second,
20875
+ PS_VALUE_TYPE.boolean
20876
+ );
20877
+ }
20878
+ }
20879
+ if (op === TOKEN.neg && operand.type === PS_NODE.binary && operand.op === TOKEN.sub) {
20880
+ return this._makeBinary(TOKEN.sub, operand.second, operand.first);
20881
+ }
20882
+ if (operand.type === PS_NODE.unary) {
20883
+ if (op === TOKEN.neg && operand.op === TOKEN.neg || op === TOKEN.not && operand.op === TOKEN.not) {
20884
+ return operand.operand;
20885
+ }
20886
+ if (op === TOKEN.abs && operand.op === TOKEN.neg) {
20887
+ return this._makeUnary(TOKEN.abs, operand.operand);
20888
+ }
20889
+ if (_PSStackToTree.#idempotentUnary.has(op) && op === operand.op) {
20890
+ return operand;
20891
+ }
20892
+ }
20893
+ return new PsUnaryNode(op, operand, _unaryValueType(op, operand.valueType));
20894
+ }
20895
+ /**
20896
+ * Create a ternary node, applying optimizations eagerly:
20897
+ *
20898
+ * 1. Constant condition — fold to the live branch.
20899
+ * 2. Identical branches — the condition is irrelevant, return either branch.
20900
+ * 3. Boolean branch constants — `cond ? true : false` → cond,
20901
+ * `cond ? false : true` → not(cond).
20902
+ * 4. Ternary → branchless min/max when the condition compares two numeric
20903
+ * expressions that are also the two branches.
20904
+ */
20905
+ _makeTernary(cond, then, otherwise) {
20906
+ if (cond.type === PS_NODE.const) {
20907
+ return cond.value ? then : otherwise;
20908
+ }
20909
+ if (_nodesEqual(then, otherwise)) {
20910
+ return then;
20911
+ }
20912
+ if (then.type === PS_NODE.const && otherwise.type === PS_NODE.const) {
20913
+ if (then.value === true && otherwise.value === false) {
20914
+ return cond;
20915
+ }
20916
+ if (then.value === false && otherwise.value === true) {
20917
+ return this._makeUnary(TOKEN.not, cond);
20918
+ }
20919
+ }
20920
+ if (cond.type === PS_NODE.binary) {
20921
+ const { op: cop, first: cf, second: cs } = cond;
20922
+ if (cop === TOKEN.gt || cop === TOKEN.ge) {
20923
+ if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
20924
+ return this._makeBinary(TOKEN.min, cf, cs);
20925
+ }
20926
+ if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
20927
+ return this._makeBinary(TOKEN.max, cf, cs);
20928
+ }
20929
+ } else if (cop === TOKEN.lt || cop === TOKEN.le) {
20930
+ if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
20931
+ return this._makeBinary(TOKEN.max, cf, cs);
20932
+ }
20933
+ if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
20934
+ return this._makeBinary(TOKEN.min, cf, cs);
20935
+ }
20936
+ }
20937
+ }
20938
+ return new PsTernaryNode(
20939
+ cond,
20940
+ then,
20941
+ otherwise,
20942
+ then.valueType === otherwise.valueType ? then.valueType : PS_VALUE_TYPE.unknown
20943
+ );
20944
+ }
20945
+ };
20946
+ var OP = {
20947
+ ARG: 0,
20948
+ // [ARG, idx]
20949
+ CONST: 1,
20950
+ // [CONST, val]
20951
+ STORE: 2,
20952
+ // [STORE, slot, min, max] clamp(pop()) → mem[slot]
20953
+ IF: 3,
20954
+ // [IF, target] jump when top-of-stack === 0
20955
+ JUMP: 4,
20956
+ // [JUMP, target] unconditional
20957
+ ABS: 5,
20958
+ NEG: 6,
20959
+ CEIL: 7,
20960
+ FLOOR: 8,
20961
+ ROUND: 9,
20962
+ // floor(x + 0.5)
20963
+ TRUNC: 10,
20964
+ NOT_B: 11,
20965
+ // boolean NOT
20966
+ NOT_N: 12,
20967
+ // bitwise NOT
20968
+ SQRT: 13,
20969
+ SIN: 14,
20970
+ // degrees in/out
20971
+ COS: 15,
20972
+ LN: 16,
20973
+ LOG10: 17,
20974
+ CVI: 18,
20975
+ SHIFT: 19,
20976
+ // [SHIFT, amount] +ve = left, −ve = right
20977
+ // Binary ops: second below, first on top; result = second OP first.
20978
+ ADD: 20,
20979
+ SUB: 21,
20980
+ MUL: 22,
20981
+ DIV: 23,
20982
+ // 0 when divisor is 0
20983
+ IDIV: 24,
20984
+ // 0 when divisor is 0
20985
+ MOD: 25,
20986
+ // 0 when divisor is 0
20987
+ POW: 26,
20988
+ EQ: 27,
20989
+ NE: 28,
20990
+ GT: 29,
20991
+ GE: 30,
20992
+ LT: 31,
20993
+ LE: 32,
20994
+ AND: 33,
20995
+ OR: 34,
20996
+ XOR: 35,
20997
+ ATAN: 36,
20998
+ // atan2(second, first) → degrees [0, 360)
20999
+ MIN: 37,
21000
+ MAX: 38,
21001
+ TEE_TMP: 39,
21002
+ // [TEE_TMP, slot] peek top of stack → tmp[slot], leave on stack
21003
+ LOAD_TMP: 40
21004
+ // [LOAD_TMP, slot] push tmp[slot]
21005
+ };
21006
+ var _DEG_TO_RAD = Math.PI / 180;
21007
+ var _RAD_TO_DEG = 180 / Math.PI;
21008
+ var PsJsCompiler = class {
21009
+ // Safe because JS is single-threaded.
21010
+ static #stack = new Float64Array(64);
21011
+ static #tmp = new Float64Array(64);
21012
+ constructor(domain, range) {
21013
+ this.nIn = domain.length >> 1;
21014
+ this.nOut = range.length >> 1;
21015
+ this.range = range;
21016
+ this.ir = [];
21017
+ this._tmpMap = /* @__PURE__ */ new Map();
21018
+ this._nextTmp = 0;
21019
+ }
21020
+ _compileNode(node) {
21021
+ if (node.shared) {
21022
+ const cached = this._tmpMap.get(node);
21023
+ if (cached !== void 0) {
21024
+ this.ir.push(OP.LOAD_TMP, cached);
21025
+ return true;
21026
+ }
21027
+ if (!this._compileNodeImpl(node)) {
21028
+ return false;
21029
+ }
21030
+ const slot = this._nextTmp++;
21031
+ this._tmpMap.set(node, slot);
21032
+ this.ir.push(OP.TEE_TMP, slot);
21033
+ return true;
21034
+ }
21035
+ return this._compileNodeImpl(node);
21036
+ }
21037
+ _compileNodeImpl(node) {
21038
+ switch (node.type) {
21039
+ case PS_NODE.arg:
21040
+ this.ir.push(OP.ARG, node.index);
21041
+ return true;
21042
+ case PS_NODE.const: {
21043
+ const v = node.value;
21044
+ this.ir.push(OP.CONST, typeof v === "boolean" ? Number(v) : v);
21045
+ return true;
21046
+ }
21047
+ case PS_NODE.unary:
21048
+ return this._compileUnary(node);
21049
+ case PS_NODE.binary:
21050
+ return this._compileBinary(node);
21051
+ case PS_NODE.ternary:
21052
+ return this._compileTernary(node);
21053
+ default:
21054
+ return false;
21055
+ }
21056
+ }
21057
+ _compileUnary(node) {
21058
+ const { op, operand, valueType } = node;
21059
+ if (op === TOKEN.cvr) {
21060
+ return this._compileNode(operand);
21061
+ }
21062
+ if (!this._compileNode(operand)) {
21063
+ return false;
21064
+ }
21065
+ switch (op) {
21066
+ case TOKEN.abs:
21067
+ this.ir.push(OP.ABS);
21068
+ break;
21069
+ case TOKEN.neg:
21070
+ this.ir.push(OP.NEG);
21071
+ break;
21072
+ case TOKEN.ceiling:
21073
+ this.ir.push(OP.CEIL);
21074
+ break;
21075
+ case TOKEN.floor:
21076
+ this.ir.push(OP.FLOOR);
21077
+ break;
21078
+ case TOKEN.round:
21079
+ this.ir.push(OP.ROUND);
21080
+ break;
21081
+ case TOKEN.truncate:
21082
+ this.ir.push(OP.TRUNC);
21083
+ break;
21084
+ case TOKEN.sqrt:
21085
+ this.ir.push(OP.SQRT);
21086
+ break;
21087
+ case TOKEN.sin:
21088
+ this.ir.push(OP.SIN);
21089
+ break;
21090
+ case TOKEN.cos:
21091
+ this.ir.push(OP.COS);
21092
+ break;
21093
+ case TOKEN.ln:
21094
+ this.ir.push(OP.LN);
21095
+ break;
21096
+ case TOKEN.log:
21097
+ this.ir.push(OP.LOG10);
21098
+ break;
21099
+ case TOKEN.cvi:
21100
+ this.ir.push(OP.CVI);
21101
+ break;
21102
+ case TOKEN.not:
21103
+ if (valueType === PS_VALUE_TYPE.boolean) {
21104
+ this.ir.push(OP.NOT_B);
21105
+ } else if (valueType === PS_VALUE_TYPE.numeric) {
21106
+ this.ir.push(OP.NOT_N);
21107
+ } else {
21108
+ return false;
21109
+ }
21110
+ break;
21111
+ default:
21112
+ return false;
21113
+ }
21114
+ return true;
21115
+ }
21116
+ _compileBinary(node) {
21117
+ const { op, first, second } = node;
21118
+ if (op === TOKEN.bitshift) {
21119
+ if (first.type !== PS_NODE.const || !Number.isInteger(first.value) || !this._compileNode(second)) {
21120
+ return false;
21121
+ }
21122
+ this.ir.push(OP.SHIFT, first.value);
21123
+ return true;
21124
+ }
21125
+ if (!this._compileNode(second) || !this._compileNode(first)) {
21126
+ return false;
21127
+ }
21128
+ switch (op) {
21129
+ case TOKEN.add:
21130
+ this.ir.push(OP.ADD);
21131
+ break;
21132
+ case TOKEN.sub:
21133
+ this.ir.push(OP.SUB);
21134
+ break;
21135
+ case TOKEN.mul:
21136
+ this.ir.push(OP.MUL);
21137
+ break;
21138
+ case TOKEN.div:
21139
+ this.ir.push(OP.DIV);
21140
+ break;
21141
+ case TOKEN.idiv:
21142
+ this.ir.push(OP.IDIV);
21143
+ break;
21144
+ case TOKEN.mod:
21145
+ this.ir.push(OP.MOD);
21146
+ break;
21147
+ case TOKEN.exp:
21148
+ this.ir.push(OP.POW);
21149
+ break;
21150
+ case TOKEN.eq:
21151
+ this.ir.push(OP.EQ);
21152
+ break;
21153
+ case TOKEN.ne:
21154
+ this.ir.push(OP.NE);
21155
+ break;
21156
+ case TOKEN.gt:
21157
+ this.ir.push(OP.GT);
21158
+ break;
21159
+ case TOKEN.ge:
21160
+ this.ir.push(OP.GE);
21161
+ break;
21162
+ case TOKEN.lt:
21163
+ this.ir.push(OP.LT);
21164
+ break;
21165
+ case TOKEN.le:
21166
+ this.ir.push(OP.LE);
21167
+ break;
21168
+ case TOKEN.and:
21169
+ this.ir.push(OP.AND);
21170
+ break;
21171
+ case TOKEN.or:
21172
+ this.ir.push(OP.OR);
21173
+ break;
21174
+ case TOKEN.xor:
21175
+ this.ir.push(OP.XOR);
21176
+ break;
21177
+ case TOKEN.atan:
21178
+ this.ir.push(OP.ATAN);
21179
+ break;
21180
+ case TOKEN.min:
21181
+ this.ir.push(OP.MIN);
21182
+ break;
21183
+ case TOKEN.max:
21184
+ this.ir.push(OP.MAX);
21185
+ break;
21186
+ default:
21187
+ return false;
21188
+ }
21189
+ return true;
21190
+ }
21191
+ _compileTernary(node) {
21192
+ if (!this._compileNode(node.cond)) {
21193
+ return false;
21194
+ }
21195
+ this.ir.push(OP.IF, 0);
21196
+ const ifPatch = this.ir.length - 1;
21197
+ if (!this._compileNode(node.then)) {
21198
+ return false;
21199
+ }
21200
+ this.ir.push(OP.JUMP, 0);
21201
+ const jumpPatch = this.ir.length - 1;
21202
+ this.ir[ifPatch] = this.ir.length;
21203
+ if (!this._compileNode(node.otherwise)) {
21204
+ return false;
21205
+ }
21206
+ this.ir[jumpPatch] = this.ir.length;
21207
+ return true;
21208
+ }
21209
+ compile(program) {
21210
+ const outputs = new PSStackToTree().evaluate(program, this.nIn);
21211
+ if (!outputs || outputs.length < this.nOut) {
21212
+ return null;
21213
+ }
21214
+ for (let i = 0; i < this.nOut; i++) {
21215
+ if (!this._compileNode(outputs[i])) {
21216
+ return null;
21217
+ }
21218
+ const min = this.range[i * 2];
21219
+ const max = this.range[i * 2 + 1];
21220
+ this.ir.push(OP.STORE, i, min, max);
21221
+ }
21222
+ return new Float64Array(this.ir);
21223
+ }
21224
+ static execute(ir, src, srcOffset, dest, destOffset) {
21225
+ let ip = 0, sp = 0;
21226
+ const n = ir.length;
21227
+ const stack = this.#stack;
21228
+ const tmp = this.#tmp;
21229
+ while (ip < n) {
21230
+ switch (ir[ip++] | 0) {
21231
+ case OP.ARG:
21232
+ stack[sp++] = src[srcOffset + (ir[ip++] | 0)];
21233
+ break;
21234
+ case OP.CONST:
21235
+ stack[sp++] = ir[ip++];
21236
+ break;
21237
+ case OP.STORE: {
21238
+ const slot = ir[ip++] | 0;
21239
+ const min = ir[ip++];
21240
+ const max = ir[ip++];
21241
+ dest[destOffset + slot] = MathClamp(stack[--sp], min, max);
21242
+ break;
21243
+ }
21244
+ case OP.IF: {
21245
+ const tgt = ir[ip++];
21246
+ if (stack[--sp] === 0) {
21247
+ ip = tgt;
21248
+ }
21249
+ break;
21250
+ }
21251
+ case OP.JUMP:
21252
+ ip = ir[ip];
21253
+ break;
21254
+ case OP.ABS:
21255
+ stack[sp - 1] = Math.abs(stack[sp - 1]);
21256
+ break;
21257
+ case OP.NEG:
21258
+ stack[sp - 1] = -stack[sp - 1];
21259
+ break;
21260
+ case OP.CEIL:
21261
+ stack[sp - 1] = Math.ceil(stack[sp - 1]);
21262
+ break;
21263
+ case OP.FLOOR:
21264
+ stack[sp - 1] = Math.floor(stack[sp - 1]);
21265
+ break;
21266
+ case OP.ROUND:
21267
+ stack[sp - 1] = Math.floor(stack[sp - 1] + 0.5);
21268
+ break;
21269
+ case OP.TRUNC:
21270
+ stack[sp - 1] = Math.trunc(stack[sp - 1]);
21271
+ break;
21272
+ case OP.NOT_B:
21273
+ stack[sp - 1] = stack[sp - 1] !== 0 ? 0 : 1;
21274
+ break;
21275
+ case OP.NOT_N:
21276
+ stack[sp - 1] = ~(stack[sp - 1] | 0);
21277
+ break;
21278
+ case OP.SQRT:
21279
+ stack[sp - 1] = Math.sqrt(stack[sp - 1]);
21280
+ break;
21281
+ case OP.SIN:
21282
+ stack[sp - 1] = Math.sin(stack[sp - 1] % 360 * _DEG_TO_RAD);
21283
+ break;
21284
+ case OP.COS:
21285
+ stack[sp - 1] = Math.cos(stack[sp - 1] % 360 * _DEG_TO_RAD);
21286
+ break;
21287
+ case OP.LN:
21288
+ stack[sp - 1] = Math.log(stack[sp - 1]);
21289
+ break;
21290
+ case OP.LOG10:
21291
+ stack[sp - 1] = Math.log10(stack[sp - 1]);
21292
+ break;
21293
+ case OP.CVI:
21294
+ stack[sp - 1] = Math.trunc(stack[sp - 1]) | 0;
21295
+ break;
21296
+ case OP.SHIFT: {
21297
+ const amt = ir[ip++];
21298
+ const v = stack[sp - 1] | 0;
21299
+ if (amt > 0) {
21300
+ stack[sp - 1] = v << amt;
21301
+ } else if (amt < 0) {
21302
+ stack[sp - 1] = v >> -amt;
21303
+ } else {
21304
+ stack[sp - 1] = v;
21305
+ }
21306
+ break;
21307
+ }
21308
+ case OP.ADD: {
21309
+ const b = stack[--sp];
21310
+ stack[sp - 1] += b;
21311
+ break;
21312
+ }
21313
+ case OP.SUB: {
21314
+ const b = stack[--sp];
21315
+ stack[sp - 1] -= b;
21316
+ break;
21317
+ }
21318
+ case OP.MUL: {
21319
+ const b = stack[--sp];
21320
+ stack[sp - 1] *= b;
21321
+ break;
21322
+ }
21323
+ case OP.DIV: {
21324
+ const b = stack[--sp];
21325
+ stack[sp - 1] = b !== 0 ? stack[sp - 1] / b : 0;
21326
+ break;
21327
+ }
21328
+ case OP.IDIV: {
21329
+ const b = stack[--sp];
21330
+ stack[sp - 1] = b !== 0 ? Math.trunc(stack[sp - 1] / b) : 0;
21331
+ break;
21332
+ }
21333
+ case OP.MOD: {
21334
+ const b = stack[--sp];
21335
+ stack[sp - 1] = b !== 0 ? stack[sp - 1] % b : 0;
21336
+ break;
21337
+ }
21338
+ case OP.POW: {
21339
+ const b = stack[--sp];
21340
+ stack[sp - 1] **= b;
21341
+ break;
21342
+ }
21343
+ case OP.EQ: {
21344
+ const b = stack[--sp];
21345
+ stack[sp - 1] = stack[sp - 1] === b ? 1 : 0;
21346
+ break;
21347
+ }
21348
+ case OP.NE: {
21349
+ const b = stack[--sp];
21350
+ stack[sp - 1] = stack[sp - 1] !== b ? 1 : 0;
21351
+ break;
21352
+ }
21353
+ case OP.GT: {
21354
+ const b = stack[--sp];
21355
+ stack[sp - 1] = stack[sp - 1] > b ? 1 : 0;
21356
+ break;
21357
+ }
21358
+ case OP.GE: {
21359
+ const b = stack[--sp];
21360
+ stack[sp - 1] = stack[sp - 1] >= b ? 1 : 0;
21361
+ break;
21362
+ }
21363
+ case OP.LT: {
21364
+ const b = stack[--sp];
21365
+ stack[sp - 1] = stack[sp - 1] < b ? 1 : 0;
21366
+ break;
21367
+ }
21368
+ case OP.LE: {
21369
+ const b = stack[--sp];
21370
+ stack[sp - 1] = stack[sp - 1] <= b ? 1 : 0;
21371
+ break;
21372
+ }
21373
+ case OP.AND: {
21374
+ const b = stack[--sp] | 0;
21375
+ stack[sp - 1] = (stack[sp - 1] | 0) & b;
21376
+ break;
21377
+ }
21378
+ case OP.OR: {
21379
+ const b = stack[--sp] | 0;
21380
+ stack[sp - 1] = stack[sp - 1] | 0 | b;
21381
+ break;
21382
+ }
21383
+ case OP.XOR: {
21384
+ const b = stack[--sp] | 0;
21385
+ stack[sp - 1] = (stack[sp - 1] | 0) ^ b;
21386
+ break;
21387
+ }
21388
+ case OP.ATAN: {
21389
+ const b = stack[--sp];
21390
+ const deg = Math.atan2(stack[sp - 1], b) * _RAD_TO_DEG;
21391
+ stack[sp - 1] = deg < 0 ? deg + 360 : deg;
21392
+ break;
21393
+ }
21394
+ case OP.MIN: {
21395
+ const b = stack[--sp];
21396
+ stack[sp - 1] = Math.min(stack[sp - 1], b);
21397
+ break;
21398
+ }
21399
+ case OP.MAX: {
21400
+ const b = stack[--sp];
21401
+ stack[sp - 1] = Math.max(stack[sp - 1], b);
21402
+ break;
21403
+ }
21404
+ case OP.TEE_TMP:
21405
+ tmp[ir[ip++] | 0] = stack[sp - 1];
21406
+ break;
21407
+ case OP.LOAD_TMP:
21408
+ stack[sp++] = tmp[ir[ip++] | 0];
21409
+ break;
21410
+ }
21411
+ }
21412
+ }
21413
+ };
21414
+ var PSStackBasedInterpreter = class {
21415
+ // Safe: JS is single-threaded.
21416
+ static #stack = new Float64Array(100);
21417
+ static #sp = 0;
21418
+ static #push(v) {
21419
+ if (this.#sp < this.#stack.length) {
21420
+ this.#stack[this.#sp++] = v;
21421
+ }
21422
+ }
21423
+ static #execOp(op) {
21424
+ const stack = this.#stack;
21425
+ switch (op) {
21426
+ case TOKEN.true:
21427
+ this.#push(1);
21428
+ break;
21429
+ case TOKEN.false:
21430
+ this.#push(0);
21431
+ break;
21432
+ case TOKEN.abs:
21433
+ stack[this.#sp - 1] = Math.abs(stack[this.#sp - 1]);
21434
+ break;
21435
+ case TOKEN.neg:
21436
+ stack[this.#sp - 1] = -stack[this.#sp - 1];
21437
+ break;
21438
+ case TOKEN.ceiling:
21439
+ stack[this.#sp - 1] = Math.ceil(stack[this.#sp - 1]);
21440
+ break;
21441
+ case TOKEN.floor:
21442
+ stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1]);
21443
+ break;
21444
+ case TOKEN.round:
21445
+ stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1] + 0.5);
21446
+ break;
21447
+ case TOKEN.truncate:
21448
+ stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]);
21449
+ break;
21450
+ case TOKEN.sqrt:
21451
+ stack[this.#sp - 1] = Math.sqrt(stack[this.#sp - 1]);
21452
+ break;
21453
+ case TOKEN.sin:
21454
+ stack[this.#sp - 1] = Math.sin(
21455
+ stack[this.#sp - 1] % 360 * _DEG_TO_RAD
21456
+ );
21457
+ break;
21458
+ case TOKEN.cos:
21459
+ stack[this.#sp - 1] = Math.cos(
21460
+ stack[this.#sp - 1] % 360 * _DEG_TO_RAD
21461
+ );
21462
+ break;
21463
+ case TOKEN.ln:
21464
+ stack[this.#sp - 1] = Math.log(stack[this.#sp - 1]);
21465
+ break;
21466
+ case TOKEN.log:
21467
+ stack[this.#sp - 1] = Math.log10(stack[this.#sp - 1]);
21468
+ break;
21469
+ case TOKEN.cvi:
21470
+ stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]) | 0;
21471
+ break;
21472
+ case TOKEN.cvr:
21473
+ break;
21474
+ // values are already f64
21475
+ case TOKEN.not: {
21476
+ const v = stack[this.#sp - 1];
21477
+ stack[this.#sp - 1] = v === 0 || v === 1 ? 1 - v : ~(v | 0);
21478
+ break;
21479
+ }
21480
+ case TOKEN.add: {
21481
+ const b = stack[--this.#sp];
21482
+ stack[this.#sp - 1] += b;
21483
+ break;
21484
+ }
21485
+ case TOKEN.sub: {
21486
+ const b = stack[--this.#sp];
21487
+ stack[this.#sp - 1] -= b;
21488
+ break;
21489
+ }
21490
+ case TOKEN.mul: {
21491
+ const b = stack[--this.#sp];
21492
+ stack[this.#sp - 1] *= b;
21493
+ break;
21494
+ }
21495
+ case TOKEN.div: {
21496
+ const b = stack[--this.#sp];
21497
+ stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] / b : 0;
21498
+ break;
21499
+ }
21500
+ case TOKEN.idiv: {
21501
+ const b = stack[--this.#sp];
21502
+ stack[this.#sp - 1] = b !== 0 ? Math.trunc(stack[this.#sp - 1] / b) : 0;
21503
+ break;
21504
+ }
21505
+ case TOKEN.mod: {
21506
+ const b = stack[--this.#sp];
21507
+ stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] % b : 0;
21508
+ break;
21509
+ }
21510
+ case TOKEN.exp: {
21511
+ const b = stack[--this.#sp];
21512
+ stack[this.#sp - 1] **= b;
21513
+ break;
21514
+ }
21515
+ case TOKEN.atan: {
21516
+ const dx = stack[--this.#sp];
21517
+ const deg = Math.atan2(stack[this.#sp - 1], dx) * _RAD_TO_DEG;
21518
+ stack[this.#sp - 1] = deg < 0 ? deg + 360 : deg;
21519
+ break;
21520
+ }
21521
+ case TOKEN.eq: {
21522
+ const b = stack[--this.#sp];
21523
+ stack[this.#sp - 1] = stack[this.#sp - 1] === b ? 1 : 0;
21524
+ break;
21525
+ }
21526
+ case TOKEN.ne: {
21527
+ const b = stack[--this.#sp];
21528
+ stack[this.#sp - 1] = stack[this.#sp - 1] !== b ? 1 : 0;
21529
+ break;
21530
+ }
21531
+ case TOKEN.gt: {
21532
+ const b = stack[--this.#sp];
21533
+ stack[this.#sp - 1] = stack[this.#sp - 1] > b ? 1 : 0;
21534
+ break;
21535
+ }
21536
+ case TOKEN.ge: {
21537
+ const b = stack[--this.#sp];
21538
+ stack[this.#sp - 1] = stack[this.#sp - 1] >= b ? 1 : 0;
21539
+ break;
21540
+ }
21541
+ case TOKEN.lt: {
21542
+ const b = stack[--this.#sp];
21543
+ stack[this.#sp - 1] = stack[this.#sp - 1] < b ? 1 : 0;
21544
+ break;
21545
+ }
21546
+ case TOKEN.le: {
21547
+ const b = stack[--this.#sp];
21548
+ stack[this.#sp - 1] = stack[this.#sp - 1] <= b ? 1 : 0;
21549
+ break;
21550
+ }
21551
+ case TOKEN.and: {
21552
+ const b = stack[--this.#sp] | 0;
21553
+ stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) & b;
21554
+ break;
21555
+ }
21556
+ case TOKEN.or: {
21557
+ const b = stack[--this.#sp] | 0;
21558
+ stack[this.#sp - 1] = stack[this.#sp - 1] | 0 | b;
21559
+ break;
21560
+ }
21561
+ case TOKEN.xor: {
21562
+ const b = stack[--this.#sp] | 0;
21563
+ stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) ^ b;
21564
+ break;
21565
+ }
21566
+ case TOKEN.bitshift: {
21567
+ const amt = stack[--this.#sp] | 0;
21568
+ const v = stack[this.#sp - 1] | 0;
21569
+ stack[this.#sp - 1] = amt > 0 ? v << amt : v >> -amt;
21570
+ break;
21571
+ }
21572
+ case TOKEN.min: {
21573
+ const b = stack[--this.#sp];
21574
+ stack[this.#sp - 1] = Math.min(stack[this.#sp - 1], b);
21575
+ break;
21576
+ }
21577
+ case TOKEN.max: {
21578
+ const b = stack[--this.#sp];
21579
+ stack[this.#sp - 1] = Math.max(stack[this.#sp - 1], b);
21580
+ break;
21581
+ }
21582
+ case TOKEN.dup:
21583
+ this.#push(stack[this.#sp - 1]);
21584
+ break;
21585
+ case TOKEN.exch: {
21586
+ const a = stack[--this.#sp];
21587
+ const b = stack[--this.#sp];
21588
+ this.#push(a);
21589
+ this.#push(b);
21590
+ break;
21591
+ }
21592
+ case TOKEN.pop:
21593
+ this.#sp--;
21594
+ break;
21595
+ case TOKEN.copy: {
21596
+ const n = Math.trunc(stack[--this.#sp]);
21597
+ const base = this.#sp - n;
21598
+ for (let k = 0; k < n; k++) {
21599
+ this.#push(stack[base + k]);
21600
+ }
21601
+ break;
21602
+ }
21603
+ case TOKEN.index: {
21604
+ const i = Math.trunc(stack[--this.#sp]);
21605
+ this.#push(stack[this.#sp - 1 - i]);
21606
+ break;
21607
+ }
21608
+ case TOKEN.roll: {
21609
+ const j = Math.trunc(stack[--this.#sp]);
21610
+ const n = Math.trunc(stack[--this.#sp]);
21611
+ if (n > 1 && j !== 0) {
21612
+ const mod = (j % n + n) % n;
21613
+ if (mod !== 0) {
21614
+ const base = this.#sp - n;
21615
+ const sub = stack.slice(base, this.#sp);
21616
+ for (let k = 0; k < n; k++) {
21617
+ stack[base + k] = sub[(k - mod + n) % n];
21618
+ }
21619
+ }
21620
+ }
21621
+ break;
21622
+ }
21623
+ }
21624
+ }
21625
+ static #execBlock(instructions) {
21626
+ for (const instr of instructions) {
21627
+ switch (instr.type) {
21628
+ case PS_NODE.number:
21629
+ this.#push(instr.value);
21630
+ break;
21631
+ case PS_NODE.operator:
21632
+ this.#execOp(instr.op);
21633
+ break;
21634
+ case PS_NODE.if:
21635
+ if (this.#stack[--this.#sp] !== 0) {
21636
+ this.#execBlock(instr.then.instructions);
21637
+ }
21638
+ break;
21639
+ case PS_NODE.ifelse:
21640
+ if (this.#stack[--this.#sp] !== 0) {
21641
+ this.#execBlock(instr.then.instructions);
21642
+ } else {
21643
+ this.#execBlock(instr.otherwise.instructions);
21644
+ }
21645
+ break;
21646
+ }
21647
+ }
21648
+ }
21649
+ /**
21650
+ * @param {import("./ast.js").PsProgram} program
21651
+ * @param {number[]} domain – flat [min0,max0, …]
21652
+ * @param {number[]} range – flat [min0,max0, …]
21653
+ * @returns {Function} – `(src, srcOffset, dest, destOffset) => void`
21654
+ */
21655
+ static build(program, domain, range) {
21656
+ const nIn = domain.length >> 1;
21657
+ const nOut = range.length >> 1;
21658
+ const { instructions } = program.body;
21659
+ return (src, srcOffset, dest, destOffset) => {
21660
+ this.#sp = 0;
21661
+ for (let i = 0; i < nIn; i++) {
21662
+ this.#push(src[srcOffset + i]);
21663
+ }
21664
+ this.#execBlock(instructions);
21665
+ const base = this.#sp - nOut;
21666
+ for (let i = 0; i < nOut; i++) {
21667
+ const v = base + i >= 0 ? this.#stack[base + i] : 0;
21668
+ dest[destOffset + i] = MathClamp(v, range[i * 2], range[i * 2 + 1]);
21669
+ }
21670
+ };
21671
+ }
21672
+ };
21673
+ function buildPostScriptJsFunction(source, domain, range, forceInterpreter = false) {
21674
+ const program = parsePostScriptFunction(source);
21675
+ const ir = !forceInterpreter && new PsJsCompiler(domain, range).compile(program);
21676
+ if (ir) {
21677
+ return (src, srcOffset, dest, destOffset) => {
21678
+ PsJsCompiler.execute(ir, src, srcOffset, dest, destOffset);
21679
+ };
21680
+ }
21681
+ return PSStackBasedInterpreter.build(program, domain, range);
21682
+ }
19075
21683
 
19076
21684
  // packages/pdf-ast/src/ast.ts
19077
21685
  init_buffer();
@@ -26356,6 +28964,27 @@ var __webpack_exports__VerbosityLevel = __webpack_exports__.VerbosityLevel;
26356
28964
  var __webpack_exports__getVerbosityLevel = __webpack_exports__.getVerbosityLevel;
26357
28965
  var __webpack_exports__setVerbosityLevel = __webpack_exports__.setVerbosityLevel;
26358
28966
 
28967
+ // packages/pdf-ast/src/content/calibrated-color.ts
28968
+ init_buffer();
28969
+ function createCalibratedColorSpace(doc, family, parameters) {
28970
+ const dict = doc.resolveDict(parameters);
28971
+ const array = (key) => {
28972
+ const value = dict ? doc.resolveArray(dictGet(dict, key)) : void 0;
28973
+ return value?.items.map((item) => {
28974
+ const number = doc.resolve(item);
28975
+ return number?.kind === "number" ? number.value : 0;
28976
+ });
28977
+ };
28978
+ const whitePoint = array("WhitePoint") ?? [0.95047, 1, 1.08883];
28979
+ const blackPoint = array("BlackPoint");
28980
+ if (family === "CalGray") {
28981
+ const gamma = dict ? doc.resolve(dictGet(dict, "Gamma")) : void 0;
28982
+ return new CalGrayCS(whitePoint, blackPoint, gamma?.kind === "number" ? gamma.value : void 0);
28983
+ }
28984
+ if (family === "CalRGB") return new CalRGBCS(whitePoint, blackPoint, array("Gamma"), array("Matrix"));
28985
+ return new LabCS(whitePoint, blackPoint, array("Range"));
28986
+ }
28987
+
26359
28988
  // packages/pdf-ast/src/content/parser.ts
26360
28989
  init_buffer();
26361
28990
 
@@ -29460,6 +32089,7 @@ function parseCosDocument(bytes, options = {}) {
29460
32089
  }
29461
32090
 
29462
32091
  // packages/pdf-ast/src/extract/images.ts
32092
+ var cmykColorSpace = new DeviceCmykCS();
29463
32093
  function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
29464
32094
  if (!csNode) return { colorSpace: "rgb", colorSpaceLabel: "rgb", components: 3 };
29465
32095
  const resolved = doc.resolve(csNode);
@@ -29500,7 +32130,7 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
29500
32130
  palette = lookupNode.bytes;
29501
32131
  }
29502
32132
  let resolvedBaseComp = baseInfo.components;
29503
- if (palette && (baseInfo.isLab || baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calRgbGamma !== void 0 || baseInfo.calGrayGamma !== void 0)) {
32133
+ if (palette && (baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calibrated !== void 0)) {
29504
32134
  const numEntries = Math.max(1, Math.min(hival + 1, Math.floor(palette.length / Math.max(1, baseInfo.components))));
29505
32135
  const rgbaPal = decodeSamplesToRgba(palette, numEntries, 1, 8, baseInfo);
29506
32136
  const rgbPal = new Uint8Array(numEntries * 3);
@@ -29530,74 +32160,21 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
29530
32160
  }
29531
32161
  return { colorSpace: "rgb", colorSpaceLabel: "icc", components: 3 };
29532
32162
  }
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
- }
32163
+ if (kindName === "CalGray" || kindName === "CalRGB" || kindName === "Lab") {
32164
+ const calibrated = createCalibratedColorSpace(doc, kindName, resolved.items[1]);
29558
32165
  return {
29559
- colorSpace: "rgb",
29560
- colorSpaceLabel: "cal-rgb",
29561
- components: 3,
29562
- calRgbGamma,
29563
- calRgbMatrix
32166
+ colorSpace: kindName === "CalGray" ? "gray" : "rgb",
32167
+ colorSpaceLabel: kindName === "CalGray" ? "cal-gray" : kindName === "CalRGB" ? "cal-rgb" : "lab",
32168
+ components: kindName === "CalGray" ? 1 : 3,
32169
+ calibrated
29564
32170
  };
29565
32171
  }
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
32172
  if (kindName === "Separation" || kindName === "DeviceN") {
29580
32173
  const isDevN = kindName === "DeviceN";
29581
32174
  const namesArr = isDevN ? doc.resolveArray(resolved.items[1]) : void 0;
29582
32175
  const devNComponents = isDevN && namesArr ? Math.max(1, namesArr.items.length) : 1;
29583
32176
  const altInfo = resolveColorSpaceInfo(doc, resolved.items[2], resourcesDict);
29584
32177
  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
32178
  return {
29602
32179
  colorSpace: altSpace,
29603
32180
  colorSpaceLabel: isDevN ? "devn" : "sep",
@@ -29605,12 +32182,9 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
29605
32182
  isSeparation: !isDevN,
29606
32183
  isDeviceN: isDevN,
29607
32184
  separationAltSpace: altSpace,
29608
- separationC0: c0,
29609
- separationC1: c1,
29610
- separationN: sepN,
32185
+ alternateCalibrated: altInfo.calibrated,
29611
32186
  tintFunctionDoc: doc,
29612
- tintFunctionNode: resolved.items[3],
29613
- tintFunctionType
32187
+ tintFunctionNode: resolved.items[3]
29614
32188
  };
29615
32189
  }
29616
32190
  }
@@ -29760,141 +32334,55 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
29760
32334
  const rgba = new Uint8Array(width * height * 4);
29761
32335
  const pixelCount = width * height;
29762
32336
  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
32337
  const alt = csInfo.separationAltSpace ?? "rgb";
29767
32338
  const numCh = Math.max(1, csInfo.components);
29768
32339
  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
32340
  for (let p = 0; p < pixelCount; p++) {
29771
32341
  const chVals = [];
29772
- let wSum = 0;
29773
32342
  for (let ch3 = 0; ch3 < numCh; ch3++) {
29774
32343
  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;
32344
+ chVals.push(remapUnitSampleWithDecode(sRaw, ch3, decodePairs));
29805
32345
  }
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);
32346
+ const outComps = evalShadingFunctionToComponents(
32347
+ csInfo.tintFunctionDoc,
32348
+ csInfo.tintFunctionNode,
32349
+ chVals
32350
+ );
32351
+ if (csInfo.alternateCalibrated) {
32352
+ rgba.set(csInfo.alternateCalibrated.getRgb(outComps, 0), p * 4);
32353
+ } else if (alt === "cmyk") {
32354
+ rgba.set(cmykColorSpace.getRgb([outComps[0] ?? 0, outComps[1] ?? 0, outComps[2] ?? 0, outComps[3] ?? 0], 0), p * 4);
29815
32355
  } 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);
32356
+ const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
29818
32357
  rgba[p * 4] = gByte;
29819
32358
  rgba[p * 4 + 1] = gByte;
29820
32359
  rgba[p * 4 + 2] = gByte;
29821
32360
  } 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);
32361
+ rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
32362
+ rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
32363
+ rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
29828
32364
  }
29829
32365
  rgba[p * 4 + 3] = 255;
29830
32366
  }
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
- };
32367
+ } else if (csInfo.calibrated?.name === "Lab") {
32368
+ const { amin, amax, bmin, bmax } = csInfo.calibrated;
32369
+ const step = bpc === 16 ? 2 : 1;
29838
32370
  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);
32371
+ const L = (rawSamples[p * 3 * step] ?? 0) / 255 * 100;
32372
+ const a = amin + (rawSamples[(p * 3 + 1) * step] ?? 128) / 255 * (amax - amin);
32373
+ const b = bmin + (rawSamples[(p * 3 + 2) * step] ?? 128) / 255 * (bmax - bmin);
32374
+ rgba.set(csInfo.calibrated.getRgb([L, a, b], 0), p * 4);
29864
32375
  rgba[p * 4 + 3] = 255;
29865
32376
  }
29866
32377
  } 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
32378
  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;
32379
+ const rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
32380
+ const gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
32381
+ const bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
32382
+ if (csInfo.calibrated) {
32383
+ rgba.set(csInfo.calibrated.getRgb([rU, gU, bU], 0), p * 4);
32384
+ rgba[p * 4 + 3] = 255;
32385
+ return;
29898
32386
  }
29899
32387
  rgba[p * 4] = Math.round(rU * 255);
29900
32388
  rgba[p * 4 + 1] = Math.round(gU * 255);
@@ -29914,10 +32402,11 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
29914
32402
  }
29915
32403
  } else if (csInfo.colorSpace === "gray") {
29916
32404
  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;
32405
+ const gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
32406
+ if (csInfo.calibrated) {
32407
+ rgba.set(csInfo.calibrated.getRgb([gU], 0), p * 4);
32408
+ rgba[p * 4 + 3] = 255;
32409
+ return;
29921
32410
  }
29922
32411
  const outG = Math.round(Math.max(0, Math.min(1, gU)) * 255);
29923
32412
  rgba[p * 4] = outG;
@@ -29973,9 +32462,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
29973
32462
  const m = remapUnitSampleWithDecode((rawSamples[p * stride + chStep] ?? 0) / 255, 1, decodePairs);
29974
32463
  const y = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 2] ?? 0) / 255, 2, decodePairs);
29975
32464
  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);
32465
+ rgba.set(cmykColorSpace.getRgb([c, m, y, k], 0), p * 4);
29979
32466
  rgba[p * 4 + 3] = 255;
29980
32467
  }
29981
32468
  } else if (csInfo.colorSpace === "index") {
@@ -30013,9 +32500,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
30013
32500
  const m = pal[idx * 4 + 1] / 255;
30014
32501
  const yel = pal[idx * 4 + 2] / 255;
30015
32502
  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);
32503
+ rgba.set(cmykColorSpace.getRgb([c, m, yel, k], 0), p * 4);
30019
32504
  } else {
30020
32505
  rgba[p * 4] = pal[idx * baseComp];
30021
32506
  rgba[p * 4 + 1] = pal[idx * baseComp + 1];
@@ -30909,6 +33394,7 @@ function embedTrueTypeFontInCos(doc, font, usedGlyphs) {
30909
33394
  }
30910
33395
 
30911
33396
  // packages/pdf-ast/src/content/evaluator.ts
33397
+ var cmykColorSpace2 = new DeviceCmykCS();
30912
33398
  function multiplyMatrices(m1, m2) {
30913
33399
  return [
30914
33400
  m1[0] * m2[0] + m1[1] * m2[2],
@@ -31125,193 +33611,7 @@ function resolvePageFonts(doc, resourcesDict) {
31125
33611
  }
31126
33612
  return fonts;
31127
33613
  }
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
- }
33614
+ var postScriptFunctions = /* @__PURE__ */ new WeakMap();
31315
33615
  function evalShadingFunctionToComponents(doc, fnNode, inputs) {
31316
33616
  const inArr = typeof inputs === "number" ? [inputs] : inputs;
31317
33617
  const t = inArr[0] ?? 0;
@@ -31358,35 +33658,50 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
31358
33658
  const decode = getNums("Decode", range);
31359
33659
  const nOut = Math.max(1, Math.floor((decode.length || range.length || 6) / 2));
31360
33660
  const mIn = Math.max(1, size.length);
31361
- let flatGridIndex = 0;
33661
+ const streamBytes = doc.decodeStream(resolved);
33662
+ let vertices = [{ index: 0, weight: 1 }];
31362
33663
  let stride = 1;
31363
33664
  for (let i = 0; i < mIn; i++) {
31364
33665
  const d02 = dom[i * 2] ?? 0;
31365
33666
  const d12 = dom[i * 2 + 1] ?? 1;
31366
- const sMax = Math.max(1, (size[i] ?? 2) - 1);
33667
+ const sMax = Math.max(0, (size[i] ?? 2) - 1);
31367
33668
  const e0 = encode[i * 2] ?? 0;
31368
33669
  const e1 = encode[i * 2 + 1] ?? sMax;
31369
33670
  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;
33671
+ const u = d12 === d02 ? 0 : (x - d02) / (d12 - d02);
33672
+ const e = Math.max(0, Math.min(sMax, e0 + u * (e1 - e0)));
33673
+ const low = Math.floor(e), fraction = e - low;
33674
+ const next = [];
33675
+ for (const vertex of vertices) {
33676
+ const index = vertex.index + low * stride;
33677
+ if (index * nOut * bps < streamBytes.length * 8) next.push({ index, weight: vertex.weight * (1 - fraction) });
33678
+ if (fraction && (index + stride) * nOut * bps < streamBytes.length * 8) {
33679
+ next.push({ index: index + stride, weight: vertex.weight * fraction });
33680
+ }
33681
+ }
33682
+ vertices = next;
31373
33683
  stride *= size[i] ?? 2;
31374
33684
  }
31375
- const streamBytes = doc.decodeStream(resolved);
33685
+ const maxSample = 2 ** bps - 1;
33686
+ const readSample = (index) => {
33687
+ let bitOffset = index * bps, remaining = bps, value = 0;
33688
+ while (remaining > 0) {
33689
+ const bitInByte = bitOffset % 8;
33690
+ const take = Math.min(remaining, 8 - bitInByte);
33691
+ const byte = streamBytes[Math.floor(bitOffset / 8)] ?? 0;
33692
+ value = value * 2 ** take + (byte >> 8 - bitInByte - take & (1 << take) - 1);
33693
+ bitOffset += take;
33694
+ remaining -= take;
33695
+ }
33696
+ return value / maxSample;
33697
+ };
31376
33698
  const out2 = [];
31377
- const maxSample = bps === 16 ? 65535 : 255;
31378
33699
  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;
33700
+ let value = 0;
33701
+ for (const vertex of vertices) value += readSample(vertex.index * nOut + j) * vertex.weight;
31387
33702
  const dec0 = decode[j * 2] ?? 0;
31388
33703
  const dec1 = decode[j * 2 + 1] ?? 1;
31389
- out2.push(dec0 + frac * (dec1 - dec0));
33704
+ out2.push(dec0 + value * (dec1 - dec0));
31390
33705
  }
31391
33706
  return clampRange(out2);
31392
33707
  }
@@ -31396,34 +33711,40 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
31396
33711
  const d12 = dom[i * 2 + 1] ?? 1;
31397
33712
  return Math.max(d02, Math.min(d12, v));
31398
33713
  });
31399
- const tokens = tokenizePostScriptCode(doc.decodeStream(resolved));
31400
- const stackOut = evaluateType4PostScriptTokens(tokens, clampedInputs);
31401
- return clampRange(stackOut);
33714
+ const source = bytesToString3(doc.decodeStream(resolved));
33715
+ let cached = postScriptFunctions.get(resolved);
33716
+ 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])) {
33717
+ cached = { source, domain: dom, range, evaluate: buildPostScriptJsFunction(source, dom, range) };
33718
+ postScriptFunctions.set(resolved, cached);
33719
+ }
33720
+ const output = [];
33721
+ cached.evaluate(clampedInputs, 0, output, 0);
33722
+ return output;
31402
33723
  }
31403
33724
  if (ft === 3) {
31404
33725
  const fnsArr = doc.resolveArray(dictGet(fnDict, "Functions"));
31405
33726
  const bounds = getNums("Bounds", []);
31406
33727
  const encode = getNums("Encode", []);
31407
33728
  if (fnsArr && fnsArr.items.length > 0) {
33729
+ const input = Math.max(dom[0] ?? 0, Math.min(dom[1] ?? 1, t));
31408
33730
  let segIdx = 0;
31409
- while (segIdx < bounds.length && t >= bounds[segIdx]) segIdx++;
33731
+ while (segIdx < bounds.length && input >= bounds[segIdx]) segIdx++;
31410
33732
  segIdx = Math.min(fnsArr.items.length - 1, segIdx);
31411
33733
  const b0 = segIdx === 0 ? dom[0] ?? 0 : bounds[segIdx - 1];
31412
33734
  const b1 = segIdx < bounds.length ? bounds[segIdx] : dom[1] ?? 1;
31413
33735
  const e0 = encode[segIdx * 2] ?? 0;
31414
33736
  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)));
33737
+ const localT = b1 !== b0 ? e0 + (input - b0) / (b1 - b0) * (e1 - e0) : e0;
33738
+ return clampRange(evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], localT));
31417
33739
  }
31418
33740
  }
31419
- const c0 = getNums("C0", [0, 0, 0]);
31420
- const c1 = getNums("C1", [1, 1, 1]);
33741
+ const c0 = getNums("C0", [0]);
33742
+ const c1 = getNums("C1", [1]);
31421
33743
  const nNode = doc.resolve(dictGet(fnDict, "N"));
31422
- const expN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
33744
+ const expN = nNode?.kind === "number" ? nNode.value : 1;
31423
33745
  const d0 = dom[0] ?? 0;
31424
33746
  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);
33747
+ const w = Math.pow(Math.max(d0, Math.min(d1, t)), expN);
31427
33748
  const len = Math.max(c0.length, c1.length);
31428
33749
  const out = [];
31429
33750
  for (let i = 0; i < len; i++) {
@@ -31439,30 +33760,14 @@ function shadingComponentsToRgb(csName, comps) {
31439
33760
  return [v, v, v];
31440
33761
  }
31441
33762
  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))];
33763
+ const rgb2 = cmykColorSpace2.getRgb([comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0, comps[3] ?? 0], 0);
33764
+ return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
31444
33765
  }
31445
33766
  return [comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0];
31446
33767
  }
31447
33768
  function kClamp(v) {
31448
33769
  return Math.max(0, Math.min(1, v));
31449
33770
  }
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
33771
  function getColorSpaceComponentCount(doc, csNode, activeResources, depth = 0) {
31467
33772
  if (!csNode || depth > 4) return 3;
31468
33773
  const resolved = doc ? doc.resolve(csNode) : csNode;
@@ -31519,63 +33824,10 @@ function convertColorSpaceComponentsToRgb(doc, csNode, csNameFallback, comps, ac
31519
33824
  if (resolved.kind === "array" && resolved.items.length > 0 && doc) {
31520
33825
  const familyNode = doc.resolve(resolved.items[0]);
31521
33826
  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);
33827
+ if (family === "CalGray" || family === "CalRGB" || family === "Lab") {
33828
+ const colorSpace = createCalibratedColorSpace(doc, family, resolved.items[1]);
33829
+ const rgb2 = colorSpace.getRgb(comps, 0);
33830
+ return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
31579
33831
  }
31580
33832
  if (family === "ICCBased" && resolved.items[1]) {
31581
33833
  const iccNode = doc.resolve(resolved.items[1]);
@@ -32226,7 +34478,8 @@ function evaluateContentStreamToDisplayList(params) {
32226
34478
  const shDict = shNode?.kind === "dict" ? shNode : shNode?.kind === "stream" ? shNode.dict : void 0;
32227
34479
  const shStream = shNode?.kind === "stream" ? shNode : void 0;
32228
34480
  if (shDict) {
32229
- const targetBox = st.clipRect ?? [0, 0, params.width, params.height];
34481
+ const [originX, originY] = params.origin ?? [0, 0];
34482
+ const targetBox = st.clipRect ?? [originX, originY, originX + params.width, originY + params.height];
32230
34483
  const img = renderShadingDictToImage(
32231
34484
  params.cosDoc,
32232
34485
  shDict,
@@ -32265,12 +34518,10 @@ function evaluateContentStreamToDisplayList(params) {
32265
34518
  } else if (operator === "RG" || operator === "SC" || operator === "SCN") {
32266
34519
  st.strokeColor = resolveScColorOperands(operator === "RG" ? "DeviceRGB" : st.strokeColorSpaceName, ops, activeResources);
32267
34520
  } 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) };
34521
+ st.fillColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
32270
34522
  st.fillPatternName = void 0;
32271
34523
  } 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) };
34524
+ st.strokeColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
32274
34525
  } else if (operator === "gs" && params.cosDoc && activeResources && ops[0]?.kind === "name") {
32275
34526
  const extDict = params.cosDoc.resolveDict(dictGet(activeResources, "ExtGState"));
32276
34527
  const gsDict = extDict ? params.cosDoc.resolveDict(dictGet(extDict, ops[0].decoded)) : void 0;
@@ -32479,7 +34730,7 @@ function evaluateContentStreamToDisplayList(params) {
32479
34730
  stateStack.pop();
32480
34731
  capturedOperations = parentOperations;
32481
34732
  }
32482
- if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
34733
+ if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, isolated, bboxClip: nextClipPaths?.[0], blendMode: st.blendMode, clipRect: st.clipRect } });
32483
34734
  };
32484
34735
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
32485
34736
  for (const node of nodes) {
@@ -33063,6 +35314,7 @@ function evaluateContentStreamToDisplayList(params) {
33063
35314
  pageIndex: params.pageIndex,
33064
35315
  width: params.width,
33065
35316
  height: params.height,
35317
+ ...params.origin ? { origin: params.origin } : {},
33066
35318
  rotation: params.rotation ?? 0,
33067
35319
  glyphs,
33068
35320
  paths,
@@ -35082,7 +37334,7 @@ function prepareStroke(path, scale) {
35082
37334
  }
35083
37335
  return { matrix, width, dashArray, dashPhase };
35084
37336
  }
35085
- function strokeContours(path, pageHeight, scale) {
37337
+ function strokeContours(path, pageHeight, scale, originX = 0, originY = 0) {
35086
37338
  const stroke = prepareStroke(path, scale);
35087
37339
  if (!stroke) return [];
35088
37340
  const inverse = inverseStrokeMatrix(stroke.matrix);
@@ -35094,8 +37346,8 @@ function strokeContours(path, pageHeight, scale) {
35094
37346
  (inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
35095
37347
  ];
35096
37348
  const toScreen = ([x, y]) => [
35097
- (a * x / strokeScale + c * y / strokeScale + e) * scale,
35098
- (pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
37349
+ (a * x / strokeScale + c * y / strokeScale + e - originX) * scale,
37350
+ (pageHeight + originY - b * x / strokeScale - d * y / strokeScale - f) * scale
35099
37351
  ];
35100
37352
  const contours = strokeOutlines(
35101
37353
  segmentsToScreenPaths(path.segments, pageHeight, scale, project),
@@ -35253,18 +37505,34 @@ function renderSoftMask(mask, displayList, scale) {
35253
37505
  }
35254
37506
  return bitmap;
35255
37507
  }
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));
37508
+ function getDisplayListCropBox(list) {
37509
+ const full = [0, 0, list.width, list.height];
37510
+ const box = list.cropBox;
37511
+ if (!box || !box.every(Number.isFinite)) return full;
37512
+ const x0 = Math.max(0, Math.min(box[0], box[2]));
37513
+ const y0 = Math.max(0, Math.min(box[1], box[3]));
37514
+ const x1 = Math.min(list.width, Math.max(box[0], box[2]));
37515
+ const y1 = Math.min(list.height, Math.max(box[1], box[3]));
37516
+ return x1 > x0 && y1 > y0 ? [x0, y0, x1, y1] : full;
37517
+ }
37518
+ function hasCompositingEffects(operations, includeSoftMasks = false) {
37519
+ 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));
37520
+ }
37521
+ function needsGroupBackdrop(group) {
37522
+ return group.isolated === false && !!group.softMask && hasCompositingEffects(group.operations, true);
35258
37523
  }
35259
37524
  function renderDisplayListToBitmap(displayList, options = {}) {
35260
37525
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
35261
37526
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
35262
37527
  const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
35263
37528
  const scale = scaleX;
37529
+ const [originX, originY] = displayList.origin ?? [0, 0];
37530
+ const pageTop = originY + displayList.height;
37531
+ const toScreen = (x, y) => [(x - originX) * scale, (pageTop - y) * scale];
35264
37532
  const width = Math.max(1, Math.round(displayList.width * scale));
35265
37533
  const height = Math.max(1, Math.round(displayList.height * scale));
35266
37534
  const rgba = new Uint8Array(width * height * 4);
35267
- const deferBackground = !options.transparent && hasBlendModes(paintOperations(displayList));
37535
+ const deferBackground = !options.transparent && hasCompositingEffects(paintOperations(displayList));
35268
37536
  const transparent = options.transparent || deferBackground;
35269
37537
  const bg = options.background ?? { r: 1, g: 1, b: 1 };
35270
37538
  const bgR = transparent ? 0 : Math.round(bg.r * 255);
@@ -35289,14 +37557,27 @@ function renderDisplayListToBitmap(displayList, options = {}) {
35289
37557
  let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
35290
37558
  if (operation.kind === "group") {
35291
37559
  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 });
37560
+ let operations = group.operations;
37561
+ if (needsGroupBackdrop(group)) {
37562
+ operations = [{ kind: "image", value: {
37563
+ name: "GroupBackdrop",
37564
+ width,
37565
+ height,
37566
+ decodedRgba: rgba.slice(),
37567
+ matrix: [width / scale, 0, 0, height / scale, originX, pageTop - height / scale],
37568
+ colorSpace: "DeviceRGB",
37569
+ bitsPerComponent: 8,
37570
+ ...group.bboxClip ? { clipPaths: [group.bboxClip] } : {}
37571
+ } }, ...operations];
37572
+ }
37573
+ const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, useCropBox: false, transparent: true });
35293
37574
  for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
35294
37575
  operation = { kind: "image", value: {
35295
37576
  name: "TransparencyGroup",
35296
37577
  width: bitmap.width,
35297
37578
  height: bitmap.height,
35298
37579
  decodedRgba: bitmap.data,
35299
- matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, 0, displayList.height - bitmap.height / scale],
37580
+ matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, originX, pageTop - bitmap.height / scale],
35300
37581
  colorSpace: "DeviceRGB",
35301
37582
  bitsPerComponent: 8,
35302
37583
  blendMode: group.blendMode,
@@ -35310,7 +37591,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
35310
37591
  for (const clip of clips) {
35311
37592
  const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
35312
37593
  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);
37594
+ fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale, toScreen), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
35314
37595
  for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
35315
37596
  }
35316
37597
  cachedClips = clips;
@@ -35357,15 +37638,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
35357
37638
  if (operation.kind === "path") {
35358
37639
  const path = operation.value;
35359
37640
  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;
37641
+ const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale, toScreen), true);
37642
+ 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
37643
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
35363
37644
  }
35364
37645
  if (path.strokeColor) {
35365
37646
  const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
35366
37647
  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;
37648
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale, originX, originY).map((points) => ({ points, closed: true })));
37649
+ 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
37650
  fillEdgesScanline4x4(
35370
37651
  rgba,
35371
37652
  width,
@@ -35388,12 +37669,12 @@ function renderDisplayListToBitmap(displayList, options = {}) {
35388
37669
  if (Math.abs(det) <= 1e-8) continue;
35389
37670
  const cornersPdfX = [e, a + e, a + c + e, c + e];
35390
37671
  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;
37672
+ const cornersPx = cornersPdfX.map((cx) => (cx - originX) * scale);
37673
+ const cornersPy = cornersPdfY.map((cy) => (pageTop - cy) * scale);
37674
+ const clipMinPx = img.clipRect ? Math.floor((img.clipRect[0] - originX) * scale) : 0;
37675
+ const clipMaxPx = img.clipRect ? Math.ceil((img.clipRect[2] - originX) * scale) - 1 : width - 1;
37676
+ const clipMinPy = img.clipRect ? Math.floor((pageTop - img.clipRect[3]) * scale) : 0;
37677
+ const clipMaxPy = img.clipRect ? Math.ceil((pageTop - img.clipRect[1]) * scale) - 1 : height - 1;
35397
37678
  const minPx = Math.max(0, clipMinPx, Math.floor(Math.min(...cornersPx)));
35398
37679
  const maxPx = Math.min(width - 1, clipMaxPx, Math.ceil(Math.max(...cornersPx)) - 1);
35399
37680
  const minPy = Math.max(0, clipMinPy, Math.floor(Math.min(...cornersPy)));
@@ -35410,11 +37691,11 @@ function renderDisplayListToBitmap(displayList, options = {}) {
35410
37691
  const smooth = Math.fround((s1 + s2 + Math.hypot(s1 - s2, 2 * cross)) / 2) <= 1;
35411
37692
  const sample = new Float64Array(4);
35412
37693
  for (let py = minPy; py <= maxPy; py++) {
35413
- const yPdf = displayList.height - (py + 0.5) / scale;
37694
+ const yPdf = pageTop - (py + 0.5) / scale;
35414
37695
  if (img.clipRect && (yPdf < img.clipRect[1] || yPdf > img.clipRect[3])) continue;
35415
37696
  const dyPdf = yPdf - f;
35416
37697
  for (let px = minPx; px <= maxPx; px++) {
35417
- const xPdf = (px + 0.5) / scale;
37698
+ const xPdf = originX + (px + 0.5) / scale;
35418
37699
  if (img.clipRect && (xPdf < img.clipRect[0] || xPdf > img.clipRect[2])) continue;
35419
37700
  const dxPdf = xPdf - e;
35420
37701
  const u = (d * dxPdf - c * dyPdf) / det;
@@ -35475,6 +37756,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
35475
37756
  }
35476
37757
  result = { width: targetW, height: targetH, data: resampled };
35477
37758
  }
37759
+ if (options.useCropBox) {
37760
+ const box = getDisplayListCropBox(displayList);
37761
+ result = cropRgbaBitmap(result, {
37762
+ x: box[0] * scaleX,
37763
+ y: (displayList.height - box[3]) * scaleY,
37764
+ width: (box[2] - box[0]) * scaleX,
37765
+ height: (box[3] - box[1]) * scaleY
37766
+ });
37767
+ }
35478
37768
  result = rotateRgbaBitmapQuarterTurns(result, displayList.rotation ?? 0);
35479
37769
  if (options.cropRect) {
35480
37770
  result = cropRgbaBitmap(result, options.cropRect);
@@ -35503,23 +37793,6 @@ function collectLeavesForRaster(cosDoc, node, out = [], visited = /* @__PURE__ *
35503
37793
  }
35504
37794
  return out;
35505
37795
  }
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
37796
  function renderPdfPageToBitmap(pdfBytes, pageIndex = 0, options) {
35524
37797
  const cos = pdfBytes instanceof Uint8Array ? parseCosDocument(pdfBytes) : pdfBytes;
35525
37798
  const catalog = cos.resolveDict(cos.rootRef);
@@ -35528,35 +37801,7 @@ function renderPdfPageToBitmap(pdfBytes, pageIndex = 0, options) {
35528
37801
  if (!leaf) throw new Error(`Page index ${pageIndex} out of bounds`);
35529
37802
  const resolvedIndex = leaves.indexOf(leaf);
35530
37803
  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;
37804
+ return page.renderToBitmap(options);
35560
37805
  }
35561
37806
  function renderPdfPageToPng(pdfBytes, pageIndex = 0, options) {
35562
37807
  const bmp = renderPdfPageToBitmap(pdfBytes, pageIndex, options);
@@ -35630,7 +37875,7 @@ var PdfPage = class {
35630
37875
  return [n0.value, n1.value, n2.value, n3.value];
35631
37876
  }
35632
37877
  }
35633
- return [0, 0, 612, 792];
37878
+ return key === "MediaBox" ? [0, 0, 612, 792] : this.resolveBox("MediaBox");
35634
37879
  }
35635
37880
  getMediaBox() {
35636
37881
  return this.resolveBox("MediaBox");
@@ -36303,16 +38548,19 @@ var PdfPage = class {
36303
38548
  });
36304
38549
  }
36305
38550
  }
36306
- return evaluateContentStreamToDisplayList({
38551
+ const mediaBox = this.getMediaBox(), cropBox = this.getCropBox();
38552
+ const originX = Math.min(mediaBox[0], mediaBox[2]), originY = Math.min(mediaBox[1], mediaBox[3]);
38553
+ return { ...evaluateContentStreamToDisplayList({
36307
38554
  pageIndex: this.index,
36308
38555
  width,
36309
38556
  height,
38557
+ origin: [originX, originY],
36310
38558
  rotation: this.getRotation(),
36311
38559
  nodes: baseNodes,
36312
38560
  cosDoc: this.cosDoc,
36313
38561
  resourcesDict: evalResourcesDict,
36314
38562
  annotations: extractPageAnnotations(this.cosDoc, this.pageDict)
36315
- });
38563
+ }), cropBox: [cropBox[0] - originX, cropBox[1] - originY, cropBox[2] - originX, cropBox[3] - originY] };
36316
38564
  }
36317
38565
  extractPage(options) {
36318
38566
  const dl = this.evaluateDisplayList();
@@ -36330,10 +38578,10 @@ var PdfPage = class {
36330
38578
  return extractTablesFromDisplayList(this.evaluateDisplayList());
36331
38579
  }
36332
38580
  renderToBitmap(options) {
36333
- return renderDisplayListToBitmap(this.evaluateDisplayList(), options);
38581
+ return renderDisplayListToBitmap(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
36334
38582
  }
36335
38583
  renderToPng(options) {
36336
- return renderDisplayListToPng(this.evaluateDisplayList(), options);
38584
+ return renderDisplayListToPng(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
36337
38585
  }
36338
38586
  };
36339
38587
  function createStandardFontHandle(standardName) {