@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
@@ -22512,6 +22512,2614 @@ var getFontBasicMetrics = getLookupTableFactory(function(t) {
22512
22512
  xHeight: Math.NaN
22513
22513
  };
22514
22514
  });
22515
+ function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
22516
+ const COMPONENTS = 3;
22517
+ alpha01 = alpha01 !== 1 ? 0 : alpha01;
22518
+ const xRatio = w1 / w2;
22519
+ const yRatio = h1 / h2;
22520
+ let newIndex = 0, oldIndex;
22521
+ const xScaled = new Uint16Array(w2);
22522
+ const w1Scanline = w1 * COMPONENTS;
22523
+ for (let i = 0; i < w2; i++) {
22524
+ xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
22525
+ }
22526
+ for (let i = 0; i < h2; i++) {
22527
+ const py = Math.floor(i * yRatio) * w1Scanline;
22528
+ for (let j = 0; j < w2; j++) {
22529
+ oldIndex = py + xScaled[j];
22530
+ dest[newIndex++] = src[oldIndex++];
22531
+ dest[newIndex++] = src[oldIndex++];
22532
+ dest[newIndex++] = src[oldIndex++];
22533
+ newIndex += alpha01;
22534
+ }
22535
+ }
22536
+ }
22537
+ function isDefaultDecodeHelper(decode, expectedLen) {
22538
+ if (!Array.isArray(decode)) {
22539
+ return true;
22540
+ }
22541
+ const decodeLen = decode.length;
22542
+ if (decodeLen < expectedLen) {
22543
+ warn2("Decode map length is too short.");
22544
+ return true;
22545
+ }
22546
+ if (decodeLen > expectedLen) {
22547
+ info("Truncating too long decode map.");
22548
+ decode.length = expectedLen;
22549
+ }
22550
+ return false;
22551
+ }
22552
+ var ColorSpace = class _ColorSpace {
22553
+ static #rgbBuf = new Uint8ClampedArray(3);
22554
+ constructor(name, numComps) {
22555
+ if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _ColorSpace) {
22556
+ unreachable2("Cannot initialize ColorSpace.");
22557
+ }
22558
+ this.name = name;
22559
+ this.numComps = numComps;
22560
+ }
22561
+ /**
22562
+ * Converts the color value to the RGB color. The color components are
22563
+ * located in the src array starting from the srcOffset. Returns the array
22564
+ * of the rgb components, each value ranging from [0,255].
22565
+ */
22566
+ getRgb(src, srcOffset, output = new Uint8ClampedArray(3)) {
22567
+ this.getRgbItem(src, srcOffset, output, 0);
22568
+ return output;
22569
+ }
22570
+ getRgbHex(src, srcOffset) {
22571
+ const buffer = this.getRgb(src, srcOffset, _ColorSpace.#rgbBuf);
22572
+ return Util.makeHexColor(buffer[0], buffer[1], buffer[2]);
22573
+ }
22574
+ /**
22575
+ * Converts the color value to the RGB color, similar to the getRgb method.
22576
+ * The result placed into the dest array starting from the destOffset.
22577
+ */
22578
+ getRgbItem(src, srcOffset, dest, destOffset) {
22579
+ unreachable2("Should not call ColorSpace.getRgbItem");
22580
+ }
22581
+ /**
22582
+ * Converts the specified number of the color values to the RGB colors.
22583
+ * The colors are located in the src array starting from the srcOffset.
22584
+ * The result is placed into the dest array starting from the destOffset.
22585
+ * The src array items shall be in [0,2^bits) range, the dest array items
22586
+ * will be in [0,255] range. alpha01 indicates how many alpha components
22587
+ * there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
22588
+ * array).
22589
+ */
22590
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
22591
+ unreachable2("Should not call ColorSpace.getRgbBuffer");
22592
+ }
22593
+ /**
22594
+ * Converts `count` unscaled colors to RGB, starting at `destOffset`.
22595
+ * Components use the native color-space ranges expected by `getRgbItem`,
22596
+ * and each output has a `3 + alpha01` byte stride.
22597
+ * Subclasses may override this to batch expensive conversions.
22598
+ */
22599
+ getRgbItems(src, count, dest, destOffset, alpha01) {
22600
+ const { numComps } = this;
22601
+ for (let i = 0, srcOffset = 0; i < count; i++, srcOffset += numComps) {
22602
+ this.getRgbItem(src, srcOffset, dest, destOffset);
22603
+ destOffset += 3 + alpha01;
22604
+ }
22605
+ }
22606
+ /**
22607
+ * Returns true if source data will be equal the result/output data.
22608
+ */
22609
+ isPassthrough(bits) {
22610
+ return false;
22611
+ }
22612
+ /**
22613
+ * Refer to the static `ColorSpace.isDefaultDecode` method below.
22614
+ */
22615
+ isDefaultDecode(decode, bpc) {
22616
+ return _ColorSpace.isDefaultDecode(decode, this.numComps);
22617
+ }
22618
+ /**
22619
+ * Fills in the RGB colors in the destination buffer. alpha01 indicates
22620
+ * how many alpha components there are in the dest array; it will be either
22621
+ * 0 (RGB array) or 1 (RGBA array).
22622
+ */
22623
+ fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {
22624
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22625
+ assert2(
22626
+ dest instanceof Uint8ClampedArray,
22627
+ 'ColorSpace.fillRgb: Unsupported "dest" type.'
22628
+ );
22629
+ }
22630
+ const count = originalWidth * originalHeight;
22631
+ let rgbBuf = null;
22632
+ const numComponentColors = 1 << bpc;
22633
+ const needsResizing = originalHeight !== height || originalWidth !== width;
22634
+ if (this.isPassthrough(bpc)) {
22635
+ rgbBuf = comps;
22636
+ } else if (this.numComps === 1 && count > numComponentColors && this.name !== "DeviceGray" && this.name !== "DeviceRGB") {
22637
+ const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);
22638
+ for (let i = 0; i < numComponentColors; i++) {
22639
+ allColors[i] = i;
22640
+ }
22641
+ const colorMap = new Uint8ClampedArray(numComponentColors * 3);
22642
+ this.getRgbBuffer(
22643
+ allColors,
22644
+ 0,
22645
+ numComponentColors,
22646
+ colorMap,
22647
+ 0,
22648
+ bpc,
22649
+ /* alpha01 = */
22650
+ 0
22651
+ );
22652
+ if (!needsResizing) {
22653
+ let destPos = 0;
22654
+ for (let i = 0; i < count; ++i) {
22655
+ const key = comps[i] * 3;
22656
+ dest[destPos++] = colorMap[key];
22657
+ dest[destPos++] = colorMap[key + 1];
22658
+ dest[destPos++] = colorMap[key + 2];
22659
+ destPos += alpha01;
22660
+ }
22661
+ } else {
22662
+ rgbBuf = new Uint8Array(count * 3);
22663
+ let rgbPos = 0;
22664
+ for (let i = 0; i < count; ++i) {
22665
+ const key = comps[i] * 3;
22666
+ rgbBuf[rgbPos++] = colorMap[key];
22667
+ rgbBuf[rgbPos++] = colorMap[key + 1];
22668
+ rgbBuf[rgbPos++] = colorMap[key + 2];
22669
+ }
22670
+ }
22671
+ } else if (!needsResizing) {
22672
+ this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);
22673
+ } else {
22674
+ rgbBuf = new Uint8ClampedArray(count * 3);
22675
+ this.getRgbBuffer(
22676
+ comps,
22677
+ 0,
22678
+ count,
22679
+ rgbBuf,
22680
+ 0,
22681
+ bpc,
22682
+ /* alpha01 = */
22683
+ 0
22684
+ );
22685
+ }
22686
+ if (rgbBuf) {
22687
+ if (needsResizing) {
22688
+ resizeRgbImage(
22689
+ rgbBuf,
22690
+ dest,
22691
+ originalWidth,
22692
+ originalHeight,
22693
+ width,
22694
+ height,
22695
+ alpha01
22696
+ );
22697
+ } else {
22698
+ let destPos = 0, rgbPos = 0;
22699
+ for (let i = 0, ii = width * actualHeight; i < ii; i++) {
22700
+ dest[destPos++] = rgbBuf[rgbPos++];
22701
+ dest[destPos++] = rgbBuf[rgbPos++];
22702
+ dest[destPos++] = rgbBuf[rgbPos++];
22703
+ destPos += alpha01;
22704
+ }
22705
+ }
22706
+ }
22707
+ }
22708
+ /**
22709
+ * True if the colorspace has components in the default range of [0, 1].
22710
+ * This should be true for all colorspaces except for lab color spaces
22711
+ * which are [0,100], [-128, 127], [-128, 127].
22712
+ */
22713
+ get usesZeroToOneRange() {
22714
+ return shadow2(this, "usesZeroToOneRange", true);
22715
+ }
22716
+ /**
22717
+ * Checks if a decode map matches the default decode map for a color space.
22718
+ * This handles the general decode maps where there are two values per
22719
+ * component, e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
22720
+ * This does not handle Lab, Indexed, or Pattern decode maps since they are
22721
+ * slightly different.
22722
+ * @param {Array} decode - Decode map (usually from an image).
22723
+ * @param {number} numComps - Number of components the color space has.
22724
+ */
22725
+ static isDefaultDecode(decode, numComps) {
22726
+ if (isDefaultDecodeHelper(decode, numComps * 2)) {
22727
+ return true;
22728
+ }
22729
+ for (let i = 0, ii = decode.length; i < ii; i += 2) {
22730
+ if (decode[i] !== 0 || decode[i + 1] !== 1) {
22731
+ return false;
22732
+ }
22733
+ }
22734
+ return true;
22735
+ }
22736
+ };
22737
+ var DeviceCmykCS = class extends ColorSpace {
22738
+ constructor() {
22739
+ super("DeviceCMYK", 4);
22740
+ }
22741
+ // The coefficients below was found using numerical analysis: the method of
22742
+ // steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
22743
+ // where color_value is the tabular value from the table of sampled RGB colors
22744
+ // from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
22745
+ // CMYK color conversion using the estimation below:
22746
+ // f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
22747
+ #toRgb(src, srcOffset, srcScale, dest, destOffset) {
22748
+ const c = src[srcOffset] * srcScale;
22749
+ const m = src[srcOffset + 1] * srcScale;
22750
+ const y = src[srcOffset + 2] * srcScale;
22751
+ const k = src[srcOffset + 3] * srcScale;
22752
+ 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);
22753
+ 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);
22754
+ 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);
22755
+ }
22756
+ getRgbItem(src, srcOffset, dest, destOffset) {
22757
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22758
+ assert2(
22759
+ dest instanceof Uint8ClampedArray,
22760
+ 'DeviceCmykCS.getRgbItem: Unsupported "dest" type.'
22761
+ );
22762
+ }
22763
+ this.#toRgb(src, srcOffset, 1, dest, destOffset);
22764
+ }
22765
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
22766
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22767
+ assert2(
22768
+ dest instanceof Uint8ClampedArray,
22769
+ 'DeviceCmykCS.getRgbBuffer: Unsupported "dest" type.'
22770
+ );
22771
+ }
22772
+ const scale = 1 / ((1 << bits) - 1);
22773
+ for (let i = 0; i < count; i++) {
22774
+ this.#toRgb(src, srcOffset, scale, dest, destOffset);
22775
+ srcOffset += 4;
22776
+ destOffset += 3 + alpha01;
22777
+ }
22778
+ }
22779
+ };
22780
+ var CalGrayCS = class extends ColorSpace {
22781
+ constructor(whitePoint, blackPoint, gamma) {
22782
+ super("CalGray", 1);
22783
+ if (!whitePoint) {
22784
+ throw new FormatError(
22785
+ "WhitePoint missing - required for color space CalGray"
22786
+ );
22787
+ }
22788
+ [this.XW, this.YW, this.ZW] = whitePoint;
22789
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
22790
+ this.G = gamma || 1;
22791
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
22792
+ throw new FormatError(
22793
+ `Invalid WhitePoint components for ${this.name}, no fallback available`
22794
+ );
22795
+ }
22796
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
22797
+ info(`Invalid BlackPoint for ${this.name}, falling back to default.`);
22798
+ this.XB = this.YB = this.ZB = 0;
22799
+ }
22800
+ if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
22801
+ warn2(
22802
+ `${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ZB: ${this.ZB}, only default values are supported.`
22803
+ );
22804
+ }
22805
+ if (this.G < 1) {
22806
+ info(
22807
+ `Invalid Gamma: ${this.G} for ${this.name}, falling back to default.`
22808
+ );
22809
+ this.G = 1;
22810
+ }
22811
+ }
22812
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
22813
+ const A = src[srcOffset] * scale;
22814
+ const AG = A ** this.G;
22815
+ const L = this.YW * AG;
22816
+ const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0);
22817
+ dest[destOffset] = val;
22818
+ dest[destOffset + 1] = val;
22819
+ dest[destOffset + 2] = val;
22820
+ }
22821
+ getRgbItem(src, srcOffset, dest, destOffset) {
22822
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22823
+ assert2(
22824
+ dest instanceof Uint8ClampedArray,
22825
+ 'CalGrayCS.getRgbItem: Unsupported "dest" type.'
22826
+ );
22827
+ }
22828
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
22829
+ }
22830
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
22831
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22832
+ assert2(
22833
+ dest instanceof Uint8ClampedArray,
22834
+ 'CalGrayCS.getRgbBuffer: Unsupported "dest" type.'
22835
+ );
22836
+ }
22837
+ const scale = 1 / ((1 << bits) - 1);
22838
+ for (let i = 0; i < count; ++i) {
22839
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
22840
+ srcOffset += 1;
22841
+ destOffset += 3 + alpha01;
22842
+ }
22843
+ }
22844
+ };
22845
+ var CalRGBCS = class _CalRGBCS extends ColorSpace {
22846
+ // See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these
22847
+ // matrices.
22848
+ // prettier-ignore
22849
+ static #BRADFORD_SCALE_MATRIX = new Float32Array([
22850
+ 0.8951,
22851
+ 0.2664,
22852
+ -0.1614,
22853
+ -0.7502,
22854
+ 1.7135,
22855
+ 0.0367,
22856
+ 0.0389,
22857
+ -0.0685,
22858
+ 1.0296
22859
+ ]);
22860
+ // prettier-ignore
22861
+ static #BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([
22862
+ 0.9869929,
22863
+ -0.1470543,
22864
+ 0.1599627,
22865
+ 0.4323053,
22866
+ 0.5183603,
22867
+ 0.0492912,
22868
+ -85287e-7,
22869
+ 0.0400428,
22870
+ 0.9684867
22871
+ ]);
22872
+ // See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html.
22873
+ // prettier-ignore
22874
+ static #SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([
22875
+ 3.2404542,
22876
+ -1.5371385,
22877
+ -0.4985314,
22878
+ -0.969266,
22879
+ 1.8760108,
22880
+ 0.041556,
22881
+ 0.0556434,
22882
+ -0.2040259,
22883
+ 1.0572252
22884
+ ]);
22885
+ static #FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);
22886
+ static #tempNormalizeMatrix = new Float32Array(3);
22887
+ static #tempConvertMatrix1 = new Float32Array(3);
22888
+ static #tempConvertMatrix2 = new Float32Array(3);
22889
+ static #DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8;
22890
+ constructor(whitePoint, blackPoint, gamma, matrix) {
22891
+ super("CalRGB", 3);
22892
+ if (!whitePoint) {
22893
+ throw new FormatError(
22894
+ "WhitePoint missing - required for color space CalRGB"
22895
+ );
22896
+ }
22897
+ const [XW, YW, ZW] = this.whitePoint = whitePoint;
22898
+ const [XB, YB, ZB] = this.blackPoint = blackPoint || new Float32Array(3);
22899
+ [this.GR, this.GG, this.GB] = gamma || new Float32Array([1, 1, 1]);
22900
+ [
22901
+ this.MXA,
22902
+ this.MYA,
22903
+ this.MZA,
22904
+ this.MXB,
22905
+ this.MYB,
22906
+ this.MZB,
22907
+ this.MXC,
22908
+ this.MYC,
22909
+ this.MZC
22910
+ ] = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
22911
+ if (XW < 0 || ZW < 0 || YW !== 1) {
22912
+ throw new FormatError(
22913
+ `Invalid WhitePoint components for ${this.name}, no fallback available`
22914
+ );
22915
+ }
22916
+ if (XB < 0 || YB < 0 || ZB < 0) {
22917
+ info(
22918
+ `Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], falling back to default.`
22919
+ );
22920
+ this.blackPoint = new Float32Array(3);
22921
+ }
22922
+ if (this.GR < 0 || this.GG < 0 || this.GB < 0) {
22923
+ info(
22924
+ `Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ${this.name}, falling back to default.`
22925
+ );
22926
+ this.GR = this.GG = this.GB = 1;
22927
+ }
22928
+ }
22929
+ #matrixProduct(a, b, result) {
22930
+ result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
22931
+ result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
22932
+ result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
22933
+ }
22934
+ #toFlat(sourceWhitePoint, LMS, result) {
22935
+ result[0] = LMS[0] * 1 / sourceWhitePoint[0];
22936
+ result[1] = LMS[1] * 1 / sourceWhitePoint[1];
22937
+ result[2] = LMS[2] * 1 / sourceWhitePoint[2];
22938
+ }
22939
+ #toD65(sourceWhitePoint, LMS, result) {
22940
+ const D65X = 0.95047;
22941
+ const D65Y = 1;
22942
+ const D65Z = 1.08883;
22943
+ result[0] = LMS[0] * D65X / sourceWhitePoint[0];
22944
+ result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
22945
+ result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
22946
+ }
22947
+ #sRGBTransferFunction(color) {
22948
+ if (color <= 31308e-7) {
22949
+ return MathClamp(12.92 * color, 0, 1);
22950
+ }
22951
+ return color >= 0.99554525 ? 1 : MathClamp((1 + 0.055) * color ** (1 / 2.4) - 0.055, 0, 1);
22952
+ }
22953
+ #decodeL(L) {
22954
+ if (L < 0) {
22955
+ return -this.#decodeL(-L);
22956
+ }
22957
+ return L > 8 ? ((L + 16) / 116) ** 3 : L * _CalRGBCS.#DECODE_L_CONSTANT;
22958
+ }
22959
+ #compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
22960
+ if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {
22961
+ result[0] = XYZ_Flat[0];
22962
+ result[1] = XYZ_Flat[1];
22963
+ result[2] = XYZ_Flat[2];
22964
+ return;
22965
+ }
22966
+ const zeroDecodeL = this.#decodeL(0);
22967
+ const X_DST = zeroDecodeL;
22968
+ const X_SRC = this.#decodeL(sourceBlackPoint[0]);
22969
+ const Y_DST = zeroDecodeL;
22970
+ const Y_SRC = this.#decodeL(sourceBlackPoint[1]);
22971
+ const Z_DST = zeroDecodeL;
22972
+ const Z_SRC = this.#decodeL(sourceBlackPoint[2]);
22973
+ const X_Scale = (1 - X_DST) / (1 - X_SRC);
22974
+ const X_Offset = 1 - X_Scale;
22975
+ const Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
22976
+ const Y_Offset = 1 - Y_Scale;
22977
+ const Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
22978
+ const Z_Offset = 1 - Z_Scale;
22979
+ result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
22980
+ result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
22981
+ result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
22982
+ }
22983
+ #normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
22984
+ if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
22985
+ result[0] = XYZ_In[0];
22986
+ result[1] = XYZ_In[1];
22987
+ result[2] = XYZ_In[2];
22988
+ return;
22989
+ }
22990
+ const LMS = result;
22991
+ this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
22992
+ const LMS_Flat = _CalRGBCS.#tempNormalizeMatrix;
22993
+ this.#toFlat(sourceWhitePoint, LMS, LMS_Flat);
22994
+ this.#matrixProduct(
22995
+ _CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
22996
+ LMS_Flat,
22997
+ result
22998
+ );
22999
+ }
23000
+ #normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
23001
+ const LMS = result;
23002
+ this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
23003
+ const LMS_D65 = _CalRGBCS.#tempNormalizeMatrix;
23004
+ this.#toD65(sourceWhitePoint, LMS, LMS_D65);
23005
+ this.#matrixProduct(
23006
+ _CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
23007
+ LMS_D65,
23008
+ result
23009
+ );
23010
+ }
23011
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
23012
+ const A = MathClamp(src[srcOffset] * scale, 0, 1);
23013
+ const B = MathClamp(src[srcOffset + 1] * scale, 0, 1);
23014
+ const C = MathClamp(src[srcOffset + 2] * scale, 0, 1);
23015
+ const AGR = A === 1 ? 1 : A ** this.GR;
23016
+ const BGG = B === 1 ? 1 : B ** this.GG;
23017
+ const CGB = C === 1 ? 1 : C ** this.GB;
23018
+ const X = this.MXA * AGR + this.MXB * BGG + this.MXC * CGB;
23019
+ const Y = this.MYA * AGR + this.MYB * BGG + this.MYC * CGB;
23020
+ const Z = this.MZA * AGR + this.MZB * BGG + this.MZC * CGB;
23021
+ const XYZ = _CalRGBCS.#tempConvertMatrix1;
23022
+ XYZ[0] = X;
23023
+ XYZ[1] = Y;
23024
+ XYZ[2] = Z;
23025
+ const XYZ_Flat = _CalRGBCS.#tempConvertMatrix2;
23026
+ this.#normalizeWhitePointToFlat(this.whitePoint, XYZ, XYZ_Flat);
23027
+ const XYZ_Black = _CalRGBCS.#tempConvertMatrix1;
23028
+ this.#compensateBlackPoint(this.blackPoint, XYZ_Flat, XYZ_Black);
23029
+ const XYZ_D65 = _CalRGBCS.#tempConvertMatrix2;
23030
+ this.#normalizeWhitePointToD65(
23031
+ _CalRGBCS.#FLAT_WHITEPOINT_MATRIX,
23032
+ XYZ_Black,
23033
+ XYZ_D65
23034
+ );
23035
+ const SRGB = _CalRGBCS.#tempConvertMatrix1;
23036
+ this.#matrixProduct(_CalRGBCS.#SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
23037
+ dest[destOffset] = this.#sRGBTransferFunction(SRGB[0]) * 255;
23038
+ dest[destOffset + 1] = this.#sRGBTransferFunction(SRGB[1]) * 255;
23039
+ dest[destOffset + 2] = this.#sRGBTransferFunction(SRGB[2]) * 255;
23040
+ }
23041
+ getRgbItem(src, srcOffset, dest, destOffset) {
23042
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23043
+ assert2(
23044
+ dest instanceof Uint8ClampedArray,
23045
+ 'CalRGBCS.getRgbItem: Unsupported "dest" type.'
23046
+ );
23047
+ }
23048
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
23049
+ }
23050
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
23051
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23052
+ assert2(
23053
+ dest instanceof Uint8ClampedArray,
23054
+ 'CalRGBCS.getRgbBuffer: Unsupported "dest" type.'
23055
+ );
23056
+ }
23057
+ const scale = 1 / ((1 << bits) - 1);
23058
+ for (let i = 0; i < count; ++i) {
23059
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
23060
+ srcOffset += 3;
23061
+ destOffset += 3 + alpha01;
23062
+ }
23063
+ }
23064
+ };
23065
+ var LabCS = class extends ColorSpace {
23066
+ constructor(whitePoint, blackPoint, range) {
23067
+ super("Lab", 3);
23068
+ if (!whitePoint) {
23069
+ throw new FormatError(
23070
+ "WhitePoint missing - required for color space Lab"
23071
+ );
23072
+ }
23073
+ [this.XW, this.YW, this.ZW] = whitePoint;
23074
+ [this.amin, this.amax, this.bmin, this.bmax] = range || [
23075
+ -100,
23076
+ 100,
23077
+ -100,
23078
+ 100
23079
+ ];
23080
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
23081
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
23082
+ throw new FormatError(
23083
+ "Invalid WhitePoint components, no fallback available"
23084
+ );
23085
+ }
23086
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
23087
+ info("Invalid BlackPoint, falling back to default");
23088
+ this.XB = this.YB = this.ZB = 0;
23089
+ }
23090
+ if (this.amin > this.amax || this.bmin > this.bmax) {
23091
+ info("Invalid Range, falling back to defaults");
23092
+ this.amin = -100;
23093
+ this.amax = 100;
23094
+ this.bmin = -100;
23095
+ this.bmax = 100;
23096
+ }
23097
+ }
23098
+ // Function g(x) from spec
23099
+ #fn_g(x) {
23100
+ return x >= 6 / 29 ? x ** 3 : 108 / 841 * (x - 4 / 29);
23101
+ }
23102
+ #decode(value, high1, low2, high2) {
23103
+ return low2 + value * (high2 - low2) / high1;
23104
+ }
23105
+ // If decoding is needed maxVal should be 2^bits per component - 1.
23106
+ #toRgb(src, srcOffset, maxVal, dest, destOffset) {
23107
+ let Ls = src[srcOffset];
23108
+ let as = src[srcOffset + 1];
23109
+ let bs = src[srcOffset + 2];
23110
+ if (maxVal !== false) {
23111
+ Ls = this.#decode(Ls, maxVal, 0, 100);
23112
+ as = this.#decode(as, maxVal, this.amin, this.amax);
23113
+ bs = this.#decode(bs, maxVal, this.bmin, this.bmax);
23114
+ }
23115
+ if (as > this.amax) {
23116
+ as = this.amax;
23117
+ } else if (as < this.amin) {
23118
+ as = this.amin;
23119
+ }
23120
+ if (bs > this.bmax) {
23121
+ bs = this.bmax;
23122
+ } else if (bs < this.bmin) {
23123
+ bs = this.bmin;
23124
+ }
23125
+ const M = (Ls + 16) / 116;
23126
+ const L = M + as / 500;
23127
+ const N = M - bs / 200;
23128
+ const X = this.XW * this.#fn_g(L);
23129
+ const Y = this.YW * this.#fn_g(M);
23130
+ const Z = this.ZW * this.#fn_g(N);
23131
+ let r, g, b;
23132
+ if (this.ZW < 1) {
23133
+ r = X * 3.1339 + Y * -1.617 + Z * -0.4906;
23134
+ g = X * -0.9785 + Y * 1.916 + Z * 0.0333;
23135
+ b = X * 0.072 + Y * -0.229 + Z * 1.4057;
23136
+ } else {
23137
+ r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
23138
+ g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
23139
+ b = X * 0.0557 + Y * -0.204 + Z * 1.057;
23140
+ }
23141
+ dest[destOffset] = Math.sqrt(r) * 255;
23142
+ dest[destOffset + 1] = Math.sqrt(g) * 255;
23143
+ dest[destOffset + 2] = Math.sqrt(b) * 255;
23144
+ }
23145
+ getRgbItem(src, srcOffset, dest, destOffset) {
23146
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23147
+ assert2(
23148
+ dest instanceof Uint8ClampedArray,
23149
+ 'LabCS.getRgbItem: Unsupported "dest" type.'
23150
+ );
23151
+ }
23152
+ this.#toRgb(src, srcOffset, false, dest, destOffset);
23153
+ }
23154
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
23155
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23156
+ assert2(
23157
+ dest instanceof Uint8ClampedArray,
23158
+ 'LabCS.getRgbBuffer: Unsupported "dest" type.'
23159
+ );
23160
+ }
23161
+ const maxVal = (1 << bits) - 1;
23162
+ for (let i = 0; i < count; i++) {
23163
+ this.#toRgb(src, srcOffset, maxVal, dest, destOffset);
23164
+ srcOffset += 3;
23165
+ destOffset += 3 + alpha01;
23166
+ }
23167
+ }
23168
+ isDefaultDecode(decode, bpc) {
23169
+ return true;
23170
+ }
23171
+ get usesZeroToOneRange() {
23172
+ return shadow2(this, "usesZeroToOneRange", false);
23173
+ }
23174
+ };
23175
+ var TOKEN = {
23176
+ // Structural tokens — not keyword operators
23177
+ number: 0,
23178
+ lbrace: 1,
23179
+ rbrace: 2,
23180
+ // Boolean literals
23181
+ true: 3,
23182
+ false: 4,
23183
+ // Arithmetic binary operators
23184
+ add: 5,
23185
+ sub: 6,
23186
+ mul: 7,
23187
+ div: 8,
23188
+ idiv: 9,
23189
+ mod: 10,
23190
+ exp: 11,
23191
+ // Comparison binary operators
23192
+ eq: 12,
23193
+ ne: 13,
23194
+ gt: 14,
23195
+ ge: 15,
23196
+ lt: 16,
23197
+ le: 17,
23198
+ // Bitwise / boolean binary operators
23199
+ and: 18,
23200
+ or: 19,
23201
+ xor: 20,
23202
+ bitshift: 21,
23203
+ // Unary arithmetic operators
23204
+ abs: 22,
23205
+ neg: 23,
23206
+ ceiling: 24,
23207
+ floor: 25,
23208
+ round: 26,
23209
+ truncate: 27,
23210
+ // Unary boolean / bitwise operator
23211
+ not: 28,
23212
+ // Mathematical functions — unary
23213
+ sqrt: 29,
23214
+ sin: 30,
23215
+ cos: 31,
23216
+ ln: 32,
23217
+ log: 33,
23218
+ // Mathematical function — binary
23219
+ atan: 34,
23220
+ // Type conversion operators
23221
+ cvi: 35,
23222
+ cvr: 36,
23223
+ // Stack operators
23224
+ dup: 37,
23225
+ exch: 38,
23226
+ pop: 39,
23227
+ copy: 40,
23228
+ index: 41,
23229
+ roll: 42,
23230
+ // Control flow
23231
+ if: 43,
23232
+ ifelse: 44,
23233
+ // End of input
23234
+ eof: 45,
23235
+ // Synthetic: produced by the optimizer, never emitted by the lexer.
23236
+ min: 46,
23237
+ max: 47
23238
+ };
23239
+ var Token = class {
23240
+ constructor(id, value = null) {
23241
+ this.id = id;
23242
+ this.value = value;
23243
+ }
23244
+ };
23245
+ var Lexer = class _Lexer {
23246
+ // Singletons for every non-number token, built lazily on first construction.
23247
+ // Keyword operator tokens carry their name as `value`; structural tokens
23248
+ // (lbrace, rbrace, eof) carry null.
23249
+ static #singletons = null;
23250
+ static #operatorSingletons = null;
23251
+ static #initSingletons() {
23252
+ const singletons = /* @__PURE__ */ Object.create(null);
23253
+ const operatorSingletons = /* @__PURE__ */ Object.create(null);
23254
+ for (const [name, id] of Object.entries(TOKEN)) {
23255
+ if (name === "number") {
23256
+ continue;
23257
+ }
23258
+ const isOperator = id >= TOKEN.true && id <= TOKEN.ifelse;
23259
+ const token = new Token(id, isOperator ? name : null);
23260
+ singletons[name] = token;
23261
+ if (isOperator) {
23262
+ operatorSingletons[name] = token;
23263
+ }
23264
+ }
23265
+ this.#singletons = singletons;
23266
+ this.#operatorSingletons = operatorSingletons;
23267
+ }
23268
+ constructor(data) {
23269
+ if (!_Lexer.#singletons) {
23270
+ _Lexer.#initSingletons();
23271
+ }
23272
+ this.data = data;
23273
+ this.pos = 0;
23274
+ this.len = data.length;
23275
+ this._numberPattern = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/iy;
23276
+ this._identifierPattern = /[a-z]+/y;
23277
+ }
23278
+ // Skip a % comment, advancing past the next \n or \r (or to EOF).
23279
+ _skipComment() {
23280
+ const lf = this.data.indexOf("\n", this.pos);
23281
+ const cr = this.data.indexOf("\r", this.pos);
23282
+ const eol = Math.min(lf < 0 ? this.len : lf, cr < 0 ? this.len : cr);
23283
+ this.pos = Math.min(eol + 1, this.len);
23284
+ }
23285
+ _getNumber() {
23286
+ this._numberPattern.lastIndex = this.pos;
23287
+ const match = this._numberPattern.exec(this.data);
23288
+ if (!match) {
23289
+ return new Token(TOKEN.number, 0);
23290
+ }
23291
+ const number = parseFloat(match[0]);
23292
+ if (!Number.isFinite(number)) {
23293
+ return new Token(TOKEN.number, 0);
23294
+ }
23295
+ this.pos = this._numberPattern.lastIndex;
23296
+ return new Token(TOKEN.number, number);
23297
+ }
23298
+ _getOperator() {
23299
+ this._identifierPattern.lastIndex = this.pos;
23300
+ const match = this._identifierPattern.exec(this.data);
23301
+ if (!match) {
23302
+ return new Token(TOKEN.number, 0);
23303
+ }
23304
+ this.pos = this._identifierPattern.lastIndex;
23305
+ const op = match[0];
23306
+ const token = _Lexer.#operatorSingletons[op];
23307
+ return token ?? new Token(TOKEN.number, 0);
23308
+ }
23309
+ // Return the next token, or Lexer.#singletons.eof at end of input.
23310
+ next() {
23311
+ while (this.pos < this.len) {
23312
+ const ch3 = this.data.charCodeAt(this.pos++);
23313
+ switch (ch3) {
23314
+ // PostScript white-space characters (PDF32000 §7.2.2)
23315
+ case 0:
23316
+ case 9:
23317
+ case 10:
23318
+ case 12:
23319
+ case 13:
23320
+ case 32:
23321
+ break;
23322
+ case 37:
23323
+ this._skipComment();
23324
+ break;
23325
+ case 123:
23326
+ return _Lexer.#singletons.lbrace;
23327
+ case 125:
23328
+ return _Lexer.#singletons.rbrace;
23329
+ case 43:
23330
+ case 45:
23331
+ this.pos--;
23332
+ return this._getNumber();
23333
+ case 46:
23334
+ this.pos--;
23335
+ return this._getNumber();
23336
+ default:
23337
+ if (ch3 >= 48 && ch3 <= 57) {
23338
+ this.pos--;
23339
+ return this._getNumber();
23340
+ }
23341
+ if (ch3 >= 97 && ch3 <= 122) {
23342
+ this.pos--;
23343
+ return this._getOperator();
23344
+ }
23345
+ return new Token(TOKEN.number, 0);
23346
+ }
23347
+ }
23348
+ return _Lexer.#singletons.eof;
23349
+ }
23350
+ };
23351
+ var PS_VALUE_TYPE = {
23352
+ numeric: 0,
23353
+ // known to be a number (f64 in Wasm)
23354
+ boolean: 1,
23355
+ // known to be a boolean (0.0 = false, 1.0 = true in f64)
23356
+ unknown: 2
23357
+ // indeterminate at compile time
23358
+ };
23359
+ var PS_NODE = {
23360
+ // Parser AST node types (produced by Parser / parsePostScriptFunction)
23361
+ program: 0,
23362
+ block: 1,
23363
+ number: 2,
23364
+ operator: 3,
23365
+ if: 4,
23366
+ ifelse: 5,
23367
+ // Tree AST node types (produced by PSStackToTree)
23368
+ arg: 6,
23369
+ const: 7,
23370
+ unary: 8,
23371
+ binary: 9,
23372
+ ternary: 10
23373
+ };
23374
+ var PsNode = class {
23375
+ constructor(type) {
23376
+ this.type = type;
23377
+ }
23378
+ };
23379
+ var PsProgram = class extends PsNode {
23380
+ constructor(body) {
23381
+ super(PS_NODE.program);
23382
+ this.body = body;
23383
+ }
23384
+ };
23385
+ var PsBlock = class extends PsNode {
23386
+ constructor(instructions) {
23387
+ super(PS_NODE.block);
23388
+ this.instructions = instructions;
23389
+ }
23390
+ };
23391
+ var PsNumber = class extends PsNode {
23392
+ /** @param {number} value */
23393
+ constructor(value) {
23394
+ super(PS_NODE.number);
23395
+ this.value = value;
23396
+ }
23397
+ };
23398
+ var PsOperator = class extends PsNode {
23399
+ /** @param {number} op — one of the TOKEN.* constants from lexer.js */
23400
+ constructor(op) {
23401
+ super(PS_NODE.operator);
23402
+ this.op = op;
23403
+ }
23404
+ };
23405
+ var PsIf = class extends PsNode {
23406
+ /** @param {PsBlock} then */
23407
+ constructor(then) {
23408
+ super(PS_NODE.if);
23409
+ this.then = then;
23410
+ }
23411
+ };
23412
+ var PsIfElse = class extends PsNode {
23413
+ /**
23414
+ * @param {PsBlock} then
23415
+ * @param {PsBlock} otherwise
23416
+ */
23417
+ constructor(then, otherwise) {
23418
+ super(PS_NODE.ifelse);
23419
+ this.then = then;
23420
+ this.otherwise = otherwise;
23421
+ }
23422
+ };
23423
+ var PsArgNode = class extends PsNode {
23424
+ /** @param {number} index */
23425
+ constructor(index) {
23426
+ super(PS_NODE.arg);
23427
+ this.index = index;
23428
+ this.valueType = PS_VALUE_TYPE.numeric;
23429
+ }
23430
+ };
23431
+ var PsConstNode = class extends PsNode {
23432
+ /** @param {number|boolean} value */
23433
+ constructor(value) {
23434
+ super(PS_NODE.const);
23435
+ this.value = value;
23436
+ this.valueType = typeof value === "boolean" ? PS_VALUE_TYPE.boolean : PS_VALUE_TYPE.numeric;
23437
+ }
23438
+ };
23439
+ var PsUnaryNode = class extends PsNode {
23440
+ /**
23441
+ * @param {number} op — TOKEN.* constant
23442
+ * @param {PsNode} operand
23443
+ * @param {number} [valueType]
23444
+ */
23445
+ constructor(op, operand, valueType = PS_VALUE_TYPE.unknown) {
23446
+ super(PS_NODE.unary);
23447
+ this.op = op;
23448
+ this.operand = operand;
23449
+ this.valueType = valueType;
23450
+ }
23451
+ };
23452
+ var PsBinaryNode = class extends PsNode {
23453
+ /**
23454
+ * @param {number} op — TOKEN.* constant
23455
+ * @param {PsNode} first — was on top of stack
23456
+ * @param {PsNode} second — was below top
23457
+ * @param {number} [valueType]
23458
+ */
23459
+ constructor(op, first, second, valueType = PS_VALUE_TYPE.unknown) {
23460
+ super(PS_NODE.binary);
23461
+ this.op = op;
23462
+ this.first = first;
23463
+ this.second = second;
23464
+ this.valueType = valueType;
23465
+ }
23466
+ };
23467
+ var PsTernaryNode = class extends PsNode {
23468
+ /**
23469
+ * @param {PsNode} cond
23470
+ * @param {PsNode} then
23471
+ * @param {PsNode} otherwise
23472
+ * @param {number} [valueType]
23473
+ */
23474
+ constructor(cond, then, otherwise, valueType = PS_VALUE_TYPE.unknown) {
23475
+ super(PS_NODE.ternary);
23476
+ this.cond = cond;
23477
+ this.then = then;
23478
+ this.otherwise = otherwise;
23479
+ this.valueType = valueType;
23480
+ }
23481
+ };
23482
+ var Parser = class _Parser {
23483
+ constructor(lexer) {
23484
+ this.lexer = lexer;
23485
+ this._token = null;
23486
+ }
23487
+ static _isRegularOperator(id) {
23488
+ return id >= TOKEN.true && id < TOKEN.if;
23489
+ }
23490
+ // Fetch the next token from the lexer.
23491
+ _advance() {
23492
+ this._token = this.lexer.next();
23493
+ }
23494
+ // Assert that the current token has the given id, consume it, and return it.
23495
+ _expect(id) {
23496
+ if (this._token.id !== id) {
23497
+ throw new FormatError(
23498
+ `PostScript function: expected token id ${id}, got ${this._token.id}.`
23499
+ );
23500
+ }
23501
+ const tok = this._token;
23502
+ this._advance();
23503
+ return tok;
23504
+ }
23505
+ /**
23506
+ * Parse the full Type 4 function body.
23507
+ *
23508
+ * Grammar (simplified):
23509
+ * program ::= '{' block '}'
23510
+ * block ::= instruction*
23511
+ * instruction ::= number
23512
+ * | operator (any PS_OPERATOR except if / ifelse)
23513
+ * | '{' block '}' 'if'
23514
+ * | '{' block '}' '{' block '}' 'ifelse'
23515
+ * @returns {PsProgram}
23516
+ */
23517
+ parse() {
23518
+ this._advance();
23519
+ this._expect(TOKEN.lbrace);
23520
+ const block = this._parseBlock();
23521
+ this._expect(TOKEN.rbrace);
23522
+ if (this._token.id !== TOKEN.eof) {
23523
+ warn2("PostScript function: unexpected content after closing brace.");
23524
+ }
23525
+ return new PsProgram(block);
23526
+ }
23527
+ _parseBlock() {
23528
+ const instructions = [];
23529
+ while (true) {
23530
+ const tok = this._token;
23531
+ switch (tok.id) {
23532
+ case TOKEN.number:
23533
+ instructions.push(new PsNumber(tok.value));
23534
+ this._advance();
23535
+ break;
23536
+ case TOKEN.lbrace: {
23537
+ this._advance();
23538
+ const thenBlock = this._parseBlock();
23539
+ this._expect(TOKEN.rbrace);
23540
+ if (this._token.id === TOKEN.if) {
23541
+ this._advance();
23542
+ instructions.push(new PsIf(thenBlock));
23543
+ } else if (this._token.id === TOKEN.lbrace) {
23544
+ this._advance();
23545
+ const elseBlock = this._parseBlock();
23546
+ this._expect(TOKEN.rbrace);
23547
+ this._expect(TOKEN.ifelse);
23548
+ instructions.push(new PsIfElse(thenBlock, elseBlock));
23549
+ } else {
23550
+ throw new FormatError(
23551
+ "PostScript function: a procedure block must be followed by 'if' or '{\u2026} ifelse'."
23552
+ );
23553
+ }
23554
+ break;
23555
+ }
23556
+ case TOKEN.rbrace:
23557
+ case TOKEN.eof:
23558
+ return new PsBlock(instructions);
23559
+ case TOKEN.if:
23560
+ case TOKEN.ifelse:
23561
+ throw new FormatError(
23562
+ `PostScript function: unexpected '${tok.value}' operator.`
23563
+ );
23564
+ default:
23565
+ if (_Parser._isRegularOperator(tok.id)) {
23566
+ instructions.push(new PsOperator(tok.id));
23567
+ this._advance();
23568
+ break;
23569
+ }
23570
+ throw new FormatError(
23571
+ `PostScript function: unexpected token id ${tok.id}.`
23572
+ );
23573
+ }
23574
+ }
23575
+ }
23576
+ };
23577
+ function parsePostScriptFunction(source) {
23578
+ return new Parser(new Lexer(source)).parse();
23579
+ }
23580
+ function _nodesEqual(a, b) {
23581
+ if (a === b) {
23582
+ return true;
23583
+ }
23584
+ if (a.type !== b.type) {
23585
+ return false;
23586
+ }
23587
+ switch (a.type) {
23588
+ case PS_NODE.arg:
23589
+ return a.index === b.index;
23590
+ case PS_NODE.const:
23591
+ return a.value === b.value;
23592
+ case PS_NODE.unary:
23593
+ return a.op === b.op && _nodesEqual(a.operand, b.operand);
23594
+ case PS_NODE.binary:
23595
+ return a.op === b.op && _nodesEqual(a.first, b.first) && _nodesEqual(a.second, b.second);
23596
+ case PS_NODE.ternary:
23597
+ return _nodesEqual(a.cond, b.cond) && _nodesEqual(a.then, b.then) && _nodesEqual(a.otherwise, b.otherwise);
23598
+ default:
23599
+ return false;
23600
+ }
23601
+ }
23602
+ function _evalBinaryConst(op, a, b) {
23603
+ switch (op) {
23604
+ case TOKEN.add:
23605
+ return a + b;
23606
+ case TOKEN.sub:
23607
+ return a - b;
23608
+ case TOKEN.mul:
23609
+ return a * b;
23610
+ case TOKEN.div:
23611
+ return b !== 0 ? a / b : 0;
23612
+ // div by zero → 0
23613
+ case TOKEN.idiv:
23614
+ return b !== 0 ? Math.trunc(a / b) : 0;
23615
+ // div by zero → 0
23616
+ case TOKEN.mod:
23617
+ return b !== 0 ? a - Math.trunc(a / b) * b : 0;
23618
+ // div by zero → 0
23619
+ case TOKEN.exp: {
23620
+ const r = a ** b;
23621
+ return Number.isFinite(r) ? r : void 0;
23622
+ }
23623
+ case TOKEN.atan: {
23624
+ let deg = Math.atan2(a, b) * (180 / Math.PI);
23625
+ if (deg < 0) {
23626
+ deg += 360;
23627
+ }
23628
+ return deg;
23629
+ }
23630
+ case TOKEN.eq:
23631
+ return a === b;
23632
+ case TOKEN.ne:
23633
+ return a !== b;
23634
+ case TOKEN.gt:
23635
+ return a > b;
23636
+ case TOKEN.ge:
23637
+ return a >= b;
23638
+ case TOKEN.lt:
23639
+ return a < b;
23640
+ case TOKEN.le:
23641
+ return a <= b;
23642
+ case TOKEN.and:
23643
+ return typeof a === "boolean" ? a && b : a & b | 0;
23644
+ case TOKEN.or:
23645
+ return typeof a === "boolean" ? a || b : a | b | 0;
23646
+ case TOKEN.xor:
23647
+ return typeof a === "boolean" ? a !== b : a ^ b | 0;
23648
+ case TOKEN.bitshift:
23649
+ return b >= 0 ? a << b | 0 : a >> -b | 0;
23650
+ case TOKEN.min:
23651
+ return Math.min(a, b);
23652
+ case TOKEN.max:
23653
+ return Math.max(a, b);
23654
+ default:
23655
+ return void 0;
23656
+ }
23657
+ }
23658
+ function _evalUnaryConst(op, v) {
23659
+ switch (op) {
23660
+ case TOKEN.abs:
23661
+ return Math.abs(v);
23662
+ case TOKEN.neg:
23663
+ return -v;
23664
+ case TOKEN.ceiling:
23665
+ return Math.ceil(v);
23666
+ case TOKEN.floor:
23667
+ return Math.floor(v);
23668
+ case TOKEN.round:
23669
+ return Math.round(v);
23670
+ case TOKEN.truncate:
23671
+ return Math.trunc(v);
23672
+ case TOKEN.sqrt: {
23673
+ const r = Math.sqrt(v);
23674
+ return Number.isFinite(r) ? r : void 0;
23675
+ }
23676
+ case TOKEN.sin:
23677
+ return Math.sin(v % 360 * Math.PI / 180);
23678
+ case TOKEN.cos:
23679
+ return Math.cos(v % 360 * Math.PI / 180);
23680
+ case TOKEN.ln: {
23681
+ const r = Math.log(v);
23682
+ return Number.isFinite(r) ? r : void 0;
23683
+ }
23684
+ case TOKEN.log: {
23685
+ const r = Math.log10(v);
23686
+ return Number.isFinite(r) ? r : void 0;
23687
+ }
23688
+ case TOKEN.cvi:
23689
+ return Math.trunc(v);
23690
+ case TOKEN.cvr:
23691
+ return v;
23692
+ case TOKEN.not:
23693
+ return typeof v === "boolean" ? !v : ~v;
23694
+ default:
23695
+ return void 0;
23696
+ }
23697
+ }
23698
+ var MAX_STACK_SIZE = 100;
23699
+ function _unaryValueType(op, operandType) {
23700
+ return op === TOKEN.not ? operandType : PS_VALUE_TYPE.numeric;
23701
+ }
23702
+ function _binaryValueType(op, firstType, secondType) {
23703
+ switch (op) {
23704
+ // Comparison operators always produce a boolean.
23705
+ case TOKEN.eq:
23706
+ case TOKEN.ne:
23707
+ case TOKEN.gt:
23708
+ case TOKEN.ge:
23709
+ case TOKEN.lt:
23710
+ case TOKEN.le:
23711
+ return PS_VALUE_TYPE.boolean;
23712
+ // and / or / xor preserve the type when both operands are the same known
23713
+ // type (both boolean or both numeric); otherwise the type is unknown.
23714
+ case TOKEN.and:
23715
+ case TOKEN.or:
23716
+ case TOKEN.xor:
23717
+ return firstType === secondType && firstType !== PS_VALUE_TYPE.unknown ? firstType : PS_VALUE_TYPE.unknown;
23718
+ // All arithmetic / bitshift operators produce a numeric result.
23719
+ default:
23720
+ return PS_VALUE_TYPE.numeric;
23721
+ }
23722
+ }
23723
+ var PSStackToTree = class _PSStackToTree {
23724
+ static #binaryOps = null;
23725
+ static #unaryOps = null;
23726
+ static #idempotentUnary = null;
23727
+ static #negatedComparison = null;
23728
+ static #init() {
23729
+ this.#binaryOps = /* @__PURE__ */ new Set([
23730
+ TOKEN.add,
23731
+ TOKEN.sub,
23732
+ TOKEN.mul,
23733
+ TOKEN.div,
23734
+ TOKEN.idiv,
23735
+ TOKEN.mod,
23736
+ TOKEN.exp,
23737
+ TOKEN.atan,
23738
+ TOKEN.eq,
23739
+ TOKEN.ne,
23740
+ TOKEN.gt,
23741
+ TOKEN.ge,
23742
+ TOKEN.lt,
23743
+ TOKEN.le,
23744
+ TOKEN.and,
23745
+ TOKEN.or,
23746
+ TOKEN.xor,
23747
+ TOKEN.bitshift
23748
+ ]);
23749
+ this.#unaryOps = /* @__PURE__ */ new Set([
23750
+ TOKEN.abs,
23751
+ TOKEN.neg,
23752
+ TOKEN.ceiling,
23753
+ TOKEN.floor,
23754
+ TOKEN.round,
23755
+ TOKEN.truncate,
23756
+ TOKEN.sqrt,
23757
+ TOKEN.sin,
23758
+ TOKEN.cos,
23759
+ TOKEN.ln,
23760
+ TOKEN.log,
23761
+ TOKEN.cvi,
23762
+ TOKEN.cvr,
23763
+ TOKEN.not
23764
+ ]);
23765
+ this.#idempotentUnary = /* @__PURE__ */ new Set([
23766
+ TOKEN.abs,
23767
+ TOKEN.ceiling,
23768
+ TOKEN.cvi,
23769
+ TOKEN.cvr,
23770
+ TOKEN.floor,
23771
+ TOKEN.round,
23772
+ TOKEN.truncate
23773
+ ]);
23774
+ this.#negatedComparison = /* @__PURE__ */ new Map([
23775
+ [TOKEN.eq, TOKEN.ne],
23776
+ [TOKEN.ne, TOKEN.eq],
23777
+ [TOKEN.lt, TOKEN.ge],
23778
+ [TOKEN.le, TOKEN.gt],
23779
+ [TOKEN.gt, TOKEN.le],
23780
+ [TOKEN.ge, TOKEN.lt]
23781
+ ]);
23782
+ }
23783
+ /**
23784
+ * @param {PsProgram} program
23785
+ * @param {number} numInputs — number of domain values placed on the stack
23786
+ * before the program runs (i.e. the length of the domain array / 2).
23787
+ * @returns {Array<PsNode>} — one tree node per output value.
23788
+ */
23789
+ evaluate(program, numInputs) {
23790
+ if (!_PSStackToTree.#binaryOps) {
23791
+ _PSStackToTree.#init();
23792
+ }
23793
+ this._failed = false;
23794
+ if (numInputs > MAX_STACK_SIZE) {
23795
+ return null;
23796
+ }
23797
+ const stack = [];
23798
+ for (let i = 0; i < numInputs; i++) {
23799
+ stack.push(new PsArgNode(i));
23800
+ }
23801
+ this._evalBlock(program.body, stack);
23802
+ if (this._failed) {
23803
+ return null;
23804
+ }
23805
+ _PSStackToTree.#markShared(stack);
23806
+ return stack;
23807
+ }
23808
+ // Set node.shared / sharedCount on non-atomic nodes referenced more than
23809
+ // once. arg/const are excluded — they are cheap to re-emit inline.
23810
+ static #markShared(outputs) {
23811
+ const refCount = /* @__PURE__ */ new Map();
23812
+ const visit = (node) => {
23813
+ if (!node || node.type === PS_NODE.arg || node.type === PS_NODE.const) {
23814
+ return;
23815
+ }
23816
+ const prev = refCount.get(node) ?? 0;
23817
+ refCount.set(node, prev + 1);
23818
+ if (prev > 0) {
23819
+ return;
23820
+ }
23821
+ switch (node.type) {
23822
+ case PS_NODE.unary:
23823
+ visit(node.operand);
23824
+ break;
23825
+ case PS_NODE.binary:
23826
+ visit(node.first);
23827
+ visit(node.second);
23828
+ break;
23829
+ case PS_NODE.ternary:
23830
+ visit(node.cond);
23831
+ visit(node.then);
23832
+ visit(node.otherwise);
23833
+ break;
23834
+ }
23835
+ };
23836
+ for (const output of outputs) {
23837
+ visit(output);
23838
+ }
23839
+ for (const [node, count] of refCount) {
23840
+ if (count > 1) {
23841
+ node.shared = true;
23842
+ node.sharedCount = count;
23843
+ }
23844
+ }
23845
+ }
23846
+ _evalBlock(block, stack) {
23847
+ this._evalBlockFrom(block.instructions, 0, stack);
23848
+ }
23849
+ /**
23850
+ * Core evaluation loop. Processes `instructions[startIdx…]` in order,
23851
+ * mutating `stack` as each instruction executes.
23852
+ *
23853
+ * When a `{ body } if` instruction grows the stack (the PostScript "early
23854
+ * exit / guard" idiom), the remaining instructions in the current array are
23855
+ * evaluated on **both** the true-branch stack and the false-branch stack,
23856
+ * then the two results are merged into PsTernaryNodes. This handles
23857
+ * patterns like:
23858
+ *
23859
+ * cond { pop R G B sentinel } if
23860
+ * … more guards …
23861
+ * sentinel 0 gt { defaultR defaultG defaultB } if
23862
+ */
23863
+ _evalBlockFrom(instructions, startIdx, stack) {
23864
+ for (let idx = startIdx; idx < instructions.length; idx++) {
23865
+ if (this._failed) {
23866
+ break;
23867
+ }
23868
+ const instr = instructions[idx];
23869
+ switch (instr.type) {
23870
+ case PS_NODE.number:
23871
+ stack.push(new PsConstNode(instr.value));
23872
+ if (stack.length > MAX_STACK_SIZE) {
23873
+ this._failed = true;
23874
+ }
23875
+ break;
23876
+ case PS_NODE.operator:
23877
+ this._evalOp(instr.op, stack);
23878
+ break;
23879
+ case PS_NODE.if: {
23880
+ if (stack.length < 1) {
23881
+ this._failed = true;
23882
+ break;
23883
+ }
23884
+ const cond = stack.pop();
23885
+ const saved = stack.slice();
23886
+ this._evalBlock(instr.then, stack);
23887
+ if (this._failed) {
23888
+ break;
23889
+ }
23890
+ if (stack.length === saved.length) {
23891
+ for (let i = 0; i < stack.length; i++) {
23892
+ if (stack[i] !== saved[i]) {
23893
+ stack[i] = this._makeTernary(cond, stack[i], saved[i]);
23894
+ }
23895
+ }
23896
+ } else if (stack.length > saved.length) {
23897
+ if (cond.type === PS_NODE.const) {
23898
+ if (!cond.value) {
23899
+ stack.length = 0;
23900
+ stack.push(...saved);
23901
+ }
23902
+ break;
23903
+ }
23904
+ const trueStack = stack.slice();
23905
+ this._evalBlockFrom(instructions, idx + 1, trueStack);
23906
+ if (this._failed) {
23907
+ break;
23908
+ }
23909
+ const falseStack = saved;
23910
+ this._evalBlockFrom(instructions, idx + 1, falseStack);
23911
+ if (this._failed) {
23912
+ break;
23913
+ }
23914
+ if (trueStack.length !== falseStack.length) {
23915
+ const zero2 = new PsConstNode(0);
23916
+ while (trueStack.length < falseStack.length) {
23917
+ trueStack.push(zero2);
23918
+ }
23919
+ while (falseStack.length < trueStack.length) {
23920
+ falseStack.push(zero2);
23921
+ }
23922
+ }
23923
+ stack.length = 0;
23924
+ for (let i = 0; i < trueStack.length; i++) {
23925
+ stack.push(this._makeTernary(cond, trueStack[i], falseStack[i]));
23926
+ }
23927
+ return;
23928
+ } else {
23929
+ this._failed = true;
23930
+ }
23931
+ break;
23932
+ }
23933
+ case PS_NODE.ifelse: {
23934
+ if (stack.length < 1) {
23935
+ this._failed = true;
23936
+ break;
23937
+ }
23938
+ const cond = stack.pop();
23939
+ const snapshot = stack.slice();
23940
+ const thenStack = snapshot.slice();
23941
+ this._evalBlock(instr.then, thenStack);
23942
+ if (this._failed) {
23943
+ break;
23944
+ }
23945
+ const elseStack = snapshot.slice();
23946
+ this._evalBlock(instr.otherwise, elseStack);
23947
+ if (this._failed) {
23948
+ break;
23949
+ }
23950
+ if (thenStack.length !== elseStack.length) {
23951
+ const zero2 = new PsConstNode(0);
23952
+ while (thenStack.length < elseStack.length) {
23953
+ thenStack.push(zero2);
23954
+ }
23955
+ while (elseStack.length < thenStack.length) {
23956
+ elseStack.push(zero2);
23957
+ }
23958
+ }
23959
+ stack.length = 0;
23960
+ for (let i = 0; i < thenStack.length; i++) {
23961
+ stack.push(this._makeTernary(cond, thenStack[i], elseStack[i]));
23962
+ }
23963
+ break;
23964
+ }
23965
+ }
23966
+ }
23967
+ }
23968
+ _evalOp(op, stack) {
23969
+ if (_PSStackToTree.#binaryOps.has(op)) {
23970
+ if (stack.length < 2) {
23971
+ this._failed = true;
23972
+ return;
23973
+ }
23974
+ const first = stack.pop();
23975
+ const second = stack.pop();
23976
+ stack.push(this._makeBinary(op, first, second));
23977
+ return;
23978
+ }
23979
+ if (_PSStackToTree.#unaryOps.has(op)) {
23980
+ if (stack.length < 1) {
23981
+ this._failed = true;
23982
+ return;
23983
+ }
23984
+ stack.push(this._makeUnary(op, stack.pop()));
23985
+ return;
23986
+ }
23987
+ switch (op) {
23988
+ case TOKEN.true:
23989
+ stack.push(new PsConstNode(true));
23990
+ if (stack.length > MAX_STACK_SIZE) {
23991
+ this._failed = true;
23992
+ }
23993
+ break;
23994
+ case TOKEN.false:
23995
+ stack.push(new PsConstNode(false));
23996
+ if (stack.length > MAX_STACK_SIZE) {
23997
+ this._failed = true;
23998
+ }
23999
+ break;
24000
+ case TOKEN.dup:
24001
+ if (stack.length < 1) {
24002
+ this._failed = true;
24003
+ break;
24004
+ }
24005
+ stack.push(stack.at(-1));
24006
+ if (stack.length > MAX_STACK_SIZE) {
24007
+ this._failed = true;
24008
+ }
24009
+ break;
24010
+ case TOKEN.exch: {
24011
+ if (stack.length < 2) {
24012
+ this._failed = true;
24013
+ break;
24014
+ }
24015
+ const a = stack.pop();
24016
+ const b = stack.pop();
24017
+ stack.push(a, b);
24018
+ break;
24019
+ }
24020
+ case TOKEN.pop:
24021
+ if (stack.length < 1) {
24022
+ this._failed = true;
24023
+ break;
24024
+ }
24025
+ stack.pop();
24026
+ break;
24027
+ case TOKEN.copy: {
24028
+ if (stack.length < 1) {
24029
+ this._failed = true;
24030
+ break;
24031
+ }
24032
+ const nNode = stack.pop();
24033
+ if (nNode.type === PS_NODE.const) {
24034
+ const n = nNode.value | 0;
24035
+ if (n === 0) {
24036
+ } else if (n < 0 || n > stack.length) {
24037
+ this._failed = true;
24038
+ } else {
24039
+ stack.push(...stack.slice(-n));
24040
+ if (stack.length > MAX_STACK_SIZE) {
24041
+ this._failed = true;
24042
+ }
24043
+ }
24044
+ } else {
24045
+ this._failed = true;
24046
+ }
24047
+ break;
24048
+ }
24049
+ case TOKEN.index: {
24050
+ if (stack.length < 1) {
24051
+ this._failed = true;
24052
+ break;
24053
+ }
24054
+ const nNode = stack.pop();
24055
+ if (nNode.type === PS_NODE.const) {
24056
+ const n = nNode.value | 0;
24057
+ if (n < 0 || n >= stack.length) {
24058
+ this._failed = true;
24059
+ } else {
24060
+ stack.push(stack.at(-n - 1));
24061
+ }
24062
+ } else {
24063
+ this._failed = true;
24064
+ }
24065
+ break;
24066
+ }
24067
+ case TOKEN.roll: {
24068
+ if (stack.length < 2) {
24069
+ this._failed = true;
24070
+ break;
24071
+ }
24072
+ const jNode = stack.pop();
24073
+ const nNode = stack.pop();
24074
+ if (nNode.type === PS_NODE.const && jNode.type === PS_NODE.const) {
24075
+ const n = nNode.value | 0;
24076
+ if (n === 0) {
24077
+ } else if (n < 0 || n > stack.length) {
24078
+ this._failed = true;
24079
+ } else {
24080
+ const j = ((jNode.value | 0) % n + n) % n;
24081
+ if (j > 0) {
24082
+ const slice = stack.splice(-n, n);
24083
+ stack.push(...slice.slice(n - j), ...slice.slice(0, n - j));
24084
+ }
24085
+ }
24086
+ } else {
24087
+ this._failed = true;
24088
+ }
24089
+ break;
24090
+ }
24091
+ default:
24092
+ this._failed = true;
24093
+ break;
24094
+ }
24095
+ }
24096
+ /**
24097
+ * Create a binary tree node, applying optimizations eagerly:
24098
+ *
24099
+ * 1. Constant folding — both operands are PsConstNode → fold to PsConstNode.
24100
+ * 2. Reflexive simplifications — x−x→0, x xor x→0, x eq x→true, etc.
24101
+ * 3. Algebraic simplifications with one known operand — identity elements
24102
+ * (x+0→x, x*1→x, …), absorbing elements (x*0→0, x and false→false, …),
24103
+ * and strength reductions (x*-1→neg(x), x^0.5→sqrt(x), x^2→x*x, …).
24104
+ *
24105
+ * Recall: `first` was on top of the stack (right operand for non-commutative
24106
+ * ops), `second` was below (left operand). So `a b sub` → second=a, first=b
24107
+ * → a − b.
24108
+ */
24109
+ _makeBinary(op, first, second) {
24110
+ if (first.type === PS_NODE.const && second.type === PS_NODE.const) {
24111
+ const v = _evalBinaryConst(op, second.value, first.value);
24112
+ if (v !== void 0) {
24113
+ return new PsConstNode(v);
24114
+ }
24115
+ }
24116
+ if (_nodesEqual(first, second)) {
24117
+ switch (op) {
24118
+ case TOKEN.sub:
24119
+ return new PsConstNode(0);
24120
+ // x − x → 0
24121
+ case TOKEN.xor:
24122
+ return new PsConstNode(
24123
+ /* eslint-disable unicorn/prefer-logical-operator-over-ternary */
24124
+ first.valueType === PS_VALUE_TYPE.boolean ? false : 0
24125
+ /* eslint-enable unicorn/prefer-logical-operator-over-ternary */
24126
+ );
24127
+ // TOKEN.mod, TOKEN.div, TOKEN.idiv are NOT simplified here:
24128
+ // x op x is undefined when x = 0, so we cannot fold without knowing
24129
+ // that x is non-zero.
24130
+ case TOKEN.and:
24131
+ case TOKEN.or:
24132
+ return first;
24133
+ // x and x → x; x or x → x
24134
+ case TOKEN.min:
24135
+ case TOKEN.max:
24136
+ return first;
24137
+ // min(x,x) → x; max(x,x) → x
24138
+ case TOKEN.eq:
24139
+ case TOKEN.ge:
24140
+ case TOKEN.le:
24141
+ return new PsConstNode(true);
24142
+ case TOKEN.ne:
24143
+ case TOKEN.gt:
24144
+ case TOKEN.lt:
24145
+ return new PsConstNode(false);
24146
+ }
24147
+ }
24148
+ if (first.type === PS_NODE.const) {
24149
+ const b = first.value;
24150
+ switch (op) {
24151
+ case TOKEN.add:
24152
+ if (b === 0) {
24153
+ return second;
24154
+ }
24155
+ break;
24156
+ case TOKEN.sub:
24157
+ if (b === 0) {
24158
+ return second;
24159
+ }
24160
+ break;
24161
+ case TOKEN.mul:
24162
+ if (b === 1) {
24163
+ return second;
24164
+ }
24165
+ if (b === 0) {
24166
+ return first;
24167
+ }
24168
+ if (b === -1) {
24169
+ return this._makeUnary(TOKEN.neg, second);
24170
+ }
24171
+ break;
24172
+ case TOKEN.div:
24173
+ if (b !== 0) {
24174
+ return this._makeBinary(TOKEN.mul, new PsConstNode(1 / b), second);
24175
+ }
24176
+ break;
24177
+ case TOKEN.idiv:
24178
+ if (b === 1) {
24179
+ return second;
24180
+ }
24181
+ break;
24182
+ case TOKEN.exp:
24183
+ if (b === 1) {
24184
+ return second;
24185
+ }
24186
+ if (b === -1) {
24187
+ return this._makeBinary(TOKEN.div, second, new PsConstNode(1));
24188
+ }
24189
+ if (b === 0.5) {
24190
+ return this._makeUnary(TOKEN.sqrt, second);
24191
+ }
24192
+ if (b === 0.25) {
24193
+ const sqrtOnce = this._makeUnary(TOKEN.sqrt, second);
24194
+ return this._makeUnary(TOKEN.sqrt, sqrtOnce);
24195
+ }
24196
+ if (b === 2) {
24197
+ return this._makeBinary(TOKEN.mul, second, second);
24198
+ }
24199
+ if (b === 3) {
24200
+ return this._makeBinary(
24201
+ TOKEN.mul,
24202
+ this._makeBinary(TOKEN.mul, second, second),
24203
+ second
24204
+ );
24205
+ }
24206
+ if (b === 4) {
24207
+ const square = this._makeBinary(TOKEN.mul, second, second);
24208
+ return this._makeBinary(TOKEN.mul, square, square);
24209
+ }
24210
+ if (b === 0) {
24211
+ return new PsConstNode(1);
24212
+ }
24213
+ break;
24214
+ case TOKEN.and:
24215
+ if (b === true) {
24216
+ return second;
24217
+ }
24218
+ if (b === false) {
24219
+ return first;
24220
+ }
24221
+ break;
24222
+ case TOKEN.or:
24223
+ if (b === false) {
24224
+ return second;
24225
+ }
24226
+ if (b === true) {
24227
+ return first;
24228
+ }
24229
+ break;
24230
+ case TOKEN.min:
24231
+ if (second.type === PS_NODE.binary && second.op === TOKEN.max && second.first.type === PS_NODE.const && second.first.value >= b) {
24232
+ return first;
24233
+ }
24234
+ break;
24235
+ case TOKEN.max:
24236
+ if (second.type === PS_NODE.binary && second.op === TOKEN.min && second.first.type === PS_NODE.const && second.first.value <= b) {
24237
+ return first;
24238
+ }
24239
+ break;
24240
+ }
24241
+ }
24242
+ if (second.type === PS_NODE.const) {
24243
+ const a = second.value;
24244
+ switch (op) {
24245
+ case TOKEN.add:
24246
+ if (a === 0) {
24247
+ return first;
24248
+ }
24249
+ break;
24250
+ case TOKEN.sub:
24251
+ if (a === 0) {
24252
+ return this._makeUnary(TOKEN.neg, first);
24253
+ }
24254
+ break;
24255
+ case TOKEN.mul:
24256
+ if (a === 1) {
24257
+ return first;
24258
+ }
24259
+ if (a === 0) {
24260
+ return second;
24261
+ }
24262
+ if (a === -1) {
24263
+ return this._makeUnary(TOKEN.neg, first);
24264
+ }
24265
+ break;
24266
+ case TOKEN.and:
24267
+ if (a === true) {
24268
+ return first;
24269
+ }
24270
+ if (a === false) {
24271
+ return second;
24272
+ }
24273
+ break;
24274
+ case TOKEN.or:
24275
+ if (a === false) {
24276
+ return first;
24277
+ }
24278
+ if (a === true) {
24279
+ return second;
24280
+ }
24281
+ break;
24282
+ }
24283
+ }
24284
+ return new PsBinaryNode(
24285
+ op,
24286
+ first,
24287
+ second,
24288
+ _binaryValueType(op, first.valueType, second.valueType)
24289
+ );
24290
+ }
24291
+ /**
24292
+ * Create a unary tree node, applying optimizations eagerly:
24293
+ *
24294
+ * 1. Constant folding.
24295
+ * 2. not(comparison) → negated comparison: not(a eq b) → a ne b, etc.
24296
+ * 3. neg(a − b) → b − a.
24297
+ * 4. Double-negation: neg(neg(x)) → x, not(not(x)) → x.
24298
+ * 5. abs(neg(x)) → abs(x).
24299
+ * 6. Idempotent: f(f(x)) → f(x) for abs, ceiling, floor, round, etc.
24300
+ */
24301
+ _makeUnary(op, operand) {
24302
+ if (operand.type === PS_NODE.const) {
24303
+ const v = _evalUnaryConst(op, operand.value);
24304
+ if (v !== void 0) {
24305
+ return new PsConstNode(v);
24306
+ }
24307
+ }
24308
+ if (op === TOKEN.not && operand.type === PS_NODE.binary) {
24309
+ const negated = _PSStackToTree.#negatedComparison.get(operand.op);
24310
+ if (negated !== void 0) {
24311
+ return new PsBinaryNode(
24312
+ negated,
24313
+ operand.first,
24314
+ operand.second,
24315
+ PS_VALUE_TYPE.boolean
24316
+ );
24317
+ }
24318
+ }
24319
+ if (op === TOKEN.neg && operand.type === PS_NODE.binary && operand.op === TOKEN.sub) {
24320
+ return this._makeBinary(TOKEN.sub, operand.second, operand.first);
24321
+ }
24322
+ if (operand.type === PS_NODE.unary) {
24323
+ if (op === TOKEN.neg && operand.op === TOKEN.neg || op === TOKEN.not && operand.op === TOKEN.not) {
24324
+ return operand.operand;
24325
+ }
24326
+ if (op === TOKEN.abs && operand.op === TOKEN.neg) {
24327
+ return this._makeUnary(TOKEN.abs, operand.operand);
24328
+ }
24329
+ if (_PSStackToTree.#idempotentUnary.has(op) && op === operand.op) {
24330
+ return operand;
24331
+ }
24332
+ }
24333
+ return new PsUnaryNode(op, operand, _unaryValueType(op, operand.valueType));
24334
+ }
24335
+ /**
24336
+ * Create a ternary node, applying optimizations eagerly:
24337
+ *
24338
+ * 1. Constant condition — fold to the live branch.
24339
+ * 2. Identical branches — the condition is irrelevant, return either branch.
24340
+ * 3. Boolean branch constants — `cond ? true : false` → cond,
24341
+ * `cond ? false : true` → not(cond).
24342
+ * 4. Ternary → branchless min/max when the condition compares two numeric
24343
+ * expressions that are also the two branches.
24344
+ */
24345
+ _makeTernary(cond, then, otherwise) {
24346
+ if (cond.type === PS_NODE.const) {
24347
+ return cond.value ? then : otherwise;
24348
+ }
24349
+ if (_nodesEqual(then, otherwise)) {
24350
+ return then;
24351
+ }
24352
+ if (then.type === PS_NODE.const && otherwise.type === PS_NODE.const) {
24353
+ if (then.value === true && otherwise.value === false) {
24354
+ return cond;
24355
+ }
24356
+ if (then.value === false && otherwise.value === true) {
24357
+ return this._makeUnary(TOKEN.not, cond);
24358
+ }
24359
+ }
24360
+ if (cond.type === PS_NODE.binary) {
24361
+ const { op: cop, first: cf, second: cs } = cond;
24362
+ if (cop === TOKEN.gt || cop === TOKEN.ge) {
24363
+ if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
24364
+ return this._makeBinary(TOKEN.min, cf, cs);
24365
+ }
24366
+ if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
24367
+ return this._makeBinary(TOKEN.max, cf, cs);
24368
+ }
24369
+ } else if (cop === TOKEN.lt || cop === TOKEN.le) {
24370
+ if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
24371
+ return this._makeBinary(TOKEN.max, cf, cs);
24372
+ }
24373
+ if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
24374
+ return this._makeBinary(TOKEN.min, cf, cs);
24375
+ }
24376
+ }
24377
+ }
24378
+ return new PsTernaryNode(
24379
+ cond,
24380
+ then,
24381
+ otherwise,
24382
+ then.valueType === otherwise.valueType ? then.valueType : PS_VALUE_TYPE.unknown
24383
+ );
24384
+ }
24385
+ };
24386
+ var OP = {
24387
+ ARG: 0,
24388
+ // [ARG, idx]
24389
+ CONST: 1,
24390
+ // [CONST, val]
24391
+ STORE: 2,
24392
+ // [STORE, slot, min, max] clamp(pop()) → mem[slot]
24393
+ IF: 3,
24394
+ // [IF, target] jump when top-of-stack === 0
24395
+ JUMP: 4,
24396
+ // [JUMP, target] unconditional
24397
+ ABS: 5,
24398
+ NEG: 6,
24399
+ CEIL: 7,
24400
+ FLOOR: 8,
24401
+ ROUND: 9,
24402
+ // floor(x + 0.5)
24403
+ TRUNC: 10,
24404
+ NOT_B: 11,
24405
+ // boolean NOT
24406
+ NOT_N: 12,
24407
+ // bitwise NOT
24408
+ SQRT: 13,
24409
+ SIN: 14,
24410
+ // degrees in/out
24411
+ COS: 15,
24412
+ LN: 16,
24413
+ LOG10: 17,
24414
+ CVI: 18,
24415
+ SHIFT: 19,
24416
+ // [SHIFT, amount] +ve = left, −ve = right
24417
+ // Binary ops: second below, first on top; result = second OP first.
24418
+ ADD: 20,
24419
+ SUB: 21,
24420
+ MUL: 22,
24421
+ DIV: 23,
24422
+ // 0 when divisor is 0
24423
+ IDIV: 24,
24424
+ // 0 when divisor is 0
24425
+ MOD: 25,
24426
+ // 0 when divisor is 0
24427
+ POW: 26,
24428
+ EQ: 27,
24429
+ NE: 28,
24430
+ GT: 29,
24431
+ GE: 30,
24432
+ LT: 31,
24433
+ LE: 32,
24434
+ AND: 33,
24435
+ OR: 34,
24436
+ XOR: 35,
24437
+ ATAN: 36,
24438
+ // atan2(second, first) → degrees [0, 360)
24439
+ MIN: 37,
24440
+ MAX: 38,
24441
+ TEE_TMP: 39,
24442
+ // [TEE_TMP, slot] peek top of stack → tmp[slot], leave on stack
24443
+ LOAD_TMP: 40
24444
+ // [LOAD_TMP, slot] push tmp[slot]
24445
+ };
24446
+ var _DEG_TO_RAD = Math.PI / 180;
24447
+ var _RAD_TO_DEG = 180 / Math.PI;
24448
+ var PsJsCompiler = class {
24449
+ // Safe because JS is single-threaded.
24450
+ static #stack = new Float64Array(64);
24451
+ static #tmp = new Float64Array(64);
24452
+ constructor(domain, range) {
24453
+ this.nIn = domain.length >> 1;
24454
+ this.nOut = range.length >> 1;
24455
+ this.range = range;
24456
+ this.ir = [];
24457
+ this._tmpMap = /* @__PURE__ */ new Map();
24458
+ this._nextTmp = 0;
24459
+ }
24460
+ _compileNode(node) {
24461
+ if (node.shared) {
24462
+ const cached = this._tmpMap.get(node);
24463
+ if (cached !== void 0) {
24464
+ this.ir.push(OP.LOAD_TMP, cached);
24465
+ return true;
24466
+ }
24467
+ if (!this._compileNodeImpl(node)) {
24468
+ return false;
24469
+ }
24470
+ const slot = this._nextTmp++;
24471
+ this._tmpMap.set(node, slot);
24472
+ this.ir.push(OP.TEE_TMP, slot);
24473
+ return true;
24474
+ }
24475
+ return this._compileNodeImpl(node);
24476
+ }
24477
+ _compileNodeImpl(node) {
24478
+ switch (node.type) {
24479
+ case PS_NODE.arg:
24480
+ this.ir.push(OP.ARG, node.index);
24481
+ return true;
24482
+ case PS_NODE.const: {
24483
+ const v = node.value;
24484
+ this.ir.push(OP.CONST, typeof v === "boolean" ? Number(v) : v);
24485
+ return true;
24486
+ }
24487
+ case PS_NODE.unary:
24488
+ return this._compileUnary(node);
24489
+ case PS_NODE.binary:
24490
+ return this._compileBinary(node);
24491
+ case PS_NODE.ternary:
24492
+ return this._compileTernary(node);
24493
+ default:
24494
+ return false;
24495
+ }
24496
+ }
24497
+ _compileUnary(node) {
24498
+ const { op, operand, valueType } = node;
24499
+ if (op === TOKEN.cvr) {
24500
+ return this._compileNode(operand);
24501
+ }
24502
+ if (!this._compileNode(operand)) {
24503
+ return false;
24504
+ }
24505
+ switch (op) {
24506
+ case TOKEN.abs:
24507
+ this.ir.push(OP.ABS);
24508
+ break;
24509
+ case TOKEN.neg:
24510
+ this.ir.push(OP.NEG);
24511
+ break;
24512
+ case TOKEN.ceiling:
24513
+ this.ir.push(OP.CEIL);
24514
+ break;
24515
+ case TOKEN.floor:
24516
+ this.ir.push(OP.FLOOR);
24517
+ break;
24518
+ case TOKEN.round:
24519
+ this.ir.push(OP.ROUND);
24520
+ break;
24521
+ case TOKEN.truncate:
24522
+ this.ir.push(OP.TRUNC);
24523
+ break;
24524
+ case TOKEN.sqrt:
24525
+ this.ir.push(OP.SQRT);
24526
+ break;
24527
+ case TOKEN.sin:
24528
+ this.ir.push(OP.SIN);
24529
+ break;
24530
+ case TOKEN.cos:
24531
+ this.ir.push(OP.COS);
24532
+ break;
24533
+ case TOKEN.ln:
24534
+ this.ir.push(OP.LN);
24535
+ break;
24536
+ case TOKEN.log:
24537
+ this.ir.push(OP.LOG10);
24538
+ break;
24539
+ case TOKEN.cvi:
24540
+ this.ir.push(OP.CVI);
24541
+ break;
24542
+ case TOKEN.not:
24543
+ if (valueType === PS_VALUE_TYPE.boolean) {
24544
+ this.ir.push(OP.NOT_B);
24545
+ } else if (valueType === PS_VALUE_TYPE.numeric) {
24546
+ this.ir.push(OP.NOT_N);
24547
+ } else {
24548
+ return false;
24549
+ }
24550
+ break;
24551
+ default:
24552
+ return false;
24553
+ }
24554
+ return true;
24555
+ }
24556
+ _compileBinary(node) {
24557
+ const { op, first, second } = node;
24558
+ if (op === TOKEN.bitshift) {
24559
+ if (first.type !== PS_NODE.const || !Number.isInteger(first.value) || !this._compileNode(second)) {
24560
+ return false;
24561
+ }
24562
+ this.ir.push(OP.SHIFT, first.value);
24563
+ return true;
24564
+ }
24565
+ if (!this._compileNode(second) || !this._compileNode(first)) {
24566
+ return false;
24567
+ }
24568
+ switch (op) {
24569
+ case TOKEN.add:
24570
+ this.ir.push(OP.ADD);
24571
+ break;
24572
+ case TOKEN.sub:
24573
+ this.ir.push(OP.SUB);
24574
+ break;
24575
+ case TOKEN.mul:
24576
+ this.ir.push(OP.MUL);
24577
+ break;
24578
+ case TOKEN.div:
24579
+ this.ir.push(OP.DIV);
24580
+ break;
24581
+ case TOKEN.idiv:
24582
+ this.ir.push(OP.IDIV);
24583
+ break;
24584
+ case TOKEN.mod:
24585
+ this.ir.push(OP.MOD);
24586
+ break;
24587
+ case TOKEN.exp:
24588
+ this.ir.push(OP.POW);
24589
+ break;
24590
+ case TOKEN.eq:
24591
+ this.ir.push(OP.EQ);
24592
+ break;
24593
+ case TOKEN.ne:
24594
+ this.ir.push(OP.NE);
24595
+ break;
24596
+ case TOKEN.gt:
24597
+ this.ir.push(OP.GT);
24598
+ break;
24599
+ case TOKEN.ge:
24600
+ this.ir.push(OP.GE);
24601
+ break;
24602
+ case TOKEN.lt:
24603
+ this.ir.push(OP.LT);
24604
+ break;
24605
+ case TOKEN.le:
24606
+ this.ir.push(OP.LE);
24607
+ break;
24608
+ case TOKEN.and:
24609
+ this.ir.push(OP.AND);
24610
+ break;
24611
+ case TOKEN.or:
24612
+ this.ir.push(OP.OR);
24613
+ break;
24614
+ case TOKEN.xor:
24615
+ this.ir.push(OP.XOR);
24616
+ break;
24617
+ case TOKEN.atan:
24618
+ this.ir.push(OP.ATAN);
24619
+ break;
24620
+ case TOKEN.min:
24621
+ this.ir.push(OP.MIN);
24622
+ break;
24623
+ case TOKEN.max:
24624
+ this.ir.push(OP.MAX);
24625
+ break;
24626
+ default:
24627
+ return false;
24628
+ }
24629
+ return true;
24630
+ }
24631
+ _compileTernary(node) {
24632
+ if (!this._compileNode(node.cond)) {
24633
+ return false;
24634
+ }
24635
+ this.ir.push(OP.IF, 0);
24636
+ const ifPatch = this.ir.length - 1;
24637
+ if (!this._compileNode(node.then)) {
24638
+ return false;
24639
+ }
24640
+ this.ir.push(OP.JUMP, 0);
24641
+ const jumpPatch = this.ir.length - 1;
24642
+ this.ir[ifPatch] = this.ir.length;
24643
+ if (!this._compileNode(node.otherwise)) {
24644
+ return false;
24645
+ }
24646
+ this.ir[jumpPatch] = this.ir.length;
24647
+ return true;
24648
+ }
24649
+ compile(program) {
24650
+ const outputs = new PSStackToTree().evaluate(program, this.nIn);
24651
+ if (!outputs || outputs.length < this.nOut) {
24652
+ return null;
24653
+ }
24654
+ for (let i = 0; i < this.nOut; i++) {
24655
+ if (!this._compileNode(outputs[i])) {
24656
+ return null;
24657
+ }
24658
+ const min = this.range[i * 2];
24659
+ const max = this.range[i * 2 + 1];
24660
+ this.ir.push(OP.STORE, i, min, max);
24661
+ }
24662
+ return new Float64Array(this.ir);
24663
+ }
24664
+ static execute(ir, src, srcOffset, dest, destOffset) {
24665
+ let ip = 0, sp = 0;
24666
+ const n = ir.length;
24667
+ const stack = this.#stack;
24668
+ const tmp = this.#tmp;
24669
+ while (ip < n) {
24670
+ switch (ir[ip++] | 0) {
24671
+ case OP.ARG:
24672
+ stack[sp++] = src[srcOffset + (ir[ip++] | 0)];
24673
+ break;
24674
+ case OP.CONST:
24675
+ stack[sp++] = ir[ip++];
24676
+ break;
24677
+ case OP.STORE: {
24678
+ const slot = ir[ip++] | 0;
24679
+ const min = ir[ip++];
24680
+ const max = ir[ip++];
24681
+ dest[destOffset + slot] = MathClamp(stack[--sp], min, max);
24682
+ break;
24683
+ }
24684
+ case OP.IF: {
24685
+ const tgt = ir[ip++];
24686
+ if (stack[--sp] === 0) {
24687
+ ip = tgt;
24688
+ }
24689
+ break;
24690
+ }
24691
+ case OP.JUMP:
24692
+ ip = ir[ip];
24693
+ break;
24694
+ case OP.ABS:
24695
+ stack[sp - 1] = Math.abs(stack[sp - 1]);
24696
+ break;
24697
+ case OP.NEG:
24698
+ stack[sp - 1] = -stack[sp - 1];
24699
+ break;
24700
+ case OP.CEIL:
24701
+ stack[sp - 1] = Math.ceil(stack[sp - 1]);
24702
+ break;
24703
+ case OP.FLOOR:
24704
+ stack[sp - 1] = Math.floor(stack[sp - 1]);
24705
+ break;
24706
+ case OP.ROUND:
24707
+ stack[sp - 1] = Math.floor(stack[sp - 1] + 0.5);
24708
+ break;
24709
+ case OP.TRUNC:
24710
+ stack[sp - 1] = Math.trunc(stack[sp - 1]);
24711
+ break;
24712
+ case OP.NOT_B:
24713
+ stack[sp - 1] = stack[sp - 1] !== 0 ? 0 : 1;
24714
+ break;
24715
+ case OP.NOT_N:
24716
+ stack[sp - 1] = ~(stack[sp - 1] | 0);
24717
+ break;
24718
+ case OP.SQRT:
24719
+ stack[sp - 1] = Math.sqrt(stack[sp - 1]);
24720
+ break;
24721
+ case OP.SIN:
24722
+ stack[sp - 1] = Math.sin(stack[sp - 1] % 360 * _DEG_TO_RAD);
24723
+ break;
24724
+ case OP.COS:
24725
+ stack[sp - 1] = Math.cos(stack[sp - 1] % 360 * _DEG_TO_RAD);
24726
+ break;
24727
+ case OP.LN:
24728
+ stack[sp - 1] = Math.log(stack[sp - 1]);
24729
+ break;
24730
+ case OP.LOG10:
24731
+ stack[sp - 1] = Math.log10(stack[sp - 1]);
24732
+ break;
24733
+ case OP.CVI:
24734
+ stack[sp - 1] = Math.trunc(stack[sp - 1]) | 0;
24735
+ break;
24736
+ case OP.SHIFT: {
24737
+ const amt = ir[ip++];
24738
+ const v = stack[sp - 1] | 0;
24739
+ if (amt > 0) {
24740
+ stack[sp - 1] = v << amt;
24741
+ } else if (amt < 0) {
24742
+ stack[sp - 1] = v >> -amt;
24743
+ } else {
24744
+ stack[sp - 1] = v;
24745
+ }
24746
+ break;
24747
+ }
24748
+ case OP.ADD: {
24749
+ const b = stack[--sp];
24750
+ stack[sp - 1] += b;
24751
+ break;
24752
+ }
24753
+ case OP.SUB: {
24754
+ const b = stack[--sp];
24755
+ stack[sp - 1] -= b;
24756
+ break;
24757
+ }
24758
+ case OP.MUL: {
24759
+ const b = stack[--sp];
24760
+ stack[sp - 1] *= b;
24761
+ break;
24762
+ }
24763
+ case OP.DIV: {
24764
+ const b = stack[--sp];
24765
+ stack[sp - 1] = b !== 0 ? stack[sp - 1] / b : 0;
24766
+ break;
24767
+ }
24768
+ case OP.IDIV: {
24769
+ const b = stack[--sp];
24770
+ stack[sp - 1] = b !== 0 ? Math.trunc(stack[sp - 1] / b) : 0;
24771
+ break;
24772
+ }
24773
+ case OP.MOD: {
24774
+ const b = stack[--sp];
24775
+ stack[sp - 1] = b !== 0 ? stack[sp - 1] % b : 0;
24776
+ break;
24777
+ }
24778
+ case OP.POW: {
24779
+ const b = stack[--sp];
24780
+ stack[sp - 1] **= b;
24781
+ break;
24782
+ }
24783
+ case OP.EQ: {
24784
+ const b = stack[--sp];
24785
+ stack[sp - 1] = stack[sp - 1] === b ? 1 : 0;
24786
+ break;
24787
+ }
24788
+ case OP.NE: {
24789
+ const b = stack[--sp];
24790
+ stack[sp - 1] = stack[sp - 1] !== b ? 1 : 0;
24791
+ break;
24792
+ }
24793
+ case OP.GT: {
24794
+ const b = stack[--sp];
24795
+ stack[sp - 1] = stack[sp - 1] > b ? 1 : 0;
24796
+ break;
24797
+ }
24798
+ case OP.GE: {
24799
+ const b = stack[--sp];
24800
+ stack[sp - 1] = stack[sp - 1] >= b ? 1 : 0;
24801
+ break;
24802
+ }
24803
+ case OP.LT: {
24804
+ const b = stack[--sp];
24805
+ stack[sp - 1] = stack[sp - 1] < b ? 1 : 0;
24806
+ break;
24807
+ }
24808
+ case OP.LE: {
24809
+ const b = stack[--sp];
24810
+ stack[sp - 1] = stack[sp - 1] <= b ? 1 : 0;
24811
+ break;
24812
+ }
24813
+ case OP.AND: {
24814
+ const b = stack[--sp] | 0;
24815
+ stack[sp - 1] = (stack[sp - 1] | 0) & b;
24816
+ break;
24817
+ }
24818
+ case OP.OR: {
24819
+ const b = stack[--sp] | 0;
24820
+ stack[sp - 1] = stack[sp - 1] | 0 | b;
24821
+ break;
24822
+ }
24823
+ case OP.XOR: {
24824
+ const b = stack[--sp] | 0;
24825
+ stack[sp - 1] = (stack[sp - 1] | 0) ^ b;
24826
+ break;
24827
+ }
24828
+ case OP.ATAN: {
24829
+ const b = stack[--sp];
24830
+ const deg = Math.atan2(stack[sp - 1], b) * _RAD_TO_DEG;
24831
+ stack[sp - 1] = deg < 0 ? deg + 360 : deg;
24832
+ break;
24833
+ }
24834
+ case OP.MIN: {
24835
+ const b = stack[--sp];
24836
+ stack[sp - 1] = Math.min(stack[sp - 1], b);
24837
+ break;
24838
+ }
24839
+ case OP.MAX: {
24840
+ const b = stack[--sp];
24841
+ stack[sp - 1] = Math.max(stack[sp - 1], b);
24842
+ break;
24843
+ }
24844
+ case OP.TEE_TMP:
24845
+ tmp[ir[ip++] | 0] = stack[sp - 1];
24846
+ break;
24847
+ case OP.LOAD_TMP:
24848
+ stack[sp++] = tmp[ir[ip++] | 0];
24849
+ break;
24850
+ }
24851
+ }
24852
+ }
24853
+ };
24854
+ var PSStackBasedInterpreter = class {
24855
+ // Safe: JS is single-threaded.
24856
+ static #stack = new Float64Array(100);
24857
+ static #sp = 0;
24858
+ static #push(v) {
24859
+ if (this.#sp < this.#stack.length) {
24860
+ this.#stack[this.#sp++] = v;
24861
+ }
24862
+ }
24863
+ static #execOp(op) {
24864
+ const stack = this.#stack;
24865
+ switch (op) {
24866
+ case TOKEN.true:
24867
+ this.#push(1);
24868
+ break;
24869
+ case TOKEN.false:
24870
+ this.#push(0);
24871
+ break;
24872
+ case TOKEN.abs:
24873
+ stack[this.#sp - 1] = Math.abs(stack[this.#sp - 1]);
24874
+ break;
24875
+ case TOKEN.neg:
24876
+ stack[this.#sp - 1] = -stack[this.#sp - 1];
24877
+ break;
24878
+ case TOKEN.ceiling:
24879
+ stack[this.#sp - 1] = Math.ceil(stack[this.#sp - 1]);
24880
+ break;
24881
+ case TOKEN.floor:
24882
+ stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1]);
24883
+ break;
24884
+ case TOKEN.round:
24885
+ stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1] + 0.5);
24886
+ break;
24887
+ case TOKEN.truncate:
24888
+ stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]);
24889
+ break;
24890
+ case TOKEN.sqrt:
24891
+ stack[this.#sp - 1] = Math.sqrt(stack[this.#sp - 1]);
24892
+ break;
24893
+ case TOKEN.sin:
24894
+ stack[this.#sp - 1] = Math.sin(
24895
+ stack[this.#sp - 1] % 360 * _DEG_TO_RAD
24896
+ );
24897
+ break;
24898
+ case TOKEN.cos:
24899
+ stack[this.#sp - 1] = Math.cos(
24900
+ stack[this.#sp - 1] % 360 * _DEG_TO_RAD
24901
+ );
24902
+ break;
24903
+ case TOKEN.ln:
24904
+ stack[this.#sp - 1] = Math.log(stack[this.#sp - 1]);
24905
+ break;
24906
+ case TOKEN.log:
24907
+ stack[this.#sp - 1] = Math.log10(stack[this.#sp - 1]);
24908
+ break;
24909
+ case TOKEN.cvi:
24910
+ stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]) | 0;
24911
+ break;
24912
+ case TOKEN.cvr:
24913
+ break;
24914
+ // values are already f64
24915
+ case TOKEN.not: {
24916
+ const v = stack[this.#sp - 1];
24917
+ stack[this.#sp - 1] = v === 0 || v === 1 ? 1 - v : ~(v | 0);
24918
+ break;
24919
+ }
24920
+ case TOKEN.add: {
24921
+ const b = stack[--this.#sp];
24922
+ stack[this.#sp - 1] += b;
24923
+ break;
24924
+ }
24925
+ case TOKEN.sub: {
24926
+ const b = stack[--this.#sp];
24927
+ stack[this.#sp - 1] -= b;
24928
+ break;
24929
+ }
24930
+ case TOKEN.mul: {
24931
+ const b = stack[--this.#sp];
24932
+ stack[this.#sp - 1] *= b;
24933
+ break;
24934
+ }
24935
+ case TOKEN.div: {
24936
+ const b = stack[--this.#sp];
24937
+ stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] / b : 0;
24938
+ break;
24939
+ }
24940
+ case TOKEN.idiv: {
24941
+ const b = stack[--this.#sp];
24942
+ stack[this.#sp - 1] = b !== 0 ? Math.trunc(stack[this.#sp - 1] / b) : 0;
24943
+ break;
24944
+ }
24945
+ case TOKEN.mod: {
24946
+ const b = stack[--this.#sp];
24947
+ stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] % b : 0;
24948
+ break;
24949
+ }
24950
+ case TOKEN.exp: {
24951
+ const b = stack[--this.#sp];
24952
+ stack[this.#sp - 1] **= b;
24953
+ break;
24954
+ }
24955
+ case TOKEN.atan: {
24956
+ const dx = stack[--this.#sp];
24957
+ const deg = Math.atan2(stack[this.#sp - 1], dx) * _RAD_TO_DEG;
24958
+ stack[this.#sp - 1] = deg < 0 ? deg + 360 : deg;
24959
+ break;
24960
+ }
24961
+ case TOKEN.eq: {
24962
+ const b = stack[--this.#sp];
24963
+ stack[this.#sp - 1] = stack[this.#sp - 1] === b ? 1 : 0;
24964
+ break;
24965
+ }
24966
+ case TOKEN.ne: {
24967
+ const b = stack[--this.#sp];
24968
+ stack[this.#sp - 1] = stack[this.#sp - 1] !== b ? 1 : 0;
24969
+ break;
24970
+ }
24971
+ case TOKEN.gt: {
24972
+ const b = stack[--this.#sp];
24973
+ stack[this.#sp - 1] = stack[this.#sp - 1] > b ? 1 : 0;
24974
+ break;
24975
+ }
24976
+ case TOKEN.ge: {
24977
+ const b = stack[--this.#sp];
24978
+ stack[this.#sp - 1] = stack[this.#sp - 1] >= b ? 1 : 0;
24979
+ break;
24980
+ }
24981
+ case TOKEN.lt: {
24982
+ const b = stack[--this.#sp];
24983
+ stack[this.#sp - 1] = stack[this.#sp - 1] < b ? 1 : 0;
24984
+ break;
24985
+ }
24986
+ case TOKEN.le: {
24987
+ const b = stack[--this.#sp];
24988
+ stack[this.#sp - 1] = stack[this.#sp - 1] <= b ? 1 : 0;
24989
+ break;
24990
+ }
24991
+ case TOKEN.and: {
24992
+ const b = stack[--this.#sp] | 0;
24993
+ stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) & b;
24994
+ break;
24995
+ }
24996
+ case TOKEN.or: {
24997
+ const b = stack[--this.#sp] | 0;
24998
+ stack[this.#sp - 1] = stack[this.#sp - 1] | 0 | b;
24999
+ break;
25000
+ }
25001
+ case TOKEN.xor: {
25002
+ const b = stack[--this.#sp] | 0;
25003
+ stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) ^ b;
25004
+ break;
25005
+ }
25006
+ case TOKEN.bitshift: {
25007
+ const amt = stack[--this.#sp] | 0;
25008
+ const v = stack[this.#sp - 1] | 0;
25009
+ stack[this.#sp - 1] = amt > 0 ? v << amt : v >> -amt;
25010
+ break;
25011
+ }
25012
+ case TOKEN.min: {
25013
+ const b = stack[--this.#sp];
25014
+ stack[this.#sp - 1] = Math.min(stack[this.#sp - 1], b);
25015
+ break;
25016
+ }
25017
+ case TOKEN.max: {
25018
+ const b = stack[--this.#sp];
25019
+ stack[this.#sp - 1] = Math.max(stack[this.#sp - 1], b);
25020
+ break;
25021
+ }
25022
+ case TOKEN.dup:
25023
+ this.#push(stack[this.#sp - 1]);
25024
+ break;
25025
+ case TOKEN.exch: {
25026
+ const a = stack[--this.#sp];
25027
+ const b = stack[--this.#sp];
25028
+ this.#push(a);
25029
+ this.#push(b);
25030
+ break;
25031
+ }
25032
+ case TOKEN.pop:
25033
+ this.#sp--;
25034
+ break;
25035
+ case TOKEN.copy: {
25036
+ const n = Math.trunc(stack[--this.#sp]);
25037
+ const base = this.#sp - n;
25038
+ for (let k = 0; k < n; k++) {
25039
+ this.#push(stack[base + k]);
25040
+ }
25041
+ break;
25042
+ }
25043
+ case TOKEN.index: {
25044
+ const i = Math.trunc(stack[--this.#sp]);
25045
+ this.#push(stack[this.#sp - 1 - i]);
25046
+ break;
25047
+ }
25048
+ case TOKEN.roll: {
25049
+ const j = Math.trunc(stack[--this.#sp]);
25050
+ const n = Math.trunc(stack[--this.#sp]);
25051
+ if (n > 1 && j !== 0) {
25052
+ const mod = (j % n + n) % n;
25053
+ if (mod !== 0) {
25054
+ const base = this.#sp - n;
25055
+ const sub = stack.slice(base, this.#sp);
25056
+ for (let k = 0; k < n; k++) {
25057
+ stack[base + k] = sub[(k - mod + n) % n];
25058
+ }
25059
+ }
25060
+ }
25061
+ break;
25062
+ }
25063
+ }
25064
+ }
25065
+ static #execBlock(instructions) {
25066
+ for (const instr of instructions) {
25067
+ switch (instr.type) {
25068
+ case PS_NODE.number:
25069
+ this.#push(instr.value);
25070
+ break;
25071
+ case PS_NODE.operator:
25072
+ this.#execOp(instr.op);
25073
+ break;
25074
+ case PS_NODE.if:
25075
+ if (this.#stack[--this.#sp] !== 0) {
25076
+ this.#execBlock(instr.then.instructions);
25077
+ }
25078
+ break;
25079
+ case PS_NODE.ifelse:
25080
+ if (this.#stack[--this.#sp] !== 0) {
25081
+ this.#execBlock(instr.then.instructions);
25082
+ } else {
25083
+ this.#execBlock(instr.otherwise.instructions);
25084
+ }
25085
+ break;
25086
+ }
25087
+ }
25088
+ }
25089
+ /**
25090
+ * @param {import("./ast.js").PsProgram} program
25091
+ * @param {number[]} domain – flat [min0,max0, …]
25092
+ * @param {number[]} range – flat [min0,max0, …]
25093
+ * @returns {Function} – `(src, srcOffset, dest, destOffset) => void`
25094
+ */
25095
+ static build(program, domain, range) {
25096
+ const nIn = domain.length >> 1;
25097
+ const nOut = range.length >> 1;
25098
+ const { instructions } = program.body;
25099
+ return (src, srcOffset, dest, destOffset) => {
25100
+ this.#sp = 0;
25101
+ for (let i = 0; i < nIn; i++) {
25102
+ this.#push(src[srcOffset + i]);
25103
+ }
25104
+ this.#execBlock(instructions);
25105
+ const base = this.#sp - nOut;
25106
+ for (let i = 0; i < nOut; i++) {
25107
+ const v = base + i >= 0 ? this.#stack[base + i] : 0;
25108
+ dest[destOffset + i] = MathClamp(v, range[i * 2], range[i * 2 + 1]);
25109
+ }
25110
+ };
25111
+ }
25112
+ };
25113
+ function buildPostScriptJsFunction(source, domain, range, forceInterpreter = false) {
25114
+ const program = parsePostScriptFunction(source);
25115
+ const ir = !forceInterpreter && new PsJsCompiler(domain, range).compile(program);
25116
+ if (ir) {
25117
+ return (src, srcOffset, dest, destOffset) => {
25118
+ PsJsCompiler.execute(ir, src, srcOffset, dest, destOffset);
25119
+ };
25120
+ }
25121
+ return PSStackBasedInterpreter.build(program, domain, range);
25122
+ }
22515
25123
  var PdfError = class extends Error {
22516
25124
  constructor(code, message) {
22517
25125
  super(message);
@@ -33591,6 +36199,25 @@ var __webpack_exports__JpxImage = __webpack_exports__.JpxImage;
33591
36199
  var __webpack_exports__VerbosityLevel = __webpack_exports__.VerbosityLevel;
33592
36200
  var __webpack_exports__getVerbosityLevel = __webpack_exports__.getVerbosityLevel;
33593
36201
  var __webpack_exports__setVerbosityLevel = __webpack_exports__.setVerbosityLevel;
36202
+ function createCalibratedColorSpace(doc, family, parameters) {
36203
+ const dict = doc.resolveDict(parameters);
36204
+ const array = (key) => {
36205
+ const value = dict ? doc.resolveArray(dictGet(dict, key)) : void 0;
36206
+ return value?.items.map((item) => {
36207
+ const number = doc.resolve(item);
36208
+ return number?.kind === "number" ? number.value : 0;
36209
+ });
36210
+ };
36211
+ const whitePoint = array("WhitePoint") ?? [0.95047, 1, 1.08883];
36212
+ const blackPoint = array("BlackPoint");
36213
+ if (family === "CalGray") {
36214
+ const gamma = dict ? doc.resolve(dictGet(dict, "Gamma")) : void 0;
36215
+ return new CalGrayCS(whitePoint, blackPoint, gamma?.kind === "number" ? gamma.value : void 0);
36216
+ }
36217
+ if (family === "CalRGB") return new CalRGBCS(whitePoint, blackPoint, array("Gamma"), array("Matrix"));
36218
+ return new LabCS(whitePoint, blackPoint, array("Range"));
36219
+ }
36220
+ var cmykColorSpace = new DeviceCmykCS();
33594
36221
  function collectPageLeaves(doc, node, inheritedResources, out = [], visited = /* @__PURE__ */ new Set()) {
33595
36222
  if (!node) return out;
33596
36223
  if (node.kind === "ref") {
@@ -33679,7 +36306,7 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
33679
36306
  palette = lookupNode.bytes;
33680
36307
  }
33681
36308
  let resolvedBaseComp = baseInfo.components;
33682
- if (palette && (baseInfo.isLab || baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calRgbGamma !== void 0 || baseInfo.calGrayGamma !== void 0)) {
36309
+ if (palette && (baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calibrated !== void 0)) {
33683
36310
  const numEntries = Math.max(1, Math.min(hival + 1, Math.floor(palette.length / Math.max(1, baseInfo.components))));
33684
36311
  const rgbaPal = decodeSamplesToRgba(palette, numEntries, 1, 8, baseInfo);
33685
36312
  const rgbPal = new Uint8Array(numEntries * 3);
@@ -33709,74 +36336,21 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
33709
36336
  }
33710
36337
  return { colorSpace: "rgb", colorSpaceLabel: "icc", components: 3 };
33711
36338
  }
33712
- if (kindName === "CalGray") {
33713
- const calDict = doc.resolveDict(resolved.items[1]);
33714
- const gammaNode = calDict ? doc.resolve(dictGet(calDict, "Gamma")) : void 0;
33715
- const gamma = gammaNode?.kind === "number" && gammaNode.value > 0 ? gammaNode.value : 1;
33716
- return { colorSpace: "gray", colorSpaceLabel: "cal-gray", components: 1, calGrayGamma: gamma };
33717
- }
33718
- if (kindName === "CalRGB") {
33719
- const calDict = doc.resolveDict(resolved.items[1]);
33720
- const gammaArr = calDict ? doc.resolveArray(dictGet(calDict, "Gamma")) : void 0;
33721
- let calRgbGamma = [1, 1, 1];
33722
- if (gammaArr && gammaArr.items.length >= 3) {
33723
- const gNums = gammaArr.items.slice(0, 3).map((it) => {
33724
- const r = doc.resolve(it);
33725
- return r?.kind === "number" && r.value > 0 ? r.value : 1;
33726
- });
33727
- calRgbGamma = [gNums[0], gNums[1], gNums[2]];
33728
- }
33729
- const matArr = calDict ? doc.resolveArray(dictGet(calDict, "Matrix")) : void 0;
33730
- let calRgbMatrix;
33731
- if (matArr && matArr.items.length >= 9) {
33732
- calRgbMatrix = matArr.items.slice(0, 9).map((it) => {
33733
- const r = doc.resolve(it);
33734
- return r?.kind === "number" ? r.value : 0;
33735
- });
33736
- }
36339
+ if (kindName === "CalGray" || kindName === "CalRGB" || kindName === "Lab") {
36340
+ const calibrated = createCalibratedColorSpace(doc, kindName, resolved.items[1]);
33737
36341
  return {
33738
- colorSpace: "rgb",
33739
- colorSpaceLabel: "cal-rgb",
33740
- components: 3,
33741
- calRgbGamma,
33742
- calRgbMatrix
36342
+ colorSpace: kindName === "CalGray" ? "gray" : "rgb",
36343
+ colorSpaceLabel: kindName === "CalGray" ? "cal-gray" : kindName === "CalRGB" ? "cal-rgb" : "lab",
36344
+ components: kindName === "CalGray" ? 1 : 3,
36345
+ calibrated
33743
36346
  };
33744
36347
  }
33745
- if (kindName === "Lab") {
33746
- const labDict = doc.resolveDict(resolved.items[1]);
33747
- const rangeArr = labDict ? doc.resolveArray(dictGet(labDict, "Range")) : void 0;
33748
- let labRange = [-100, 100, -100, 100];
33749
- if (rangeArr && rangeArr.items.length >= 4) {
33750
- const nums = rangeArr.items.slice(0, 4).map((it) => {
33751
- const r = doc.resolve(it);
33752
- return r?.kind === "number" ? r.value : 0;
33753
- });
33754
- labRange = [nums[0], nums[1], nums[2], nums[3]];
33755
- }
33756
- return { colorSpace: "rgb", colorSpaceLabel: "lab", components: 3, isLab: true, labRange };
33757
- }
33758
36348
  if (kindName === "Separation" || kindName === "DeviceN") {
33759
36349
  const isDevN = kindName === "DeviceN";
33760
36350
  const namesArr = isDevN ? doc.resolveArray(resolved.items[1]) : void 0;
33761
36351
  const devNComponents = isDevN && namesArr ? Math.max(1, namesArr.items.length) : 1;
33762
36352
  const altInfo = resolveColorSpaceInfo(doc, resolved.items[2], resourcesDict);
33763
36353
  const altSpace = altInfo.colorSpace === "cmyk" ? "cmyk" : altInfo.colorSpace === "gray" ? "gray" : "rgb";
33764
- const fnResolved = doc.resolve(resolved.items[3]);
33765
- const fnDict = fnResolved?.kind === "stream" ? fnResolved.dict : fnResolved?.kind === "dict" ? fnResolved : void 0;
33766
- const ftNode = fnDict ? doc.resolve(dictGet(fnDict, "FunctionType")) : void 0;
33767
- const tintFunctionType = ftNode?.kind === "number" ? ftNode.value : 2;
33768
- const c0Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C0")) : void 0;
33769
- const c1Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C1")) : void 0;
33770
- const nNode = fnDict ? doc.resolve(dictGet(fnDict, "N")) : void 0;
33771
- const c0 = c0Arr ? c0Arr.items.map((it) => {
33772
- const r = doc.resolve(it);
33773
- return r?.kind === "number" ? r.value : 0;
33774
- }) : altSpace === "cmyk" ? [0, 0, 0, 0] : altSpace === "gray" ? [1] : [1, 1, 1];
33775
- const c1 = c1Arr ? c1Arr.items.map((it) => {
33776
- const r = doc.resolve(it);
33777
- return r?.kind === "number" ? r.value : 0;
33778
- }) : altSpace === "cmyk" ? [0, 0, 0, 1] : altSpace === "gray" ? [0] : [0, 0, 0];
33779
- const sepN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
33780
36354
  return {
33781
36355
  colorSpace: altSpace,
33782
36356
  colorSpaceLabel: isDevN ? "devn" : "sep",
@@ -33784,12 +36358,9 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
33784
36358
  isSeparation: !isDevN,
33785
36359
  isDeviceN: isDevN,
33786
36360
  separationAltSpace: altSpace,
33787
- separationC0: c0,
33788
- separationC1: c1,
33789
- separationN: sepN,
36361
+ alternateCalibrated: altInfo.calibrated,
33790
36362
  tintFunctionDoc: doc,
33791
- tintFunctionNode: resolved.items[3],
33792
- tintFunctionType
36363
+ tintFunctionNode: resolved.items[3]
33793
36364
  };
33794
36365
  }
33795
36366
  }
@@ -33939,141 +36510,55 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
33939
36510
  const rgba = new Uint8Array(width * height * 4);
33940
36511
  const pixelCount = width * height;
33941
36512
  if (csInfo.isSeparation || csInfo.isDeviceN) {
33942
- const c0 = csInfo.separationC0 ?? [1, 1, 1];
33943
- const c1 = csInfo.separationC1 ?? [0, 0, 0];
33944
- const expN = csInfo.separationN ?? 1;
33945
36513
  const alt = csInfo.separationAltSpace ?? "rgb";
33946
36514
  const numCh = Math.max(1, csInfo.components);
33947
36515
  const step = bpc === 16 ? 2 : 1;
33948
- const useGenericTintFn = csInfo.tintFunctionDoc !== void 0 && csInfo.tintFunctionNode !== void 0 && (csInfo.tintFunctionType === 0 || csInfo.tintFunctionType === 3 || csInfo.tintFunctionType === 4);
33949
36516
  for (let p = 0; p < pixelCount; p++) {
33950
36517
  const chVals = [];
33951
- let wSum = 0;
33952
36518
  for (let ch3 = 0; ch3 < numCh; ch3++) {
33953
36519
  const sRaw = (rawSamples[(p * numCh + ch3) * step] ?? 0) / 255;
33954
- const tRemapped = remapUnitSampleWithDecode(sRaw, ch3, decodePairs);
33955
- chVals.push(tRemapped);
33956
- wSum += Math.pow(Math.max(0, Math.min(1, tRemapped)), expN);
33957
- }
33958
- if (useGenericTintFn) {
33959
- const outComps = evalShadingFunctionToComponents(
33960
- csInfo.tintFunctionDoc,
33961
- csInfo.tintFunctionNode,
33962
- chVals
33963
- );
33964
- if (alt === "cmyk") {
33965
- const c = outComps[0] ?? 0;
33966
- const m = outComps[1] ?? 0;
33967
- const y = outComps[2] ?? 0;
33968
- const k = outComps[3] ?? 0;
33969
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, (1 - c) * (1 - k))) * 255);
33970
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, (1 - m) * (1 - k))) * 255);
33971
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, (1 - y) * (1 - k))) * 255);
33972
- } else if (alt === "gray") {
33973
- const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
33974
- rgba[p * 4] = gByte;
33975
- rgba[p * 4 + 1] = gByte;
33976
- rgba[p * 4 + 2] = gByte;
33977
- } else {
33978
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
33979
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
33980
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
33981
- }
33982
- rgba[p * 4 + 3] = 255;
33983
- continue;
36520
+ chVals.push(remapUnitSampleWithDecode(sRaw, ch3, decodePairs));
33984
36521
  }
33985
- const w = Math.max(0, Math.min(1, wSum));
33986
- if (alt === "cmyk") {
33987
- const c = (c0[0] ?? 0) + w * ((c1[0] ?? 0) - (c0[0] ?? 0));
33988
- const m = (c0[1] ?? 0) + w * ((c1[1] ?? 0) - (c0[1] ?? 0));
33989
- const y = (c0[2] ?? 0) + w * ((c1[2] ?? 0) - (c0[2] ?? 0));
33990
- const k = (c0[3] ?? 0) + w * ((c1[3] ?? 1) - (c0[3] ?? 0));
33991
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, (1 - c) * (1 - k))) * 255);
33992
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, (1 - m) * (1 - k))) * 255);
33993
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, (1 - y) * (1 - k))) * 255);
36522
+ const outComps = evalShadingFunctionToComponents(
36523
+ csInfo.tintFunctionDoc,
36524
+ csInfo.tintFunctionNode,
36525
+ chVals
36526
+ );
36527
+ if (csInfo.alternateCalibrated) {
36528
+ rgba.set(csInfo.alternateCalibrated.getRgb(outComps, 0), p * 4);
36529
+ } else if (alt === "cmyk") {
36530
+ rgba.set(cmykColorSpace.getRgb([outComps[0] ?? 0, outComps[1] ?? 0, outComps[2] ?? 0, outComps[3] ?? 0], 0), p * 4);
33994
36531
  } else if (alt === "gray") {
33995
- const gVal = (c0[0] ?? 1) + w * ((c1[0] ?? 0) - (c0[0] ?? 1));
33996
- const gByte = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
36532
+ const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
33997
36533
  rgba[p * 4] = gByte;
33998
36534
  rgba[p * 4 + 1] = gByte;
33999
36535
  rgba[p * 4 + 2] = gByte;
34000
36536
  } else {
34001
- const rVal = (c0[0] ?? 1) + w * ((c1[0] ?? 0) - (c0[0] ?? 1));
34002
- const gVal = (c0[1] ?? 1) + w * ((c1[1] ?? 0) - (c0[1] ?? 1));
34003
- const bVal = (c0[2] ?? 1) + w * ((c1[2] ?? 0) - (c0[2] ?? 1));
34004
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, rVal)) * 255);
34005
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
34006
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, bVal)) * 255);
36537
+ rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
36538
+ rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
36539
+ rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
34007
36540
  }
34008
36541
  rgba[p * 4 + 3] = 255;
34009
36542
  }
34010
- } else if (csInfo.isLab) {
34011
- const [amin, amax, bmin, bmax] = csInfo.labRange ?? [-100, 100, -100, 100];
34012
- const invF = (t) => t > 6 / 29 ? t * t * t : 3 * (6 / 29) * (6 / 29) * (t - 4 / 29);
34013
- const toSrgb = (u) => {
34014
- const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
34015
- return Math.round(Math.max(0, Math.min(1, c)) * 255);
34016
- };
36543
+ } else if (csInfo.calibrated?.name === "Lab") {
36544
+ const { amin, amax, bmin, bmax } = csInfo.calibrated;
36545
+ const step = bpc === 16 ? 2 : 1;
34017
36546
  for (let p = 0; p < pixelCount; p++) {
34018
- const s0 = (rawSamples[p * 3] ?? 0) / 255;
34019
- const s1 = (rawSamples[p * 3 + 1] ?? 128) / 255;
34020
- const s2 = (rawSamples[p * 3 + 2] ?? 128) / 255;
34021
- const L = s0 * 100;
34022
- if (L <= 0.01) {
34023
- rgba[p * 4] = 0;
34024
- rgba[p * 4 + 1] = 0;
34025
- rgba[p * 4 + 2] = 0;
34026
- rgba[p * 4 + 3] = 255;
34027
- continue;
34028
- }
34029
- const a = amin + s1 * (amax - amin);
34030
- const b = bmin + s2 * (bmax - bmin);
34031
- const fy = (L + 16) / 116;
34032
- const fx = fy + a / 500;
34033
- const fz = fy - b / 200;
34034
- const X = 0.95047 * invF(fx);
34035
- const Y = 1 * invF(fy);
34036
- const Z = 1.08883 * invF(fz);
34037
- const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
34038
- const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
34039
- const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
34040
- rgba[p * 4] = toSrgb(linR);
34041
- rgba[p * 4 + 1] = toSrgb(linG);
34042
- rgba[p * 4 + 2] = toSrgb(linB);
36547
+ const L = (rawSamples[p * 3 * step] ?? 0) / 255 * 100;
36548
+ const a = amin + (rawSamples[(p * 3 + 1) * step] ?? 128) / 255 * (amax - amin);
36549
+ const b = bmin + (rawSamples[(p * 3 + 2) * step] ?? 128) / 255 * (bmax - bmin);
36550
+ rgba.set(csInfo.calibrated.getRgb([L, a, b], 0), p * 4);
34043
36551
  rgba[p * 4 + 3] = 255;
34044
36552
  }
34045
36553
  } else if (csInfo.colorSpace === "rgb") {
34046
- const hasCalRgb = Boolean(csInfo.calRgbGamma || csInfo.calRgbMatrix);
34047
- const toSrgbByte = (u) => {
34048
- const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
34049
- return Math.round(Math.max(0, Math.min(1, c)) * 255);
34050
- };
34051
36554
  const writeRgbPixel = (p, rByte, gByte, bByte) => {
34052
- let rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
34053
- let gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
34054
- let bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
34055
- if (hasCalRgb) {
34056
- const [gr, gg, gb] = csInfo.calRgbGamma ?? [1, 1, 1];
34057
- const ag = Math.pow(rU, gr);
34058
- const bg = Math.pow(gU, gg);
34059
- const cg = Math.pow(bU, gb);
34060
- if (csInfo.calRgbMatrix && csInfo.calRgbMatrix.length >= 9) {
34061
- const m = csInfo.calRgbMatrix;
34062
- const X = m[0] * ag + m[3] * bg + m[6] * cg;
34063
- const Y = m[1] * ag + m[4] * bg + m[7] * cg;
34064
- const Z = m[2] * ag + m[5] * bg + m[8] * cg;
34065
- const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
34066
- const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
34067
- const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
34068
- rgba[p * 4] = toSrgbByte(linR);
34069
- rgba[p * 4 + 1] = toSrgbByte(linG);
34070
- rgba[p * 4 + 2] = toSrgbByte(linB);
34071
- rgba[p * 4 + 3] = 255;
34072
- return;
34073
- }
34074
- rU = ag;
34075
- gU = bg;
34076
- bU = cg;
36555
+ const rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
36556
+ const gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
36557
+ const bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
36558
+ if (csInfo.calibrated) {
36559
+ rgba.set(csInfo.calibrated.getRgb([rU, gU, bU], 0), p * 4);
36560
+ rgba[p * 4 + 3] = 255;
36561
+ return;
34077
36562
  }
34078
36563
  rgba[p * 4] = Math.round(rU * 255);
34079
36564
  rgba[p * 4 + 1] = Math.round(gU * 255);
@@ -34093,10 +36578,11 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
34093
36578
  }
34094
36579
  } else if (csInfo.colorSpace === "gray") {
34095
36580
  const writeGrayPixel = (p, gByte) => {
34096
- let gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
34097
- if (csInfo.calGrayGamma && csInfo.calGrayGamma !== 1) {
34098
- const lin = Math.pow(gU, csInfo.calGrayGamma);
34099
- gU = lin <= 31308e-7 ? 12.92 * lin : 1.055 * Math.pow(lin, 1 / 2.4) - 0.055;
36581
+ const gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
36582
+ if (csInfo.calibrated) {
36583
+ rgba.set(csInfo.calibrated.getRgb([gU], 0), p * 4);
36584
+ rgba[p * 4 + 3] = 255;
36585
+ return;
34100
36586
  }
34101
36587
  const outG = Math.round(Math.max(0, Math.min(1, gU)) * 255);
34102
36588
  rgba[p * 4] = outG;
@@ -34152,9 +36638,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
34152
36638
  const m = remapUnitSampleWithDecode((rawSamples[p * stride + chStep] ?? 0) / 255, 1, decodePairs);
34153
36639
  const y = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 2] ?? 0) / 255, 2, decodePairs);
34154
36640
  const k = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 3] ?? 0) / 255, 3, decodePairs);
34155
- rgba[p * 4] = Math.round((1 - c) * (1 - k) * 255);
34156
- rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
34157
- rgba[p * 4 + 2] = Math.round((1 - y) * (1 - k) * 255);
36641
+ rgba.set(cmykColorSpace.getRgb([c, m, y, k], 0), p * 4);
34158
36642
  rgba[p * 4 + 3] = 255;
34159
36643
  }
34160
36644
  } else if (csInfo.colorSpace === "index") {
@@ -34192,9 +36676,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
34192
36676
  const m = pal[idx * 4 + 1] / 255;
34193
36677
  const yel = pal[idx * 4 + 2] / 255;
34194
36678
  const k = pal[idx * 4 + 3] / 255;
34195
- rgba[p * 4] = Math.round((1 - c) * (1 - k) * 255);
34196
- rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
34197
- rgba[p * 4 + 2] = Math.round((1 - yel) * (1 - k) * 255);
36679
+ rgba.set(cmykColorSpace.getRgb([c, m, yel, k], 0), p * 4);
34198
36680
  } else {
34199
36681
  rgba[p * 4] = pal[idx * baseComp];
34200
36682
  rgba[p * 4 + 1] = pal[idx * baseComp + 1];
@@ -34746,6 +37228,7 @@ function extractDocumentImages(doc, options = {}) {
34746
37228
  }
34747
37229
  return extracted;
34748
37230
  }
37231
+ var cmykColorSpace2 = new DeviceCmykCS();
34749
37232
  function multiplyMatrices(m1, m2) {
34750
37233
  return [
34751
37234
  m1[0] * m2[0] + m1[1] * m2[2],
@@ -34962,193 +37445,7 @@ function resolvePageFonts(doc, resourcesDict) {
34962
37445
  }
34963
37446
  return fonts;
34964
37447
  }
34965
- function evaluateType4PostScriptTokens(tokens, initialStack) {
34966
- const stack = [...initialStack];
34967
- const runRange = (start, end) => {
34968
- let i = start;
34969
- while (i < end) {
34970
- const tok = tokens[i];
34971
- if (tok === "{") {
34972
- let depth = 1;
34973
- let j = i + 1;
34974
- while (j < end && depth > 0) {
34975
- if (tokens[j] === "{") depth++;
34976
- else if (tokens[j] === "}") depth--;
34977
- j++;
34978
- }
34979
- const blockStart = i + 1;
34980
- const blockEnd = j - 1;
34981
- if (j < end && tokens[j] === "{") {
34982
- let depth2 = 1;
34983
- let k = j + 1;
34984
- while (k < end && depth2 > 0) {
34985
- if (tokens[k] === "{") depth2++;
34986
- else if (tokens[k] === "}") depth2--;
34987
- k++;
34988
- }
34989
- if (k < end && tokens[k] === "ifelse") {
34990
- const cond = stack.pop() ?? 0;
34991
- if (cond !== 0) runRange(blockStart, blockEnd);
34992
- else runRange(j + 1, k - 1);
34993
- i = k + 1;
34994
- continue;
34995
- }
34996
- }
34997
- if (j < end && tokens[j] === "if") {
34998
- const cond = stack.pop() ?? 0;
34999
- if (cond !== 0) runRange(blockStart, blockEnd);
35000
- i = j + 1;
35001
- continue;
35002
- }
35003
- runRange(blockStart, blockEnd);
35004
- i = j;
35005
- continue;
35006
- }
35007
- if (tok === "}") {
35008
- i++;
35009
- continue;
35010
- }
35011
- const numVal2 = Number(tok);
35012
- if (tok.length > 0 && !Number.isNaN(numVal2)) {
35013
- stack.push(numVal2);
35014
- } else if (tok === "true") {
35015
- stack.push(1);
35016
- } else if (tok === "false") {
35017
- stack.push(0);
35018
- } else if (tok === "add") {
35019
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35020
- stack.push(a + b);
35021
- } else if (tok === "sub") {
35022
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35023
- stack.push(a - b);
35024
- } else if (tok === "mul") {
35025
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35026
- stack.push(a * b);
35027
- } else if (tok === "div") {
35028
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
35029
- stack.push(Math.abs(b) > 1e-12 ? a / b : 0);
35030
- } else if (tok === "idiv") {
35031
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
35032
- stack.push(Math.abs(b) > 1e-12 ? Math.trunc(a / b) : 0);
35033
- } else if (tok === "mod") {
35034
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
35035
- stack.push(Math.abs(b) > 1e-12 ? a % b : 0);
35036
- } else if (tok === "neg") {
35037
- stack.push(-(stack.pop() ?? 0));
35038
- } else if (tok === "abs") {
35039
- stack.push(Math.abs(stack.pop() ?? 0));
35040
- } else if (tok === "ceiling") {
35041
- stack.push(Math.ceil(stack.pop() ?? 0));
35042
- } else if (tok === "floor") {
35043
- stack.push(Math.floor(stack.pop() ?? 0));
35044
- } else if (tok === "round") {
35045
- stack.push(Math.round(stack.pop() ?? 0));
35046
- } else if (tok === "truncate" || tok === "cvi") {
35047
- stack.push(Math.trunc(stack.pop() ?? 0));
35048
- } else if (tok === "sqrt") {
35049
- stack.push(Math.sqrt(Math.max(0, stack.pop() ?? 0)));
35050
- } else if (tok === "sin") {
35051
- stack.push(Math.sin((stack.pop() ?? 0) * Math.PI / 180));
35052
- } else if (tok === "cos") {
35053
- stack.push(Math.cos((stack.pop() ?? 0) * Math.PI / 180));
35054
- } else if (tok === "atan") {
35055
- const dx = stack.pop() ?? 1, dy = stack.pop() ?? 0;
35056
- let deg = Math.atan2(dy, dx) * 180 / Math.PI;
35057
- if (deg < 0) deg += 360;
35058
- stack.push(deg);
35059
- } else if (tok === "exp") {
35060
- const exp = stack.pop() ?? 1, base = stack.pop() ?? 0;
35061
- stack.push(Math.pow(base, exp));
35062
- } else if (tok === "ln") {
35063
- stack.push(Math.log(Math.max(1e-12, stack.pop() ?? 1)));
35064
- } else if (tok === "log") {
35065
- stack.push(Math.log10(Math.max(1e-12, stack.pop() ?? 1)));
35066
- } else if (tok === "dup") {
35067
- if (stack.length > 0) stack.push(stack[stack.length - 1]);
35068
- } else if (tok === "exch") {
35069
- if (stack.length >= 2) {
35070
- const b = stack.pop(), a = stack.pop();
35071
- stack.push(b, a);
35072
- }
35073
- } else if (tok === "pop") {
35074
- stack.pop();
35075
- } else if (tok === "copy") {
35076
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
35077
- const slice = stack.slice(Math.max(0, stack.length - n));
35078
- stack.push(...slice);
35079
- } else if (tok === "index") {
35080
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
35081
- const idx = stack.length - 1 - n;
35082
- if (idx >= 0 && idx < stack.length) stack.push(stack[idx]);
35083
- } else if (tok === "roll") {
35084
- const jShift = Math.trunc(stack.pop() ?? 0);
35085
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
35086
- if (n > 0 && stack.length >= n) {
35087
- const sub = stack.splice(stack.length - n, n);
35088
- const modShift = (jShift % n + n) % n;
35089
- const rolled = [...sub.slice(n - modShift), ...sub.slice(0, n - modShift)];
35090
- stack.push(...rolled);
35091
- }
35092
- } else if (tok === "eq") {
35093
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35094
- stack.push(Math.abs(a - b) < 1e-9 ? 1 : 0);
35095
- } else if (tok === "ne") {
35096
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35097
- stack.push(Math.abs(a - b) >= 1e-9 ? 1 : 0);
35098
- } else if (tok === "gt") {
35099
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35100
- stack.push(a > b ? 1 : 0);
35101
- } else if (tok === "ge") {
35102
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35103
- stack.push(a >= b ? 1 : 0);
35104
- } else if (tok === "lt") {
35105
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35106
- stack.push(a < b ? 1 : 0);
35107
- } else if (tok === "le") {
35108
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35109
- stack.push(a <= b ? 1 : 0);
35110
- } else if (tok === "and") {
35111
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35112
- stack.push(a !== 0 && b !== 0 ? 1 : 0);
35113
- } else if (tok === "or") {
35114
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35115
- stack.push(a !== 0 || b !== 0 ? 1 : 0);
35116
- } else if (tok === "not") {
35117
- const a = stack.pop() ?? 0;
35118
- stack.push(a === 0 ? 1 : 0);
35119
- }
35120
- i++;
35121
- }
35122
- };
35123
- runRange(0, tokens.length);
35124
- return stack;
35125
- }
35126
- function tokenizePostScriptCode(bytes) {
35127
- const tokens = [];
35128
- let cur = "";
35129
- for (let i = 0; i < bytes.length; i++) {
35130
- const ch3 = String.fromCharCode(bytes[i]);
35131
- if (ch3 === "{" || ch3 === "}") {
35132
- if (cur.length > 0) {
35133
- tokens.push(cur);
35134
- cur = "";
35135
- }
35136
- tokens.push(ch3);
35137
- } else if (ch3 === " " || ch3 === " " || ch3 === "\n" || ch3 === "\r") {
35138
- if (cur.length > 0) {
35139
- tokens.push(cur);
35140
- cur = "";
35141
- }
35142
- } else {
35143
- cur += ch3;
35144
- }
35145
- }
35146
- if (cur.length > 0) tokens.push(cur);
35147
- if (tokens[0] === "{" && tokens[tokens.length - 1] === "}") {
35148
- return tokens.slice(1, -1);
35149
- }
35150
- return tokens;
35151
- }
37448
+ var postScriptFunctions = /* @__PURE__ */ new WeakMap();
35152
37449
  function evalShadingFunctionToComponents(doc, fnNode, inputs) {
35153
37450
  const inArr = typeof inputs === "number" ? [inputs] : inputs;
35154
37451
  const t = inArr[0] ?? 0;
@@ -35195,35 +37492,50 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
35195
37492
  const decode = getNums("Decode", range);
35196
37493
  const nOut = Math.max(1, Math.floor((decode.length || range.length || 6) / 2));
35197
37494
  const mIn = Math.max(1, size.length);
35198
- let flatGridIndex = 0;
37495
+ const streamBytes = doc.decodeStream(resolved);
37496
+ let vertices = [{ index: 0, weight: 1 }];
35199
37497
  let stride = 1;
35200
37498
  for (let i = 0; i < mIn; i++) {
35201
37499
  const d02 = dom[i * 2] ?? 0;
35202
37500
  const d12 = dom[i * 2 + 1] ?? 1;
35203
- const sMax = Math.max(1, (size[i] ?? 2) - 1);
37501
+ const sMax = Math.max(0, (size[i] ?? 2) - 1);
35204
37502
  const e0 = encode[i * 2] ?? 0;
35205
37503
  const e1 = encode[i * 2 + 1] ?? sMax;
35206
37504
  const x = Math.max(d02, Math.min(d12, inArr[i] ?? 0));
35207
- const u = Math.abs(d12 - d02) > 1e-8 ? (x - d02) / (d12 - d02) : 0;
35208
- const idx = Math.round(Math.max(0, Math.min(sMax, e0 + u * (e1 - e0))));
35209
- flatGridIndex += idx * stride;
37505
+ const u = d12 === d02 ? 0 : (x - d02) / (d12 - d02);
37506
+ const e = Math.max(0, Math.min(sMax, e0 + u * (e1 - e0)));
37507
+ const low = Math.floor(e), fraction = e - low;
37508
+ const next = [];
37509
+ for (const vertex of vertices) {
37510
+ const index = vertex.index + low * stride;
37511
+ if (index * nOut * bps < streamBytes.length * 8) next.push({ index, weight: vertex.weight * (1 - fraction) });
37512
+ if (fraction && (index + stride) * nOut * bps < streamBytes.length * 8) {
37513
+ next.push({ index: index + stride, weight: vertex.weight * fraction });
37514
+ }
37515
+ }
37516
+ vertices = next;
35210
37517
  stride *= size[i] ?? 2;
35211
37518
  }
35212
- const streamBytes = doc.decodeStream(resolved);
37519
+ const maxSample = 2 ** bps - 1;
37520
+ const readSample = (index) => {
37521
+ let bitOffset = index * bps, remaining = bps, value = 0;
37522
+ while (remaining > 0) {
37523
+ const bitInByte = bitOffset % 8;
37524
+ const take = Math.min(remaining, 8 - bitInByte);
37525
+ const byte = streamBytes[Math.floor(bitOffset / 8)] ?? 0;
37526
+ value = value * 2 ** take + (byte >> 8 - bitInByte - take & (1 << take) - 1);
37527
+ bitOffset += take;
37528
+ remaining -= take;
37529
+ }
37530
+ return value / maxSample;
37531
+ };
35213
37532
  const out2 = [];
35214
- const maxSample = bps === 16 ? 65535 : 255;
35215
37533
  for (let j = 0; j < nOut; j++) {
35216
- const sampleIdx = flatGridIndex * nOut + j;
35217
- let rawVal = 0;
35218
- if (bps === 16) {
35219
- rawVal = (streamBytes[sampleIdx * 2] ?? 0) << 8 | (streamBytes[sampleIdx * 2 + 1] ?? 0);
35220
- } else {
35221
- rawVal = streamBytes[sampleIdx] ?? 0;
35222
- }
35223
- const frac = rawVal / maxSample;
37534
+ let value = 0;
37535
+ for (const vertex of vertices) value += readSample(vertex.index * nOut + j) * vertex.weight;
35224
37536
  const dec0 = decode[j * 2] ?? 0;
35225
37537
  const dec1 = decode[j * 2 + 1] ?? 1;
35226
- out2.push(dec0 + frac * (dec1 - dec0));
37538
+ out2.push(dec0 + value * (dec1 - dec0));
35227
37539
  }
35228
37540
  return clampRange(out2);
35229
37541
  }
@@ -35233,34 +37545,40 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
35233
37545
  const d12 = dom[i * 2 + 1] ?? 1;
35234
37546
  return Math.max(d02, Math.min(d12, v));
35235
37547
  });
35236
- const tokens = tokenizePostScriptCode(doc.decodeStream(resolved));
35237
- const stackOut = evaluateType4PostScriptTokens(tokens, clampedInputs);
35238
- return clampRange(stackOut);
37548
+ const source = bytesToString3(doc.decodeStream(resolved));
37549
+ let cached = postScriptFunctions.get(resolved);
37550
+ 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])) {
37551
+ cached = { source, domain: dom, range, evaluate: buildPostScriptJsFunction(source, dom, range) };
37552
+ postScriptFunctions.set(resolved, cached);
37553
+ }
37554
+ const output = [];
37555
+ cached.evaluate(clampedInputs, 0, output, 0);
37556
+ return output;
35239
37557
  }
35240
37558
  if (ft === 3) {
35241
37559
  const fnsArr = doc.resolveArray(dictGet(fnDict, "Functions"));
35242
37560
  const bounds = getNums("Bounds", []);
35243
37561
  const encode = getNums("Encode", []);
35244
37562
  if (fnsArr && fnsArr.items.length > 0) {
37563
+ const input = Math.max(dom[0] ?? 0, Math.min(dom[1] ?? 1, t));
35245
37564
  let segIdx = 0;
35246
- while (segIdx < bounds.length && t >= bounds[segIdx]) segIdx++;
37565
+ while (segIdx < bounds.length && input >= bounds[segIdx]) segIdx++;
35247
37566
  segIdx = Math.min(fnsArr.items.length - 1, segIdx);
35248
37567
  const b0 = segIdx === 0 ? dom[0] ?? 0 : bounds[segIdx - 1];
35249
37568
  const b1 = segIdx < bounds.length ? bounds[segIdx] : dom[1] ?? 1;
35250
37569
  const e0 = encode[segIdx * 2] ?? 0;
35251
37570
  const e1 = encode[segIdx * 2 + 1] ?? 1;
35252
- const localT = Math.abs(b1 - b0) > 1e-8 ? e0 + (t - b0) / (b1 - b0) * (e1 - e0) : e0;
35253
- return evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], Math.max(0, Math.min(1, localT)));
37571
+ const localT = b1 !== b0 ? e0 + (input - b0) / (b1 - b0) * (e1 - e0) : e0;
37572
+ return clampRange(evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], localT));
35254
37573
  }
35255
37574
  }
35256
- const c0 = getNums("C0", [0, 0, 0]);
35257
- const c1 = getNums("C1", [1, 1, 1]);
37575
+ const c0 = getNums("C0", [0]);
37576
+ const c1 = getNums("C1", [1]);
35258
37577
  const nNode = doc.resolve(dictGet(fnDict, "N"));
35259
- const expN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
37578
+ const expN = nNode?.kind === "number" ? nNode.value : 1;
35260
37579
  const d0 = dom[0] ?? 0;
35261
37580
  const d1 = dom[1] ?? 1;
35262
- const normT = Math.abs(d1 - d0) > 1e-8 ? (t - d0) / (d1 - d0) : t;
35263
- const w = Math.pow(Math.max(0, Math.min(1, normT)), expN);
37581
+ const w = Math.pow(Math.max(d0, Math.min(d1, t)), expN);
35264
37582
  const len = Math.max(c0.length, c1.length);
35265
37583
  const out = [];
35266
37584
  for (let i = 0; i < len; i++) {
@@ -35276,30 +37594,14 @@ function shadingComponentsToRgb(csName, comps) {
35276
37594
  return [v, v, v];
35277
37595
  }
35278
37596
  if (csName === "DeviceCMYK" || csName === "CMYK" || comps.length >= 4) {
35279
- const cc = comps[0] ?? 0, cm = comps[1] ?? 0, cy = comps[2] ?? 0, ck = comps[3] ?? 0;
35280
- return [(1 - cc) * (1 - ck), (1 - cm) * (1 - kClamp(ck)), (1 - cy) * (1 - kClamp(ck))];
37597
+ const rgb2 = cmykColorSpace2.getRgb([comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0, comps[3] ?? 0], 0);
37598
+ return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
35281
37599
  }
35282
37600
  return [comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0];
35283
37601
  }
35284
37602
  function kClamp(v) {
35285
37603
  return Math.max(0, Math.min(1, v));
35286
37604
  }
35287
- function xyzToSrgb(X, Y, Z, Xw = 0.95047, Yw = 1, Zw = 1.08883) {
35288
- const scaleX = Xw > 1e-6 ? 0.95047 / Xw : 1;
35289
- const scaleY = Yw > 1e-6 ? 1 / Yw : 1;
35290
- const scaleZ = Zw > 1e-6 ? 1.08883 / Zw : 1;
35291
- const x = X * scaleX;
35292
- const y = Y * scaleY;
35293
- const z = Z * scaleZ;
35294
- const rl = 3.2404542 * x - 1.5371385 * y - 0.4985314 * z;
35295
- const gl = -0.969266 * x + 1.8760108 * y + 0.041556 * z;
35296
- const bl = 0.0556434 * x - 0.2040259 * y + 1.0572252 * z;
35297
- const toGamma = (u) => {
35298
- const c = Math.max(0, Math.min(1, u));
35299
- return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
35300
- };
35301
- return [toGamma(rl), toGamma(gl), toGamma(bl)];
35302
- }
35303
37605
  function getColorSpaceComponentCount(doc, csNode, activeResources, depth = 0) {
35304
37606
  if (!csNode || depth > 4) return 3;
35305
37607
  const resolved = doc ? doc.resolve(csNode) : csNode;
@@ -35356,63 +37658,10 @@ function convertColorSpaceComponentsToRgb(doc, csNode, csNameFallback, comps, ac
35356
37658
  if (resolved.kind === "array" && resolved.items.length > 0 && doc) {
35357
37659
  const familyNode = doc.resolve(resolved.items[0]);
35358
37660
  const family = familyNode?.kind === "name" ? familyNode.decoded : "";
35359
- if (family === "CalGray") {
35360
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
35361
- const gNode = paramDict ? doc.resolve(dictGet(paramDict, "Gamma")) : void 0;
35362
- const gamma = gNode?.kind === "number" && gNode.value > 0 ? gNode.value : 1;
35363
- const a = Math.pow(kClamp(comps[0] ?? 0), gamma);
35364
- return [a, a, a];
35365
- }
35366
- if (family === "CalRGB") {
35367
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
35368
- const gammaArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Gamma")) : void 0;
35369
- const getArrNum = (arr, idx, fb) => {
35370
- const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
35371
- return r?.kind === "number" ? r.value : fb;
35372
- };
35373
- const gr = getArrNum(gammaArr, 0, 1);
35374
- const gg = getArrNum(gammaArr, 1, 1);
35375
- const gb = getArrNum(gammaArr, 2, 1);
35376
- const ag = Math.pow(kClamp(comps[0] ?? 0), gr > 0 ? gr : 1);
35377
- const bg = Math.pow(kClamp(comps[1] ?? 0), gg > 0 ? gg : 1);
35378
- const cg = Math.pow(kClamp(comps[2] ?? 0), gb > 0 ? gb : 1);
35379
- const matArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Matrix")) : void 0;
35380
- if (matArr && matArr.items.length >= 9) {
35381
- const m = (i) => getArrNum(matArr, i, 0);
35382
- const X = m(0) * ag + m(3) * bg + m(6) * cg;
35383
- const Y = m(1) * ag + m(4) * bg + m(7) * cg;
35384
- const Z = m(2) * ag + m(5) * bg + m(8) * cg;
35385
- const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
35386
- const Xw = getArrNum(wpArr, 0, 0.95047);
35387
- const Yw = getArrNum(wpArr, 1, 1);
35388
- const Zw = getArrNum(wpArr, 2, 1.08883);
35389
- return xyzToSrgb(X, Y, Z, Xw, Yw, Zw);
35390
- }
35391
- return [ag, bg, cg];
35392
- }
35393
- if (family === "Lab") {
35394
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
35395
- const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
35396
- const rangeArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Range")) : void 0;
35397
- const getNum = (arr, idx, fb) => {
35398
- const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
35399
- return r?.kind === "number" ? r.value : fb;
35400
- };
35401
- const Xw = getNum(wpArr, 0, 0.95047);
35402
- const Yw = getNum(wpArr, 1, 1);
35403
- const Zw = getNum(wpArr, 2, 1.08883);
35404
- const amin = getNum(rangeArr, 0, -100);
35405
- const amax = getNum(rangeArr, 1, 100);
35406
- const bmin = getNum(rangeArr, 2, -100);
35407
- const bmax = getNum(rangeArr, 3, 100);
35408
- const Lstar = Math.max(0, Math.min(100, comps[0] ?? 0));
35409
- const astar = Math.max(amin, Math.min(amax, comps[1] ?? 0));
35410
- const bstar = Math.max(bmin, Math.min(bmax, comps[2] ?? 0));
35411
- const M = (Lstar + 16) / 116;
35412
- const L = M + astar / 500;
35413
- const N = M - bstar / 200;
35414
- const gFn = (x) => x >= 6 / 29 ? x * x * x : 108 / 841 * (x - 4 / 29);
35415
- return xyzToSrgb(Xw * gFn(L), Yw * gFn(M), Zw * gFn(N), Xw, Yw, Zw);
37661
+ if (family === "CalGray" || family === "CalRGB" || family === "Lab") {
37662
+ const colorSpace = createCalibratedColorSpace(doc, family, resolved.items[1]);
37663
+ const rgb2 = colorSpace.getRgb(comps, 0);
37664
+ return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
35416
37665
  }
35417
37666
  if (family === "ICCBased" && resolved.items[1]) {
35418
37667
  const iccNode = doc.resolve(resolved.items[1]);
@@ -36063,7 +38312,8 @@ function evaluateContentStreamToDisplayList(params) {
36063
38312
  const shDict = shNode?.kind === "dict" ? shNode : shNode?.kind === "stream" ? shNode.dict : void 0;
36064
38313
  const shStream = shNode?.kind === "stream" ? shNode : void 0;
36065
38314
  if (shDict) {
36066
- const targetBox = st.clipRect ?? [0, 0, params.width, params.height];
38315
+ const [originX, originY] = params.origin ?? [0, 0];
38316
+ const targetBox = st.clipRect ?? [originX, originY, originX + params.width, originY + params.height];
36067
38317
  const img = renderShadingDictToImage(
36068
38318
  params.cosDoc,
36069
38319
  shDict,
@@ -36102,12 +38352,10 @@ function evaluateContentStreamToDisplayList(params) {
36102
38352
  } else if (operator === "RG" || operator === "SC" || operator === "SCN") {
36103
38353
  st.strokeColor = resolveScColorOperands(operator === "RG" ? "DeviceRGB" : st.strokeColorSpaceName, ops, activeResources);
36104
38354
  } else if (operator === "k") {
36105
- const c = num(0), m = num(1), y = num(2), k = num(3);
36106
- st.fillColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
38355
+ st.fillColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
36107
38356
  st.fillPatternName = void 0;
36108
38357
  } else if (operator === "K") {
36109
- const c = num(0), m = num(1), y = num(2), k = num(3);
36110
- st.strokeColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
38358
+ st.strokeColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
36111
38359
  } else if (operator === "gs" && params.cosDoc && activeResources && ops[0]?.kind === "name") {
36112
38360
  const extDict = params.cosDoc.resolveDict(dictGet(activeResources, "ExtGState"));
36113
38361
  const gsDict = extDict ? params.cosDoc.resolveDict(dictGet(extDict, ops[0].decoded)) : void 0;
@@ -36316,7 +38564,7 @@ function evaluateContentStreamToDisplayList(params) {
36316
38564
  stateStack.pop();
36317
38565
  capturedOperations = parentOperations;
36318
38566
  }
36319
- if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
38567
+ if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, isolated, bboxClip: nextClipPaths?.[0], blendMode: st.blendMode, clipRect: st.clipRect } });
36320
38568
  };
36321
38569
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
36322
38570
  for (const node of nodes) {
@@ -36900,6 +39148,7 @@ function evaluateContentStreamToDisplayList(params) {
36900
39148
  pageIndex: params.pageIndex,
36901
39149
  width: params.width,
36902
39150
  height: params.height,
39151
+ ...params.origin ? { origin: params.origin } : {},
36903
39152
  rotation: params.rotation ?? 0,
36904
39153
  glyphs,
36905
39154
  paths,
@@ -38370,7 +40619,7 @@ var PdfPage = class {
38370
40619
  return [n0.value, n1.value, n2.value, n3.value];
38371
40620
  }
38372
40621
  }
38373
- return [0, 0, 612, 792];
40622
+ return key === "MediaBox" ? [0, 0, 612, 792] : this.resolveBox("MediaBox");
38374
40623
  }
38375
40624
  getMediaBox() {
38376
40625
  return this.resolveBox("MediaBox");
@@ -39043,16 +41292,19 @@ var PdfPage = class {
39043
41292
  });
39044
41293
  }
39045
41294
  }
39046
- return evaluateContentStreamToDisplayList({
41295
+ const mediaBox = this.getMediaBox(), cropBox = this.getCropBox();
41296
+ const originX = Math.min(mediaBox[0], mediaBox[2]), originY = Math.min(mediaBox[1], mediaBox[3]);
41297
+ return { ...evaluateContentStreamToDisplayList({
39047
41298
  pageIndex: this.index,
39048
41299
  width,
39049
41300
  height,
41301
+ origin: [originX, originY],
39050
41302
  rotation: this.getRotation(),
39051
41303
  nodes: baseNodes,
39052
41304
  cosDoc: this.cosDoc,
39053
41305
  resourcesDict: evalResourcesDict,
39054
41306
  annotations: extractPageAnnotations(this.cosDoc, this.pageDict)
39055
- });
41307
+ }), cropBox: [cropBox[0] - originX, cropBox[1] - originY, cropBox[2] - originX, cropBox[3] - originY] };
39056
41308
  }
39057
41309
  extractPage(options) {
39058
41310
  const dl = this.evaluateDisplayList();
@@ -39070,10 +41322,10 @@ var PdfPage = class {
39070
41322
  return extractTablesFromDisplayList(this.evaluateDisplayList());
39071
41323
  }
39072
41324
  renderToBitmap(options) {
39073
- return renderDisplayListToBitmap(this.evaluateDisplayList(), options);
41325
+ return renderDisplayListToBitmap(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
39074
41326
  }
39075
41327
  renderToPng(options) {
39076
- return renderDisplayListToPng(this.evaluateDisplayList(), options);
41328
+ return renderDisplayListToPng(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
39077
41329
  }
39078
41330
  };
39079
41331
  function createStandardFontHandle(standardName) {
@@ -40350,7 +42602,7 @@ function prepareStroke(path, scale) {
40350
42602
  }
40351
42603
  return { matrix, width, dashArray, dashPhase };
40352
42604
  }
40353
- function strokeContours(path, pageHeight, scale) {
42605
+ function strokeContours(path, pageHeight, scale, originX = 0, originY = 0) {
40354
42606
  const stroke = prepareStroke(path, scale);
40355
42607
  if (!stroke) return [];
40356
42608
  const inverse = inverseStrokeMatrix(stroke.matrix);
@@ -40362,8 +42614,8 @@ function strokeContours(path, pageHeight, scale) {
40362
42614
  (inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
40363
42615
  ];
40364
42616
  const toScreen = ([x, y]) => [
40365
- (a * x / strokeScale + c * y / strokeScale + e) * scale,
40366
- (pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
42617
+ (a * x / strokeScale + c * y / strokeScale + e - originX) * scale,
42618
+ (pageHeight + originY - b * x / strokeScale - d * y / strokeScale - f) * scale
40367
42619
  ];
40368
42620
  const contours = strokeOutlines(
40369
42621
  segmentsToScreenPaths(path.segments, pageHeight, scale, project),
@@ -40521,18 +42773,34 @@ function renderSoftMask(mask, displayList, scale) {
40521
42773
  }
40522
42774
  return bitmap;
40523
42775
  }
40524
- function hasBlendModes(operations) {
40525
- return operations.some((operation) => !!operation.value.blendMode && operation.value.blendMode !== "Normal" && operation.value.blendMode !== "Compatible" || operation.kind === "group" && hasBlendModes(operation.value.operations));
42776
+ function getDisplayListCropBox(list) {
42777
+ const full = [0, 0, list.width, list.height];
42778
+ const box = list.cropBox;
42779
+ if (!box || !box.every(Number.isFinite)) return full;
42780
+ const x0 = Math.max(0, Math.min(box[0], box[2]));
42781
+ const y0 = Math.max(0, Math.min(box[1], box[3]));
42782
+ const x1 = Math.min(list.width, Math.max(box[0], box[2]));
42783
+ const y1 = Math.min(list.height, Math.max(box[1], box[3]));
42784
+ return x1 > x0 && y1 > y0 ? [x0, y0, x1, y1] : full;
42785
+ }
42786
+ function hasCompositingEffects(operations, includeSoftMasks = false) {
42787
+ 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));
42788
+ }
42789
+ function needsGroupBackdrop(group) {
42790
+ return group.isolated === false && !!group.softMask && hasCompositingEffects(group.operations, true);
40526
42791
  }
40527
42792
  function renderDisplayListToBitmap(displayList, options = {}) {
40528
42793
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
40529
42794
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
40530
42795
  const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
40531
42796
  const scale = scaleX;
42797
+ const [originX, originY] = displayList.origin ?? [0, 0];
42798
+ const pageTop = originY + displayList.height;
42799
+ const toScreen = (x, y) => [(x - originX) * scale, (pageTop - y) * scale];
40532
42800
  const width = Math.max(1, Math.round(displayList.width * scale));
40533
42801
  const height = Math.max(1, Math.round(displayList.height * scale));
40534
42802
  const rgba = new Uint8Array(width * height * 4);
40535
- const deferBackground = !options.transparent && hasBlendModes(paintOperations(displayList));
42803
+ const deferBackground = !options.transparent && hasCompositingEffects(paintOperations(displayList));
40536
42804
  const transparent = options.transparent || deferBackground;
40537
42805
  const bg = options.background ?? { r: 1, g: 1, b: 1 };
40538
42806
  const bgR = transparent ? 0 : Math.round(bg.r * 255);
@@ -40557,14 +42825,27 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40557
42825
  let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
40558
42826
  if (operation.kind === "group") {
40559
42827
  const group = operation.value;
40560
- const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations: group.operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, transparent: true });
42828
+ let operations = group.operations;
42829
+ if (needsGroupBackdrop(group)) {
42830
+ operations = [{ kind: "image", value: {
42831
+ name: "GroupBackdrop",
42832
+ width,
42833
+ height,
42834
+ decodedRgba: rgba.slice(),
42835
+ matrix: [width / scale, 0, 0, height / scale, originX, pageTop - height / scale],
42836
+ colorSpace: "DeviceRGB",
42837
+ bitsPerComponent: 8,
42838
+ ...group.bboxClip ? { clipPaths: [group.bboxClip] } : {}
42839
+ } }, ...operations];
42840
+ }
42841
+ const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, useCropBox: false, transparent: true });
40561
42842
  for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
40562
42843
  operation = { kind: "image", value: {
40563
42844
  name: "TransparencyGroup",
40564
42845
  width: bitmap.width,
40565
42846
  height: bitmap.height,
40566
42847
  decodedRgba: bitmap.data,
40567
- matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, 0, displayList.height - bitmap.height / scale],
42848
+ matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, originX, pageTop - bitmap.height / scale],
40568
42849
  colorSpace: "DeviceRGB",
40569
42850
  bitsPerComponent: 8,
40570
42851
  blendMode: group.blendMode,
@@ -40578,7 +42859,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40578
42859
  for (const clip of clips) {
40579
42860
  const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
40580
42861
  const layer = new Uint8Array(width * height * 4);
40581
- fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
42862
+ fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale, toScreen), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
40582
42863
  for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
40583
42864
  }
40584
42865
  cachedClips = clips;
@@ -40625,15 +42906,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40625
42906
  if (operation.kind === "path") {
40626
42907
  const path = operation.value;
40627
42908
  if (path.fillColor) {
40628
- const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale), true);
40629
- 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;
42909
+ const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale, toScreen), true);
42910
+ 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;
40630
42911
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
40631
42912
  }
40632
42913
  if (path.strokeColor) {
40633
42914
  const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
40634
42915
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
40635
- const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
40636
- const clipScreen = path.clipRect ? [path.clipRect[0] * scale, (displayList.height - path.clipRect[3]) * scale, path.clipRect[2] * scale, (displayList.height - path.clipRect[1]) * scale] : void 0;
42916
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale, originX, originY).map((points) => ({ points, closed: true })));
42917
+ 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;
40637
42918
  fillEdgesScanline4x4(
40638
42919
  rgba,
40639
42920
  width,
@@ -40656,12 +42937,12 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40656
42937
  if (Math.abs(det) <= 1e-8) continue;
40657
42938
  const cornersPdfX = [e, a + e, a + c + e, c + e];
40658
42939
  const cornersPdfY = [f, b + f, b + d + f, d + f];
40659
- const cornersPx = cornersPdfX.map((cx) => cx * scale);
40660
- const cornersPy = cornersPdfY.map((cy) => (displayList.height - cy) * scale);
40661
- const clipMinPx = img.clipRect ? Math.floor(img.clipRect[0] * scale) : 0;
40662
- const clipMaxPx = img.clipRect ? Math.ceil(img.clipRect[2] * scale) - 1 : width - 1;
40663
- const clipMinPy = img.clipRect ? Math.floor((displayList.height - img.clipRect[3]) * scale) : 0;
40664
- const clipMaxPy = img.clipRect ? Math.ceil((displayList.height - img.clipRect[1]) * scale) - 1 : height - 1;
42940
+ const cornersPx = cornersPdfX.map((cx) => (cx - originX) * scale);
42941
+ const cornersPy = cornersPdfY.map((cy) => (pageTop - cy) * scale);
42942
+ const clipMinPx = img.clipRect ? Math.floor((img.clipRect[0] - originX) * scale) : 0;
42943
+ const clipMaxPx = img.clipRect ? Math.ceil((img.clipRect[2] - originX) * scale) - 1 : width - 1;
42944
+ const clipMinPy = img.clipRect ? Math.floor((pageTop - img.clipRect[3]) * scale) : 0;
42945
+ const clipMaxPy = img.clipRect ? Math.ceil((pageTop - img.clipRect[1]) * scale) - 1 : height - 1;
40665
42946
  const minPx = Math.max(0, clipMinPx, Math.floor(Math.min(...cornersPx)));
40666
42947
  const maxPx = Math.min(width - 1, clipMaxPx, Math.ceil(Math.max(...cornersPx)) - 1);
40667
42948
  const minPy = Math.max(0, clipMinPy, Math.floor(Math.min(...cornersPy)));
@@ -40678,11 +42959,11 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40678
42959
  const smooth = Math.fround((s1 + s2 + Math.hypot(s1 - s2, 2 * cross)) / 2) <= 1;
40679
42960
  const sample = new Float64Array(4);
40680
42961
  for (let py = minPy; py <= maxPy; py++) {
40681
- const yPdf = displayList.height - (py + 0.5) / scale;
42962
+ const yPdf = pageTop - (py + 0.5) / scale;
40682
42963
  if (img.clipRect && (yPdf < img.clipRect[1] || yPdf > img.clipRect[3])) continue;
40683
42964
  const dyPdf = yPdf - f;
40684
42965
  for (let px = minPx; px <= maxPx; px++) {
40685
- const xPdf = (px + 0.5) / scale;
42966
+ const xPdf = originX + (px + 0.5) / scale;
40686
42967
  if (img.clipRect && (xPdf < img.clipRect[0] || xPdf > img.clipRect[2])) continue;
40687
42968
  const dxPdf = xPdf - e;
40688
42969
  const u = (d * dxPdf - c * dyPdf) / det;
@@ -40743,6 +43024,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40743
43024
  }
40744
43025
  result = { width: targetW, height: targetH, data: resampled };
40745
43026
  }
43027
+ if (options.useCropBox) {
43028
+ const box = getDisplayListCropBox(displayList);
43029
+ result = cropRgbaBitmap(result, {
43030
+ x: box[0] * scaleX,
43031
+ y: (displayList.height - box[3]) * scaleY,
43032
+ width: (box[2] - box[0]) * scaleX,
43033
+ height: (box[3] - box[1]) * scaleY
43034
+ });
43035
+ }
40746
43036
  result = rotateRgbaBitmapQuarterTurns(result, displayList.rotation ?? 0);
40747
43037
  if (options.cropRect) {
40748
43038
  result = cropRgbaBitmap(result, options.cropRect);