@poe-platform/safe-bash 0.1.772 → 0.1.774

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/image-ast/index.browser.js +3543 -706
  2. package/dist/image-ast/index.js +3543 -706
  3. package/dist/pdf-ast/ast.d.ts +7 -0
  4. package/dist/pdf-ast/content/evaluator.d.ts +1 -0
  5. package/dist/pdf-ast/index.js +3587 -718
  6. package/dist/pdf-ast/render/raster.d.ts +1 -0
  7. package/dist/pdf-ast/vendor/pdfjs-fonts.d.mts +36 -0
  8. package/dist/pdf-ast/vendor/pdfjs-fonts.mjs +3323 -0
  9. package/dist/safe-bash/command-chunks/{chunk-M2XU2YCK.js → chunk-4ZHDCMQX.js} +2 -2
  10. package/dist/safe-bash/command-chunks/{chunk-NBENXODJ.js → chunk-HH5QPKIN.js} +1 -1
  11. package/dist/safe-bash/command-chunks/{chunk-C4AAJTXF.js → chunk-PM63UJE6.js} +3546 -706
  12. package/dist/safe-bash/core.browser.js +101 -45
  13. package/dist/safe-bash/core.d.ts +1 -1
  14. package/dist/safe-bash/plugins/composition.d.ts +2 -0
  15. package/dist/safe-bash/plugins/composition.js +2 -1
  16. package/dist/safe-bash/shell/runtime.js +17 -9
  17. package/dist/safe-bash/shell/sync-posix-regex.d.ts +3 -0
  18. package/dist/safe-bash/shell/sync-posix-regex.js +48 -0
  19. package/dist/safe-bash-command-ffmpeg/index.js +11032 -9579
  20. package/dist/safe-bash-command-gh/index.d.ts +1 -0
  21. package/dist/safe-bash-command-gh/index.js +43 -13
  22. package/dist/safe-bash-command-gh/types.d.ts +1 -0
  23. package/dist/safe-bash-command-git/git_rust.wasm +0 -0
  24. package/dist/safe-bash-command-git/index.js +22 -15
  25. package/dist/safe-bash-command-git/wasm.generated.js +1 -1
  26. package/dist/safe-bash-command-gpg/index.js +28 -7
  27. package/dist/safe-bash-command-imagemagick/index.js +2 -2
  28. package/dist/safe-bash-command-openssl/index.js +24 -6
  29. package/dist/safe-bash-command-pandoc/command.js +3 -3
  30. package/dist/safe-bash-command-pandoc/index.js +3 -3
  31. package/dist/safe-bash-command-pdfimages/index.js +3542 -660
  32. package/dist/safe-bash-command-pdfinfo/index.js +3584 -718
  33. package/dist/safe-bash-command-pdftk/index.js +3542 -660
  34. package/dist/safe-bash-command-pdftoppm/index.js +3589 -787
  35. package/dist/safe-bash-command-pdftotext/index.js +3542 -660
  36. package/dist/safe-bash-command-qpdf/index.js +3542 -660
  37. package/dist/safe-bash-command-sips/index.js +2 -2
  38. package/dist/safe-bash-command-soffice/index.js +1 -1
  39. package/dist/safe-bash-command-ssconvert/index.js +3553 -716
  40. package/dist/safe-bash-command-ssh/index.js +124 -23
  41. package/dist/safe-bash-command-wkhtmltopdf/index.js +3581 -660
  42. package/dist/safe-bash-mcp/index.d.ts +8 -2
  43. package/dist/safe-bash-mcp/index.js +13 -6
  44. package/package.json +7 -7
  45. package/third-party/pdf-ast/THIRD_PARTY_NOTICES.md +84 -1
@@ -3578,6 +3578,11 @@ var FONT_IDENTITY_MATRIX = [1e-3, 0, 0, 1e-3, 0, 0];
3578
3578
  var LINE_FACTOR = 1.35;
3579
3579
  var LINE_DESCENT_FACTOR = 0.35;
3580
3580
  var BASELINE_FACTOR = LINE_DESCENT_FACTOR / LINE_FACTOR;
3581
+ var MeshFigureType = {
3582
+ TRIANGLES: 1,
3583
+ LATTICE: 2,
3584
+ PATCH: 3
3585
+ };
3581
3586
  var VerbosityLevel = {
3582
3587
  ERRORS: 0,
3583
3588
  WARNINGS: 1,
@@ -22696,6 +22701,3308 @@ var PageViewport = class _PageViewport {
22696
22701
  return p;
22697
22702
  }
22698
22703
  };
