@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
@@ -22706,6 +22706,2614 @@ var PageViewport = class _PageViewport {
22706
22706
  return p;
22707
22707
  }
22708
22708
  };
22709
+ function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
22710
+ const COMPONENTS = 3;
22711
+ alpha01 = alpha01 !== 1 ? 0 : alpha01;
22712
+ const xRatio = w1 / w2;
22713
+ const yRatio = h1 / h2;
22714
+ let newIndex = 0, oldIndex;
22715
+ const xScaled = new Uint16Array(w2);
22716
+ const w1Scanline = w1 * COMPONENTS;
22717
+ for (let i = 0; i < w2; i++) {
22718
+ xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
22719
+ }
22720
+ for (let i = 0; i < h2; i++) {
22721
+ const py = Math.floor(i * yRatio) * w1Scanline;
22722
+ for (let j = 0; j < w2; j++) {
22723
+ oldIndex = py + xScaled[j];
22724
+ dest[newIndex++] = src[oldIndex++];
22725
+ dest[newIndex++] = src[oldIndex++];
22726
+ dest[newIndex++] = src[oldIndex++];
22727
+ newIndex += alpha01;
22728
+ }
22729
+ }
22730
+ }
22731
+ function isDefaultDecodeHelper(decode, expectedLen) {
22732
+ if (!Array.isArray(decode)) {
22733
+ return true;
22734
+ }
22735
+ const decodeLen = decode.length;
22736
+ if (decodeLen < expectedLen) {
22737
+ warn2("Decode map length is too short.");
22738
+ return true;
22739
+ }
22740
+ if (decodeLen > expectedLen) {
22741
+ info("Truncating too long decode map.");
22742
+ decode.length = expectedLen;
22743
+ }
22744
+ return false;
22745
+ }
22746
+ var ColorSpace = class _ColorSpace {
22747
+ static #rgbBuf = new Uint8ClampedArray(3);
22748
+ constructor(name, numComps) {
22749
+ if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _ColorSpace) {
22750
+ unreachable2("Cannot initialize ColorSpace.");
22751
+ }
22752
+ this.name = name;
22753
+ this.numComps = numComps;
22754
+ }
22755
+ /**
22756
+ * Converts the color value to the RGB color. The color components are
22757
+ * located in the src array starting from the srcOffset. Returns the array
22758
+ * of the rgb components, each value ranging from [0,255].
22759
+ */
22760
+ getRgb(src, srcOffset, output = new Uint8ClampedArray(3)) {
22761
+ this.getRgbItem(src, srcOffset, output, 0);
22762
+ return output;
22763
+ }
22764
+ getRgbHex(src, srcOffset) {
22765
+ const buffer = this.getRgb(src, srcOffset, _ColorSpace.#rgbBuf);
22766
+ return Util.makeHexColor(buffer[0], buffer[1], buffer[2]);
22767
+ }
22768
+ /**
22769
+ * Converts the color value to the RGB color, similar to the getRgb method.
22770
+ * The result placed into the dest array starting from the destOffset.
22771
+ */
22772
+ getRgbItem(src, srcOffset, dest, destOffset) {
22773
+ unreachable2("Should not call ColorSpace.getRgbItem");
22774
+ }
22775
+ /**
22776
+ * Converts the specified number of the color values to the RGB colors.
22777
+ * The colors are located in the src array starting from the srcOffset.
22778
+ * The result is placed into the dest array starting from the destOffset.
22779
+ * The src array items shall be in [0,2^bits) range, the dest array items
22780
+ * will be in [0,255] range. alpha01 indicates how many alpha components
22781
+ * there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
22782
+ * array).
22783
+ */
22784
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
22785
+ unreachable2("Should not call ColorSpace.getRgbBuffer");
22786
+ }
22787
+ /**
22788
+ * Converts `count` unscaled colors to RGB, starting at `destOffset`.
22789
+ * Components use the native color-space ranges expected by `getRgbItem`,
22790
+ * and each output has a `3 + alpha01` byte stride.
22791
+ * Subclasses may override this to batch expensive conversions.
22792
+ */
22793
+ getRgbItems(src, count, dest, destOffset, alpha01) {
22794
+ const { numComps } = this;
22795
+ for (let i = 0, srcOffset = 0; i < count; i++, srcOffset += numComps) {
22796
+ this.getRgbItem(src, srcOffset, dest, destOffset);
22797
+ destOffset += 3 + alpha01;
22798
+ }
22799
+ }
22800
+ /**
22801
+ * Returns true if source data will be equal the result/output data.
22802
+ */
22803
+ isPassthrough(bits) {
22804
+ return false;
22805
+ }
22806
+ /**
22807
+ * Refer to the static `ColorSpace.isDefaultDecode` method below.
22808
+ */
22809
+ isDefaultDecode(decode, bpc) {
22810
+ return _ColorSpace.isDefaultDecode(decode, this.numComps);
22811
+ }
22812
+ /**
22813
+ * Fills in the RGB colors in the destination buffer. alpha01 indicates
22814
+ * how many alpha components there are in the dest array; it will be either
22815
+ * 0 (RGB array) or 1 (RGBA array).
22816
+ */
22817
+ fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {
22818
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22819
+ assert2(
22820
+ dest instanceof Uint8ClampedArray,
22821
+ 'ColorSpace.fillRgb: Unsupported "dest" type.'
22822
+ );
22823
+ }
22824
+ const count = originalWidth * originalHeight;
22825
+ let rgbBuf = null;
22826
+ const numComponentColors = 1 << bpc;
22827
+ const needsResizing = originalHeight !== height || originalWidth !== width;
22828
+ if (this.isPassthrough(bpc)) {
22829
+ rgbBuf = comps;
22830
+ } else if (this.numComps === 1 && count > numComponentColors && this.name !== "DeviceGray" && this.name !== "DeviceRGB") {
22831
+ const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);
22832
+ for (let i = 0; i < numComponentColors; i++) {
22833
+ allColors[i] = i;
22834
+ }
22835
+ const colorMap = new Uint8ClampedArray(numComponentColors * 3);
22836
+ this.getRgbBuffer(
22837
+ allColors,
22838
+ 0,
22839
+ numComponentColors,
22840
+ colorMap,
22841
+ 0,
22842
+ bpc,
22843
+ /* alpha01 = */
22844
+ 0
22845
+ );
22846
+ if (!needsResizing) {
22847
+ let destPos = 0;
22848
+ for (let i = 0; i < count; ++i) {
22849
+ const key = comps[i] * 3;
22850
+ dest[destPos++] = colorMap[key];
22851
+ dest[destPos++] = colorMap[key + 1];
22852
+ dest[destPos++] = colorMap[key + 2];
22853
+ destPos += alpha01;
22854
+ }
22855
+ } else {
22856
+ rgbBuf = new Uint8Array(count * 3);
22857
+ let rgbPos = 0;
22858
+ for (let i = 0; i < count; ++i) {
22859
+ const key = comps[i] * 3;
22860
+ rgbBuf[rgbPos++] = colorMap[key];
22861
+ rgbBuf[rgbPos++] = colorMap[key + 1];
22862
+ rgbBuf[rgbPos++] = colorMap[key + 2];
22863
+ }
22864
+ }
22865
+ } else if (!needsResizing) {
22866
+ this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);
22867
+ } else {
22868
+ rgbBuf = new Uint8ClampedArray(count * 3);
22869
+ this.getRgbBuffer(
22870
+ comps,
22871
+ 0,
22872
+ count,
22873
+ rgbBuf,
22874
+ 0,
22875
+ bpc,
22876
+ /* alpha01 = */
22877
+ 0
22878
+ );
22879
+ }
22880
+ if (rgbBuf) {
22881
+ if (needsResizing) {
22882
+ resizeRgbImage(
22883
+ rgbBuf,
22884
+ dest,
22885
+ originalWidth,
22886
+ originalHeight,
22887
+ width,
22888
+ height,
22889
+ alpha01
22890
+ );
22891
+ } else {
22892
+ let destPos = 0, rgbPos = 0;
22893
+ for (let i = 0, ii = width * actualHeight; i < ii; i++) {
22894
+ dest[destPos++] = rgbBuf[rgbPos++];
22895
+ dest[destPos++] = rgbBuf[rgbPos++];
22896
+ dest[destPos++] = rgbBuf[rgbPos++];
22897
+ destPos += alpha01;
22898
+ }
22899
+ }
22900
+ }
22901
+ }
22902
+ /**
22903
+ * True if the colorspace has components in the default range of [0, 1].
22904
+ * This should be true for all colorspaces except for lab color spaces
22905
+ * which are [0,100], [-128, 127], [-128, 127].
22906
+ */
22907
+ get usesZeroToOneRange() {
22908
+ return shadow2(this, "usesZeroToOneRange", true);
22909
+ }
22910
+ /**
22911
+ * Checks if a decode map matches the default decode map for a color space.
22912
+ * This handles the general decode maps where there are two values per
22913
+ * component, e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
22914
+ * This does not handle Lab, Indexed, or Pattern decode maps since they are
22915
+ * slightly different.
22916
+ * @param {Array} decode - Decode map (usually from an image).
22917
+ * @param {number} numComps - Number of components the color space has.
22918
+ */
22919
+ static isDefaultDecode(decode, numComps) {
22920
+ if (isDefaultDecodeHelper(decode, numComps * 2)) {
22921
+ return true;
22922
+ }
22923
+ for (let i = 0, ii = decode.length; i < ii; i += 2) {
22924
+ if (decode[i] !== 0 || decode[i + 1] !== 1) {
22925
+ return false;
22926
+ }
22927
+ }
22928
+ return true;
22929
+ }
22930
+ };
22931
+ var DeviceCmykCS = class extends ColorSpace {
22932
+ constructor() {
22933
+ super("DeviceCMYK", 4);
22934
+ }
22935
+ // The coefficients below was found using numerical analysis: the method of
22936
+ // steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
22937
+ // where color_value is the tabular value from the table of sampled RGB colors
22938
+ // from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
22939
+ // CMYK color conversion using the estimation below:
22940
+ // f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
22941
+ #toRgb(src, srcOffset, srcScale, dest, destOffset) {
22942
+ const c = src[srcOffset] * srcScale;
22943
+ const m = src[srcOffset + 1] * srcScale;
22944
+ const y = src[srcOffset + 2] * srcScale;
22945
+ const k = src[srcOffset + 3] * srcScale;
22946
+ 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);
22947
+ 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);
22948
+ 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);
22949
+ }
22950
+ getRgbItem(src, srcOffset, dest, destOffset) {
22951
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22952
+ assert2(
22953
+ dest instanceof Uint8ClampedArray,
22954
+ 'DeviceCmykCS.getRgbItem: Unsupported "dest" type.'
22955
+ );
22956
+ }
22957
+ this.#toRgb(src, srcOffset, 1, dest, destOffset);
22958
+ }
22959
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
22960
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22961
+ assert2(
22962
+ dest instanceof Uint8ClampedArray,
22963
+ 'DeviceCmykCS.getRgbBuffer: Unsupported "dest" type.'
22964
+ );
22965
+ }
22966
+ const scale = 1 / ((1 << bits) - 1);
22967
+ for (let i = 0; i < count; i++) {
22968
+ this.#toRgb(src, srcOffset, scale, dest, destOffset);
22969
+ srcOffset += 4;
22970
+ destOffset += 3 + alpha01;
22971
+ }
22972
+ }
22973
+ };
22974
+ var CalGrayCS = class extends ColorSpace {
22975
+ constructor(whitePoint, blackPoint, gamma) {
22976
+ super("CalGray", 1);
22977
+ if (!whitePoint) {
22978
+ throw new FormatError(
22979
+ "WhitePoint missing - required for color space CalGray"
22980
+ );
22981
+ }
22982
+ [this.XW, this.YW, this.ZW] = whitePoint;
22983
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
22984
+ this.G = gamma || 1;
22985
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
22986
+ throw new FormatError(
22987
+ `Invalid WhitePoint components for ${this.name}, no fallback available`
22988
+ );
22989
+ }
22990
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
22991
+ info(`Invalid BlackPoint for ${this.name}, falling back to default.`);
22992
+ this.XB = this.YB = this.ZB = 0;
22993
+ }
22994
+ if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
22995
+ warn2(
22996
+ `${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ZB: ${this.ZB}, only default values are supported.`
22997
+ );
22998
+ }
22999
+ if (this.G < 1) {
23000
+ info(
23001
+ `Invalid Gamma: ${this.G} for ${this.name}, falling back to default.`
23002
+ );
23003
+ this.G = 1;
23004
+ }
23005
+ }
23006
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
23007
+ const A = src[srcOffset] * scale;
23008
+ const AG = A ** this.G;
23009
+ const L = this.YW * AG;
23010
+ const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0);
23011
+ dest[destOffset] = val;
23012
+ dest[destOffset + 1] = val;
23013
+ dest[destOffset + 2] = val;
23014
+ }
23015
+ getRgbItem(src, srcOffset, dest, destOffset) {
23016
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23017
+ assert2(
23018
+ dest instanceof Uint8ClampedArray,
23019
+ 'CalGrayCS.getRgbItem: Unsupported "dest" type.'
23020
+ );
23021
+ }
23022
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
23023
+ }
23024
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
23025
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23026
+ assert2(
23027
+ dest instanceof Uint8ClampedArray,
23028
+ 'CalGrayCS.getRgbBuffer: Unsupported "dest" type.'
23029
+ );
23030
+ }
23031
+ const scale = 1 / ((1 << bits) - 1);
23032
+ for (let i = 0; i < count; ++i) {
23033
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
23034
+ srcOffset += 1;
23035
+ destOffset += 3 + alpha01;
23036
+ }
23037
+ }
23038
+ };
23039
+ var CalRGBCS = class _CalRGBCS extends ColorSpace {
23040
+ // See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these
23041
+ // matrices.
23042
+ // prettier-ignore
23043
+ static #BRADFORD_SCALE_MATRIX = new Float32Array([
23044
+ 0.8951,
23045
+ 0.2664,
23046
+ -0.1614,
23047
+ -0.7502,
23048
+ 1.7135,
23049
+ 0.0367,
23050
+ 0.0389,
23051
+ -0.0685,
23052
+ 1.0296
23053
+ ]);
23054
+ // prettier-ignore
23055
+ static #BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([
23056
+ 0.9869929,
23057
+ -0.1470543,
23058
+ 0.1599627,
23059
+ 0.4323053,
23060
+ 0.5183603,
23061
+ 0.0492912,
23062
+ -85287e-7,
23063
+ 0.0400428,
23064
+ 0.9684867
23065
+ ]);
23066
+ // See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html.
23067
+ // prettier-ignore
23068
+ static #SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([
23069
+ 3.2404542,
23070
+ -1.5371385,
23071
+ -0.4985314,
23072
+ -0.969266,
23073
+ 1.8760108,
23074
+ 0.041556,
23075
+ 0.0556434,
23076
+ -0.2040259,
23077
+ 1.0572252
23078
+ ]);
23079
+ static #FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);
23080
+ static #tempNormalizeMatrix = new Float32Array(3);
23081
+ static #tempConvertMatrix1 = new Float32Array(3);
23082
+ static #tempConvertMatrix2 = new Float32Array(3);
23083
+ static #DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8;
23084
+ constructor(whitePoint, blackPoint, gamma, matrix) {
23085
+ super("CalRGB", 3);
23086
+ if (!whitePoint) {
23087
+ throw new FormatError(
23088
+ "WhitePoint missing - required for color space CalRGB"
23089
+ );
23090
+ }
23091
+ const [XW, YW, ZW] = this.whitePoint = whitePoint;
23092
+ const [XB, YB, ZB] = this.blackPoint = blackPoint || new Float32Array(3);
23093
+ [this.GR, this.GG, this.GB] = gamma || new Float32Array([1, 1, 1]);
23094
+ [
23095
+ this.MXA,
23096
+ this.MYA,
23097
+ this.MZA,
23098
+ this.MXB,
23099
+ this.MYB,
23100
+ this.MZB,
23101
+ this.MXC,
23102
+ this.MYC,
23103
+ this.MZC
23104
+ ] = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
23105
+ if (XW < 0 || ZW < 0 || YW !== 1) {
23106
+ throw new FormatError(
23107
+ `Invalid WhitePoint components for ${this.name}, no fallback available`
23108
+ );
23109
+ }
23110
+ if (XB < 0 || YB < 0 || ZB < 0) {
23111
+ info(
23112
+ `Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], falling back to default.`
23113
+ );
23114
+ this.blackPoint = new Float32Array(3);
23115
+ }
23116
+ if (this.GR < 0 || this.GG < 0 || this.GB < 0) {
23117
+ info(
23118
+ `Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ${this.name}, falling back to default.`
23119
+ );
23120
+ this.GR = this.GG = this.GB = 1;
23121
+ }
23122
+ }
23123
+ #matrixProduct(a, b, result) {
23124
+ result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
23125
+ result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
23126
+ result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
23127
+ }
23128
+ #toFlat(sourceWhitePoint, LMS, result) {
23129
+ result[0] = LMS[0] * 1 / sourceWhitePoint[0];
23130
+ result[1] = LMS[1] * 1 / sourceWhitePoint[1];
23131
+ result[2] = LMS[2] * 1 / sourceWhitePoint[2];
23132
+ }
23133
+ #toD65(sourceWhitePoint, LMS, result) {
23134
+ const D65X = 0.95047;
23135
+ const D65Y = 1;
23136
+ const D65Z = 1.08883;
23137
+ result[0] = LMS[0] * D65X / sourceWhitePoint[0];
23138
+ result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
23139
+ result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
23140
+ }
23141
+ #sRGBTransferFunction(color) {
23142
+ if (color <= 31308e-7) {
23143
+ return MathClamp(12.92 * color, 0, 1);
23144
+ }
23145
+ return color >= 0.99554525 ? 1 : MathClamp((1 + 0.055) * color ** (1 / 2.4) - 0.055, 0, 1);
23146
+ }
23147
+ #decodeL(L) {
23148
+ if (L < 0) {
23149
+ return -this.#decodeL(-L);
23150
+ }
23151
+ return L > 8 ? ((L + 16) / 116) ** 3 : L * _CalRGBCS.#DECODE_L_CONSTANT;
23152
+ }
23153
+ #compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
23154
+ if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {
23155
+ result[0] = XYZ_Flat[0];
23156
+ result[1] = XYZ_Flat[1];
23157
+ result[2] = XYZ_Flat[2];
23158
+ return;
23159
+ }
23160
+ const zeroDecodeL = this.#decodeL(0);
23161
+ const X_DST = zeroDecodeL;
23162
+ const X_SRC = this.#decodeL(sourceBlackPoint[0]);
23163
+ const Y_DST = zeroDecodeL;
23164
+ const Y_SRC = this.#decodeL(sourceBlackPoint[1]);
23165
+ const Z_DST = zeroDecodeL;
23166
+ const Z_SRC = this.#decodeL(sourceBlackPoint[2]);
23167
+ const X_Scale = (1 - X_DST) / (1 - X_SRC);
23168
+ const X_Offset = 1 - X_Scale;
23169
+ const Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
23170
+ const Y_Offset = 1 - Y_Scale;
23171
+ const Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
23172
+ const Z_Offset = 1 - Z_Scale;
23173
+ result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
23174
+ result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
23175
+ result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
23176
+ }
23177
+ #normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
23178
+ if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
23179
+ result[0] = XYZ_In[0];
23180
+ result[1] = XYZ_In[1];
23181
+ result[2] = XYZ_In[2];
23182
+ return;
23183
+ }
23184
+ const LMS = result;
23185
+ this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
23186
+ const LMS_Flat = _CalRGBCS.#tempNormalizeMatrix;
23187
+ this.#toFlat(sourceWhitePoint, LMS, LMS_Flat);
23188
+ this.#matrixProduct(
23189
+ _CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
23190
+ LMS_Flat,
23191
+ result
23192
+ );
23193
+ }
23194
+ #normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
23195
+ const LMS = result;
23196
+ this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
23197
+ const LMS_D65 = _CalRGBCS.#tempNormalizeMatrix;
23198
+ this.#toD65(sourceWhitePoint, LMS, LMS_D65);
23199
+ this.#matrixProduct(
23200
+ _CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
23201
+ LMS_D65,
23202
+ result
23203
+ );
23204
+ }
23205
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
23206
+ const A = MathClamp(src[srcOffset] * scale, 0, 1);
23207
+ const B = MathClamp(src[srcOffset + 1] * scale, 0, 1);
23208
+ const C = MathClamp(src[srcOffset + 2] * scale, 0, 1);
23209
+ const AGR = A === 1 ? 1 : A ** this.GR;
23210
+ const BGG = B === 1 ? 1 : B ** this.GG;
23211
+ const CGB = C === 1 ? 1 : C ** this.GB;
23212
+ const X = this.MXA * AGR + this.MXB * BGG + this.MXC * CGB;
23213
+ const Y = this.MYA * AGR + this.MYB * BGG + this.MYC * CGB;
23214
+ const Z = this.MZA * AGR + this.MZB * BGG + this.MZC * CGB;
23215
+ const XYZ = _CalRGBCS.#tempConvertMatrix1;
23216
+ XYZ[0] = X;
23217
+ XYZ[1] = Y;
23218
+ XYZ[2] = Z;
23219
+ const XYZ_Flat = _CalRGBCS.#tempConvertMatrix2;
23220
+ this.#normalizeWhitePointToFlat(this.whitePoint, XYZ, XYZ_Flat);
23221
+ const XYZ_Black = _CalRGBCS.#tempConvertMatrix1;
23222
+ this.#compensateBlackPoint(this.blackPoint, XYZ_Flat, XYZ_Black);
23223
+ const XYZ_D65 = _CalRGBCS.#tempConvertMatrix2;
23224
+ this.#normalizeWhitePointToD65(
23225
+ _CalRGBCS.#FLAT_WHITEPOINT_MATRIX,
23226
+ XYZ_Black,
23227
+ XYZ_D65
23228
+ );
23229
+ const SRGB = _CalRGBCS.#tempConvertMatrix1;
23230
+ this.#matrixProduct(_CalRGBCS.#SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
23231
+ dest[destOffset] = this.#sRGBTransferFunction(SRGB[0]) * 255;
23232
+ dest[destOffset + 1] = this.#sRGBTransferFunction(SRGB[1]) * 255;
23233
+ dest[destOffset + 2] = this.#sRGBTransferFunction(SRGB[2]) * 255;
23234
+ }
23235
+ getRgbItem(src, srcOffset, dest, destOffset) {
23236
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23237
+ assert2(
23238
+ dest instanceof Uint8ClampedArray,
23239
+ 'CalRGBCS.getRgbItem: Unsupported "dest" type.'
23240
+ );
23241
+ }
23242
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
23243
+ }
23244
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
23245
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23246
+ assert2(
23247
+ dest instanceof Uint8ClampedArray,
23248
+ 'CalRGBCS.getRgbBuffer: Unsupported "dest" type.'
23249
+ );
23250
+ }
23251
+ const scale = 1 / ((1 << bits) - 1);
23252
+ for (let i = 0; i < count; ++i) {
23253
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
23254
+ srcOffset += 3;
23255
+ destOffset += 3 + alpha01;
23256
+ }
23257
+ }
23258
+ };
23259
+ var LabCS = class extends ColorSpace {
23260
+ constructor(whitePoint, blackPoint, range) {
23261
+ super("Lab", 3);
23262
+ if (!whitePoint) {
23263
+ throw new FormatError(
23264
+ "WhitePoint missing - required for color space Lab"
23265
+ );
23266
+ }
23267
+ [this.XW, this.YW, this.ZW] = whitePoint;
23268
+ [this.amin, this.amax, this.bmin, this.bmax] = range || [
23269
+ -100,
23270
+ 100,
23271
+ -100,
23272
+ 100
23273
+ ];
23274
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
23275
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
23276
+ throw new FormatError(
23277
+ "Invalid WhitePoint components, no fallback available"
23278
+ );
23279
+ }
23280
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
23281
+ info("Invalid BlackPoint, falling back to default");
23282
+ this.XB = this.YB = this.ZB = 0;
23283
+ }
23284
+ if (this.amin > this.amax || this.bmin > this.bmax) {
23285
+ info("Invalid Range, falling back to defaults");
23286
+ this.amin = -100;
23287
+ this.amax = 100;
23288
+ this.bmin = -100;
23289
+ this.bmax = 100;
23290
+ }
23291
+ }
23292
+ // Function g(x) from spec
23293
+ #fn_g(x) {
23294
+ return x >= 6 / 29 ? x ** 3 : 108 / 841 * (x - 4 / 29);
23295
+ }
23296
+ #decode(value, high1, low2, high2) {
23297
+ return low2 + value * (high2 - low2) / high1;
23298
+ }
23299
+ // If decoding is needed maxVal should be 2^bits per component - 1.
23300
+ #toRgb(src, srcOffset, maxVal, dest, destOffset) {
23301
+ let Ls = src[srcOffset];
23302
+ let as = src[srcOffset + 1];
23303
+ let bs = src[srcOffset + 2];
23304
+ if (maxVal !== false) {
23305
+ Ls = this.#decode(Ls, maxVal, 0, 100);
23306
+ as = this.#decode(as, maxVal, this.amin, this.amax);
23307
+ bs = this.#decode(bs, maxVal, this.bmin, this.bmax);
23308
+ }
23309
+ if (as > this.amax) {
23310
+ as = this.amax;
23311
+ } else if (as < this.amin) {
23312
+ as = this.amin;
23313
+ }
23314
+ if (bs > this.bmax) {
23315
+ bs = this.bmax;
23316
+ } else if (bs < this.bmin) {
23317
+ bs = this.bmin;
23318
+ }
23319
+ const M = (Ls + 16) / 116;
23320
+ const L = M + as / 500;
23321
+ const N = M - bs / 200;
23322
+ const X = this.XW * this.#fn_g(L);
23323
+ const Y = this.YW * this.#fn_g(M);
23324
+ const Z = this.ZW * this.#fn_g(N);
23325
+ let r, g, b;
23326
+ if (this.ZW < 1) {
23327
+ r = X * 3.1339 + Y * -1.617 + Z * -0.4906;
23328
+ g = X * -0.9785 + Y * 1.916 + Z * 0.0333;
23329
+ b = X * 0.072 + Y * -0.229 + Z * 1.4057;
23330
+ } else {
23331
+ r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
23332
+ g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
23333
+ b = X * 0.0557 + Y * -0.204 + Z * 1.057;
23334
+ }
23335
+ dest[destOffset] = Math.sqrt(r) * 255;
23336
+ dest[destOffset + 1] = Math.sqrt(g) * 255;
23337
+ dest[destOffset + 2] = Math.sqrt(b) * 255;
23338
+ }
23339
+ getRgbItem(src, srcOffset, dest, destOffset) {
23340
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23341
+ assert2(
23342
+ dest instanceof Uint8ClampedArray,
23343
+ 'LabCS.getRgbItem: Unsupported "dest" type.'
23344
+ );
23345
+ }
23346
+ this.#toRgb(src, srcOffset, false, dest, destOffset);
23347
+ }
23348
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
23349
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23350
+ assert2(
23351
+ dest instanceof Uint8ClampedArray,
23352
+ 'LabCS.getRgbBuffer: Unsupported "dest" type.'
23353
+ );
23354
+ }
23355
+ const maxVal = (1 << bits) - 1;
23356
+ for (let i = 0; i < count; i++) {
23357
+ this.#toRgb(src, srcOffset, maxVal, dest, destOffset);
23358
+ srcOffset += 3;
23359
+ destOffset += 3 + alpha01;
23360
+ }
23361
+ }
23362
+ isDefaultDecode(decode, bpc) {
23363
+ return true;
23364
+ }
23365
+ get usesZeroToOneRange() {
23366
+ return shadow2(this, "usesZeroToOneRange", false);
23367
+ }
23368
+ };
23369
+ var TOKEN = {
23370
+ // Structural tokens — not keyword operators
23371
+ number: 0,
23372
+ lbrace: 1,
23373
+ rbrace: 2,
23374
+ // Boolean literals
23375
+ true: 3,
23376
+ false: 4,
23377
+ // Arithmetic binary operators
23378
+ add: 5,
23379
+ sub: 6,
23380
+ mul: 7,
23381
+ div: 8,
23382
+ idiv: 9,
23383
+ mod: 10,
23384
+ exp: 11,
23385
+ // Comparison binary operators
23386
+ eq: 12,
23387
+ ne: 13,
23388
+ gt: 14,
23389
+ ge: 15,
23390
+ lt: 16,
23391
+ le: 17,
23392
+ // Bitwise / boolean binary operators
23393
+ and: 18,
23394
+ or: 19,
23395
+ xor: 20,
23396
+ bitshift: 21,
23397
+ // Unary arithmetic operators
23398
+ abs: 22,
23399
+ neg: 23,
23400
+ ceiling: 24,
23401
+ floor: 25,
23402
+ round: 26,
23403
+ truncate: 27,
23404
+ // Unary boolean / bitwise operator
23405
+ not: 28,
23406
+ // Mathematical functions — unary
23407
+ sqrt: 29,
23408
+ sin: 30,
23409
+ cos: 31,
23410
+ ln: 32,
23411
+ log: 33,
23412
+ // Mathematical function — binary
23413
+ atan: 34,
23414
+ // Type conversion operators
23415
+ cvi: 35,
23416
+ cvr: 36,
23417
+ // Stack operators
23418
+ dup: 37,
23419
+ exch: 38,
23420
+ pop: 39,
23421
+ copy: 40,
23422
+ index: 41,
23423
+ roll: 42,
23424
+ // Control flow
23425
+ if: 43,
23426
+ ifelse: 44,
23427
+ // End of input
23428
+ eof: 45,
23429
+ // Synthetic: produced by the optimizer, never emitted by the lexer.
23430
+ min: 46,
23431
+ max: 47
23432
+ };
23433
+ var Token = class {
23434
+ constructor(id, value = null) {
23435
+ this.id = id;
23436
+ this.value = value;
23437
+ }
23438
+ };
23439
+ var Lexer = class _Lexer {
23440
+ // Singletons for every non-number token, built lazily on first construction.
23441
+ // Keyword operator tokens carry their name as `value`; structural tokens
23442
+ // (lbrace, rbrace, eof) carry null.
23443
+ static #singletons = null;
23444
+ static #operatorSingletons = null;
23445
+ static #initSingletons() {
23446
+ const singletons = /* @__PURE__ */ Object.create(null);
23447
+ const operatorSingletons = /* @__PURE__ */ Object.create(null);
23448
+ for (const [name, id] of Object.entries(TOKEN)) {
23449
+ if (name === "number") {
23450
+ continue;
23451
+ }
23452
+ const isOperator = id >= TOKEN.true && id <= TOKEN.ifelse;
23453
+ const token = new Token(id, isOperator ? name : null);
23454
+ singletons[name] = token;
23455
+ if (isOperator) {
23456
+ operatorSingletons[name] = token;
23457
+ }
23458
+ }
23459
+ this.#singletons = singletons;
23460
+ this.#operatorSingletons = operatorSingletons;
23461
+ }
23462
+ constructor(data) {
23463
+ if (!_Lexer.#singletons) {
23464
+ _Lexer.#initSingletons();
23465
+ }
23466
+ this.data = data;
23467
+ this.pos = 0;
23468
+ this.len = data.length;
23469
+ this._numberPattern = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/iy;
23470
+ this._identifierPattern = /[a-z]+/y;
23471
+ }
23472
+ // Skip a % comment, advancing past the next \n or \r (or to EOF).
23473
+ _skipComment() {
23474
+ const lf = this.data.indexOf("\n", this.pos);
23475
+ const cr = this.data.indexOf("\r", this.pos);
23476
+ const eol = Math.min(lf < 0 ? this.len : lf, cr < 0 ? this.len : cr);
23477
+ this.pos = Math.min(eol + 1, this.len);
23478
+ }
23479
+ _getNumber() {
23480
+ this._numberPattern.lastIndex = this.pos;
23481
+ const match = this._numberPattern.exec(this.data);
23482
+ if (!match) {
23483
+ return new Token(TOKEN.number, 0);
23484
+ }
23485
+ const number = parseFloat(match[0]);
23486
+ if (!Number.isFinite(number)) {
23487
+ return new Token(TOKEN.number, 0);
23488
+ }
23489
+ this.pos = this._numberPattern.lastIndex;
23490
+ return new Token(TOKEN.number, number);
23491
+ }
23492
+ _getOperator() {
23493
+ this._identifierPattern.lastIndex = this.pos;
23494
+ const match = this._identifierPattern.exec(this.data);
23495
+ if (!match) {
23496
+ return new Token(TOKEN.number, 0);
23497
+ }
23498
+ this.pos = this._identifierPattern.lastIndex;
23499
+ const op = match[0];
23500
+ const token = _Lexer.#operatorSingletons[op];
23501
+ return token ?? new Token(TOKEN.number, 0);
23502
+ }
23503
+ // Return the next token, or Lexer.#singletons.eof at end of input.
23504
+ next() {
23505
+ while (this.pos < this.len) {
23506
+ const ch3 = this.data.charCodeAt(this.pos++);
23507
+ switch (ch3) {
23508
+ // PostScript white-space characters (PDF32000 §7.2.2)
23509
+ case 0:
23510
+ case 9:
23511
+ case 10:
23512
+ case 12:
23513
+ case 13:
23514
+ case 32:
23515
+ break;
23516
+ case 37:
23517
+ this._skipComment();
23518
+ break;
23519
+ case 123:
23520
+ return _Lexer.#singletons.lbrace;
23521
+ case 125:
23522
+ return _Lexer.#singletons.rbrace;
23523
+ case 43:
23524
+ case 45:
23525
+ this.pos--;
23526
+ return this._getNumber();
23527
+ case 46:
23528
+ this.pos--;
23529
+ return this._getNumber();
23530
+ default:
23531
+ if (ch3 >= 48 && ch3 <= 57) {
23532
+ this.pos--;
23533
+ return this._getNumber();
23534
+ }
23535
+ if (ch3 >= 97 && ch3 <= 122) {
23536
+ this.pos--;
23537
+ return this._getOperator();
23538
+ }
23539
+ return new Token(TOKEN.number, 0);
23540
+ }
23541
+ }
23542
+ return _Lexer.#singletons.eof;
23543
+ }
23544
+ };
23545
+ var PS_VALUE_TYPE = {
23546
+ numeric: 0,
23547
+ // known to be a number (f64 in Wasm)
23548
+ boolean: 1,
23549
+ // known to be a boolean (0.0 = false, 1.0 = true in f64)
23550
+ unknown: 2
23551
+ // indeterminate at compile time
23552
+ };
23553
+ var PS_NODE = {
23554
+ // Parser AST node types (produced by Parser / parsePostScriptFunction)
23555
+ program: 0,
23556
+ block: 1,
23557
+ number: 2,
23558
+ operator: 3,
23559
+ if: 4,
23560
+ ifelse: 5,
23561
+ // Tree AST node types (produced by PSStackToTree)
23562
+ arg: 6,
23563
+ const: 7,
23564
+ unary: 8,
23565
+ binary: 9,
23566
+ ternary: 10
23567
+ };
23568
+ var PsNode = class {
23569
+ constructor(type) {
23570
+ this.type = type;
23571
+ }
23572
+ };
23573
+ var PsProgram = class extends PsNode {
23574
+ constructor(body) {
23575
+ super(PS_NODE.program);
23576
+ this.body = body;
23577
+ }
23578
+ };
23579
+ var PsBlock = class extends PsNode {
23580
+ constructor(instructions) {
23581
+ super(PS_NODE.block);
23582
+ this.instructions = instructions;
23583
+ }
23584
+ };
23585
+ var PsNumber = class extends PsNode {
23586
+ /** @param {number} value */
23587
+ constructor(value) {
23588
+ super(PS_NODE.number);
23589
+ this.value = value;
23590
+ }
23591
+ };
23592
+ var PsOperator = class extends PsNode {
23593
+ /** @param {number} op — one of the TOKEN.* constants from lexer.js */
23594
+ constructor(op) {
23595
+ super(PS_NODE.operator);
23596
+ this.op = op;
23597
+ }
23598
+ };
23599
+ var PsIf = class extends PsNode {
23600
+ /** @param {PsBlock} then */
23601
+ constructor(then) {
23602
+ super(PS_NODE.if);
23603
+ this.then = then;
23604
+ }
23605
+ };
23606
+ var PsIfElse = class extends PsNode {
23607
+ /**
23608
+ * @param {PsBlock} then
23609
+ * @param {PsBlock} otherwise
23610
+ */
23611
+ constructor(then, otherwise) {
23612
+ super(PS_NODE.ifelse);
23613
+ this.then = then;
23614
+ this.otherwise = otherwise;
23615
+ }
23616
+ };
23617
+ var PsArgNode = class extends PsNode {
23618
+ /** @param {number} index */
23619
+ constructor(index) {
23620
+ super(PS_NODE.arg);
23621
+ this.index = index;
23622
+ this.valueType = PS_VALUE_TYPE.numeric;
23623
+ }
23624
+ };
23625
+ var PsConstNode = class extends PsNode {
23626
+ /** @param {number|boolean} value */
23627
+ constructor(value) {
23628
+ super(PS_NODE.const);
23629
+ this.value = value;
23630
+ this.valueType = typeof value === "boolean" ? PS_VALUE_TYPE.boolean : PS_VALUE_TYPE.numeric;
23631
+ }
23632
+ };
23633
+ var PsUnaryNode = class extends PsNode {
23634
+ /**
23635
+ * @param {number} op — TOKEN.* constant
23636
+ * @param {PsNode} operand
23637
+ * @param {number} [valueType]
23638
+ */
23639
+ constructor(op, operand, valueType = PS_VALUE_TYPE.unknown) {
23640
+ super(PS_NODE.unary);
23641
+ this.op = op;
23642
+ this.operand = operand;
23643
+ this.valueType = valueType;
23644
+ }
23645
+ };
23646
+ var PsBinaryNode = class extends PsNode {
23647
+ /**
23648
+ * @param {number} op — TOKEN.* constant
23649
+ * @param {PsNode} first — was on top of stack
23650
+ * @param {PsNode} second — was below top
23651
+ * @param {number} [valueType]
23652
+ */
23653
+ constructor(op, first, second, valueType = PS_VALUE_TYPE.unknown) {
23654
+ super(PS_NODE.binary);
23655
+ this.op = op;
23656
+ this.first = first;
23657
+ this.second = second;
23658
+ this.valueType = valueType;
23659
+ }
23660
+ };
23661
+ var PsTernaryNode = class extends PsNode {
23662
+ /**
23663
+ * @param {PsNode} cond
23664
+ * @param {PsNode} then
23665
+ * @param {PsNode} otherwise
23666
+ * @param {number} [valueType]
23667
+ */
23668
+ constructor(cond, then, otherwise, valueType = PS_VALUE_TYPE.unknown) {
23669
+ super(PS_NODE.ternary);
23670
+ this.cond = cond;
23671
+ this.then = then;
23672
+ this.otherwise = otherwise;
23673
+ this.valueType = valueType;
23674
+ }
23675
+ };
23676
+ var Parser = class _Parser {
23677
+ constructor(lexer) {
23678
+ this.lexer = lexer;
23679
+ this._token = null;
23680
+ }
23681
+ static _isRegularOperator(id) {
23682
+ return id >= TOKEN.true && id < TOKEN.if;
23683
+ }
23684
+ // Fetch the next token from the lexer.
23685
+ _advance() {
23686
+ this._token = this.lexer.next();
23687
+ }
23688
+ // Assert that the current token has the given id, consume it, and return it.
23689
+ _expect(id) {
23690
+ if (this._token.id !== id) {
23691
+ throw new FormatError(
23692
+ `PostScript function: expected token id ${id}, got ${this._token.id}.`
23693
+ );
23694
+ }
23695
+ const tok = this._token;
23696
+ this._advance();
23697
+ return tok;
23698
+ }
23699
+ /**
23700
+ * Parse the full Type 4 function body.
23701
+ *
23702
+ * Grammar (simplified):
23703
+ * program ::= '{' block '}'
23704
+ * block ::= instruction*
23705
+ * instruction ::= number
23706
+ * | operator (any PS_OPERATOR except if / ifelse)
23707
+ * | '{' block '}' 'if'
23708
+ * | '{' block '}' '{' block '}' 'ifelse'
23709
+ * @returns {PsProgram}
23710
+ */
23711
+ parse() {
23712
+ this._advance();
23713
+ this._expect(TOKEN.lbrace);
23714
+ const block = this._parseBlock();
23715
+ this._expect(TOKEN.rbrace);
23716
+ if (this._token.id !== TOKEN.eof) {
23717
+ warn2("PostScript function: unexpected content after closing brace.");
23718
+ }
23719
+ return new PsProgram(block);
23720
+ }
23721
+ _parseBlock() {
23722
+ const instructions = [];
23723
+ while (true) {
23724
+ const tok = this._token;
23725
+ switch (tok.id) {
23726
+ case TOKEN.number:
23727
+ instructions.push(new PsNumber(tok.value));
23728
+ this._advance();
23729
+ break;
23730
+ case TOKEN.lbrace: {
23731
+ this._advance();
23732
+ const thenBlock = this._parseBlock();
23733
+ this._expect(TOKEN.rbrace);
23734
+ if (this._token.id === TOKEN.if) {
23735
+ this._advance();
23736
+ instructions.push(new PsIf(thenBlock));
23737
+ } else if (this._token.id === TOKEN.lbrace) {
23738
+ this._advance();
23739
+ const elseBlock = this._parseBlock();
23740
+ this._expect(TOKEN.rbrace);
23741
+ this._expect(TOKEN.ifelse);
23742
+ instructions.push(new PsIfElse(thenBlock, elseBlock));
23743
+ } else {
23744
+ throw new FormatError(
23745
+ "PostScript function: a procedure block must be followed by 'if' or '{\u2026} ifelse'."
23746
+ );
23747
+ }
23748
+ break;
23749
+ }
23750
+ case TOKEN.rbrace:
23751
+ case TOKEN.eof:
23752
+ return new PsBlock(instructions);
23753
+ case TOKEN.if:
23754
+ case TOKEN.ifelse:
23755
+ throw new FormatError(
23756
+ `PostScript function: unexpected '${tok.value}' operator.`
23757
+ );
23758
+ default:
23759
+ if (_Parser._isRegularOperator(tok.id)) {
23760
+ instructions.push(new PsOperator(tok.id));
23761
+ this._advance();
23762
+ break;
23763
+ }
23764
+ throw new FormatError(
23765
+ `PostScript function: unexpected token id ${tok.id}.`
23766
+ );
23767
+ }
23768
+ }
23769
+ }
23770
+ };
23771
+ function parsePostScriptFunction(source) {
23772
+ return new Parser(new Lexer(source)).parse();
23773
+ }
23774
+ function _nodesEqual(a, b) {
23775
+ if (a === b) {
23776
+ return true;
23777
+ }
23778
+ if (a.type !== b.type) {
23779
+ return false;
23780
+ }
23781
+ switch (a.type) {
23782
+ case PS_NODE.arg:
23783
+ return a.index === b.index;
23784
+ case PS_NODE.const:
23785
+ return a.value === b.value;
23786
+ case PS_NODE.unary:
23787
+ return a.op === b.op && _nodesEqual(a.operand, b.operand);
23788
+ case PS_NODE.binary:
23789
+ return a.op === b.op && _nodesEqual(a.first, b.first) && _nodesEqual(a.second, b.second);
23790
+ case PS_NODE.ternary:
23791
+ return _nodesEqual(a.cond, b.cond) && _nodesEqual(a.then, b.then) && _nodesEqual(a.otherwise, b.otherwise);
23792
+ default:
23793
+ return false;
23794
+ }
23795
+ }
23796
+ function _evalBinaryConst(op, a, b) {
23797
+ switch (op) {
23798
+ case TOKEN.add:
23799
+ return a + b;
23800
+ case TOKEN.sub:
23801
+ return a - b;
23802
+ case TOKEN.mul:
23803
+ return a * b;
23804
+ case TOKEN.div:
23805
+ return b !== 0 ? a / b : 0;
23806
+ // div by zero → 0
23807
+ case TOKEN.idiv:
23808
+ return b !== 0 ? Math.trunc(a / b) : 0;
23809
+ // div by zero → 0
23810
+ case TOKEN.mod:
23811
+ return b !== 0 ? a - Math.trunc(a / b) * b : 0;
23812
+ // div by zero → 0
23813
+ case TOKEN.exp: {
23814
+ const r = a ** b;
23815
+ return Number.isFinite(r) ? r : void 0;
23816
+ }
23817
+ case TOKEN.atan: {
23818
+ let deg = Math.atan2(a, b) * (180 / Math.PI);
23819
+ if (deg < 0) {
23820
+ deg += 360;
23821
+ }
23822
+ return deg;
23823
+ }
23824
+ case TOKEN.eq:
23825
+ return a === b;
23826
+ case TOKEN.ne:
23827
+ return a !== b;
23828
+ case TOKEN.gt:
23829
+ return a > b;
23830
+ case TOKEN.ge:
23831
+ return a >= b;
23832
+ case TOKEN.lt:
23833
+ return a < b;
23834
+ case TOKEN.le:
23835
+ return a <= b;
23836
+ case TOKEN.and:
23837
+ return typeof a === "boolean" ? a && b : a & b | 0;
23838
+ case TOKEN.or:
23839
+ return typeof a === "boolean" ? a || b : a | b | 0;
23840
+ case TOKEN.xor:
23841
+ return typeof a === "boolean" ? a !== b : a ^ b | 0;
23842
+ case TOKEN.bitshift:
23843
+ return b >= 0 ? a << b | 0 : a >> -b | 0;
23844
+ case TOKEN.min:
23845
+ return Math.min(a, b);
23846
+ case TOKEN.max:
23847
+ return Math.max(a, b);
23848
+ default:
23849
+ return void 0;
23850
+ }
23851
+ }
23852
+ function _evalUnaryConst(op, v) {
23853
+ switch (op) {
23854
+ case TOKEN.abs:
23855
+ return Math.abs(v);
23856
+ case TOKEN.neg:
23857
+ return -v;
23858
+ case TOKEN.ceiling:
23859
+ return Math.ceil(v);
23860
+ case TOKEN.floor:
23861
+ return Math.floor(v);
23862
+ case TOKEN.round:
23863
+ return Math.round(v);
23864
+ case TOKEN.truncate:
23865
+ return Math.trunc(v);
23866
+ case TOKEN.sqrt: {
23867
+ const r = Math.sqrt(v);
23868
+ return Number.isFinite(r) ? r : void 0;
23869
+ }
23870
+ case TOKEN.sin:
23871
+ return Math.sin(v % 360 * Math.PI / 180);
23872
+ case TOKEN.cos:
23873
+ return Math.cos(v % 360 * Math.PI / 180);
23874
+ case TOKEN.ln: {
23875
+ const r = Math.log(v);
23876
+ return Number.isFinite(r) ? r : void 0;
23877
+ }
23878
+ case TOKEN.log: {
23879
+ const r = Math.log10(v);
23880
+ return Number.isFinite(r) ? r : void 0;
23881
+ }
23882
+ case TOKEN.cvi:
23883
+ return Math.trunc(v);
23884
+ case TOKEN.cvr:
23885
+ return v;
23886
+ case TOKEN.not:
23887
+ return typeof v === "boolean" ? !v : ~v;
23888
+ default:
23889
+ return void 0;
23890
+ }
23891
+ }
23892
+ var MAX_STACK_SIZE = 100;
23893
+ function _unaryValueType(op, operandType) {
23894
+ return op === TOKEN.not ? operandType : PS_VALUE_TYPE.numeric;
23895
+ }
23896
+ function _binaryValueType(op, firstType, secondType) {
23897
+ switch (op) {
23898
+ // Comparison operators always produce a boolean.
23899
+ case TOKEN.eq:
23900
+ case TOKEN.ne:
23901
+ case TOKEN.gt:
23902
+ case TOKEN.ge:
23903
+ case TOKEN.lt:
23904
+ case TOKEN.le:
23905
+ return PS_VALUE_TYPE.boolean;
23906
+ // and / or / xor preserve the type when both operands are the same known
23907
+ // type (both boolean or both numeric); otherwise the type is unknown.
23908
+ case TOKEN.and:
23909
+ case TOKEN.or:
23910
+ case TOKEN.xor:
23911
+ return firstType === secondType && firstType !== PS_VALUE_TYPE.unknown ? firstType : PS_VALUE_TYPE.unknown;
23912
+ // All arithmetic / bitshift operators produce a numeric result.
23913
+ default:
23914
+ return PS_VALUE_TYPE.numeric;
23915
+ }
23916
+ }
23917
+ var PSStackToTree = class _PSStackToTree {
23918
+ static #binaryOps = null;
23919
+ static #unaryOps = null;
23920
+ static #idempotentUnary = null;
23921
+ static #negatedComparison = null;
23922
+ static #init() {
23923
+ this.#binaryOps = /* @__PURE__ */ new Set([
23924
+ TOKEN.add,
23925
+ TOKEN.sub,
23926
+ TOKEN.mul,
23927
+ TOKEN.div,
23928
+ TOKEN.idiv,
23929
+ TOKEN.mod,
23930
+ TOKEN.exp,
23931
+ TOKEN.atan,
23932
+ TOKEN.eq,
23933
+ TOKEN.ne,
23934
+ TOKEN.gt,
23935
+ TOKEN.ge,
23936
+ TOKEN.lt,
23937
+ TOKEN.le,
23938
+ TOKEN.and,
23939
+ TOKEN.or,
23940
+ TOKEN.xor,
23941
+ TOKEN.bitshift
23942
+ ]);
23943
+ this.#unaryOps = /* @__PURE__ */ new Set([
23944
+ TOKEN.abs,
23945
+ TOKEN.neg,
23946
+ TOKEN.ceiling,
23947
+ TOKEN.floor,
23948
+ TOKEN.round,
23949
+ TOKEN.truncate,
23950
+ TOKEN.sqrt,
23951
+ TOKEN.sin,
23952
+ TOKEN.cos,
23953
+ TOKEN.ln,
23954
+ TOKEN.log,
23955
+ TOKEN.cvi,
23956
+ TOKEN.cvr,
23957
+ TOKEN.not
23958
+ ]);
23959
+ this.#idempotentUnary = /* @__PURE__ */ new Set([
23960
+ TOKEN.abs,
23961
+ TOKEN.ceiling,
23962
+ TOKEN.cvi,
23963
+ TOKEN.cvr,
23964
+ TOKEN.floor,
23965
+ TOKEN.round,
23966
+ TOKEN.truncate
23967
+ ]);
23968
+ this.#negatedComparison = /* @__PURE__ */ new Map([
23969
+ [TOKEN.eq, TOKEN.ne],
23970
+ [TOKEN.ne, TOKEN.eq],
23971
+ [TOKEN.lt, TOKEN.ge],
23972
+ [TOKEN.le, TOKEN.gt],
23973
+ [TOKEN.gt, TOKEN.le],
23974
+ [TOKEN.ge, TOKEN.lt]
23975
+ ]);
23976
+ }
23977
+ /**
23978
+ * @param {PsProgram} program
23979
+ * @param {number} numInputs — number of domain values placed on the stack
23980
+ * before the program runs (i.e. the length of the domain array / 2).
23981
+ * @returns {Array<PsNode>} — one tree node per output value.
23982
+ */
23983
+ evaluate(program, numInputs) {
23984
+ if (!_PSStackToTree.#binaryOps) {
23985
+ _PSStackToTree.#init();
23986
+ }
23987
+ this._failed = false;
23988
+ if (numInputs > MAX_STACK_SIZE) {
23989
+ return null;
23990
+ }
23991
+ const stack = [];
23992
+ for (let i = 0; i < numInputs; i++) {
23993
+ stack.push(new PsArgNode(i));
23994
+ }
23995
+ this._evalBlock(program.body, stack);
23996
+ if (this._failed) {
23997
+ return null;
23998
+ }
23999
+ _PSStackToTree.#markShared(stack);
24000
+ return stack;
24001
+ }
24002
+ // Set node.shared / sharedCount on non-atomic nodes referenced more than
24003
+ // once. arg/const are excluded — they are cheap to re-emit inline.
24004
+ static #markShared(outputs) {
24005
+ const refCount = /* @__PURE__ */ new Map();
24006
+ const visit = (node) => {
24007
+ if (!node || node.type === PS_NODE.arg || node.type === PS_NODE.const) {
24008
+ return;
24009
+ }
24010
+ const prev = refCount.get(node) ?? 0;
24011
+ refCount.set(node, prev + 1);
24012
+ if (prev > 0) {
24013
+ return;
24014
+ }
24015
+ switch (node.type) {
24016
+ case PS_NODE.unary:
24017
+ visit(node.operand);
24018
+ break;
24019
+ case PS_NODE.binary:
24020
+ visit(node.first);
24021
+ visit(node.second);
24022
+ break;
24023
+ case PS_NODE.ternary:
24024
+ visit(node.cond);
24025
+ visit(node.then);
24026
+ visit(node.otherwise);
24027
+ break;
24028
+ }
24029
+ };
24030
+ for (const output of outputs) {
24031
+ visit(output);
24032
+ }
24033
+ for (const [node, count] of refCount) {
24034
+ if (count > 1) {
24035
+ node.shared = true;
24036
+ node.sharedCount = count;
24037
+ }
24038
+ }
24039
+ }
24040
+ _evalBlock(block, stack) {
24041
+ this._evalBlockFrom(block.instructions, 0, stack);
24042
+ }
24043
+ /**
24044
+ * Core evaluation loop. Processes `instructions[startIdx…]` in order,
24045
+ * mutating `stack` as each instruction executes.
24046
+ *
24047
+ * When a `{ body } if` instruction grows the stack (the PostScript "early
24048
+ * exit / guard" idiom), the remaining instructions in the current array are
24049
+ * evaluated on **both** the true-branch stack and the false-branch stack,
24050
+ * then the two results are merged into PsTernaryNodes. This handles
24051
+ * patterns like:
24052
+ *
24053
+ * cond { pop R G B sentinel } if
24054
+ * … more guards …
24055
+ * sentinel 0 gt { defaultR defaultG defaultB } if
24056
+ */
24057
+ _evalBlockFrom(instructions, startIdx, stack) {
24058
+ for (let idx = startIdx; idx < instructions.length; idx++) {
24059
+ if (this._failed) {
24060
+ break;
24061
+ }
24062
+ const instr = instructions[idx];
24063
+ switch (instr.type) {
24064
+ case PS_NODE.number:
24065
+ stack.push(new PsConstNode(instr.value));
24066
+ if (stack.length > MAX_STACK_SIZE) {
24067
+ this._failed = true;
24068
+ }
24069
+ break;
24070
+ case PS_NODE.operator:
24071
+ this._evalOp(instr.op, stack);
24072
+ break;
24073
+ case PS_NODE.if: {
24074
+ if (stack.length < 1) {
24075
+ this._failed = true;
24076
+ break;
24077
+ }
24078
+ const cond = stack.pop();
24079
+ const saved = stack.slice();
24080
+ this._evalBlock(instr.then, stack);
24081
+ if (this._failed) {
24082
+ break;
24083
+ }
24084
+ if (stack.length === saved.length) {
24085
+ for (let i = 0; i < stack.length; i++) {
24086
+ if (stack[i] !== saved[i]) {
24087
+ stack[i] = this._makeTernary(cond, stack[i], saved[i]);
24088
+ }
24089
+ }
24090
+ } else if (stack.length > saved.length) {
24091
+ if (cond.type === PS_NODE.const) {
24092
+ if (!cond.value) {
24093
+ stack.length = 0;
24094
+ stack.push(...saved);
24095
+ }
24096
+ break;
24097
+ }
24098
+ const trueStack = stack.slice();
24099
+ this._evalBlockFrom(instructions, idx + 1, trueStack);
24100
+ if (this._failed) {
24101
+ break;
24102
+ }
24103
+ const falseStack = saved;
24104
+ this._evalBlockFrom(instructions, idx + 1, falseStack);
24105
+ if (this._failed) {
24106
+ break;
24107
+ }
24108
+ if (trueStack.length !== falseStack.length) {
24109
+ const zero2 = new PsConstNode(0);
24110
+ while (trueStack.length < falseStack.length) {
24111
+ trueStack.push(zero2);
24112
+ }
24113
+ while (falseStack.length < trueStack.length) {
24114
+ falseStack.push(zero2);
24115
+ }
24116
+ }
24117
+ stack.length = 0;
24118
+ for (let i = 0; i < trueStack.length; i++) {
24119
+ stack.push(this._makeTernary(cond, trueStack[i], falseStack[i]));
24120
+ }
24121
+ return;
24122
+ } else {
24123
+ this._failed = true;
24124
+ }
24125
+ break;
24126
+ }
24127
+ case PS_NODE.ifelse: {
24128
+ if (stack.length < 1) {
24129
+ this._failed = true;
24130
+ break;
24131
+ }
24132
+ const cond = stack.pop();
24133
+ const snapshot = stack.slice();
24134
+ const thenStack = snapshot.slice();
24135
+ this._evalBlock(instr.then, thenStack);
24136
+ if (this._failed) {
24137
+ break;
24138
+ }
24139
+ const elseStack = snapshot.slice();
24140
+ this._evalBlock(instr.otherwise, elseStack);
24141
+ if (this._failed) {
24142
+ break;
24143
+ }
24144
+ if (thenStack.length !== elseStack.length) {
24145
+ const zero2 = new PsConstNode(0);
24146
+ while (thenStack.length < elseStack.length) {
24147
+ thenStack.push(zero2);
24148
+ }
24149
+ while (elseStack.length < thenStack.length) {
24150
+ elseStack.push(zero2);
24151
+ }
24152
+ }
24153
+ stack.length = 0;
24154
+ for (let i = 0; i < thenStack.length; i++) {
24155
+ stack.push(this._makeTernary(cond, thenStack[i], elseStack[i]));
24156
+ }
24157
+ break;
24158
+ }
24159
+ }
24160
+ }
24161
+ }
24162
+ _evalOp(op, stack) {
24163
+ if (_PSStackToTree.#binaryOps.has(op)) {
24164
+ if (stack.length < 2) {
24165
+ this._failed = true;
24166
+ return;
24167
+ }
24168
+ const first = stack.pop();
24169
+ const second = stack.pop();
24170
+ stack.push(this._makeBinary(op, first, second));
24171
+ return;
24172
+ }
24173
+ if (_PSStackToTree.#unaryOps.has(op)) {
24174
+ if (stack.length < 1) {
24175
+ this._failed = true;
24176
+ return;
24177
+ }
24178
+ stack.push(this._makeUnary(op, stack.pop()));
24179
+ return;
24180
+ }
24181
+ switch (op) {
24182
+ case TOKEN.true:
24183
+ stack.push(new PsConstNode(true));
24184
+ if (stack.length > MAX_STACK_SIZE) {
24185
+ this._failed = true;
24186
+ }
24187
+ break;
24188
+ case TOKEN.false:
24189
+ stack.push(new PsConstNode(false));
24190
+ if (stack.length > MAX_STACK_SIZE) {
24191
+ this._failed = true;
24192
+ }
24193
+ break;
24194
+ case TOKEN.dup:
24195
+ if (stack.length < 1) {
24196
+ this._failed = true;
24197
+ break;
24198
+ }
24199
+ stack.push(stack.at(-1));
24200
+ if (stack.length > MAX_STACK_SIZE) {
24201
+ this._failed = true;
24202
+ }
24203
+ break;
24204
+ case TOKEN.exch: {
24205
+ if (stack.length < 2) {
24206
+ this._failed = true;
24207
+ break;
24208
+ }
24209
+ const a = stack.pop();
24210
+ const b = stack.pop();
24211
+ stack.push(a, b);
24212
+ break;
24213
+ }
24214
+ case TOKEN.pop:
24215
+ if (stack.length < 1) {
24216
+ this._failed = true;
24217
+ break;
24218
+ }
24219
+ stack.pop();
24220
+ break;
24221
+ case TOKEN.copy: {
24222
+ if (stack.length < 1) {
24223
+ this._failed = true;
24224
+ break;
24225
+ }
24226
+ const nNode = stack.pop();
24227
+ if (nNode.type === PS_NODE.const) {
24228
+ const n = nNode.value | 0;
24229
+ if (n === 0) {
24230
+ } else if (n < 0 || n > stack.length) {
24231
+ this._failed = true;
24232
+ } else {
24233
+ stack.push(...stack.slice(-n));
24234
+ if (stack.length > MAX_STACK_SIZE) {
24235
+ this._failed = true;
24236
+ }
24237
+ }
24238
+ } else {
24239
+ this._failed = true;
24240
+ }
24241
+ break;
24242
+ }
24243
+ case TOKEN.index: {
24244
+ if (stack.length < 1) {
24245
+ this._failed = true;
24246
+ break;
24247
+ }
24248
+ const nNode = stack.pop();
24249
+ if (nNode.type === PS_NODE.const) {
24250
+ const n = nNode.value | 0;
24251
+ if (n < 0 || n >= stack.length) {
24252
+ this._failed = true;
24253
+ } else {
24254
+ stack.push(stack.at(-n - 1));
24255
+ }
24256
+ } else {
24257
+ this._failed = true;
24258
+ }
24259
+ break;
24260
+ }
24261
+ case TOKEN.roll: {
24262
+ if (stack.length < 2) {
24263
+ this._failed = true;
24264
+ break;
24265
+ }
24266
+ const jNode = stack.pop();
24267
+ const nNode = stack.pop();
24268
+ if (nNode.type === PS_NODE.const && jNode.type === PS_NODE.const) {
24269
+ const n = nNode.value | 0;
24270
+ if (n === 0) {
24271
+ } else if (n < 0 || n > stack.length) {
24272
+ this._failed = true;
24273
+ } else {
24274
+ const j = ((jNode.value | 0) % n + n) % n;
24275
+ if (j > 0) {
24276
+ const slice = stack.splice(-n, n);
24277
+ stack.push(...slice.slice(n - j), ...slice.slice(0, n - j));
24278
+ }
24279
+ }
24280
+ } else {
24281
+ this._failed = true;
24282
+ }
24283
+ break;
24284
+ }
24285
+ default:
24286
+ this._failed = true;
24287
+ break;
24288
+ }
24289
+ }
24290
+ /**
24291
+ * Create a binary tree node, applying optimizations eagerly:
24292
+ *
24293
+ * 1. Constant folding — both operands are PsConstNode → fold to PsConstNode.
24294
+ * 2. Reflexive simplifications — x−x→0, x xor x→0, x eq x→true, etc.
24295
+ * 3. Algebraic simplifications with one known operand — identity elements
24296
+ * (x+0→x, x*1→x, …), absorbing elements (x*0→0, x and false→false, …),
24297
+ * and strength reductions (x*-1→neg(x), x^0.5→sqrt(x), x^2→x*x, …).
24298
+ *
24299
+ * Recall: `first` was on top of the stack (right operand for non-commutative
24300
+ * ops), `second` was below (left operand). So `a b sub` → second=a, first=b
24301
+ * → a − b.
24302
+ */
24303
+ _makeBinary(op, first, second) {
24304
+ if (first.type === PS_NODE.const && second.type === PS_NODE.const) {
24305
+ const v = _evalBinaryConst(op, second.value, first.value);
24306
+ if (v !== void 0) {
24307
+ return new PsConstNode(v);
24308
+ }
24309
+ }
24310
+ if (_nodesEqual(first, second)) {
24311
+ switch (op) {
24312
+ case TOKEN.sub:
24313
+ return new PsConstNode(0);
24314
+ // x − x → 0
24315
+ case TOKEN.xor:
24316
+ return new PsConstNode(
24317
+ /* eslint-disable unicorn/prefer-logical-operator-over-ternary */
24318
+ first.valueType === PS_VALUE_TYPE.boolean ? false : 0
24319
+ /* eslint-enable unicorn/prefer-logical-operator-over-ternary */
24320
+ );
24321
+ // TOKEN.mod, TOKEN.div, TOKEN.idiv are NOT simplified here:
24322
+ // x op x is undefined when x = 0, so we cannot fold without knowing
24323
+ // that x is non-zero.
24324
+ case TOKEN.and:
24325
+ case TOKEN.or:
24326
+ return first;
24327
+ // x and x → x; x or x → x
24328
+ case TOKEN.min:
24329
+ case TOKEN.max:
24330
+ return first;
24331
+ // min(x,x) → x; max(x,x) → x
24332
+ case TOKEN.eq:
24333
+ case TOKEN.ge:
24334
+ case TOKEN.le:
24335
+ return new PsConstNode(true);
24336
+ case TOKEN.ne:
24337
+ case TOKEN.gt:
24338
+ case TOKEN.lt:
24339
+ return new PsConstNode(false);
24340
+ }
24341
+ }
24342
+ if (first.type === PS_NODE.const) {
24343
+ const b = first.value;
24344
+ switch (op) {
24345
+ case TOKEN.add:
24346
+ if (b === 0) {
24347
+ return second;
24348
+ }
24349
+ break;
24350
+ case TOKEN.sub:
24351
+ if (b === 0) {
24352
+ return second;
24353
+ }
24354
+ break;
24355
+ case TOKEN.mul:
24356
+ if (b === 1) {
24357
+ return second;
24358
+ }
24359
+ if (b === 0) {
24360
+ return first;
24361
+ }
24362
+ if (b === -1) {
24363
+ return this._makeUnary(TOKEN.neg, second);
24364
+ }
24365
+ break;
24366
+ case TOKEN.div:
24367
+ if (b !== 0) {
24368
+ return this._makeBinary(TOKEN.mul, new PsConstNode(1 / b), second);
24369
+ }
24370
+ break;
24371
+ case TOKEN.idiv:
24372
+ if (b === 1) {
24373
+ return second;
24374
+ }
24375
+ break;
24376
+ case TOKEN.exp:
24377
+ if (b === 1) {
24378
+ return second;
24379
+ }
24380
+ if (b === -1) {
24381
+ return this._makeBinary(TOKEN.div, second, new PsConstNode(1));
24382
+ }
24383
+ if (b === 0.5) {
24384
+ return this._makeUnary(TOKEN.sqrt, second);
24385
+ }
24386
+ if (b === 0.25) {
24387
+ const sqrtOnce = this._makeUnary(TOKEN.sqrt, second);
24388
+ return this._makeUnary(TOKEN.sqrt, sqrtOnce);
24389
+ }
24390
+ if (b === 2) {
24391
+ return this._makeBinary(TOKEN.mul, second, second);
24392
+ }
24393
+ if (b === 3) {
24394
+ return this._makeBinary(
24395
+ TOKEN.mul,
24396
+ this._makeBinary(TOKEN.mul, second, second),
24397
+ second
24398
+ );
24399
+ }
24400
+ if (b === 4) {
24401
+ const square = this._makeBinary(TOKEN.mul, second, second);
24402
+ return this._makeBinary(TOKEN.mul, square, square);
24403
+ }
24404
+ if (b === 0) {
24405
+ return new PsConstNode(1);
24406
+ }
24407
+ break;
24408
+ case TOKEN.and:
24409
+ if (b === true) {
24410
+ return second;
24411
+ }
24412
+ if (b === false) {
24413
+ return first;
24414
+ }
24415
+ break;
24416
+ case TOKEN.or:
24417
+ if (b === false) {
24418
+ return second;
24419
+ }
24420
+ if (b === true) {
24421
+ return first;
24422
+ }
24423
+ break;
24424
+ case TOKEN.min:
24425
+ if (second.type === PS_NODE.binary && second.op === TOKEN.max && second.first.type === PS_NODE.const && second.first.value >= b) {
24426
+ return first;
24427
+ }
24428
+ break;
24429
+ case TOKEN.max:
24430
+ if (second.type === PS_NODE.binary && second.op === TOKEN.min && second.first.type === PS_NODE.const && second.first.value <= b) {
24431
+ return first;
24432
+ }
24433
+ break;
24434
+ }
24435
+ }
24436
+ if (second.type === PS_NODE.const) {
24437
+ const a = second.value;
24438
+ switch (op) {
24439
+ case TOKEN.add:
24440
+ if (a === 0) {
24441
+ return first;
24442
+ }
24443
+ break;
24444
+ case TOKEN.sub:
24445
+ if (a === 0) {
24446
+ return this._makeUnary(TOKEN.neg, first);
24447
+ }
24448
+ break;
24449
+ case TOKEN.mul:
24450
+ if (a === 1) {
24451
+ return first;
24452
+ }
24453
+ if (a === 0) {
24454
+ return second;
24455
+ }
24456
+ if (a === -1) {
24457
+ return this._makeUnary(TOKEN.neg, first);
24458
+ }
24459
+ break;
24460
+ case TOKEN.and:
24461
+ if (a === true) {
24462
+ return first;
24463
+ }
24464
+ if (a === false) {
24465
+ return second;
24466
+ }
24467
+ break;
24468
+ case TOKEN.or:
24469
+ if (a === false) {
24470
+ return first;
24471
+ }
24472
+ if (a === true) {
24473
+ return second;
24474
+ }
24475
+ break;
24476
+ }
24477
+ }
24478
+ return new PsBinaryNode(
24479
+ op,
24480
+ first,
24481
+ second,
24482
+ _binaryValueType(op, first.valueType, second.valueType)
24483
+ );
24484
+ }
24485
+ /**
24486
+ * Create a unary tree node, applying optimizations eagerly:
24487
+ *
24488
+ * 1. Constant folding.
24489
+ * 2. not(comparison) → negated comparison: not(a eq b) → a ne b, etc.
24490
+ * 3. neg(a − b) → b − a.
24491
+ * 4. Double-negation: neg(neg(x)) → x, not(not(x)) → x.
24492
+ * 5. abs(neg(x)) → abs(x).
24493
+ * 6. Idempotent: f(f(x)) → f(x) for abs, ceiling, floor, round, etc.
24494
+ */
24495
+ _makeUnary(op, operand) {
24496
+ if (operand.type === PS_NODE.const) {
24497
+ const v = _evalUnaryConst(op, operand.value);
24498
+ if (v !== void 0) {
24499
+ return new PsConstNode(v);
24500
+ }
24501
+ }
24502
+ if (op === TOKEN.not && operand.type === PS_NODE.binary) {
24503
+ const negated = _PSStackToTree.#negatedComparison.get(operand.op);
24504
+ if (negated !== void 0) {
24505
+ return new PsBinaryNode(
24506
+ negated,
24507
+ operand.first,
24508
+ operand.second,
24509
+ PS_VALUE_TYPE.boolean
24510
+ );
24511
+ }
24512
+ }
24513
+ if (op === TOKEN.neg && operand.type === PS_NODE.binary && operand.op === TOKEN.sub) {
24514
+ return this._makeBinary(TOKEN.sub, operand.second, operand.first);
24515
+ }
24516
+ if (operand.type === PS_NODE.unary) {
24517
+ if (op === TOKEN.neg && operand.op === TOKEN.neg || op === TOKEN.not && operand.op === TOKEN.not) {
24518
+ return operand.operand;
24519
+ }
24520
+ if (op === TOKEN.abs && operand.op === TOKEN.neg) {
24521
+ return this._makeUnary(TOKEN.abs, operand.operand);
24522
+ }
24523
+ if (_PSStackToTree.#idempotentUnary.has(op) && op === operand.op) {
24524
+ return operand;
24525
+ }
24526
+ }
24527
+ return new PsUnaryNode(op, operand, _unaryValueType(op, operand.valueType));
24528
+ }
24529
+ /**
24530
+ * Create a ternary node, applying optimizations eagerly:
24531
+ *
24532
+ * 1. Constant condition — fold to the live branch.
24533
+ * 2. Identical branches — the condition is irrelevant, return either branch.
24534
+ * 3. Boolean branch constants — `cond ? true : false` → cond,
24535
+ * `cond ? false : true` → not(cond).
24536
+ * 4. Ternary → branchless min/max when the condition compares two numeric
24537
+ * expressions that are also the two branches.
24538
+ */
24539
+ _makeTernary(cond, then, otherwise) {
24540
+ if (cond.type === PS_NODE.const) {
24541
+ return cond.value ? then : otherwise;
24542
+ }
24543
+ if (_nodesEqual(then, otherwise)) {
24544
+ return then;
24545
+ }
24546
+ if (then.type === PS_NODE.const && otherwise.type === PS_NODE.const) {
24547
+ if (then.value === true && otherwise.value === false) {
24548
+ return cond;
24549
+ }
24550
+ if (then.value === false && otherwise.value === true) {
24551
+ return this._makeUnary(TOKEN.not, cond);
24552
+ }
24553
+ }
24554
+ if (cond.type === PS_NODE.binary) {
24555
+ const { op: cop, first: cf, second: cs } = cond;
24556
+ if (cop === TOKEN.gt || cop === TOKEN.ge) {
24557
+ if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
24558
+ return this._makeBinary(TOKEN.min, cf, cs);
24559
+ }
24560
+ if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
24561
+ return this._makeBinary(TOKEN.max, cf, cs);
24562
+ }
24563
+ } else if (cop === TOKEN.lt || cop === TOKEN.le) {
24564
+ if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
24565
+ return this._makeBinary(TOKEN.max, cf, cs);
24566
+ }
24567
+ if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
24568
+ return this._makeBinary(TOKEN.min, cf, cs);
24569
+ }
24570
+ }
24571
+ }
24572
+ return new PsTernaryNode(
24573
+ cond,
24574
+ then,
24575
+ otherwise,
24576
+ then.valueType === otherwise.valueType ? then.valueType : PS_VALUE_TYPE.unknown
24577
+ );
24578
+ }
24579
+ };
24580
+ var OP = {
24581
+ ARG: 0,
24582
+ // [ARG, idx]
24583
+ CONST: 1,
24584
+ // [CONST, val]
24585
+ STORE: 2,
24586
+ // [STORE, slot, min, max] clamp(pop()) → mem[slot]
24587
+ IF: 3,
24588
+ // [IF, target] jump when top-of-stack === 0
24589
+ JUMP: 4,
24590
+ // [JUMP, target] unconditional
24591
+ ABS: 5,
24592
+ NEG: 6,
24593
+ CEIL: 7,
24594
+ FLOOR: 8,
24595
+ ROUND: 9,
24596
+ // floor(x + 0.5)
24597
+ TRUNC: 10,
24598
+ NOT_B: 11,
24599
+ // boolean NOT
24600
+ NOT_N: 12,
24601
+ // bitwise NOT
24602
+ SQRT: 13,
24603
+ SIN: 14,
24604
+ // degrees in/out
24605
+ COS: 15,
24606
+ LN: 16,
24607
+ LOG10: 17,
24608
+ CVI: 18,
24609
+ SHIFT: 19,
24610
+ // [SHIFT, amount] +ve = left, −ve = right
24611
+ // Binary ops: second below, first on top; result = second OP first.
24612
+ ADD: 20,
24613
+ SUB: 21,
24614
+ MUL: 22,
24615
+ DIV: 23,
24616
+ // 0 when divisor is 0
24617
+ IDIV: 24,
24618
+ // 0 when divisor is 0
24619
+ MOD: 25,
24620
+ // 0 when divisor is 0
24621
+ POW: 26,
24622
+ EQ: 27,
24623
+ NE: 28,
24624
+ GT: 29,
24625
+ GE: 30,
24626
+ LT: 31,
24627
+ LE: 32,
24628
+ AND: 33,
24629
+ OR: 34,
24630
+ XOR: 35,
24631
+ ATAN: 36,
24632
+ // atan2(second, first) → degrees [0, 360)
24633
+ MIN: 37,
24634
+ MAX: 38,
24635
+ TEE_TMP: 39,
24636
+ // [TEE_TMP, slot] peek top of stack → tmp[slot], leave on stack
24637
+ LOAD_TMP: 40
24638
+ // [LOAD_TMP, slot] push tmp[slot]
24639
+ };
24640
+ var _DEG_TO_RAD = Math.PI / 180;
24641
+ var _RAD_TO_DEG = 180 / Math.PI;
24642
+ var PsJsCompiler = class {
24643
+ // Safe because JS is single-threaded.
24644
+ static #stack = new Float64Array(64);
24645
+ static #tmp = new Float64Array(64);
24646
+ constructor(domain, range) {
24647
+ this.nIn = domain.length >> 1;
24648
+ this.nOut = range.length >> 1;
24649
+ this.range = range;
24650
+ this.ir = [];
24651
+ this._tmpMap = /* @__PURE__ */ new Map();
24652
+ this._nextTmp = 0;
24653
+ }
24654
+ _compileNode(node) {
24655
+ if (node.shared) {
24656
+ const cached = this._tmpMap.get(node);
24657
+ if (cached !== void 0) {
24658
+ this.ir.push(OP.LOAD_TMP, cached);
24659
+ return true;
24660
+ }
24661
+ if (!this._compileNodeImpl(node)) {
24662
+ return false;
24663
+ }
24664
+ const slot = this._nextTmp++;
24665
+ this._tmpMap.set(node, slot);
24666
+ this.ir.push(OP.TEE_TMP, slot);
24667
+ return true;
24668
+ }
24669
+ return this._compileNodeImpl(node);
24670
+ }
24671
+ _compileNodeImpl(node) {
24672
+ switch (node.type) {
24673
+ case PS_NODE.arg:
24674
+ this.ir.push(OP.ARG, node.index);
24675
+ return true;
24676
+ case PS_NODE.const: {
24677
+ const v = node.value;
24678
+ this.ir.push(OP.CONST, typeof v === "boolean" ? Number(v) : v);
24679
+ return true;
24680
+ }
24681
+ case PS_NODE.unary:
24682
+ return this._compileUnary(node);
24683
+ case PS_NODE.binary:
24684
+ return this._compileBinary(node);
24685
+ case PS_NODE.ternary:
24686
+ return this._compileTernary(node);
24687
+ default:
24688
+ return false;
24689
+ }
24690
+ }
24691
+ _compileUnary(node) {
24692
+ const { op, operand, valueType } = node;
24693
+ if (op === TOKEN.cvr) {
24694
+ return this._compileNode(operand);
24695
+ }
24696
+ if (!this._compileNode(operand)) {
24697
+ return false;
24698
+ }
24699
+ switch (op) {
24700
+ case TOKEN.abs:
24701
+ this.ir.push(OP.ABS);
24702
+ break;
24703
+ case TOKEN.neg:
24704
+ this.ir.push(OP.NEG);
24705
+ break;
24706
+ case TOKEN.ceiling:
24707
+ this.ir.push(OP.CEIL);
24708
+ break;
24709
+ case TOKEN.floor:
24710
+ this.ir.push(OP.FLOOR);
24711
+ break;
24712
+ case TOKEN.round:
24713
+ this.ir.push(OP.ROUND);
24714
+ break;
24715
+ case TOKEN.truncate:
24716
+ this.ir.push(OP.TRUNC);
24717
+ break;
24718
+ case TOKEN.sqrt:
24719
+ this.ir.push(OP.SQRT);
24720
+ break;
24721
+ case TOKEN.sin:
24722
+ this.ir.push(OP.SIN);
24723
+ break;
24724
+ case TOKEN.cos:
24725
+ this.ir.push(OP.COS);
24726
+ break;
24727
+ case TOKEN.ln:
24728
+ this.ir.push(OP.LN);
24729
+ break;
24730
+ case TOKEN.log:
24731
+ this.ir.push(OP.LOG10);
24732
+ break;
24733
+ case TOKEN.cvi:
24734
+ this.ir.push(OP.CVI);
24735
+ break;
24736
+ case TOKEN.not:
24737
+ if (valueType === PS_VALUE_TYPE.boolean) {
24738
+ this.ir.push(OP.NOT_B);
24739
+ } else if (valueType === PS_VALUE_TYPE.numeric) {
24740
+ this.ir.push(OP.NOT_N);
24741
+ } else {
24742
+ return false;
24743
+ }
24744
+ break;
24745
+ default:
24746
+ return false;
24747
+ }
24748
+ return true;
24749
+ }
24750
+ _compileBinary(node) {
24751
+ const { op, first, second } = node;
24752
+ if (op === TOKEN.bitshift) {
24753
+ if (first.type !== PS_NODE.const || !Number.isInteger(first.value) || !this._compileNode(second)) {
24754
+ return false;
24755
+ }
24756
+ this.ir.push(OP.SHIFT, first.value);
24757
+ return true;
24758
+ }
24759
+ if (!this._compileNode(second) || !this._compileNode(first)) {
24760
+ return false;
24761
+ }
24762
+ switch (op) {
24763
+ case TOKEN.add:
24764
+ this.ir.push(OP.ADD);
24765
+ break;
24766
+ case TOKEN.sub:
24767
+ this.ir.push(OP.SUB);
24768
+ break;
24769
+ case TOKEN.mul:
24770
+ this.ir.push(OP.MUL);
24771
+ break;
24772
+ case TOKEN.div:
24773
+ this.ir.push(OP.DIV);
24774
+ break;
24775
+ case TOKEN.idiv:
24776
+ this.ir.push(OP.IDIV);
24777
+ break;
24778
+ case TOKEN.mod:
24779
+ this.ir.push(OP.MOD);
24780
+ break;
24781
+ case TOKEN.exp:
24782
+ this.ir.push(OP.POW);
24783
+ break;
24784
+ case TOKEN.eq:
24785
+ this.ir.push(OP.EQ);
24786
+ break;
24787
+ case TOKEN.ne:
24788
+ this.ir.push(OP.NE);
24789
+ break;
24790
+ case TOKEN.gt:
24791
+ this.ir.push(OP.GT);
24792
+ break;
24793
+ case TOKEN.ge:
24794
+ this.ir.push(OP.GE);
24795
+ break;
24796
+ case TOKEN.lt:
24797
+ this.ir.push(OP.LT);
24798
+ break;
24799
+ case TOKEN.le:
24800
+ this.ir.push(OP.LE);
24801
+ break;
24802
+ case TOKEN.and:
24803
+ this.ir.push(OP.AND);
24804
+ break;
24805
+ case TOKEN.or:
24806
+ this.ir.push(OP.OR);
24807
+ break;
24808
+ case TOKEN.xor:
24809
+ this.ir.push(OP.XOR);
24810
+ break;
24811
+ case TOKEN.atan:
24812
+ this.ir.push(OP.ATAN);
24813
+ break;
24814
+ case TOKEN.min:
24815
+ this.ir.push(OP.MIN);
24816
+ break;
24817
+ case TOKEN.max:
24818
+ this.ir.push(OP.MAX);
24819
+ break;
24820
+ default:
24821
+ return false;
24822
+ }
24823
+ return true;
24824
+ }
24825
+ _compileTernary(node) {
24826
+ if (!this._compileNode(node.cond)) {
24827
+ return false;
24828
+ }
24829
+ this.ir.push(OP.IF, 0);
24830
+ const ifPatch = this.ir.length - 1;
24831
+ if (!this._compileNode(node.then)) {
24832
+ return false;
24833
+ }
24834
+ this.ir.push(OP.JUMP, 0);
24835
+ const jumpPatch = this.ir.length - 1;
24836
+ this.ir[ifPatch] = this.ir.length;
24837
+ if (!this._compileNode(node.otherwise)) {
24838
+ return false;
24839
+ }
24840
+ this.ir[jumpPatch] = this.ir.length;
24841
+ return true;
24842
+ }
24843
+ compile(program) {
24844
+ const outputs = new PSStackToTree().evaluate(program, this.nIn);
24845
+ if (!outputs || outputs.length < this.nOut) {
24846
+ return null;
24847
+ }
24848
+ for (let i = 0; i < this.nOut; i++) {
24849
+ if (!this._compileNode(outputs[i])) {
24850
+ return null;
24851
+ }
24852
+ const min = this.range[i * 2];
24853
+ const max = this.range[i * 2 + 1];
24854
+ this.ir.push(OP.STORE, i, min, max);
24855
+ }
24856
+ return new Float64Array(this.ir);
24857
+ }
24858
+ static execute(ir, src, srcOffset, dest, destOffset) {
24859
+ let ip = 0, sp = 0;
24860
+ const n = ir.length;
24861
+ const stack = this.#stack;
24862
+ const tmp = this.#tmp;
24863
+ while (ip < n) {
24864
+ switch (ir[ip++] | 0) {
24865
+ case OP.ARG:
24866
+ stack[sp++] = src[srcOffset + (ir[ip++] | 0)];
24867
+ break;
24868
+ case OP.CONST:
24869
+ stack[sp++] = ir[ip++];
24870
+ break;
24871
+ case OP.STORE: {
24872
+ const slot = ir[ip++] | 0;
24873
+ const min = ir[ip++];
24874
+ const max = ir[ip++];
24875
+ dest[destOffset + slot] = MathClamp(stack[--sp], min, max);
24876
+ break;
24877
+ }
24878
+ case OP.IF: {
24879
+ const tgt = ir[ip++];
24880
+ if (stack[--sp] === 0) {
24881
+ ip = tgt;
24882
+ }
24883
+ break;
24884
+ }
24885
+ case OP.JUMP:
24886
+ ip = ir[ip];
24887
+ break;
24888
+ case OP.ABS:
24889
+ stack[sp - 1] = Math.abs(stack[sp - 1]);
24890
+ break;
24891
+ case OP.NEG:
24892
+ stack[sp - 1] = -stack[sp - 1];
24893
+ break;
24894
+ case OP.CEIL:
24895
+ stack[sp - 1] = Math.ceil(stack[sp - 1]);
24896
+ break;
24897
+ case OP.FLOOR:
24898
+ stack[sp - 1] = Math.floor(stack[sp - 1]);
24899
+ break;
24900
+ case OP.ROUND:
24901
+ stack[sp - 1] = Math.floor(stack[sp - 1] + 0.5);
24902
+ break;
24903
+ case OP.TRUNC:
24904
+ stack[sp - 1] = Math.trunc(stack[sp - 1]);
24905
+ break;
24906
+ case OP.NOT_B:
24907
+ stack[sp - 1] = stack[sp - 1] !== 0 ? 0 : 1;
24908
+ break;
24909
+ case OP.NOT_N:
24910
+ stack[sp - 1] = ~(stack[sp - 1] | 0);
24911
+ break;
24912
+ case OP.SQRT:
24913
+ stack[sp - 1] = Math.sqrt(stack[sp - 1]);
24914
+ break;
24915
+ case OP.SIN:
24916
+ stack[sp - 1] = Math.sin(stack[sp - 1] % 360 * _DEG_TO_RAD);
24917
+ break;
24918
+ case OP.COS:
24919
+ stack[sp - 1] = Math.cos(stack[sp - 1] % 360 * _DEG_TO_RAD);
24920
+ break;
24921
+ case OP.LN:
24922
+ stack[sp - 1] = Math.log(stack[sp - 1]);
24923
+ break;
24924
+ case OP.LOG10:
24925
+ stack[sp - 1] = Math.log10(stack[sp - 1]);
24926
+ break;
24927
+ case OP.CVI:
24928
+ stack[sp - 1] = Math.trunc(stack[sp - 1]) | 0;
24929
+ break;
24930
+ case OP.SHIFT: {
24931
+ const amt = ir[ip++];
24932
+ const v = stack[sp - 1] | 0;
24933
+ if (amt > 0) {
24934
+ stack[sp - 1] = v << amt;
24935
+ } else if (amt < 0) {
24936
+ stack[sp - 1] = v >> -amt;
24937
+ } else {
24938
+ stack[sp - 1] = v;
24939
+ }
24940
+ break;
24941
+ }
24942
+ case OP.ADD: {
24943
+ const b = stack[--sp];
24944
+ stack[sp - 1] += b;
24945
+ break;
24946
+ }
24947
+ case OP.SUB: {
24948
+ const b = stack[--sp];
24949
+ stack[sp - 1] -= b;
24950
+ break;
24951
+ }
24952
+ case OP.MUL: {
24953
+ const b = stack[--sp];
24954
+ stack[sp - 1] *= b;
24955
+ break;
24956
+ }
24957
+ case OP.DIV: {
24958
+ const b = stack[--sp];
24959
+ stack[sp - 1] = b !== 0 ? stack[sp - 1] / b : 0;
24960
+ break;
24961
+ }
24962
+ case OP.IDIV: {
24963
+ const b = stack[--sp];
24964
+ stack[sp - 1] = b !== 0 ? Math.trunc(stack[sp - 1] / b) : 0;
24965
+ break;
24966
+ }
24967
+ case OP.MOD: {
24968
+ const b = stack[--sp];
24969
+ stack[sp - 1] = b !== 0 ? stack[sp - 1] % b : 0;
24970
+ break;
24971
+ }
24972
+ case OP.POW: {
24973
+ const b = stack[--sp];
24974
+ stack[sp - 1] **= b;
24975
+ break;
24976
+ }
24977
+ case OP.EQ: {
24978
+ const b = stack[--sp];
24979
+ stack[sp - 1] = stack[sp - 1] === b ? 1 : 0;
24980
+ break;
24981
+ }
24982
+ case OP.NE: {
24983
+ const b = stack[--sp];
24984
+ stack[sp - 1] = stack[sp - 1] !== b ? 1 : 0;
24985
+ break;
24986
+ }
24987
+ case OP.GT: {
24988
+ const b = stack[--sp];
24989
+ stack[sp - 1] = stack[sp - 1] > b ? 1 : 0;
24990
+ break;
24991
+ }
24992
+ case OP.GE: {
24993
+ const b = stack[--sp];
24994
+ stack[sp - 1] = stack[sp - 1] >= b ? 1 : 0;
24995
+ break;
24996
+ }
24997
+ case OP.LT: {
24998
+ const b = stack[--sp];
24999
+ stack[sp - 1] = stack[sp - 1] < b ? 1 : 0;
25000
+ break;
25001
+ }
25002
+ case OP.LE: {
25003
+ const b = stack[--sp];
25004
+ stack[sp - 1] = stack[sp - 1] <= b ? 1 : 0;
25005
+ break;
25006
+ }
25007
+ case OP.AND: {
25008
+ const b = stack[--sp] | 0;
25009
+ stack[sp - 1] = (stack[sp - 1] | 0) & b;
25010
+ break;
25011
+ }
25012
+ case OP.OR: {
25013
+ const b = stack[--sp] | 0;
25014
+ stack[sp - 1] = stack[sp - 1] | 0 | b;
25015
+ break;
25016
+ }
25017
+ case OP.XOR: {
25018
+ const b = stack[--sp] | 0;
25019
+ stack[sp - 1] = (stack[sp - 1] | 0) ^ b;
25020
+ break;
25021
+ }
25022
+ case OP.ATAN: {
25023
+ const b = stack[--sp];
25024
+ const deg = Math.atan2(stack[sp - 1], b) * _RAD_TO_DEG;
25025
+ stack[sp - 1] = deg < 0 ? deg + 360 : deg;
25026
+ break;
25027
+ }
25028
+ case OP.MIN: {
25029
+ const b = stack[--sp];
25030
+ stack[sp - 1] = Math.min(stack[sp - 1], b);
25031
+ break;
25032
+ }
25033
+ case OP.MAX: {
25034
+ const b = stack[--sp];
25035
+ stack[sp - 1] = Math.max(stack[sp - 1], b);
25036
+ break;
25037
+ }
25038
+ case OP.TEE_TMP:
25039
+ tmp[ir[ip++] | 0] = stack[sp - 1];
25040
+ break;
25041
+ case OP.LOAD_TMP:
25042
+ stack[sp++] = tmp[ir[ip++] | 0];
25043
+ break;
25044
+ }
25045
+ }
25046
+ }
25047
+ };
25048
+ var PSStackBasedInterpreter = class {
25049
+ // Safe: JS is single-threaded.
25050
+ static #stack = new Float64Array(100);
25051
+ static #sp = 0;
25052
+ static #push(v) {
25053
+ if (this.#sp < this.#stack.length) {
25054
+ this.#stack[this.#sp++] = v;
25055
+ }
25056
+ }
25057
+ static #execOp(op) {
25058
+ const stack = this.#stack;
25059
+ switch (op) {
25060
+ case TOKEN.true:
25061
+ this.#push(1);
25062
+ break;
25063
+ case TOKEN.false:
25064
+ this.#push(0);
25065
+ break;
25066
+ case TOKEN.abs:
25067
+ stack[this.#sp - 1] = Math.abs(stack[this.#sp - 1]);
25068
+ break;
25069
+ case TOKEN.neg:
25070
+ stack[this.#sp - 1] = -stack[this.#sp - 1];
25071
+ break;
25072
+ case TOKEN.ceiling:
25073
+ stack[this.#sp - 1] = Math.ceil(stack[this.#sp - 1]);
25074
+ break;
25075
+ case TOKEN.floor:
25076
+ stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1]);
25077
+ break;
25078
+ case TOKEN.round:
25079
+ stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1] + 0.5);
25080
+ break;
25081
+ case TOKEN.truncate:
25082
+ stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]);
25083
+ break;
25084
+ case TOKEN.sqrt:
25085
+ stack[this.#sp - 1] = Math.sqrt(stack[this.#sp - 1]);
25086
+ break;
25087
+ case TOKEN.sin:
25088
+ stack[this.#sp - 1] = Math.sin(
25089
+ stack[this.#sp - 1] % 360 * _DEG_TO_RAD
25090
+ );
25091
+ break;
25092
+ case TOKEN.cos:
25093
+ stack[this.#sp - 1] = Math.cos(
25094
+ stack[this.#sp - 1] % 360 * _DEG_TO_RAD
25095
+ );
25096
+ break;
25097
+ case TOKEN.ln:
25098
+ stack[this.#sp - 1] = Math.log(stack[this.#sp - 1]);
25099
+ break;
25100
+ case TOKEN.log:
25101
+ stack[this.#sp - 1] = Math.log10(stack[this.#sp - 1]);
25102
+ break;
25103
+ case TOKEN.cvi:
25104
+ stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]) | 0;
25105
+ break;
25106
+ case TOKEN.cvr:
25107
+ break;
25108
+ // values are already f64
25109
+ case TOKEN.not: {
25110
+ const v = stack[this.#sp - 1];
25111
+ stack[this.#sp - 1] = v === 0 || v === 1 ? 1 - v : ~(v | 0);
25112
+ break;
25113
+ }
25114
+ case TOKEN.add: {
25115
+ const b = stack[--this.#sp];
25116
+ stack[this.#sp - 1] += b;
25117
+ break;
25118
+ }
25119
+ case TOKEN.sub: {
25120
+ const b = stack[--this.#sp];
25121
+ stack[this.#sp - 1] -= b;
25122
+ break;
25123
+ }
25124
+ case TOKEN.mul: {
25125
+ const b = stack[--this.#sp];
25126
+ stack[this.#sp - 1] *= b;
25127
+ break;
25128
+ }
25129
+ case TOKEN.div: {
25130
+ const b = stack[--this.#sp];
25131
+ stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] / b : 0;
25132
+ break;
25133
+ }
25134
+ case TOKEN.idiv: {
25135
+ const b = stack[--this.#sp];
25136
+ stack[this.#sp - 1] = b !== 0 ? Math.trunc(stack[this.#sp - 1] / b) : 0;
25137
+ break;
25138
+ }
25139
+ case TOKEN.mod: {
25140
+ const b = stack[--this.#sp];
25141
+ stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] % b : 0;
25142
+ break;
25143
+ }
25144
+ case TOKEN.exp: {
25145
+ const b = stack[--this.#sp];
25146
+ stack[this.#sp - 1] **= b;
25147
+ break;
25148
+ }
25149
+ case TOKEN.atan: {
25150
+ const dx = stack[--this.#sp];
25151
+ const deg = Math.atan2(stack[this.#sp - 1], dx) * _RAD_TO_DEG;
25152
+ stack[this.#sp - 1] = deg < 0 ? deg + 360 : deg;
25153
+ break;
25154
+ }
25155
+ case TOKEN.eq: {
25156
+ const b = stack[--this.#sp];
25157
+ stack[this.#sp - 1] = stack[this.#sp - 1] === b ? 1 : 0;
25158
+ break;
25159
+ }
25160
+ case TOKEN.ne: {
25161
+ const b = stack[--this.#sp];
25162
+ stack[this.#sp - 1] = stack[this.#sp - 1] !== b ? 1 : 0;
25163
+ break;
25164
+ }
25165
+ case TOKEN.gt: {
25166
+ const b = stack[--this.#sp];
25167
+ stack[this.#sp - 1] = stack[this.#sp - 1] > b ? 1 : 0;
25168
+ break;
25169
+ }
25170
+ case TOKEN.ge: {
25171
+ const b = stack[--this.#sp];
25172
+ stack[this.#sp - 1] = stack[this.#sp - 1] >= b ? 1 : 0;
25173
+ break;
25174
+ }
25175
+ case TOKEN.lt: {
25176
+ const b = stack[--this.#sp];
25177
+ stack[this.#sp - 1] = stack[this.#sp - 1] < b ? 1 : 0;
25178
+ break;
25179
+ }
25180
+ case TOKEN.le: {
25181
+ const b = stack[--this.#sp];
25182
+ stack[this.#sp - 1] = stack[this.#sp - 1] <= b ? 1 : 0;
25183
+ break;
25184
+ }
25185
+ case TOKEN.and: {
25186
+ const b = stack[--this.#sp] | 0;
25187
+ stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) & b;
25188
+ break;
25189
+ }
25190
+ case TOKEN.or: {
25191
+ const b = stack[--this.#sp] | 0;
25192
+ stack[this.#sp - 1] = stack[this.#sp - 1] | 0 | b;
25193
+ break;
25194
+ }
25195
+ case TOKEN.xor: {
25196
+ const b = stack[--this.#sp] | 0;
25197
+ stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) ^ b;
25198
+ break;
25199
+ }
25200
+ case TOKEN.bitshift: {
25201
+ const amt = stack[--this.#sp] | 0;
25202
+ const v = stack[this.#sp - 1] | 0;
25203
+ stack[this.#sp - 1] = amt > 0 ? v << amt : v >> -amt;
25204
+ break;
25205
+ }
25206
+ case TOKEN.min: {
25207
+ const b = stack[--this.#sp];
25208
+ stack[this.#sp - 1] = Math.min(stack[this.#sp - 1], b);
25209
+ break;
25210
+ }
25211
+ case TOKEN.max: {
25212
+ const b = stack[--this.#sp];
25213
+ stack[this.#sp - 1] = Math.max(stack[this.#sp - 1], b);
25214
+ break;
25215
+ }
25216
+ case TOKEN.dup:
25217
+ this.#push(stack[this.#sp - 1]);
25218
+ break;
25219
+ case TOKEN.exch: {
25220
+ const a = stack[--this.#sp];
25221
+ const b = stack[--this.#sp];
25222
+ this.#push(a);
25223
+ this.#push(b);
25224
+ break;
25225
+ }
25226
+ case TOKEN.pop:
25227
+ this.#sp--;
25228
+ break;
25229
+ case TOKEN.copy: {
25230
+ const n = Math.trunc(stack[--this.#sp]);
25231
+ const base = this.#sp - n;
25232
+ for (let k = 0; k < n; k++) {
25233
+ this.#push(stack[base + k]);
25234
+ }
25235
+ break;
25236
+ }
25237
+ case TOKEN.index: {
25238
+ const i = Math.trunc(stack[--this.#sp]);
25239
+ this.#push(stack[this.#sp - 1 - i]);
25240
+ break;
25241
+ }
25242
+ case TOKEN.roll: {
25243
+ const j = Math.trunc(stack[--this.#sp]);
25244
+ const n = Math.trunc(stack[--this.#sp]);
25245
+ if (n > 1 && j !== 0) {
25246
+ const mod = (j % n + n) % n;
25247
+ if (mod !== 0) {
25248
+ const base = this.#sp - n;
25249
+ const sub = stack.slice(base, this.#sp);
25250
+ for (let k = 0; k < n; k++) {
25251
+ stack[base + k] = sub[(k - mod + n) % n];
25252
+ }
25253
+ }
25254
+ }
25255
+ break;
25256
+ }
25257
+ }
25258
+ }
25259
+ static #execBlock(instructions) {
25260
+ for (const instr of instructions) {
25261
+ switch (instr.type) {
25262
+ case PS_NODE.number:
25263
+ this.#push(instr.value);
25264
+ break;
25265
+ case PS_NODE.operator:
25266
+ this.#execOp(instr.op);
25267
+ break;
25268
+ case PS_NODE.if:
25269
+ if (this.#stack[--this.#sp] !== 0) {
25270
+ this.#execBlock(instr.then.instructions);
25271
+ }
25272
+ break;
25273
+ case PS_NODE.ifelse:
25274
+ if (this.#stack[--this.#sp] !== 0) {
25275
+ this.#execBlock(instr.then.instructions);
25276
+ } else {
25277
+ this.#execBlock(instr.otherwise.instructions);
25278
+ }
25279
+ break;
25280
+ }
25281
+ }
25282
+ }
25283
+ /**
25284
+ * @param {import("./ast.js").PsProgram} program
25285
+ * @param {number[]} domain – flat [min0,max0, …]
25286
+ * @param {number[]} range – flat [min0,max0, …]
25287
+ * @returns {Function} – `(src, srcOffset, dest, destOffset) => void`
25288
+ */
25289
+ static build(program, domain, range) {
25290
+ const nIn = domain.length >> 1;
25291
+ const nOut = range.length >> 1;
25292
+ const { instructions } = program.body;
25293
+ return (src, srcOffset, dest, destOffset) => {
25294
+ this.#sp = 0;
25295
+ for (let i = 0; i < nIn; i++) {
25296
+ this.#push(src[srcOffset + i]);
25297
+ }
25298
+ this.#execBlock(instructions);
25299
+ const base = this.#sp - nOut;
25300
+ for (let i = 0; i < nOut; i++) {
25301
+ const v = base + i >= 0 ? this.#stack[base + i] : 0;
25302
+ dest[destOffset + i] = MathClamp(v, range[i * 2], range[i * 2 + 1]);
25303
+ }
25304
+ };
25305
+ }
25306
+ };
25307
+ function buildPostScriptJsFunction(source, domain, range, forceInterpreter = false) {
25308
+ const program = parsePostScriptFunction(source);
25309
+ const ir = !forceInterpreter && new PsJsCompiler(domain, range).compile(program);
25310
+ if (ir) {
25311
+ return (src, srcOffset, dest, destOffset) => {
25312
+ PsJsCompiler.execute(ir, src, srcOffset, dest, destOffset);
25313
+ };
25314
+ }
25315
+ return PSStackBasedInterpreter.build(program, domain, range);
25316
+ }
22709
25317
  var PdfError = class extends Error {
22710
25318
  constructor(code, message) {
22711
25319
  super(message);
@@ -33785,6 +36393,25 @@ var __webpack_exports__JpxImage = __webpack_exports__.JpxImage;
33785
36393
  var __webpack_exports__VerbosityLevel = __webpack_exports__.VerbosityLevel;
33786
36394
  var __webpack_exports__getVerbosityLevel = __webpack_exports__.getVerbosityLevel;
33787
36395
  var __webpack_exports__setVerbosityLevel = __webpack_exports__.setVerbosityLevel;
36396
+ function createCalibratedColorSpace(doc, family, parameters) {
36397
+ const dict = doc.resolveDict(parameters);
36398
+ const array = (key) => {
36399
+ const value = dict ? doc.resolveArray(dictGet(dict, key)) : void 0;
36400
+ return value?.items.map((item) => {
36401
+ const number = doc.resolve(item);
36402
+ return number?.kind === "number" ? number.value : 0;
36403
+ });
36404
+ };
36405
+ const whitePoint = array("WhitePoint") ?? [0.95047, 1, 1.08883];
36406
+ const blackPoint = array("BlackPoint");
36407
+ if (family === "CalGray") {
36408
+ const gamma = dict ? doc.resolve(dictGet(dict, "Gamma")) : void 0;
36409
+ return new CalGrayCS(whitePoint, blackPoint, gamma?.kind === "number" ? gamma.value : void 0);
36410
+ }
36411
+ if (family === "CalRGB") return new CalRGBCS(whitePoint, blackPoint, array("Gamma"), array("Matrix"));
36412
+ return new LabCS(whitePoint, blackPoint, array("Range"));
36413
+ }
36414
+ var cmykColorSpace = new DeviceCmykCS();
33788
36415
  function collectPageLeaves(doc, node, inheritedResources, out = [], visited = /* @__PURE__ */ new Set()) {
33789
36416
  if (!node) return out;
33790
36417
  if (node.kind === "ref") {
@@ -33873,7 +36500,7 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
33873
36500
  palette = lookupNode.bytes;
33874
36501
  }
33875
36502
  let resolvedBaseComp = baseInfo.components;
33876
- if (palette && (baseInfo.isLab || baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calRgbGamma !== void 0 || baseInfo.calGrayGamma !== void 0)) {
36503
+ if (palette && (baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calibrated !== void 0)) {
33877
36504
  const numEntries = Math.max(1, Math.min(hival + 1, Math.floor(palette.length / Math.max(1, baseInfo.components))));
33878
36505
  const rgbaPal = decodeSamplesToRgba(palette, numEntries, 1, 8, baseInfo);
33879
36506
  const rgbPal = new Uint8Array(numEntries * 3);
@@ -33903,74 +36530,21 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
33903
36530
  }
33904
36531
  return { colorSpace: "rgb", colorSpaceLabel: "icc", components: 3 };
33905
36532
  }
33906
- if (kindName === "CalGray") {
33907
- const calDict = doc.resolveDict(resolved.items[1]);
33908
- const gammaNode = calDict ? doc.resolve(dictGet(calDict, "Gamma")) : void 0;
33909
- const gamma = gammaNode?.kind === "number" && gammaNode.value > 0 ? gammaNode.value : 1;
33910
- return { colorSpace: "gray", colorSpaceLabel: "cal-gray", components: 1, calGrayGamma: gamma };
33911
- }
33912
- if (kindName === "CalRGB") {
33913
- const calDict = doc.resolveDict(resolved.items[1]);
33914
- const gammaArr = calDict ? doc.resolveArray(dictGet(calDict, "Gamma")) : void 0;
33915
- let calRgbGamma = [1, 1, 1];
33916
- if (gammaArr && gammaArr.items.length >= 3) {
33917
- const gNums = gammaArr.items.slice(0, 3).map((it) => {
33918
- const r = doc.resolve(it);
33919
- return r?.kind === "number" && r.value > 0 ? r.value : 1;
33920
- });
33921
- calRgbGamma = [gNums[0], gNums[1], gNums[2]];
33922
- }
33923
- const matArr = calDict ? doc.resolveArray(dictGet(calDict, "Matrix")) : void 0;
33924
- let calRgbMatrix;
33925
- if (matArr && matArr.items.length >= 9) {
33926
- calRgbMatrix = matArr.items.slice(0, 9).map((it) => {
33927
- const r = doc.resolve(it);
33928
- return r?.kind === "number" ? r.value : 0;
33929
- });
33930
- }
36533
+ if (kindName === "CalGray" || kindName === "CalRGB" || kindName === "Lab") {
36534
+ const calibrated = createCalibratedColorSpace(doc, kindName, resolved.items[1]);
33931
36535
  return {
33932
- colorSpace: "rgb",
33933
- colorSpaceLabel: "cal-rgb",
33934
- components: 3,
33935
- calRgbGamma,
33936
- calRgbMatrix
36536
+ colorSpace: kindName === "CalGray" ? "gray" : "rgb",
36537
+ colorSpaceLabel: kindName === "CalGray" ? "cal-gray" : kindName === "CalRGB" ? "cal-rgb" : "lab",
36538
+ components: kindName === "CalGray" ? 1 : 3,
36539
+ calibrated
33937
36540
  };
33938
36541
  }
33939
- if (kindName === "Lab") {
33940
- const labDict = doc.resolveDict(resolved.items[1]);
33941
- const rangeArr = labDict ? doc.resolveArray(dictGet(labDict, "Range")) : void 0;
33942
- let labRange = [-100, 100, -100, 100];
33943
- if (rangeArr && rangeArr.items.length >= 4) {
33944
- const nums = rangeArr.items.slice(0, 4).map((it) => {
33945
- const r = doc.resolve(it);
33946
- return r?.kind === "number" ? r.value : 0;
33947
- });
33948
- labRange = [nums[0], nums[1], nums[2], nums[3]];
33949
- }
33950
- return { colorSpace: "rgb", colorSpaceLabel: "lab", components: 3, isLab: true, labRange };
33951
- }
33952
36542
  if (kindName === "Separation" || kindName === "DeviceN") {
33953
36543
  const isDevN = kindName === "DeviceN";
33954
36544
  const namesArr = isDevN ? doc.resolveArray(resolved.items[1]) : void 0;
33955
36545
  const devNComponents = isDevN && namesArr ? Math.max(1, namesArr.items.length) : 1;
33956
36546
  const altInfo = resolveColorSpaceInfo(doc, resolved.items[2], resourcesDict);
33957
36547
  const altSpace = altInfo.colorSpace === "cmyk" ? "cmyk" : altInfo.colorSpace === "gray" ? "gray" : "rgb";
33958
- const fnResolved = doc.resolve(resolved.items[3]);
33959
- const fnDict = fnResolved?.kind === "stream" ? fnResolved.dict : fnResolved?.kind === "dict" ? fnResolved : void 0;
33960
- const ftNode = fnDict ? doc.resolve(dictGet(fnDict, "FunctionType")) : void 0;
33961
- const tintFunctionType = ftNode?.kind === "number" ? ftNode.value : 2;
33962
- const c0Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C0")) : void 0;
33963
- const c1Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C1")) : void 0;
33964
- const nNode = fnDict ? doc.resolve(dictGet(fnDict, "N")) : void 0;
33965
- const c0 = c0Arr ? c0Arr.items.map((it) => {
33966
- const r = doc.resolve(it);
33967
- return r?.kind === "number" ? r.value : 0;
33968
- }) : altSpace === "cmyk" ? [0, 0, 0, 0] : altSpace === "gray" ? [1] : [1, 1, 1];
33969
- const c1 = c1Arr ? c1Arr.items.map((it) => {
33970
- const r = doc.resolve(it);
33971
- return r?.kind === "number" ? r.value : 0;
33972
- }) : altSpace === "cmyk" ? [0, 0, 0, 1] : altSpace === "gray" ? [0] : [0, 0, 0];
33973
- const sepN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
33974
36548
  return {
33975
36549
  colorSpace: altSpace,
33976
36550
  colorSpaceLabel: isDevN ? "devn" : "sep",
@@ -33978,12 +36552,9 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
33978
36552
  isSeparation: !isDevN,
33979
36553
  isDeviceN: isDevN,
33980
36554
  separationAltSpace: altSpace,
33981
- separationC0: c0,
33982
- separationC1: c1,
33983
- separationN: sepN,
36555
+ alternateCalibrated: altInfo.calibrated,
33984
36556
  tintFunctionDoc: doc,
33985
- tintFunctionNode: resolved.items[3],
33986
- tintFunctionType
36557
+ tintFunctionNode: resolved.items[3]
33987
36558
  };
33988
36559
  }
33989
36560
  }
@@ -34133,141 +36704,55 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
34133
36704
  const rgba = new Uint8Array(width * height * 4);
34134
36705
  const pixelCount = width * height;
34135
36706
  if (csInfo.isSeparation || csInfo.isDeviceN) {
34136
- const c0 = csInfo.separationC0 ?? [1, 1, 1];
34137
- const c1 = csInfo.separationC1 ?? [0, 0, 0];
34138
- const expN = csInfo.separationN ?? 1;
34139
36707
  const alt = csInfo.separationAltSpace ?? "rgb";
34140
36708
  const numCh = Math.max(1, csInfo.components);
34141
36709
  const step = bpc === 16 ? 2 : 1;
34142
- const useGenericTintFn = csInfo.tintFunctionDoc !== void 0 && csInfo.tintFunctionNode !== void 0 && (csInfo.tintFunctionType === 0 || csInfo.tintFunctionType === 3 || csInfo.tintFunctionType === 4);
34143
36710
  for (let p = 0; p < pixelCount; p++) {
34144
36711
  const chVals = [];
34145
- let wSum = 0;
34146
36712
  for (let ch3 = 0; ch3 < numCh; ch3++) {
34147
36713
  const sRaw = (rawSamples[(p * numCh + ch3) * step] ?? 0) / 255;
34148
- const tRemapped = remapUnitSampleWithDecode(sRaw, ch3, decodePairs);
34149
- chVals.push(tRemapped);
34150
- wSum += Math.pow(Math.max(0, Math.min(1, tRemapped)), expN);
34151
- }
34152
- if (useGenericTintFn) {
34153
- const outComps = evalShadingFunctionToComponents(
34154
- csInfo.tintFunctionDoc,
34155
- csInfo.tintFunctionNode,
34156
- chVals
34157
- );
34158
- if (alt === "cmyk") {
34159
- const c = outComps[0] ?? 0;
34160
- const m = outComps[1] ?? 0;
34161
- const y = outComps[2] ?? 0;
34162
- const k = outComps[3] ?? 0;
34163
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, (1 - c) * (1 - k))) * 255);
34164
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, (1 - m) * (1 - k))) * 255);
34165
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, (1 - y) * (1 - k))) * 255);
34166
- } else if (alt === "gray") {
34167
- const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
34168
- rgba[p * 4] = gByte;
34169
- rgba[p * 4 + 1] = gByte;
34170
- rgba[p * 4 + 2] = gByte;
34171
- } else {
34172
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
34173
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
34174
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
34175
- }
34176
- rgba[p * 4 + 3] = 255;
34177
- continue;
36714
+ chVals.push(remapUnitSampleWithDecode(sRaw, ch3, decodePairs));
34178
36715
  }
34179
- const w = Math.max(0, Math.min(1, wSum));
34180
- if (alt === "cmyk") {
34181
- const c = (c0[0] ?? 0) + w * ((c1[0] ?? 0) - (c0[0] ?? 0));
34182
- const m = (c0[1] ?? 0) + w * ((c1[1] ?? 0) - (c0[1] ?? 0));
34183
- const y = (c0[2] ?? 0) + w * ((c1[2] ?? 0) - (c0[2] ?? 0));
34184
- const k = (c0[3] ?? 0) + w * ((c1[3] ?? 1) - (c0[3] ?? 0));
34185
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, (1 - c) * (1 - k))) * 255);
34186
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, (1 - m) * (1 - k))) * 255);
34187
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, (1 - y) * (1 - k))) * 255);
36716
+ const outComps = evalShadingFunctionToComponents(
36717
+ csInfo.tintFunctionDoc,
36718
+ csInfo.tintFunctionNode,
36719
+ chVals
36720
+ );
36721
+ if (csInfo.alternateCalibrated) {
36722
+ rgba.set(csInfo.alternateCalibrated.getRgb(outComps, 0), p * 4);
36723
+ } else if (alt === "cmyk") {
36724
+ rgba.set(cmykColorSpace.getRgb([outComps[0] ?? 0, outComps[1] ?? 0, outComps[2] ?? 0, outComps[3] ?? 0], 0), p * 4);
34188
36725
  } else if (alt === "gray") {
34189
- const gVal = (c0[0] ?? 1) + w * ((c1[0] ?? 0) - (c0[0] ?? 1));
34190
- const gByte = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
36726
+ const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
34191
36727
  rgba[p * 4] = gByte;
34192
36728
  rgba[p * 4 + 1] = gByte;
34193
36729
  rgba[p * 4 + 2] = gByte;
34194
36730
  } else {
34195
- const rVal = (c0[0] ?? 1) + w * ((c1[0] ?? 0) - (c0[0] ?? 1));
34196
- const gVal = (c0[1] ?? 1) + w * ((c1[1] ?? 0) - (c0[1] ?? 1));
34197
- const bVal = (c0[2] ?? 1) + w * ((c1[2] ?? 0) - (c0[2] ?? 1));
34198
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, rVal)) * 255);
34199
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
34200
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, bVal)) * 255);
36731
+ rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
36732
+ rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
36733
+ rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
34201
36734
  }
34202
36735
  rgba[p * 4 + 3] = 255;
34203
36736
  }
34204
- } else if (csInfo.isLab) {
34205
- const [amin, amax, bmin, bmax] = csInfo.labRange ?? [-100, 100, -100, 100];
34206
- const invF = (t) => t > 6 / 29 ? t * t * t : 3 * (6 / 29) * (6 / 29) * (t - 4 / 29);
34207
- const toSrgb = (u) => {
34208
- const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
34209
- return Math.round(Math.max(0, Math.min(1, c)) * 255);
34210
- };
36737
+ } else if (csInfo.calibrated?.name === "Lab") {
36738
+ const { amin, amax, bmin, bmax } = csInfo.calibrated;
36739
+ const step = bpc === 16 ? 2 : 1;
34211
36740
  for (let p = 0; p < pixelCount; p++) {
34212
- const s0 = (rawSamples[p * 3] ?? 0) / 255;
34213
- const s1 = (rawSamples[p * 3 + 1] ?? 128) / 255;
34214
- const s2 = (rawSamples[p * 3 + 2] ?? 128) / 255;
34215
- const L = s0 * 100;
34216
- if (L <= 0.01) {
34217
- rgba[p * 4] = 0;
34218
- rgba[p * 4 + 1] = 0;
34219
- rgba[p * 4 + 2] = 0;
34220
- rgba[p * 4 + 3] = 255;
34221
- continue;
34222
- }
34223
- const a = amin + s1 * (amax - amin);
34224
- const b = bmin + s2 * (bmax - bmin);
34225
- const fy = (L + 16) / 116;
34226
- const fx = fy + a / 500;
34227
- const fz = fy - b / 200;
34228
- const X = 0.95047 * invF(fx);
34229
- const Y = 1 * invF(fy);
34230
- const Z = 1.08883 * invF(fz);
34231
- const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
34232
- const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
34233
- const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
34234
- rgba[p * 4] = toSrgb(linR);
34235
- rgba[p * 4 + 1] = toSrgb(linG);
34236
- rgba[p * 4 + 2] = toSrgb(linB);
36741
+ const L = (rawSamples[p * 3 * step] ?? 0) / 255 * 100;
36742
+ const a = amin + (rawSamples[(p * 3 + 1) * step] ?? 128) / 255 * (amax - amin);
36743
+ const b = bmin + (rawSamples[(p * 3 + 2) * step] ?? 128) / 255 * (bmax - bmin);
36744
+ rgba.set(csInfo.calibrated.getRgb([L, a, b], 0), p * 4);
34237
36745
  rgba[p * 4 + 3] = 255;
34238
36746
  }
34239
36747
  } else if (csInfo.colorSpace === "rgb") {
34240
- const hasCalRgb = Boolean(csInfo.calRgbGamma || csInfo.calRgbMatrix);
34241
- const toSrgbByte = (u) => {
34242
- const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
34243
- return Math.round(Math.max(0, Math.min(1, c)) * 255);
34244
- };
34245
36748
  const writeRgbPixel = (p, rByte, gByte, bByte) => {
34246
- let rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
34247
- let gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
34248
- let bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
34249
- if (hasCalRgb) {
34250
- const [gr, gg, gb] = csInfo.calRgbGamma ?? [1, 1, 1];
34251
- const ag = Math.pow(rU, gr);
34252
- const bg = Math.pow(gU, gg);
34253
- const cg = Math.pow(bU, gb);
34254
- if (csInfo.calRgbMatrix && csInfo.calRgbMatrix.length >= 9) {
34255
- const m = csInfo.calRgbMatrix;
34256
- const X = m[0] * ag + m[3] * bg + m[6] * cg;
34257
- const Y = m[1] * ag + m[4] * bg + m[7] * cg;
34258
- const Z = m[2] * ag + m[5] * bg + m[8] * cg;
34259
- const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
34260
- const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
34261
- const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
34262
- rgba[p * 4] = toSrgbByte(linR);
34263
- rgba[p * 4 + 1] = toSrgbByte(linG);
34264
- rgba[p * 4 + 2] = toSrgbByte(linB);
34265
- rgba[p * 4 + 3] = 255;
34266
- return;
34267
- }
34268
- rU = ag;
34269
- gU = bg;
34270
- bU = cg;
36749
+ const rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
36750
+ const gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
36751
+ const bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
36752
+ if (csInfo.calibrated) {
36753
+ rgba.set(csInfo.calibrated.getRgb([rU, gU, bU], 0), p * 4);
36754
+ rgba[p * 4 + 3] = 255;
36755
+ return;
34271
36756
  }
34272
36757
  rgba[p * 4] = Math.round(rU * 255);
34273
36758
  rgba[p * 4 + 1] = Math.round(gU * 255);
@@ -34287,10 +36772,11 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
34287
36772
  }
34288
36773
  } else if (csInfo.colorSpace === "gray") {
34289
36774
  const writeGrayPixel = (p, gByte) => {
34290
- let gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
34291
- if (csInfo.calGrayGamma && csInfo.calGrayGamma !== 1) {
34292
- const lin = Math.pow(gU, csInfo.calGrayGamma);
34293
- gU = lin <= 31308e-7 ? 12.92 * lin : 1.055 * Math.pow(lin, 1 / 2.4) - 0.055;
36775
+ const gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
36776
+ if (csInfo.calibrated) {
36777
+ rgba.set(csInfo.calibrated.getRgb([gU], 0), p * 4);
36778
+ rgba[p * 4 + 3] = 255;
36779
+ return;
34294
36780
  }
34295
36781
  const outG = Math.round(Math.max(0, Math.min(1, gU)) * 255);
34296
36782
  rgba[p * 4] = outG;
@@ -34346,9 +36832,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
34346
36832
  const m = remapUnitSampleWithDecode((rawSamples[p * stride + chStep] ?? 0) / 255, 1, decodePairs);
34347
36833
  const y = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 2] ?? 0) / 255, 2, decodePairs);
34348
36834
  const k = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 3] ?? 0) / 255, 3, decodePairs);
34349
- rgba[p * 4] = Math.round((1 - c) * (1 - k) * 255);
34350
- rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
34351
- rgba[p * 4 + 2] = Math.round((1 - y) * (1 - k) * 255);
36835
+ rgba.set(cmykColorSpace.getRgb([c, m, y, k], 0), p * 4);
34352
36836
  rgba[p * 4 + 3] = 255;
34353
36837
  }
34354
36838
  } else if (csInfo.colorSpace === "index") {
@@ -34386,9 +36870,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
34386
36870
  const m = pal[idx * 4 + 1] / 255;
34387
36871
  const yel = pal[idx * 4 + 2] / 255;
34388
36872
  const k = pal[idx * 4 + 3] / 255;
34389
- rgba[p * 4] = Math.round((1 - c) * (1 - k) * 255);
34390
- rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
34391
- rgba[p * 4 + 2] = Math.round((1 - yel) * (1 - k) * 255);
36873
+ rgba.set(cmykColorSpace.getRgb([c, m, yel, k], 0), p * 4);
34392
36874
  } else {
34393
36875
  rgba[p * 4] = pal[idx * baseComp];
34394
36876
  rgba[p * 4 + 1] = pal[idx * baseComp + 1];
@@ -34940,6 +37422,7 @@ function extractDocumentImages(doc, options = {}) {
34940
37422
  }
34941
37423
  return extracted;
34942
37424
  }
37425
+ var cmykColorSpace2 = new DeviceCmykCS();
34943
37426
  function multiplyMatrices(m1, m2) {
34944
37427
  return [
34945
37428
  m1[0] * m2[0] + m1[1] * m2[2],
@@ -35156,193 +37639,7 @@ function resolvePageFonts(doc, resourcesDict) {
35156
37639
  }
35157
37640
  return fonts;
35158
37641
  }
35159
- function evaluateType4PostScriptTokens(tokens, initialStack) {
35160
- const stack = [...initialStack];
35161
- const runRange = (start, end) => {
35162
- let i = start;
35163
- while (i < end) {
35164
- const tok = tokens[i];
35165
- if (tok === "{") {
35166
- let depth = 1;
35167
- let j = i + 1;
35168
- while (j < end && depth > 0) {
35169
- if (tokens[j] === "{") depth++;
35170
- else if (tokens[j] === "}") depth--;
35171
- j++;
35172
- }
35173
- const blockStart = i + 1;
35174
- const blockEnd = j - 1;
35175
- if (j < end && tokens[j] === "{") {
35176
- let depth2 = 1;
35177
- let k = j + 1;
35178
- while (k < end && depth2 > 0) {
35179
- if (tokens[k] === "{") depth2++;
35180
- else if (tokens[k] === "}") depth2--;
35181
- k++;
35182
- }
35183
- if (k < end && tokens[k] === "ifelse") {
35184
- const cond = stack.pop() ?? 0;
35185
- if (cond !== 0) runRange(blockStart, blockEnd);
35186
- else runRange(j + 1, k - 1);
35187
- i = k + 1;
35188
- continue;
35189
- }
35190
- }
35191
- if (j < end && tokens[j] === "if") {
35192
- const cond = stack.pop() ?? 0;
35193
- if (cond !== 0) runRange(blockStart, blockEnd);
35194
- i = j + 1;
35195
- continue;
35196
- }
35197
- runRange(blockStart, blockEnd);
35198
- i = j;
35199
- continue;
35200
- }
35201
- if (tok === "}") {
35202
- i++;
35203
- continue;
35204
- }
35205
- const numVal2 = Number(tok);
35206
- if (tok.length > 0 && !Number.isNaN(numVal2)) {
35207
- stack.push(numVal2);
35208
- } else if (tok === "true") {
35209
- stack.push(1);
35210
- } else if (tok === "false") {
35211
- stack.push(0);
35212
- } else if (tok === "add") {
35213
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35214
- stack.push(a + b);
35215
- } else if (tok === "sub") {
35216
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35217
- stack.push(a - b);
35218
- } else if (tok === "mul") {
35219
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35220
- stack.push(a * b);
35221
- } else if (tok === "div") {
35222
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
35223
- stack.push(Math.abs(b) > 1e-12 ? a / b : 0);
35224
- } else if (tok === "idiv") {
35225
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
35226
- stack.push(Math.abs(b) > 1e-12 ? Math.trunc(a / b) : 0);
35227
- } else if (tok === "mod") {
35228
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
35229
- stack.push(Math.abs(b) > 1e-12 ? a % b : 0);
35230
- } else if (tok === "neg") {
35231
- stack.push(-(stack.pop() ?? 0));
35232
- } else if (tok === "abs") {
35233
- stack.push(Math.abs(stack.pop() ?? 0));
35234
- } else if (tok === "ceiling") {
35235
- stack.push(Math.ceil(stack.pop() ?? 0));
35236
- } else if (tok === "floor") {
35237
- stack.push(Math.floor(stack.pop() ?? 0));
35238
- } else if (tok === "round") {
35239
- stack.push(Math.round(stack.pop() ?? 0));
35240
- } else if (tok === "truncate" || tok === "cvi") {
35241
- stack.push(Math.trunc(stack.pop() ?? 0));
35242
- } else if (tok === "sqrt") {
35243
- stack.push(Math.sqrt(Math.max(0, stack.pop() ?? 0)));
35244
- } else if (tok === "sin") {
35245
- stack.push(Math.sin((stack.pop() ?? 0) * Math.PI / 180));
35246
- } else if (tok === "cos") {
35247
- stack.push(Math.cos((stack.pop() ?? 0) * Math.PI / 180));
35248
- } else if (tok === "atan") {
35249
- const dx = stack.pop() ?? 1, dy = stack.pop() ?? 0;
35250
- let deg = Math.atan2(dy, dx) * 180 / Math.PI;
35251
- if (deg < 0) deg += 360;
35252
- stack.push(deg);
35253
- } else if (tok === "exp") {
35254
- const exp = stack.pop() ?? 1, base = stack.pop() ?? 0;
35255
- stack.push(Math.pow(base, exp));
35256
- } else if (tok === "ln") {
35257
- stack.push(Math.log(Math.max(1e-12, stack.pop() ?? 1)));
35258
- } else if (tok === "log") {
35259
- stack.push(Math.log10(Math.max(1e-12, stack.pop() ?? 1)));
35260
- } else if (tok === "dup") {
35261
- if (stack.length > 0) stack.push(stack[stack.length - 1]);
35262
- } else if (tok === "exch") {
35263
- if (stack.length >= 2) {
35264
- const b = stack.pop(), a = stack.pop();
35265
- stack.push(b, a);
35266
- }
35267
- } else if (tok === "pop") {
35268
- stack.pop();
35269
- } else if (tok === "copy") {
35270
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
35271
- const slice = stack.slice(Math.max(0, stack.length - n));
35272
- stack.push(...slice);
35273
- } else if (tok === "index") {
35274
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
35275
- const idx = stack.length - 1 - n;
35276
- if (idx >= 0 && idx < stack.length) stack.push(stack[idx]);
35277
- } else if (tok === "roll") {
35278
- const jShift = Math.trunc(stack.pop() ?? 0);
35279
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
35280
- if (n > 0 && stack.length >= n) {
35281
- const sub = stack.splice(stack.length - n, n);
35282
- const modShift = (jShift % n + n) % n;
35283
- const rolled = [...sub.slice(n - modShift), ...sub.slice(0, n - modShift)];
35284
- stack.push(...rolled);
35285
- }
35286
- } else if (tok === "eq") {
35287
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35288
- stack.push(Math.abs(a - b) < 1e-9 ? 1 : 0);
35289
- } else if (tok === "ne") {
35290
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35291
- stack.push(Math.abs(a - b) >= 1e-9 ? 1 : 0);
35292
- } else if (tok === "gt") {
35293
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35294
- stack.push(a > b ? 1 : 0);
35295
- } else if (tok === "ge") {
35296
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35297
- stack.push(a >= b ? 1 : 0);
35298
- } else if (tok === "lt") {
35299
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35300
- stack.push(a < b ? 1 : 0);
35301
- } else if (tok === "le") {
35302
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35303
- stack.push(a <= b ? 1 : 0);
35304
- } else if (tok === "and") {
35305
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35306
- stack.push(a !== 0 && b !== 0 ? 1 : 0);
35307
- } else if (tok === "or") {
35308
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35309
- stack.push(a !== 0 || b !== 0 ? 1 : 0);
35310
- } else if (tok === "not") {
35311
- const a = stack.pop() ?? 0;
35312
- stack.push(a === 0 ? 1 : 0);
35313
- }
35314
- i++;
35315
- }
35316
- };
35317
- runRange(0, tokens.length);
35318
- return stack;
35319
- }
35320
- function tokenizePostScriptCode(bytes) {
35321
- const tokens = [];
35322
- let cur = "";
35323
- for (let i = 0; i < bytes.length; i++) {
35324
- const ch3 = String.fromCharCode(bytes[i]);
35325
- if (ch3 === "{" || ch3 === "}") {
35326
- if (cur.length > 0) {
35327
- tokens.push(cur);
35328
- cur = "";
35329
- }
35330
- tokens.push(ch3);
35331
- } else if (ch3 === " " || ch3 === " " || ch3 === "\n" || ch3 === "\r") {
35332
- if (cur.length > 0) {
35333
- tokens.push(cur);
35334
- cur = "";
35335
- }
35336
- } else {
35337
- cur += ch3;
35338
- }
35339
- }
35340
- if (cur.length > 0) tokens.push(cur);
35341
- if (tokens[0] === "{" && tokens[tokens.length - 1] === "}") {
35342
- return tokens.slice(1, -1);
35343
- }
35344
- return tokens;
35345
- }
37642
+ var postScriptFunctions = /* @__PURE__ */ new WeakMap();
35346
37643
  function evalShadingFunctionToComponents(doc, fnNode, inputs) {
35347
37644
  const inArr = typeof inputs === "number" ? [inputs] : inputs;
35348
37645
  const t = inArr[0] ?? 0;
@@ -35389,35 +37686,50 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
35389
37686
  const decode = getNums("Decode", range);
35390
37687
  const nOut = Math.max(1, Math.floor((decode.length || range.length || 6) / 2));
35391
37688
  const mIn = Math.max(1, size.length);
35392
- let flatGridIndex = 0;
37689
+ const streamBytes = doc.decodeStream(resolved);
37690
+ let vertices = [{ index: 0, weight: 1 }];
35393
37691
  let stride = 1;
35394
37692
  for (let i = 0; i < mIn; i++) {
35395
37693
  const d02 = dom[i * 2] ?? 0;
35396
37694
  const d12 = dom[i * 2 + 1] ?? 1;
35397
- const sMax = Math.max(1, (size[i] ?? 2) - 1);
37695
+ const sMax = Math.max(0, (size[i] ?? 2) - 1);
35398
37696
  const e0 = encode[i * 2] ?? 0;
35399
37697
  const e1 = encode[i * 2 + 1] ?? sMax;
35400
37698
  const x = Math.max(d02, Math.min(d12, inArr[i] ?? 0));
35401
- const u = Math.abs(d12 - d02) > 1e-8 ? (x - d02) / (d12 - d02) : 0;
35402
- const idx = Math.round(Math.max(0, Math.min(sMax, e0 + u * (e1 - e0))));
35403
- flatGridIndex += idx * stride;
37699
+ const u = d12 === d02 ? 0 : (x - d02) / (d12 - d02);
37700
+ const e = Math.max(0, Math.min(sMax, e0 + u * (e1 - e0)));
37701
+ const low = Math.floor(e), fraction = e - low;
37702
+ const next = [];
37703
+ for (const vertex of vertices) {
37704
+ const index = vertex.index + low * stride;
37705
+ if (index * nOut * bps < streamBytes.length * 8) next.push({ index, weight: vertex.weight * (1 - fraction) });
37706
+ if (fraction && (index + stride) * nOut * bps < streamBytes.length * 8) {
37707
+ next.push({ index: index + stride, weight: vertex.weight * fraction });
37708
+ }
37709
+ }
37710
+ vertices = next;
35404
37711
  stride *= size[i] ?? 2;
35405
37712
  }
35406
- const streamBytes = doc.decodeStream(resolved);
37713
+ const maxSample = 2 ** bps - 1;
37714
+ const readSample = (index) => {
37715
+ let bitOffset = index * bps, remaining = bps, value = 0;
37716
+ while (remaining > 0) {
37717
+ const bitInByte = bitOffset % 8;
37718
+ const take = Math.min(remaining, 8 - bitInByte);
37719
+ const byte = streamBytes[Math.floor(bitOffset / 8)] ?? 0;
37720
+ value = value * 2 ** take + (byte >> 8 - bitInByte - take & (1 << take) - 1);
37721
+ bitOffset += take;
37722
+ remaining -= take;
37723
+ }
37724
+ return value / maxSample;
37725
+ };
35407
37726
  const out2 = [];
35408
- const maxSample = bps === 16 ? 65535 : 255;
35409
37727
  for (let j = 0; j < nOut; j++) {
35410
- const sampleIdx = flatGridIndex * nOut + j;
35411
- let rawVal = 0;
35412
- if (bps === 16) {
35413
- rawVal = (streamBytes[sampleIdx * 2] ?? 0) << 8 | (streamBytes[sampleIdx * 2 + 1] ?? 0);
35414
- } else {
35415
- rawVal = streamBytes[sampleIdx] ?? 0;
35416
- }
35417
- const frac = rawVal / maxSample;
37728
+ let value = 0;
37729
+ for (const vertex of vertices) value += readSample(vertex.index * nOut + j) * vertex.weight;
35418
37730
  const dec0 = decode[j * 2] ?? 0;
35419
37731
  const dec1 = decode[j * 2 + 1] ?? 1;
35420
- out2.push(dec0 + frac * (dec1 - dec0));
37732
+ out2.push(dec0 + value * (dec1 - dec0));
35421
37733
  }
35422
37734
  return clampRange(out2);
35423
37735
  }
@@ -35427,34 +37739,40 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
35427
37739
  const d12 = dom[i * 2 + 1] ?? 1;
35428
37740
  return Math.max(d02, Math.min(d12, v));
35429
37741
  });
35430
- const tokens = tokenizePostScriptCode(doc.decodeStream(resolved));
35431
- const stackOut = evaluateType4PostScriptTokens(tokens, clampedInputs);
35432
- return clampRange(stackOut);
37742
+ const source = bytesToString3(doc.decodeStream(resolved));
37743
+ let cached = postScriptFunctions.get(resolved);
37744
+ 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])) {
37745
+ cached = { source, domain: dom, range, evaluate: buildPostScriptJsFunction(source, dom, range) };
37746
+ postScriptFunctions.set(resolved, cached);
37747
+ }
37748
+ const output = [];
37749
+ cached.evaluate(clampedInputs, 0, output, 0);
37750
+ return output;
35433
37751
  }
35434
37752
  if (ft === 3) {
35435
37753
  const fnsArr = doc.resolveArray(dictGet(fnDict, "Functions"));
35436
37754
  const bounds = getNums("Bounds", []);
35437
37755
  const encode = getNums("Encode", []);
35438
37756
  if (fnsArr && fnsArr.items.length > 0) {
37757
+ const input = Math.max(dom[0] ?? 0, Math.min(dom[1] ?? 1, t));
35439
37758
  let segIdx = 0;
35440
- while (segIdx < bounds.length && t >= bounds[segIdx]) segIdx++;
37759
+ while (segIdx < bounds.length && input >= bounds[segIdx]) segIdx++;
35441
37760
  segIdx = Math.min(fnsArr.items.length - 1, segIdx);
35442
37761
  const b0 = segIdx === 0 ? dom[0] ?? 0 : bounds[segIdx - 1];
35443
37762
  const b1 = segIdx < bounds.length ? bounds[segIdx] : dom[1] ?? 1;
35444
37763
  const e0 = encode[segIdx * 2] ?? 0;
35445
37764
  const e1 = encode[segIdx * 2 + 1] ?? 1;
35446
- const localT = Math.abs(b1 - b0) > 1e-8 ? e0 + (t - b0) / (b1 - b0) * (e1 - e0) : e0;
35447
- return evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], Math.max(0, Math.min(1, localT)));
37765
+ const localT = b1 !== b0 ? e0 + (input - b0) / (b1 - b0) * (e1 - e0) : e0;
37766
+ return clampRange(evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], localT));
35448
37767
  }
35449
37768
  }
35450
- const c0 = getNums("C0", [0, 0, 0]);
35451
- const c1 = getNums("C1", [1, 1, 1]);
37769
+ const c0 = getNums("C0", [0]);
37770
+ const c1 = getNums("C1", [1]);
35452
37771
  const nNode = doc.resolve(dictGet(fnDict, "N"));
35453
- const expN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
37772
+ const expN = nNode?.kind === "number" ? nNode.value : 1;
35454
37773
  const d0 = dom[0] ?? 0;
35455
37774
  const d1 = dom[1] ?? 1;
35456
- const normT = Math.abs(d1 - d0) > 1e-8 ? (t - d0) / (d1 - d0) : t;
35457
- const w = Math.pow(Math.max(0, Math.min(1, normT)), expN);
37775
+ const w = Math.pow(Math.max(d0, Math.min(d1, t)), expN);
35458
37776
  const len = Math.max(c0.length, c1.length);
35459
37777
  const out = [];
35460
37778
  for (let i = 0; i < len; i++) {
@@ -35470,30 +37788,14 @@ function shadingComponentsToRgb(csName, comps) {
35470
37788
  return [v, v, v];
35471
37789
  }
35472
37790
  if (csName === "DeviceCMYK" || csName === "CMYK" || comps.length >= 4) {
35473
- const cc = comps[0] ?? 0, cm = comps[1] ?? 0, cy = comps[2] ?? 0, ck = comps[3] ?? 0;
35474
- return [(1 - cc) * (1 - ck), (1 - cm) * (1 - kClamp(ck)), (1 - cy) * (1 - kClamp(ck))];
37791
+ const rgb2 = cmykColorSpace2.getRgb([comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0, comps[3] ?? 0], 0);
37792
+ return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
35475
37793
  }
35476
37794
  return [comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0];
35477
37795
  }
35478
37796
  function kClamp(v) {
35479
37797
  return Math.max(0, Math.min(1, v));
35480
37798
  }
35481
- function xyzToSrgb(X, Y, Z, Xw = 0.95047, Yw = 1, Zw = 1.08883) {
35482
- const scaleX = Xw > 1e-6 ? 0.95047 / Xw : 1;
35483
- const scaleY = Yw > 1e-6 ? 1 / Yw : 1;
35484
- const scaleZ = Zw > 1e-6 ? 1.08883 / Zw : 1;
35485
- const x = X * scaleX;
35486
- const y = Y * scaleY;
35487
- const z = Z * scaleZ;
35488
- const rl = 3.2404542 * x - 1.5371385 * y - 0.4985314 * z;
35489
- const gl = -0.969266 * x + 1.8760108 * y + 0.041556 * z;
35490
- const bl = 0.0556434 * x - 0.2040259 * y + 1.0572252 * z;
35491
- const toGamma = (u) => {
35492
- const c = Math.max(0, Math.min(1, u));
35493
- return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
35494
- };
35495
- return [toGamma(rl), toGamma(gl), toGamma(bl)];
35496
- }
35497
37799
  function getColorSpaceComponentCount(doc, csNode, activeResources, depth = 0) {
35498
37800
  if (!csNode || depth > 4) return 3;
35499
37801
  const resolved = doc ? doc.resolve(csNode) : csNode;
@@ -35550,63 +37852,10 @@ function convertColorSpaceComponentsToRgb(doc, csNode, csNameFallback, comps, ac
35550
37852
  if (resolved.kind === "array" && resolved.items.length > 0 && doc) {
35551
37853
  const familyNode = doc.resolve(resolved.items[0]);
35552
37854
  const family = familyNode?.kind === "name" ? familyNode.decoded : "";
35553
- if (family === "CalGray") {
35554
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
35555
- const gNode = paramDict ? doc.resolve(dictGet(paramDict, "Gamma")) : void 0;
35556
- const gamma = gNode?.kind === "number" && gNode.value > 0 ? gNode.value : 1;
35557
- const a = Math.pow(kClamp(comps[0] ?? 0), gamma);
35558
- return [a, a, a];
35559
- }
35560
- if (family === "CalRGB") {
35561
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
35562
- const gammaArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Gamma")) : void 0;
35563
- const getArrNum = (arr, idx, fb) => {
35564
- const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
35565
- return r?.kind === "number" ? r.value : fb;
35566
- };
35567
- const gr = getArrNum(gammaArr, 0, 1);
35568
- const gg = getArrNum(gammaArr, 1, 1);
35569
- const gb = getArrNum(gammaArr, 2, 1);
35570
- const ag = Math.pow(kClamp(comps[0] ?? 0), gr > 0 ? gr : 1);
35571
- const bg = Math.pow(kClamp(comps[1] ?? 0), gg > 0 ? gg : 1);
35572
- const cg = Math.pow(kClamp(comps[2] ?? 0), gb > 0 ? gb : 1);
35573
- const matArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Matrix")) : void 0;
35574
- if (matArr && matArr.items.length >= 9) {
35575
- const m = (i) => getArrNum(matArr, i, 0);
35576
- const X = m(0) * ag + m(3) * bg + m(6) * cg;
35577
- const Y = m(1) * ag + m(4) * bg + m(7) * cg;
35578
- const Z = m(2) * ag + m(5) * bg + m(8) * cg;
35579
- const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
35580
- const Xw = getArrNum(wpArr, 0, 0.95047);
35581
- const Yw = getArrNum(wpArr, 1, 1);
35582
- const Zw = getArrNum(wpArr, 2, 1.08883);
35583
- return xyzToSrgb(X, Y, Z, Xw, Yw, Zw);
35584
- }
35585
- return [ag, bg, cg];
35586
- }
35587
- if (family === "Lab") {
35588
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
35589
- const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
35590
- const rangeArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Range")) : void 0;
35591
- const getNum = (arr, idx, fb) => {
35592
- const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
35593
- return r?.kind === "number" ? r.value : fb;
35594
- };
35595
- const Xw = getNum(wpArr, 0, 0.95047);
35596
- const Yw = getNum(wpArr, 1, 1);
35597
- const Zw = getNum(wpArr, 2, 1.08883);
35598
- const amin = getNum(rangeArr, 0, -100);
35599
- const amax = getNum(rangeArr, 1, 100);
35600
- const bmin = getNum(rangeArr, 2, -100);
35601
- const bmax = getNum(rangeArr, 3, 100);
35602
- const Lstar = Math.max(0, Math.min(100, comps[0] ?? 0));
35603
- const astar = Math.max(amin, Math.min(amax, comps[1] ?? 0));
35604
- const bstar = Math.max(bmin, Math.min(bmax, comps[2] ?? 0));
35605
- const M = (Lstar + 16) / 116;
35606
- const L = M + astar / 500;
35607
- const N = M - bstar / 200;
35608
- const gFn = (x) => x >= 6 / 29 ? x * x * x : 108 / 841 * (x - 4 / 29);
35609
- return xyzToSrgb(Xw * gFn(L), Yw * gFn(M), Zw * gFn(N), Xw, Yw, Zw);
37855
+ if (family === "CalGray" || family === "CalRGB" || family === "Lab") {
37856
+ const colorSpace = createCalibratedColorSpace(doc, family, resolved.items[1]);
37857
+ const rgb2 = colorSpace.getRgb(comps, 0);
37858
+ return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
35610
37859
  }
35611
37860
  if (family === "ICCBased" && resolved.items[1]) {
35612
37861
  const iccNode = doc.resolve(resolved.items[1]);
@@ -36257,7 +38506,8 @@ function evaluateContentStreamToDisplayList(params) {
36257
38506
  const shDict = shNode?.kind === "dict" ? shNode : shNode?.kind === "stream" ? shNode.dict : void 0;
36258
38507
  const shStream = shNode?.kind === "stream" ? shNode : void 0;
36259
38508
  if (shDict) {
36260
- const targetBox = st.clipRect ?? [0, 0, params.width, params.height];
38509
+ const [originX, originY] = params.origin ?? [0, 0];
38510
+ const targetBox = st.clipRect ?? [originX, originY, originX + params.width, originY + params.height];
36261
38511
  const img = renderShadingDictToImage(
36262
38512
  params.cosDoc,
36263
38513
  shDict,
@@ -36296,12 +38546,10 @@ function evaluateContentStreamToDisplayList(params) {
36296
38546
  } else if (operator === "RG" || operator === "SC" || operator === "SCN") {
36297
38547
  st.strokeColor = resolveScColorOperands(operator === "RG" ? "DeviceRGB" : st.strokeColorSpaceName, ops, activeResources);
36298
38548
  } else if (operator === "k") {
36299
- const c = num(0), m = num(1), y = num(2), k = num(3);
36300
- st.fillColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
38549
+ st.fillColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
36301
38550
  st.fillPatternName = void 0;
36302
38551
  } else if (operator === "K") {
36303
- const c = num(0), m = num(1), y = num(2), k = num(3);
36304
- st.strokeColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
38552
+ st.strokeColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
36305
38553
  } else if (operator === "gs" && params.cosDoc && activeResources && ops[0]?.kind === "name") {
36306
38554
  const extDict = params.cosDoc.resolveDict(dictGet(activeResources, "ExtGState"));
36307
38555
  const gsDict = extDict ? params.cosDoc.resolveDict(dictGet(extDict, ops[0].decoded)) : void 0;
@@ -36510,7 +38758,7 @@ function evaluateContentStreamToDisplayList(params) {
36510
38758
  stateStack.pop();
36511
38759
  capturedOperations = parentOperations;
36512
38760
  }
36513
- if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
38761
+ if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, isolated, bboxClip: nextClipPaths?.[0], blendMode: st.blendMode, clipRect: st.clipRect } });
36514
38762
  };
36515
38763
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
36516
38764
  for (const node of nodes) {
@@ -37094,6 +39342,7 @@ function evaluateContentStreamToDisplayList(params) {
37094
39342
  pageIndex: params.pageIndex,
37095
39343
  width: params.width,
37096
39344
  height: params.height,
39345
+ ...params.origin ? { origin: params.origin } : {},
37097
39346
  rotation: params.rotation ?? 0,
37098
39347
  glyphs,
37099
39348
  paths,
@@ -38564,7 +40813,7 @@ var PdfPage = class {
38564
40813
  return [n0.value, n1.value, n2.value, n3.value];
38565
40814
  }
38566
40815
  }
38567
- return [0, 0, 612, 792];
40816
+ return key === "MediaBox" ? [0, 0, 612, 792] : this.resolveBox("MediaBox");
38568
40817
  }
38569
40818
  getMediaBox() {
38570
40819
  return this.resolveBox("MediaBox");
@@ -39237,16 +41486,19 @@ var PdfPage = class {
39237
41486
  });
39238
41487
  }
39239
41488
  }
39240
- return evaluateContentStreamToDisplayList({
41489
+ const mediaBox = this.getMediaBox(), cropBox = this.getCropBox();
41490
+ const originX = Math.min(mediaBox[0], mediaBox[2]), originY = Math.min(mediaBox[1], mediaBox[3]);
41491
+ return { ...evaluateContentStreamToDisplayList({
39241
41492
  pageIndex: this.index,
39242
41493
  width,
39243
41494
  height,
41495
+ origin: [originX, originY],
39244
41496
  rotation: this.getRotation(),
39245
41497
  nodes: baseNodes,
39246
41498
  cosDoc: this.cosDoc,
39247
41499
  resourcesDict: evalResourcesDict,
39248
41500
  annotations: extractPageAnnotations(this.cosDoc, this.pageDict)
39249
- });
41501
+ }), cropBox: [cropBox[0] - originX, cropBox[1] - originY, cropBox[2] - originX, cropBox[3] - originY] };
39250
41502
  }
39251
41503
  extractPage(options) {
39252
41504
  const dl = this.evaluateDisplayList();
@@ -39264,10 +41516,10 @@ var PdfPage = class {
39264
41516
  return extractTablesFromDisplayList(this.evaluateDisplayList());
39265
41517
  }
39266
41518
  renderToBitmap(options) {
39267
- return renderDisplayListToBitmap(this.evaluateDisplayList(), options);
41519
+ return renderDisplayListToBitmap(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
39268
41520
  }
39269
41521
  renderToPng(options) {
39270
- return renderDisplayListToPng(this.evaluateDisplayList(), options);
41522
+ return renderDisplayListToPng(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
39271
41523
  }
39272
41524
  };
39273
41525
  function createStandardFontHandle(standardName) {
@@ -40713,7 +42965,7 @@ function prepareStroke(path, scale) {
40713
42965
  }
40714
42966
  return { matrix, width, dashArray, dashPhase };
40715
42967
  }
40716
- function strokeContours(path, pageHeight, scale) {
42968
+ function strokeContours(path, pageHeight, scale, originX = 0, originY = 0) {
40717
42969
  const stroke = prepareStroke(path, scale);
40718
42970
  if (!stroke) return [];
40719
42971
  const inverse = inverseStrokeMatrix(stroke.matrix);
@@ -40725,8 +42977,8 @@ function strokeContours(path, pageHeight, scale) {
40725
42977
  (inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
40726
42978
  ];
40727
42979
  const toScreen = ([x, y]) => [
40728
- (a * x / strokeScale + c * y / strokeScale + e) * scale,
40729
- (pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
42980
+ (a * x / strokeScale + c * y / strokeScale + e - originX) * scale,
42981
+ (pageHeight + originY - b * x / strokeScale - d * y / strokeScale - f) * scale
40730
42982
  ];
40731
42983
  const contours = strokeOutlines(
40732
42984
  segmentsToScreenPaths(path.segments, pageHeight, scale, project),
@@ -40884,18 +43136,37 @@ function renderSoftMask(mask, displayList, scale) {
40884
43136
  }
40885
43137
  return bitmap;
40886
43138
  }
40887
- function hasBlendModes(operations) {
40888
- return operations.some((operation) => !!operation.value.blendMode && operation.value.blendMode !== "Normal" && operation.value.blendMode !== "Compatible" || operation.kind === "group" && hasBlendModes(operation.value.operations));
43139
+ function getDisplayListCropBox(list) {
43140
+ const full = [0, 0, list.width, list.height];
43141
+ const box = list.cropBox;
43142
+ if (!box || !box.every(Number.isFinite)) return full;
43143
+ const x0 = Math.max(0, Math.min(box[0], box[2]));
43144
+ const y0 = Math.max(0, Math.min(box[1], box[3]));
43145
+ const x1 = Math.min(list.width, Math.max(box[0], box[2]));
43146
+ const y1 = Math.min(list.height, Math.max(box[1], box[3]));
43147
+ return x1 > x0 && y1 > y0 ? [x0, y0, x1, y1] : full;
43148
+ }
43149
+ function hasCompositingEffects(operations, includeSoftMasks = false) {
43150
+ 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));
43151
+ }
43152
+ function needsGroupBackdrop(group) {
43153
+ return group.isolated === false && !!group.softMask && hasCompositingEffects(group.operations, true);
43154
+ }
43155
+ function containsBackdropGroup(operations) {
43156
+ return operations.some((operation) => operation.kind === "group" && (needsGroupBackdrop(operation.value) || containsBackdropGroup(operation.value.operations)));
40889
43157
  }
40890
43158
  function renderDisplayListToBitmap(displayList, options = {}) {
40891
43159
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
40892
43160
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
40893
43161
  const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
40894
43162
  const scale = scaleX;
43163
+ const [originX, originY] = displayList.origin ?? [0, 0];
43164
+ const pageTop = originY + displayList.height;
43165
+ const toScreen = (x, y) => [(x - originX) * scale, (pageTop - y) * scale];
40895
43166
  const width = Math.max(1, Math.round(displayList.width * scale));
40896
43167
  const height = Math.max(1, Math.round(displayList.height * scale));
40897
43168
  const rgba = new Uint8Array(width * height * 4);
40898
- const deferBackground = !options.transparent && hasBlendModes(paintOperations(displayList));
43169
+ const deferBackground = !options.transparent && hasCompositingEffects(paintOperations(displayList));
40899
43170
  const transparent = options.transparent || deferBackground;
40900
43171
  const bg = options.background ?? { r: 1, g: 1, b: 1 };
40901
43172
  const bgR = transparent ? 0 : Math.round(bg.r * 255);
@@ -40920,14 +43191,27 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40920
43191
  let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
40921
43192
  if (operation.kind === "group") {
40922
43193
  const group = operation.value;
40923
- const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations: group.operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, transparent: true });
43194
+ let operations = group.operations;
43195
+ if (needsGroupBackdrop(group)) {
43196
+ operations = [{ kind: "image", value: {
43197
+ name: "GroupBackdrop",
43198
+ width,
43199
+ height,
43200
+ decodedRgba: rgba.slice(),
43201
+ matrix: [width / scale, 0, 0, height / scale, originX, pageTop - height / scale],
43202
+ colorSpace: "DeviceRGB",
43203
+ bitsPerComponent: 8,
43204
+ ...group.bboxClip ? { clipPaths: [group.bboxClip] } : {}
43205
+ } }, ...operations];
43206
+ }
43207
+ const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, useCropBox: false, transparent: true });
40924
43208
  for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
40925
43209
  operation = { kind: "image", value: {
40926
43210
  name: "TransparencyGroup",
40927
43211
  width: bitmap.width,
40928
43212
  height: bitmap.height,
40929
43213
  decodedRgba: bitmap.data,
40930
- matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, 0, displayList.height - bitmap.height / scale],
43214
+ matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, originX, pageTop - bitmap.height / scale],
40931
43215
  colorSpace: "DeviceRGB",
40932
43216
  bitsPerComponent: 8,
40933
43217
  blendMode: group.blendMode,
@@ -40941,7 +43225,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40941
43225
  for (const clip of clips) {
40942
43226
  const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
40943
43227
  const layer = new Uint8Array(width * height * 4);
40944
- fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
43228
+ fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale, toScreen), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
40945
43229
  for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
40946
43230
  }
40947
43231
  cachedClips = clips;
@@ -40988,15 +43272,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40988
43272
  if (operation.kind === "path") {
40989
43273
  const path = operation.value;
40990
43274
  if (path.fillColor) {
40991
- const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale), true);
40992
- 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;
43275
+ const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale, toScreen), true);
43276
+ 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;
40993
43277
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
40994
43278
  }
40995
43279
  if (path.strokeColor) {
40996
43280
  const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
40997
43281
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
40998
- const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
40999
- 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;
43282
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale, originX, originY).map((points) => ({ points, closed: true })));
43283
+ 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;
41000
43284
  fillEdgesScanline4x4(
41001
43285
  rgba,
41002
43286
  width,
@@ -41019,12 +43303,12 @@ function renderDisplayListToBitmap(displayList, options = {}) {
41019
43303
  if (Math.abs(det) <= 1e-8) continue;
41020
43304
  const cornersPdfX = [e, a + e, a + c + e, c + e];
41021
43305
  const cornersPdfY = [f, b + f, b + d + f, d + f];
41022
- const cornersPx = cornersPdfX.map((cx) => cx * scale);
41023
- const cornersPy = cornersPdfY.map((cy) => (displayList.height - cy) * scale);
41024
- const clipMinPx = img.clipRect ? Math.floor(img.clipRect[0] * scale) : 0;
41025
- const clipMaxPx = img.clipRect ? Math.ceil(img.clipRect[2] * scale) - 1 : width - 1;
41026
- const clipMinPy = img.clipRect ? Math.floor((displayList.height - img.clipRect[3]) * scale) : 0;
41027
- const clipMaxPy = img.clipRect ? Math.ceil((displayList.height - img.clipRect[1]) * scale) - 1 : height - 1;
43306
+ const cornersPx = cornersPdfX.map((cx) => (cx - originX) * scale);
43307
+ const cornersPy = cornersPdfY.map((cy) => (pageTop - cy) * scale);
43308
+ const clipMinPx = img.clipRect ? Math.floor((img.clipRect[0] - originX) * scale) : 0;
43309
+ const clipMaxPx = img.clipRect ? Math.ceil((img.clipRect[2] - originX) * scale) - 1 : width - 1;
43310
+ const clipMinPy = img.clipRect ? Math.floor((pageTop - img.clipRect[3]) * scale) : 0;
43311
+ const clipMaxPy = img.clipRect ? Math.ceil((pageTop - img.clipRect[1]) * scale) - 1 : height - 1;
41028
43312
  const minPx = Math.max(0, clipMinPx, Math.floor(Math.min(...cornersPx)));
41029
43313
  const maxPx = Math.min(width - 1, clipMaxPx, Math.ceil(Math.max(...cornersPx)) - 1);
41030
43314
  const minPy = Math.max(0, clipMinPy, Math.floor(Math.min(...cornersPy)));
@@ -41041,11 +43325,11 @@ function renderDisplayListToBitmap(displayList, options = {}) {
41041
43325
  const smooth = Math.fround((s1 + s2 + Math.hypot(s1 - s2, 2 * cross)) / 2) <= 1;
41042
43326
  const sample = new Float64Array(4);
41043
43327
  for (let py = minPy; py <= maxPy; py++) {
41044
- const yPdf = displayList.height - (py + 0.5) / scale;
43328
+ const yPdf = pageTop - (py + 0.5) / scale;
41045
43329
  if (img.clipRect && (yPdf < img.clipRect[1] || yPdf > img.clipRect[3])) continue;
41046
43330
  const dyPdf = yPdf - f;
41047
43331
  for (let px = minPx; px <= maxPx; px++) {
41048
- const xPdf = (px + 0.5) / scale;
43332
+ const xPdf = originX + (px + 0.5) / scale;
41049
43333
  if (img.clipRect && (xPdf < img.clipRect[0] || xPdf > img.clipRect[2])) continue;
41050
43334
  const dxPdf = xPdf - e;
41051
43335
  const u = (d * dxPdf - c * dyPdf) / det;
@@ -41106,6 +43390,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
41106
43390
  }
41107
43391
  result = { width: targetW, height: targetH, data: resampled };
41108
43392
  }
43393
+ if (options.useCropBox) {
43394
+ const box = getDisplayListCropBox(displayList);
43395
+ result = cropRgbaBitmap(result, {
43396
+ x: box[0] * scaleX,
43397
+ y: (displayList.height - box[3]) * scaleY,
43398
+ width: (box[2] - box[0]) * scaleX,
43399
+ height: (box[3] - box[1]) * scaleY
43400
+ });
43401
+ }
41109
43402
  result = rotateRgbaBitmapQuarterTurns(result, displayList.rotation ?? 0);
41110
43403
  if (options.cropRect) {
41111
43404
  result = cropRgbaBitmap(result, options.cropRect);
@@ -41175,18 +43468,44 @@ function svgPathData(segments, height, matrix) {
41175
43468
  }
41176
43469
  function renderDisplayListToSvg(displayList, options = {}) {
41177
43470
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1);
43471
+ if (containsBackdropGroup(paintOperations(displayList))) {
43472
+ const bitmap = renderDisplayListToBitmap(displayList, { ...options, scale: baseScale });
43473
+ const embedded = svgImage({
43474
+ name: "PageComposite",
43475
+ width: bitmap.width,
43476
+ height: bitmap.height,
43477
+ decodedRgba: bitmap.data,
43478
+ matrix: [bitmap.width, 0, 0, bitmap.height, 0, 0],
43479
+ colorSpace: "DeviceRGB",
43480
+ bitsPerComponent: 8
43481
+ }, bitmap.height);
43482
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${bitmap.width}" height="${bitmap.height}" viewBox="0 0 ${bitmap.width} ${bitmap.height}">${embedded}</svg>
43483
+ `;
43484
+ }
41178
43485
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
41179
43486
  const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
41180
- const viewport = new PageViewport({ viewBox: [0, 0, displayList.width, displayList.height], userUnit: 1, scale: 1, rotation: displayList.rotation ?? 0 });
43487
+ const [originX, originY] = displayList.origin ?? [0, 0];
43488
+ const viewport = new PageViewport({ viewBox: [originX, originY, originX + displayList.width, originY + displayList.height], userUnit: 1, scale: 1, rotation: displayList.rotation ?? 0 });
41181
43489
  const quarterTurn = displayList.rotation === 90 || displayList.rotation === 270;
41182
43490
  const outputScaleX = quarterTurn ? scaleY : scaleX;
41183
43491
  const outputScaleY = quarterTurn ? scaleX : scaleY;
41184
- const fullW = Math.max(1, Math.round(viewport.width * outputScaleX));
41185
- const fullH = Math.max(1, Math.round(viewport.height * outputScaleY));
41186
- const vbX = options.cropRect ? options.cropRect.x / outputScaleX : 0;
41187
- const vbY = options.cropRect ? options.cropRect.y / outputScaleY : 0;
41188
- const vbW = options.cropRect && options.cropRect.width > 0 ? options.cropRect.width / outputScaleX : Math.max(1, viewport.width - vbX);
41189
- const vbH = options.cropRect && options.cropRect.height > 0 ? options.cropRect.height / outputScaleY : Math.max(1, viewport.height - vbY);
43492
+ let bounds = [0, 0, viewport.width, viewport.height];
43493
+ if (options.useCropBox) {
43494
+ const box = getDisplayListCropBox(displayList);
43495
+ const [x0, y0, x1, y1] = [box[0] + originX, box[1] + originY, box[2] + originX, box[3] + originY];
43496
+ const [a, b, c, d, e, f] = viewport.transform;
43497
+ bounds = [a * x0 + c * y0 + e, b * x0 + d * y0 + f, a * x1 + c * y1 + e, b * x1 + d * y1 + f];
43498
+ }
43499
+ const viewX = Math.min(bounds[0], bounds[2]), viewY = Math.min(bounds[1], bounds[3]);
43500
+ const viewWidth = Math.abs(bounds[2] - bounds[0]), viewHeight = Math.abs(bounds[3] - bounds[1]);
43501
+ const fullW = Math.max(1, Math.round(viewWidth * outputScaleX));
43502
+ const fullH = Math.max(1, Math.round(viewHeight * outputScaleY));
43503
+ const cropX = options.cropRect ? options.cropRect.x / outputScaleX : 0;
43504
+ const vbX = viewX + cropX;
43505
+ const cropY = options.cropRect ? options.cropRect.y / outputScaleY : 0;
43506
+ const vbY = viewY + cropY;
43507
+ const vbW = options.cropRect && options.cropRect.width > 0 ? options.cropRect.width / outputScaleX : Math.max(1, viewWidth - cropX);
43508
+ const vbH = options.cropRect && options.cropRect.height > 0 ? options.cropRect.height / outputScaleY : Math.max(1, viewHeight - cropY);
41190
43509
  const outW = options.cropRect && options.cropRect.width > 0 ? Math.round(options.cropRect.width) : Math.max(1, fullW - Math.round(options.cropRect?.x ?? 0));
41191
43510
  const outH = options.cropRect && options.cropRect.height > 0 ? Math.round(options.cropRect.height) : Math.max(1, fullH - Math.round(options.cropRect?.y ?? 0));
41192
43511
  const parts = [
@@ -41196,7 +43515,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
41196
43515
  parts.push(` <rect x="${vbX}" y="${vbY}" width="${vbW}" height="${vbH}" fill="#ffffff"/>`);
41197
43516
  }
41198
43517
  parts.push('<g style="isolation:isolate">');
41199
- if (displayList.rotation) {
43518
+ if (displayList.rotation || originX || originY) {
41200
43519
  const [a, b, c, d, e, f] = viewport.transform;
41201
43520
  parts.push(`<g transform="matrix(${a} ${b} ${-c} ${-d} ${e + c * displayList.height} ${f + d * displayList.height})">`);
41202
43521
  }
@@ -41222,11 +43541,11 @@ function renderDisplayListToSvg(displayList, options = {}) {
41222
43541
  width: bitmap.width,
41223
43542
  height: bitmap.height,
41224
43543
  decodedRgba: bitmap.data,
41225
- matrix: [displayList.width, 0, 0, displayList.height, 0, 0],
43544
+ matrix: [displayList.width, 0, 0, displayList.height, originX, originY],
41226
43545
  colorSpace: "DeviceGray",
41227
43546
  bitsPerComponent: 8
41228
43547
  };
41229
- parts.push(`<defs><mask id="${id}" maskUnits="userSpaceOnUse" x="0" y="0" width="${displayList.width}" height="${displayList.height}" style="mask-type:alpha">${svgImage(image, displayList.height)}</mask></defs>`);
43548
+ parts.push(`<defs><mask id="${id}" maskUnits="userSpaceOnUse" x="${originX}" y="${-originY}" width="${displayList.width}" height="${displayList.height}" style="mask-type:alpha">${svgImage(image, displayList.height)}</mask></defs>`);
41230
43549
  }
41231
43550
  parts.push(`<g mask="url(#${id})">`);
41232
43551
  }
@@ -41238,7 +43557,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
41238
43557
  }
41239
43558
  for (const image of imageClips) {
41240
43559
  const id = `image-clip-${clipId++}`;
41241
- parts.push(`<defs><mask id="${id}" maskUnits="userSpaceOnUse" x="0" y="0" width="${displayList.width}" height="${displayList.height}" style="mask-type:alpha">${svgImage(image, displayList.height)}</mask></defs><g mask="url(#${id})">`);
43560
+ parts.push(`<defs><mask id="${id}" maskUnits="userSpaceOnUse" x="${originX}" y="${-originY}" width="${displayList.width}" height="${displayList.height}" style="mask-type:alpha">${svgImage(image, displayList.height)}</mask></defs><g mask="url(#${id})">`);
41242
43561
  }
41243
43562
  if (operation.kind === "group") {
41244
43563
  parts.push(`<g opacity="${operation.value.alpha}" style="isolation:isolate">`);
@@ -41282,7 +43601,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
41282
43601
  }
41283
43602
  };
41284
43603
  appendOperations(paintOperations(displayList));
41285
- if (displayList.rotation) parts.push("</g>");
43604
+ if (displayList.rotation || originX || originY) parts.push("</g>");
41286
43605
  parts.push("</g>");
41287
43606
  parts.push("</svg>\n");
41288
43607
  return parts.join("\n");
@@ -41305,23 +43624,6 @@ function collectLeavesForRaster(cosDoc, node, out = [], visited = /* @__PURE__ *
41305
43624
  }
41306
43625
  return out;
41307
43626
  }
41308
- function extractBoxArray(cosDoc, dict, key) {
41309
- let cur = dict;
41310
- const visited = /* @__PURE__ */ new Set();
41311
- while (cur && !visited.has(cur)) {
41312
- visited.add(cur);
41313
- const arr = cosDoc.resolveArray(dictGet(cur, key));
41314
- if (arr && arr.items.length >= 4) {
41315
- const nums = arr.items.slice(0, 4).map((item) => {
41316
- const r = cosDoc.resolve(item);
41317
- return r?.kind === "number" ? r.value : 0;
41318
- });
41319
- return [nums[0], nums[1], nums[2], nums[3]];
41320
- }
41321
- cur = cosDoc.resolveDict(dictGet(cur, "Parent"));
41322
- }
41323
- return void 0;
41324
- }
41325
43627
  function renderPdfPageToBitmap(pdfBytes, pageIndex = 0, options) {
41326
43628
  const cos = pdfBytes instanceof Uint8Array ? parseCosDocument(pdfBytes) : pdfBytes;
41327
43629
  const catalog = cos.resolveDict(cos.rootRef);
@@ -41330,35 +43632,7 @@ function renderPdfPageToBitmap(pdfBytes, pageIndex = 0, options) {
41330
43632
  if (!leaf) throw new Error(`Page index ${pageIndex} out of bounds`);
41331
43633
  const resolvedIndex = leaves.indexOf(leaf);
41332
43634
  const page = new PdfPage(cos, leaf.ref, leaf.dict, resolvedIndex);
41333
- const { cropRect, ...restOptions } = options ?? {};
41334
- let bitmap = renderDisplayListToBitmap(
41335
- // CropBox is in unrotated page coordinates. Apply page rotation after it.
41336
- { ...page.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), rotation: 0 },
41337
- restOptions
41338
- );
41339
- if (options?.useCropBox) {
41340
- const cropBox = extractBoxArray(cos, leaf.dict, "CropBox");
41341
- if (cropBox) {
41342
- const mediaBox = extractBoxArray(cos, leaf.dict, "MediaBox") ?? [0, 0, page.getSize().width, page.getSize().height];
41343
- const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
41344
- const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
41345
- const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
41346
- const mediaH = mediaBox[3] - mediaBox[1];
41347
- const bx = Math.round((cropBox[0] - mediaBox[0]) * scaleX);
41348
- const by = Math.round((mediaH - (cropBox[3] - mediaBox[1])) * scaleY);
41349
- const bw = Math.max(1, Math.round(Math.abs(cropBox[2] - cropBox[0]) * scaleX));
41350
- const bh = Math.max(1, Math.round(Math.abs(cropBox[3] - cropBox[1]) * scaleY));
41351
- bitmap = cropRgbaBitmap(bitmap, { x: bx, y: by, width: bw, height: bh });
41352
- }
41353
- }
41354
- const rotation = page.getRotation();
41355
- if (rotation === 90 || rotation === 180 || rotation === 270) {
41356
- bitmap = rotateRgbaBitmapQuarterTurns(bitmap, rotation);
41357
- }
41358
- if (cropRect) {
41359
- bitmap = cropRgbaBitmap(bitmap, cropRect);
41360
- }
41361
- return bitmap;
43635
+ return page.renderToBitmap(options);
41362
43636
  }
41363
43637
  function discardUnreachableObjects(doc) {
41364
43638
  const reachable = /* @__PURE__ */ new Set();