22704
+ function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
22705
+ const COMPONENTS = 3;
22706
+ alpha01 = alpha01 !== 1 ? 0 : alpha01;
22707
+ const xRatio = w1 / w2;
22708
+ const yRatio = h1 / h2;
22709
+ let newIndex = 0, oldIndex;
22710
+ const xScaled = new Uint16Array(w2);
22711
+ const w1Scanline = w1 * COMPONENTS;
22712
+ for (let i = 0; i < w2; i++) {
22713
+ xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
22714
+ }
22715
+ for (let i = 0; i < h2; i++) {
22716
+ const py = Math.floor(i * yRatio) * w1Scanline;
22717
+ for (let j = 0; j < w2; j++) {
22718
+ oldIndex = py + xScaled[j];
22719
+ dest[newIndex++] = src[oldIndex++];
22720
+ dest[newIndex++] = src[oldIndex++];
22721
+ dest[newIndex++] = src[oldIndex++];
22722
+ newIndex += alpha01;
22723
+ }
22724
+ }
22725
+ }
22726
+ function isDefaultDecodeHelper(decode, expectedLen) {
22727
+ if (!Array.isArray(decode)) {
22728
+ return true;
22729
+ }
22730
+ const decodeLen = decode.length;
22731
+ if (decodeLen < expectedLen) {
22732
+ warn2("Decode map length is too short.");
22733
+ return true;
22734
+ }
22735
+ if (decodeLen > expectedLen) {
22736
+ info("Truncating too long decode map.");
22737
+ decode.length = expectedLen;
22738
+ }
22739
+ return false;
22740
+ }
22741
+ var ColorSpace = class _ColorSpace {
22742
+ static #rgbBuf = new Uint8ClampedArray(3);
22743
+ constructor(name, numComps) {
22744
+ if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _ColorSpace) {
22745
+ unreachable2("Cannot initialize ColorSpace.");
22746
+ }
22747
+ this.name = name;
22748
+ this.numComps = numComps;
22749
+ }
22750
+ /**
22751
+ * Converts the color value to the RGB color. The color components are
22752
+ * located in the src array starting from the srcOffset. Returns the array
22753
+ * of the rgb components, each value ranging from [0,255].
22754
+ */
22755
+ getRgb(src, srcOffset, output = new Uint8ClampedArray(3)) {
22756
+ this.getRgbItem(src, srcOffset, output, 0);
22757
+ return output;
22758
+ }
22759
+ getRgbHex(src, srcOffset) {
22760
+ const buffer = this.getRgb(src, srcOffset, _ColorSpace.#rgbBuf);
22761
+ return Util.makeHexColor(buffer[0], buffer[1], buffer[2]);
22762
+ }
22763
+ /**
22764
+ * Converts the color value to the RGB color, similar to the getRgb method.
22765
+ * The result placed into the dest array starting from the destOffset.
22766
+ */
22767
+ getRgbItem(src, srcOffset, dest, destOffset) {
22768
+ unreachable2("Should not call ColorSpace.getRgbItem");
22769
+ }
22770
+ /**
22771
+ * Converts the specified number of the color values to the RGB colors.
22772
+ * The colors are located in the src array starting from the srcOffset.
22773
+ * The result is placed into the dest array starting from the destOffset.
22774
+ * The src array items shall be in [0,2^bits) range, the dest array items
22775
+ * will be in [0,255] range. alpha01 indicates how many alpha components
22776
+ * there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
22777
+ * array).
22778
+ */
22779
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
22780
+ unreachable2("Should not call ColorSpace.getRgbBuffer");
22781
+ }
22782
+ /**
22783
+ * Converts `count` unscaled colors to RGB, starting at `destOffset`.
22784
+ * Components use the native color-space ranges expected by `getRgbItem`,
22785
+ * and each output has a `3 + alpha01` byte stride.
22786
+ * Subclasses may override this to batch expensive conversions.
22787
+ */
22788
+ getRgbItems(src, count, dest, destOffset, alpha01) {
22789
+ const { numComps } = this;
22790
+ for (let i = 0, srcOffset = 0; i < count; i++, srcOffset += numComps) {
22791
+ this.getRgbItem(src, srcOffset, dest, destOffset);
22792
+ destOffset += 3 + alpha01;
22793
+ }
22794
+ }
22795
+ /**
22796
+ * Returns true if source data will be equal the result/output data.
22797
+ */
22798
+ isPassthrough(bits) {
22799
+ return false;
22800
+ }
22801
+ /**
22802
+ * Refer to the static `ColorSpace.isDefaultDecode` method below.
22803
+ */
22804
+ isDefaultDecode(decode, bpc) {
22805
+ return _ColorSpace.isDefaultDecode(decode, this.numComps);
22806
+ }
22807
+ /**
22808
+ * Fills in the RGB colors in the destination buffer. alpha01 indicates
22809
+ * how many alpha components there are in the dest array; it will be either
22810
+ * 0 (RGB array) or 1 (RGBA array).
22811
+ */
22812
+ fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {
22813
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22814
+ assert2(
22815
+ dest instanceof Uint8ClampedArray,
22816
+ 'ColorSpace.fillRgb: Unsupported "dest" type.'
22817
+ );
22818
+ }
22819
+ const count = originalWidth * originalHeight;
22820
+ let rgbBuf = null;
22821
+ const numComponentColors = 1 << bpc;
22822
+ const needsResizing = originalHeight !== height || originalWidth !== width;
22823
+ if (this.isPassthrough(bpc)) {
22824
+ rgbBuf = comps;
22825
+ } else if (this.numComps === 1 && count > numComponentColors && this.name !== "DeviceGray" && this.name !== "DeviceRGB") {
22826
+ const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);
22827
+ for (let i = 0; i < numComponentColors; i++) {
22828
+ allColors[i] = i;
22829
+ }
22830
+ const colorMap = new Uint8ClampedArray(numComponentColors * 3);
22831
+ this.getRgbBuffer(
22832
+ allColors,
22833
+ 0,
22834
+ numComponentColors,
22835
+ colorMap,
22836
+ 0,
22837
+ bpc,
22838
+ /* alpha01 = */
22839
+ 0
22840
+ );
22841
+ if (!needsResizing) {
22842
+ let destPos = 0;
22843
+ for (let i = 0; i < count; ++i) {
22844
+ const key = comps[i] * 3;
22845
+ dest[destPos++] = colorMap[key];
22846
+ dest[destPos++] = colorMap[key + 1];
22847
+ dest[destPos++] = colorMap[key + 2];
22848
+ destPos += alpha01;
22849
+ }
22850
+ } else {
22851
+ rgbBuf = new Uint8Array(count * 3);
22852
+ let rgbPos = 0;
22853
+ for (let i = 0; i < count; ++i) {
22854
+ const key = comps[i] * 3;
22855
+ rgbBuf[rgbPos++] = colorMap[key];
22856
+ rgbBuf[rgbPos++] = colorMap[key + 1];
22857
+ rgbBuf[rgbPos++] = colorMap[key + 2];
22858
+ }
22859
+ }
22860
+ } else if (!needsResizing) {
22861
+ this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);
22862
+ } else {
22863
+ rgbBuf = new Uint8ClampedArray(count * 3);
22864
+ this.getRgbBuffer(
22865
+ comps,
22866
+ 0,
22867
+ count,
22868
+ rgbBuf,
22869
+ 0,
22870
+ bpc,
22871
+ /* alpha01 = */
22872
+ 0
22873
+ );
22874
+ }
22875
+ if (rgbBuf) {
22876
+ if (needsResizing) {
22877
+ resizeRgbImage(
22878
+ rgbBuf,
22879
+ dest,
22880
+ originalWidth,
22881
+ originalHeight,
22882
+ width,
22883
+ height,
22884
+ alpha01
22885
+ );
22886
+ } else {
22887
+ let destPos = 0, rgbPos = 0;
22888
+ for (let i = 0, ii = width * actualHeight; i < ii; i++) {
22889
+ dest[destPos++] = rgbBuf[rgbPos++];
22890
+ dest[destPos++] = rgbBuf[rgbPos++];
22891
+ dest[destPos++] = rgbBuf[rgbPos++];
22892
+ destPos += alpha01;
22893
+ }
22894
+ }
22895
+ }
22896
+ }
22897
+ /**
22898
+ * True if the colorspace has components in the default range of [0, 1].
22899
+ * This should be true for all colorspaces except for lab color spaces
22900
+ * which are [0,100], [-128, 127], [-128, 127].
22901
+ */
22902
+ get usesZeroToOneRange() {
22903
+ return shadow2(this, "usesZeroToOneRange", true);
22904
+ }
22905
+ /**
22906
+ * Checks if a decode map matches the default decode map for a color space.
22907
+ * This handles the general decode maps where there are two values per
22908
+ * component, e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
22909
+ * This does not handle Lab, Indexed, or Pattern decode maps since they are
22910
+ * slightly different.
22911
+ * @param {Array} decode - Decode map (usually from an image).
22912
+ * @param {number} numComps - Number of components the color space has.
22913
+ */
22914
+ static isDefaultDecode(decode, numComps) {
22915
+ if (isDefaultDecodeHelper(decode, numComps * 2)) {
22916
+ return true;
22917
+ }
22918
+ for (let i = 0, ii = decode.length; i < ii; i += 2) {
22919
+ if (decode[i] !== 0 || decode[i + 1] !== 1) {
22920
+ return false;
22921
+ }
22922
+ }
22923
+ return true;
22924
+ }
22925
+ };
22926
+ var DeviceCmykCS = class extends ColorSpace {
22927
+ constructor() {
22928
+ super("DeviceCMYK", 4);
22929
+ }
22930
+ // The coefficients below was found using numerical analysis: the method of
22931
+ // steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
22932
+ // where color_value is the tabular value from the table of sampled RGB colors
22933
+ // from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
22934
+ // CMYK color conversion using the estimation below:
22935
+ // f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
22936
+ #toRgb(src, srcOffset, srcScale, dest, destOffset) {
22937
+ const c = src[srcOffset] * srcScale;
22938
+ const m = src[srcOffset + 1] * srcScale;
22939
+ const y = src[srcOffset + 2] * srcScale;
22940
+ const k = src[srcOffset + 3] * srcScale;
22941
+ 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);
22942
+ 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);
22943
+ 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);
22944
+ }
22945
+ getRgbItem(src, srcOffset, dest, destOffset) {
22946
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22947
+ assert2(
22948
+ dest instanceof Uint8ClampedArray,
22949
+ 'DeviceCmykCS.getRgbItem: Unsupported "dest" type.'
22950
+ );
22951
+ }
22952
+ this.#toRgb(src, srcOffset, 1, dest, destOffset);
22953
+ }
22954
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
22955
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22956
+ assert2(
22957
+ dest instanceof Uint8ClampedArray,
22958
+ 'DeviceCmykCS.getRgbBuffer: Unsupported "dest" type.'
22959
+ );
22960
+ }
22961
+ const scale = 1 / ((1 << bits) - 1);
22962
+ for (let i = 0; i < count; i++) {
22963
+ this.#toRgb(src, srcOffset, scale, dest, destOffset);
22964
+ srcOffset += 4;
22965
+ destOffset += 3 + alpha01;
22966
+ }
22967
+ }
22968
+ };
22969
+ var CalGrayCS = class extends ColorSpace {
22970
+ constructor(whitePoint, blackPoint, gamma) {
22971
+ super("CalGray", 1);
22972
+ if (!whitePoint) {
22973
+ throw new FormatError(
22974
+ "WhitePoint missing - required for color space CalGray"
22975
+ );
22976
+ }
22977
+ [this.XW, this.YW, this.ZW] = whitePoint;
22978
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
22979
+ this.G = gamma || 1;
22980
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
22981
+ throw new FormatError(
22982
+ `Invalid WhitePoint components for ${this.name}, no fallback available`
22983
+ );
22984
+ }
22985
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
22986
+ info(`Invalid BlackPoint for ${this.name}, falling back to default.`);
22987
+ this.XB = this.YB = this.ZB = 0;
22988
+ }
22989
+ if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
22990
+ warn2(
22991
+ `${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ZB: ${this.ZB}, only default values are supported.`
22992
+ );
22993
+ }
22994
+ if (this.G < 1) {
22995
+ info(
22996
+ `Invalid Gamma: ${this.G} for ${this.name}, falling back to default.`
22997
+ );
22998
+ this.G = 1;
22999
+ }
23000
+ }
23001
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
23002
+ const A = src[srcOffset] * scale;
23003
+ const AG = A ** this.G;
23004
+ const L = this.YW * AG;
23005
+ const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0);
23006
+ dest[destOffset] = val;
23007
+ dest[destOffset + 1] = val;
23008
+ dest[destOffset + 2] = val;
23009
+ }
23010
+ getRgbItem(src, srcOffset, dest, destOffset) {
23011
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23012
+ assert2(
23013
+ dest instanceof Uint8ClampedArray,
23014
+ 'CalGrayCS.getRgbItem: Unsupported "dest" type.'
23015
+ );
23016
+ }
23017
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
23018
+ }
23019
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
23020
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23021
+ assert2(
23022
+ dest instanceof Uint8ClampedArray,
23023
+ 'CalGrayCS.getRgbBuffer: Unsupported "dest" type.'
23024
+ );
23025
+ }
23026
+ const scale = 1 / ((1 << bits) - 1);
23027
+ for (let i = 0; i < count; ++i) {
23028
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
23029
+ srcOffset += 1;
23030
+ destOffset += 3 + alpha01;
23031
+ }
23032
+ }
23033
+ };
23034
+ var CalRGBCS = class _CalRGBCS extends ColorSpace {
23035
+ // See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these
23036
+ // matrices.
23037
+ // prettier-ignore
23038
+ static #BRADFORD_SCALE_MATRIX = new Float32Array([
23039
+ 0.8951,
23040
+ 0.2664,
23041
+ -0.1614,
23042
+ -0.7502,
23043
+ 1.7135,
23044
+ 0.0367,
23045
+ 0.0389,
23046
+ -0.0685,
23047
+ 1.0296
23048
+ ]);
23049
+ // prettier-ignore
23050
+ static #BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([
23051
+ 0.9869929,
23052
+ -0.1470543,
23053
+ 0.1599627,
23054
+ 0.4323053,
23055
+ 0.5183603,
23056
+ 0.0492912,
23057
+ -85287e-7,
23058
+ 0.0400428,
23059
+ 0.9684867
23060
+ ]);
23061
+ // See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html.
23062
+ // prettier-ignore
23063
+ static #SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([
23064
+ 3.2404542,
23065
+ -1.5371385,
23066
+ -0.4985314,
23067
+ -0.969266,
23068
+ 1.8760108,
23069
+ 0.041556,
23070
+ 0.0556434,
23071
+ -0.2040259,
23072
+ 1.0572252
23073
+ ]);
23074
+ static #FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);
23075
+ static #tempNormalizeMatrix = new Float32Array(3);
23076
+ static #tempConvertMatrix1 = new Float32Array(3);
23077
+ static #tempConvertMatrix2 = new Float32Array(3);
23078
+ static #DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8;
23079
+ constructor(whitePoint, blackPoint, gamma, matrix) {
23080
+ super("CalRGB", 3);
23081
+ if (!whitePoint) {
23082
+ throw new FormatError(
23083
+ "WhitePoint missing - required for color space CalRGB"
23084
+ );
23085
+ }
23086
+ const [XW, YW, ZW] = this.whitePoint = whitePoint;
23087
+ const [XB, YB, ZB] = this.blackPoint = blackPoint || new Float32Array(3);
23088
+ [this.GR, this.GG, this.GB] = gamma || new Float32Array([1, 1, 1]);
23089
+ [
23090
+ this.MXA,
23091
+ this.MYA,
23092
+ this.MZA,
23093
+ this.MXB,
23094
+ this.MYB,
23095
+ this.MZB,
23096
+ this.MXC,
23097
+ this.MYC,
23098
+ this.MZC
23099
+ ] = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
23100
+ if (XW < 0 || ZW < 0 || YW !== 1) {
23101
+ throw new FormatError(
23102
+ `Invalid WhitePoint components for ${this.name}, no fallback available`
23103
+ );
23104
+ }
23105
+ if (XB < 0 || YB < 0 || ZB < 0) {
23106
+ info(
23107
+ `Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], falling back to default.`
23108
+ );
23109
+ this.blackPoint = new Float32Array(3);
23110
+ }
23111
+ if (this.GR < 0 || this.GG < 0 || this.GB < 0) {
23112
+ info(
23113
+ `Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ${this.name}, falling back to default.`
23114
+ );
23115
+ this.GR = this.GG = this.GB = 1;
23116
+ }
23117
+ }
23118
+ #matrixProduct(a, b, result) {
23119
+ result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
23120
+ result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
23121
+ result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
23122
+ }
23123
+ #toFlat(sourceWhitePoint, LMS, result) {
23124
+ result[0] = LMS[0] * 1 / sourceWhitePoint[0];
23125
+ result[1] = LMS[1] * 1 / sourceWhitePoint[1];
23126
+ result[2] = LMS[2] * 1 / sourceWhitePoint[2];
23127
+ }
23128
+ #toD65(sourceWhitePoint, LMS, result) {
23129
+ const D65X = 0.95047;
23130
+ const D65Y = 1;
23131
+ const D65Z = 1.08883;
23132
+ result[0] = LMS[0] * D65X / sourceWhitePoint[0];
23133
+ result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
23134
+ result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
23135
+ }
23136
+ #sRGBTransferFunction(color) {
23137
+ if (color <= 31308e-7) {
23138
+ return MathClamp(12.92 * color, 0, 1);
23139
+ }
23140
+ return color >= 0.99554525 ? 1 : MathClamp((1 + 0.055) * color ** (1 / 2.4) - 0.055, 0, 1);
23141
+ }
23142
+ #decodeL(L) {
23143
+ if (L < 0) {
23144
+ return -this.#decodeL(-L);
23145
+ }
23146
+ return L > 8 ? ((L + 16) / 116) ** 3 : L * _CalRGBCS.#DECODE_L_CONSTANT;
23147
+ }
23148
+ #compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
23149
+ if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {
23150
+ result[0] = XYZ_Flat[0];
23151
+ result[1] = XYZ_Flat[1];
23152
+ result[2] = XYZ_Flat[2];
23153
+ return;
23154
+ }
23155
+ const zeroDecodeL = this.#decodeL(0);
23156
+ const X_DST = zeroDecodeL;
23157
+ const X_SRC = this.#decodeL(sourceBlackPoint[0]);
23158
+ const Y_DST = zeroDecodeL;
23159
+ const Y_SRC = this.#decodeL(sourceBlackPoint[1]);
23160
+ const Z_DST = zeroDecodeL;
23161
+ const Z_SRC = this.#decodeL(sourceBlackPoint[2]);
23162
+ const X_Scale = (1 - X_DST) / (1 - X_SRC);
23163
+ const X_Offset = 1 - X_Scale;
23164
+ const Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
23165
+ const Y_Offset = 1 - Y_Scale;
23166
+ const Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
23167
+ const Z_Offset = 1 - Z_Scale;
23168
+ result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
23169
+ result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
23170
+ result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
23171
+ }
23172
+ #normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
23173
+ if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
23174
+ result[0] = XYZ_In[0];
23175
+ result[1] = XYZ_In[1];
23176
+ result[2] = XYZ_In[2];
23177
+ return;
23178
+ }
23179
+ const LMS = result;
23180
+ this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
23181
+ const LMS_Flat = _CalRGBCS.#tempNormalizeMatrix;
23182
+ this.#toFlat(sourceWhitePoint, LMS, LMS_Flat);
23183
+ this.#matrixProduct(
23184
+ _CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
23185
+ LMS_Flat,
23186
+ result
23187
+ );
23188
+ }
23189
+ #normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
23190
+ const LMS = result;
23191
+ this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
23192
+ const LMS_D65 = _CalRGBCS.#tempNormalizeMatrix;
23193
+ this.#toD65(sourceWhitePoint, LMS, LMS_D65);
23194
+ this.#matrixProduct(
23195
+ _CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
23196
+ LMS_D65,
23197
+ result
23198
+ );
23199
+ }
23200
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
23201
+ const A = MathClamp(src[srcOffset] * scale, 0, 1);
23202
+ const B = MathClamp(src[srcOffset + 1] * scale, 0, 1);
23203
+ const C = MathClamp(src[srcOffset + 2] * scale, 0, 1);
23204
+ const AGR = A === 1 ? 1 : A ** this.GR;
23205
+ const BGG = B === 1 ? 1 : B ** this.GG;
23206
+ const CGB = C === 1 ? 1 : C ** this.GB;
23207
+ const X = this.MXA * AGR + this.MXB * BGG + this.MXC * CGB;
23208
+ const Y = this.MYA * AGR + this.MYB * BGG + this.MYC * CGB;
23209
+ const Z = this.MZA * AGR + this.MZB * BGG + this.MZC * CGB;
23210
+ const XYZ = _CalRGBCS.#tempConvertMatrix1;
23211
+ XYZ[0] = X;
23212
+ XYZ[1] = Y;
23213
+ XYZ[2] = Z;
23214
+ const XYZ_Flat = _CalRGBCS.#tempConvertMatrix2;
23215
+ this.#normalizeWhitePointToFlat(this.whitePoint, XYZ, XYZ_Flat);
23216
+ const XYZ_Black = _CalRGBCS.#tempConvertMatrix1;
23217
+ this.#compensateBlackPoint(this.blackPoint, XYZ_Flat, XYZ_Black);
23218
+ const XYZ_D65 = _CalRGBCS.#tempConvertMatrix2;
23219
+ this.#normalizeWhitePointToD65(
23220
+ _CalRGBCS.#FLAT_WHITEPOINT_MATRIX,
23221
+ XYZ_Black,
23222
+ XYZ_D65
23223
+ );
23224
+ const SRGB = _CalRGBCS.#tempConvertMatrix1;
23225
+ this.#matrixProduct(_CalRGBCS.#SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
23226
+ dest[destOffset] = this.#sRGBTransferFunction(SRGB[0]) * 255;
23227
+ dest[destOffset + 1] = this.#sRGBTransferFunction(SRGB[1]) * 255;
23228
+ dest[destOffset + 2] = this.#sRGBTransferFunction(SRGB[2]) * 255;
23229
+ }
23230
+ getRgbItem(src, srcOffset, dest, destOffset) {
23231
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23232
+ assert2(
23233
+ dest instanceof Uint8ClampedArray,
23234
+ 'CalRGBCS.getRgbItem: Unsupported "dest" type.'
23235
+ );
23236
+ }
23237
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
23238
+ }
23239
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
23240
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23241
+ assert2(
23242
+ dest instanceof Uint8ClampedArray,
23243
+ 'CalRGBCS.getRgbBuffer: Unsupported "dest" type.'
23244
+ );
23245
+ }
23246
+ const scale = 1 / ((1 << bits) - 1);
23247
+ for (let i = 0; i < count; ++i) {
23248
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
23249
+ srcOffset += 3;
23250
+ destOffset += 3 + alpha01;
23251
+ }
23252
+ }
23253
+ };
23254
+ var LabCS = class extends ColorSpace {
23255
+ constructor(whitePoint, blackPoint, range) {
23256
+ super("Lab", 3);
23257
+ if (!whitePoint) {
23258
+ throw new FormatError(
23259
+ "WhitePoint missing - required for color space Lab"
23260
+ );
23261
+ }
23262
+ [this.XW, this.YW, this.ZW] = whitePoint;
23263
+ [this.amin, this.amax, this.bmin, this.bmax] = range || [
23264
+ -100,
23265
+ 100,
23266
+ -100,
23267
+ 100
23268
+ ];
23269
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
23270
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
23271
+ throw new FormatError(
23272
+ "Invalid WhitePoint components, no fallback available"
23273
+ );
23274
+ }
23275
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
23276
+ info("Invalid BlackPoint, falling back to default");
23277
+ this.XB = this.YB = this.ZB = 0;
23278
+ }
23279
+ if (this.amin > this.amax || this.bmin > this.bmax) {
23280
+ info("Invalid Range, falling back to defaults");
23281
+ this.amin = -100;
23282
+ this.amax = 100;
23283
+ this.bmin = -100;
23284
+ this.bmax = 100;
23285
+ }
23286
+ }
23287
+ // Function g(x) from spec
23288
+ #fn_g(x) {
23289
+ return x >= 6 / 29 ? x ** 3 : 108 / 841 * (x - 4 / 29);
23290
+ }
23291
+ #decode(value, high1, low2, high2) {
23292
+ return low2 + value * (high2 - low2) / high1;
23293
+ }
23294
+ // If decoding is needed maxVal should be 2^bits per component - 1.
23295
+ #toRgb(src, srcOffset, maxVal, dest, destOffset) {
23296
+ let Ls = src[srcOffset];
23297
+ let as = src[srcOffset + 1];
23298
+ let bs = src[srcOffset + 2];
23299
+ if (maxVal !== false) {
23300
+ Ls = this.#decode(Ls, maxVal, 0, 100);
23301
+ as = this.#decode(as, maxVal, this.amin, this.amax);
23302
+ bs = this.#decode(bs, maxVal, this.bmin, this.bmax);
23303
+ }
23304
+ if (as > this.amax) {
23305
+ as = this.amax;
23306
+ } else if (as < this.amin) {
23307
+ as = this.amin;
23308
+ }
23309
+ if (bs > this.bmax) {
23310
+ bs = this.bmax;
23311
+ } else if (bs < this.bmin) {
23312
+ bs = this.bmin;
23313
+ }
23314
+ const M = (Ls + 16) / 116;
23315
+ const L = M + as / 500;
23316
+ const N = M - bs / 200;
23317
+ const X = this.XW * this.#fn_g(L);
23318
+ const Y = this.YW * this.#fn_g(M);
23319
+ const Z = this.ZW * this.#fn_g(N);
23320
+ let r, g, b;
23321
+ if (this.ZW < 1) {
23322
+ r = X * 3.1339 + Y * -1.617 + Z * -0.4906;
23323
+ g = X * -0.9785 + Y * 1.916 + Z * 0.0333;
23324
+ b = X * 0.072 + Y * -0.229 + Z * 1.4057;
23325
+ } else {
23326
+ r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
23327
+ g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
23328
+ b = X * 0.0557 + Y * -0.204 + Z * 1.057;
23329
+ }
23330
+ dest[destOffset] = Math.sqrt(r) * 255;
23331
+ dest[destOffset + 1] = Math.sqrt(g) * 255;
23332
+ dest[destOffset + 2] = Math.sqrt(b) * 255;
23333
+ }
23334
+ getRgbItem(src, srcOffset, dest, destOffset) {
23335
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23336
+ assert2(
23337
+ dest instanceof Uint8ClampedArray,
23338
+ 'LabCS.getRgbItem: Unsupported "dest" type.'
23339
+ );
23340
+ }
23341
+ this.#toRgb(src, srcOffset, false, dest, destOffset);
23342
+ }
23343
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
23344
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23345
+ assert2(
23346
+ dest instanceof Uint8ClampedArray,
23347
+ 'LabCS.getRgbBuffer: Unsupported "dest" type.'
23348
+ );
23349
+ }
23350
+ const maxVal = (1 << bits) - 1;
23351
+ for (let i = 0; i < count; i++) {
23352
+ this.#toRgb(src, srcOffset, maxVal, dest, destOffset);
23353
+ srcOffset += 3;
23354
+ destOffset += 3 + alpha01;
23355
+ }
23356
+ }
23357
+ isDefaultDecode(decode, bpc) {
23358
+ return true;
23359
+ }
23360
+ get usesZeroToOneRange() {
23361
+ return shadow2(this, "usesZeroToOneRange", false);
23362
+ }
23363
+ };
23364
+ var TOKEN = {
23365
+ // Structural tokens — not keyword operators
23366
+ number: 0,
23367
+ lbrace: 1,
23368
+ rbrace: 2,
23369
+ // Boolean literals
23370
+ true: 3,
23371
+ false: 4,
23372
+ // Arithmetic binary operators
23373
+ add: 5,
23374
+ sub: 6,
23375
+ mul: 7,
23376
+ div: 8,
23377
+ idiv: 9,
23378
+ mod: 10,
23379
+ exp: 11,
23380
+ // Comparison binary operators
23381
+ eq: 12,
23382
+ ne: 13,
23383
+ gt: 14,
23384
+ ge: 15,
23385
+ lt: 16,
23386
+ le: 17,
23387
+ // Bitwise / boolean binary operators
23388
+ and: 18,
23389
+ or: 19,
23390
+ xor: 20,
23391
+ bitshift: 21,
23392
+ // Unary arithmetic operators
23393
+ abs: 22,
23394
+ neg: 23,
23395
+ ceiling: 24,
23396
+ floor: 25,
23397
+ round: 26,
23398
+ truncate: 27,
23399
+ // Unary boolean / bitwise operator
23400
+ not: 28,
23401
+ // Mathematical functions — unary
23402
+ sqrt: 29,
23403
+ sin: 30,
23404
+ cos: 31,
23405
+ ln: 32,
23406
+ log: 33,
23407
+ // Mathematical function — binary
23408
+ atan: 34,
23409
+ // Type conversion operators
23410
+ cvi: 35,
23411
+ cvr: 36,
23412
+ // Stack operators
23413
+ dup: 37,
23414
+ exch: 38,
23415
+ pop: 39,
23416
+ copy: 40,
23417
+ index: 41,
23418
+ roll: 42,
23419
+ // Control flow
23420
+ if: 43,
23421
+ ifelse: 44,
23422
+ // End of input
23423
+ eof: 45,
23424
+ // Synthetic: produced by the optimizer, never emitted by the lexer.
23425
+ min: 46,
23426
+ max: 47
23427
+ };
23428
+ var Token = class {
23429
+ constructor(id, value = null) {
23430
+ this.id = id;
23431
+ this.value = value;
23432
+ }
23433
+ };
23434
+ var Lexer = class _Lexer {
23435
+ // Singletons for every non-number token, built lazily on first construction.
23436
+ // Keyword operator tokens carry their name as `value`; structural tokens
23437
+ // (lbrace, rbrace, eof) carry null.
23438
+ static #singletons = null;
23439
+ static #operatorSingletons = null;
23440
+ static #initSingletons() {
23441
+ const singletons = /* @__PURE__ */ Object.create(null);
23442
+ const operatorSingletons = /* @__PURE__ */ Object.create(null);
23443
+ for (const [name, id] of Object.entries(TOKEN)) {
23444
+ if (name === "number") {
23445
+ continue;
23446
+ }
23447
+ const isOperator = id >= TOKEN.true && id <= TOKEN.ifelse;
23448
+ const token = new Token(id, isOperator ? name : null);
23449
+ singletons[name] = token;
23450
+ if (isOperator) {
23451
+ operatorSingletons[name] = token;
23452
+ }
23453
+ }
23454
+ this.#singletons = singletons;
23455
+ this.#operatorSingletons = operatorSingletons;
23456
+ }
23457
+ constructor(data) {
23458
+ if (!_Lexer.#singletons) {
23459
+ _Lexer.#initSingletons();
23460
+ }
23461
+ this.data = data;
23462
+ this.pos = 0;
23463
+ this.len = data.length;
23464
+ this._numberPattern = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/iy;
23465
+ this._identifierPattern = /[a-z]+/y;
23466
+ }
23467
+ // Skip a % comment, advancing past the next \n or \r (or to EOF).
23468
+ _skipComment() {
23469
+ const lf = this.data.indexOf("\n", this.pos);
23470
+ const cr = this.data.indexOf("\r", this.pos);
23471
+ const eol = Math.min(lf < 0 ? this.len : lf, cr < 0 ? this.len : cr);
23472
+ this.pos = Math.min(eol + 1, this.len);
23473
+ }
23474
+ _getNumber() {
23475
+ this._numberPattern.lastIndex = this.pos;
23476
+ const match = this._numberPattern.exec(this.data);
23477
+ if (!match) {
23478
+ return new Token(TOKEN.number, 0);
23479
+ }
23480
+ const number = parseFloat(match[0]);
23481
+ if (!Number.isFinite(number)) {
23482
+ return new Token(TOKEN.number, 0);
23483
+ }
23484
+ this.pos = this._numberPattern.lastIndex;
23485
+ return new Token(TOKEN.number, number);
23486
+ }
23487
+ _getOperator() {
23488
+ this._identifierPattern.lastIndex = this.pos;
23489
+ const match = this._identifierPattern.exec(this.data);
23490
+ if (!match) {
23491
+ return new Token(TOKEN.number, 0);
23492
+ }
23493
+ this.pos = this._identifierPattern.lastIndex;
23494
+ const op = match[0];
23495
+ const token = _Lexer.#operatorSingletons[op];
23496
+ return token ?? new Token(TOKEN.number, 0);
23497
+ }
23498
+ // Return the next token, or Lexer.#singletons.eof at end of input.
23499
+ next() {
23500
+ while (this.pos < this.len) {
23501
+ const ch3 = this.data.charCodeAt(this.pos++);
23502
+ switch (ch3) {
23503
+ // PostScript white-space characters (PDF32000 §7.2.2)
23504
+ case 0:
23505
+ case 9:
23506
+ case 10:
23507
+ case 12:
23508
+ case 13:
23509
+ case 32:
23510
+ break;
23511
+ case 37:
23512
+ this._skipComment();
23513
+ break;
23514
+ case 123:
23515
+ return _Lexer.#singletons.lbrace;
23516
+ case 125:
23517
+ return _Lexer.#singletons.rbrace;
23518
+ case 43:
23519
+ case 45:
23520
+ this.pos--;
23521
+ return this._getNumber();
23522
+ case 46:
23523
+ this.pos--;
23524
+ return this._getNumber();
23525
+ default:
23526
+ if (ch3 >= 48 && ch3 <= 57) {
23527
+ this.pos--;
23528
+ return this._getNumber();
23529
+ }
23530
+ if (ch3 >= 97 && ch3 <= 122) {
23531
+ this.pos--;
23532
+ return this._getOperator();
23533
+ }
23534
+ return new Token(TOKEN.number, 0);
23535
+ }
23536
+ }
23537
+ return _Lexer.#singletons.eof;
23538
+ }
23539
+ };
23540
+ var PS_VALUE_TYPE = {
23541
+ numeric: 0,
23542
+ // known to be a number (f64 in Wasm)
23543
+ boolean: 1,
23544
+ // known to be a boolean (0.0 = false, 1.0 = true in f64)
23545
+ unknown: 2
23546
+ // indeterminate at compile time
23547
+ };
23548
+ var PS_NODE = {
23549
+ // Parser AST node types (produced by Parser / parsePostScriptFunction)
23550
+ program: 0,
23551
+ block: 1,
23552
+ number: 2,
23553
+ operator: 3,
23554
+ if: 4,
23555
+ ifelse: 5,
23556
+ // Tree AST node types (produced by PSStackToTree)
23557
+ arg: 6,
23558
+ const: 7,
23559
+ unary: 8,
23560
+ binary: 9,
23561
+ ternary: 10
23562
+ };
23563
+ var PsNode = class {
23564
+ constructor(type) {
23565
+ this.type = type;
23566
+ }
23567
+ };
23568
+ var PsProgram = class extends PsNode {
23569
+ constructor(body) {
23570
+ super(PS_NODE.program);
23571
+ this.body = body;
23572
+ }
23573
+ };
23574
+ var PsBlock = class extends PsNode {
23575
+ constructor(instructions) {
23576
+ super(PS_NODE.block);
23577
+ this.instructions = instructions;
23578
+ }
23579
+ };
23580
+ var PsNumber = class extends PsNode {
23581
+ /** @param {number} value */
23582
+ constructor(value) {
23583
+ super(PS_NODE.number);
23584
+ this.value = value;
23585
+ }
23586
+ };
23587
+ var PsOperator = class extends PsNode {
23588
+ /** @param {number} op — one of the TOKEN.* constants from lexer.js */
23589
+ constructor(op) {
23590
+ super(PS_NODE.operator);
23591
+ this.op = op;
23592
+ }
23593
+ };
23594
+ var PsIf = class extends PsNode {
23595
+ /** @param {PsBlock} then */
23596
+ constructor(then) {
23597
+ super(PS_NODE.if);
23598
+ this.then = then;
23599
+ }
23600
+ };
23601
+ var PsIfElse = class extends PsNode {
23602
+ /**
23603
+ * @param {PsBlock} then
23604
+ * @param {PsBlock} otherwise
23605
+ */
23606
+ constructor(then, otherwise) {
23607
+ super(PS_NODE.ifelse);
23608
+ this.then = then;
23609
+ this.otherwise = otherwise;
23610
+ }
23611
+ };
23612
+ var PsArgNode = class extends PsNode {
23613
+ /** @param {number} index */
23614
+ constructor(index) {
23615
+ super(PS_NODE.arg);
23616
+ this.index = index;
23617
+ this.valueType = PS_VALUE_TYPE.numeric;
23618
+ }
23619
+ };
23620
+ var PsConstNode = class extends PsNode {
23621
+ /** @param {number|boolean} value */
23622
+ constructor(value) {
23623
+ super(PS_NODE.const);
23624
+ this.value = value;
23625
+ this.valueType = typeof value === "boolean" ? PS_VALUE_TYPE.boolean : PS_VALUE_TYPE.numeric;
23626
+ }
23627
+ };
23628
+ var PsUnaryNode = class extends PsNode {
23629
+ /**
23630
+ * @param {number} op — TOKEN.* constant
23631
+ * @param {PsNode} operand
23632
+ * @param {number} [valueType]
23633
+ */
23634
+ constructor(op, operand, valueType = PS_VALUE_TYPE.unknown) {
23635
+ super(PS_NODE.unary);
23636
+ this.op = op;
23637
+ this.operand = operand;
23638
+ this.valueType = valueType;
23639
+ }
23640
+ };
23641
+ var PsBinaryNode = class extends PsNode {
23642
+ /**
23643
+ * @param {number} op — TOKEN.* constant
23644
+ * @param {PsNode} first — was on top of stack
23645
+ * @param {PsNode} second — was below top
23646
+ * @param {number} [valueType]
23647
+ */
23648
+ constructor(op, first, second, valueType = PS_VALUE_TYPE.unknown) {
23649
+ super(PS_NODE.binary);
23650
+ this.op = op;
23651
+ this.first = first;
23652
+ this.second = second;
23653
+ this.valueType = valueType;
23654
+ }
23655
+ };
23656
+ var PsTernaryNode = class extends PsNode {
23657
+ /**
23658
+ * @param {PsNode} cond
23659
+ * @param {PsNode} then
23660
+ * @param {PsNode} otherwise
23661
+ * @param {number} [valueType]
23662
+ */
23663
+ constructor(cond, then, otherwise, valueType = PS_VALUE_TYPE.unknown) {
23664
+ super(PS_NODE.ternary);
23665
+ this.cond = cond;
23666
+ this.then = then;
23667
+ this.otherwise = otherwise;
23668
+ this.valueType = valueType;
23669
+ }
23670
+ };
23671
+ var Parser = class _Parser {
23672
+ constructor(lexer) {
23673
+ this.lexer = lexer;
23674
+ this._token = null;
23675
+ }
23676
+ static _isRegularOperator(id) {
23677
+ return id >= TOKEN.true && id < TOKEN.if;
23678
+ }
23679
+ // Fetch the next token from the lexer.
23680
+ _advance() {
23681
+ this._token = this.lexer.next();
23682
+ }
23683
+ // Assert that the current token has the given id, consume it, and return it.
23684
+ _expect(id) {
23685
+ if (this._token.id !== id) {
23686
+ throw new FormatError(
23687
+ `PostScript function: expected token id ${id}, got ${this._token.id}.`
23688
+ );
23689
+ }
23690
+ const tok = this._token;
23691
+ this._advance();
23692
+ return tok;
23693
+ }
23694
+ /**
23695
+ * Parse the full Type 4 function body.
23696
+ *
23697
+ * Grammar (simplified):
23698
+ * program ::= '{' block '}'
23699
+ * block ::= instruction*
23700
+ * instruction ::= number
23701
+ * | operator (any PS_OPERATOR except if / ifelse)
23702
+ * | '{' block '}' 'if'
23703
+ * | '{' block '}' '{' block '}' 'ifelse'
23704
+ * @returns {PsProgram}
23705
+ */
23706
+ parse() {
23707
+ this._advance();
23708
+ this._expect(TOKEN.lbrace);
23709
+ const block = this._parseBlock();
23710
+ this._expect(TOKEN.rbrace);
23711
+ if (this._token.id !== TOKEN.eof) {
23712
+ warn2("PostScript function: unexpected content after closing brace.");
23713
+ }
23714
+ return new PsProgram(block);
23715
+ }
23716
+ _parseBlock() {
23717
+ const instructions = [];
23718
+ while (true) {
23719
+ const tok = this._token;
23720
+ switch (tok.id) {
23721
+ case TOKEN.number:
23722
+ instructions.push(new PsNumber(tok.value));
23723
+ this._advance();
23724
+ break;
23725
+ case TOKEN.lbrace: {
23726
+ this._advance();
23727
+ const thenBlock = this._parseBlock();
23728
+ this._expect(TOKEN.rbrace);
23729
+ if (this._token.id === TOKEN.if) {
23730
+ this._advance();
23731
+ instructions.push(new PsIf(thenBlock));
23732
+ } else if (this._token.id === TOKEN.lbrace) {
23733
+ this._advance();
23734
+ const elseBlock = this._parseBlock();
23735
+ this._expect(TOKEN.rbrace);
23736
+ this._expect(TOKEN.ifelse);
23737
+ instructions.push(new PsIfElse(thenBlock, elseBlock));
23738
+ } else {
23739
+ throw new FormatError(
23740
+ "PostScript function: a procedure block must be followed by 'if' or '{\u2026} ifelse'."
23741
+ );
23742
+ }
23743
+ break;
23744
+ }
23745
+ case TOKEN.rbrace:
23746
+ case TOKEN.eof:
23747
+ return new PsBlock(instructions);
23748
+ case TOKEN.if:
23749
+ case TOKEN.ifelse:
23750
+ throw new FormatError(
23751
+ `PostScript function: unexpected '${tok.value}' operator.`
23752
+ );
23753
+ default:
23754
+ if (_Parser._isRegularOperator(tok.id)) {
23755
+ instructions.push(new PsOperator(tok.id));
23756
+ this._advance();
23757
+ break;
23758
+ }
23759
+ throw new FormatError(
23760
+ `PostScript function: unexpected token id ${tok.id}.`
23761
+ );
23762
+ }
23763
+ }
23764
+ }
23765
+ };
23766
+ function parsePostScriptFunction(source) {
23767
+ return new Parser(new Lexer(source)).parse();
23768
+ }
23769
+ function _nodesEqual(a, b) {
23770
+ if (a === b) {
23771
+ return true;
23772
+ }
23773
+ if (a.type !== b.type) {
23774
+ return false;
23775
+ }
23776
+ switch (a.type) {
23777
+ case PS_NODE.arg:
23778
+ return a.index === b.index;
23779
+ case PS_NODE.const:
23780
+ return a.value === b.value;
23781
+ case PS_NODE.unary:
23782
+ return a.op === b.op && _nodesEqual(a.operand, b.operand);
23783
+ case PS_NODE.binary:
23784
+ return a.op === b.op && _nodesEqual(a.first, b.first) && _nodesEqual(a.second, b.second);
23785
+ case PS_NODE.ternary:
23786
+ return _nodesEqual(a.cond, b.cond) && _nodesEqual(a.then, b.then) && _nodesEqual(a.otherwise, b.otherwise);
23787
+ default:
23788
+ return false;
23789
+ }
23790
+ }
23791
+ function _evalBinaryConst(op, a, b) {
23792
+ switch (op) {
23793
+ case TOKEN.add:
23794
+ return a + b;
23795
+ case TOKEN.sub:
23796
+ return a - b;
23797
+ case TOKEN.mul:
23798
+ return a * b;
23799
+ case TOKEN.div:
23800
+ return b !== 0 ? a / b : 0;
23801
+ // div by zero → 0
23802
+ case TOKEN.idiv:
23803
+ return b !== 0 ? Math.trunc(a / b) : 0;
23804
+ // div by zero → 0
23805
+ case TOKEN.mod:
23806
+ return b !== 0 ? a - Math.trunc(a / b) * b : 0;
23807
+ // div by zero → 0
23808
+ case TOKEN.exp: {
23809
+ const r = a ** b;
23810
+ return Number.isFinite(r) ? r : void 0;
23811
+ }
23812
+ case TOKEN.atan: {
23813
+ let deg = Math.atan2(a, b) * (180 / Math.PI);
23814
+ if (deg < 0) {
23815
+ deg += 360;
23816
+ }
23817
+ return deg;
23818
+ }
23819
+ case TOKEN.eq:
23820
+ return a === b;
23821
+ case TOKEN.ne:
23822
+ return a !== b;
23823
+ case TOKEN.gt:
23824
+ return a > b;
23825
+ case TOKEN.ge:
23826
+ return a >= b;
23827
+ case TOKEN.lt:
23828
+ return a < b;
23829
+ case TOKEN.le:
23830
+ return a <= b;
23831
+ case TOKEN.and:
23832
+ return typeof a === "boolean" ? a && b : a & b | 0;
23833
+ case TOKEN.or:
23834
+ return typeof a === "boolean" ? a || b : a | b | 0;
23835
+ case TOKEN.xor:
23836
+ return typeof a === "boolean" ? a !== b : a ^ b | 0;
23837
+ case TOKEN.bitshift:
23838
+ return b >= 0 ? a << b | 0 : a >> -b | 0;
23839
+ case TOKEN.min:
23840
+ return Math.min(a, b);
23841
+ case TOKEN.max:
23842
+ return Math.max(a, b);
23843
+ default:
23844
+ return void 0;
23845
+ }
23846
+ }
23847
+ function _evalUnaryConst(op, v) {
23848
+ switch (op) {
23849
+ case TOKEN.abs:
23850
+ return Math.abs(v);
23851
+ case TOKEN.neg:
23852
+ return -v;
23853
+ case TOKEN.ceiling:
23854
+ return Math.ceil(v);
23855
+ case TOKEN.floor:
23856
+ return Math.floor(v);
23857
+ case TOKEN.round:
23858
+ return Math.round(v);
23859
+ case TOKEN.truncate:
23860
+ return Math.trunc(v);
23861
+ case TOKEN.sqrt: {
23862
+ const r = Math.sqrt(v);
23863
+ return Number.isFinite(r) ? r : void 0;
23864
+ }
23865
+ case TOKEN.sin:
23866
+ return Math.sin(v % 360 * Math.PI / 180);
23867
+ case TOKEN.cos:
23868
+ return Math.cos(v % 360 * Math.PI / 180);
23869
+ case TOKEN.ln: {
23870
+ const r = Math.log(v);
23871
+ return Number.isFinite(r) ? r : void 0;
23872
+ }
23873
+ case TOKEN.log: {
23874
+ const r = Math.log10(v);
23875
+ return Number.isFinite(r) ? r : void 0;
23876
+ }
23877
+ case TOKEN.cvi:
23878
+ return Math.trunc(v);
23879
+ case TOKEN.cvr:
23880
+ return v;
23881
+ case TOKEN.not:
23882
+ return typeof v === "boolean" ? !v : ~v;
23883
+ default:
23884
+ return void 0;
23885
+ }
23886
+ }
23887
+ var MAX_STACK_SIZE = 100;
23888
+ function _unaryValueType(op, operandType) {
23889
+ return op === TOKEN.not ? operandType : PS_VALUE_TYPE.numeric;
23890
+ }
23891
+ function _binaryValueType(op, firstType, secondType) {
23892
+ switch (op) {
23893
+ // Comparison operators always produce a boolean.
23894
+ case TOKEN.eq:
23895
+ case TOKEN.ne:
23896
+ case TOKEN.gt:
23897
+ case TOKEN.ge:
23898
+ case TOKEN.lt:
23899
+ case TOKEN.le:
23900
+ return PS_VALUE_TYPE.boolean;
23901
+ // and / or / xor preserve the type when both operands are the same known
23902
+ // type (both boolean or both numeric); otherwise the type is unknown.
23903
+ case TOKEN.and:
23904
+ case TOKEN.or:
23905
+ case TOKEN.xor:
23906
+ return firstType === secondType && firstType !== PS_VALUE_TYPE.unknown ? firstType : PS_VALUE_TYPE.unknown;
23907
+ // All arithmetic / bitshift operators produce a numeric result.
23908
+ default:
23909
+ return PS_VALUE_TYPE.numeric;
23910
+ }
23911
+ }
23912
+ var PSStackToTree = class _PSStackToTree {
23913
+ static #binaryOps = null;
23914
+ static #unaryOps = null;
23915
+ static #idempotentUnary = null;
23916
+ static #negatedComparison = null;
23917
+ static #init() {
23918
+ this.#binaryOps = /* @__PURE__ */ new Set([
23919
+ TOKEN.add,
23920
+ TOKEN.sub,
23921
+ TOKEN.mul,
23922
+ TOKEN.div,
23923
+ TOKEN.idiv,
23924
+ TOKEN.mod,
23925
+ TOKEN.exp,
23926
+ TOKEN.atan,
23927
+ TOKEN.eq,
23928
+ TOKEN.ne,
23929
+ TOKEN.gt,
23930
+ TOKEN.ge,
23931
+ TOKEN.lt,
23932
+ TOKEN.le,
23933
+ TOKEN.and,
23934
+ TOKEN.or,
23935
+ TOKEN.xor,
23936
+ TOKEN.bitshift
23937
+ ]);
23938
+ this.#unaryOps = /* @__PURE__ */ new Set([
23939
+ TOKEN.abs,
23940
+ TOKEN.neg,
23941
+ TOKEN.ceiling,
23942
+ TOKEN.floor,
23943
+ TOKEN.round,
23944
+ TOKEN.truncate,
23945
+ TOKEN.sqrt,
23946
+ TOKEN.sin,
23947
+ TOKEN.cos,
23948
+ TOKEN.ln,
23949
+ TOKEN.log,
23950
+ TOKEN.cvi,
23951
+ TOKEN.cvr,
23952
+ TOKEN.not
23953
+ ]);
23954
+ this.#idempotentUnary = /* @__PURE__ */ new Set([
23955
+ TOKEN.abs,
23956
+ TOKEN.ceiling,
23957
+ TOKEN.cvi,
23958
+ TOKEN.cvr,
23959
+ TOKEN.floor,
23960
+ TOKEN.round,
23961
+ TOKEN.truncate
23962
+ ]);
23963
+ this.#negatedComparison = /* @__PURE__ */ new Map([
23964
+ [TOKEN.eq, TOKEN.ne],
23965
+ [TOKEN.ne, TOKEN.eq],
23966
+ [TOKEN.lt, TOKEN.ge],
23967
+ [TOKEN.le, TOKEN.gt],
23968
+ [TOKEN.gt, TOKEN.le],
23969
+ [TOKEN.ge, TOKEN.lt]
23970
+ ]);
23971
+ }
23972
+ /**
23973
+ * @param {PsProgram} program
23974
+ * @param {number} numInputs — number of domain values placed on the stack
23975
+ * before the program runs (i.e. the length of the domain array / 2).
23976
+ * @returns {Array<PsNode>} — one tree node per output value.
23977
+ */
23978
+ evaluate(program, numInputs) {
23979
+ if (!_PSStackToTree.#binaryOps) {
23980
+ _PSStackToTree.#init();
23981
+ }
23982
+ this._failed = false;
23983
+ if (numInputs > MAX_STACK_SIZE) {
23984
+ return null;
23985
+ }
23986
+ const stack = [];
23987
+ for (let i = 0; i < numInputs; i++) {
23988
+ stack.push(new PsArgNode(i));
23989
+ }
23990
+ this._evalBlock(program.body, stack);
23991
+ if (this._failed) {
23992
+ return null;
23993
+ }
23994
+ _PSStackToTree.#markShared(stack);
23995
+ return stack;
23996
+ }
23997
+ // Set node.shared / sharedCount on non-atomic nodes referenced more than
23998
+ // once. arg/const are excluded — they are cheap to re-emit inline.
23999
+ static #markShared(outputs) {
24000
+ const refCount = /* @__PURE__ */ new Map();
24001
+ const visit = (node) => {
24002
+ if (!node || node.type === PS_NODE.arg || node.type === PS_NODE.const) {
24003
+ return;
24004
+ }
24005
+ const prev = refCount.get(node) ?? 0;
24006
+ refCount.set(node, prev + 1);
24007
+ if (prev > 0) {
24008
+ return;
24009
+ }
24010
+ switch (node.type) {
24011
+ case PS_NODE.unary:
24012
+ visit(node.operand);
24013
+ break;
24014
+ case PS_NODE.binary:
24015
+ visit(node.first);
24016
+ visit(node.second);
24017
+ break;
24018
+ case PS_NODE.ternary:
24019
+ visit(node.cond);
24020
+ visit(node.then);
24021
+ visit(node.otherwise);
24022
+ break;
24023
+ }
24024
+ };
24025
+ for (const output of outputs) {
24026
+ visit(output);
24027
+ }
24028
+ for (const [node, count] of refCount) {
24029
+ if (count > 1) {
24030
+ node.shared = true;
24031
+ node.sharedCount = count;
24032
+ }
24033
+ }
24034
+ }
24035
+ _evalBlock(block, stack) {
24036
+ this._evalBlockFrom(block.instructions, 0, stack);
24037
+ }
24038
+ /**
24039
+ * Core evaluation loop. Processes `instructions[startIdx…]` in order,
24040
+ * mutating `stack` as each instruction executes.
24041
+ *
24042
+ * When a `{ body } if` instruction grows the stack (the PostScript "early
24043
+ * exit / guard" idiom), the remaining instructions in the current array are
24044
+ * evaluated on **both** the true-branch stack and the false-branch stack,
24045
+ * then the two results are merged into PsTernaryNodes. This handles
24046
+ * patterns like:
24047
+ *
24048
+ * cond { pop R G B sentinel } if
24049
+ * … more guards …
24050
+ * sentinel 0 gt { defaultR defaultG defaultB } if
24051
+ */
24052
+ _evalBlockFrom(instructions, startIdx, stack) {
24053
+ for (let idx = startIdx; idx < instructions.length; idx++) {
24054
+ if (this._failed) {
24055
+ break;
24056
+ }
24057
+ const instr = instructions[idx];
24058
+ switch (instr.type) {
24059
+ case PS_NODE.number:
24060
+ stack.push(new PsConstNode(instr.value));
24061
+ if (stack.length > MAX_STACK_SIZE) {
24062
+ this._failed = true;
24063
+ }
24064
+ break;
24065
+ case PS_NODE.operator:
24066
+ this._evalOp(instr.op, stack);
24067
+ break;
24068
+ case PS_NODE.if: {
24069
+ if (stack.length < 1) {
24070
+ this._failed = true;
24071
+ break;
24072
+ }
24073
+ const cond = stack.pop();
24074
+ const saved = stack.slice();
24075
+ this._evalBlock(instr.then, stack);
24076
+ if (this._failed) {
24077
+ break;
24078
+ }
24079
+ if (stack.length === saved.length) {
24080
+ for (let i = 0; i < stack.length; i++) {
24081
+ if (stack[i] !== saved[i]) {
24082
+ stack[i] = this._makeTernary(cond, stack[i], saved[i]);
24083
+ }
24084
+ }
24085
+ } else if (stack.length > saved.length) {
24086
+ if (cond.type === PS_NODE.const) {
24087
+ if (!cond.value) {
24088
+ stack.length = 0;
24089
+ stack.push(...saved);
24090
+ }
24091
+ break;
24092
+ }
24093
+ const trueStack = stack.slice();
24094
+ this._evalBlockFrom(instructions, idx + 1, trueStack);
24095
+ if (this._failed) {
24096
+ break;
24097
+ }
24098
+ const falseStack = saved;
24099
+ this._evalBlockFrom(instructions, idx + 1, falseStack);
24100
+ if (this._failed) {
24101
+ break;
24102
+ }
24103
+ if (trueStack.length !== falseStack.length) {
24104
+ const zero2 = new PsConstNode(0);
24105
+ while (trueStack.length < falseStack.length) {
24106
+ trueStack.push(zero2);
24107
+ }
24108
+ while (falseStack.length < trueStack.length) {
24109
+ falseStack.push(zero2);
24110
+ }
24111
+ }
24112
+ stack.length = 0;
24113
+ for (let i = 0; i < trueStack.length; i++) {
24114
+ stack.push(this._makeTernary(cond, trueStack[i], falseStack[i]));
24115
+ }
24116
+ return;
24117
+ } else {
24118
+ this._failed = true;
24119
+ }
24120
+ break;
24121
+ }
24122
+ case PS_NODE.ifelse: {
24123
+ if (stack.length < 1) {
24124
+ this._failed = true;
24125
+ break;
24126
+ }
24127
+ const cond = stack.pop();
24128
+ const snapshot = stack.slice();
24129
+ const thenStack = snapshot.slice();
24130
+ this._evalBlock(instr.then, thenStack);
24131
+ if (this._failed) {
24132
+ break;
24133
+ }
24134
+ const elseStack = snapshot.slice();
24135
+ this._evalBlock(instr.otherwise, elseStack);
24136
+ if (this._failed) {
24137
+ break;
24138
+ }
24139
+ if (thenStack.length !== elseStack.length) {
24140
+ const zero2 = new PsConstNode(0);
24141
+ while (thenStack.length < elseStack.length) {
24142
+ thenStack.push(zero2);
24143
+ }
24144
+ while (elseStack.length < thenStack.length) {
24145
+ elseStack.push(zero2);
24146
+ }
24147
+ }
24148
+ stack.length = 0;
24149
+ for (let i = 0; i < thenStack.length; i++) {
24150
+ stack.push(this._makeTernary(cond, thenStack[i], elseStack[i]));
24151
+ }
24152
+ break;
24153
+ }
24154
+ }
24155
+ }
24156
+ }
24157
+ _evalOp(op, stack) {
24158
+ if (_PSStackToTree.#binaryOps.has(op)) {
24159
+ if (stack.length < 2) {
24160
+ this._failed = true;
24161
+ return;
24162
+ }
24163
+ const first = stack.pop();
24164
+ const second = stack.pop();
24165
+ stack.push(this._makeBinary(op, first, second));
24166
+ return;
24167
+ }
24168
+ if (_PSStackToTree.#unaryOps.has(op)) {
24169
+ if (stack.length < 1) {
24170
+ this._failed = true;
24171
+ return;
24172
+ }
24173
+ stack.push(this._makeUnary(op, stack.pop()));
24174
+ return;
24175
+ }
24176
+ switch (op) {
24177
+ case TOKEN.true:
24178
+ stack.push(new PsConstNode(true));
24179
+ if (stack.length > MAX_STACK_SIZE) {
24180
+ this._failed = true;
24181
+ }
24182
+ break;
24183
+ case TOKEN.false:
24184
+ stack.push(new PsConstNode(false));
24185
+ if (stack.length > MAX_STACK_SIZE) {
24186
+ this._failed = true;
24187
+ }
24188
+ break;
24189
+ case TOKEN.dup:
24190
+ if (stack.length < 1) {
24191
+ this._failed = true;
24192
+ break;
24193
+ }
24194
+ stack.push(stack.at(-1));
24195
+ if (stack.length > MAX_STACK_SIZE) {
24196
+ this._failed = true;
24197
+ }
24198
+ break;
24199
+ case TOKEN.exch: {
24200
+ if (stack.length < 2) {
24201
+ this._failed = true;
24202
+ break;
24203
+ }
24204
+ const a = stack.pop();
24205
+ const b = stack.pop();
24206
+ stack.push(a, b);
24207
+ break;
24208
+ }
24209
+ case TOKEN.pop:
24210
+ if (stack.length < 1) {
24211
+ this._failed = true;
24212
+ break;
24213
+ }
24214
+ stack.pop();
24215
+ break;
24216
+ case TOKEN.copy: {
24217
+ if (stack.length < 1) {
24218
+ this._failed = true;
24219
+ break;
24220
+ }
24221
+ const nNode = stack.pop();
24222
+ if (nNode.type === PS_NODE.const) {
24223
+ const n = nNode.value | 0;
24224
+ if (n === 0) {
24225
+ } else if (n < 0 || n > stack.length) {
24226
+ this._failed = true;
24227
+ } else {
24228
+ stack.push(...stack.slice(-n));
24229
+ if (stack.length > MAX_STACK_SIZE) {
24230
+ this._failed = true;
24231
+ }
24232
+ }
24233
+ } else {
24234
+ this._failed = true;
24235
+ }
24236
+ break;
24237
+ }
24238
+ case TOKEN.index: {
24239
+ if (stack.length < 1) {
24240
+ this._failed = true;
24241
+ break;
24242
+ }
24243
+ const nNode = stack.pop();
24244
+ if (nNode.type === PS_NODE.const) {
24245
+ const n = nNode.value | 0;
24246
+ if (n < 0 || n >= stack.length) {
24247
+ this._failed = true;
24248
+ } else {
24249
+ stack.push(stack.at(-n - 1));
24250
+ }
24251
+ } else {
24252
+ this._failed = true;
24253
+ }
24254
+ break;
24255
+ }
24256
+ case TOKEN.roll: {
24257
+ if (stack.length < 2) {
24258
+ this._failed = true;
24259
+ break;
24260
+ }
24261
+ const jNode = stack.pop();
24262
+ const nNode = stack.pop();
24263
+ if (nNode.type === PS_NODE.const && jNode.type === PS_NODE.const) {
24264
+ const n = nNode.value | 0;
24265
+ if (n === 0) {
24266
+ } else if (n < 0 || n > stack.length) {
24267
+ this._failed = true;
24268
+ } else {
24269
+ const j = ((jNode.value | 0) % n + n) % n;
24270
+ if (j > 0) {
24271
+ const slice = stack.splice(-n, n);
24272
+ stack.push(...slice.slice(n - j), ...slice.slice(0, n - j));
24273
+ }
24274
+ }
24275
+ } else {
24276
+ this._failed = true;
24277
+ }
24278
+ break;
24279
+ }
24280
+ default:
24281
+ this._failed = true;
24282
+ break;
24283
+ }
24284
+ }
24285
+ /**
24286
+ * Create a binary tree node, applying optimizations eagerly:
24287
+ *
24288
+ * 1. Constant folding — both operands are PsConstNode → fold to PsConstNode.
24289
+ * 2. Reflexive simplifications — x−x→0, x xor x→0, x eq x→true, etc.
24290
+ * 3. Algebraic simplifications with one known operand — identity elements
24291
+ * (x+0→x, x*1→x, …), absorbing elements (x*0→0, x and false→false, …),
24292
+ * and strength reductions (x*-1→neg(x), x^0.5→sqrt(x), x^2→x*x, …).
24293
+ *
24294
+ * Recall: `first` was on top of the stack (right operand for non-commutative
24295
+ * ops), `second` was below (left operand). So `a b sub` → second=a, first=b
24296
+ * → a − b.
24297
+ */
24298
+ _makeBinary(op, first, second) {
24299
+ if (first.type === PS_NODE.const && second.type === PS_NODE.const) {
24300
+ const v = _evalBinaryConst(op, second.value, first.value);
24301
+ if (v !== void 0) {
24302
+ return new PsConstNode(v);
24303
+ }
24304
+ }
24305
+ if (_nodesEqual(first, second)) {
24306
+ switch (op) {
24307
+ case TOKEN.sub:
24308
+ return new PsConstNode(0);
24309
+ // x − x → 0
24310
+ case TOKEN.xor:
24311
+ return new PsConstNode(
24312
+ /* eslint-disable unicorn/prefer-logical-operator-over-ternary */
24313
+ first.valueType === PS_VALUE_TYPE.boolean ? false : 0
24314
+ /* eslint-enable unicorn/prefer-logical-operator-over-ternary */
24315
+ );
24316
+ // TOKEN.mod, TOKEN.div, TOKEN.idiv are NOT simplified here:
24317
+ // x op x is undefined when x = 0, so we cannot fold without knowing
24318
+ // that x is non-zero.
24319
+ case TOKEN.and:
24320
+ case TOKEN.or:
24321
+ return first;
24322
+ // x and x → x; x or x → x
24323
+ case TOKEN.min:
24324
+ case TOKEN.max:
24325
+ return first;
24326
+ // min(x,x) → x; max(x,x) → x
24327
+ case TOKEN.eq:
24328
+ case TOKEN.ge:
24329
+ case TOKEN.le:
24330
+ return new PsConstNode(true);
24331
+ case TOKEN.ne:
24332
+ case TOKEN.gt:
24333
+ case TOKEN.lt:
24334
+ return new PsConstNode(false);
24335
+ }
24336
+ }
24337
+ if (first.type === PS_NODE.const) {
24338
+ const b = first.value;
24339
+ switch (op) {
24340
+ case TOKEN.add:
24341
+ if (b === 0) {
24342
+ return second;
24343
+ }
24344
+ break;
24345
+ case TOKEN.sub:
24346
+ if (b === 0) {
24347
+ return second;
24348
+ }
24349
+ break;
24350
+ case TOKEN.mul:
24351
+ if (b === 1) {
24352
+ return second;
24353
+ }
24354
+ if (b === 0) {
24355
+ return first;
24356
+ }
24357
+ if (b === -1) {
24358
+ return this._makeUnary(TOKEN.neg, second);
24359
+ }
24360
+ break;
24361
+ case TOKEN.div:
24362
+ if (b !== 0) {
24363
+ return this._makeBinary(TOKEN.mul, new PsConstNode(1 / b), second);
24364
+ }
24365
+ break;
24366
+ case TOKEN.idiv:
24367
+ if (b === 1) {
24368
+ return second;
24369
+ }
24370
+ break;
24371
+ case TOKEN.exp:
24372
+ if (b === 1) {
24373
+ return second;
24374
+ }
24375
+ if (b === -1) {
24376
+ return this._makeBinary(TOKEN.div, second, new PsConstNode(1));
24377
+ }
24378
+ if (b === 0.5) {
24379
+ return this._makeUnary(TOKEN.sqrt, second);
24380
+ }
24381
+ if (b === 0.25) {
24382
+ const sqrtOnce = this._makeUnary(TOKEN.sqrt, second);
24383
+ return this._makeUnary(TOKEN.sqrt, sqrtOnce);
24384
+ }
24385
+ if (b === 2) {
24386
+ return this._makeBinary(TOKEN.mul, second, second);
24387
+ }
24388
+ if (b === 3) {
24389
+ return this._makeBinary(
24390
+ TOKEN.mul,
24391
+ this._makeBinary(TOKEN.mul, second, second),
24392
+ second
24393
+ );
24394
+ }
24395
+ if (b === 4) {
24396
+ const square = this._makeBinary(TOKEN.mul, second, second);
24397
+ return this._makeBinary(TOKEN.mul, square, square);
24398
+ }
24399
+ if (b === 0) {
24400
+ return new PsConstNode(1);
24401
+ }
24402
+ break;
24403
+ case TOKEN.and:
24404
+ if (b === true) {
24405
+ return second;
24406
+ }
24407
+ if (b === false) {
24408
+ return first;
24409
+ }
24410
+ break;
24411
+ case TOKEN.or:
24412
+ if (b === false) {
24413
+ return second;
24414
+ }
24415
+ if (b === true) {
24416
+ return first;
24417
+ }
24418
+ break;
24419
+ case TOKEN.min:
24420
+ if (second.type === PS_NODE.binary && second.op === TOKEN.max && second.first.type === PS_NODE.const && second.first.value >= b) {
24421
+ return first;
24422
+ }
24423
+ break;
24424
+ case TOKEN.max:
24425
+ if (second.type === PS_NODE.binary && second.op === TOKEN.min && second.first.type === PS_NODE.const && second.first.value <= b) {
24426
+ return first;
24427
+ }
24428
+ break;
24429
+ }
24430
+ }
24431
+ if (second.type === PS_NODE.const) {
24432
+ const a = second.value;
24433
+ switch (op) {
24434
+ case TOKEN.add:
24435
+ if (a === 0) {
24436
+ return first;
24437
+ }
24438
+ break;
24439
+ case TOKEN.sub:
24440
+ if (a === 0) {
24441
+ return this._makeUnary(TOKEN.neg, first);
24442
+ }
24443
+ break;
24444
+ case TOKEN.mul:
24445
+ if (a === 1) {
24446
+ return first;
24447
+ }
24448
+ if (a === 0) {
24449
+ return second;
24450
+ }
24451
+ if (a === -1) {
24452
+ return this._makeUnary(TOKEN.neg, first);
24453
+ }
24454
+ break;
24455
+ case TOKEN.and:
24456
+ if (a === true) {
24457
+ return first;
24458
+ }
24459
+ if (a === false) {
24460
+ return second;
24461
+ }
24462
+ break;
24463
+ case TOKEN.or:
24464
+ if (a === false) {
24465
+ return first;
24466
+ }
24467
+ if (a === true) {
24468
+ return second;
24469
+ }
24470
+ break;
24471
+ }
24472
+ }
24473
+ return new PsBinaryNode(
24474
+ op,
24475
+ first,
24476
+ second,
24477
+ _binaryValueType(op, first.valueType, second.valueType)
24478
+ );
24479
+ }
24480
+ /**
24481
+ * Create a unary tree node, applying optimizations eagerly:
24482
+ *
24483
+ * 1. Constant folding.
24484
+ * 2. not(comparison) → negated comparison: not(a eq b) → a ne b, etc.
24485
+ * 3. neg(a − b) → b − a.
24486
+ * 4. Double-negation: neg(neg(x)) → x, not(not(x)) → x.
24487
+ * 5. abs(neg(x)) → abs(x).
24488
+ * 6. Idempotent: f(f(x)) → f(x) for abs, ceiling, floor, round, etc.
24489
+ */
24490
+ _makeUnary(op, operand) {
24491
+ if (operand.type === PS_NODE.const) {
24492
+ const v = _evalUnaryConst(op, operand.value);
24493
+ if (v !== void 0) {
24494
+ return new PsConstNode(v);
24495
+ }
24496
+ }
24497
+ if (op === TOKEN.not && operand.type === PS_NODE.binary) {
24498
+ const negated = _PSStackToTree.#negatedComparison.get(operand.op);
24499
+ if (negated !== void 0) {
24500
+ return new PsBinaryNode(
24501
+ negated,
24502
+ operand.first,
24503
+ operand.second,
24504
+ PS_VALUE_TYPE.boolean
24505
+ );
24506
+ }
24507
+ }
24508
+ if (op === TOKEN.neg && operand.type === PS_NODE.binary && operand.op === TOKEN.sub) {
24509
+ return this._makeBinary(TOKEN.sub, operand.second, operand.first);
24510
+ }
24511
+ if (operand.type === PS_NODE.unary) {
24512
+ if (op === TOKEN.neg && operand.op === TOKEN.neg || op === TOKEN.not && operand.op === TOKEN.not) {
24513
+ return operand.operand;
24514
+ }
24515
+ if (op === TOKEN.abs && operand.op === TOKEN.neg) {
24516
+ return this._makeUnary(TOKEN.abs, operand.operand);
24517
+ }
24518
+ if (_PSStackToTree.#idempotentUnary.has(op) && op === operand.op) {
24519
+ return operand;
24520
+ }
24521
+ }
24522
+ return new PsUnaryNode(op, operand, _unaryValueType(op, operand.valueType));
24523
+ }
24524
+ /**
24525
+ * Create a ternary node, applying optimizations eagerly:
24526
+ *
24527
+ * 1. Constant condition — fold to the live branch.
24528
+ * 2. Identical branches — the condition is irrelevant, return either branch.
24529
+ * 3. Boolean branch constants — `cond ? true : false` → cond,
24530
+ * `cond ? false : true` → not(cond).
24531
+ * 4. Ternary → branchless min/max when the condition compares two numeric
24532
+ * expressions that are also the two branches.
24533
+ */
24534
+ _makeTernary(cond, then, otherwise) {
24535
+ if (cond.type === PS_NODE.const) {
24536
+ return cond.value ? then : otherwise;
24537
+ }
24538
+ if (_nodesEqual(then, otherwise)) {
24539
+ return then;
24540
+ }
24541
+ if (then.type === PS_NODE.const && otherwise.type === PS_NODE.const) {
24542
+ if (then.value === true && otherwise.value === false) {
24543
+ return cond;
24544
+ }
24545
+ if (then.value === false && otherwise.value === true) {
24546
+ return this._makeUnary(TOKEN.not, cond);
24547
+ }
24548
+ }
24549
+ if (cond.type === PS_NODE.binary) {
24550
+ const { op: cop, first: cf, second: cs } = cond;
24551
+ if (cop === TOKEN.gt || cop === TOKEN.ge) {
24552
+ if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
24553
+ return this._makeBinary(TOKEN.min, cf, cs);
24554
+ }
24555
+ if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
24556
+ return this._makeBinary(TOKEN.max, cf, cs);
24557
+ }
24558
+ } else if (cop === TOKEN.lt || cop === TOKEN.le) {
24559
+ if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
24560
+ return this._makeBinary(TOKEN.max, cf, cs);
24561
+ }
24562
+ if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
24563
+ return this._makeBinary(TOKEN.min, cf, cs);
24564
+ }
24565
+ }
24566
+ }
24567
+ return new PsTernaryNode(
24568
+ cond,
24569
+ then,
24570
+ otherwise,
24571
+ then.valueType === otherwise.valueType ? then.valueType : PS_VALUE_TYPE.unknown
24572
+ );
24573
+ }
24574
+ };
24575
+ var OP = {
24576
+ ARG: 0,
24577
+ // [ARG, idx]
24578
+ CONST: 1,
24579
+ // [CONST, val]
24580
+ STORE: 2,
24581
+ // [STORE, slot, min, max] clamp(pop()) → mem[slot]
24582
+ IF: 3,
24583
+ // [IF, target] jump when top-of-stack === 0
24584
+ JUMP: 4,
24585
+ // [JUMP, target] unconditional
24586
+ ABS: 5,
24587
+ NEG: 6,
24588
+ CEIL: 7,
24589
+ FLOOR: 8,
24590
+ ROUND: 9,
24591
+ // floor(x + 0.5)
24592
+ TRUNC: 10,
24593
+ NOT_B: 11,
24594
+ // boolean NOT
24595
+ NOT_N: 12,
24596
+ // bitwise NOT
24597
+ SQRT: 13,
24598
+ SIN: 14,
24599
+ // degrees in/out
24600
+ COS: 15,
24601
+ LN: 16,
24602
+ LOG10: 17,
24603
+ CVI: 18,
24604
+ SHIFT: 19,
24605
+ // [SHIFT, amount] +ve = left, −ve = right
24606
+ // Binary ops: second below, first on top; result = second OP first.
24607
+ ADD: 20,
24608
+ SUB: 21,
24609
+ MUL: 22,
24610
+ DIV: 23,
24611
+ // 0 when divisor is 0
24612
+ IDIV: 24,
24613
+ // 0 when divisor is 0
24614
+ MOD: 25,
24615
+ // 0 when divisor is 0
24616
+ POW: 26,
24617
+ EQ: 27,
24618
+ NE: 28,
24619
+ GT: 29,
24620
+ GE: 30,
24621
+ LT: 31,
24622
+ LE: 32,
24623
+ AND: 33,
24624
+ OR: 34,
24625
+ XOR: 35,
24626
+ ATAN: 36,
24627
+ // atan2(second, first) → degrees [0, 360)
24628
+ MIN: 37,
24629
+ MAX: 38,
24630
+ TEE_TMP: 39,
24631
+ // [TEE_TMP, slot] peek top of stack → tmp[slot], leave on stack
24632
+ LOAD_TMP: 40
24633
+ // [LOAD_TMP, slot] push tmp[slot]
24634
+ };
24635
+ var _DEG_TO_RAD = Math.PI / 180;
24636
+ var _RAD_TO_DEG = 180 / Math.PI;
24637
+ var PsJsCompiler = class {
24638
+ // Safe because JS is single-threaded.
24639
+ static #stack = new Float64Array(64);
24640
+ static #tmp = new Float64Array(64);
24641
+ constructor(domain, range) {
24642
+ this.nIn = domain.length >> 1;
24643
+ this.nOut = range.length >> 1;
24644
+ this.range = range;
24645
+ this.ir = [];
24646
+ this._tmpMap = /* @__PURE__ */ new Map();
24647
+ this._nextTmp = 0;
24648
+ }
24649
+ _compileNode(node) {
24650
+ if (node.shared) {
24651
+ const cached = this._tmpMap.get(node);
24652
+ if (cached !== void 0) {
24653
+ this.ir.push(OP.LOAD_TMP, cached);
24654
+ return true;
24655
+ }
24656
+ if (!this._compileNodeImpl(node)) {
24657
+ return false;
24658
+ }
24659
+ const slot = this._nextTmp++;
24660
+ this._tmpMap.set(node, slot);
24661
+ this.ir.push(OP.TEE_TMP, slot);
24662
+ return true;
24663
+ }
24664
+ return this._compileNodeImpl(node);
24665
+ }
24666
+ _compileNodeImpl(node) {
24667
+ switch (node.type) {
24668
+ case PS_NODE.arg:
24669
+ this.ir.push(OP.ARG, node.index);
24670
+ return true;
24671
+ case PS_NODE.const: {
24672
+ const v = node.value;
24673
+ this.ir.push(OP.CONST, typeof v === "boolean" ? Number(v) : v);
24674
+ return true;
24675
+ }
24676
+ case PS_NODE.unary:
24677
+ return this._compileUnary(node);
24678
+ case PS_NODE.binary:
24679
+ return this._compileBinary(node);
24680
+ case PS_NODE.ternary:
24681
+ return this._compileTernary(node);
24682
+ default:
24683
+ return false;
24684
+ }
24685
+ }
24686
+ _compileUnary(node) {
24687
+ const { op, operand, valueType } = node;
24688
+ if (op === TOKEN.cvr) {
24689
+ return this._compileNode(operand);
24690
+ }
24691
+ if (!this._compileNode(operand)) {
24692
+ return false;
24693
+ }
24694
+ switch (op) {
24695
+ case TOKEN.abs:
24696
+ this.ir.push(OP.ABS);
24697
+ break;
24698
+ case TOKEN.neg:
24699
+ this.ir.push(OP.NEG);
24700
+ break;
24701
+ case TOKEN.ceiling:
24702
+ this.ir.push(OP.CEIL);
24703
+ break;
24704
+ case TOKEN.floor:
24705
+ this.ir.push(OP.FLOOR);
24706
+ break;
24707
+ case TOKEN.round:
24708
+ this.ir.push(OP.ROUND);
24709
+ break;
24710
+ case TOKEN.truncate:
24711
+ this.ir.push(OP.TRUNC);
24712
+ break;
24713
+ case TOKEN.sqrt:
24714
+ this.ir.push(OP.SQRT);
24715
+ break;
24716
+ case TOKEN.sin:
24717
+ this.ir.push(OP.SIN);
24718
+ break;
24719
+ case TOKEN.cos:
24720
+ this.ir.push(OP.COS);
24721
+ break;
24722
+ case TOKEN.ln:
24723
+ this.ir.push(OP.LN);
24724
+ break;
24725
+ case TOKEN.log:
24726
+ this.ir.push(OP.LOG10);
24727
+ break;
24728
+ case TOKEN.cvi:
24729
+ this.ir.push(OP.CVI);
24730
+ break;
24731
+ case TOKEN.not:
24732
+ if (valueType === PS_VALUE_TYPE.boolean) {
24733
+ this.ir.push(OP.NOT_B);
24734
+ } else if (valueType === PS_VALUE_TYPE.numeric) {
24735
+ this.ir.push(OP.NOT_N);
24736
+ } else {
24737
+ return false;
24738
+ }
24739
+ break;
24740
+ default:
24741
+ return false;
24742
+ }
24743
+ return true;
24744
+ }
24745
+ _compileBinary(node) {
24746
+ const { op, first, second } = node;
24747
+ if (op === TOKEN.bitshift) {
24748
+ if (first.type !== PS_NODE.const || !Number.isInteger(first.value) || !this._compileNode(second)) {
24749
+ return false;
24750
+ }
24751
+ this.ir.push(OP.SHIFT, first.value);
24752
+ return true;
24753
+ }
24754
+ if (!this._compileNode(second) || !this._compileNode(first)) {
24755
+ return false;
24756
+ }
24757
+ switch (op) {
24758
+ case TOKEN.add:
24759
+ this.ir.push(OP.ADD);
24760
+ break;
24761
+ case TOKEN.sub:
24762
+ this.ir.push(OP.SUB);
24763
+ break;
24764
+ case TOKEN.mul:
24765
+ this.ir.push(OP.MUL);
24766
+ break;
24767
+ case TOKEN.div:
24768
+ this.ir.push(OP.DIV);
24769
+ break;
24770
+ case TOKEN.idiv:
24771
+ this.ir.push(OP.IDIV);
24772
+ break;
24773
+ case TOKEN.mod:
24774
+ this.ir.push(OP.MOD);
24775
+ break;
24776
+ case TOKEN.exp:
24777
+ this.ir.push(OP.POW);
24778
+ break;
24779
+ case TOKEN.eq:
24780
+ this.ir.push(OP.EQ);
24781
+ break;
24782
+ case TOKEN.ne:
24783
+ this.ir.push(OP.NE);
24784
+ break;
24785
+ case TOKEN.gt:
24786
+ this.ir.push(OP.GT);
24787
+ break;
24788
+ case TOKEN.ge:
24789
+ this.ir.push(OP.GE);
24790
+ break;
24791
+ case TOKEN.lt:
24792
+ this.ir.push(OP.LT);
24793
+ break;
24794
+ case TOKEN.le:
24795
+ this.ir.push(OP.LE);
24796
+ break;
24797
+ case TOKEN.and:
24798
+ this.ir.push(OP.AND);
24799
+ break;
24800
+ case TOKEN.or:
24801
+ this.ir.push(OP.OR);
24802
+ break;
24803
+ case TOKEN.xor:
24804
+ this.ir.push(OP.XOR);
24805
+ break;
24806
+ case TOKEN.atan:
24807
+ this.ir.push(OP.ATAN);
24808
+ break;
24809
+ case TOKEN.min:
24810
+ this.ir.push(OP.MIN);
24811
+ break;
24812
+ case TOKEN.max:
24813
+ this.ir.push(OP.MAX);
24814
+ break;
24815
+ default:
24816
+ return false;
24817
+ }
24818
+ return true;
24819
+ }
24820
+ _compileTernary(node) {
24821
+ if (!this._compileNode(node.cond)) {
24822
+ return false;
24823
+ }
24824
+ this.ir.push(OP.IF, 0);
24825
+ const ifPatch = this.ir.length - 1;
24826
+ if (!this._compileNode(node.then)) {
24827
+ return false;
24828
+ }
24829
+ this.ir.push(OP.JUMP, 0);
24830
+ const jumpPatch = this.ir.length - 1;
24831
+ this.ir[ifPatch] = this.ir.length;
24832
+ if (!this._compileNode(node.otherwise)) {
24833
+ return false;
24834
+ }
24835
+ this.ir[jumpPatch] = this.ir.length;
24836
+ return true;
24837
+ }
24838
+ compile(program) {
24839
+ const outputs = new PSStackToTree().evaluate(program, this.nIn);
24840
+ if (!outputs || outputs.length < this.nOut) {
24841
+ return null;
24842
+ }
24843
+ for (let i = 0; i < this.nOut; i++) {
24844
+ if (!this._compileNode(outputs[i])) {
24845
+ return null;
24846
+ }
24847
+ const min = this.range[i * 2];
24848
+ const max = this.range[i * 2 + 1];
24849
+ this.ir.push(OP.STORE, i, min, max);
24850
+ }
24851
+ return new Float64Array(this.ir);
24852
+ }
24853
+ static execute(ir, src, srcOffset, dest, destOffset) {
24854
+ let ip = 0, sp = 0;
24855
+ const n = ir.length;
24856
+ const stack = this.#stack;
24857
+ const tmp = this.#tmp;
24858
+ while (ip < n) {
24859
+ switch (ir[ip++] | 0) {
24860
+ case OP.ARG:
24861
+ stack[sp++] = src[srcOffset + (ir[ip++] | 0)];
24862
+ break;
24863
+ case OP.CONST:
24864
+ stack[sp++] = ir[ip++];
24865
+ break;
24866
+ case OP.STORE: {
24867
+ const slot = ir[ip++] | 0;
24868
+ const min = ir[ip++];
24869
+ const max = ir[ip++];
24870
+ dest[destOffset + slot] = MathClamp(stack[--sp], min, max);
24871
+ break;
24872
+ }
24873
+ case OP.IF: {
24874
+ const tgt = ir[ip++];
24875
+ if (stack[--sp] === 0) {
24876
+ ip = tgt;
24877
+ }
24878
+ break;
24879
+ }
24880
+ case OP.JUMP:
24881
+ ip = ir[ip];
24882
+ break;
24883
+ case OP.ABS:
24884
+ stack[sp - 1] = Math.abs(stack[sp - 1]);
24885
+ break;
24886
+ case OP.NEG:
24887
+ stack[sp - 1] = -stack[sp - 1];
24888
+ break;
24889
+ case OP.CEIL:
24890
+ stack[sp - 1] = Math.ceil(stack[sp - 1]);
24891
+ break;
24892
+ case OP.FLOOR:
24893
+ stack[sp - 1] = Math.floor(stack[sp - 1]);
24894
+ break;
24895
+ case OP.ROUND:
24896
+ stack[sp - 1] = Math.floor(stack[sp - 1] + 0.5);
24897
+ break;
24898
+ case OP.TRUNC:
24899
+ stack[sp - 1] = Math.trunc(stack[sp - 1]);
24900
+ break;
24901
+ case OP.NOT_B:
24902
+ stack[sp - 1] = stack[sp - 1] !== 0 ? 0 : 1;
24903
+ break;
24904
+ case OP.NOT_N:
24905
+ stack[sp - 1] = ~(stack[sp - 1] | 0);
24906
+ break;
24907
+ case OP.SQRT:
24908
+ stack[sp - 1] = Math.sqrt(stack[sp - 1]);
24909
+ break;
24910
+ case OP.SIN:
24911
+ stack[sp - 1] = Math.sin(stack[sp - 1] % 360 * _DEG_TO_RAD);
24912
+ break;
24913
+ case OP.COS:
24914
+ stack[sp - 1] = Math.cos(stack[sp - 1] % 360 * _DEG_TO_RAD);
24915
+ break;
24916
+ case OP.LN:
24917
+ stack[sp - 1] = Math.log(stack[sp - 1]);
24918
+ break;
24919
+ case OP.LOG10:
24920
+ stack[sp - 1] = Math.log10(stack[sp - 1]);
24921
+ break;
24922
+ case OP.CVI:
24923
+ stack[sp - 1] = Math.trunc(stack[sp - 1]) | 0;
24924
+ break;
24925
+ case OP.SHIFT: {
24926
+ const amt = ir[ip++];
24927
+ const v = stack[sp - 1] | 0;
24928
+ if (amt > 0) {
24929
+ stack[sp - 1] = v << amt;
24930
+ } else if (amt < 0) {
24931
+ stack[sp - 1] = v >> -amt;
24932
+ } else {
24933
+ stack[sp - 1] = v;
24934
+ }
24935
+ break;
24936
+ }
24937
+ case OP.ADD: {
24938
+ const b = stack[--sp];
24939
+ stack[sp - 1] += b;
24940
+ break;
24941
+ }
24942
+ case OP.SUB: {
24943
+ const b = stack[--sp];
24944
+ stack[sp - 1] -= b;
24945
+ break;
24946
+ }
24947
+ case OP.MUL: {
24948
+ const b = stack[--sp];
24949
+ stack[sp - 1] *= b;
24950
+ break;
24951
+ }
24952
+ case OP.DIV: {
24953
+ const b = stack[--sp];
24954
+ stack[sp - 1] = b !== 0 ? stack[sp - 1] / b : 0;
24955
+ break;
24956
+ }
24957
+ case OP.IDIV: {
24958
+ const b = stack[--sp];
24959
+ stack[sp - 1] = b !== 0 ? Math.trunc(stack[sp - 1] / b) : 0;
24960
+ break;
24961
+ }
24962
+ case OP.MOD: {
24963
+ const b = stack[--sp];
24964
+ stack[sp - 1] = b !== 0 ? stack[sp - 1] % b : 0;
24965
+ break;
24966
+ }
24967
+ case OP.POW: {
24968
+ const b = stack[--sp];
24969
+ stack[sp - 1] **= b;
24970
+ break;
24971
+ }
24972
+ case OP.EQ: {
24973
+ const b = stack[--sp];
24974
+ stack[sp - 1] = stack[sp - 1] === b ? 1 : 0;
24975
+ break;
24976
+ }
24977
+ case OP.NE: {
24978
+ const b = stack[--sp];
24979
+ stack[sp - 1] = stack[sp - 1] !== b ? 1 : 0;
24980
+ break;
24981
+ }
24982
+ case OP.GT: {
24983
+ const b = stack[--sp];
24984
+ stack[sp - 1] = stack[sp - 1] > b ? 1 : 0;
24985
+ break;
24986
+ }
24987
+ case OP.GE: {
24988
+ const b = stack[--sp];
24989
+ stack[sp - 1] = stack[sp - 1] >= b ? 1 : 0;
24990
+ break;
24991
+ }
24992
+ case OP.LT: {
24993
+ const b = stack[--sp];
24994
+ stack[sp - 1] = stack[sp - 1] < b ? 1 : 0;
24995
+ break;
24996
+ }
24997
+ case OP.LE: {
24998
+ const b = stack[--sp];
24999
+ stack[sp - 1] = stack[sp - 1] <= b ? 1 : 0;
25000
+ break;
25001
+ }
25002
+ case OP.AND: {
25003
+ const b = stack[--sp] | 0;
25004
+ stack[sp - 1] = (stack[sp - 1] | 0) & b;
25005
+ break;
25006
+ }
25007
+ case OP.OR: {
25008
+ const b = stack[--sp] | 0;
25009
+ stack[sp - 1] = stack[sp - 1] | 0 | b;
25010
+ break;
25011
+ }
25012
+ case OP.XOR: {
25013
+ const b = stack[--sp] | 0;
25014
+ stack[sp - 1] = (stack[sp - 1] | 0) ^ b;
25015
+ break;
25016
+ }
25017
+ case OP.ATAN: {
25018
+ const b = stack[--sp];
25019
+ const deg = Math.atan2(stack[sp - 1], b) * _RAD_TO_DEG;
25020
+ stack[sp - 1] = deg < 0 ? deg + 360 : deg;
25021
+ break;
25022
+ }
25023
+ case OP.MIN: {
25024
+ const b = stack[--sp];
25025
+ stack[sp - 1] = Math.min(stack[sp - 1], b);
25026
+ break;
25027
+ }
25028
+ case OP.MAX: {
25029
+ const b = stack[--sp];
25030
+ stack[sp - 1] = Math.max(stack[sp - 1], b);
25031
+ break;
25032
+ }
25033
+ case OP.TEE_TMP:
25034
+ tmp[ir[ip++] | 0] = stack[sp - 1];
25035
+ break;
25036
+ case OP.LOAD_TMP:
25037
+ stack[sp++] = tmp[ir[ip++] | 0];
25038
+ break;
25039
+ }
25040
+ }
25041
+ }
25042
+ };
25043
+ var PSStackBasedInterpreter = class {
25044
+ // Safe: JS is single-threaded.
25045
+ static #stack = new Float64Array(100);
25046
+ static #sp = 0;
25047
+ static #push(v) {
25048
+ if (this.#sp < this.#stack.length) {
25049
+ this.#stack[this.#sp++] = v;
25050
+ }
25051
+ }
25052
+ static #execOp(op) {
25053
+ const stack = this.#stack;
25054
+ switch (op) {
25055
+ case TOKEN.true:
25056
+ this.#push(1);
25057
+ break;
25058
+ case TOKEN.false:
25059
+ this.#push(0);
25060
+ break;
25061
+ case TOKEN.abs:
25062
+ stack[this.#sp - 1] = Math.abs(stack[this.#sp - 1]);
25063
+ break;
25064
+ case TOKEN.neg:
25065
+ stack[this.#sp - 1] = -stack[this.#sp - 1];
25066
+ break;
25067
+ case TOKEN.ceiling:
25068
+ stack[this.#sp - 1] = Math.ceil(stack[this.#sp - 1]);
25069
+ break;
25070
+ case TOKEN.floor:
25071
+ stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1]);
25072
+ break;
25073
+ case TOKEN.round:
25074
+ stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1] + 0.5);
25075
+ break;
25076
+ case TOKEN.truncate:
25077
+ stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]);
25078
+ break;
25079
+ case TOKEN.sqrt:
25080
+ stack[this.#sp - 1] = Math.sqrt(stack[this.#sp - 1]);
25081
+ break;
25082
+ case TOKEN.sin:
25083
+ stack[this.#sp - 1] = Math.sin(
25084
+ stack[this.#sp - 1] % 360 * _DEG_TO_RAD
25085
+ );
25086
+ break;
25087
+ case TOKEN.cos:
25088
+ stack[this.#sp - 1] = Math.cos(
25089
+ stack[this.#sp - 1] % 360 * _DEG_TO_RAD
25090
+ );
25091
+ break;
25092
+ case TOKEN.ln:
25093
+ stack[this.#sp - 1] = Math.log(stack[this.#sp - 1]);
25094
+ break;
25095
+ case TOKEN.log:
25096
+ stack[this.#sp - 1] = Math.log10(stack[this.#sp - 1]);
25097
+ break;
25098
+ case TOKEN.cvi:
25099
+ stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]) | 0;
25100
+ break;
25101
+ case TOKEN.cvr:
25102
+ break;
25103
+ // values are already f64
25104
+ case TOKEN.not: {
25105
+ const v = stack[this.#sp - 1];
25106
+ stack[this.#sp - 1] = v === 0 || v === 1 ? 1 - v : ~(v | 0);
25107
+ break;
25108
+ }
25109
+ case TOKEN.add: {
25110
+ const b = stack[--this.#sp];
25111
+ stack[this.#sp - 1] += b;
25112
+ break;
25113
+ }
25114
+ case TOKEN.sub: {
25115
+ const b = stack[--this.#sp];
25116
+ stack[this.#sp - 1] -= b;
25117
+ break;
25118
+ }
25119
+ case TOKEN.mul: {
25120
+ const b = stack[--this.#sp];
25121
+ stack[this.#sp - 1] *= b;
25122
+ break;
25123
+ }
25124
+ case TOKEN.div: {
25125
+ const b = stack[--this.#sp];
25126
+ stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] / b : 0;
25127
+ break;
25128
+ }
25129
+ case TOKEN.idiv: {
25130
+ const b = stack[--this.#sp];
25131
+ stack[this.#sp - 1] = b !== 0 ? Math.trunc(stack[this.#sp - 1] / b) : 0;
25132
+ break;
25133
+ }
25134
+ case TOKEN.mod: {
25135
+ const b = stack[--this.#sp];
25136
+ stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] % b : 0;
25137
+ break;
25138
+ }
25139
+ case TOKEN.exp: {
25140
+ const b = stack[--this.#sp];
25141
+ stack[this.#sp - 1] **= b;
25142
+ break;
25143
+ }
25144
+ case TOKEN.atan: {
25145
+ const dx = stack[--this.#sp];
25146
+ const deg = Math.atan2(stack[this.#sp - 1], dx) * _RAD_TO_DEG;
25147
+ stack[this.#sp - 1] = deg < 0 ? deg + 360 : deg;
25148
+ break;
25149
+ }
25150
+ case TOKEN.eq: {
25151
+ const b = stack[--this.#sp];
25152
+ stack[this.#sp - 1] = stack[this.#sp - 1] === b ? 1 : 0;
25153
+ break;
25154
+ }
25155
+ case TOKEN.ne: {
25156
+ const b = stack[--this.#sp];
25157
+ stack[this.#sp - 1] = stack[this.#sp - 1] !== b ? 1 : 0;
25158
+ break;
25159
+ }
25160
+ case TOKEN.gt: {
25161
+ const b = stack[--this.#sp];
25162
+ stack[this.#sp - 1] = stack[this.#sp - 1] > b ? 1 : 0;
25163
+ break;
25164
+ }
25165
+ case TOKEN.ge: {
25166
+ const b = stack[--this.#sp];
25167
+ stack[this.#sp - 1] = stack[this.#sp - 1] >= b ? 1 : 0;
25168
+ break;
25169
+ }
25170
+ case TOKEN.lt: {
25171
+ const b = stack[--this.#sp];
25172
+ stack[this.#sp - 1] = stack[this.#sp - 1] < b ? 1 : 0;
25173
+ break;
25174
+ }
25175
+ case TOKEN.le: {
25176
+ const b = stack[--this.#sp];
25177
+ stack[this.#sp - 1] = stack[this.#sp - 1] <= b ? 1 : 0;
25178
+ break;
25179
+ }
25180
+ case TOKEN.and: {
25181
+ const b = stack[--this.#sp] | 0;
25182
+ stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) & b;
25183
+ break;
25184
+ }
25185
+ case TOKEN.or: {
25186
+ const b = stack[--this.#sp] | 0;
25187
+ stack[this.#sp - 1] = stack[this.#sp - 1] | 0 | b;
25188
+ break;
25189
+ }
25190
+ case TOKEN.xor: {
25191
+ const b = stack[--this.#sp] | 0;
25192
+ stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) ^ b;
25193
+ break;
25194
+ }
25195
+ case TOKEN.bitshift: {
25196
+ const amt = stack[--this.#sp] | 0;
25197
+ const v = stack[this.#sp - 1] | 0;
25198
+ stack[this.#sp - 1] = amt > 0 ? v << amt : v >> -amt;
25199
+ break;
25200
+ }
25201
+ case TOKEN.min: {
25202
+ const b = stack[--this.#sp];
25203
+ stack[this.#sp - 1] = Math.min(stack[this.#sp - 1], b);
25204
+ break;
25205
+ }
25206
+ case TOKEN.max: {
25207
+ const b = stack[--this.#sp];
25208
+ stack[this.#sp - 1] = Math.max(stack[this.#sp - 1], b);
25209
+ break;
25210
+ }
25211
+ case TOKEN.dup:
25212
+ this.#push(stack[this.#sp - 1]);
25213
+ break;
25214
+ case TOKEN.exch: {
25215
+ const a = stack[--this.#sp];
25216
+ const b = stack[--this.#sp];
25217
+ this.#push(a);
25218
+ this.#push(b);
25219
+ break;
25220
+ }
25221
+ case TOKEN.pop:
25222
+ this.#sp--;
25223
+ break;
25224
+ case TOKEN.copy: {
25225
+ const n = Math.trunc(stack[--this.#sp]);
25226
+ const base = this.#sp - n;
25227
+ for (let k = 0; k < n; k++) {
25228
+ this.#push(stack[base + k]);
25229
+ }
25230
+ break;
25231
+ }
25232
+ case TOKEN.index: {
25233
+ const i = Math.trunc(stack[--this.#sp]);
25234
+ this.#push(stack[this.#sp - 1 - i]);
25235
+ break;
25236
+ }
25237
+ case TOKEN.roll: {
25238
+ const j = Math.trunc(stack[--this.#sp]);
25239
+ const n = Math.trunc(stack[--this.#sp]);
25240
+ if (n > 1 && j !== 0) {
25241
+ const mod = (j % n + n) % n;
25242
+ if (mod !== 0) {
25243
+ const base = this.#sp - n;
25244
+ const sub = stack.slice(base, this.#sp);
25245
+ for (let k = 0; k < n; k++) {
25246
+ stack[base + k] = sub[(k - mod + n) % n];
25247
+ }
25248
+ }
25249
+ }
25250
+ break;
25251
+ }
25252
+ }
25253
+ }
25254
+ static #execBlock(instructions) {
25255
+ for (const instr of instructions) {
25256
+ switch (instr.type) {
25257
+ case PS_NODE.number:
25258
+ this.#push(instr.value);
25259
+ break;
25260
+ case PS_NODE.operator:
25261
+ this.#execOp(instr.op);
25262
+ break;
25263
+ case PS_NODE.if:
25264
+ if (this.#stack[--this.#sp] !== 0) {
25265
+ this.#execBlock(instr.then.instructions);
25266
+ }
25267
+ break;
25268
+ case PS_NODE.ifelse:
25269
+ if (this.#stack[--this.#sp] !== 0) {
25270
+ this.#execBlock(instr.then.instructions);
25271
+ } else {
25272
+ this.#execBlock(instr.otherwise.instructions);
25273
+ }
25274
+ break;
25275
+ }
25276
+ }
25277
+ }
25278
+ /**
25279
+ * @param {import("./ast.js").PsProgram} program
25280
+ * @param {number[]} domain – flat [min0,max0, …]
25281
+ * @param {number[]} range – flat [min0,max0, …]
25282
+ * @returns {Function} – `(src, srcOffset, dest, destOffset) => void`
25283
+ */
25284
+ static build(program, domain, range) {
25285
+ const nIn = domain.length >> 1;
25286
+ const nOut = range.length >> 1;
25287
+ const { instructions } = program.body;
25288
+ return (src, srcOffset, dest, destOffset) => {
25289
+ this.#sp = 0;
25290
+ for (let i = 0; i < nIn; i++) {
25291
+ this.#push(src[srcOffset + i]);
25292
+ }
25293
+ this.#execBlock(instructions);
25294
+ const base = this.#sp - nOut;
25295
+ for (let i = 0; i < nOut; i++) {
25296
+ const v = base + i >= 0 ? this.#stack[base + i] : 0;
25297
+ dest[destOffset + i] = MathClamp(v, range[i * 2], range[i * 2 + 1]);
25298
+ }
25299
+ };
25300
+ }
25301
+ };
25302
+ function buildPostScriptJsFunction(source, domain, range, forceInterpreter = false) {
25303
+ const program = parsePostScriptFunction(source);
25304
+ const ir = !forceInterpreter && new PsJsCompiler(domain, range).compile(program);
25305
+ if (ir) {
25306
+ return (src, srcOffset, dest, destOffset) => {
25307
+ PsJsCompiler.execute(ir, src, srcOffset, dest, destOffset);
25308
+ };
25309
+ }
25310
+ return PSStackBasedInterpreter.build(program, domain, range);
25311
+ }
25312
+ var ShadingType = {
25313
+ FUNCTION_BASED: 1,
25314
+ AXIAL: 2,
25315
+ RADIAL: 3,
25316
+ FREE_FORM_MESH: 4,
25317
+ LATTICE_FORM_MESH: 5,
25318
+ COONS_PATCH_MESH: 6,
25319
+ TENSOR_PATCH_MESH: 7
25320
+ };
25321
+ var BaseShading = class _BaseShading {
25322
+ // A small number to offset the first/last color stops so we can insert ones
25323
+ // to support extend. Number.MIN_VALUE is too small and breaks the extend.
25324
+ static SMALL_NUMBER = 1e-6;
25325
+ constructor() {
25326
+ if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _BaseShading) {
25327
+ unreachable2("Cannot initialize BaseShading.");
25328
+ }
25329
+ }
25330
+ getIR() {
25331
+ unreachable2("Abstract method `getIR` called.");
25332
+ }
25333
+ };
25334
+ function meshUpdateBounds(self) {
25335
+ let minX = self.coords[0][0], minY = self.coords[0][1], maxX = minX, maxY = minY;
25336
+ for (let i = 1, ii = self.coords.length; i < ii; i++) {
25337
+ const x = self.coords[i][0], y = self.coords[i][1];
25338
+ minX = minX > x ? x : minX;
25339
+ minY = minY > y ? y : minY;
25340
+ maxX = maxX < x ? x : maxX;
25341
+ maxY = maxY < y ? y : maxY;
25342
+ }
25343
+ self.bounds = [minX, minY, maxX, maxY];
25344
+ }
25345
+ function meshPackData(self) {
25346
+ let i, j, ii;
25347
+ const coords = self.coords;
25348
+ const coordsPacked = new Float32Array(coords.length * 2);
25349
+ for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
25350
+ const xy = coords[i];
25351
+ coordsPacked[j++] = xy[0];
25352
+ coordsPacked[j++] = xy[1];
25353
+ }
25354
+ self.coords = coordsPacked;
25355
+ const colors = self.colors;
25356
+ const colorsPacked = new Uint8Array(colors.length * 4);
25357
+ for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
25358
+ const c = colors[i];
25359
+ colorsPacked[j++] = c[0];
25360
+ colorsPacked[j++] = c[1];
25361
+ colorsPacked[j++] = c[2];
25362
+ j++;
25363
+ }
25364
+ self.colors = colorsPacked;
25365
+ for (const figure of self.figures) {
25366
+ figure.coords = new Uint32Array(figure.coords);
25367
+ figure.colors = new Uint32Array(figure.colors);
25368
+ }
25369
+ }
25370
+ function buildMeshVertexData(coords, colors, figures) {
25371
+ let vertexCount = 0;
25372
+ for (const figure of figures) {
25373
+ if (figure.type === MeshFigureType.TRIANGLES) {
25374
+ vertexCount += figure.coords.length;
25375
+ } else if (figure.type === MeshFigureType.LATTICE) {
25376
+ const vpr = figure.verticesPerRow;
25377
+ vertexCount += (Math.floor(figure.coords.length / vpr) - 1) * (vpr - 1) * 6;
25378
+ }
25379
+ }
25380
+ const posData = new Float32Array(vertexCount * 2);
25381
+ const colData = new Uint8Array(vertexCount * 4);
25382
+ let pOff = 0, cOff = 0;
25383
+ const addVertex = (pi, ci) => {
25384
+ posData[pOff++] = coords[pi * 2];
25385
+ posData[pOff++] = coords[pi * 2 + 1];
25386
+ colData[cOff++] = colors[ci * 4];
25387
+ colData[cOff++] = colors[ci * 4 + 1];
25388
+ colData[cOff++] = colors[ci * 4 + 2];
25389
+ cOff++;
25390
+ };
25391
+ for (const figure of figures) {
25392
+ const ps = figure.coords;
25393
+ const cs = figure.colors;
25394
+ if (figure.type === MeshFigureType.TRIANGLES) {
25395
+ for (let i = 0, ii = ps.length; i < ii; i++) {
25396
+ addVertex(ps[i], cs[i]);
25397
+ }
25398
+ } else if (figure.type === MeshFigureType.LATTICE) {
25399
+ const vpr = figure.verticesPerRow;
25400
+ const rows = Math.floor(ps.length / vpr) - 1;
25401
+ const cols = vpr - 1;
25402
+ for (let i = 0; i < rows; i++) {
25403
+ let q = i * vpr;
25404
+ for (let j = 0; j < cols; j++, q++) {
25405
+ addVertex(ps[q], cs[q]);
25406
+ addVertex(ps[q + 1], cs[q + 1]);
25407
+ addVertex(ps[q + vpr], cs[q + vpr]);
25408
+ addVertex(ps[q + vpr + 1], cs[q + vpr + 1]);
25409
+ addVertex(ps[q + 1], cs[q + 1]);
25410
+ addVertex(ps[q + vpr], cs[q + vpr]);
25411
+ }
25412
+ }
25413
+ }
25414
+ }
25415
+ return { posData, colData, vertexCount };
25416
+ }
25417
+ var MeshStreamReader = class {
25418
+ constructor(stream, context) {
25419
+ this.stream = stream;
25420
+ this.context = context;
25421
+ this.buffer = 0;
25422
+ this.bufferLength = 0;
25423
+ const numComps = context.numComps;
25424
+ this.tmpCompsBuf = new Float32Array(numComps);
25425
+ const csNumComps = context.colorSpace.numComps;
25426
+ this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf;
25427
+ }
25428
+ get hasData() {
25429
+ if (this.stream.end) {
25430
+ return this.stream.pos < this.stream.end;
25431
+ }
25432
+ if (this.bufferLength > 0) {
25433
+ return true;
25434
+ }
25435
+ const nextByte = this.stream.getByte();
25436
+ if (nextByte < 0) {
25437
+ return false;
25438
+ }
25439
+ this.buffer = nextByte;
25440
+ this.bufferLength = 8;
25441
+ return true;
25442
+ }
25443
+ readBits(n) {
25444
+ const { stream } = this;
25445
+ let { buffer, bufferLength } = this;
25446
+ if (n === 32) {
25447
+ if (bufferLength === 0) {
25448
+ return stream.getInt32() >>> 0;
25449
+ }
25450
+ buffer = buffer << 24 | stream.getByte() << 16 | stream.getByte() << 8 | stream.getByte();
25451
+ const nextByte = stream.getByte();
25452
+ this.buffer = nextByte & (1 << bufferLength) - 1;
25453
+ return (buffer << 8 - bufferLength | (nextByte & 255) >> bufferLength) >>> 0;
25454
+ }
25455
+ if (n === 8 && bufferLength === 0) {
25456
+ return stream.getByte();
25457
+ }
25458
+ while (bufferLength < n) {
25459
+ buffer = buffer << 8 | stream.getByte();
25460
+ bufferLength += 8;
25461
+ }
25462
+ bufferLength -= n;
25463
+ this.bufferLength = bufferLength;
25464
+ this.buffer = buffer & (1 << bufferLength) - 1;
25465
+ return buffer >> bufferLength;
25466
+ }
25467
+ align() {
25468
+ this.buffer = 0;
25469
+ this.bufferLength = 0;
25470
+ }
25471
+ readFlag() {
25472
+ return this.readBits(this.context.bitsPerFlag);
25473
+ }
25474
+ readCoordinate() {
25475
+ const { bitsPerCoordinate, decode } = this.context;
25476
+ const xi = this.readBits(bitsPerCoordinate);
25477
+ const yi = this.readBits(bitsPerCoordinate);
25478
+ const scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 23283064365386963e-26;
25479
+ return [
25480
+ xi * scale * (decode[1] - decode[0]) + decode[0],
25481
+ yi * scale * (decode[3] - decode[2]) + decode[2]
25482
+ ];
25483
+ }
25484
+ readComponents() {
25485
+ const { bitsPerComponent, colorFn, colorSpace, decode, numComps } = this.context;
25486
+ const scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 23283064365386963e-26;
25487
+ const components = this.tmpCompsBuf;
25488
+ for (let i = 0, j = 4; i < numComps; i++, j += 2) {
25489
+ const ci = this.readBits(bitsPerComponent);
25490
+ components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j];
25491
+ }
25492
+ const color = this.tmpCsCompsBuf;
25493
+ colorFn?.(components, 0, color, 0);
25494
+ return colorSpace.getRgb(color, 0);
25495
+ }
25496
+ };
25497
+ var bCache = null;
25498
+ function getB(count) {
25499
+ if (bCache?.has(count)) return bCache.get(count);
25500
+ const values = Array.from({ length: count + 1 }, (_, i) => {
25501
+ const t = i / count, t_ = 1 - t;
25502
+ return new Float32Array([
25503
+ t_ ** 3,
25504
+ 3 * t * t_ ** 2,
25505
+ 3 * t ** 2 * t_,
25506
+ t ** 3
25507
+ ]);
25508
+ });
25509
+ (bCache ??= /* @__PURE__ */ new Map()).set(count, values);
25510
+ return values;
25511
+ }
25512
+ var MeshShading = class _MeshShading extends BaseShading {
25513
+ static MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;
25514
+ static MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;
25515
+ // Count of triangles per entire mesh bounds.
25516
+ static TRIANGLE_DENSITY = 20;
25517
+ constructor(shadingType, stream, context, rowVertices) {
25518
+ super();
25519
+ this.shadingType = shadingType;
25520
+ this.bbox = this.background = null;
25521
+ this.coords = [];
25522
+ this.colors = [];
25523
+ this.figures = [];
25524
+ const reader = new MeshStreamReader(stream, context);
25525
+ let patchMesh = false;
25526
+ switch (this.shadingType) {
25527
+ case ShadingType.FREE_FORM_MESH:
25528
+ this._decodeType4Shading(reader);
25529
+ break;
25530
+ case ShadingType.LATTICE_FORM_MESH:
25531
+ const verticesPerRow = rowVertices | 0;
25532
+ if (verticesPerRow < 2) {
25533
+ throw new FormatError("Invalid VerticesPerRow");
25534
+ }
25535
+ this._decodeType5Shading(reader, verticesPerRow);
25536
+ break;
25537
+ case ShadingType.COONS_PATCH_MESH:
25538
+ this._decodeType6Shading(reader);
25539
+ patchMesh = true;
25540
+ break;
25541
+ case ShadingType.TENSOR_PATCH_MESH:
25542
+ this._decodeType7Shading(reader);
25543
+ patchMesh = true;
25544
+ break;
25545
+ default:
25546
+ unreachable2("Unsupported mesh type.");
25547
+ break;
25548
+ }
25549
+ if (patchMesh) {
25550
+ this._updateBounds();
25551
+ for (let i = 0, ii = this.figures.length; i < ii; i++) {
25552
+ this._buildFigureFromPatch(i);
25553
+ }
25554
+ }
25555
+ this._updateBounds();
25556
+ this._packData();
25557
+ }
25558
+ _decodeType4Shading(reader) {
25559
+ const coords = this.coords;
25560
+ const colors = this.colors;
25561
+ const operators = [];
25562
+ const ps = [];
25563
+ let verticesLeft = 0;
25564
+ while (reader.hasData) {
25565
+ const f = reader.readFlag();
25566
+ const coord = reader.readCoordinate();
25567
+ const color = reader.readComponents();
25568
+ if (verticesLeft === 0) {
25569
+ if (!(0 <= f && f <= 2)) {
25570
+ throw new FormatError("Unknown type4 flag");
25571
+ }
25572
+ switch (f) {
25573
+ case 0:
25574
+ verticesLeft = 3;
25575
+ break;
25576
+ case 1:
25577
+ ps.push(ps.at(-2), ps.at(-1));
25578
+ verticesLeft = 1;
25579
+ break;
25580
+ case 2:
25581
+ ps.push(ps.at(-3), ps.at(-1));
25582
+ verticesLeft = 1;
25583
+ break;
25584
+ }
25585
+ operators.push(f);
25586
+ }
25587
+ ps.push(coords.length);
25588
+ coords.push(coord);
25589
+ colors.push(color);
25590
+ verticesLeft--;
25591
+ reader.align();
25592
+ }
25593
+ this.figures.push({
25594
+ type: MeshFigureType.TRIANGLES,
25595
+ coords: new Int32Array(ps),
25596
+ colors: new Int32Array(ps)
25597
+ });
25598
+ }
25599
+ _decodeType5Shading(reader, verticesPerRow) {
25600
+ const coords = this.coords;
25601
+ const colors = this.colors;
25602
+ const ps = [];
25603
+ while (reader.hasData) {
25604
+ const coord = reader.readCoordinate();
25605
+ const color = reader.readComponents();
25606
+ ps.push(coords.length);
25607
+ coords.push(coord);
25608
+ colors.push(color);
25609
+ }
25610
+ this.figures.push({
25611
+ type: MeshFigureType.LATTICE,
25612
+ coords: new Int32Array(ps),
25613
+ colors: new Int32Array(ps),
25614
+ verticesPerRow
25615
+ });
25616
+ }
25617
+ _decodeType6Shading(reader) {
25618
+ const coords = this.coords;
25619
+ const colors = this.colors;
25620
+ const ps = new Int32Array(16);
25621
+ const cs = new Int32Array(4);
25622
+ while (reader.hasData) {
25623
+ const f = reader.readFlag();
25624
+ if (!(0 <= f && f <= 3)) {
25625
+ throw new FormatError("Unknown type6 flag");
25626
+ }
25627
+ const pi = coords.length;
25628
+ for (let i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) {
25629
+ coords.push(reader.readCoordinate());
25630
+ }
25631
+ const ci = colors.length;
25632
+ for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
25633
+ colors.push(reader.readComponents());
25634
+ }
25635
+ let tmp1, tmp2, tmp3, tmp4;
25636
+ switch (f) {
25637
+ // prettier-ignore
25638
+ case 0:
25639
+ ps[12] = pi + 3;
25640
+ ps[13] = pi + 4;
25641
+ ps[14] = pi + 5;
25642
+ ps[15] = pi + 6;
25643
+ ps[8] = pi + 2;
25644
+ ps[11] = pi + 7;
25645
+ ps[4] = pi + 1;
25646
+ ps[7] = pi + 8;
25647
+ ps[0] = pi;
25648
+ ps[1] = pi + 11;
25649
+ ps[2] = pi + 10;
25650
+ ps[3] = pi + 9;
25651
+ cs[2] = ci + 1;
25652
+ cs[3] = ci + 2;
25653
+ cs[0] = ci;
25654
+ cs[1] = ci + 3;
25655
+ break;
25656
+ // prettier-ignore
25657
+ case 1:
25658
+ tmp1 = ps[12];
25659
+ tmp2 = ps[13];
25660
+ tmp3 = ps[14];
25661
+ tmp4 = ps[15];
25662
+ ps[12] = tmp4;
25663
+ ps[13] = pi + 0;
25664
+ ps[14] = pi + 1;
25665
+ ps[15] = pi + 2;
25666
+ ps[8] = tmp3;
25667
+ ps[11] = pi + 3;
25668
+ ps[4] = tmp2;
25669
+ ps[7] = pi + 4;
25670
+ ps[0] = tmp1;
25671
+ ps[1] = pi + 7;
25672
+ ps[2] = pi + 6;
25673
+ ps[3] = pi + 5;
25674
+ tmp1 = cs[2];
25675
+ tmp2 = cs[3];
25676
+ cs[2] = tmp2;
25677
+ cs[3] = ci;
25678
+ cs[0] = tmp1;
25679
+ cs[1] = ci + 1;
25680
+ break;
25681
+ // prettier-ignore
25682
+ case 2:
25683
+ tmp1 = ps[15];
25684
+ tmp2 = ps[11];
25685
+ ps[12] = ps[3];
25686
+ ps[13] = pi + 0;
25687
+ ps[14] = pi + 1;
25688
+ ps[15] = pi + 2;
25689
+ ps[8] = ps[7];
25690
+ ps[11] = pi + 3;
25691
+ ps[4] = tmp2;
25692
+ ps[7] = pi + 4;
25693
+ ps[0] = tmp1;
25694
+ ps[1] = pi + 7;
25695
+ ps[2] = pi + 6;
25696
+ ps[3] = pi + 5;
25697
+ tmp1 = cs[3];
25698
+ cs[2] = cs[1];
25699
+ cs[3] = ci;
25700
+ cs[0] = tmp1;
25701
+ cs[1] = ci + 1;
25702
+ break;
25703
+ // prettier-ignore
25704
+ case 3:
25705
+ ps[12] = ps[0];
25706
+ ps[13] = pi + 0;
25707
+ ps[14] = pi + 1;
25708
+ ps[15] = pi + 2;
25709
+ ps[8] = ps[1];
25710
+ ps[11] = pi + 3;
25711
+ ps[4] = ps[2];
25712
+ ps[7] = pi + 4;
25713
+ ps[0] = ps[3];
25714
+ ps[1] = pi + 7;
25715
+ ps[2] = pi + 6;
25716
+ ps[3] = pi + 5;
25717
+ cs[2] = cs[0];
25718
+ cs[3] = ci;
25719
+ cs[0] = cs[1];
25720
+ cs[1] = ci + 1;
25721
+ break;
25722
+ }
25723
+ ps[5] = coords.length;
25724
+ coords.push([
25725
+ (-4 * coords[ps[0]][0] - coords[ps[15]][0] + 6 * (coords[ps[4]][0] + coords[ps[1]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9,
25726
+ (-4 * coords[ps[0]][1] - coords[ps[15]][1] + 6 * (coords[ps[4]][1] + coords[ps[1]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9
25727
+ ]);
25728
+ ps[6] = coords.length;
25729
+ coords.push([
25730
+ (-4 * coords[ps[3]][0] - coords[ps[12]][0] + 6 * (coords[ps[2]][0] + coords[ps[7]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9,
25731
+ (-4 * coords[ps[3]][1] - coords[ps[12]][1] + 6 * (coords[ps[2]][1] + coords[ps[7]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9
25732
+ ]);
25733
+ ps[9] = coords.length;
25734
+ coords.push([
25735
+ (-4 * coords[ps[12]][0] - coords[ps[3]][0] + 6 * (coords[ps[8]][0] + coords[ps[13]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9,
25736
+ (-4 * coords[ps[12]][1] - coords[ps[3]][1] + 6 * (coords[ps[8]][1] + coords[ps[13]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9
25737
+ ]);
25738
+ ps[10] = coords.length;
25739
+ coords.push([
25740
+ (-4 * coords[ps[15]][0] - coords[ps[0]][0] + 6 * (coords[ps[11]][0] + coords[ps[14]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9,
25741
+ (-4 * coords[ps[15]][1] - coords[ps[0]][1] + 6 * (coords[ps[11]][1] + coords[ps[14]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9
25742
+ ]);
25743
+ this.figures.push({
25744
+ type: MeshFigureType.PATCH,
25745
+ coords: new Int32Array(ps),
25746
+ // making copies of ps and cs
25747
+ colors: new Int32Array(cs)
25748
+ });
25749
+ }
25750
+ }
25751
+ _decodeType7Shading(reader) {
25752
+ const coords = this.coords;
25753
+ const colors = this.colors;
25754
+ const ps = new Int32Array(16);
25755
+ const cs = new Int32Array(4);
25756
+ while (reader.hasData) {
25757
+ const f = reader.readFlag();
25758
+ if (!(0 <= f && f <= 3)) {
25759
+ throw new FormatError("Unknown type7 flag");
25760
+ }
25761
+ const pi = coords.length;
25762
+ for (let i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) {
25763
+ coords.push(reader.readCoordinate());
25764
+ }
25765
+ const ci = colors.length;
25766
+ for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
25767
+ colors.push(reader.readComponents());
25768
+ }
25769
+ let tmp1, tmp2, tmp3, tmp4;
25770
+ switch (f) {
25771
+ // prettier-ignore
25772
+ case 0:
25773
+ ps[12] = pi + 3;
25774
+ ps[13] = pi + 4;
25775
+ ps[14] = pi + 5;
25776
+ ps[15] = pi + 6;
25777
+ ps[8] = pi + 2;
25778
+ ps[9] = pi + 13;
25779
+ ps[10] = pi + 14;
25780
+ ps[11] = pi + 7;
25781
+ ps[4] = pi + 1;
25782
+ ps[5] = pi + 12;
25783
+ ps[6] = pi + 15;
25784
+ ps[7] = pi + 8;
25785
+ ps[0] = pi;
25786
+ ps[1] = pi + 11;
25787
+ ps[2] = pi + 10;
25788
+ ps[3] = pi + 9;
25789
+ cs[2] = ci + 1;
25790
+ cs[3] = ci + 2;
25791
+ cs[0] = ci;
25792
+ cs[1] = ci + 3;
25793
+ break;
25794
+ // prettier-ignore
25795
+ case 1:
25796
+ tmp1 = ps[12];
25797
+ tmp2 = ps[13];
25798
+ tmp3 = ps[14];
25799
+ tmp4 = ps[15];
25800
+ ps[12] = tmp4;
25801
+ ps[13] = pi + 0;
25802
+ ps[14] = pi + 1;
25803
+ ps[15] = pi + 2;
25804
+ ps[8] = tmp3;
25805
+ ps[9] = pi + 9;
25806
+ ps[10] = pi + 10;
25807
+ ps[11] = pi + 3;
25808
+ ps[4] = tmp2;
25809
+ ps[5] = pi + 8;
25810
+ ps[6] = pi + 11;
25811
+ ps[7] = pi + 4;
25812
+ ps[0] = tmp1;
25813
+ ps[1] = pi + 7;
25814
+ ps[2] = pi + 6;
25815
+ ps[3] = pi + 5;
25816
+ tmp1 = cs[2];
25817
+ tmp2 = cs[3];
25818
+ cs[2] = tmp2;
25819
+ cs[3] = ci;
25820
+ cs[0] = tmp1;
25821
+ cs[1] = ci + 1;
25822
+ break;
25823
+ // prettier-ignore
25824
+ case 2:
25825
+ tmp1 = ps[15];
25826
+ tmp2 = ps[11];
25827
+ ps[12] = ps[3];
25828
+ ps[13] = pi + 0;
25829
+ ps[14] = pi + 1;
25830
+ ps[15] = pi + 2;
25831
+ ps[8] = ps[7];
25832
+ ps[9] = pi + 9;
25833
+ ps[10] = pi + 10;
25834
+ ps[11] = pi + 3;
25835
+ ps[4] = tmp2;
25836
+ ps[5] = pi + 8;
25837
+ ps[6] = pi + 11;
25838
+ ps[7] = pi + 4;
25839
+ ps[0] = tmp1;
25840
+ ps[1] = pi + 7;
25841
+ ps[2] = pi + 6;
25842
+ ps[3] = pi + 5;
25843
+ tmp1 = cs[3];
25844
+ cs[2] = cs[1];
25845
+ cs[3] = ci;
25846
+ cs[0] = tmp1;
25847
+ cs[1] = ci + 1;
25848
+ break;
25849
+ // prettier-ignore
25850
+ case 3:
25851
+ ps[12] = ps[0];
25852
+ ps[13] = pi + 0;
25853
+ ps[14] = pi + 1;
25854
+ ps[15] = pi + 2;
25855
+ ps[8] = ps[1];
25856
+ ps[9] = pi + 9;
25857
+ ps[10] = pi + 10;
25858
+ ps[11] = pi + 3;
25859
+ ps[4] = ps[2];
25860
+ ps[5] = pi + 8;
25861
+ ps[6] = pi + 11;
25862
+ ps[7] = pi + 4;
25863
+ ps[0] = ps[3];
25864
+ ps[1] = pi + 7;
25865
+ ps[2] = pi + 6;
25866
+ ps[3] = pi + 5;
25867
+ cs[2] = cs[0];
25868
+ cs[3] = ci;
25869
+ cs[0] = cs[1];
25870
+ cs[1] = ci + 1;
25871
+ break;
25872
+ }
25873
+ this.figures.push({
25874
+ type: MeshFigureType.PATCH,
25875
+ coords: new Int32Array(ps),
25876
+ // making copies of ps and cs
25877
+ colors: new Int32Array(cs)
25878
+ });
25879
+ }
25880
+ }
25881
+ _buildFigureFromPatch(index) {
25882
+ const figure = this.figures[index];
25883
+ assert2(
25884
+ figure.type === MeshFigureType.PATCH,
25885
+ "Unexpected patch mesh figure"
25886
+ );
25887
+ const coords = this.coords, colors = this.colors;
25888
+ const pi = figure.coords;
25889
+ const ci = figure.colors;
25890
+ const figureMinX = Math.min(
25891
+ coords[pi[0]][0],
25892
+ coords[pi[3]][0],
25893
+ coords[pi[12]][0],
25894
+ coords[pi[15]][0]
25895
+ );
25896
+ const figureMinY = Math.min(
25897
+ coords[pi[0]][1],
25898
+ coords[pi[3]][1],
25899
+ coords[pi[12]][1],
25900
+ coords[pi[15]][1]
25901
+ );
25902
+ const figureMaxX = Math.max(
25903
+ coords[pi[0]][0],
25904
+ coords[pi[3]][0],
25905
+ coords[pi[12]][0],
25906
+ coords[pi[15]][0]
25907
+ );
25908
+ const figureMaxY = Math.max(
25909
+ coords[pi[0]][1],
25910
+ coords[pi[3]][1],
25911
+ coords[pi[12]][1],
25912
+ coords[pi[15]][1]
25913
+ );
25914
+ let splitXBy = Math.ceil(
25915
+ (figureMaxX - figureMinX) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[2] - this.bounds[0])
25916
+ );
25917
+ splitXBy = MathClamp(
25918
+ splitXBy,
25919
+ _MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
25920
+ _MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT
25921
+ );
25922
+ let splitYBy = Math.ceil(
25923
+ (figureMaxY - figureMinY) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[3] - this.bounds[1])
25924
+ );
25925
+ splitYBy = MathClamp(
25926
+ splitYBy,
25927
+ _MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
25928
+ _MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT
25929
+ );
25930
+ const verticesPerRow = splitXBy + 1;
25931
+ const figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
25932
+ const figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
25933
+ let k = 0;
25934
+ const cl = new Uint8Array(3), cr = new Uint8Array(3);
25935
+ const c0 = colors[ci[0]], c1 = colors[ci[1]], c2 = colors[ci[2]], c3 = colors[ci[3]];
25936
+ const bRow = getB(splitYBy), bCol = getB(splitXBy);
25937
+ for (let row = 0; row <= splitYBy; row++) {
25938
+ cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0;
25939
+ cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0;
25940
+ cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0;
25941
+ cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0;
25942
+ cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0;
25943
+ cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0;
25944
+ for (let col = 0; col <= splitXBy; col++, k++) {
25945
+ if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) {
25946
+ continue;
25947
+ }
25948
+ let x = 0, y = 0;
25949
+ let q = 0;
25950
+ for (let i = 0; i <= 3; i++) {
25951
+ for (let j = 0; j <= 3; j++, q++) {
25952
+ const m = bRow[row][i] * bCol[col][j];
25953
+ x += coords[pi[q]][0] * m;
25954
+ y += coords[pi[q]][1] * m;
25955
+ }
25956
+ }
25957
+ figureCoords[k] = coords.length;
25958
+ coords.push([x, y]);
25959
+ figureColors[k] = colors.length;
25960
+ const newColor = new Uint8Array(3);
25961
+ newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0;
25962
+ newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0;
25963
+ newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0;
25964
+ colors.push(newColor);
25965
+ }
25966
+ }
25967
+ figureCoords[0] = pi[0];
25968
+ figureColors[0] = ci[0];
25969
+ figureCoords[splitXBy] = pi[3];
25970
+ figureColors[splitXBy] = ci[1];
25971
+ figureCoords[verticesPerRow * splitYBy] = pi[12];
25972
+ figureColors[verticesPerRow * splitYBy] = ci[2];
25973
+ figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15];
25974
+ figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
25975
+ this.figures[index] = {
25976
+ type: MeshFigureType.LATTICE,
25977
+ coords: figureCoords,
25978
+ colors: figureColors,
25979
+ verticesPerRow
25980
+ };
25981
+ }
25982
+ _updateBounds() {
25983
+ meshUpdateBounds(this);
25984
+ }
25985
+ _packData() {
25986
+ meshPackData(this);
25987
+ }
25988
+ getIR() {
25989
+ const { posData, colData, vertexCount } = buildMeshVertexData(
25990
+ this.coords,
25991
+ this.colors,
25992
+ this.figures
25993
+ );
25994
+ return [
25995
+ "Mesh",
25996
+ this.shadingType,
25997
+ posData,
25998
+ colData,
25999
+ vertexCount,
26000
+ this.bounds,
26001
+ this.bbox,
26002
+ this.background
26003
+ ];
26004
+ }
26005
+ };
22699
26006
 
22700
26007
  // src/errors.ts
22701
26008
  var PdfError = class extends Error {
@@ -25746,11 +29053,16 @@ function parseDictionaryStream(dictNode, lexer, bytes) {
25746
29053
  let streamEnd = streamStart;
25747
29054
  if (resolvedLength !== void 0 && resolvedLength >= 0 && streamStart + resolvedLength <= bytes.length) {
25748
29055
  const candidateEnd = streamStart + resolvedLength;
25749
- const tailSlice = bytes.subarray(candidateEnd, Math.min(bytes.length, candidateEnd + 32));
25750
- const tailStr = new TextDecoder("latin1").decode(tailSlice);
25751
- if (tailStr.includes("endstream")) {
29056
+ const tailLexer = new CosByteLexer(bytes, candidateEnd);
29057
+ let endToken;
29058
+ try {
29059
+ endToken = tailLexer.nextToken();
29060
+ } catch (error) {
29061
+ if (!(error instanceof PdfError) || error.code !== "E_PARSE") throw error;
29062
+ }
29063
+ if (endToken?.kind === "keyword" && endToken.value === "endstream") {
25752
29064
  rawStreamBytes = bytes.subarray(streamStart, candidateEnd);
25753
- streamEnd = candidateEnd + tailStr.indexOf("endstream") + "endstream".length;
29065
+ streamEnd = tailLexer.offset;
25754
29066
  }
25755
29067
  }
25756
29068
  if (!rawStreamBytes) {
@@ -33948,7 +37260,28 @@ var __webpack_exports__VerbosityLevel = __webpack_exports__.VerbosityLevel;
33948
37260
  var __webpack_exports__getVerbosityLevel = __webpack_exports__.getVerbosityLevel;
33949
37261
  var __webpack_exports__setVerbosityLevel = __webpack_exports__.setVerbosityLevel;
33950
37262
 
37263
+ // src/content/calibrated-color.ts
37264
+ function createCalibratedColorSpace(doc, family, parameters) {
37265
+ const dict = doc.resolveDict(parameters);
37266
+ const array = (key) => {
37267
+ const value = dict ? doc.resolveArray(dictGet(dict, key)) : void 0;
37268
+ return value?.items.map((item) => {
37269
+ const number = doc.resolve(item);
37270
+ return number?.kind === "number" ? number.value : 0;
37271
+ });
37272
+ };
37273
+ const whitePoint = array("WhitePoint") ?? [0.95047, 1, 1.08883];
37274
+ const blackPoint = array("BlackPoint");
37275
+ if (family === "CalGray") {
37276
+ const gamma = dict ? doc.resolve(dictGet(dict, "Gamma")) : void 0;
37277
+ return new CalGrayCS(whitePoint, blackPoint, gamma?.kind === "number" ? gamma.value : void 0);
37278
+ }
37279
+ if (family === "CalRGB") return new CalRGBCS(whitePoint, blackPoint, array("Gamma"), array("Matrix"));
37280
+ return new LabCS(whitePoint, blackPoint, array("Range"));
37281
+ }
37282
+
33951
37283
  // src/extract/images.ts
37284
+ var cmykColorSpace = new DeviceCmykCS();
33952
37285
  function collectPageLeaves(doc, node, inheritedResources, out = [], visited = /* @__PURE__ */ new Set()) {
33953
37286
  if (!node) return out;
33954
37287
  if (node.kind === "ref") {
@@ -34037,7 +37370,7 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
34037
37370
  palette = lookupNode.bytes;
34038
37371
  }
34039
37372
  let resolvedBaseComp = baseInfo.components;
34040
- if (palette && (baseInfo.isLab || baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calRgbGamma !== void 0 || baseInfo.calGrayGamma !== void 0)) {
37373
+ if (palette && (baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calibrated !== void 0)) {
34041
37374
  const numEntries = Math.max(1, Math.min(hival + 1, Math.floor(palette.length / Math.max(1, baseInfo.components))));
34042
37375
  const rgbaPal = decodeSamplesToRgba(palette, numEntries, 1, 8, baseInfo);
34043
37376
  const rgbPal = new Uint8Array(numEntries * 3);
@@ -34067,74 +37400,21 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
34067
37400
  }
34068
37401
  return { colorSpace: "rgb", colorSpaceLabel: "icc", components: 3 };
34069
37402
  }
34070
- if (kindName === "CalGray") {
34071
- const calDict = doc.resolveDict(resolved.items[1]);
34072
- const gammaNode = calDict ? doc.resolve(dictGet(calDict, "Gamma")) : void 0;
34073
- const gamma = gammaNode?.kind === "number" && gammaNode.value > 0 ? gammaNode.value : 1;
34074
- return { colorSpace: "gray", colorSpaceLabel: "cal-gray", components: 1, calGrayGamma: gamma };
34075
- }
34076
- if (kindName === "CalRGB") {
34077
- const calDict = doc.resolveDict(resolved.items[1]);
34078
- const gammaArr = calDict ? doc.resolveArray(dictGet(calDict, "Gamma")) : void 0;
34079
- let calRgbGamma = [1, 1, 1];
34080
- if (gammaArr && gammaArr.items.length >= 3) {
34081
- const gNums = gammaArr.items.slice(0, 3).map((it) => {
34082
- const r = doc.resolve(it);
34083
- return r?.kind === "number" && r.value > 0 ? r.value : 1;
34084
- });
34085
- calRgbGamma = [gNums[0], gNums[1], gNums[2]];
34086
- }
34087
- const matArr = calDict ? doc.resolveArray(dictGet(calDict, "Matrix")) : void 0;
34088
- let calRgbMatrix;
34089
- if (matArr && matArr.items.length >= 9) {
34090
- calRgbMatrix = matArr.items.slice(0, 9).map((it) => {
34091
- const r = doc.resolve(it);
34092
- return r?.kind === "number" ? r.value : 0;
34093
- });
34094
- }
37403
+ if (kindName === "CalGray" || kindName === "CalRGB" || kindName === "Lab") {
37404
+ const calibrated = createCalibratedColorSpace(doc, kindName, resolved.items[1]);
34095
37405
  return {
34096
- colorSpace: "rgb",
34097
- colorSpaceLabel: "cal-rgb",
34098
- components: 3,
34099
- calRgbGamma,
34100
- calRgbMatrix
37406
+ colorSpace: kindName === "CalGray" ? "gray" : "rgb",
37407
+ colorSpaceLabel: kindName === "CalGray" ? "cal-gray" : kindName === "CalRGB" ? "cal-rgb" : "lab",
37408
+ components: kindName === "CalGray" ? 1 : 3,
37409
+ calibrated
34101
37410
  };
34102
37411
  }
34103
- if (kindName === "Lab") {
34104
- const labDict = doc.resolveDict(resolved.items[1]);
34105
- const rangeArr = labDict ? doc.resolveArray(dictGet(labDict, "Range")) : void 0;
34106
- let labRange = [-100, 100, -100, 100];
34107
- if (rangeArr && rangeArr.items.length >= 4) {
34108
- const nums = rangeArr.items.slice(0, 4).map((it) => {
34109
- const r = doc.resolve(it);
34110
- return r?.kind === "number" ? r.value : 0;
34111
- });
34112
- labRange = [nums[0], nums[1], nums[2], nums[3]];
34113
- }
34114
- return { colorSpace: "rgb", colorSpaceLabel: "lab", components: 3, isLab: true, labRange };
34115
- }
34116
37412
  if (kindName === "Separation" || kindName === "DeviceN") {
34117
37413
  const isDevN = kindName === "DeviceN";
34118
37414
  const namesArr = isDevN ? doc.resolveArray(resolved.items[1]) : void 0;
34119
37415
  const devNComponents = isDevN && namesArr ? Math.max(1, namesArr.items.length) : 1;
34120
37416
  const altInfo = resolveColorSpaceInfo(doc, resolved.items[2], resourcesDict);
34121
37417
  const altSpace = altInfo.colorSpace === "cmyk" ? "cmyk" : altInfo.colorSpace === "gray" ? "gray" : "rgb";
34122
- const fnResolved = doc.resolve(resolved.items[3]);
34123
- const fnDict = fnResolved?.kind === "stream" ? fnResolved.dict : fnResolved?.kind === "dict" ? fnResolved : void 0;
34124
- const ftNode = fnDict ? doc.resolve(dictGet(fnDict, "FunctionType")) : void 0;
34125
- const tintFunctionType = ftNode?.kind === "number" ? ftNode.value : 2;
34126
- const c0Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C0")) : void 0;
34127
- const c1Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C1")) : void 0;
34128
- const nNode = fnDict ? doc.resolve(dictGet(fnDict, "N")) : void 0;
34129
- const c0 = c0Arr ? c0Arr.items.map((it) => {
34130
- const r = doc.resolve(it);
34131
- return r?.kind === "number" ? r.value : 0;
34132
- }) : altSpace === "cmyk" ? [0, 0, 0, 0] : altSpace === "gray" ? [1] : [1, 1, 1];
34133
- const c1 = c1Arr ? c1Arr.items.map((it) => {
34134
- const r = doc.resolve(it);
34135
- return r?.kind === "number" ? r.value : 0;
34136
- }) : altSpace === "cmyk" ? [0, 0, 0, 1] : altSpace === "gray" ? [0] : [0, 0, 0];
34137
- const sepN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
34138
37418
  return {
34139
37419
  colorSpace: altSpace,
34140
37420
  colorSpaceLabel: isDevN ? "devn" : "sep",
@@ -34142,12 +37422,9 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
34142
37422
  isSeparation: !isDevN,
34143
37423
  isDeviceN: isDevN,
34144
37424
  separationAltSpace: altSpace,
34145
- separationC0: c0,
34146
- separationC1: c1,
34147
- separationN: sepN,
37425
+ alternateCalibrated: altInfo.calibrated,
34148
37426
  tintFunctionDoc: doc,
34149
- tintFunctionNode: resolved.items[3],
34150
- tintFunctionType
37427
+ tintFunctionNode: resolved.items[3]
34151
37428
  };
34152
37429
  }
34153
37430
  }
@@ -34305,141 +37582,55 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
34305
37582
  const rgba = new Uint8Array(width * height * 4);
34306
37583
  const pixelCount = width * height;
34307
37584
  if (csInfo.isSeparation || csInfo.isDeviceN) {
34308
- const c0 = csInfo.separationC0 ?? [1, 1, 1];
34309
- const c1 = csInfo.separationC1 ?? [0, 0, 0];
34310
- const expN = csInfo.separationN ?? 1;
34311
37585
  const alt = csInfo.separationAltSpace ?? "rgb";
34312
37586
  const numCh = Math.max(1, csInfo.components);
34313
37587
  const step = bpc === 16 ? 2 : 1;
34314
- const useGenericTintFn = csInfo.tintFunctionDoc !== void 0 && csInfo.tintFunctionNode !== void 0 && (csInfo.tintFunctionType === 0 || csInfo.tintFunctionType === 3 || csInfo.tintFunctionType === 4);
34315
37588
  for (let p = 0; p < pixelCount; p++) {
34316
37589
  const chVals = [];
34317
- let wSum = 0;
34318
37590
  for (let ch3 = 0; ch3 < numCh; ch3++) {
34319
37591
  const sRaw = (rawSamples[(p * numCh + ch3) * step] ?? 0) / 255;
34320
- const tRemapped = remapUnitSampleWithDecode(sRaw, ch3, decodePairs);
34321
- chVals.push(tRemapped);
34322
- wSum += Math.pow(Math.max(0, Math.min(1, tRemapped)), expN);
34323
- }
34324
- if (useGenericTintFn) {
34325
- const outComps = evalShadingFunctionToComponents(
34326
- csInfo.tintFunctionDoc,
34327
- csInfo.tintFunctionNode,
34328
- chVals
34329
- );
34330
- if (alt === "cmyk") {
34331
- const c = outComps[0] ?? 0;
34332
- const m = outComps[1] ?? 0;
34333
- const y = outComps[2] ?? 0;
34334
- const k = outComps[3] ?? 0;
34335
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, (1 - c) * (1 - k))) * 255);
34336
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, (1 - m) * (1 - k))) * 255);
34337
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, (1 - y) * (1 - k))) * 255);
34338
- } else if (alt === "gray") {
34339
- const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
34340
- rgba[p * 4] = gByte;
34341
- rgba[p * 4 + 1] = gByte;
34342
- rgba[p * 4 + 2] = gByte;
34343
- } else {
34344
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
34345
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
34346
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
34347
- }
34348
- rgba[p * 4 + 3] = 255;
34349
- continue;
37592
+ chVals.push(remapUnitSampleWithDecode(sRaw, ch3, decodePairs));
34350
37593
  }
34351
- const w = Math.max(0, Math.min(1, wSum));
34352
- if (alt === "cmyk") {
34353
- const c = (c0[0] ?? 0) + w * ((c1[0] ?? 0) - (c0[0] ?? 0));
34354
- const m = (c0[1] ?? 0) + w * ((c1[1] ?? 0) - (c0[1] ?? 0));
34355
- const y = (c0[2] ?? 0) + w * ((c1[2] ?? 0) - (c0[2] ?? 0));
34356
- const k = (c0[3] ?? 0) + w * ((c1[3] ?? 1) - (c0[3] ?? 0));
34357
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, (1 - c) * (1 - k))) * 255);
34358
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, (1 - m) * (1 - k))) * 255);
34359
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, (1 - y) * (1 - k))) * 255);
37594
+ const outComps = evalShadingFunctionToComponents(
37595
+ csInfo.tintFunctionDoc,
37596
+ csInfo.tintFunctionNode,
37597
+ chVals
37598
+ );
37599
+ if (csInfo.alternateCalibrated) {
37600
+ rgba.set(csInfo.alternateCalibrated.getRgb(outComps, 0), p * 4);
37601
+ } else if (alt === "cmyk") {
37602
+ rgba.set(cmykColorSpace.getRgb([outComps[0] ?? 0, outComps[1] ?? 0, outComps[2] ?? 0, outComps[3] ?? 0], 0), p * 4);
34360
37603
  } else if (alt === "gray") {
34361
- const gVal = (c0[0] ?? 1) + w * ((c1[0] ?? 0) - (c0[0] ?? 1));
34362
- const gByte = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
37604
+ const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
34363
37605
  rgba[p * 4] = gByte;
34364
37606
  rgba[p * 4 + 1] = gByte;
34365
37607
  rgba[p * 4 + 2] = gByte;
34366
37608
  } else {
34367
- const rVal = (c0[0] ?? 1) + w * ((c1[0] ?? 0) - (c0[0] ?? 1));
34368
- const gVal = (c0[1] ?? 1) + w * ((c1[1] ?? 0) - (c0[1] ?? 1));
34369
- const bVal = (c0[2] ?? 1) + w * ((c1[2] ?? 0) - (c0[2] ?? 1));
34370
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, rVal)) * 255);
34371
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
34372
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, bVal)) * 255);
37609
+ rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
37610
+ rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
37611
+ rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
34373
37612
  }
34374
37613
  rgba[p * 4 + 3] = 255;
34375
37614
  }
34376
- } else if (csInfo.isLab) {
34377
- const [amin, amax, bmin, bmax] = csInfo.labRange ?? [-100, 100, -100, 100];
34378
- const invF = (t) => t > 6 / 29 ? t * t * t : 3 * (6 / 29) * (6 / 29) * (t - 4 / 29);
34379
- const toSrgb = (u) => {
34380
- const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
34381
- return Math.round(Math.max(0, Math.min(1, c)) * 255);
34382
- };
37615
+ } else if (csInfo.calibrated?.name === "Lab") {
37616
+ const { amin, amax, bmin, bmax } = csInfo.calibrated;
37617
+ const step = bpc === 16 ? 2 : 1;
34383
37618
  for (let p = 0; p < pixelCount; p++) {
34384
- const s0 = (rawSamples[p * 3] ?? 0) / 255;
34385
- const s1 = (rawSamples[p * 3 + 1] ?? 128) / 255;
34386
- const s2 = (rawSamples[p * 3 + 2] ?? 128) / 255;
34387
- const L = s0 * 100;
34388
- if (L <= 0.01) {
34389
- rgba[p * 4] = 0;
34390
- rgba[p * 4 + 1] = 0;
34391
- rgba[p * 4 + 2] = 0;
34392
- rgba[p * 4 + 3] = 255;
34393
- continue;
34394
- }
34395
- const a = amin + s1 * (amax - amin);
34396
- const b = bmin + s2 * (bmax - bmin);
34397
- const fy = (L + 16) / 116;
34398
- const fx = fy + a / 500;
34399
- const fz = fy - b / 200;
34400
- const X = 0.95047 * invF(fx);
34401
- const Y = 1 * invF(fy);
34402
- const Z = 1.08883 * invF(fz);
34403
- const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
34404
- const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
34405
- const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
34406
- rgba[p * 4] = toSrgb(linR);
34407
- rgba[p * 4 + 1] = toSrgb(linG);
34408
- rgba[p * 4 + 2] = toSrgb(linB);
37619
+ const L = (rawSamples[p * 3 * step] ?? 0) / 255 * 100;
37620
+ const a = amin + (rawSamples[(p * 3 + 1) * step] ?? 128) / 255 * (amax - amin);
37621
+ const b = bmin + (rawSamples[(p * 3 + 2) * step] ?? 128) / 255 * (bmax - bmin);
37622
+ rgba.set(csInfo.calibrated.getRgb([L, a, b], 0), p * 4);
34409
37623
  rgba[p * 4 + 3] = 255;
34410
37624
  }
34411
37625
  } else if (csInfo.colorSpace === "rgb") {
34412
- const hasCalRgb = Boolean(csInfo.calRgbGamma || csInfo.calRgbMatrix);
34413
- const toSrgbByte = (u) => {
34414
- const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
34415
- return Math.round(Math.max(0, Math.min(1, c)) * 255);
34416
- };
34417
37626
  const writeRgbPixel = (p, rByte, gByte, bByte) => {
34418
- let rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
34419
- let gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
34420
- let bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
34421
- if (hasCalRgb) {
34422
- const [gr, gg, gb] = csInfo.calRgbGamma ?? [1, 1, 1];
34423
- const ag = Math.pow(rU, gr);
34424
- const bg = Math.pow(gU, gg);
34425
- const cg = Math.pow(bU, gb);
34426
- if (csInfo.calRgbMatrix && csInfo.calRgbMatrix.length >= 9) {
34427
- const m = csInfo.calRgbMatrix;
34428
- const X = m[0] * ag + m[3] * bg + m[6] * cg;
34429
- const Y = m[1] * ag + m[4] * bg + m[7] * cg;
34430
- const Z = m[2] * ag + m[5] * bg + m[8] * cg;
34431
- const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
34432
- const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
34433
- const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
34434
- rgba[p * 4] = toSrgbByte(linR);
34435
- rgba[p * 4 + 1] = toSrgbByte(linG);
34436
- rgba[p * 4 + 2] = toSrgbByte(linB);
34437
- rgba[p * 4 + 3] = 255;
34438
- return;
34439
- }
34440
- rU = ag;
34441
- gU = bg;
34442
- bU = cg;
37627
+ const rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
37628
+ const gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
37629
+ const bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
37630
+ if (csInfo.calibrated) {
37631
+ rgba.set(csInfo.calibrated.getRgb([rU, gU, bU], 0), p * 4);
37632
+ rgba[p * 4 + 3] = 255;
37633
+ return;
34443
37634
  }
34444
37635
  rgba[p * 4] = Math.round(rU * 255);
34445
37636
  rgba[p * 4 + 1] = Math.round(gU * 255);
@@ -34459,10 +37650,11 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
34459
37650
  }
34460
37651
  } else if (csInfo.colorSpace === "gray") {
34461
37652
  const writeGrayPixel = (p, gByte) => {
34462
- let gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
34463
- if (csInfo.calGrayGamma && csInfo.calGrayGamma !== 1) {
34464
- const lin = Math.pow(gU, csInfo.calGrayGamma);
34465
- gU = lin <= 31308e-7 ? 12.92 * lin : 1.055 * Math.pow(lin, 1 / 2.4) - 0.055;
37653
+ const gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
37654
+ if (csInfo.calibrated) {
37655
+ rgba.set(csInfo.calibrated.getRgb([gU], 0), p * 4);
37656
+ rgba[p * 4 + 3] = 255;
37657
+ return;
34466
37658
  }
34467
37659
  const outG = Math.round(Math.max(0, Math.min(1, gU)) * 255);
34468
37660
  rgba[p * 4] = outG;
@@ -34518,9 +37710,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
34518
37710
  const m = remapUnitSampleWithDecode((rawSamples[p * stride + chStep] ?? 0) / 255, 1, decodePairs);
34519
37711
  const y = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 2] ?? 0) / 255, 2, decodePairs);
34520
37712
  const k = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 3] ?? 0) / 255, 3, decodePairs);
34521
- rgba[p * 4] = Math.round((1 - c) * (1 - k) * 255);
34522
- rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
34523
- rgba[p * 4 + 2] = Math.round((1 - y) * (1 - k) * 255);
37713
+ rgba.set(cmykColorSpace.getRgb([c, m, y, k], 0), p * 4);
34524
37714
  rgba[p * 4 + 3] = 255;
34525
37715
  }
34526
37716
  } else if (csInfo.colorSpace === "index") {
@@ -34558,9 +37748,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
34558
37748
  const m = pal[idx * 4 + 1] / 255;
34559
37749
  const yel = pal[idx * 4 + 2] / 255;
34560
37750
  const k = pal[idx * 4 + 3] / 255;
34561
- rgba[p * 4] = Math.round((1 - c) * (1 - k) * 255);
34562
- rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
34563
- rgba[p * 4 + 2] = Math.round((1 - yel) * (1 - k) * 255);
37751
+ rgba.set(cmykColorSpace.getRgb([c, m, yel, k], 0), p * 4);
34564
37752
  } else {
34565
37753
  rgba[p * 4] = pal[idx * baseComp];
34566
37754
  rgba[p * 4 + 1] = pal[idx * baseComp + 1];
@@ -35114,6 +38302,7 @@ function extractDocumentImages(doc, options = {}) {
35114
38302
  }
35115
38303
 
35116
38304
  // src/content/evaluator.ts
38305
+ var cmykColorSpace2 = new DeviceCmykCS();
35117
38306
  function multiplyMatrices(m1, m2) {
35118
38307
  return [
35119
38308
  m1[0] * m2[0] + m1[1] * m2[2],
@@ -35330,193 +38519,7 @@ function resolvePageFonts(doc, resourcesDict) {
35330
38519
  }
35331
38520
  return fonts;
35332
38521
  }
35333
- function evaluateType4PostScriptTokens(tokens, initialStack) {
35334
- const stack = [...initialStack];
35335
- const runRange = (start, end) => {
35336
- let i = start;
35337
- while (i < end) {
35338
- const tok = tokens[i];
35339
- if (tok === "{") {
35340
- let depth = 1;
35341
- let j = i + 1;
35342
- while (j < end && depth > 0) {
35343
- if (tokens[j] === "{") depth++;
35344
- else if (tokens[j] === "}") depth--;
35345
- j++;
35346
- }
35347
- const blockStart = i + 1;
35348
- const blockEnd = j - 1;
35349
- if (j < end && tokens[j] === "{") {
35350
- let depth2 = 1;
35351
- let k = j + 1;
35352
- while (k < end && depth2 > 0) {
35353
- if (tokens[k] === "{") depth2++;
35354
- else if (tokens[k] === "}") depth2--;
35355
- k++;
35356
- }
35357
- if (k < end && tokens[k] === "ifelse") {
35358
- const cond = stack.pop() ?? 0;
35359
- if (cond !== 0) runRange(blockStart, blockEnd);
35360
- else runRange(j + 1, k - 1);
35361
- i = k + 1;
35362
- continue;
35363
- }
35364
- }
35365
- if (j < end && tokens[j] === "if") {
35366
- const cond = stack.pop() ?? 0;
35367
- if (cond !== 0) runRange(blockStart, blockEnd);
35368
- i = j + 1;
35369
- continue;
35370
- }
35371
- runRange(blockStart, blockEnd);
35372
- i = j;
35373
- continue;
35374
- }
35375
- if (tok === "}") {
35376
- i++;
35377
- continue;
35378
- }
35379
- const numVal2 = Number(tok);
35380
- if (tok.length > 0 && !Number.isNaN(numVal2)) {
35381
- stack.push(numVal2);
35382
- } else if (tok === "true") {
35383
- stack.push(1);
35384
- } else if (tok === "false") {
35385
- stack.push(0);
35386
- } else if (tok === "add") {
35387
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35388
- stack.push(a + b);
35389
- } else if (tok === "sub") {
35390
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35391
- stack.push(a - b);
35392
- } else if (tok === "mul") {
35393
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35394
- stack.push(a * b);
35395
- } else if (tok === "div") {
35396
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
35397
- stack.push(Math.abs(b) > 1e-12 ? a / b : 0);
35398
- } else if (tok === "idiv") {
35399
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
35400
- stack.push(Math.abs(b) > 1e-12 ? Math.trunc(a / b) : 0);
35401
- } else if (tok === "mod") {
35402
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
35403
- stack.push(Math.abs(b) > 1e-12 ? a % b : 0);
35404
- } else if (tok === "neg") {
35405
- stack.push(-(stack.pop() ?? 0));
35406
- } else if (tok === "abs") {
35407
- stack.push(Math.abs(stack.pop() ?? 0));
35408
- } else if (tok === "ceiling") {
35409
- stack.push(Math.ceil(stack.pop() ?? 0));
35410
- } else if (tok === "floor") {
35411
- stack.push(Math.floor(stack.pop() ?? 0));
35412
- } else if (tok === "round") {
35413
- stack.push(Math.round(stack.pop() ?? 0));
35414
- } else if (tok === "truncate" || tok === "cvi") {
35415
- stack.push(Math.trunc(stack.pop() ?? 0));
35416
- } else if (tok === "sqrt") {
35417
- stack.push(Math.sqrt(Math.max(0, stack.pop() ?? 0)));
35418
- } else if (tok === "sin") {
35419
- stack.push(Math.sin((stack.pop() ?? 0) * Math.PI / 180));
35420
- } else if (tok === "cos") {
35421
- stack.push(Math.cos((stack.pop() ?? 0) * Math.PI / 180));
35422
- } else if (tok === "atan") {
35423
- const dx = stack.pop() ?? 1, dy = stack.pop() ?? 0;
35424
- let deg = Math.atan2(dy, dx) * 180 / Math.PI;
35425
- if (deg < 0) deg += 360;
35426
- stack.push(deg);
35427
- } else if (tok === "exp") {
35428
- const exp = stack.pop() ?? 1, base = stack.pop() ?? 0;
35429
- stack.push(Math.pow(base, exp));
35430
- } else if (tok === "ln") {
35431
- stack.push(Math.log(Math.max(1e-12, stack.pop() ?? 1)));
35432
- } else if (tok === "log") {
35433
- stack.push(Math.log10(Math.max(1e-12, stack.pop() ?? 1)));
35434
- } else if (tok === "dup") {
35435
- if (stack.length > 0) stack.push(stack[stack.length - 1]);
35436
- } else if (tok === "exch") {
35437
- if (stack.length >= 2) {
35438
- const b = stack.pop(), a = stack.pop();
35439
- stack.push(b, a);
35440
- }
35441
- } else if (tok === "pop") {
35442
- stack.pop();
35443
- } else if (tok === "copy") {
35444
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
35445
- const slice = stack.slice(Math.max(0, stack.length - n));
35446
- stack.push(...slice);
35447
- } else if (tok === "index") {
35448
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
35449
- const idx = stack.length - 1 - n;
35450
- if (idx >= 0 && idx < stack.length) stack.push(stack[idx]);
35451
- } else if (tok === "roll") {
35452
- const jShift = Math.trunc(stack.pop() ?? 0);
35453
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
35454
- if (n > 0 && stack.length >= n) {
35455
- const sub = stack.splice(stack.length - n, n);
35456
- const modShift = (jShift % n + n) % n;
35457
- const rolled = [...sub.slice(n - modShift), ...sub.slice(0, n - modShift)];
35458
- stack.push(...rolled);
35459
- }
35460
- } else if (tok === "eq") {
35461
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35462
- stack.push(Math.abs(a - b) < 1e-9 ? 1 : 0);
35463
- } else if (tok === "ne") {
35464
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35465
- stack.push(Math.abs(a - b) >= 1e-9 ? 1 : 0);
35466
- } else if (tok === "gt") {
35467
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35468
- stack.push(a > b ? 1 : 0);
35469
- } else if (tok === "ge") {
35470
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35471
- stack.push(a >= b ? 1 : 0);
35472
- } else if (tok === "lt") {
35473
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35474
- stack.push(a < b ? 1 : 0);
35475
- } else if (tok === "le") {
35476
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35477
- stack.push(a <= b ? 1 : 0);
35478
- } else if (tok === "and") {
35479
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35480
- stack.push(a !== 0 && b !== 0 ? 1 : 0);
35481
- } else if (tok === "or") {
35482
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35483
- stack.push(a !== 0 || b !== 0 ? 1 : 0);
35484
- } else if (tok === "not") {
35485
- const a = stack.pop() ?? 0;
35486
- stack.push(a === 0 ? 1 : 0);
35487
- }
35488
- i++;
35489
- }
35490
- };
35491
- runRange(0, tokens.length);
35492
- return stack;
35493
- }
35494
- function tokenizePostScriptCode(bytes) {
35495
- const tokens = [];
35496
- let cur = "";
35497
- for (let i = 0; i < bytes.length; i++) {
35498
- const ch3 = String.fromCharCode(bytes[i]);
35499
- if (ch3 === "{" || ch3 === "}") {
35500
- if (cur.length > 0) {
35501
- tokens.push(cur);
35502
- cur = "";
35503
- }
35504
- tokens.push(ch3);
35505
- } else if (ch3 === " " || ch3 === " " || ch3 === "\n" || ch3 === "\r") {
35506
- if (cur.length > 0) {
35507
- tokens.push(cur);
35508
- cur = "";
35509
- }
35510
- } else {
35511
- cur += ch3;
35512
- }
35513
- }
35514
- if (cur.length > 0) tokens.push(cur);
35515
- if (tokens[0] === "{" && tokens[tokens.length - 1] === "}") {
35516
- return tokens.slice(1, -1);
35517
- }
35518
- return tokens;
35519
- }
38522
+ var postScriptFunctions = /* @__PURE__ */ new WeakMap();
35520
38523
  function evalShadingFunctionToComponents(doc, fnNode, inputs) {
35521
38524
  const inArr = typeof inputs === "number" ? [inputs] : inputs;
35522
38525
  const t = inArr[0] ?? 0;
@@ -35563,35 +38566,50 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
35563
38566
  const decode = getNums("Decode", range);
35564
38567
  const nOut = Math.max(1, Math.floor((decode.length || range.length || 6) / 2));
35565
38568
  const mIn = Math.max(1, size.length);
35566
- let flatGridIndex = 0;
38569
+ const streamBytes = doc.decodeStream(resolved);
38570
+ let vertices = [{ index: 0, weight: 1 }];
35567
38571
  let stride = 1;
35568
38572
  for (let i = 0; i < mIn; i++) {
35569
38573
  const d02 = dom[i * 2] ?? 0;
35570
38574
  const d12 = dom[i * 2 + 1] ?? 1;
35571
- const sMax = Math.max(1, (size[i] ?? 2) - 1);
38575
+ const sMax = Math.max(0, (size[i] ?? 2) - 1);
35572
38576
  const e0 = encode[i * 2] ?? 0;
35573
38577
  const e1 = encode[i * 2 + 1] ?? sMax;
35574
38578
  const x = Math.max(d02, Math.min(d12, inArr[i] ?? 0));
35575
- const u = Math.abs(d12 - d02) > 1e-8 ? (x - d02) / (d12 - d02) : 0;
35576
- const idx = Math.round(Math.max(0, Math.min(sMax, e0 + u * (e1 - e0))));
35577
- flatGridIndex += idx * stride;
38579
+ const u = d12 === d02 ? 0 : (x - d02) / (d12 - d02);
38580
+ const e = Math.max(0, Math.min(sMax, e0 + u * (e1 - e0)));
38581
+ const low = Math.floor(e), fraction = e - low;
38582
+ const next = [];
38583
+ for (const vertex of vertices) {
38584
+ const index = vertex.index + low * stride;
38585
+ if (index * nOut * bps < streamBytes.length * 8) next.push({ index, weight: vertex.weight * (1 - fraction) });
38586
+ if (fraction && (index + stride) * nOut * bps < streamBytes.length * 8) {
38587
+ next.push({ index: index + stride, weight: vertex.weight * fraction });
38588
+ }
38589
+ }
38590
+ vertices = next;
35578
38591
  stride *= size[i] ?? 2;
35579
38592
  }
35580
- const streamBytes = doc.decodeStream(resolved);
38593
+ const maxSample = 2 ** bps - 1;
38594
+ const readSample = (index) => {
38595
+ let bitOffset = index * bps, remaining = bps, value = 0;
38596
+ while (remaining > 0) {
38597
+ const bitInByte = bitOffset % 8;
38598
+ const take = Math.min(remaining, 8 - bitInByte);
38599
+ const byte = streamBytes[Math.floor(bitOffset / 8)] ?? 0;
38600
+ value = value * 2 ** take + (byte >> 8 - bitInByte - take & (1 << take) - 1);
38601
+ bitOffset += take;
38602
+ remaining -= take;
38603
+ }
38604
+ return value / maxSample;
38605
+ };
35581
38606
  const out2 = [];
35582
- const maxSample = bps === 16 ? 65535 : 255;
35583
38607
  for (let j = 0; j < nOut; j++) {
35584
- const sampleIdx = flatGridIndex * nOut + j;
35585
- let rawVal = 0;
35586
- if (bps === 16) {
35587
- rawVal = (streamBytes[sampleIdx * 2] ?? 0) << 8 | (streamBytes[sampleIdx * 2 + 1] ?? 0);
35588
- } else {
35589
- rawVal = streamBytes[sampleIdx] ?? 0;
35590
- }
35591
- const frac = rawVal / maxSample;
38608
+ let value = 0;
38609
+ for (const vertex of vertices) value += readSample(vertex.index * nOut + j) * vertex.weight;
35592
38610
  const dec0 = decode[j * 2] ?? 0;
35593
38611
  const dec1 = decode[j * 2 + 1] ?? 1;
35594
- out2.push(dec0 + frac * (dec1 - dec0));
38612
+ out2.push(dec0 + value * (dec1 - dec0));
35595
38613
  }
35596
38614
  return clampRange(out2);
35597
38615
  }
@@ -35601,34 +38619,40 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
35601
38619
  const d12 = dom[i * 2 + 1] ?? 1;
35602
38620
  return Math.max(d02, Math.min(d12, v));
35603
38621
  });
35604
- const tokens = tokenizePostScriptCode(doc.decodeStream(resolved));
35605
- const stackOut = evaluateType4PostScriptTokens(tokens, clampedInputs);
35606
- return clampRange(stackOut);
38622
+ const source = bytesToString3(doc.decodeStream(resolved));
38623
+ let cached = postScriptFunctions.get(resolved);
38624
+ 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])) {
38625
+ cached = { source, domain: dom, range, evaluate: buildPostScriptJsFunction(source, dom, range) };
38626
+ postScriptFunctions.set(resolved, cached);
38627
+ }
38628
+ const output = [];
38629
+ cached.evaluate(clampedInputs, 0, output, 0);
38630
+ return output;
35607
38631
  }
35608
38632
  if (ft === 3) {
35609
38633
  const fnsArr = doc.resolveArray(dictGet(fnDict, "Functions"));
35610
38634
  const bounds = getNums("Bounds", []);
35611
38635
  const encode = getNums("Encode", []);
35612
38636
  if (fnsArr && fnsArr.items.length > 0) {
38637
+ const input = Math.max(dom[0] ?? 0, Math.min(dom[1] ?? 1, t));
35613
38638
  let segIdx = 0;
35614
- while (segIdx < bounds.length && t >= bounds[segIdx]) segIdx++;
38639
+ while (segIdx < bounds.length && input >= bounds[segIdx]) segIdx++;
35615
38640
  segIdx = Math.min(fnsArr.items.length - 1, segIdx);
35616
38641
  const b0 = segIdx === 0 ? dom[0] ?? 0 : bounds[segIdx - 1];
35617
38642
  const b1 = segIdx < bounds.length ? bounds[segIdx] : dom[1] ?? 1;
35618
38643
  const e0 = encode[segIdx * 2] ?? 0;
35619
38644
  const e1 = encode[segIdx * 2 + 1] ?? 1;
35620
- const localT = Math.abs(b1 - b0) > 1e-8 ? e0 + (t - b0) / (b1 - b0) * (e1 - e0) : e0;
35621
- return evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], Math.max(0, Math.min(1, localT)));
38645
+ const localT = b1 !== b0 ? e0 + (input - b0) / (b1 - b0) * (e1 - e0) : e0;
38646
+ return clampRange(evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], localT));
35622
38647
  }
35623
38648
  }
35624
- const c0 = getNums("C0", [0, 0, 0]);
35625
- const c1 = getNums("C1", [1, 1, 1]);
38649
+ const c0 = getNums("C0", [0]);
38650
+ const c1 = getNums("C1", [1]);
35626
38651
  const nNode = doc.resolve(dictGet(fnDict, "N"));
35627
- const expN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
38652
+ const expN = nNode?.kind === "number" ? nNode.value : 1;
35628
38653
  const d0 = dom[0] ?? 0;
35629
38654
  const d1 = dom[1] ?? 1;
35630
- const normT = Math.abs(d1 - d0) > 1e-8 ? (t - d0) / (d1 - d0) : t;
35631
- const w = Math.pow(Math.max(0, Math.min(1, normT)), expN);
38655
+ const w = Math.pow(Math.max(d0, Math.min(d1, t)), expN);
35632
38656
  const len = Math.max(c0.length, c1.length);
35633
38657
  const out = [];
35634
38658
  for (let i = 0; i < len; i++) {
@@ -35644,30 +38668,14 @@ function shadingComponentsToRgb(csName, comps) {
35644
38668
  return [v, v, v];
35645
38669
  }
35646
38670
  if (csName === "DeviceCMYK" || csName === "CMYK" || comps.length >= 4) {
35647
- const cc = comps[0] ?? 0, cm = comps[1] ?? 0, cy = comps[2] ?? 0, ck = comps[3] ?? 0;
35648
- return [(1 - cc) * (1 - ck), (1 - cm) * (1 - kClamp(ck)), (1 - cy) * (1 - kClamp(ck))];
38671
+ const rgb2 = cmykColorSpace2.getRgb([comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0, comps[3] ?? 0], 0);
38672
+ return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
35649
38673
  }
35650
38674
  return [comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0];
35651
38675
  }
35652
38676
  function kClamp(v) {
35653
38677
  return Math.max(0, Math.min(1, v));
35654
38678
  }
35655
- function xyzToSrgb(X, Y, Z, Xw = 0.95047, Yw = 1, Zw = 1.08883) {
35656
- const scaleX = Xw > 1e-6 ? 0.95047 / Xw : 1;
35657
- const scaleY = Yw > 1e-6 ? 1 / Yw : 1;
35658
- const scaleZ = Zw > 1e-6 ? 1.08883 / Zw : 1;
35659
- const x = X * scaleX;
35660
- const y = Y * scaleY;
35661
- const z = Z * scaleZ;
35662
- const rl = 3.2404542 * x - 1.5371385 * y - 0.4985314 * z;
35663
- const gl = -0.969266 * x + 1.8760108 * y + 0.041556 * z;
35664
- const bl = 0.0556434 * x - 0.2040259 * y + 1.0572252 * z;
35665
- const toGamma = (u) => {
35666
- const c = Math.max(0, Math.min(1, u));
35667
- return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
35668
- };
35669
- return [toGamma(rl), toGamma(gl), toGamma(bl)];
35670
- }
35671
38679
  function getColorSpaceComponentCount(doc, csNode, activeResources, depth = 0) {
35672
38680
  if (!csNode || depth > 4) return 3;
35673
38681
  const resolved = doc ? doc.resolve(csNode) : csNode;
@@ -35724,63 +38732,10 @@ function convertColorSpaceComponentsToRgb(doc, csNode, csNameFallback, comps, ac
35724
38732
  if (resolved.kind === "array" && resolved.items.length > 0 && doc) {
35725
38733
  const familyNode = doc.resolve(resolved.items[0]);
35726
38734
  const family = familyNode?.kind === "name" ? familyNode.decoded : "";
35727
- if (family === "CalGray") {
35728
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
35729
- const gNode = paramDict ? doc.resolve(dictGet(paramDict, "Gamma")) : void 0;
35730
- const gamma = gNode?.kind === "number" && gNode.value > 0 ? gNode.value : 1;
35731
- const a = Math.pow(kClamp(comps[0] ?? 0), gamma);
35732
- return [a, a, a];
35733
- }
35734
- if (family === "CalRGB") {
35735
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
35736
- const gammaArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Gamma")) : void 0;
35737
- const getArrNum = (arr, idx, fb) => {
35738
- const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
35739
- return r?.kind === "number" ? r.value : fb;
35740
- };
35741
- const gr = getArrNum(gammaArr, 0, 1);
35742
- const gg = getArrNum(gammaArr, 1, 1);
35743
- const gb = getArrNum(gammaArr, 2, 1);
35744
- const ag = Math.pow(kClamp(comps[0] ?? 0), gr > 0 ? gr : 1);
35745
- const bg = Math.pow(kClamp(comps[1] ?? 0), gg > 0 ? gg : 1);
35746
- const cg = Math.pow(kClamp(comps[2] ?? 0), gb > 0 ? gb : 1);
35747
- const matArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Matrix")) : void 0;
35748
- if (matArr && matArr.items.length >= 9) {
35749
- const m = (i) => getArrNum(matArr, i, 0);
35750
- const X = m(0) * ag + m(3) * bg + m(6) * cg;
35751
- const Y = m(1) * ag + m(4) * bg + m(7) * cg;
35752
- const Z = m(2) * ag + m(5) * bg + m(8) * cg;
35753
- const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
35754
- const Xw = getArrNum(wpArr, 0, 0.95047);
35755
- const Yw = getArrNum(wpArr, 1, 1);
35756
- const Zw = getArrNum(wpArr, 2, 1.08883);
35757
- return xyzToSrgb(X, Y, Z, Xw, Yw, Zw);
35758
- }
35759
- return [ag, bg, cg];
35760
- }
35761
- if (family === "Lab") {
35762
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
35763
- const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
35764
- const rangeArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Range")) : void 0;
35765
- const getNum = (arr, idx, fb) => {
35766
- const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
35767
- return r?.kind === "number" ? r.value : fb;
35768
- };
35769
- const Xw = getNum(wpArr, 0, 0.95047);
35770
- const Yw = getNum(wpArr, 1, 1);
35771
- const Zw = getNum(wpArr, 2, 1.08883);
35772
- const amin = getNum(rangeArr, 0, -100);
35773
- const amax = getNum(rangeArr, 1, 100);
35774
- const bmin = getNum(rangeArr, 2, -100);
35775
- const bmax = getNum(rangeArr, 3, 100);
35776
- const Lstar = Math.max(0, Math.min(100, comps[0] ?? 0));
35777
- const astar = Math.max(amin, Math.min(amax, comps[1] ?? 0));
35778
- const bstar = Math.max(bmin, Math.min(bmax, comps[2] ?? 0));
35779
- const M = (Lstar + 16) / 116;
35780
- const L = M + astar / 500;
35781
- const N = M - bstar / 200;
35782
- const gFn = (x) => x >= 6 / 29 ? x * x * x : 108 / 841 * (x - 4 / 29);
35783
- return xyzToSrgb(Xw * gFn(L), Yw * gFn(M), Zw * gFn(N), Xw, Yw, Zw);
38735
+ if (family === "CalGray" || family === "CalRGB" || family === "Lab") {
38736
+ const colorSpace = createCalibratedColorSpace(doc, family, resolved.items[1]);
38737
+ const rgb2 = colorSpace.getRgb(comps, 0);
38738
+ return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
35784
38739
  }
35785
38740
  if (family === "ICCBased" && resolved.items[1]) {
35786
38741
  const iccNode = doc.resolve(resolved.items[1]);
@@ -35861,143 +38816,28 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
35861
38816
  const r = doc.resolve(it);
35862
38817
  return r?.kind === "number" ? r.value : 0;
35863
38818
  });
35864
- const xmin = decodeNums[0], xmax = decodeNums[1], ymin = decodeNums[2], ymax = decodeNums[3];
35865
- const numColorParams = Math.max(1, Math.floor((decodeNums.length - 4) / 2));
35866
38819
  const fnNode = dictGet(shDict, "Function");
35867
38820
  const csNode = doc.resolve(dictGet(shDict, "ColorSpace"));
35868
38821
  const csName = csNode?.kind === "name" ? csNode.decoded : "DeviceRGB";
35869
- let bitPos = 0;
35870
- const totalBits = bytes.length * 8;
35871
- const readBits = (n) => {
35872
- let val = 0;
35873
- for (let i = 0; i < n; i++) {
35874
- if (bitPos >= totalBits) return val;
35875
- const byteIdx = bitPos >> 3;
35876
- const bitIdx = 7 - (bitPos & 7);
35877
- val = val * 2 + (bytes[byteIdx] >> bitIdx & 1);
35878
- bitPos++;
35879
- }
35880
- return val;
35881
- };
35882
- const coordMax = Math.pow(2, bpcCoord) - 1 || 1;
35883
- const compMax = Math.pow(2, bpcComp) - 1 || 1;
35884
- const readCoord = () => {
35885
- const rx = readBits(bpcCoord) / coordMax;
35886
- const ry = readBits(bpcCoord) / coordMax;
35887
- return [xmin + rx * (xmax - xmin), ymin + ry * (ymax - ymin)];
35888
- };
35889
- const readColorRgb = () => {
35890
- const params = [];
35891
- for (let c = 0; c < numColorParams; c++) {
35892
- const rc = readBits(bpcComp) / compMax;
35893
- const cMin = decodeNums[4 + c * 2] ?? 0;
35894
- const cMax = decodeNums[4 + c * 2 + 1] ?? 1;
35895
- params.push(cMin + rc * (cMax - cMin));
35896
- }
35897
- const comps = fnNode ? evalShadingFunctionToComponents(doc, fnNode, params) : params;
35898
- return convertColorSpaceComponentsToRgb(doc, csNode, csName, comps);
35899
- };
35900
- const triangles = [];
35901
- if (shType === 4) {
35902
- const minBitsPerVert = bpcFlag + 2 * bpcCoord + numColorParams * bpcComp;
35903
- let triVerts;
35904
- while (bitPos + minBitsPerVert <= totalBits) {
35905
- const flag = readBits(bpcFlag) & 3;
35906
- const [x, y] = readCoord();
35907
- const rgb2 = readColorRgb();
35908
- const vNew = { x, y, rgb: rgb2 };
35909
- if (flag === 0 || !triVerts) {
35910
- if (bitPos + 2 * minBitsPerVert > totalBits) break;
35911
- readBits(bpcFlag);
35912
- const [x1, y1] = readCoord();
35913
- const rgb1 = readColorRgb();
35914
- readBits(bpcFlag);
35915
- const [x2, y2] = readCoord();
35916
- const rgb22 = readColorRgb();
35917
- triVerts = [vNew, { x: x1, y: y1, rgb: rgb1 }, { x: x2, y: y2, rgb: rgb22 }];
35918
- triangles.push(triVerts);
35919
- } else if (flag === 1) {
35920
- triVerts = [triVerts[1], triVerts[2], vNew];
35921
- triangles.push(triVerts);
35922
- } else if (flag === 2) {
35923
- triVerts = [triVerts[0], triVerts[2], vNew];
35924
- triangles.push(triVerts);
35925
- }
35926
- }
35927
- } else if (shType === 5) {
35928
- const minBitsPerVert = 2 * bpcCoord + numColorParams * bpcComp;
35929
- const verts = [];
35930
- while (bitPos + minBitsPerVert <= totalBits) {
35931
- const [x, y] = readCoord();
35932
- const rgb2 = readColorRgb();
35933
- verts.push({ x, y, rgb: rgb2 });
35934
- }
35935
- const numRows = Math.floor(verts.length / vPerRow);
35936
- for (let r = 0; r + 1 < numRows; r++) {
35937
- for (let c = 0; c + 1 < vPerRow; c++) {
35938
- const v00 = verts[r * vPerRow + c];
35939
- const v01 = verts[r * vPerRow + c + 1];
35940
- const v11 = verts[(r + 1) * vPerRow + c + 1];
35941
- const v10 = verts[(r + 1) * vPerRow + c];
35942
- triangles.push([v00, v01, v11], [v00, v11, v10]);
35943
- }
35944
- }
35945
- } else if (shType === 6 || shType === 7) {
35946
- const numCtrl = shType === 6 ? 12 : 16;
35947
- const minBitsPatch = bpcFlag + (numCtrl - 4) * 2 * bpcCoord + 2 * numColorParams * bpcComp;
35948
- let prevPts;
35949
- let prevColors;
35950
- while (bitPos + minBitsPatch <= totalBits) {
35951
- const flag = readBits(bpcFlag) & 3;
35952
- let pts = [];
35953
- let cols = [];
35954
- if (flag === 0 || !prevPts || !prevColors) {
35955
- for (let i = 0; i < numCtrl; i++) pts.push(readCoord());
35956
- for (let i = 0; i < 4; i++) cols.push(readColorRgb());
35957
- } else {
35958
- const extraCtrl = numCtrl - 4;
35959
- const readExtra = [];
35960
- for (let i = 0; i < extraCtrl; i++) readExtra.push(readCoord());
35961
- const c2 = readColorRgb();
35962
- const c3 = readColorRgb();
35963
- pts = [prevPts[3], prevPts[4], prevPts[5], prevPts[6], ...readExtra];
35964
- cols = [prevColors[1], prevColors[2], c2, c3];
35965
- }
35966
- prevPts = pts;
35967
- prevColors = cols;
35968
- const p00 = pts[0];
35969
- const p03 = pts[3];
35970
- const p33 = pts[6];
35971
- const p30 = pts[9];
35972
- const c00 = cols[0], c03 = cols[1], c33 = cols[2], c30 = cols[3];
35973
- const steps = 4;
35974
- const grid = [];
35975
- for (let iu = 0; iu <= steps; iu++) {
35976
- const u = iu / steps;
35977
- const row = [];
35978
- for (let iv = 0; iv <= steps; iv++) {
35979
- const v = iv / steps;
35980
- const x = (1 - u) * (1 - v) * p00[0] + (1 - u) * v * p03[0] + u * v * p33[0] + u * (1 - v) * p30[0];
35981
- const y = (1 - u) * (1 - v) * p00[1] + (1 - u) * v * p03[1] + u * v * p33[1] + u * (1 - v) * p30[1];
35982
- const r = (1 - u) * (1 - v) * c00[0] + (1 - u) * v * c03[0] + u * v * c33[0] + u * (1 - v) * c30[0];
35983
- const g = (1 - u) * (1 - v) * c00[1] + (1 - u) * v * c03[1] + u * v * c33[1] + u * (1 - v) * c30[1];
35984
- const b = (1 - u) * (1 - v) * c00[2] + (1 - u) * v * c03[2] + u * v * c33[2] + u * (1 - v) * c30[2];
35985
- row.push({ x, y, rgb: [r, g, b] });
35986
- }
35987
- grid.push(row);
35988
- }
35989
- for (let iu = 0; iu < steps; iu++) {
35990
- for (let iv = 0; iv < steps; iv++) {
35991
- const g00 = grid[iu][iv];
35992
- const g01 = grid[iu][iv + 1];
35993
- const g11 = grid[iu + 1][iv + 1];
35994
- const g10 = grid[iu + 1][iv];
35995
- triangles.push([g00, g01, g11], [g00, g11, g10]);
35996
- }
35997
- }
35998
- }
35999
- }
36000
- if (triangles.length === 0) return void 0;
38822
+ const numComps = fnNode ? 1 : getColorSpaceComponentCount(doc, csNode);
38823
+ const mesh = new MeshShading(shType, new Stream(bytes), {
38824
+ bitsPerCoordinate: bpcCoord,
38825
+ bitsPerComponent: bpcComp,
38826
+ bitsPerFlag: bpcFlag,
38827
+ decode: decodeNums,
38828
+ numComps,
38829
+ colorFn: null,
38830
+ colorSpace: {
38831
+ numComps,
38832
+ getRgb(components) {
38833
+ const params = Array.from(components);
38834
+ const values = fnNode ? evalShadingFunctionToComponents(doc, fnNode, params) : params;
38835
+ return new Uint8Array(convertColorSpaceComponentsToRgb(doc, csNode, csName, values).map((value) => Math.round(Math.max(0, Math.min(1, value)) * 255)));
38836
+ }
38837
+ }
38838
+ }, vPerRow);
38839
+ const [, , positions, colors, vertexCount] = mesh.getIR();
38840
+ if (vertexCount === 0) return void 0;
36001
38841
  const [bx0, by0, bx1, by1] = targetBox;
36002
38842
  const boxW = Math.max(1, bx1 - bx0);
36003
38843
  const boxH = Math.max(1, by1 - by0);
@@ -36009,10 +38849,10 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
36009
38849
  const [px, py] = transformPoint(effectiveCtm, vx, vy);
36010
38850
  return [(px - bx0) / boxW * imgW, (by1 - py) / boxH * imgH];
36011
38851
  };
36012
- for (const [v0, v1, v2] of triangles) {
36013
- const [x0, y0] = toImgCoords(v0.x, v0.y);
36014
- const [x1, y1] = toImgCoords(v1.x, v1.y);
36015
- const [x2, y2] = toImgCoords(v2.x, v2.y);
38852
+ for (let vertex = 0; vertex < vertexCount; vertex += 3) {
38853
+ const [x0, y0] = toImgCoords(positions[vertex * 2], positions[vertex * 2 + 1]);
38854
+ const [x1, y1] = toImgCoords(positions[vertex * 2 + 2], positions[vertex * 2 + 3]);
38855
+ const [x2, y2] = toImgCoords(positions[vertex * 2 + 4], positions[vertex * 2 + 5]);
36016
38856
  const denom = (y1 - y2) * (x0 - x2) + (x2 - x1) * (y0 - y2);
36017
38857
  if (Math.abs(denom) < 1e-6) continue;
36018
38858
  const minX = Math.max(0, Math.floor(Math.min(x0, x1, x2)));
@@ -36027,13 +38867,12 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
36027
38867
  const w1 = ((y2 - y0) * (px - x2) + (x0 - x2) * (py - y2)) / denom;
36028
38868
  const w2 = 1 - w0 - w1;
36029
38869
  if (w0 >= -1e-4 && w1 >= -1e-4 && w2 >= -1e-4) {
36030
- const r = w0 * v0.rgb[0] + w1 * v1.rgb[0] + w2 * v2.rgb[0];
36031
- const g = w0 * v0.rgb[1] + w1 * v1.rgb[1] + w2 * v2.rgb[1];
36032
- const b = w0 * v0.rgb[2] + w1 * v1.rgb[2] + w2 * v2.rgb[2];
36033
38870
  const pIdx = (iy * imgW + ix) * 4;
36034
- rgba[pIdx] = Math.round(Math.max(0, Math.min(1, r)) * 255);
36035
- rgba[pIdx + 1] = Math.round(Math.max(0, Math.min(1, g)) * 255);
36036
- rgba[pIdx + 2] = Math.round(Math.max(0, Math.min(1, b)) * 255);
38871
+ for (let channel = 0; channel < 3; channel++) {
38872
+ rgba[pIdx + channel] = Math.round(
38873
+ w0 * colors[vertex * 4 + channel] + w1 * colors[vertex * 4 + 4 + channel] + w2 * colors[vertex * 4 + 8 + channel]
38874
+ );
38875
+ }
36037
38876
  rgba[pIdx + 3] = a8;
36038
38877
  }
36039
38878
  }
@@ -36120,6 +38959,8 @@ function renderShadingDictToImage(doc, shDict, shadingCtm, targetBox, fillAlpha,
36120
38959
  const [a, b, c, d, e, f] = effectiveCtm;
36121
38960
  const det = a * d - b * c;
36122
38961
  if (Math.abs(det) <= 1e-8) return void 0;
38962
+ const [sa, sb, sc, sd, se, sf] = shadingCtm;
38963
+ const shadingDet = sa * sd - sb * sc;
36123
38964
  const t0Dom = shDomain[0] ?? 0;
36124
38965
  const t1Dom = shDomain[1] ?? 1;
36125
38966
  for (let iy = 0; iy < imgH; iy++) {
@@ -36130,8 +38971,10 @@ function renderShadingDictToImage(doc, shDict, shadingCtm, targetBox, fillAlpha,
36130
38971
  const dxPdf = xPdf - e;
36131
38972
  const xs = (d * dxPdf - c * dyPdf) / det;
36132
38973
  const ys = (-b * dxPdf + a * dyPdf) / det;
36133
- if (shBBox && (xs < shBBox[0] || xs > shBBox[2] || ys < shBBox[1] || ys > shBBox[3])) {
36134
- continue;
38974
+ if (shBBox) {
38975
+ const bboxX = (sd * (xPdf - se) - sc * (yPdf - sf)) / shadingDet;
38976
+ const bboxY = (-sb * (xPdf - se) + sa * (yPdf - sf)) / shadingDet;
38977
+ if (bboxX < shBBox[0] || bboxX > shBBox[2] || bboxY < shBBox[1] || bboxY > shBBox[3]) continue;
36135
38978
  }
36136
38979
  let comps;
36137
38980
  if (shType === 1) {
@@ -36431,7 +39274,8 @@ function evaluateContentStreamToDisplayList(params) {
36431
39274
  const shDict = shNode?.kind === "dict" ? shNode : shNode?.kind === "stream" ? shNode.dict : void 0;
36432
39275
  const shStream = shNode?.kind === "stream" ? shNode : void 0;
36433
39276
  if (shDict) {
36434
- const targetBox = st.clipRect ?? [0, 0, params.width, params.height];
39277
+ const [originX, originY] = params.origin ?? [0, 0];
39278
+ const targetBox = st.clipRect ?? [originX, originY, originX + params.width, originY + params.height];
36435
39279
  const img = renderShadingDictToImage(
36436
39280
  params.cosDoc,
36437
39281
  shDict,
@@ -36470,12 +39314,10 @@ function evaluateContentStreamToDisplayList(params) {
36470
39314
  } else if (operator === "RG" || operator === "SC" || operator === "SCN") {
36471
39315
  st.strokeColor = resolveScColorOperands(operator === "RG" ? "DeviceRGB" : st.strokeColorSpaceName, ops, activeResources);
36472
39316
  } else if (operator === "k") {
36473
- const c = num(0), m = num(1), y = num(2), k = num(3);
36474
- st.fillColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
39317
+ st.fillColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
36475
39318
  st.fillPatternName = void 0;
36476
39319
  } else if (operator === "K") {
36477
- const c = num(0), m = num(1), y = num(2), k = num(3);
36478
- st.strokeColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
39320
+ st.strokeColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
36479
39321
  } else if (operator === "gs" && params.cosDoc && activeResources && ops[0]?.kind === "name") {
36480
39322
  const extDict = params.cosDoc.resolveDict(dictGet(activeResources, "ExtGState"));
36481
39323
  const gsDict = extDict ? params.cosDoc.resolveDict(dictGet(extDict, ops[0].decoded)) : void 0;
@@ -36684,7 +39526,7 @@ function evaluateContentStreamToDisplayList(params) {
36684
39526
  stateStack.pop();
36685
39527
  capturedOperations = parentOperations;
36686
39528
  }
36687
- if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
39529
+ if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, isolated, bboxClip: nextClipPaths?.[0], blendMode: st.blendMode, clipRect: st.clipRect } });
36688
39530
  };
36689
39531
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
36690
39532
  for (const node of nodes) {
@@ -37268,6 +40110,7 @@ function evaluateContentStreamToDisplayList(params) {
37268
40110
  pageIndex: params.pageIndex,
37269
40111
  width: params.width,
37270
40112
  height: params.height,
40113
+ ...params.origin ? { origin: params.origin } : {},
37271
40114
  rotation: params.rotation ?? 0,
37272
40115
  glyphs,
37273
40116
  paths,
@@ -39427,7 +42270,7 @@ var PdfPage = class {
39427
42270
  return [n0.value, n1.value, n2.value, n3.value];
39428
42271
  }
39429
42272
  }
39430
- return [0, 0, 612, 792];
42273
+ return key === "MediaBox" ? [0, 0, 612, 792] : this.resolveBox("MediaBox");
39431
42274
  }
39432
42275
  getMediaBox() {
39433
42276
  return this.resolveBox("MediaBox");
@@ -40100,16 +42943,19 @@ var PdfPage = class {
40100
42943
  });
40101
42944
  }
40102
42945
  }
40103
- return evaluateContentStreamToDisplayList({
42946
+ const mediaBox = this.getMediaBox(), cropBox = this.getCropBox();
42947
+ const originX = Math.min(mediaBox[0], mediaBox[2]), originY = Math.min(mediaBox[1], mediaBox[3]);
42948
+ return { ...evaluateContentStreamToDisplayList({
40104
42949
  pageIndex: this.index,
40105
42950
  width,
40106
42951
  height,
42952
+ origin: [originX, originY],
40107
42953
  rotation: this.getRotation(),
40108
42954
  nodes: baseNodes,
40109
42955
  cosDoc: this.cosDoc,
40110
42956
  resourcesDict: evalResourcesDict,
40111
42957
  annotations: extractPageAnnotations(this.cosDoc, this.pageDict)
40112
- });
42958
+ }), cropBox: [cropBox[0] - originX, cropBox[1] - originY, cropBox[2] - originX, cropBox[3] - originY] };
40113
42959
  }
40114
42960
  extractPage(options) {
40115
42961
  const dl = this.evaluateDisplayList();
@@ -40127,10 +42973,10 @@ var PdfPage = class {
40127
42973
  return extractTablesFromDisplayList(this.evaluateDisplayList());
40128
42974
  }
40129
42975
  renderToBitmap(options) {
40130
- return renderDisplayListToBitmap(this.evaluateDisplayList(), options);
42976
+ return renderDisplayListToBitmap(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
40131
42977
  }
40132
42978
  renderToPng(options) {
40133
- return renderDisplayListToPng(this.evaluateDisplayList(), options);
42979
+ return renderDisplayListToPng(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
40134
42980
  }
40135
42981
  };
40136
42982
  function createStandardFontHandle(standardName) {
@@ -41584,7 +44430,7 @@ function prepareStroke(path, scale) {
41584
44430
  }
41585
44431
  return { matrix, width, dashArray, dashPhase };
41586
44432
  }
41587
- function strokeContours(path, pageHeight, scale) {
44433
+ function strokeContours(path, pageHeight, scale, originX = 0, originY = 0) {
41588
44434
  const stroke = prepareStroke(path, scale);
41589
44435
  if (!stroke) return [];
41590
44436
  const inverse = inverseStrokeMatrix(stroke.matrix);
@@ -41596,8 +44442,8 @@ function strokeContours(path, pageHeight, scale) {
41596
44442
  (inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
41597
44443
  ];
41598
44444
  const toScreen = ([x, y]) => [
41599
- (a * x / strokeScale + c * y / strokeScale + e) * scale,
41600
- (pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
44445
+ (a * x / strokeScale + c * y / strokeScale + e - originX) * scale,
44446
+ (pageHeight + originY - b * x / strokeScale - d * y / strokeScale - f) * scale
41601
44447
  ];
41602
44448
  const contours = strokeOutlines(
41603
44449
  segmentsToScreenPaths(path.segments, pageHeight, scale, project),
@@ -41755,18 +44601,37 @@ function renderSoftMask(mask, displayList, scale) {
41755
44601
  }
41756
44602
  return bitmap;
41757
44603
  }
41758
- function hasBlendModes(operations) {
41759
- return operations.some((operation) => !!operation.value.blendMode && operation.value.blendMode !== "Normal" && operation.value.blendMode !== "Compatible" || operation.kind === "group" && hasBlendModes(operation.value.operations));
44604
+ function getDisplayListCropBox(list) {
44605
+ const full = [0, 0, list.width, list.height];
44606
+ const box = list.cropBox;
44607
+ if (!box || !box.every(Number.isFinite)) return full;
44608
+ const x0 = Math.max(0, Math.min(box[0], box[2]));
44609
+ const y0 = Math.max(0, Math.min(box[1], box[3]));
44610
+ const x1 = Math.min(list.width, Math.max(box[0], box[2]));
44611
+ const y1 = Math.min(list.height, Math.max(box[1], box[3]));
44612
+ return x1 > x0 && y1 > y0 ? [x0, y0, x1, y1] : full;
44613
+ }
44614
+ function hasCompositingEffects(operations, includeSoftMasks = false) {
44615
+ 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));
44616
+ }
44617
+ function needsGroupBackdrop(group) {
44618
+ return group.isolated === false && !!group.softMask && hasCompositingEffects(group.operations, true);
44619
+ }
44620
+ function containsBackdropGroup(operations) {
44621
+ return operations.some((operation) => operation.kind === "group" && (needsGroupBackdrop(operation.value) || containsBackdropGroup(operation.value.operations)));
41760
44622
  }
41761
44623
  function renderDisplayListToBitmap(displayList, options = {}) {
41762
44624
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
41763
44625
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
41764
44626
  const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
41765
44627
  const scale = scaleX;
44628
+ const [originX, originY] = displayList.origin ?? [0, 0];
44629
+ const pageTop = originY + displayList.height;
44630
+ const toScreen = (x, y) => [(x - originX) * scale, (pageTop - y) * scale];
41766
44631
  const width = Math.max(1, Math.round(displayList.width * scale));
41767
44632
  const height = Math.max(1, Math.round(displayList.height * scale));
41768
44633
  const rgba = new Uint8Array(width * height * 4);
41769
- const deferBackground = !options.transparent && hasBlendModes(paintOperations(displayList));
44634
+ const deferBackground = !options.transparent && hasCompositingEffects(paintOperations(displayList));
41770
44635
  const transparent = options.transparent || deferBackground;
41771
44636
  const bg = options.background ?? { r: 1, g: 1, b: 1 };
41772
44637
  const bgR = transparent ? 0 : Math.round(bg.r * 255);
@@ -41791,14 +44656,27 @@ function renderDisplayListToBitmap(displayList, options = {}) {
41791
44656
  let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
41792
44657
  if (operation.kind === "group") {
41793
44658
  const group = operation.value;
41794
- const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations: group.operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, transparent: true });
44659
+ let operations = group.operations;
44660
+ if (needsGroupBackdrop(group)) {
44661
+ operations = [{ kind: "image", value: {
44662
+ name: "GroupBackdrop",
44663
+ width,
44664
+ height,
44665
+ decodedRgba: rgba.slice(),
44666
+ matrix: [width / scale, 0, 0, height / scale, originX, pageTop - height / scale],
44667
+ colorSpace: "DeviceRGB",
44668
+ bitsPerComponent: 8,
44669
+ ...group.bboxClip ? { clipPaths: [group.bboxClip] } : {}
44670
+ } }, ...operations];
44671
+ }
44672
+ const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, useCropBox: false, transparent: true });
41795
44673
  for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
41796
44674
  operation = { kind: "image", value: {
41797
44675
  name: "TransparencyGroup",
41798
44676
  width: bitmap.width,
41799
44677
  height: bitmap.height,
41800
44678
  decodedRgba: bitmap.data,
41801
- matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, 0, displayList.height - bitmap.height / scale],
44679
+ matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, originX, pageTop - bitmap.height / scale],
41802
44680
  colorSpace: "DeviceRGB",
41803
44681
  bitsPerComponent: 8,
41804
44682
  blendMode: group.blendMode,
@@ -41812,7 +44690,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
41812
44690
  for (const clip of clips) {
41813
44691
  const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
41814
44692
  const layer = new Uint8Array(width * height * 4);
41815
- fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
44693
+ fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale, toScreen), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
41816
44694
  for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
41817
44695
  }
41818
44696
  cachedClips = clips;
@@ -41859,15 +44737,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
41859
44737
  if (operation.kind === "path") {
41860
44738
  const path = operation.value;
41861
44739
  if (path.fillColor) {
41862
- const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale), true);
41863
- 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;
44740
+ const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale, toScreen), true);
44741
+ 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;
41864
44742
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
41865
44743
  }
41866
44744
  if (path.strokeColor) {
41867
44745
  const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
41868
44746
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
41869
- const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
41870
- 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;
44747
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale, originX, originY).map((points) => ({ points, closed: true })));
44748
+ 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;
41871
44749
  fillEdgesScanline4x4(
41872
44750
  rgba,
41873
44751
  width,
@@ -41890,12 +44768,12 @@ function renderDisplayListToBitmap(displayList, options = {}) {
41890
44768
  if (Math.abs(det) <= 1e-8) continue;
41891
44769
  const cornersPdfX = [e, a + e, a + c + e, c + e];
41892
44770
  const cornersPdfY = [f, b + f, b + d + f, d + f];
41893
- const cornersPx = cornersPdfX.map((cx) => cx * scale);
41894
- const cornersPy = cornersPdfY.map((cy) => (displayList.height - cy) * scale);
41895
- const clipMinPx = img.clipRect ? Math.floor(img.clipRect[0] * scale) : 0;
41896
- const clipMaxPx = img.clipRect ? Math.ceil(img.clipRect[2] * scale) - 1 : width - 1;
41897
- const clipMinPy = img.clipRect ? Math.floor((displayList.height - img.clipRect[3]) * scale) : 0;
41898
- const clipMaxPy = img.clipRect ? Math.ceil((displayList.height - img.clipRect[1]) * scale) - 1 : height - 1;
44771
+ const cornersPx = cornersPdfX.map((cx) => (cx - originX) * scale);
44772
+ const cornersPy = cornersPdfY.map((cy) => (pageTop - cy) * scale);
44773
+ const clipMinPx = img.clipRect ? Math.floor((img.clipRect[0] - originX) * scale) : 0;
44774
+ const clipMaxPx = img.clipRect ? Math.ceil((img.clipRect[2] - originX) * scale) - 1 : width - 1;
44775
+ const clipMinPy = img.clipRect ? Math.floor((pageTop - img.clipRect[3]) * scale) : 0;
44776
+ const clipMaxPy = img.clipRect ? Math.ceil((pageTop - img.clipRect[1]) * scale) - 1 : height - 1;
41899
44777
  const minPx = Math.max(0, clipMinPx, Math.floor(Math.min(...cornersPx)));
41900
44778
  const maxPx = Math.min(width - 1, clipMaxPx, Math.ceil(Math.max(...cornersPx)) - 1);
41901
44779
  const minPy = Math.max(0, clipMinPy, Math.floor(Math.min(...cornersPy)));
@@ -41912,11 +44790,11 @@ function renderDisplayListToBitmap(displayList, options = {}) {
41912
44790
  const smooth = Math.fround((s1 + s2 + Math.hypot(s1 - s2, 2 * cross)) / 2) <= 1;
41913
44791
  const sample = new Float64Array(4);
41914
44792
  for (let py = minPy; py <= maxPy; py++) {
41915
- const yPdf = displayList.height - (py + 0.5) / scale;
44793
+ const yPdf = pageTop - (py + 0.5) / scale;
41916
44794
  if (img.clipRect && (yPdf < img.clipRect[1] || yPdf > img.clipRect[3])) continue;
41917
44795
  const dyPdf = yPdf - f;
41918
44796
  for (let px = minPx; px <= maxPx; px++) {
41919
- const xPdf = (px + 0.5) / scale;
44797
+ const xPdf = originX + (px + 0.5) / scale;
41920
44798
  if (img.clipRect && (xPdf < img.clipRect[0] || xPdf > img.clipRect[2])) continue;
41921
44799
  const dxPdf = xPdf - e;
41922
44800
  const u = (d * dxPdf - c * dyPdf) / det;
@@ -41977,6 +44855,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
41977
44855
  }
41978
44856
  result = { width: targetW, height: targetH, data: resampled };
41979
44857
  }
44858
+ if (options.useCropBox) {
44859
+ const box = getDisplayListCropBox(displayList);
44860
+ result = cropRgbaBitmap(result, {
44861
+ x: box[0] * scaleX,
44862
+ y: (displayList.height - box[3]) * scaleY,
44863
+ width: (box[2] - box[0]) * scaleX,
44864
+ height: (box[3] - box[1]) * scaleY
44865
+ });
44866
+ }
41980
44867
  result = rotateRgbaBitmapQuarterTurns(result, displayList.rotation ?? 0);
41981
44868
  if (options.cropRect) {
41982
44869
  result = cropRgbaBitmap(result, options.cropRect);
@@ -42046,18 +44933,44 @@ function svgPathData(segments, height, matrix) {
42046
44933
  }
42047
44934
  function renderDisplayListToSvg(displayList, options = {}) {
42048
44935
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1);
44936
+ if (containsBackdropGroup(paintOperations(displayList))) {
44937
+ const bitmap = renderDisplayListToBitmap(displayList, { ...options, scale: baseScale });
44938
+ const embedded = svgImage({
44939
+ name: "PageComposite",
44940
+ width: bitmap.width,
44941
+ height: bitmap.height,
44942
+ decodedRgba: bitmap.data,
44943
+ matrix: [bitmap.width, 0, 0, bitmap.height, 0, 0],
44944
+ colorSpace: "DeviceRGB",
44945
+ bitsPerComponent: 8
44946
+ }, bitmap.height);
44947
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${bitmap.width}" height="${bitmap.height}" viewBox="0 0 ${bitmap.width} ${bitmap.height}">${embedded}</svg>
44948
+ `;
44949
+ }
42049
44950
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
42050
44951
  const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
42051
- const viewport = new PageViewport({ viewBox: [0, 0, displayList.width, displayList.height], userUnit: 1, scale: 1, rotation: displayList.rotation ?? 0 });
44952
+ const [originX, originY] = displayList.origin ?? [0, 0];
44953
+ const viewport = new PageViewport({ viewBox: [originX, originY, originX + displayList.width, originY + displayList.height], userUnit: 1, scale: 1, rotation: displayList.rotation ?? 0 });
42052
44954
  const quarterTurn = displayList.rotation === 90 || displayList.rotation === 270;
42053
44955
  const outputScaleX = quarterTurn ? scaleY : scaleX;
42054
44956
  const outputScaleY = quarterTurn ? scaleX : scaleY;
42055
- const fullW = Math.max(1, Math.round(viewport.width * outputScaleX));
42056
- const fullH = Math.max(1, Math.round(viewport.height * outputScaleY));
42057
- const vbX = options.cropRect ? options.cropRect.x / outputScaleX : 0;
42058
- const vbY = options.cropRect ? options.cropRect.y / outputScaleY : 0;
42059
- const vbW = options.cropRect && options.cropRect.width > 0 ? options.cropRect.width / outputScaleX : Math.max(1, viewport.width - vbX);
42060
- const vbH = options.cropRect && options.cropRect.height > 0 ? options.cropRect.height / outputScaleY : Math.max(1, viewport.height - vbY);
44957
+ let bounds = [0, 0, viewport.width, viewport.height];
44958
+ if (options.useCropBox) {
44959
+ const box = getDisplayListCropBox(displayList);
44960
+ const [x0, y0, x1, y1] = [box[0] + originX, box[1] + originY, box[2] + originX, box[3] + originY];
44961
+ const [a, b, c, d, e, f] = viewport.transform;
44962
+ bounds = [a * x0 + c * y0 + e, b * x0 + d * y0 + f, a * x1 + c * y1 + e, b * x1 + d * y1 + f];
44963
+ }
44964
+ const viewX = Math.min(bounds[0], bounds[2]), viewY = Math.min(bounds[1], bounds[3]);
44965
+ const viewWidth = Math.abs(bounds[2] - bounds[0]), viewHeight = Math.abs(bounds[3] - bounds[1]);
44966
+ const fullW = Math.max(1, Math.round(viewWidth * outputScaleX));
44967
+ const fullH = Math.max(1, Math.round(viewHeight * outputScaleY));
44968
+ const cropX = options.cropRect ? options.cropRect.x / outputScaleX : 0;
44969
+ const vbX = viewX + cropX;
44970
+ const cropY = options.cropRect ? options.cropRect.y / outputScaleY : 0;
44971
+ const vbY = viewY + cropY;
44972
+ const vbW = options.cropRect && options.cropRect.width > 0 ? options.cropRect.width / outputScaleX : Math.max(1, viewWidth - cropX);
44973
+ const vbH = options.cropRect && options.cropRect.height > 0 ? options.cropRect.height / outputScaleY : Math.max(1, viewHeight - cropY);
42061
44974
  const outW = options.cropRect && options.cropRect.width > 0 ? Math.round(options.cropRect.width) : Math.max(1, fullW - Math.round(options.cropRect?.x ?? 0));
42062
44975
  const outH = options.cropRect && options.cropRect.height > 0 ? Math.round(options.cropRect.height) : Math.max(1, fullH - Math.round(options.cropRect?.y ?? 0));
42063
44976
  const parts = [
@@ -42067,7 +44980,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
42067
44980
  parts.push(` <rect x="${vbX}" y="${vbY}" width="${vbW}" height="${vbH}" fill="#ffffff"/>`);
42068
44981
  }
42069
44982
  parts.push('<g style="isolation:isolate">');
42070
- if (displayList.rotation) {
44983
+ if (displayList.rotation || originX || originY) {
42071
44984
  const [a, b, c, d, e, f] = viewport.transform;
42072
44985
  parts.push(`<g transform="matrix(${a} ${b} ${-c} ${-d} ${e + c * displayList.height} ${f + d * displayList.height})">`);
42073
44986
  }
@@ -42093,11 +45006,11 @@ function renderDisplayListToSvg(displayList, options = {}) {
42093
45006
  width: bitmap.width,
42094
45007
  height: bitmap.height,
42095
45008
  decodedRgba: bitmap.data,
42096
- matrix: [displayList.width, 0, 0, displayList.height, 0, 0],
45009
+ matrix: [displayList.width, 0, 0, displayList.height, originX, originY],
42097
45010
  colorSpace: "DeviceGray",
42098
45011
  bitsPerComponent: 8
42099
45012
  };
42100
- 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>`);
45013
+ 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>`);
42101
45014
  }
42102
45015
  parts.push(`<g mask="url(#${id})">`);
42103
45016
  }
@@ -42109,7 +45022,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
42109
45022
  }
42110
45023
  for (const image of imageClips) {
42111
45024
  const id = `image-clip-${clipId++}`;
42112
- 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})">`);
45025
+ 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})">`);
42113
45026
  }
42114
45027
  if (operation.kind === "group") {
42115
45028
  parts.push(`<g opacity="${operation.value.alpha}" style="isolation:isolate">`);
@@ -42153,7 +45066,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
42153
45066
  }
42154
45067
  };
42155
45068
  appendOperations(paintOperations(displayList));
42156
- if (displayList.rotation) parts.push("</g>");
45069
+ if (displayList.rotation || originX || originY) parts.push("</g>");
42157
45070
  parts.push("</g>");
42158
45071
  parts.push("</svg>\n");
42159
45072
  return parts.join("\n");
@@ -42176,23 +45089,6 @@ function collectLeavesForRaster(cosDoc, node, out = [], visited = /* @__PURE__ *
42176
45089
  }
42177
45090
  return out;
42178
45091
  }
42179
- function extractBoxArray(cosDoc, dict, key) {
42180
- let cur = dict;
42181
- const visited = /* @__PURE__ */ new Set();
42182
- while (cur && !visited.has(cur)) {
42183
- visited.add(cur);
42184
- const arr = cosDoc.resolveArray(dictGet(cur, key));
42185
- if (arr && arr.items.length >= 4) {
42186
- const nums = arr.items.slice(0, 4).map((item) => {
42187
- const r = cosDoc.resolve(item);
42188
- return r?.kind === "number" ? r.value : 0;
42189
- });
42190
- return [nums[0], nums[1], nums[2], nums[3]];
42191
- }
42192
- cur = cosDoc.resolveDict(dictGet(cur, "Parent"));
42193
- }
42194
- return void 0;
42195
- }
42196
45092
  function renderPdfPageToBitmap(pdfBytes, pageIndex = 0, options) {
42197
45093
  const cos = pdfBytes instanceof Uint8Array ? parseCosDocument(pdfBytes) : pdfBytes;
42198
45094
  const catalog = cos.resolveDict(cos.rootRef);
@@ -42201,35 +45097,7 @@ function renderPdfPageToBitmap(pdfBytes, pageIndex = 0, options) {
42201
45097
  if (!leaf) throw new Error(`Page index ${pageIndex} out of bounds`);
42202
45098
  const resolvedIndex = leaves.indexOf(leaf);
42203
45099
  const page = new PdfPage(cos, leaf.ref, leaf.dict, resolvedIndex);
42204
- const { cropRect, ...restOptions } = options ?? {};
42205
- let bitmap = renderDisplayListToBitmap(
42206
- // CropBox is in unrotated page coordinates. Apply page rotation after it.
42207
- { ...page.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), rotation: 0 },
42208
- restOptions
42209
- );
42210
- if (options?.useCropBox) {
42211
- const cropBox = extractBoxArray(cos, leaf.dict, "CropBox");
42212
- if (cropBox) {
42213
- const mediaBox = extractBoxArray(cos, leaf.dict, "MediaBox") ?? [0, 0, page.getSize().width, page.getSize().height];
42214
- const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
42215
- const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
42216
- const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
42217
- const mediaH = mediaBox[3] - mediaBox[1];
42218
- const bx = Math.round((cropBox[0] - mediaBox[0]) * scaleX);
42219
- const by = Math.round((mediaH - (cropBox[3] - mediaBox[1])) * scaleY);
42220
- const bw = Math.max(1, Math.round(Math.abs(cropBox[2] - cropBox[0]) * scaleX));
42221
- const bh = Math.max(1, Math.round(Math.abs(cropBox[3] - cropBox[1]) * scaleY));
42222
- bitmap = cropRgbaBitmap(bitmap, { x: bx, y: by, width: bw, height: bh });
42223
- }
42224
- }
42225
- const rotation = page.getRotation();
42226
- if (rotation === 90 || rotation === 180 || rotation === 270) {
42227
- bitmap = rotateRgbaBitmapQuarterTurns(bitmap, rotation);
42228
- }
42229
- if (cropRect) {
42230
- bitmap = cropRgbaBitmap(bitmap, cropRect);
42231
- }
42232
- return bitmap;
45100
+ return page.renderToBitmap(options);
42233
45101
  }
42234
45102
  function renderPdfPageToPng(pdfBytes, pageIndex = 0, options) {
42235
45103
  const bmp = renderPdfPageToBitmap(pdfBytes, pageIndex, options);
@@ -43063,6 +45931,7 @@ export {
43063
45931
  formatPdfNumber,
43064
45932
  generateDocumentFormAppearances,
43065
45933
  generateToUnicodeCMap,
45934
+ getDisplayListCropBox,
43066
45935
  getDocumentFormFields,
43067
45936
  glyphNameToUnicode,
43068
45937
  isOptionalContentVisible,