@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
@@ -3588,6 +3588,11 @@ var FONT_IDENTITY_MATRIX = [1e-3, 0, 0, 1e-3, 0, 0];
3588
3588
  var LINE_FACTOR = 1.35;
3589
3589
  var LINE_DESCENT_FACTOR = 0.35;
3590
3590
  var BASELINE_FACTOR = LINE_DESCENT_FACTOR / LINE_FACTOR;
3591
+ var MeshFigureType = {
3592
+ TRIANGLES: 1,
3593
+ LATTICE: 2,
3594
+ PATCH: 3
3595
+ };
3591
3596
  var VerbosityLevel = {
3592
3597
  ERRORS: 0,
3593
3598
  WARNINGS: 1,
@@ -22706,6 +22711,3308 @@ var PageViewport = class _PageViewport {
22706
22711
  return p;
22707
22712
  }
22708
22713
  };
22714
+ function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
22715
+ const COMPONENTS = 3;
22716
+ alpha01 = alpha01 !== 1 ? 0 : alpha01;
22717
+ const xRatio = w1 / w2;
22718
+ const yRatio = h1 / h2;
22719
+ let newIndex = 0, oldIndex;
22720
+ const xScaled = new Uint16Array(w2);
22721
+ const w1Scanline = w1 * COMPONENTS;
22722
+ for (let i = 0; i < w2; i++) {
22723
+ xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
22724
+ }
22725
+ for (let i = 0; i < h2; i++) {
22726
+ const py = Math.floor(i * yRatio) * w1Scanline;
22727
+ for (let j = 0; j < w2; j++) {
22728
+ oldIndex = py + xScaled[j];
22729
+ dest[newIndex++] = src[oldIndex++];
22730
+ dest[newIndex++] = src[oldIndex++];
22731
+ dest[newIndex++] = src[oldIndex++];
22732
+ newIndex += alpha01;
22733
+ }
22734
+ }
22735
+ }
22736
+ function isDefaultDecodeHelper(decode, expectedLen) {
22737
+ if (!Array.isArray(decode)) {
22738
+ return true;
22739
+ }
22740
+ const decodeLen = decode.length;
22741
+ if (decodeLen < expectedLen) {
22742
+ warn2("Decode map length is too short.");
22743
+ return true;
22744
+ }
22745
+ if (decodeLen > expectedLen) {
22746
+ info("Truncating too long decode map.");
22747
+ decode.length = expectedLen;
22748
+ }
22749
+ return false;
22750
+ }
22751
+ var ColorSpace = class _ColorSpace {
22752
+ static #rgbBuf = new Uint8ClampedArray(3);
22753
+ constructor(name, numComps) {
22754
+ if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _ColorSpace) {
22755
+ unreachable2("Cannot initialize ColorSpace.");
22756
+ }
22757
+ this.name = name;
22758
+ this.numComps = numComps;
22759
+ }
22760
+ /**
22761
+ * Converts the color value to the RGB color. The color components are
22762
+ * located in the src array starting from the srcOffset. Returns the array
22763
+ * of the rgb components, each value ranging from [0,255].
22764
+ */
22765
+ getRgb(src, srcOffset, output = new Uint8ClampedArray(3)) {
22766
+ this.getRgbItem(src, srcOffset, output, 0);
22767
+ return output;
22768
+ }
22769
+ getRgbHex(src, srcOffset) {
22770
+ const buffer = this.getRgb(src, srcOffset, _ColorSpace.#rgbBuf);
22771
+ return Util.makeHexColor(buffer[0], buffer[1], buffer[2]);
22772
+ }
22773
+ /**
22774
+ * Converts the color value to the RGB color, similar to the getRgb method.
22775
+ * The result placed into the dest array starting from the destOffset.
22776
+ */
22777
+ getRgbItem(src, srcOffset, dest, destOffset) {
22778
+ unreachable2("Should not call ColorSpace.getRgbItem");
22779
+ }
22780
+ /**
22781
+ * Converts the specified number of the color values to the RGB colors.
22782
+ * The colors are located in the src array starting from the srcOffset.
22783
+ * The result is placed into the dest array starting from the destOffset.
22784
+ * The src array items shall be in [0,2^bits) range, the dest array items
22785
+ * will be in [0,255] range. alpha01 indicates how many alpha components
22786
+ * there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
22787
+ * array).
22788
+ */
22789
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
22790
+ unreachable2("Should not call ColorSpace.getRgbBuffer");
22791
+ }
22792
+ /**
22793
+ * Converts `count` unscaled colors to RGB, starting at `destOffset`.
22794
+ * Components use the native color-space ranges expected by `getRgbItem`,
22795
+ * and each output has a `3 + alpha01` byte stride.
22796
+ * Subclasses may override this to batch expensive conversions.
22797
+ */
22798
+ getRgbItems(src, count, dest, destOffset, alpha01) {
22799
+ const { numComps } = this;
22800
+ for (let i = 0, srcOffset = 0; i < count; i++, srcOffset += numComps) {
22801
+ this.getRgbItem(src, srcOffset, dest, destOffset);
22802
+ destOffset += 3 + alpha01;
22803
+ }
22804
+ }
22805
+ /**
22806
+ * Returns true if source data will be equal the result/output data.
22807
+ */
22808
+ isPassthrough(bits) {
22809
+ return false;
22810
+ }
22811
+ /**
22812
+ * Refer to the static `ColorSpace.isDefaultDecode` method below.
22813
+ */
22814
+ isDefaultDecode(decode, bpc) {
22815
+ return _ColorSpace.isDefaultDecode(decode, this.numComps);
22816
+ }
22817
+ /**
22818
+ * Fills in the RGB colors in the destination buffer. alpha01 indicates
22819
+ * how many alpha components there are in the dest array; it will be either
22820
+ * 0 (RGB array) or 1 (RGBA array).
22821
+ */
22822
+ fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {
22823
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22824
+ assert2(
22825
+ dest instanceof Uint8ClampedArray,
22826
+ 'ColorSpace.fillRgb: Unsupported "dest" type.'
22827
+ );
22828
+ }
22829
+ const count = originalWidth * originalHeight;
22830
+ let rgbBuf = null;
22831
+ const numComponentColors = 1 << bpc;
22832
+ const needsResizing = originalHeight !== height || originalWidth !== width;
22833
+ if (this.isPassthrough(bpc)) {
22834
+ rgbBuf = comps;
22835
+ } else if (this.numComps === 1 && count > numComponentColors && this.name !== "DeviceGray" && this.name !== "DeviceRGB") {
22836
+ const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);
22837
+ for (let i = 0; i < numComponentColors; i++) {
22838
+ allColors[i] = i;
22839
+ }
22840
+ const colorMap = new Uint8ClampedArray(numComponentColors * 3);
22841
+ this.getRgbBuffer(
22842
+ allColors,
22843
+ 0,
22844
+ numComponentColors,
22845
+ colorMap,
22846
+ 0,
22847
+ bpc,
22848
+ /* alpha01 = */
22849
+ 0
22850
+ );
22851
+ if (!needsResizing) {
22852
+ let destPos = 0;
22853
+ for (let i = 0; i < count; ++i) {
22854
+ const key = comps[i] * 3;
22855
+ dest[destPos++] = colorMap[key];
22856
+ dest[destPos++] = colorMap[key + 1];
22857
+ dest[destPos++] = colorMap[key + 2];
22858
+ destPos += alpha01;
22859
+ }
22860
+ } else {
22861
+ rgbBuf = new Uint8Array(count * 3);
22862
+ let rgbPos = 0;
22863
+ for (let i = 0; i < count; ++i) {
22864
+ const key = comps[i] * 3;
22865
+ rgbBuf[rgbPos++] = colorMap[key];
22866
+ rgbBuf[rgbPos++] = colorMap[key + 1];
22867
+ rgbBuf[rgbPos++] = colorMap[key + 2];
22868
+ }
22869
+ }
22870
+ } else if (!needsResizing) {
22871
+ this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);
22872
+ } else {
22873
+ rgbBuf = new Uint8ClampedArray(count * 3);
22874
+ this.getRgbBuffer(
22875
+ comps,
22876
+ 0,
22877
+ count,
22878
+ rgbBuf,
22879
+ 0,
22880
+ bpc,
22881
+ /* alpha01 = */
22882
+ 0
22883
+ );
22884
+ }
22885
+ if (rgbBuf) {
22886
+ if (needsResizing) {
22887
+ resizeRgbImage(
22888
+ rgbBuf,
22889
+ dest,
22890
+ originalWidth,
22891
+ originalHeight,
22892
+ width,
22893
+ height,
22894
+ alpha01
22895
+ );
22896
+ } else {
22897
+ let destPos = 0, rgbPos = 0;
22898
+ for (let i = 0, ii = width * actualHeight; i < ii; i++) {
22899
+ dest[destPos++] = rgbBuf[rgbPos++];
22900
+ dest[destPos++] = rgbBuf[rgbPos++];
22901
+ dest[destPos++] = rgbBuf[rgbPos++];
22902
+ destPos += alpha01;
22903
+ }
22904
+ }
22905
+ }
22906
+ }
22907
+ /**
22908
+ * True if the colorspace has components in the default range of [0, 1].
22909
+ * This should be true for all colorspaces except for lab color spaces
22910
+ * which are [0,100], [-128, 127], [-128, 127].
22911
+ */
22912
+ get usesZeroToOneRange() {
22913
+ return shadow2(this, "usesZeroToOneRange", true);
22914
+ }
22915
+ /**
22916
+ * Checks if a decode map matches the default decode map for a color space.
22917
+ * This handles the general decode maps where there are two values per
22918
+ * component, e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
22919
+ * This does not handle Lab, Indexed, or Pattern decode maps since they are
22920
+ * slightly different.
22921
+ * @param {Array} decode - Decode map (usually from an image).
22922
+ * @param {number} numComps - Number of components the color space has.
22923
+ */
22924
+ static isDefaultDecode(decode, numComps) {
22925
+ if (isDefaultDecodeHelper(decode, numComps * 2)) {
22926
+ return true;
22927
+ }
22928
+ for (let i = 0, ii = decode.length; i < ii; i += 2) {
22929
+ if (decode[i] !== 0 || decode[i + 1] !== 1) {
22930
+ return false;
22931
+ }
22932
+ }
22933
+ return true;
22934
+ }
22935
+ };
22936
+ var DeviceCmykCS = class extends ColorSpace {
22937
+ constructor() {
22938
+ super("DeviceCMYK", 4);
22939
+ }
22940
+ // The coefficients below was found using numerical analysis: the method of
22941
+ // steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
22942
+ // where color_value is the tabular value from the table of sampled RGB colors
22943
+ // from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
22944
+ // CMYK color conversion using the estimation below:
22945
+ // f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
22946
+ #toRgb(src, srcOffset, srcScale, dest, destOffset) {
22947
+ const c = src[srcOffset] * srcScale;
22948
+ const m = src[srcOffset + 1] * srcScale;
22949
+ const y = src[srcOffset + 2] * srcScale;
22950
+ const k = src[srcOffset + 3] * srcScale;
22951
+ 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);
22952
+ 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);
22953
+ 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);
22954
+ }
22955
+ getRgbItem(src, srcOffset, dest, destOffset) {
22956
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22957
+ assert2(
22958
+ dest instanceof Uint8ClampedArray,
22959
+ 'DeviceCmykCS.getRgbItem: Unsupported "dest" type.'
22960
+ );
22961
+ }
22962
+ this.#toRgb(src, srcOffset, 1, dest, destOffset);
22963
+ }
22964
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
22965
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22966
+ assert2(
22967
+ dest instanceof Uint8ClampedArray,
22968
+ 'DeviceCmykCS.getRgbBuffer: Unsupported "dest" type.'
22969
+ );
22970
+ }
22971
+ const scale = 1 / ((1 << bits) - 1);
22972
+ for (let i = 0; i < count; i++) {
22973
+ this.#toRgb(src, srcOffset, scale, dest, destOffset);
22974
+ srcOffset += 4;
22975
+ destOffset += 3 + alpha01;
22976
+ }
22977
+ }
22978
+ };
22979
+ var CalGrayCS = class extends ColorSpace {
22980
+ constructor(whitePoint, blackPoint, gamma) {
22981
+ super("CalGray", 1);
22982
+ if (!whitePoint) {
22983
+ throw new FormatError(
22984
+ "WhitePoint missing - required for color space CalGray"
22985
+ );
22986
+ }
22987
+ [this.XW, this.YW, this.ZW] = whitePoint;
22988
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
22989
+ this.G = gamma || 1;
22990
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
22991
+ throw new FormatError(
22992
+ `Invalid WhitePoint components for ${this.name}, no fallback available`
22993
+ );
22994
+ }
22995
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
22996
+ info(`Invalid BlackPoint for ${this.name}, falling back to default.`);
22997
+ this.XB = this.YB = this.ZB = 0;
22998
+ }
22999
+ if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
23000
+ warn2(
23001
+ `${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ZB: ${this.ZB}, only default values are supported.`
23002
+ );
23003
+ }
23004
+ if (this.G < 1) {
23005
+ info(
23006
+ `Invalid Gamma: ${this.G} for ${this.name}, falling back to default.`
23007
+ );
23008
+ this.G = 1;
23009
+ }
23010
+ }
23011
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
23012
+ const A = src[srcOffset] * scale;
23013
+ const AG = A ** this.G;
23014
+ const L = this.YW * AG;
23015
+ const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0);
23016
+ dest[destOffset] = val;
23017
+ dest[destOffset + 1] = val;
23018
+ dest[destOffset + 2] = val;
23019
+ }
23020
+ getRgbItem(src, srcOffset, dest, destOffset) {
23021
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23022
+ assert2(
23023
+ dest instanceof Uint8ClampedArray,
23024
+ 'CalGrayCS.getRgbItem: Unsupported "dest" type.'
23025
+ );
23026
+ }
23027
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
23028
+ }
23029
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
23030
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23031
+ assert2(
23032
+ dest instanceof Uint8ClampedArray,
23033
+ 'CalGrayCS.getRgbBuffer: Unsupported "dest" type.'
23034
+ );
23035
+ }
23036
+ const scale = 1 / ((1 << bits) - 1);
23037
+ for (let i = 0; i < count; ++i) {
23038
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
23039
+ srcOffset += 1;
23040
+ destOffset += 3 + alpha01;
23041
+ }
23042
+ }
23043
+ };
23044
+ var CalRGBCS = class _CalRGBCS extends ColorSpace {
23045
+ // See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these
23046
+ // matrices.
23047
+ // prettier-ignore
23048
+ static #BRADFORD_SCALE_MATRIX = new Float32Array([
23049
+ 0.8951,
23050
+ 0.2664,
23051
+ -0.1614,
23052
+ -0.7502,
23053
+ 1.7135,
23054
+ 0.0367,
23055
+ 0.0389,
23056
+ -0.0685,
23057
+ 1.0296
23058
+ ]);
23059
+ // prettier-ignore
23060
+ static #BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([
23061
+ 0.9869929,
23062
+ -0.1470543,
23063
+ 0.1599627,
23064
+ 0.4323053,
23065
+ 0.5183603,
23066
+ 0.0492912,
23067
+ -85287e-7,
23068
+ 0.0400428,
23069
+ 0.9684867
23070
+ ]);
23071
+ // See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html.
23072
+ // prettier-ignore
23073
+ static #SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([
23074
+ 3.2404542,
23075
+ -1.5371385,
23076
+ -0.4985314,
23077
+ -0.969266,
23078
+ 1.8760108,
23079
+ 0.041556,
23080
+ 0.0556434,
23081
+ -0.2040259,
23082
+ 1.0572252
23083
+ ]);
23084
+ static #FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);
23085
+ static #tempNormalizeMatrix = new Float32Array(3);
23086
+ static #tempConvertMatrix1 = new Float32Array(3);
23087
+ static #tempConvertMatrix2 = new Float32Array(3);
23088
+ static #DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8;
23089
+ constructor(whitePoint, blackPoint, gamma, matrix) {
23090
+ super("CalRGB", 3);
23091
+ if (!whitePoint) {
23092
+ throw new FormatError(
23093
+ "WhitePoint missing - required for color space CalRGB"
23094
+ );
23095
+ }
23096
+ const [XW, YW, ZW] = this.whitePoint = whitePoint;
23097
+ const [XB, YB, ZB] = this.blackPoint = blackPoint || new Float32Array(3);
23098
+ [this.GR, this.GG, this.GB] = gamma || new Float32Array([1, 1, 1]);
23099
+ [
23100
+ this.MXA,
23101
+ this.MYA,
23102
+ this.MZA,
23103
+ this.MXB,
23104
+ this.MYB,
23105
+ this.MZB,
23106
+ this.MXC,
23107
+ this.MYC,
23108
+ this.MZC
23109
+ ] = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
23110
+ if (XW < 0 || ZW < 0 || YW !== 1) {
23111
+ throw new FormatError(
23112
+ `Invalid WhitePoint components for ${this.name}, no fallback available`
23113
+ );
23114
+ }
23115
+ if (XB < 0 || YB < 0 || ZB < 0) {
23116
+ info(
23117
+ `Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], falling back to default.`
23118
+ );
23119
+ this.blackPoint = new Float32Array(3);
23120
+ }
23121
+ if (this.GR < 0 || this.GG < 0 || this.GB < 0) {
23122
+ info(
23123
+ `Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ${this.name}, falling back to default.`
23124
+ );
23125
+ this.GR = this.GG = this.GB = 1;
23126
+ }
23127
+ }
23128
+ #matrixProduct(a, b, result) {
23129
+ result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
23130
+ result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
23131
+ result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
23132
+ }
23133
+ #toFlat(sourceWhitePoint, LMS, result) {
23134
+ result[0] = LMS[0] * 1 / sourceWhitePoint[0];
23135
+ result[1] = LMS[1] * 1 / sourceWhitePoint[1];
23136
+ result[2] = LMS[2] * 1 / sourceWhitePoint[2];
23137
+ }
23138
+ #toD65(sourceWhitePoint, LMS, result) {
23139
+ const D65X = 0.95047;
23140
+ const D65Y = 1;
23141
+ const D65Z = 1.08883;
23142
+ result[0] = LMS[0] * D65X / sourceWhitePoint[0];
23143
+ result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
23144
+ result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
23145
+ }
23146
+ #sRGBTransferFunction(color) {
23147
+ if (color <= 31308e-7) {
23148
+ return MathClamp(12.92 * color, 0, 1);
23149
+ }
23150
+ return color >= 0.99554525 ? 1 : MathClamp((1 + 0.055) * color ** (1 / 2.4) - 0.055, 0, 1);
23151
+ }
23152
+ #decodeL(L) {
23153
+ if (L < 0) {
23154
+ return -this.#decodeL(-L);
23155
+ }
23156
+ return L > 8 ? ((L + 16) / 116) ** 3 : L * _CalRGBCS.#DECODE_L_CONSTANT;
23157
+ }
23158
+ #compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
23159
+ if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {
23160
+ result[0] = XYZ_Flat[0];
23161
+ result[1] = XYZ_Flat[1];
23162
+ result[2] = XYZ_Flat[2];
23163
+ return;
23164
+ }
23165
+ const zeroDecodeL = this.#decodeL(0);
23166
+ const X_DST = zeroDecodeL;
23167
+ const X_SRC = this.#decodeL(sourceBlackPoint[0]);
23168
+ const Y_DST = zeroDecodeL;
23169
+ const Y_SRC = this.#decodeL(sourceBlackPoint[1]);
23170
+ const Z_DST = zeroDecodeL;
23171
+ const Z_SRC = this.#decodeL(sourceBlackPoint[2]);
23172
+ const X_Scale = (1 - X_DST) / (1 - X_SRC);
23173
+ const X_Offset = 1 - X_Scale;
23174
+ const Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
23175
+ const Y_Offset = 1 - Y_Scale;
23176
+ const Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
23177
+ const Z_Offset = 1 - Z_Scale;
23178
+ result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
23179
+ result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
23180
+ result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
23181
+ }
23182
+ #normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
23183
+ if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
23184
+ result[0] = XYZ_In[0];
23185
+ result[1] = XYZ_In[1];
23186
+ result[2] = XYZ_In[2];
23187
+ return;
23188
+ }
23189
+ const LMS = result;
23190
+ this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
23191
+ const LMS_Flat = _CalRGBCS.#tempNormalizeMatrix;
23192
+ this.#toFlat(sourceWhitePoint, LMS, LMS_Flat);
23193
+ this.#matrixProduct(
23194
+ _CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
23195
+ LMS_Flat,
23196
+ result
23197
+ );
23198
+ }
23199
+ #normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
23200
+ const LMS = result;
23201
+ this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
23202
+ const LMS_D65 = _CalRGBCS.#tempNormalizeMatrix;
23203
+ this.#toD65(sourceWhitePoint, LMS, LMS_D65);
23204
+ this.#matrixProduct(
23205
+ _CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
23206
+ LMS_D65,
23207
+ result
23208
+ );
23209
+ }
23210
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
23211
+ const A = MathClamp(src[srcOffset] * scale, 0, 1);
23212
+ const B = MathClamp(src[srcOffset + 1] * scale, 0, 1);
23213
+ const C = MathClamp(src[srcOffset + 2] * scale, 0, 1);
23214
+ const AGR = A === 1 ? 1 : A ** this.GR;
23215
+ const BGG = B === 1 ? 1 : B ** this.GG;
23216
+ const CGB = C === 1 ? 1 : C ** this.GB;
23217
+ const X = this.MXA * AGR + this.MXB * BGG + this.MXC * CGB;
23218
+ const Y = this.MYA * AGR + this.MYB * BGG + this.MYC * CGB;
23219
+ const Z = this.MZA * AGR + this.MZB * BGG + this.MZC * CGB;
23220
+ const XYZ = _CalRGBCS.#tempConvertMatrix1;
23221
+ XYZ[0] = X;
23222
+ XYZ[1] = Y;
23223
+ XYZ[2] = Z;
23224
+ const XYZ_Flat = _CalRGBCS.#tempConvertMatrix2;
23225
+ this.#normalizeWhitePointToFlat(this.whitePoint, XYZ, XYZ_Flat);
23226
+ const XYZ_Black = _CalRGBCS.#tempConvertMatrix1;
23227
+ this.#compensateBlackPoint(this.blackPoint, XYZ_Flat, XYZ_Black);
23228
+ const XYZ_D65 = _CalRGBCS.#tempConvertMatrix2;
23229
+ this.#normalizeWhitePointToD65(
23230
+ _CalRGBCS.#FLAT_WHITEPOINT_MATRIX,
23231
+ XYZ_Black,
23232
+ XYZ_D65
23233
+ );
23234
+ const SRGB = _CalRGBCS.#tempConvertMatrix1;
23235
+ this.#matrixProduct(_CalRGBCS.#SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
23236
+ dest[destOffset] = this.#sRGBTransferFunction(SRGB[0]) * 255;
23237
+ dest[destOffset + 1] = this.#sRGBTransferFunction(SRGB[1]) * 255;
23238
+ dest[destOffset + 2] = this.#sRGBTransferFunction(SRGB[2]) * 255;
23239
+ }
23240
+ getRgbItem(src, srcOffset, dest, destOffset) {
23241
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23242
+ assert2(
23243
+ dest instanceof Uint8ClampedArray,
23244
+ 'CalRGBCS.getRgbItem: Unsupported "dest" type.'
23245
+ );
23246
+ }
23247
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
23248
+ }
23249
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
23250
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23251
+ assert2(
23252
+ dest instanceof Uint8ClampedArray,
23253
+ 'CalRGBCS.getRgbBuffer: Unsupported "dest" type.'
23254
+ );
23255
+ }
23256
+ const scale = 1 / ((1 << bits) - 1);
23257
+ for (let i = 0; i < count; ++i) {
23258
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
23259
+ srcOffset += 3;
23260
+ destOffset += 3 + alpha01;
23261
+ }
23262
+ }
23263
+ };
23264
+ var LabCS = class extends ColorSpace {
23265
+ constructor(whitePoint, blackPoint, range) {
23266
+ super("Lab", 3);
23267
+ if (!whitePoint) {
23268
+ throw new FormatError(
23269
+ "WhitePoint missing - required for color space Lab"
23270
+ );
23271
+ }
23272
+ [this.XW, this.YW, this.ZW] = whitePoint;
23273
+ [this.amin, this.amax, this.bmin, this.bmax] = range || [
23274
+ -100,
23275
+ 100,
23276
+ -100,
23277
+ 100
23278
+ ];
23279
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
23280
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
23281
+ throw new FormatError(
23282
+ "Invalid WhitePoint components, no fallback available"
23283
+ );
23284
+ }
23285
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
23286
+ info("Invalid BlackPoint, falling back to default");
23287
+ this.XB = this.YB = this.ZB = 0;
23288
+ }
23289
+ if (this.amin > this.amax || this.bmin > this.bmax) {
23290
+ info("Invalid Range, falling back to defaults");
23291
+ this.amin = -100;
23292
+ this.amax = 100;
23293
+ this.bmin = -100;
23294
+ this.bmax = 100;
23295
+ }
23296
+ }
23297
+ // Function g(x) from spec
23298
+ #fn_g(x) {
23299
+ return x >= 6 / 29 ? x ** 3 : 108 / 841 * (x - 4 / 29);
23300
+ }
23301
+ #decode(value, high1, low2, high2) {
23302
+ return low2 + value * (high2 - low2) / high1;
23303
+ }
23304
+ // If decoding is needed maxVal should be 2^bits per component - 1.
23305
+ #toRgb(src, srcOffset, maxVal, dest, destOffset) {
23306
+ let Ls = src[srcOffset];
23307
+ let as = src[srcOffset + 1];
23308
+ let bs = src[srcOffset + 2];
23309
+ if (maxVal !== false) {
23310
+ Ls = this.#decode(Ls, maxVal, 0, 100);
23311
+ as = this.#decode(as, maxVal, this.amin, this.amax);
23312
+ bs = this.#decode(bs, maxVal, this.bmin, this.bmax);
23313
+ }
23314
+ if (as > this.amax) {
23315
+ as = this.amax;
23316
+ } else if (as < this.amin) {
23317
+ as = this.amin;
23318
+ }
23319
+ if (bs > this.bmax) {
23320
+ bs = this.bmax;
23321
+ } else if (bs < this.bmin) {
23322
+ bs = this.bmin;
23323
+ }
23324
+ const M = (Ls + 16) / 116;
23325
+ const L = M + as / 500;
23326
+ const N = M - bs / 200;
23327
+ const X = this.XW * this.#fn_g(L);
23328
+ const Y = this.YW * this.#fn_g(M);
23329
+ const Z = this.ZW * this.#fn_g(N);
23330
+ let r, g, b;
23331
+ if (this.ZW < 1) {
23332
+ r = X * 3.1339 + Y * -1.617 + Z * -0.4906;
23333
+ g = X * -0.9785 + Y * 1.916 + Z * 0.0333;
23334
+ b = X * 0.072 + Y * -0.229 + Z * 1.4057;
23335
+ } else {
23336
+ r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
23337
+ g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
23338
+ b = X * 0.0557 + Y * -0.204 + Z * 1.057;
23339
+ }
23340
+ dest[destOffset] = Math.sqrt(r) * 255;
23341
+ dest[destOffset + 1] = Math.sqrt(g) * 255;
23342
+ dest[destOffset + 2] = Math.sqrt(b) * 255;
23343
+ }
23344
+ getRgbItem(src, srcOffset, dest, destOffset) {
23345
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23346
+ assert2(
23347
+ dest instanceof Uint8ClampedArray,
23348
+ 'LabCS.getRgbItem: Unsupported "dest" type.'
23349
+ );
23350
+ }
23351
+ this.#toRgb(src, srcOffset, false, dest, destOffset);
23352
+ }
23353
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
23354
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23355
+ assert2(
23356
+ dest instanceof Uint8ClampedArray,
23357
+ 'LabCS.getRgbBuffer: Unsupported "dest" type.'
23358
+ );
23359
+ }
23360
+ const maxVal = (1 << bits) - 1;
23361
+ for (let i = 0; i < count; i++) {
23362
+ this.#toRgb(src, srcOffset, maxVal, dest, destOffset);
23363
+ srcOffset += 3;
23364
+ destOffset += 3 + alpha01;
23365
+ }
23366
+ }
23367
+ isDefaultDecode(decode, bpc) {
23368
+ return true;
23369
+ }
23370
+ get usesZeroToOneRange() {
23371
+ return shadow2(this, "usesZeroToOneRange", false);
23372
+ }
23373
+ };
23374
+ var TOKEN = {
23375
+ // Structural tokens — not keyword operators
23376
+ number: 0,
23377
+ lbrace: 1,
23378
+ rbrace: 2,
23379
+ // Boolean literals
23380
+ true: 3,
23381
+ false: 4,
23382
+ // Arithmetic binary operators
23383
+ add: 5,
23384
+ sub: 6,
23385
+ mul: 7,
23386
+ div: 8,
23387
+ idiv: 9,
23388
+ mod: 10,
23389
+ exp: 11,
23390
+ // Comparison binary operators
23391
+ eq: 12,
23392
+ ne: 13,
23393
+ gt: 14,
23394
+ ge: 15,
23395
+ lt: 16,
23396
+ le: 17,
23397
+ // Bitwise / boolean binary operators
23398
+ and: 18,
23399
+ or: 19,
23400
+ xor: 20,
23401
+ bitshift: 21,
23402
+ // Unary arithmetic operators
23403
+ abs: 22,
23404
+ neg: 23,
23405
+ ceiling: 24,
23406
+ floor: 25,
23407
+ round: 26,
23408
+ truncate: 27,
23409
+ // Unary boolean / bitwise operator
23410
+ not: 28,
23411
+ // Mathematical functions — unary
23412
+ sqrt: 29,
23413
+ sin: 30,
23414
+ cos: 31,
23415
+ ln: 32,
23416
+ log: 33,
23417
+ // Mathematical function — binary
23418
+ atan: 34,
23419
+ // Type conversion operators
23420
+ cvi: 35,
23421
+ cvr: 36,
23422
+ // Stack operators
23423
+ dup: 37,
23424
+ exch: 38,
23425
+ pop: 39,
23426
+ copy: 40,
23427
+ index: 41,
23428
+ roll: 42,
23429
+ // Control flow
23430
+ if: 43,
23431
+ ifelse: 44,
23432
+ // End of input
23433
+ eof: 45,
23434
+ // Synthetic: produced by the optimizer, never emitted by the lexer.
23435
+ min: 46,
23436
+ max: 47
23437
+ };
23438
+ var Token = class {
23439
+ constructor(id, value = null) {
23440
+ this.id = id;
23441
+ this.value = value;
23442
+ }
23443
+ };
23444
+ var Lexer = class _Lexer {
23445
+ // Singletons for every non-number token, built lazily on first construction.
23446
+ // Keyword operator tokens carry their name as `value`; structural tokens
23447
+ // (lbrace, rbrace, eof) carry null.
23448
+ static #singletons = null;
23449
+ static #operatorSingletons = null;
23450
+ static #initSingletons() {
23451
+ const singletons = /* @__PURE__ */ Object.create(null);
23452
+ const operatorSingletons = /* @__PURE__ */ Object.create(null);
23453
+ for (const [name, id] of Object.entries(TOKEN)) {
23454
+ if (name === "number") {
23455
+ continue;
23456
+ }
23457
+ const isOperator = id >= TOKEN.true && id <= TOKEN.ifelse;
23458
+ const token = new Token(id, isOperator ? name : null);
23459
+ singletons[name] = token;
23460
+ if (isOperator) {
23461
+ operatorSingletons[name] = token;
23462
+ }
23463
+ }
23464
+ this.#singletons = singletons;
23465
+ this.#operatorSingletons = operatorSingletons;
23466
+ }
23467
+ constructor(data) {
23468
+ if (!_Lexer.#singletons) {
23469
+ _Lexer.#initSingletons();
23470
+ }
23471
+ this.data = data;
23472
+ this.pos = 0;
23473
+ this.len = data.length;
23474
+ this._numberPattern = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/iy;
23475
+ this._identifierPattern = /[a-z]+/y;
23476
+ }
23477
+ // Skip a % comment, advancing past the next \n or \r (or to EOF).
23478
+ _skipComment() {
23479
+ const lf = this.data.indexOf("\n", this.pos);
23480
+ const cr = this.data.indexOf("\r", this.pos);
23481
+ const eol = Math.min(lf < 0 ? this.len : lf, cr < 0 ? this.len : cr);
23482
+ this.pos = Math.min(eol + 1, this.len);
23483
+ }
23484
+ _getNumber() {
23485
+ this._numberPattern.lastIndex = this.pos;
23486
+ const match = this._numberPattern.exec(this.data);
23487
+ if (!match) {
23488
+ return new Token(TOKEN.number, 0);
23489
+ }
23490
+ const number = parseFloat(match[0]);
23491
+ if (!Number.isFinite(number)) {
23492
+ return new Token(TOKEN.number, 0);
23493
+ }
23494
+ this.pos = this._numberPattern.lastIndex;
23495
+ return new Token(TOKEN.number, number);
23496
+ }
23497
+ _getOperator() {
23498
+ this._identifierPattern.lastIndex = this.pos;
23499
+ const match = this._identifierPattern.exec(this.data);
23500
+ if (!match) {
23501
+ return new Token(TOKEN.number, 0);
23502
+ }
23503
+ this.pos = this._identifierPattern.lastIndex;
23504
+ const op = match[0];
23505
+ const token = _Lexer.#operatorSingletons[op];
23506
+ return token ?? new Token(TOKEN.number, 0);
23507
+ }
23508
+ // Return the next token, or Lexer.#singletons.eof at end of input.
23509
+ next() {
23510
+ while (this.pos < this.len) {
23511
+ const ch3 = this.data.charCodeAt(this.pos++);
23512
+ switch (ch3) {
23513
+ // PostScript white-space characters (PDF32000 §7.2.2)
23514
+ case 0:
23515
+ case 9:
23516
+ case 10:
23517
+ case 12:
23518
+ case 13:
23519
+ case 32:
23520
+ break;
23521
+ case 37:
23522
+ this._skipComment();
23523
+ break;
23524
+ case 123:
23525
+ return _Lexer.#singletons.lbrace;
23526
+ case 125:
23527
+ return _Lexer.#singletons.rbrace;
23528
+ case 43:
23529
+ case 45:
23530
+ this.pos--;
23531
+ return this._getNumber();
23532
+ case 46:
23533
+ this.pos--;
23534
+ return this._getNumber();
23535
+ default:
23536
+ if (ch3 >= 48 && ch3 <= 57) {
23537
+ this.pos--;
23538
+ return this._getNumber();
23539
+ }
23540
+ if (ch3 >= 97 && ch3 <= 122) {
23541
+ this.pos--;
23542
+ return this._getOperator();
23543
+ }
23544
+ return new Token(TOKEN.number, 0);
23545
+ }
23546
+ }
23547
+ return _Lexer.#singletons.eof;
23548
+ }
23549
+ };
23550
+ var PS_VALUE_TYPE = {
23551
+ numeric: 0,
23552
+ // known to be a number (f64 in Wasm)
23553
+ boolean: 1,
23554
+ // known to be a boolean (0.0 = false, 1.0 = true in f64)
23555
+ unknown: 2
23556
+ // indeterminate at compile time
23557
+ };
23558
+ var PS_NODE = {
23559
+ // Parser AST node types (produced by Parser / parsePostScriptFunction)
23560
+ program: 0,
23561
+ block: 1,
23562
+ number: 2,
23563
+ operator: 3,
23564
+ if: 4,
23565
+ ifelse: 5,
23566
+ // Tree AST node types (produced by PSStackToTree)
23567
+ arg: 6,
23568
+ const: 7,
23569
+ unary: 8,
23570
+ binary: 9,
23571
+ ternary: 10
23572
+ };
23573
+ var PsNode = class {
23574
+ constructor(type) {
23575
+ this.type = type;
23576
+ }
23577
+ };
23578
+ var PsProgram = class extends PsNode {
23579
+ constructor(body) {
23580
+ super(PS_NODE.program);
23581
+ this.body = body;
23582
+ }
23583
+ };
23584
+ var PsBlock = class extends PsNode {
23585
+ constructor(instructions) {
23586
+ super(PS_NODE.block);
23587
+ this.instructions = instructions;
23588
+ }
23589
+ };
23590
+ var PsNumber = class extends PsNode {
23591
+ /** @param {number} value */
23592
+ constructor(value) {
23593
+ super(PS_NODE.number);
23594
+ this.value = value;
23595
+ }
23596
+ };
23597
+ var PsOperator = class extends PsNode {
23598
+ /** @param {number} op — one of the TOKEN.* constants from lexer.js */
23599
+ constructor(op) {
23600
+ super(PS_NODE.operator);
23601
+ this.op = op;
23602
+ }
23603
+ };
23604
+ var PsIf = class extends PsNode {
23605
+ /** @param {PsBlock} then */
23606
+ constructor(then) {
23607
+ super(PS_NODE.if);
23608
+ this.then = then;
23609
+ }
23610
+ };
23611
+ var PsIfElse = class extends PsNode {
23612
+ /**
23613
+ * @param {PsBlock} then
23614
+ * @param {PsBlock} otherwise
23615
+ */
23616
+ constructor(then, otherwise) {
23617
+ super(PS_NODE.ifelse);
23618
+ this.then = then;
23619
+ this.otherwise = otherwise;
23620
+ }
23621
+ };
23622
+ var PsArgNode = class extends PsNode {
23623
+ /** @param {number} index */
23624
+ constructor(index) {
23625
+ super(PS_NODE.arg);
23626
+ this.index = index;
23627
+ this.valueType = PS_VALUE_TYPE.numeric;
23628
+ }
23629
+ };
23630
+ var PsConstNode = class extends PsNode {
23631
+ /** @param {number|boolean} value */
23632
+ constructor(value) {
23633
+ super(PS_NODE.const);
23634
+ this.value = value;
23635
+ this.valueType = typeof value === "boolean" ? PS_VALUE_TYPE.boolean : PS_VALUE_TYPE.numeric;
23636
+ }
23637
+ };
23638
+ var PsUnaryNode = class extends PsNode {
23639
+ /**
23640
+ * @param {number} op — TOKEN.* constant
23641
+ * @param {PsNode} operand
23642
+ * @param {number} [valueType]
23643
+ */
23644
+ constructor(op, operand, valueType = PS_VALUE_TYPE.unknown) {
23645
+ super(PS_NODE.unary);
23646
+ this.op = op;
23647
+ this.operand = operand;
23648
+ this.valueType = valueType;
23649
+ }
23650
+ };
23651
+ var PsBinaryNode = class extends PsNode {
23652
+ /**
23653
+ * @param {number} op — TOKEN.* constant
23654
+ * @param {PsNode} first — was on top of stack
23655
+ * @param {PsNode} second — was below top
23656
+ * @param {number} [valueType]
23657
+ */
23658
+ constructor(op, first, second, valueType = PS_VALUE_TYPE.unknown) {
23659
+ super(PS_NODE.binary);
23660
+ this.op = op;
23661
+ this.first = first;
23662
+ this.second = second;
23663
+ this.valueType = valueType;
23664
+ }
23665
+ };
23666
+ var PsTernaryNode = class extends PsNode {
23667
+ /**
23668
+ * @param {PsNode} cond
23669
+ * @param {PsNode} then
23670
+ * @param {PsNode} otherwise
23671
+ * @param {number} [valueType]
23672
+ */
23673
+ constructor(cond, then, otherwise, valueType = PS_VALUE_TYPE.unknown) {
23674
+ super(PS_NODE.ternary);
23675
+ this.cond = cond;
23676
+ this.then = then;
23677
+ this.otherwise = otherwise;
23678
+ this.valueType = valueType;
23679
+ }
23680
+ };
23681
+ var Parser = class _Parser {
23682
+ constructor(lexer) {
23683
+ this.lexer = lexer;
23684
+ this._token = null;
23685
+ }
23686
+ static _isRegularOperator(id) {
23687
+ return id >= TOKEN.true && id < TOKEN.if;
23688
+ }
23689
+ // Fetch the next token from the lexer.
23690
+ _advance() {
23691
+ this._token = this.lexer.next();
23692
+ }
23693
+ // Assert that the current token has the given id, consume it, and return it.
23694
+ _expect(id) {
23695
+ if (this._token.id !== id) {
23696
+ throw new FormatError(
23697
+ `PostScript function: expected token id ${id}, got ${this._token.id}.`
23698
+ );
23699
+ }
23700
+ const tok = this._token;
23701
+ this._advance();
23702
+ return tok;
23703
+ }
23704
+ /**
23705
+ * Parse the full Type 4 function body.
23706
+ *
23707
+ * Grammar (simplified):
23708
+ * program ::= '{' block '}'
23709
+ * block ::= instruction*
23710
+ * instruction ::= number
23711
+ * | operator (any PS_OPERATOR except if / ifelse)
23712
+ * | '{' block '}' 'if'
23713
+ * | '{' block '}' '{' block '}' 'ifelse'
23714
+ * @returns {PsProgram}
23715
+ */
23716
+ parse() {
23717
+ this._advance();
23718
+ this._expect(TOKEN.lbrace);
23719
+ const block = this._parseBlock();
23720
+ this._expect(TOKEN.rbrace);
23721
+ if (this._token.id !== TOKEN.eof) {
23722
+ warn2("PostScript function: unexpected content after closing brace.");
23723
+ }
23724
+ return new PsProgram(block);
23725
+ }
23726
+ _parseBlock() {
23727
+ const instructions = [];
23728
+ while (true) {
23729
+ const tok = this._token;
23730
+ switch (tok.id) {
23731
+ case TOKEN.number:
23732
+ instructions.push(new PsNumber(tok.value));
23733
+ this._advance();
23734
+ break;
23735
+ case TOKEN.lbrace: {
23736
+ this._advance();
23737
+ const thenBlock = this._parseBlock();
23738
+ this._expect(TOKEN.rbrace);
23739
+ if (this._token.id === TOKEN.if) {
23740
+ this._advance();
23741
+ instructions.push(new PsIf(thenBlock));
23742
+ } else if (this._token.id === TOKEN.lbrace) {
23743
+ this._advance();
23744
+ const elseBlock = this._parseBlock();
23745
+ this._expect(TOKEN.rbrace);
23746
+ this._expect(TOKEN.ifelse);
23747
+ instructions.push(new PsIfElse(thenBlock, elseBlock));
23748
+ } else {
23749
+ throw new FormatError(
23750
+ "PostScript function: a procedure block must be followed by 'if' or '{\u2026} ifelse'."
23751
+ );
23752
+ }
23753
+ break;
23754
+ }
23755
+ case TOKEN.rbrace:
23756
+ case TOKEN.eof:
23757
+ return new PsBlock(instructions);
23758
+ case TOKEN.if:
23759
+ case TOKEN.ifelse:
23760
+ throw new FormatError(
23761
+ `PostScript function: unexpected '${tok.value}' operator.`
23762
+ );
23763
+ default:
23764
+ if (_Parser._isRegularOperator(tok.id)) {
23765
+ instructions.push(new PsOperator(tok.id));
23766
+ this._advance();
23767
+ break;
23768
+ }
23769
+ throw new FormatError(
23770
+ `PostScript function: unexpected token id ${tok.id}.`
23771
+ );
23772
+ }
23773
+ }
23774
+ }
23775
+ };
23776
+ function parsePostScriptFunction(source) {
23777
+ return new Parser(new Lexer(source)).parse();
23778
+ }
23779
+ function _nodesEqual(a, b) {
23780
+ if (a === b) {
23781
+ return true;
23782
+ }
23783
+ if (a.type !== b.type) {
23784
+ return false;
23785
+ }
23786
+ switch (a.type) {
23787
+ case PS_NODE.arg:
23788
+ return a.index === b.index;
23789
+ case PS_NODE.const:
23790
+ return a.value === b.value;
23791
+ case PS_NODE.unary:
23792
+ return a.op === b.op && _nodesEqual(a.operand, b.operand);
23793
+ case PS_NODE.binary:
23794
+ return a.op === b.op && _nodesEqual(a.first, b.first) && _nodesEqual(a.second, b.second);
23795
+ case PS_NODE.ternary:
23796
+ return _nodesEqual(a.cond, b.cond) && _nodesEqual(a.then, b.then) && _nodesEqual(a.otherwise, b.otherwise);
23797
+ default:
23798
+ return false;
23799
+ }
23800
+ }
23801
+ function _evalBinaryConst(op, a, b) {
23802
+ switch (op) {
23803
+ case TOKEN.add:
23804
+ return a + b;
23805
+ case TOKEN.sub:
23806
+ return a - b;
23807
+ case TOKEN.mul:
23808
+ return a * b;
23809
+ case TOKEN.div:
23810
+ return b !== 0 ? a / b : 0;
23811
+ // div by zero → 0
23812
+ case TOKEN.idiv:
23813
+ return b !== 0 ? Math.trunc(a / b) : 0;
23814
+ // div by zero → 0
23815
+ case TOKEN.mod:
23816
+ return b !== 0 ? a - Math.trunc(a / b) * b : 0;
23817
+ // div by zero → 0
23818
+ case TOKEN.exp: {
23819
+ const r = a ** b;
23820
+ return Number.isFinite(r) ? r : void 0;
23821
+ }
23822
+ case TOKEN.atan: {
23823
+ let deg = Math.atan2(a, b) * (180 / Math.PI);
23824
+ if (deg < 0) {
23825
+ deg += 360;
23826
+ }
23827
+ return deg;
23828
+ }
23829
+ case TOKEN.eq:
23830
+ return a === b;
23831
+ case TOKEN.ne:
23832
+ return a !== b;
23833
+ case TOKEN.gt:
23834
+ return a > b;
23835
+ case TOKEN.ge:
23836
+ return a >= b;
23837
+ case TOKEN.lt:
23838
+ return a < b;
23839
+ case TOKEN.le:
23840
+ return a <= b;
23841
+ case TOKEN.and:
23842
+ return typeof a === "boolean" ? a && b : a & b | 0;
23843
+ case TOKEN.or:
23844
+ return typeof a === "boolean" ? a || b : a | b | 0;
23845
+ case TOKEN.xor:
23846
+ return typeof a === "boolean" ? a !== b : a ^ b | 0;
23847
+ case TOKEN.bitshift:
23848
+ return b >= 0 ? a << b | 0 : a >> -b | 0;
23849
+ case TOKEN.min:
23850
+ return Math.min(a, b);
23851
+ case TOKEN.max:
23852
+ return Math.max(a, b);
23853
+ default:
23854
+ return void 0;
23855
+ }
23856
+ }
23857
+ function _evalUnaryConst(op, v) {
23858
+ switch (op) {
23859
+ case TOKEN.abs:
23860
+ return Math.abs(v);
23861
+ case TOKEN.neg:
23862
+ return -v;
23863
+ case TOKEN.ceiling:
23864
+ return Math.ceil(v);
23865
+ case TOKEN.floor:
23866
+ return Math.floor(v);
23867
+ case TOKEN.round:
23868
+ return Math.round(v);
23869
+ case TOKEN.truncate:
23870
+ return Math.trunc(v);
23871
+ case TOKEN.sqrt: {
23872
+ const r = Math.sqrt(v);
23873
+ return Number.isFinite(r) ? r : void 0;
23874
+ }
23875
+ case TOKEN.sin:
23876
+ return Math.sin(v % 360 * Math.PI / 180);
23877
+ case TOKEN.cos:
23878
+ return Math.cos(v % 360 * Math.PI / 180);
23879
+ case TOKEN.ln: {
23880
+ const r = Math.log(v);
23881
+ return Number.isFinite(r) ? r : void 0;
23882
+ }
23883
+ case TOKEN.log: {
23884
+ const r = Math.log10(v);
23885
+ return Number.isFinite(r) ? r : void 0;
23886
+ }
23887
+ case TOKEN.cvi:
23888
+ return Math.trunc(v);
23889
+ case TOKEN.cvr:
23890
+ return v;
23891
+ case TOKEN.not:
23892
+ return typeof v === "boolean" ? !v : ~v;
23893
+ default:
23894
+ return void 0;
23895
+ }
23896
+ }
23897
+ var MAX_STACK_SIZE = 100;
23898
+ function _unaryValueType(op, operandType) {
23899
+ return op === TOKEN.not ? operandType : PS_VALUE_TYPE.numeric;
23900
+ }
23901
+ function _binaryValueType(op, firstType, secondType) {
23902
+ switch (op) {
23903
+ // Comparison operators always produce a boolean.
23904
+ case TOKEN.eq:
23905
+ case TOKEN.ne:
23906
+ case TOKEN.gt:
23907
+ case TOKEN.ge:
23908
+ case TOKEN.lt:
23909
+ case TOKEN.le:
23910
+ return PS_VALUE_TYPE.boolean;
23911
+ // and / or / xor preserve the type when both operands are the same known
23912
+ // type (both boolean or both numeric); otherwise the type is unknown.
23913
+ case TOKEN.and:
23914
+ case TOKEN.or:
23915
+ case TOKEN.xor:
23916
+ return firstType === secondType && firstType !== PS_VALUE_TYPE.unknown ? firstType : PS_VALUE_TYPE.unknown;
23917
+ // All arithmetic / bitshift operators produce a numeric result.
23918
+ default:
23919
+ return PS_VALUE_TYPE.numeric;
23920
+ }
23921
+ }
23922
+ var PSStackToTree = class _PSStackToTree {
23923
+ static #binaryOps = null;
23924
+ static #unaryOps = null;
23925
+ static #idempotentUnary = null;
23926
+ static #negatedComparison = null;
23927
+ static #init() {
23928
+ this.#binaryOps = /* @__PURE__ */ new Set([
23929
+ TOKEN.add,
23930
+ TOKEN.sub,
23931
+ TOKEN.mul,
23932
+ TOKEN.div,
23933
+ TOKEN.idiv,
23934
+ TOKEN.mod,
23935
+ TOKEN.exp,
23936
+ TOKEN.atan,
23937
+ TOKEN.eq,
23938
+ TOKEN.ne,
23939
+ TOKEN.gt,
23940
+ TOKEN.ge,
23941
+ TOKEN.lt,
23942
+ TOKEN.le,
23943
+ TOKEN.and,
23944
+ TOKEN.or,
23945
+ TOKEN.xor,
23946
+ TOKEN.bitshift
23947
+ ]);
23948
+ this.#unaryOps = /* @__PURE__ */ new Set([
23949
+ TOKEN.abs,
23950
+ TOKEN.neg,
23951
+ TOKEN.ceiling,
23952
+ TOKEN.floor,
23953
+ TOKEN.round,
23954
+ TOKEN.truncate,
23955
+ TOKEN.sqrt,
23956
+ TOKEN.sin,
23957
+ TOKEN.cos,
23958
+ TOKEN.ln,
23959
+ TOKEN.log,
23960
+ TOKEN.cvi,
23961
+ TOKEN.cvr,
23962
+ TOKEN.not
23963
+ ]);
23964
+ this.#idempotentUnary = /* @__PURE__ */ new Set([
23965
+ TOKEN.abs,
23966
+ TOKEN.ceiling,
23967
+ TOKEN.cvi,
23968
+ TOKEN.cvr,
23969
+ TOKEN.floor,
23970
+ TOKEN.round,
23971
+ TOKEN.truncate
23972
+ ]);
23973
+ this.#negatedComparison = /* @__PURE__ */ new Map([
23974
+ [TOKEN.eq, TOKEN.ne],
23975
+ [TOKEN.ne, TOKEN.eq],
23976
+ [TOKEN.lt, TOKEN.ge],
23977
+ [TOKEN.le, TOKEN.gt],
23978
+ [TOKEN.gt, TOKEN.le],
23979
+ [TOKEN.ge, TOKEN.lt]
23980
+ ]);
23981
+ }
23982
+ /**
23983
+ * @param {PsProgram} program
23984
+ * @param {number} numInputs — number of domain values placed on the stack
23985
+ * before the program runs (i.e. the length of the domain array / 2).
23986
+ * @returns {Array<PsNode>} — one tree node per output value.
23987
+ */
23988
+ evaluate(program, numInputs) {
23989
+ if (!_PSStackToTree.#binaryOps) {
23990
+ _PSStackToTree.#init();
23991
+ }
23992
+ this._failed = false;
23993
+ if (numInputs > MAX_STACK_SIZE) {
23994
+ return null;
23995
+ }
23996
+ const stack = [];
23997
+ for (let i = 0; i < numInputs; i++) {
23998
+ stack.push(new PsArgNode(i));
23999
+ }
24000
+ this._evalBlock(program.body, stack);
24001
+ if (this._failed) {
24002
+ return null;
24003
+ }
24004
+ _PSStackToTree.#markShared(stack);
24005
+ return stack;
24006
+ }
24007
+ // Set node.shared / sharedCount on non-atomic nodes referenced more than
24008
+ // once. arg/const are excluded — they are cheap to re-emit inline.
24009
+ static #markShared(outputs) {
24010
+ const refCount = /* @__PURE__ */ new Map();
24011
+ const visit = (node) => {
24012
+ if (!node || node.type === PS_NODE.arg || node.type === PS_NODE.const) {
24013
+ return;
24014
+ }
24015
+ const prev = refCount.get(node) ?? 0;
24016
+ refCount.set(node, prev + 1);
24017
+ if (prev > 0) {
24018
+ return;
24019
+ }
24020
+ switch (node.type) {
24021
+ case PS_NODE.unary:
24022
+ visit(node.operand);
24023
+ break;
24024
+ case PS_NODE.binary:
24025
+ visit(node.first);
24026
+ visit(node.second);
24027
+ break;
24028
+ case PS_NODE.ternary:
24029
+ visit(node.cond);
24030
+ visit(node.then);
24031
+ visit(node.otherwise);
24032
+ break;
24033
+ }
24034
+ };
24035
+ for (const output of outputs) {
24036
+ visit(output);
24037
+ }
24038
+ for (const [node, count] of refCount) {
24039
+ if (count > 1) {
24040
+ node.shared = true;
24041
+ node.sharedCount = count;
24042
+ }
24043
+ }
24044
+ }
24045
+ _evalBlock(block, stack) {
24046
+ this._evalBlockFrom(block.instructions, 0, stack);
24047
+ }
24048
+ /**
24049
+ * Core evaluation loop. Processes `instructions[startIdx…]` in order,
24050
+ * mutating `stack` as each instruction executes.
24051
+ *
24052
+ * When a `{ body } if` instruction grows the stack (the PostScript "early
24053
+ * exit / guard" idiom), the remaining instructions in the current array are
24054
+ * evaluated on **both** the true-branch stack and the false-branch stack,
24055
+ * then the two results are merged into PsTernaryNodes. This handles
24056
+ * patterns like:
24057
+ *
24058
+ * cond { pop R G B sentinel } if
24059
+ * … more guards …
24060
+ * sentinel 0 gt { defaultR defaultG defaultB } if
24061
+ */
24062
+ _evalBlockFrom(instructions, startIdx, stack) {
24063
+ for (let idx = startIdx; idx < instructions.length; idx++) {
24064
+ if (this._failed) {
24065
+ break;
24066
+ }
24067
+ const instr = instructions[idx];
24068
+ switch (instr.type) {
24069
+ case PS_NODE.number:
24070
+ stack.push(new PsConstNode(instr.value));
24071
+ if (stack.length > MAX_STACK_SIZE) {
24072
+ this._failed = true;
24073
+ }
24074
+ break;
24075
+ case PS_NODE.operator:
24076
+ this._evalOp(instr.op, stack);
24077
+ break;
24078
+ case PS_NODE.if: {
24079
+ if (stack.length < 1) {
24080
+ this._failed = true;
24081
+ break;
24082
+ }
24083
+ const cond = stack.pop();
24084
+ const saved = stack.slice();
24085
+ this._evalBlock(instr.then, stack);
24086
+ if (this._failed) {
24087
+ break;
24088
+ }
24089
+ if (stack.length === saved.length) {
24090
+ for (let i = 0; i < stack.length; i++) {
24091
+ if (stack[i] !== saved[i]) {
24092
+ stack[i] = this._makeTernary(cond, stack[i], saved[i]);
24093
+ }
24094
+ }
24095
+ } else if (stack.length > saved.length) {
24096
+ if (cond.type === PS_NODE.const) {
24097
+ if (!cond.value) {
24098
+ stack.length = 0;
24099
+ stack.push(...saved);
24100
+ }
24101
+ break;
24102
+ }
24103
+ const trueStack = stack.slice();
24104
+ this._evalBlockFrom(instructions, idx + 1, trueStack);
24105
+ if (this._failed) {
24106
+ break;
24107
+ }
24108
+ const falseStack = saved;
24109
+ this._evalBlockFrom(instructions, idx + 1, falseStack);
24110
+ if (this._failed) {
24111
+ break;
24112
+ }
24113
+ if (trueStack.length !== falseStack.length) {
24114
+ const zero2 = new PsConstNode(0);
24115
+ while (trueStack.length < falseStack.length) {
24116
+ trueStack.push(zero2);
24117
+ }
24118
+ while (falseStack.length < trueStack.length) {
24119
+ falseStack.push(zero2);
24120
+ }
24121
+ }
24122
+ stack.length = 0;
24123
+ for (let i = 0; i < trueStack.length; i++) {
24124
+ stack.push(this._makeTernary(cond, trueStack[i], falseStack[i]));
24125
+ }
24126
+ return;
24127
+ } else {
24128
+ this._failed = true;
24129
+ }
24130
+ break;
24131
+ }
24132
+ case PS_NODE.ifelse: {
24133
+ if (stack.length < 1) {
24134
+ this._failed = true;
24135
+ break;
24136
+ }
24137
+ const cond = stack.pop();
24138
+ const snapshot = stack.slice();
24139
+ const thenStack = snapshot.slice();
24140
+ this._evalBlock(instr.then, thenStack);
24141
+ if (this._failed) {
24142
+ break;
24143
+ }
24144
+ const elseStack = snapshot.slice();
24145
+ this._evalBlock(instr.otherwise, elseStack);
24146
+ if (this._failed) {
24147
+ break;
24148
+ }
24149
+ if (thenStack.length !== elseStack.length) {
24150
+ const zero2 = new PsConstNode(0);
24151
+ while (thenStack.length < elseStack.length) {
24152
+ thenStack.push(zero2);
24153
+ }
24154
+ while (elseStack.length < thenStack.length) {
24155
+ elseStack.push(zero2);
24156
+ }
24157
+ }
24158
+ stack.length = 0;
24159
+ for (let i = 0; i < thenStack.length; i++) {
24160
+ stack.push(this._makeTernary(cond, thenStack[i], elseStack[i]));
24161
+ }
24162
+ break;
24163
+ }
24164
+ }
24165
+ }
24166
+ }
24167
+ _evalOp(op, stack) {
24168
+ if (_PSStackToTree.#binaryOps.has(op)) {
24169
+ if (stack.length < 2) {
24170
+ this._failed = true;
24171
+ return;
24172
+ }
24173
+ const first = stack.pop();
24174
+ const second = stack.pop();
24175
+ stack.push(this._makeBinary(op, first, second));
24176
+ return;
24177
+ }
24178
+ if (_PSStackToTree.#unaryOps.has(op)) {
24179
+ if (stack.length < 1) {
24180
+ this._failed = true;
24181
+ return;
24182
+ }
24183
+ stack.push(this._makeUnary(op, stack.pop()));
24184
+ return;
24185
+ }
24186
+ switch (op) {
24187
+ case TOKEN.true:
24188
+ stack.push(new PsConstNode(true));
24189
+ if (stack.length > MAX_STACK_SIZE) {
24190
+ this._failed = true;
24191
+ }
24192
+ break;
24193
+ case TOKEN.false:
24194
+ stack.push(new PsConstNode(false));
24195
+ if (stack.length > MAX_STACK_SIZE) {
24196
+ this._failed = true;
24197
+ }
24198
+ break;
24199
+ case TOKEN.dup:
24200
+ if (stack.length < 1) {
24201
+ this._failed = true;
24202
+ break;
24203
+ }
24204
+ stack.push(stack.at(-1));
24205
+ if (stack.length > MAX_STACK_SIZE) {
24206
+ this._failed = true;
24207
+ }
24208
+ break;
24209
+ case TOKEN.exch: {
24210
+ if (stack.length < 2) {
24211
+ this._failed = true;
24212
+ break;
24213
+ }
24214
+ const a = stack.pop();
24215
+ const b = stack.pop();
24216
+ stack.push(a, b);
24217
+ break;
24218
+ }
24219
+ case TOKEN.pop:
24220
+ if (stack.length < 1) {
24221
+ this._failed = true;
24222
+ break;
24223
+ }
24224
+ stack.pop();
24225
+ break;
24226
+ case TOKEN.copy: {
24227
+ if (stack.length < 1) {
24228
+ this._failed = true;
24229
+ break;
24230
+ }
24231
+ const nNode = stack.pop();
24232
+ if (nNode.type === PS_NODE.const) {
24233
+ const n = nNode.value | 0;
24234
+ if (n === 0) {
24235
+ } else if (n < 0 || n > stack.length) {
24236
+ this._failed = true;
24237
+ } else {
24238
+ stack.push(...stack.slice(-n));
24239
+ if (stack.length > MAX_STACK_SIZE) {
24240
+ this._failed = true;
24241
+ }
24242
+ }
24243
+ } else {
24244
+ this._failed = true;
24245
+ }
24246
+ break;
24247
+ }
24248
+ case TOKEN.index: {
24249
+ if (stack.length < 1) {
24250
+ this._failed = true;
24251
+ break;
24252
+ }
24253
+ const nNode = stack.pop();
24254
+ if (nNode.type === PS_NODE.const) {
24255
+ const n = nNode.value | 0;
24256
+ if (n < 0 || n >= stack.length) {
24257
+ this._failed = true;
24258
+ } else {
24259
+ stack.push(stack.at(-n - 1));
24260
+ }
24261
+ } else {
24262
+ this._failed = true;
24263
+ }
24264
+ break;
24265
+ }
24266
+ case TOKEN.roll: {
24267
+ if (stack.length < 2) {
24268
+ this._failed = true;
24269
+ break;
24270
+ }
24271
+ const jNode = stack.pop();
24272
+ const nNode = stack.pop();
24273
+ if (nNode.type === PS_NODE.const && jNode.type === PS_NODE.const) {
24274
+ const n = nNode.value | 0;
24275
+ if (n === 0) {
24276
+ } else if (n < 0 || n > stack.length) {
24277
+ this._failed = true;
24278
+ } else {
24279
+ const j = ((jNode.value | 0) % n + n) % n;
24280
+ if (j > 0) {
24281
+ const slice = stack.splice(-n, n);
24282
+ stack.push(...slice.slice(n - j), ...slice.slice(0, n - j));
24283
+ }
24284
+ }
24285
+ } else {
24286
+ this._failed = true;
24287
+ }
24288
+ break;
24289
+ }
24290
+ default:
24291
+ this._failed = true;
24292
+ break;
24293
+ }
24294
+ }
24295
+ /**
24296
+ * Create a binary tree node, applying optimizations eagerly:
24297
+ *
24298
+ * 1. Constant folding — both operands are PsConstNode → fold to PsConstNode.
24299
+ * 2. Reflexive simplifications — x−x→0, x xor x→0, x eq x→true, etc.
24300
+ * 3. Algebraic simplifications with one known operand — identity elements
24301
+ * (x+0→x, x*1→x, …), absorbing elements (x*0→0, x and false→false, …),
24302
+ * and strength reductions (x*-1→neg(x), x^0.5→sqrt(x), x^2→x*x, …).
24303
+ *
24304
+ * Recall: `first` was on top of the stack (right operand for non-commutative
24305
+ * ops), `second` was below (left operand). So `a b sub` → second=a, first=b
24306
+ * → a − b.
24307
+ */
24308
+ _makeBinary(op, first, second) {
24309
+ if (first.type === PS_NODE.const && second.type === PS_NODE.const) {
24310
+ const v = _evalBinaryConst(op, second.value, first.value);
24311
+ if (v !== void 0) {
24312
+ return new PsConstNode(v);
24313
+ }
24314
+ }
24315
+ if (_nodesEqual(first, second)) {
24316
+ switch (op) {
24317
+ case TOKEN.sub:
24318
+ return new PsConstNode(0);
24319
+ // x − x → 0
24320
+ case TOKEN.xor:
24321
+ return new PsConstNode(
24322
+ /* eslint-disable unicorn/prefer-logical-operator-over-ternary */
24323
+ first.valueType === PS_VALUE_TYPE.boolean ? false : 0
24324
+ /* eslint-enable unicorn/prefer-logical-operator-over-ternary */
24325
+ );
24326
+ // TOKEN.mod, TOKEN.div, TOKEN.idiv are NOT simplified here:
24327
+ // x op x is undefined when x = 0, so we cannot fold without knowing
24328
+ // that x is non-zero.
24329
+ case TOKEN.and:
24330
+ case TOKEN.or:
24331
+ return first;
24332
+ // x and x → x; x or x → x
24333
+ case TOKEN.min:
24334
+ case TOKEN.max:
24335
+ return first;
24336
+ // min(x,x) → x; max(x,x) → x
24337
+ case TOKEN.eq:
24338
+ case TOKEN.ge:
24339
+ case TOKEN.le:
24340
+ return new PsConstNode(true);
24341
+ case TOKEN.ne:
24342
+ case TOKEN.gt:
24343
+ case TOKEN.lt:
24344
+ return new PsConstNode(false);
24345
+ }
24346
+ }
24347
+ if (first.type === PS_NODE.const) {
24348
+ const b = first.value;
24349
+ switch (op) {
24350
+ case TOKEN.add:
24351
+ if (b === 0) {
24352
+ return second;
24353
+ }
24354
+ break;
24355
+ case TOKEN.sub:
24356
+ if (b === 0) {
24357
+ return second;
24358
+ }
24359
+ break;
24360
+ case TOKEN.mul:
24361
+ if (b === 1) {
24362
+ return second;
24363
+ }
24364
+ if (b === 0) {
24365
+ return first;
24366
+ }
24367
+ if (b === -1) {
24368
+ return this._makeUnary(TOKEN.neg, second);
24369
+ }
24370
+ break;
24371
+ case TOKEN.div:
24372
+ if (b !== 0) {
24373
+ return this._makeBinary(TOKEN.mul, new PsConstNode(1 / b), second);
24374
+ }
24375
+ break;
24376
+ case TOKEN.idiv:
24377
+ if (b === 1) {
24378
+ return second;
24379
+ }
24380
+ break;
24381
+ case TOKEN.exp:
24382
+ if (b === 1) {
24383
+ return second;
24384
+ }
24385
+ if (b === -1) {
24386
+ return this._makeBinary(TOKEN.div, second, new PsConstNode(1));
24387
+ }
24388
+ if (b === 0.5) {
24389
+ return this._makeUnary(TOKEN.sqrt, second);
24390
+ }
24391
+ if (b === 0.25) {
24392
+ const sqrtOnce = this._makeUnary(TOKEN.sqrt, second);
24393
+ return this._makeUnary(TOKEN.sqrt, sqrtOnce);
24394
+ }
24395
+ if (b === 2) {
24396
+ return this._makeBinary(TOKEN.mul, second, second);
24397
+ }
24398
+ if (b === 3) {
24399
+ return this._makeBinary(
24400
+ TOKEN.mul,
24401
+ this._makeBinary(TOKEN.mul, second, second),
24402
+ second
24403
+ );
24404
+ }
24405
+ if (b === 4) {
24406
+ const square = this._makeBinary(TOKEN.mul, second, second);
24407
+ return this._makeBinary(TOKEN.mul, square, square);
24408
+ }
24409
+ if (b === 0) {
24410
+ return new PsConstNode(1);
24411
+ }
24412
+ break;
24413
+ case TOKEN.and:
24414
+ if (b === true) {
24415
+ return second;
24416
+ }
24417
+ if (b === false) {
24418
+ return first;
24419
+ }
24420
+ break;
24421
+ case TOKEN.or:
24422
+ if (b === false) {
24423
+ return second;
24424
+ }
24425
+ if (b === true) {
24426
+ return first;
24427
+ }
24428
+ break;
24429
+ case TOKEN.min:
24430
+ if (second.type === PS_NODE.binary && second.op === TOKEN.max && second.first.type === PS_NODE.const && second.first.value >= b) {
24431
+ return first;
24432
+ }
24433
+ break;
24434
+ case TOKEN.max:
24435
+ if (second.type === PS_NODE.binary && second.op === TOKEN.min && second.first.type === PS_NODE.const && second.first.value <= b) {
24436
+ return first;
24437
+ }
24438
+ break;
24439
+ }
24440
+ }
24441
+ if (second.type === PS_NODE.const) {
24442
+ const a = second.value;
24443
+ switch (op) {
24444
+ case TOKEN.add:
24445
+ if (a === 0) {
24446
+ return first;
24447
+ }
24448
+ break;
24449
+ case TOKEN.sub:
24450
+ if (a === 0) {
24451
+ return this._makeUnary(TOKEN.neg, first);
24452
+ }
24453
+ break;
24454
+ case TOKEN.mul:
24455
+ if (a === 1) {
24456
+ return first;
24457
+ }
24458
+ if (a === 0) {
24459
+ return second;
24460
+ }
24461
+ if (a === -1) {
24462
+ return this._makeUnary(TOKEN.neg, first);
24463
+ }
24464
+ break;
24465
+ case TOKEN.and:
24466
+ if (a === true) {
24467
+ return first;
24468
+ }
24469
+ if (a === false) {
24470
+ return second;
24471
+ }
24472
+ break;
24473
+ case TOKEN.or:
24474
+ if (a === false) {
24475
+ return first;
24476
+ }
24477
+ if (a === true) {
24478
+ return second;
24479
+ }
24480
+ break;
24481
+ }
24482
+ }
24483
+ return new PsBinaryNode(
24484
+ op,
24485
+ first,
24486
+ second,
24487
+ _binaryValueType(op, first.valueType, second.valueType)
24488
+ );
24489
+ }
24490
+ /**
24491
+ * Create a unary tree node, applying optimizations eagerly:
24492
+ *
24493
+ * 1. Constant folding.
24494
+ * 2. not(comparison) → negated comparison: not(a eq b) → a ne b, etc.
24495
+ * 3. neg(a − b) → b − a.
24496
+ * 4. Double-negation: neg(neg(x)) → x, not(not(x)) → x.
24497
+ * 5. abs(neg(x)) → abs(x).
24498
+ * 6. Idempotent: f(f(x)) → f(x) for abs, ceiling, floor, round, etc.
24499
+ */
24500
+ _makeUnary(op, operand) {
24501
+ if (operand.type === PS_NODE.const) {
24502
+ const v = _evalUnaryConst(op, operand.value);
24503
+ if (v !== void 0) {
24504
+ return new PsConstNode(v);
24505
+ }
24506
+ }
24507
+ if (op === TOKEN.not && operand.type === PS_NODE.binary) {
24508
+ const negated = _PSStackToTree.#negatedComparison.get(operand.op);
24509
+ if (negated !== void 0) {
24510
+ return new PsBinaryNode(
24511
+ negated,
24512
+ operand.first,
24513
+ operand.second,
24514
+ PS_VALUE_TYPE.boolean
24515
+ );
24516
+ }
24517
+ }
24518
+ if (op === TOKEN.neg && operand.type === PS_NODE.binary && operand.op === TOKEN.sub) {
24519
+ return this._makeBinary(TOKEN.sub, operand.second, operand.first);
24520
+ }
24521
+ if (operand.type === PS_NODE.unary) {
24522
+ if (op === TOKEN.neg && operand.op === TOKEN.neg || op === TOKEN.not && operand.op === TOKEN.not) {
24523
+ return operand.operand;
24524
+ }
24525
+ if (op === TOKEN.abs && operand.op === TOKEN.neg) {
24526
+ return this._makeUnary(TOKEN.abs, operand.operand);
24527
+ }
24528
+ if (_PSStackToTree.#idempotentUnary.has(op) && op === operand.op) {
24529
+ return operand;
24530
+ }
24531
+ }
24532
+ return new PsUnaryNode(op, operand, _unaryValueType(op, operand.valueType));
24533
+ }
24534
+ /**
24535
+ * Create a ternary node, applying optimizations eagerly:
24536
+ *
24537
+ * 1. Constant condition — fold to the live branch.
24538
+ * 2. Identical branches — the condition is irrelevant, return either branch.
24539
+ * 3. Boolean branch constants — `cond ? true : false` → cond,
24540
+ * `cond ? false : true` → not(cond).
24541
+ * 4. Ternary → branchless min/max when the condition compares two numeric
24542
+ * expressions that are also the two branches.
24543
+ */
24544
+ _makeTernary(cond, then, otherwise) {
24545
+ if (cond.type === PS_NODE.const) {
24546
+ return cond.value ? then : otherwise;
24547
+ }
24548
+ if (_nodesEqual(then, otherwise)) {
24549
+ return then;
24550
+ }
24551
+ if (then.type === PS_NODE.const && otherwise.type === PS_NODE.const) {
24552
+ if (then.value === true && otherwise.value === false) {
24553
+ return cond;
24554
+ }
24555
+ if (then.value === false && otherwise.value === true) {
24556
+ return this._makeUnary(TOKEN.not, cond);
24557
+ }
24558
+ }
24559
+ if (cond.type === PS_NODE.binary) {
24560
+ const { op: cop, first: cf, second: cs } = cond;
24561
+ if (cop === TOKEN.gt || cop === TOKEN.ge) {
24562
+ if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
24563
+ return this._makeBinary(TOKEN.min, cf, cs);
24564
+ }
24565
+ if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
24566
+ return this._makeBinary(TOKEN.max, cf, cs);
24567
+ }
24568
+ } else if (cop === TOKEN.lt || cop === TOKEN.le) {
24569
+ if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
24570
+ return this._makeBinary(TOKEN.max, cf, cs);
24571
+ }
24572
+ if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
24573
+ return this._makeBinary(TOKEN.min, cf, cs);
24574
+ }
24575
+ }
24576
+ }
24577
+ return new PsTernaryNode(
24578
+ cond,
24579
+ then,
24580
+ otherwise,
24581
+ then.valueType === otherwise.valueType ? then.valueType : PS_VALUE_TYPE.unknown
24582
+ );
24583
+ }
24584
+ };
24585
+ var OP = {
24586
+ ARG: 0,
24587
+ // [ARG, idx]
24588
+ CONST: 1,
24589
+ // [CONST, val]
24590
+ STORE: 2,
24591
+ // [STORE, slot, min, max] clamp(pop()) → mem[slot]
24592
+ IF: 3,
24593
+ // [IF, target] jump when top-of-stack === 0
24594
+ JUMP: 4,
24595
+ // [JUMP, target] unconditional
24596
+ ABS: 5,
24597
+ NEG: 6,
24598
+ CEIL: 7,
24599
+ FLOOR: 8,
24600
+ ROUND: 9,
24601
+ // floor(x + 0.5)
24602
+ TRUNC: 10,
24603
+ NOT_B: 11,
24604
+ // boolean NOT
24605
+ NOT_N: 12,
24606
+ // bitwise NOT
24607
+ SQRT: 13,
24608
+ SIN: 14,
24609
+ // degrees in/out
24610
+ COS: 15,
24611
+ LN: 16,
24612
+ LOG10: 17,
24613
+ CVI: 18,
24614
+ SHIFT: 19,
24615
+ // [SHIFT, amount] +ve = left, −ve = right
24616
+ // Binary ops: second below, first on top; result = second OP first.
24617
+ ADD: 20,
24618
+ SUB: 21,
24619
+ MUL: 22,
24620
+ DIV: 23,
24621
+ // 0 when divisor is 0
24622
+ IDIV: 24,
24623
+ // 0 when divisor is 0
24624
+ MOD: 25,
24625
+ // 0 when divisor is 0
24626
+ POW: 26,
24627
+ EQ: 27,
24628
+ NE: 28,
24629
+ GT: 29,
24630
+ GE: 30,
24631
+ LT: 31,
24632
+ LE: 32,
24633
+ AND: 33,
24634
+ OR: 34,
24635
+ XOR: 35,
24636
+ ATAN: 36,
24637
+ // atan2(second, first) → degrees [0, 360)
24638
+ MIN: 37,
24639
+ MAX: 38,
24640
+ TEE_TMP: 39,
24641
+ // [TEE_TMP, slot] peek top of stack → tmp[slot], leave on stack
24642
+ LOAD_TMP: 40
24643
+ // [LOAD_TMP, slot] push tmp[slot]
24644
+ };
24645
+ var _DEG_TO_RAD = Math.PI / 180;
24646
+ var _RAD_TO_DEG = 180 / Math.PI;
24647
+ var PsJsCompiler = class {
24648
+ // Safe because JS is single-threaded.
24649
+ static #stack = new Float64Array(64);
24650
+ static #tmp = new Float64Array(64);
24651
+ constructor(domain, range) {
24652
+ this.nIn = domain.length >> 1;
24653
+ this.nOut = range.length >> 1;
24654
+ this.range = range;
24655
+ this.ir = [];
24656
+ this._tmpMap = /* @__PURE__ */ new Map();
24657
+ this._nextTmp = 0;
24658
+ }
24659
+ _compileNode(node) {
24660
+ if (node.shared) {
24661
+ const cached = this._tmpMap.get(node);
24662
+ if (cached !== void 0) {
24663
+ this.ir.push(OP.LOAD_TMP, cached);
24664
+ return true;
24665
+ }
24666
+ if (!this._compileNodeImpl(node)) {
24667
+ return false;
24668
+ }
24669
+ const slot = this._nextTmp++;
24670
+ this._tmpMap.set(node, slot);
24671
+ this.ir.push(OP.TEE_TMP, slot);
24672
+ return true;
24673
+ }
24674
+ return this._compileNodeImpl(node);
24675
+ }
24676
+ _compileNodeImpl(node) {
24677
+ switch (node.type) {
24678
+ case PS_NODE.arg:
24679
+ this.ir.push(OP.ARG, node.index);
24680
+ return true;
24681
+ case PS_NODE.const: {
24682
+ const v = node.value;
24683
+ this.ir.push(OP.CONST, typeof v === "boolean" ? Number(v) : v);
24684
+ return true;
24685
+ }
24686
+ case PS_NODE.unary:
24687
+ return this._compileUnary(node);
24688
+ case PS_NODE.binary:
24689
+ return this._compileBinary(node);
24690
+ case PS_NODE.ternary:
24691
+ return this._compileTernary(node);
24692
+ default:
24693
+ return false;
24694
+ }
24695
+ }
24696
+ _compileUnary(node) {
24697
+ const { op, operand, valueType } = node;
24698
+ if (op === TOKEN.cvr) {
24699
+ return this._compileNode(operand);
24700
+ }
24701
+ if (!this._compileNode(operand)) {
24702
+ return false;
24703
+ }
24704
+ switch (op) {
24705
+ case TOKEN.abs:
24706
+ this.ir.push(OP.ABS);
24707
+ break;
24708
+ case TOKEN.neg:
24709
+ this.ir.push(OP.NEG);
24710
+ break;
24711
+ case TOKEN.ceiling:
24712
+ this.ir.push(OP.CEIL);
24713
+ break;
24714
+ case TOKEN.floor:
24715
+ this.ir.push(OP.FLOOR);
24716
+ break;
24717
+ case TOKEN.round:
24718
+ this.ir.push(OP.ROUND);
24719
+ break;
24720
+ case TOKEN.truncate:
24721
+ this.ir.push(OP.TRUNC);
24722
+ break;
24723
+ case TOKEN.sqrt:
24724
+ this.ir.push(OP.SQRT);
24725
+ break;
24726
+ case TOKEN.sin:
24727
+ this.ir.push(OP.SIN);
24728
+ break;
24729
+ case TOKEN.cos:
24730
+ this.ir.push(OP.COS);
24731
+ break;
24732
+ case TOKEN.ln:
24733
+ this.ir.push(OP.LN);
24734
+ break;
24735
+ case TOKEN.log:
24736
+ this.ir.push(OP.LOG10);
24737
+ break;
24738
+ case TOKEN.cvi:
24739
+ this.ir.push(OP.CVI);
24740
+ break;
24741
+ case TOKEN.not:
24742
+ if (valueType === PS_VALUE_TYPE.boolean) {
24743
+ this.ir.push(OP.NOT_B);
24744
+ } else if (valueType === PS_VALUE_TYPE.numeric) {
24745
+ this.ir.push(OP.NOT_N);
24746
+ } else {
24747
+ return false;
24748
+ }
24749
+ break;
24750
+ default:
24751
+ return false;
24752
+ }
24753
+ return true;
24754
+ }
24755
+ _compileBinary(node) {
24756
+ const { op, first, second } = node;
24757
+ if (op === TOKEN.bitshift) {
24758
+ if (first.type !== PS_NODE.const || !Number.isInteger(first.value) || !this._compileNode(second)) {
24759
+ return false;
24760
+ }
24761
+ this.ir.push(OP.SHIFT, first.value);
24762
+ return true;
24763
+ }
24764
+ if (!this._compileNode(second) || !this._compileNode(first)) {
24765
+ return false;
24766
+ }
24767
+ switch (op) {
24768
+ case TOKEN.add:
24769
+ this.ir.push(OP.ADD);
24770
+ break;
24771
+ case TOKEN.sub:
24772
+ this.ir.push(OP.SUB);
24773
+ break;
24774
+ case TOKEN.mul:
24775
+ this.ir.push(OP.MUL);
24776
+ break;
24777
+ case TOKEN.div:
24778
+ this.ir.push(OP.DIV);
24779
+ break;
24780
+ case TOKEN.idiv:
24781
+ this.ir.push(OP.IDIV);
24782
+ break;
24783
+ case TOKEN.mod:
24784
+ this.ir.push(OP.MOD);
24785
+ break;
24786
+ case TOKEN.exp:
24787
+ this.ir.push(OP.POW);
24788
+ break;
24789
+ case TOKEN.eq:
24790
+ this.ir.push(OP.EQ);
24791
+ break;
24792
+ case TOKEN.ne:
24793
+ this.ir.push(OP.NE);
24794
+ break;
24795
+ case TOKEN.gt:
24796
+ this.ir.push(OP.GT);
24797
+ break;
24798
+ case TOKEN.ge:
24799
+ this.ir.push(OP.GE);
24800
+ break;
24801
+ case TOKEN.lt:
24802
+ this.ir.push(OP.LT);
24803
+ break;
24804
+ case TOKEN.le:
24805
+ this.ir.push(OP.LE);
24806
+ break;
24807
+ case TOKEN.and:
24808
+ this.ir.push(OP.AND);
24809
+ break;
24810
+ case TOKEN.or:
24811
+ this.ir.push(OP.OR);
24812
+ break;
24813
+ case TOKEN.xor:
24814
+ this.ir.push(OP.XOR);
24815
+ break;
24816
+ case TOKEN.atan:
24817
+ this.ir.push(OP.ATAN);
24818
+ break;
24819
+ case TOKEN.min:
24820
+ this.ir.push(OP.MIN);
24821
+ break;
24822
+ case TOKEN.max:
24823
+ this.ir.push(OP.MAX);
24824
+ break;
24825
+ default:
24826
+ return false;
24827
+ }
24828
+ return true;
24829
+ }
24830
+ _compileTernary(node) {
24831
+ if (!this._compileNode(node.cond)) {
24832
+ return false;
24833
+ }
24834
+ this.ir.push(OP.IF, 0);
24835
+ const ifPatch = this.ir.length - 1;
24836
+ if (!this._compileNode(node.then)) {
24837
+ return false;
24838
+ }
24839
+ this.ir.push(OP.JUMP, 0);
24840
+ const jumpPatch = this.ir.length - 1;
24841
+ this.ir[ifPatch] = this.ir.length;
24842
+ if (!this._compileNode(node.otherwise)) {
24843
+ return false;
24844
+ }
24845
+ this.ir[jumpPatch] = this.ir.length;
24846
+ return true;
24847
+ }
24848
+ compile(program) {
24849
+ const outputs = new PSStackToTree().evaluate(program, this.nIn);
24850
+ if (!outputs || outputs.length < this.nOut) {
24851
+ return null;
24852
+ }
24853
+ for (let i = 0; i < this.nOut; i++) {
24854
+ if (!this._compileNode(outputs[i])) {
24855
+ return null;
24856
+ }
24857
+ const min = this.range[i * 2];
24858
+ const max = this.range[i * 2 + 1];
24859
+ this.ir.push(OP.STORE, i, min, max);
24860
+ }
24861
+ return new Float64Array(this.ir);
24862
+ }
24863
+ static execute(ir, src, srcOffset, dest, destOffset) {
24864
+ let ip = 0, sp = 0;
24865
+ const n = ir.length;
24866
+ const stack = this.#stack;
24867
+ const tmp = this.#tmp;
24868
+ while (ip < n) {
24869
+ switch (ir[ip++] | 0) {
24870
+ case OP.ARG:
24871
+ stack[sp++] = src[srcOffset + (ir[ip++] | 0)];
24872
+ break;
24873
+ case OP.CONST:
24874
+ stack[sp++] = ir[ip++];
24875
+ break;
24876
+ case OP.STORE: {
24877
+ const slot = ir[ip++] | 0;
24878
+ const min = ir[ip++];
24879
+ const max = ir[ip++];
24880
+ dest[destOffset + slot] = MathClamp(stack[--sp], min, max);
24881
+ break;
24882
+ }
24883
+ case OP.IF: {
24884
+ const tgt = ir[ip++];
24885
+ if (stack[--sp] === 0) {
24886
+ ip = tgt;
24887
+ }
24888
+ break;
24889
+ }
24890
+ case OP.JUMP:
24891
+ ip = ir[ip];
24892
+ break;
24893
+ case OP.ABS:
24894
+ stack[sp - 1] = Math.abs(stack[sp - 1]);
24895
+ break;
24896
+ case OP.NEG:
24897
+ stack[sp - 1] = -stack[sp - 1];
24898
+ break;
24899
+ case OP.CEIL:
24900
+ stack[sp - 1] = Math.ceil(stack[sp - 1]);
24901
+ break;
24902
+ case OP.FLOOR:
24903
+ stack[sp - 1] = Math.floor(stack[sp - 1]);
24904
+ break;
24905
+ case OP.ROUND:
24906
+ stack[sp - 1] = Math.floor(stack[sp - 1] + 0.5);
24907
+ break;
24908
+ case OP.TRUNC:
24909
+ stack[sp - 1] = Math.trunc(stack[sp - 1]);
24910
+ break;
24911
+ case OP.NOT_B:
24912
+ stack[sp - 1] = stack[sp - 1] !== 0 ? 0 : 1;
24913
+ break;
24914
+ case OP.NOT_N:
24915
+ stack[sp - 1] = ~(stack[sp - 1] | 0);
24916
+ break;
24917
+ case OP.SQRT:
24918
+ stack[sp - 1] = Math.sqrt(stack[sp - 1]);
24919
+ break;
24920
+ case OP.SIN:
24921
+ stack[sp - 1] = Math.sin(stack[sp - 1] % 360 * _DEG_TO_RAD);
24922
+ break;
24923
+ case OP.COS:
24924
+ stack[sp - 1] = Math.cos(stack[sp - 1] % 360 * _DEG_TO_RAD);
24925
+ break;
24926
+ case OP.LN:
24927
+ stack[sp - 1] = Math.log(stack[sp - 1]);
24928
+ break;
24929
+ case OP.LOG10:
24930
+ stack[sp - 1] = Math.log10(stack[sp - 1]);
24931
+ break;
24932
+ case OP.CVI:
24933
+ stack[sp - 1] = Math.trunc(stack[sp - 1]) | 0;
24934
+ break;
24935
+ case OP.SHIFT: {
24936
+ const amt = ir[ip++];
24937
+ const v = stack[sp - 1] | 0;
24938
+ if (amt > 0) {
24939
+ stack[sp - 1] = v << amt;
24940
+ } else if (amt < 0) {
24941
+ stack[sp - 1] = v >> -amt;
24942
+ } else {
24943
+ stack[sp - 1] = v;
24944
+ }
24945
+ break;
24946
+ }
24947
+ case OP.ADD: {
24948
+ const b = stack[--sp];
24949
+ stack[sp - 1] += b;
24950
+ break;
24951
+ }
24952
+ case OP.SUB: {
24953
+ const b = stack[--sp];
24954
+ stack[sp - 1] -= b;
24955
+ break;
24956
+ }
24957
+ case OP.MUL: {
24958
+ const b = stack[--sp];
24959
+ stack[sp - 1] *= b;
24960
+ break;
24961
+ }
24962
+ case OP.DIV: {
24963
+ const b = stack[--sp];
24964
+ stack[sp - 1] = b !== 0 ? stack[sp - 1] / b : 0;
24965
+ break;
24966
+ }
24967
+ case OP.IDIV: {
24968
+ const b = stack[--sp];
24969
+ stack[sp - 1] = b !== 0 ? Math.trunc(stack[sp - 1] / b) : 0;
24970
+ break;
24971
+ }
24972
+ case OP.MOD: {
24973
+ const b = stack[--sp];
24974
+ stack[sp - 1] = b !== 0 ? stack[sp - 1] % b : 0;
24975
+ break;
24976
+ }
24977
+ case OP.POW: {
24978
+ const b = stack[--sp];
24979
+ stack[sp - 1] **= b;
24980
+ break;
24981
+ }
24982
+ case OP.EQ: {
24983
+ const b = stack[--sp];
24984
+ stack[sp - 1] = stack[sp - 1] === b ? 1 : 0;
24985
+ break;
24986
+ }
24987
+ case OP.NE: {
24988
+ const b = stack[--sp];
24989
+ stack[sp - 1] = stack[sp - 1] !== b ? 1 : 0;
24990
+ break;
24991
+ }
24992
+ case OP.GT: {
24993
+ const b = stack[--sp];
24994
+ stack[sp - 1] = stack[sp - 1] > b ? 1 : 0;
24995
+ break;
24996
+ }
24997
+ case OP.GE: {
24998
+ const b = stack[--sp];
24999
+ stack[sp - 1] = stack[sp - 1] >= b ? 1 : 0;
25000
+ break;
25001
+ }
25002
+ case OP.LT: {
25003
+ const b = stack[--sp];
25004
+ stack[sp - 1] = stack[sp - 1] < b ? 1 : 0;
25005
+ break;
25006
+ }
25007
+ case OP.LE: {
25008
+ const b = stack[--sp];
25009
+ stack[sp - 1] = stack[sp - 1] <= b ? 1 : 0;
25010
+ break;
25011
+ }
25012
+ case OP.AND: {
25013
+ const b = stack[--sp] | 0;
25014
+ stack[sp - 1] = (stack[sp - 1] | 0) & b;
25015
+ break;
25016
+ }
25017
+ case OP.OR: {
25018
+ const b = stack[--sp] | 0;
25019
+ stack[sp - 1] = stack[sp - 1] | 0 | b;
25020
+ break;
25021
+ }
25022
+ case OP.XOR: {
25023
+ const b = stack[--sp] | 0;
25024
+ stack[sp - 1] = (stack[sp - 1] | 0) ^ b;
25025
+ break;
25026
+ }
25027
+ case OP.ATAN: {
25028
+ const b = stack[--sp];
25029
+ const deg = Math.atan2(stack[sp - 1], b) * _RAD_TO_DEG;
25030
+ stack[sp - 1] = deg < 0 ? deg + 360 : deg;
25031
+ break;
25032
+ }
25033
+ case OP.MIN: {
25034
+ const b = stack[--sp];
25035
+ stack[sp - 1] = Math.min(stack[sp - 1], b);
25036
+ break;
25037
+ }
25038
+ case OP.MAX: {
25039
+ const b = stack[--sp];
25040
+ stack[sp - 1] = Math.max(stack[sp - 1], b);
25041
+ break;
25042
+ }
25043
+ case OP.TEE_TMP:
25044
+ tmp[ir[ip++] | 0] = stack[sp - 1];
25045
+ break;
25046
+ case OP.LOAD_TMP:
25047
+ stack[sp++] = tmp[ir[ip++] | 0];
25048
+ break;
25049
+ }
25050
+ }
25051
+ }
25052
+ };
25053
+ var PSStackBasedInterpreter = class {
25054
+ // Safe: JS is single-threaded.
25055
+ static #stack = new Float64Array(100);
25056
+ static #sp = 0;
25057
+ static #push(v) {
25058
+ if (this.#sp < this.#stack.length) {
25059
+ this.#stack[this.#sp++] = v;
25060
+ }
25061
+ }
25062
+ static #execOp(op) {
25063
+ const stack = this.#stack;
25064
+ switch (op) {
25065
+ case TOKEN.true:
25066
+ this.#push(1);
25067
+ break;
25068
+ case TOKEN.false:
25069
+ this.#push(0);
25070
+ break;
25071
+ case TOKEN.abs:
25072
+ stack[this.#sp - 1] = Math.abs(stack[this.#sp - 1]);
25073
+ break;
25074
+ case TOKEN.neg:
25075
+ stack[this.#sp - 1] = -stack[this.#sp - 1];
25076
+ break;
25077
+ case TOKEN.ceiling:
25078
+ stack[this.#sp - 1] = Math.ceil(stack[this.#sp - 1]);
25079
+ break;
25080
+ case TOKEN.floor:
25081
+ stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1]);
25082
+ break;
25083
+ case TOKEN.round:
25084
+ stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1] + 0.5);
25085
+ break;
25086
+ case TOKEN.truncate:
25087
+ stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]);
25088
+ break;
25089
+ case TOKEN.sqrt:
25090
+ stack[this.#sp - 1] = Math.sqrt(stack[this.#sp - 1]);
25091
+ break;
25092
+ case TOKEN.sin:
25093
+ stack[this.#sp - 1] = Math.sin(
25094
+ stack[this.#sp - 1] % 360 * _DEG_TO_RAD
25095
+ );
25096
+ break;
25097
+ case TOKEN.cos:
25098
+ stack[this.#sp - 1] = Math.cos(
25099
+ stack[this.#sp - 1] % 360 * _DEG_TO_RAD
25100
+ );
25101
+ break;
25102
+ case TOKEN.ln:
25103
+ stack[this.#sp - 1] = Math.log(stack[this.#sp - 1]);
25104
+ break;
25105
+ case TOKEN.log:
25106
+ stack[this.#sp - 1] = Math.log10(stack[this.#sp - 1]);
25107
+ break;
25108
+ case TOKEN.cvi:
25109
+ stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]) | 0;
25110
+ break;
25111
+ case TOKEN.cvr:
25112
+ break;
25113
+ // values are already f64
25114
+ case TOKEN.not: {
25115
+ const v = stack[this.#sp - 1];
25116
+ stack[this.#sp - 1] = v === 0 || v === 1 ? 1 - v : ~(v | 0);
25117
+ break;
25118
+ }
25119
+ case TOKEN.add: {
25120
+ const b = stack[--this.#sp];
25121
+ stack[this.#sp - 1] += b;
25122
+ break;
25123
+ }
25124
+ case TOKEN.sub: {
25125
+ const b = stack[--this.#sp];
25126
+ stack[this.#sp - 1] -= b;
25127
+ break;
25128
+ }
25129
+ case TOKEN.mul: {
25130
+ const b = stack[--this.#sp];
25131
+ stack[this.#sp - 1] *= b;
25132
+ break;
25133
+ }
25134
+ case TOKEN.div: {
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.idiv: {
25140
+ const b = stack[--this.#sp];
25141
+ stack[this.#sp - 1] = b !== 0 ? Math.trunc(stack[this.#sp - 1] / b) : 0;
25142
+ break;
25143
+ }
25144
+ case TOKEN.mod: {
25145
+ const b = stack[--this.#sp];
25146
+ stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] % b : 0;
25147
+ break;
25148
+ }
25149
+ case TOKEN.exp: {
25150
+ const b = stack[--this.#sp];
25151
+ stack[this.#sp - 1] **= b;
25152
+ break;
25153
+ }
25154
+ case TOKEN.atan: {
25155
+ const dx = stack[--this.#sp];
25156
+ const deg = Math.atan2(stack[this.#sp - 1], dx) * _RAD_TO_DEG;
25157
+ stack[this.#sp - 1] = deg < 0 ? deg + 360 : deg;
25158
+ break;
25159
+ }
25160
+ case TOKEN.eq: {
25161
+ const b = stack[--this.#sp];
25162
+ stack[this.#sp - 1] = stack[this.#sp - 1] === b ? 1 : 0;
25163
+ break;
25164
+ }
25165
+ case TOKEN.ne: {
25166
+ const b = stack[--this.#sp];
25167
+ stack[this.#sp - 1] = stack[this.#sp - 1] !== b ? 1 : 0;
25168
+ break;
25169
+ }
25170
+ case TOKEN.gt: {
25171
+ const b = stack[--this.#sp];
25172
+ stack[this.#sp - 1] = stack[this.#sp - 1] > b ? 1 : 0;
25173
+ break;
25174
+ }
25175
+ case TOKEN.ge: {
25176
+ const b = stack[--this.#sp];
25177
+ stack[this.#sp - 1] = stack[this.#sp - 1] >= b ? 1 : 0;
25178
+ break;
25179
+ }
25180
+ case TOKEN.lt: {
25181
+ const b = stack[--this.#sp];
25182
+ stack[this.#sp - 1] = stack[this.#sp - 1] < b ? 1 : 0;
25183
+ break;
25184
+ }
25185
+ case TOKEN.le: {
25186
+ const b = stack[--this.#sp];
25187
+ stack[this.#sp - 1] = stack[this.#sp - 1] <= b ? 1 : 0;
25188
+ break;
25189
+ }
25190
+ case TOKEN.and: {
25191
+ const b = stack[--this.#sp] | 0;
25192
+ stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) & b;
25193
+ break;
25194
+ }
25195
+ case TOKEN.or: {
25196
+ const b = stack[--this.#sp] | 0;
25197
+ stack[this.#sp - 1] = stack[this.#sp - 1] | 0 | b;
25198
+ break;
25199
+ }
25200
+ case TOKEN.xor: {
25201
+ const b = stack[--this.#sp] | 0;
25202
+ stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) ^ b;
25203
+ break;
25204
+ }
25205
+ case TOKEN.bitshift: {
25206
+ const amt = stack[--this.#sp] | 0;
25207
+ const v = stack[this.#sp - 1] | 0;
25208
+ stack[this.#sp - 1] = amt > 0 ? v << amt : v >> -amt;
25209
+ break;
25210
+ }
25211
+ case TOKEN.min: {
25212
+ const b = stack[--this.#sp];
25213
+ stack[this.#sp - 1] = Math.min(stack[this.#sp - 1], b);
25214
+ break;
25215
+ }
25216
+ case TOKEN.max: {
25217
+ const b = stack[--this.#sp];
25218
+ stack[this.#sp - 1] = Math.max(stack[this.#sp - 1], b);
25219
+ break;
25220
+ }
25221
+ case TOKEN.dup:
25222
+ this.#push(stack[this.#sp - 1]);
25223
+ break;
25224
+ case TOKEN.exch: {
25225
+ const a = stack[--this.#sp];
25226
+ const b = stack[--this.#sp];
25227
+ this.#push(a);
25228
+ this.#push(b);
25229
+ break;
25230
+ }
25231
+ case TOKEN.pop:
25232
+ this.#sp--;
25233
+ break;
25234
+ case TOKEN.copy: {
25235
+ const n = Math.trunc(stack[--this.#sp]);
25236
+ const base = this.#sp - n;
25237
+ for (let k = 0; k < n; k++) {
25238
+ this.#push(stack[base + k]);
25239
+ }
25240
+ break;
25241
+ }
25242
+ case TOKEN.index: {
25243
+ const i = Math.trunc(stack[--this.#sp]);
25244
+ this.#push(stack[this.#sp - 1 - i]);
25245
+ break;
25246
+ }
25247
+ case TOKEN.roll: {
25248
+ const j = Math.trunc(stack[--this.#sp]);
25249
+ const n = Math.trunc(stack[--this.#sp]);
25250
+ if (n > 1 && j !== 0) {
25251
+ const mod = (j % n + n) % n;
25252
+ if (mod !== 0) {
25253
+ const base = this.#sp - n;
25254
+ const sub = stack.slice(base, this.#sp);
25255
+ for (let k = 0; k < n; k++) {
25256
+ stack[base + k] = sub[(k - mod + n) % n];
25257
+ }
25258
+ }
25259
+ }
25260
+ break;
25261
+ }
25262
+ }
25263
+ }
25264
+ static #execBlock(instructions) {
25265
+ for (const instr of instructions) {
25266
+ switch (instr.type) {
25267
+ case PS_NODE.number:
25268
+ this.#push(instr.value);
25269
+ break;
25270
+ case PS_NODE.operator:
25271
+ this.#execOp(instr.op);
25272
+ break;
25273
+ case PS_NODE.if:
25274
+ if (this.#stack[--this.#sp] !== 0) {
25275
+ this.#execBlock(instr.then.instructions);
25276
+ }
25277
+ break;
25278
+ case PS_NODE.ifelse:
25279
+ if (this.#stack[--this.#sp] !== 0) {
25280
+ this.#execBlock(instr.then.instructions);
25281
+ } else {
25282
+ this.#execBlock(instr.otherwise.instructions);
25283
+ }
25284
+ break;
25285
+ }
25286
+ }
25287
+ }
25288
+ /**
25289
+ * @param {import("./ast.js").PsProgram} program
25290
+ * @param {number[]} domain – flat [min0,max0, …]
25291
+ * @param {number[]} range – flat [min0,max0, …]
25292
+ * @returns {Function} – `(src, srcOffset, dest, destOffset) => void`
25293
+ */
25294
+ static build(program, domain, range) {
25295
+ const nIn = domain.length >> 1;
25296
+ const nOut = range.length >> 1;
25297
+ const { instructions } = program.body;
25298
+ return (src, srcOffset, dest, destOffset) => {
25299
+ this.#sp = 0;
25300
+ for (let i = 0; i < nIn; i++) {
25301
+ this.#push(src[srcOffset + i]);
25302
+ }
25303
+ this.#execBlock(instructions);
25304
+ const base = this.#sp - nOut;
25305
+ for (let i = 0; i < nOut; i++) {
25306
+ const v = base + i >= 0 ? this.#stack[base + i] : 0;
25307
+ dest[destOffset + i] = MathClamp(v, range[i * 2], range[i * 2 + 1]);
25308
+ }
25309
+ };
25310
+ }
25311
+ };
25312
+ function buildPostScriptJsFunction(source, domain, range, forceInterpreter = false) {
25313
+ const program = parsePostScriptFunction(source);
25314
+ const ir = !forceInterpreter && new PsJsCompiler(domain, range).compile(program);
25315
+ if (ir) {
25316
+ return (src, srcOffset, dest, destOffset) => {
25317
+ PsJsCompiler.execute(ir, src, srcOffset, dest, destOffset);
25318
+ };
25319
+ }
25320
+ return PSStackBasedInterpreter.build(program, domain, range);
25321
+ }
25322
+ var ShadingType = {
25323
+ FUNCTION_BASED: 1,
25324
+ AXIAL: 2,
25325
+ RADIAL: 3,
25326
+ FREE_FORM_MESH: 4,
25327
+ LATTICE_FORM_MESH: 5,
25328
+ COONS_PATCH_MESH: 6,
25329
+ TENSOR_PATCH_MESH: 7
25330
+ };
25331
+ var BaseShading = class _BaseShading {
25332
+ // A small number to offset the first/last color stops so we can insert ones
25333
+ // to support extend. Number.MIN_VALUE is too small and breaks the extend.
25334
+ static SMALL_NUMBER = 1e-6;
25335
+ constructor() {
25336
+ if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _BaseShading) {
25337
+ unreachable2("Cannot initialize BaseShading.");
25338
+ }
25339
+ }
25340
+ getIR() {
25341
+ unreachable2("Abstract method `getIR` called.");
25342
+ }
25343
+ };
25344
+ function meshUpdateBounds(self) {
25345
+ let minX = self.coords[0][0], minY = self.coords[0][1], maxX = minX, maxY = minY;
25346
+ for (let i = 1, ii = self.coords.length; i < ii; i++) {
25347
+ const x = self.coords[i][0], y = self.coords[i][1];
25348
+ minX = minX > x ? x : minX;
25349
+ minY = minY > y ? y : minY;
25350
+ maxX = maxX < x ? x : maxX;
25351
+ maxY = maxY < y ? y : maxY;
25352
+ }
25353
+ self.bounds = [minX, minY, maxX, maxY];
25354
+ }
25355
+ function meshPackData(self) {
25356
+ let i, j, ii;
25357
+ const coords = self.coords;
25358
+ const coordsPacked = new Float32Array(coords.length * 2);
25359
+ for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
25360
+ const xy = coords[i];
25361
+ coordsPacked[j++] = xy[0];
25362
+ coordsPacked[j++] = xy[1];
25363
+ }
25364
+ self.coords = coordsPacked;
25365
+ const colors = self.colors;
25366
+ const colorsPacked = new Uint8Array(colors.length * 4);
25367
+ for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
25368
+ const c = colors[i];
25369
+ colorsPacked[j++] = c[0];
25370
+ colorsPacked[j++] = c[1];
25371
+ colorsPacked[j++] = c[2];
25372
+ j++;
25373
+ }
25374
+ self.colors = colorsPacked;
25375
+ for (const figure of self.figures) {
25376
+ figure.coords = new Uint32Array(figure.coords);
25377
+ figure.colors = new Uint32Array(figure.colors);
25378
+ }
25379
+ }
25380
+ function buildMeshVertexData(coords, colors, figures) {
25381
+ let vertexCount = 0;
25382
+ for (const figure of figures) {
25383
+ if (figure.type === MeshFigureType.TRIANGLES) {
25384
+ vertexCount += figure.coords.length;
25385
+ } else if (figure.type === MeshFigureType.LATTICE) {
25386
+ const vpr = figure.verticesPerRow;
25387
+ vertexCount += (Math.floor(figure.coords.length / vpr) - 1) * (vpr - 1) * 6;
25388
+ }
25389
+ }
25390
+ const posData = new Float32Array(vertexCount * 2);
25391
+ const colData = new Uint8Array(vertexCount * 4);
25392
+ let pOff = 0, cOff = 0;
25393
+ const addVertex = (pi, ci) => {
25394
+ posData[pOff++] = coords[pi * 2];
25395
+ posData[pOff++] = coords[pi * 2 + 1];
25396
+ colData[cOff++] = colors[ci * 4];
25397
+ colData[cOff++] = colors[ci * 4 + 1];
25398
+ colData[cOff++] = colors[ci * 4 + 2];
25399
+ cOff++;
25400
+ };
25401
+ for (const figure of figures) {
25402
+ const ps = figure.coords;
25403
+ const cs = figure.colors;
25404
+ if (figure.type === MeshFigureType.TRIANGLES) {
25405
+ for (let i = 0, ii = ps.length; i < ii; i++) {
25406
+ addVertex(ps[i], cs[i]);
25407
+ }
25408
+ } else if (figure.type === MeshFigureType.LATTICE) {
25409
+ const vpr = figure.verticesPerRow;
25410
+ const rows = Math.floor(ps.length / vpr) - 1;
25411
+ const cols = vpr - 1;
25412
+ for (let i = 0; i < rows; i++) {
25413
+ let q = i * vpr;
25414
+ for (let j = 0; j < cols; j++, q++) {
25415
+ addVertex(ps[q], cs[q]);
25416
+ addVertex(ps[q + 1], cs[q + 1]);
25417
+ addVertex(ps[q + vpr], cs[q + vpr]);
25418
+ addVertex(ps[q + vpr + 1], cs[q + vpr + 1]);
25419
+ addVertex(ps[q + 1], cs[q + 1]);
25420
+ addVertex(ps[q + vpr], cs[q + vpr]);
25421
+ }
25422
+ }
25423
+ }
25424
+ }
25425
+ return { posData, colData, vertexCount };
25426
+ }
25427
+ var MeshStreamReader = class {
25428
+ constructor(stream, context) {
25429
+ this.stream = stream;
25430
+ this.context = context;
25431
+ this.buffer = 0;
25432
+ this.bufferLength = 0;
25433
+ const numComps = context.numComps;
25434
+ this.tmpCompsBuf = new Float32Array(numComps);
25435
+ const csNumComps = context.colorSpace.numComps;
25436
+ this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf;
25437
+ }
25438
+ get hasData() {
25439
+ if (this.stream.end) {
25440
+ return this.stream.pos < this.stream.end;
25441
+ }
25442
+ if (this.bufferLength > 0) {
25443
+ return true;
25444
+ }
25445
+ const nextByte = this.stream.getByte();
25446
+ if (nextByte < 0) {
25447
+ return false;
25448
+ }
25449
+ this.buffer = nextByte;
25450
+ this.bufferLength = 8;
25451
+ return true;
25452
+ }
25453
+ readBits(n) {
25454
+ const { stream } = this;
25455
+ let { buffer, bufferLength } = this;
25456
+ if (n === 32) {
25457
+ if (bufferLength === 0) {
25458
+ return stream.getInt32() >>> 0;
25459
+ }
25460
+ buffer = buffer << 24 | stream.getByte() << 16 | stream.getByte() << 8 | stream.getByte();
25461
+ const nextByte = stream.getByte();
25462
+ this.buffer = nextByte & (1 << bufferLength) - 1;
25463
+ return (buffer << 8 - bufferLength | (nextByte & 255) >> bufferLength) >>> 0;
25464
+ }
25465
+ if (n === 8 && bufferLength === 0) {
25466
+ return stream.getByte();
25467
+ }
25468
+ while (bufferLength < n) {
25469
+ buffer = buffer << 8 | stream.getByte();
25470
+ bufferLength += 8;
25471
+ }
25472
+ bufferLength -= n;
25473
+ this.bufferLength = bufferLength;
25474
+ this.buffer = buffer & (1 << bufferLength) - 1;
25475
+ return buffer >> bufferLength;
25476
+ }
25477
+ align() {
25478
+ this.buffer = 0;
25479
+ this.bufferLength = 0;
25480
+ }
25481
+ readFlag() {
25482
+ return this.readBits(this.context.bitsPerFlag);
25483
+ }
25484
+ readCoordinate() {
25485
+ const { bitsPerCoordinate, decode } = this.context;
25486
+ const xi = this.readBits(bitsPerCoordinate);
25487
+ const yi = this.readBits(bitsPerCoordinate);
25488
+ const scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 23283064365386963e-26;
25489
+ return [
25490
+ xi * scale * (decode[1] - decode[0]) + decode[0],
25491
+ yi * scale * (decode[3] - decode[2]) + decode[2]
25492
+ ];
25493
+ }
25494
+ readComponents() {
25495
+ const { bitsPerComponent, colorFn, colorSpace, decode, numComps } = this.context;
25496
+ const scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 23283064365386963e-26;
25497
+ const components = this.tmpCompsBuf;
25498
+ for (let i = 0, j = 4; i < numComps; i++, j += 2) {
25499
+ const ci = this.readBits(bitsPerComponent);
25500
+ components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j];
25501
+ }
25502
+ const color = this.tmpCsCompsBuf;
25503
+ colorFn?.(components, 0, color, 0);
25504
+ return colorSpace.getRgb(color, 0);
25505
+ }
25506
+ };
25507
+ var bCache = null;
25508
+ function getB(count) {
25509
+ if (bCache?.has(count)) return bCache.get(count);
25510
+ const values = Array.from({ length: count + 1 }, (_, i) => {
25511
+ const t = i / count, t_ = 1 - t;
25512
+ return new Float32Array([
25513
+ t_ ** 3,
25514
+ 3 * t * t_ ** 2,
25515
+ 3 * t ** 2 * t_,
25516
+ t ** 3
25517
+ ]);
25518
+ });
25519
+ (bCache ??= /* @__PURE__ */ new Map()).set(count, values);
25520
+ return values;
25521
+ }
25522
+ var MeshShading = class _MeshShading extends BaseShading {
25523
+ static MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;
25524
+ static MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;
25525
+ // Count of triangles per entire mesh bounds.
25526
+ static TRIANGLE_DENSITY = 20;
25527
+ constructor(shadingType, stream, context, rowVertices) {
25528
+ super();
25529
+ this.shadingType = shadingType;
25530
+ this.bbox = this.background = null;
25531
+ this.coords = [];
25532
+ this.colors = [];
25533
+ this.figures = [];
25534
+ const reader = new MeshStreamReader(stream, context);
25535
+ let patchMesh = false;
25536
+ switch (this.shadingType) {
25537
+ case ShadingType.FREE_FORM_MESH:
25538
+ this._decodeType4Shading(reader);
25539
+ break;
25540
+ case ShadingType.LATTICE_FORM_MESH:
25541
+ const verticesPerRow = rowVertices | 0;
25542
+ if (verticesPerRow < 2) {
25543
+ throw new FormatError("Invalid VerticesPerRow");
25544
+ }
25545
+ this._decodeType5Shading(reader, verticesPerRow);
25546
+ break;
25547
+ case ShadingType.COONS_PATCH_MESH:
25548
+ this._decodeType6Shading(reader);
25549
+ patchMesh = true;
25550
+ break;
25551
+ case ShadingType.TENSOR_PATCH_MESH:
25552
+ this._decodeType7Shading(reader);
25553
+ patchMesh = true;
25554
+ break;
25555
+ default:
25556
+ unreachable2("Unsupported mesh type.");
25557
+ break;
25558
+ }
25559
+ if (patchMesh) {
25560
+ this._updateBounds();
25561
+ for (let i = 0, ii = this.figures.length; i < ii; i++) {
25562
+ this._buildFigureFromPatch(i);
25563
+ }
25564
+ }
25565
+ this._updateBounds();
25566
+ this._packData();
25567
+ }
25568
+ _decodeType4Shading(reader) {
25569
+ const coords = this.coords;
25570
+ const colors = this.colors;
25571
+ const operators = [];
25572
+ const ps = [];
25573
+ let verticesLeft = 0;
25574
+ while (reader.hasData) {
25575
+ const f = reader.readFlag();
25576
+ const coord = reader.readCoordinate();
25577
+ const color = reader.readComponents();
25578
+ if (verticesLeft === 0) {
25579
+ if (!(0 <= f && f <= 2)) {
25580
+ throw new FormatError("Unknown type4 flag");
25581
+ }
25582
+ switch (f) {
25583
+ case 0:
25584
+ verticesLeft = 3;
25585
+ break;
25586
+ case 1:
25587
+ ps.push(ps.at(-2), ps.at(-1));
25588
+ verticesLeft = 1;
25589
+ break;
25590
+ case 2:
25591
+ ps.push(ps.at(-3), ps.at(-1));
25592
+ verticesLeft = 1;
25593
+ break;
25594
+ }
25595
+ operators.push(f);
25596
+ }
25597
+ ps.push(coords.length);
25598
+ coords.push(coord);
25599
+ colors.push(color);
25600
+ verticesLeft--;
25601
+ reader.align();
25602
+ }
25603
+ this.figures.push({
25604
+ type: MeshFigureType.TRIANGLES,
25605
+ coords: new Int32Array(ps),
25606
+ colors: new Int32Array(ps)
25607
+ });
25608
+ }
25609
+ _decodeType5Shading(reader, verticesPerRow) {
25610
+ const coords = this.coords;
25611
+ const colors = this.colors;
25612
+ const ps = [];
25613
+ while (reader.hasData) {
25614
+ const coord = reader.readCoordinate();
25615
+ const color = reader.readComponents();
25616
+ ps.push(coords.length);
25617
+ coords.push(coord);
25618
+ colors.push(color);
25619
+ }
25620
+ this.figures.push({
25621
+ type: MeshFigureType.LATTICE,
25622
+ coords: new Int32Array(ps),
25623
+ colors: new Int32Array(ps),
25624
+ verticesPerRow
25625
+ });
25626
+ }
25627
+ _decodeType6Shading(reader) {
25628
+ const coords = this.coords;
25629
+ const colors = this.colors;
25630
+ const ps = new Int32Array(16);
25631
+ const cs = new Int32Array(4);
25632
+ while (reader.hasData) {
25633
+ const f = reader.readFlag();
25634
+ if (!(0 <= f && f <= 3)) {
25635
+ throw new FormatError("Unknown type6 flag");
25636
+ }
25637
+ const pi = coords.length;
25638
+ for (let i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) {
25639
+ coords.push(reader.readCoordinate());
25640
+ }
25641
+ const ci = colors.length;
25642
+ for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
25643
+ colors.push(reader.readComponents());
25644
+ }
25645
+ let tmp1, tmp2, tmp3, tmp4;
25646
+ switch (f) {
25647
+ // prettier-ignore
25648
+ case 0:
25649
+ ps[12] = pi + 3;
25650
+ ps[13] = pi + 4;
25651
+ ps[14] = pi + 5;
25652
+ ps[15] = pi + 6;
25653
+ ps[8] = pi + 2;
25654
+ ps[11] = pi + 7;
25655
+ ps[4] = pi + 1;
25656
+ ps[7] = pi + 8;
25657
+ ps[0] = pi;
25658
+ ps[1] = pi + 11;
25659
+ ps[2] = pi + 10;
25660
+ ps[3] = pi + 9;
25661
+ cs[2] = ci + 1;
25662
+ cs[3] = ci + 2;
25663
+ cs[0] = ci;
25664
+ cs[1] = ci + 3;
25665
+ break;
25666
+ // prettier-ignore
25667
+ case 1:
25668
+ tmp1 = ps[12];
25669
+ tmp2 = ps[13];
25670
+ tmp3 = ps[14];
25671
+ tmp4 = ps[15];
25672
+ ps[12] = tmp4;
25673
+ ps[13] = pi + 0;
25674
+ ps[14] = pi + 1;
25675
+ ps[15] = pi + 2;
25676
+ ps[8] = tmp3;
25677
+ ps[11] = pi + 3;
25678
+ ps[4] = tmp2;
25679
+ ps[7] = pi + 4;
25680
+ ps[0] = tmp1;
25681
+ ps[1] = pi + 7;
25682
+ ps[2] = pi + 6;
25683
+ ps[3] = pi + 5;
25684
+ tmp1 = cs[2];
25685
+ tmp2 = cs[3];
25686
+ cs[2] = tmp2;
25687
+ cs[3] = ci;
25688
+ cs[0] = tmp1;
25689
+ cs[1] = ci + 1;
25690
+ break;
25691
+ // prettier-ignore
25692
+ case 2:
25693
+ tmp1 = ps[15];
25694
+ tmp2 = ps[11];
25695
+ ps[12] = ps[3];
25696
+ ps[13] = pi + 0;
25697
+ ps[14] = pi + 1;
25698
+ ps[15] = pi + 2;
25699
+ ps[8] = ps[7];
25700
+ ps[11] = pi + 3;
25701
+ ps[4] = tmp2;
25702
+ ps[7] = pi + 4;
25703
+ ps[0] = tmp1;
25704
+ ps[1] = pi + 7;
25705
+ ps[2] = pi + 6;
25706
+ ps[3] = pi + 5;
25707
+ tmp1 = cs[3];
25708
+ cs[2] = cs[1];
25709
+ cs[3] = ci;
25710
+ cs[0] = tmp1;
25711
+ cs[1] = ci + 1;
25712
+ break;
25713
+ // prettier-ignore
25714
+ case 3:
25715
+ ps[12] = ps[0];
25716
+ ps[13] = pi + 0;
25717
+ ps[14] = pi + 1;
25718
+ ps[15] = pi + 2;
25719
+ ps[8] = ps[1];
25720
+ ps[11] = pi + 3;
25721
+ ps[4] = ps[2];
25722
+ ps[7] = pi + 4;
25723
+ ps[0] = ps[3];
25724
+ ps[1] = pi + 7;
25725
+ ps[2] = pi + 6;
25726
+ ps[3] = pi + 5;
25727
+ cs[2] = cs[0];
25728
+ cs[3] = ci;
25729
+ cs[0] = cs[1];
25730
+ cs[1] = ci + 1;
25731
+ break;
25732
+ }
25733
+ ps[5] = coords.length;
25734
+ coords.push([
25735
+ (-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,
25736
+ (-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
25737
+ ]);
25738
+ ps[6] = coords.length;
25739
+ coords.push([
25740
+ (-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,
25741
+ (-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
25742
+ ]);
25743
+ ps[9] = coords.length;
25744
+ coords.push([
25745
+ (-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,
25746
+ (-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
25747
+ ]);
25748
+ ps[10] = coords.length;
25749
+ coords.push([
25750
+ (-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,
25751
+ (-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
25752
+ ]);
25753
+ this.figures.push({
25754
+ type: MeshFigureType.PATCH,
25755
+ coords: new Int32Array(ps),
25756
+ // making copies of ps and cs
25757
+ colors: new Int32Array(cs)
25758
+ });
25759
+ }
25760
+ }
25761
+ _decodeType7Shading(reader) {
25762
+ const coords = this.coords;
25763
+ const colors = this.colors;
25764
+ const ps = new Int32Array(16);
25765
+ const cs = new Int32Array(4);
25766
+ while (reader.hasData) {
25767
+ const f = reader.readFlag();
25768
+ if (!(0 <= f && f <= 3)) {
25769
+ throw new FormatError("Unknown type7 flag");
25770
+ }
25771
+ const pi = coords.length;
25772
+ for (let i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) {
25773
+ coords.push(reader.readCoordinate());
25774
+ }
25775
+ const ci = colors.length;
25776
+ for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
25777
+ colors.push(reader.readComponents());
25778
+ }
25779
+ let tmp1, tmp2, tmp3, tmp4;
25780
+ switch (f) {
25781
+ // prettier-ignore
25782
+ case 0:
25783
+ ps[12] = pi + 3;
25784
+ ps[13] = pi + 4;
25785
+ ps[14] = pi + 5;
25786
+ ps[15] = pi + 6;
25787
+ ps[8] = pi + 2;
25788
+ ps[9] = pi + 13;
25789
+ ps[10] = pi + 14;
25790
+ ps[11] = pi + 7;
25791
+ ps[4] = pi + 1;
25792
+ ps[5] = pi + 12;
25793
+ ps[6] = pi + 15;
25794
+ ps[7] = pi + 8;
25795
+ ps[0] = pi;
25796
+ ps[1] = pi + 11;
25797
+ ps[2] = pi + 10;
25798
+ ps[3] = pi + 9;
25799
+ cs[2] = ci + 1;
25800
+ cs[3] = ci + 2;
25801
+ cs[0] = ci;
25802
+ cs[1] = ci + 3;
25803
+ break;
25804
+ // prettier-ignore
25805
+ case 1:
25806
+ tmp1 = ps[12];
25807
+ tmp2 = ps[13];
25808
+ tmp3 = ps[14];
25809
+ tmp4 = ps[15];
25810
+ ps[12] = tmp4;
25811
+ ps[13] = pi + 0;
25812
+ ps[14] = pi + 1;
25813
+ ps[15] = pi + 2;
25814
+ ps[8] = tmp3;
25815
+ ps[9] = pi + 9;
25816
+ ps[10] = pi + 10;
25817
+ ps[11] = pi + 3;
25818
+ ps[4] = tmp2;
25819
+ ps[5] = pi + 8;
25820
+ ps[6] = pi + 11;
25821
+ ps[7] = pi + 4;
25822
+ ps[0] = tmp1;
25823
+ ps[1] = pi + 7;
25824
+ ps[2] = pi + 6;
25825
+ ps[3] = pi + 5;
25826
+ tmp1 = cs[2];
25827
+ tmp2 = cs[3];
25828
+ cs[2] = tmp2;
25829
+ cs[3] = ci;
25830
+ cs[0] = tmp1;
25831
+ cs[1] = ci + 1;
25832
+ break;
25833
+ // prettier-ignore
25834
+ case 2:
25835
+ tmp1 = ps[15];
25836
+ tmp2 = ps[11];
25837
+ ps[12] = ps[3];
25838
+ ps[13] = pi + 0;
25839
+ ps[14] = pi + 1;
25840
+ ps[15] = pi + 2;
25841
+ ps[8] = ps[7];
25842
+ ps[9] = pi + 9;
25843
+ ps[10] = pi + 10;
25844
+ ps[11] = pi + 3;
25845
+ ps[4] = tmp2;
25846
+ ps[5] = pi + 8;
25847
+ ps[6] = pi + 11;
25848
+ ps[7] = pi + 4;
25849
+ ps[0] = tmp1;
25850
+ ps[1] = pi + 7;
25851
+ ps[2] = pi + 6;
25852
+ ps[3] = pi + 5;
25853
+ tmp1 = cs[3];
25854
+ cs[2] = cs[1];
25855
+ cs[3] = ci;
25856
+ cs[0] = tmp1;
25857
+ cs[1] = ci + 1;
25858
+ break;
25859
+ // prettier-ignore
25860
+ case 3:
25861
+ ps[12] = ps[0];
25862
+ ps[13] = pi + 0;
25863
+ ps[14] = pi + 1;
25864
+ ps[15] = pi + 2;
25865
+ ps[8] = ps[1];
25866
+ ps[9] = pi + 9;
25867
+ ps[10] = pi + 10;
25868
+ ps[11] = pi + 3;
25869
+ ps[4] = ps[2];
25870
+ ps[5] = pi + 8;
25871
+ ps[6] = pi + 11;
25872
+ ps[7] = pi + 4;
25873
+ ps[0] = ps[3];
25874
+ ps[1] = pi + 7;
25875
+ ps[2] = pi + 6;
25876
+ ps[3] = pi + 5;
25877
+ cs[2] = cs[0];
25878
+ cs[3] = ci;
25879
+ cs[0] = cs[1];
25880
+ cs[1] = ci + 1;
25881
+ break;
25882
+ }
25883
+ this.figures.push({
25884
+ type: MeshFigureType.PATCH,
25885
+ coords: new Int32Array(ps),
25886
+ // making copies of ps and cs
25887
+ colors: new Int32Array(cs)
25888
+ });
25889
+ }
25890
+ }
25891
+ _buildFigureFromPatch(index) {
25892
+ const figure = this.figures[index];
25893
+ assert2(
25894
+ figure.type === MeshFigureType.PATCH,
25895
+ "Unexpected patch mesh figure"
25896
+ );
25897
+ const coords = this.coords, colors = this.colors;
25898
+ const pi = figure.coords;
25899
+ const ci = figure.colors;
25900
+ const figureMinX = Math.min(
25901
+ coords[pi[0]][0],
25902
+ coords[pi[3]][0],
25903
+ coords[pi[12]][0],
25904
+ coords[pi[15]][0]
25905
+ );
25906
+ const figureMinY = Math.min(
25907
+ coords[pi[0]][1],
25908
+ coords[pi[3]][1],
25909
+ coords[pi[12]][1],
25910
+ coords[pi[15]][1]
25911
+ );
25912
+ const figureMaxX = Math.max(
25913
+ coords[pi[0]][0],
25914
+ coords[pi[3]][0],
25915
+ coords[pi[12]][0],
25916
+ coords[pi[15]][0]
25917
+ );
25918
+ const figureMaxY = Math.max(
25919
+ coords[pi[0]][1],
25920
+ coords[pi[3]][1],
25921
+ coords[pi[12]][1],
25922
+ coords[pi[15]][1]
25923
+ );
25924
+ let splitXBy = Math.ceil(
25925
+ (figureMaxX - figureMinX) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[2] - this.bounds[0])
25926
+ );
25927
+ splitXBy = MathClamp(
25928
+ splitXBy,
25929
+ _MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
25930
+ _MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT
25931
+ );
25932
+ let splitYBy = Math.ceil(
25933
+ (figureMaxY - figureMinY) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[3] - this.bounds[1])
25934
+ );
25935
+ splitYBy = MathClamp(
25936
+ splitYBy,
25937
+ _MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
25938
+ _MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT
25939
+ );
25940
+ const verticesPerRow = splitXBy + 1;
25941
+ const figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
25942
+ const figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
25943
+ let k = 0;
25944
+ const cl = new Uint8Array(3), cr = new Uint8Array(3);
25945
+ const c0 = colors[ci[0]], c1 = colors[ci[1]], c2 = colors[ci[2]], c3 = colors[ci[3]];
25946
+ const bRow = getB(splitYBy), bCol = getB(splitXBy);
25947
+ for (let row = 0; row <= splitYBy; row++) {
25948
+ cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0;
25949
+ cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0;
25950
+ cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0;
25951
+ cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0;
25952
+ cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0;
25953
+ cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0;
25954
+ for (let col = 0; col <= splitXBy; col++, k++) {
25955
+ if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) {
25956
+ continue;
25957
+ }
25958
+ let x = 0, y = 0;
25959
+ let q = 0;
25960
+ for (let i = 0; i <= 3; i++) {
25961
+ for (let j = 0; j <= 3; j++, q++) {
25962
+ const m = bRow[row][i] * bCol[col][j];
25963
+ x += coords[pi[q]][0] * m;
25964
+ y += coords[pi[q]][1] * m;
25965
+ }
25966
+ }
25967
+ figureCoords[k] = coords.length;
25968
+ coords.push([x, y]);
25969
+ figureColors[k] = colors.length;
25970
+ const newColor = new Uint8Array(3);
25971
+ newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0;
25972
+ newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0;
25973
+ newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0;
25974
+ colors.push(newColor);
25975
+ }
25976
+ }
25977
+ figureCoords[0] = pi[0];
25978
+ figureColors[0] = ci[0];
25979
+ figureCoords[splitXBy] = pi[3];
25980
+ figureColors[splitXBy] = ci[1];
25981
+ figureCoords[verticesPerRow * splitYBy] = pi[12];
25982
+ figureColors[verticesPerRow * splitYBy] = ci[2];
25983
+ figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15];
25984
+ figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
25985
+ this.figures[index] = {
25986
+ type: MeshFigureType.LATTICE,
25987
+ coords: figureCoords,
25988
+ colors: figureColors,
25989
+ verticesPerRow
25990
+ };
25991
+ }
25992
+ _updateBounds() {
25993
+ meshUpdateBounds(this);
25994
+ }
25995
+ _packData() {
25996
+ meshPackData(this);
25997
+ }
25998
+ getIR() {
25999
+ const { posData, colData, vertexCount } = buildMeshVertexData(
26000
+ this.coords,
26001
+ this.colors,
26002
+ this.figures
26003
+ );
26004
+ return [
26005
+ "Mesh",
26006
+ this.shadingType,
26007
+ posData,
26008
+ colData,
26009
+ vertexCount,
26010
+ this.bounds,
26011
+ this.bbox,
26012
+ this.background
26013
+ ];
26014
+ }
26015
+ };
22709
26016
  var PdfError = class extends Error {
22710
26017
  constructor(code, message) {
22711
26018
  super(message);
@@ -25611,11 +28918,16 @@ function parseDictionaryStream(dictNode, lexer, bytes) {
25611
28918
  let streamEnd = streamStart;
25612
28919
  if (resolvedLength !== void 0 && resolvedLength >= 0 && streamStart + resolvedLength <= bytes.length) {
25613
28920
  const candidateEnd = streamStart + resolvedLength;
25614
- const tailSlice = bytes.subarray(candidateEnd, Math.min(bytes.length, candidateEnd + 32));
25615
- const tailStr = new TextDecoder("latin1").decode(tailSlice);
25616
- if (tailStr.includes("endstream")) {
28921
+ const tailLexer = new CosByteLexer(bytes, candidateEnd);
28922
+ let endToken;
28923
+ try {
28924
+ endToken = tailLexer.nextToken();
28925
+ } catch (error) {
28926
+ if (!(error instanceof PdfError) || error.code !== "E_PARSE") throw error;
28927
+ }
28928
+ if (endToken?.kind === "keyword" && endToken.value === "endstream") {
25617
28929
  rawStreamBytes = bytes.subarray(streamStart, candidateEnd);
25618
- streamEnd = candidateEnd + tailStr.indexOf("endstream") + "endstream".length;
28930
+ streamEnd = tailLexer.offset;
25619
28931
  }
25620
28932
  }
25621
28933
  if (!rawStreamBytes) {
@@ -33785,6 +37097,25 @@ var __webpack_exports__JpxImage = __webpack_exports__.JpxImage;
33785
37097
  var __webpack_exports__VerbosityLevel = __webpack_exports__.VerbosityLevel;
33786
37098
  var __webpack_exports__getVerbosityLevel = __webpack_exports__.getVerbosityLevel;
33787
37099
  var __webpack_exports__setVerbosityLevel = __webpack_exports__.setVerbosityLevel;
37100
+ function createCalibratedColorSpace(doc, family, parameters) {
37101
+ const dict = doc.resolveDict(parameters);
37102
+ const array = (key) => {
37103
+ const value = dict ? doc.resolveArray(dictGet(dict, key)) : void 0;
37104
+ return value?.items.map((item) => {
37105
+ const number = doc.resolve(item);
37106
+ return number?.kind === "number" ? number.value : 0;
37107
+ });
37108
+ };
37109
+ const whitePoint = array("WhitePoint") ?? [0.95047, 1, 1.08883];
37110
+ const blackPoint = array("BlackPoint");
37111
+ if (family === "CalGray") {
37112
+ const gamma = dict ? doc.resolve(dictGet(dict, "Gamma")) : void 0;
37113
+ return new CalGrayCS(whitePoint, blackPoint, gamma?.kind === "number" ? gamma.value : void 0);
37114
+ }
37115
+ if (family === "CalRGB") return new CalRGBCS(whitePoint, blackPoint, array("Gamma"), array("Matrix"));
37116
+ return new LabCS(whitePoint, blackPoint, array("Range"));
37117
+ }
37118
+ var cmykColorSpace = new DeviceCmykCS();
33788
37119
  function collectPageLeaves(doc, node, inheritedResources, out = [], visited = /* @__PURE__ */ new Set()) {
33789
37120
  if (!node) return out;
33790
37121
  if (node.kind === "ref") {
@@ -33873,7 +37204,7 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
33873
37204
  palette = lookupNode.bytes;
33874
37205
  }
33875
37206
  let resolvedBaseComp = baseInfo.components;
33876
- if (palette && (baseInfo.isLab || baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calRgbGamma !== void 0 || baseInfo.calGrayGamma !== void 0)) {
37207
+ if (palette && (baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calibrated !== void 0)) {
33877
37208
  const numEntries = Math.max(1, Math.min(hival + 1, Math.floor(palette.length / Math.max(1, baseInfo.components))));
33878
37209
  const rgbaPal = decodeSamplesToRgba(palette, numEntries, 1, 8, baseInfo);
33879
37210
  const rgbPal = new Uint8Array(numEntries * 3);
@@ -33903,74 +37234,21 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
33903
37234
  }
33904
37235
  return { colorSpace: "rgb", colorSpaceLabel: "icc", components: 3 };
33905
37236
  }
33906
- if (kindName === "CalGray") {
33907
- const calDict = doc.resolveDict(resolved.items[1]);
33908
- const gammaNode = calDict ? doc.resolve(dictGet(calDict, "Gamma")) : void 0;
33909
- const gamma = gammaNode?.kind === "number" && gammaNode.value > 0 ? gammaNode.value : 1;
33910
- return { colorSpace: "gray", colorSpaceLabel: "cal-gray", components: 1, calGrayGamma: gamma };
33911
- }
33912
- if (kindName === "CalRGB") {
33913
- const calDict = doc.resolveDict(resolved.items[1]);
33914
- const gammaArr = calDict ? doc.resolveArray(dictGet(calDict, "Gamma")) : void 0;
33915
- let calRgbGamma = [1, 1, 1];
33916
- if (gammaArr && gammaArr.items.length >= 3) {
33917
- const gNums = gammaArr.items.slice(0, 3).map((it) => {
33918
- const r = doc.resolve(it);
33919
- return r?.kind === "number" && r.value > 0 ? r.value : 1;
33920
- });
33921
- calRgbGamma = [gNums[0], gNums[1], gNums[2]];
33922
- }
33923
- const matArr = calDict ? doc.resolveArray(dictGet(calDict, "Matrix")) : void 0;
33924
- let calRgbMatrix;
33925
- if (matArr && matArr.items.length >= 9) {
33926
- calRgbMatrix = matArr.items.slice(0, 9).map((it) => {
33927
- const r = doc.resolve(it);
33928
- return r?.kind === "number" ? r.value : 0;
33929
- });
33930
- }
37237
+ if (kindName === "CalGray" || kindName === "CalRGB" || kindName === "Lab") {
37238
+ const calibrated = createCalibratedColorSpace(doc, kindName, resolved.items[1]);
33931
37239
  return {
33932
- colorSpace: "rgb",
33933
- colorSpaceLabel: "cal-rgb",
33934
- components: 3,
33935
- calRgbGamma,
33936
- calRgbMatrix
37240
+ colorSpace: kindName === "CalGray" ? "gray" : "rgb",
37241
+ colorSpaceLabel: kindName === "CalGray" ? "cal-gray" : kindName === "CalRGB" ? "cal-rgb" : "lab",
37242
+ components: kindName === "CalGray" ? 1 : 3,
37243
+ calibrated
33937
37244
  };
33938
37245
  }
33939
- if (kindName === "Lab") {
33940
- const labDict = doc.resolveDict(resolved.items[1]);
33941
- const rangeArr = labDict ? doc.resolveArray(dictGet(labDict, "Range")) : void 0;
33942
- let labRange = [-100, 100, -100, 100];
33943
- if (rangeArr && rangeArr.items.length >= 4) {
33944
- const nums = rangeArr.items.slice(0, 4).map((it) => {
33945
- const r = doc.resolve(it);
33946
- return r?.kind === "number" ? r.value : 0;
33947
- });
33948
- labRange = [nums[0], nums[1], nums[2], nums[3]];
33949
- }
33950
- return { colorSpace: "rgb", colorSpaceLabel: "lab", components: 3, isLab: true, labRange };
33951
- }
33952
37246
  if (kindName === "Separation" || kindName === "DeviceN") {
33953
37247
  const isDevN = kindName === "DeviceN";
33954
37248
  const namesArr = isDevN ? doc.resolveArray(resolved.items[1]) : void 0;
33955
37249
  const devNComponents = isDevN && namesArr ? Math.max(1, namesArr.items.length) : 1;
33956
37250
  const altInfo = resolveColorSpaceInfo(doc, resolved.items[2], resourcesDict);
33957
37251
  const altSpace = altInfo.colorSpace === "cmyk" ? "cmyk" : altInfo.colorSpace === "gray" ? "gray" : "rgb";
33958
- const fnResolved = doc.resolve(resolved.items[3]);
33959
- const fnDict = fnResolved?.kind === "stream" ? fnResolved.dict : fnResolved?.kind === "dict" ? fnResolved : void 0;
33960
- const ftNode = fnDict ? doc.resolve(dictGet(fnDict, "FunctionType")) : void 0;
33961
- const tintFunctionType = ftNode?.kind === "number" ? ftNode.value : 2;
33962
- const c0Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C0")) : void 0;
33963
- const c1Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C1")) : void 0;
33964
- const nNode = fnDict ? doc.resolve(dictGet(fnDict, "N")) : void 0;
33965
- const c0 = c0Arr ? c0Arr.items.map((it) => {
33966
- const r = doc.resolve(it);
33967
- return r?.kind === "number" ? r.value : 0;
33968
- }) : altSpace === "cmyk" ? [0, 0, 0, 0] : altSpace === "gray" ? [1] : [1, 1, 1];
33969
- const c1 = c1Arr ? c1Arr.items.map((it) => {
33970
- const r = doc.resolve(it);
33971
- return r?.kind === "number" ? r.value : 0;
33972
- }) : altSpace === "cmyk" ? [0, 0, 0, 1] : altSpace === "gray" ? [0] : [0, 0, 0];
33973
- const sepN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
33974
37252
  return {
33975
37253
  colorSpace: altSpace,
33976
37254
  colorSpaceLabel: isDevN ? "devn" : "sep",
@@ -33978,12 +37256,9 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
33978
37256
  isSeparation: !isDevN,
33979
37257
  isDeviceN: isDevN,
33980
37258
  separationAltSpace: altSpace,
33981
- separationC0: c0,
33982
- separationC1: c1,
33983
- separationN: sepN,
37259
+ alternateCalibrated: altInfo.calibrated,
33984
37260
  tintFunctionDoc: doc,
33985
- tintFunctionNode: resolved.items[3],
33986
- tintFunctionType
37261
+ tintFunctionNode: resolved.items[3]
33987
37262
  };
33988
37263
  }
33989
37264
  }
@@ -34133,141 +37408,55 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
34133
37408
  const rgba = new Uint8Array(width * height * 4);
34134
37409
  const pixelCount = width * height;
34135
37410
  if (csInfo.isSeparation || csInfo.isDeviceN) {
34136
- const c0 = csInfo.separationC0 ?? [1, 1, 1];
34137
- const c1 = csInfo.separationC1 ?? [0, 0, 0];
34138
- const expN = csInfo.separationN ?? 1;
34139
37411
  const alt = csInfo.separationAltSpace ?? "rgb";
34140
37412
  const numCh = Math.max(1, csInfo.components);
34141
37413
  const step = bpc === 16 ? 2 : 1;
34142
- const useGenericTintFn = csInfo.tintFunctionDoc !== void 0 && csInfo.tintFunctionNode !== void 0 && (csInfo.tintFunctionType === 0 || csInfo.tintFunctionType === 3 || csInfo.tintFunctionType === 4);
34143
37414
  for (let p = 0; p < pixelCount; p++) {
34144
37415
  const chVals = [];
34145
- let wSum = 0;
34146
37416
  for (let ch3 = 0; ch3 < numCh; ch3++) {
34147
37417
  const sRaw = (rawSamples[(p * numCh + ch3) * step] ?? 0) / 255;
34148
- const tRemapped = remapUnitSampleWithDecode(sRaw, ch3, decodePairs);
34149
- chVals.push(tRemapped);
34150
- wSum += Math.pow(Math.max(0, Math.min(1, tRemapped)), expN);
34151
- }
34152
- if (useGenericTintFn) {
34153
- const outComps = evalShadingFunctionToComponents(
34154
- csInfo.tintFunctionDoc,
34155
- csInfo.tintFunctionNode,
34156
- chVals
34157
- );
34158
- if (alt === "cmyk") {
34159
- const c = outComps[0] ?? 0;
34160
- const m = outComps[1] ?? 0;
34161
- const y = outComps[2] ?? 0;
34162
- const k = outComps[3] ?? 0;
34163
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, (1 - c) * (1 - k))) * 255);
34164
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, (1 - m) * (1 - k))) * 255);
34165
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, (1 - y) * (1 - k))) * 255);
34166
- } else if (alt === "gray") {
34167
- const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
34168
- rgba[p * 4] = gByte;
34169
- rgba[p * 4 + 1] = gByte;
34170
- rgba[p * 4 + 2] = gByte;
34171
- } else {
34172
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
34173
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
34174
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
34175
- }
34176
- rgba[p * 4 + 3] = 255;
34177
- continue;
37418
+ chVals.push(remapUnitSampleWithDecode(sRaw, ch3, decodePairs));
34178
37419
  }
34179
- const w = Math.max(0, Math.min(1, wSum));
34180
- if (alt === "cmyk") {
34181
- const c = (c0[0] ?? 0) + w * ((c1[0] ?? 0) - (c0[0] ?? 0));
34182
- const m = (c0[1] ?? 0) + w * ((c1[1] ?? 0) - (c0[1] ?? 0));
34183
- const y = (c0[2] ?? 0) + w * ((c1[2] ?? 0) - (c0[2] ?? 0));
34184
- const k = (c0[3] ?? 0) + w * ((c1[3] ?? 1) - (c0[3] ?? 0));
34185
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, (1 - c) * (1 - k))) * 255);
34186
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, (1 - m) * (1 - k))) * 255);
34187
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, (1 - y) * (1 - k))) * 255);
37420
+ const outComps = evalShadingFunctionToComponents(
37421
+ csInfo.tintFunctionDoc,
37422
+ csInfo.tintFunctionNode,
37423
+ chVals
37424
+ );
37425
+ if (csInfo.alternateCalibrated) {
37426
+ rgba.set(csInfo.alternateCalibrated.getRgb(outComps, 0), p * 4);
37427
+ } else if (alt === "cmyk") {
37428
+ rgba.set(cmykColorSpace.getRgb([outComps[0] ?? 0, outComps[1] ?? 0, outComps[2] ?? 0, outComps[3] ?? 0], 0), p * 4);
34188
37429
  } else if (alt === "gray") {
34189
- const gVal = (c0[0] ?? 1) + w * ((c1[0] ?? 0) - (c0[0] ?? 1));
34190
- const gByte = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
37430
+ const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
34191
37431
  rgba[p * 4] = gByte;
34192
37432
  rgba[p * 4 + 1] = gByte;
34193
37433
  rgba[p * 4 + 2] = gByte;
34194
37434
  } else {
34195
- const rVal = (c0[0] ?? 1) + w * ((c1[0] ?? 0) - (c0[0] ?? 1));
34196
- const gVal = (c0[1] ?? 1) + w * ((c1[1] ?? 0) - (c0[1] ?? 1));
34197
- const bVal = (c0[2] ?? 1) + w * ((c1[2] ?? 0) - (c0[2] ?? 1));
34198
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, rVal)) * 255);
34199
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
34200
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, bVal)) * 255);
37435
+ rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
37436
+ rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
37437
+ rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
34201
37438
  }
34202
37439
  rgba[p * 4 + 3] = 255;
34203
37440
  }
34204
- } else if (csInfo.isLab) {
34205
- const [amin, amax, bmin, bmax] = csInfo.labRange ?? [-100, 100, -100, 100];
34206
- const invF = (t) => t > 6 / 29 ? t * t * t : 3 * (6 / 29) * (6 / 29) * (t - 4 / 29);
34207
- const toSrgb = (u) => {
34208
- const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
34209
- return Math.round(Math.max(0, Math.min(1, c)) * 255);
34210
- };
37441
+ } else if (csInfo.calibrated?.name === "Lab") {
37442
+ const { amin, amax, bmin, bmax } = csInfo.calibrated;
37443
+ const step = bpc === 16 ? 2 : 1;
34211
37444
  for (let p = 0; p < pixelCount; p++) {
34212
- const s0 = (rawSamples[p * 3] ?? 0) / 255;
34213
- const s1 = (rawSamples[p * 3 + 1] ?? 128) / 255;
34214
- const s2 = (rawSamples[p * 3 + 2] ?? 128) / 255;
34215
- const L = s0 * 100;
34216
- if (L <= 0.01) {
34217
- rgba[p * 4] = 0;
34218
- rgba[p * 4 + 1] = 0;
34219
- rgba[p * 4 + 2] = 0;
34220
- rgba[p * 4 + 3] = 255;
34221
- continue;
34222
- }
34223
- const a = amin + s1 * (amax - amin);
34224
- const b = bmin + s2 * (bmax - bmin);
34225
- const fy = (L + 16) / 116;
34226
- const fx = fy + a / 500;
34227
- const fz = fy - b / 200;
34228
- const X = 0.95047 * invF(fx);
34229
- const Y = 1 * invF(fy);
34230
- const Z = 1.08883 * invF(fz);
34231
- const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
34232
- const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
34233
- const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
34234
- rgba[p * 4] = toSrgb(linR);
34235
- rgba[p * 4 + 1] = toSrgb(linG);
34236
- rgba[p * 4 + 2] = toSrgb(linB);
37445
+ const L = (rawSamples[p * 3 * step] ?? 0) / 255 * 100;
37446
+ const a = amin + (rawSamples[(p * 3 + 1) * step] ?? 128) / 255 * (amax - amin);
37447
+ const b = bmin + (rawSamples[(p * 3 + 2) * step] ?? 128) / 255 * (bmax - bmin);
37448
+ rgba.set(csInfo.calibrated.getRgb([L, a, b], 0), p * 4);
34237
37449
  rgba[p * 4 + 3] = 255;
34238
37450
  }
34239
37451
  } else if (csInfo.colorSpace === "rgb") {
34240
- const hasCalRgb = Boolean(csInfo.calRgbGamma || csInfo.calRgbMatrix);
34241
- const toSrgbByte = (u) => {
34242
- const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
34243
- return Math.round(Math.max(0, Math.min(1, c)) * 255);
34244
- };
34245
37452
  const writeRgbPixel = (p, rByte, gByte, bByte) => {
34246
- let rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
34247
- let gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
34248
- let bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
34249
- if (hasCalRgb) {
34250
- const [gr, gg, gb] = csInfo.calRgbGamma ?? [1, 1, 1];
34251
- const ag = Math.pow(rU, gr);
34252
- const bg = Math.pow(gU, gg);
34253
- const cg = Math.pow(bU, gb);
34254
- if (csInfo.calRgbMatrix && csInfo.calRgbMatrix.length >= 9) {
34255
- const m = csInfo.calRgbMatrix;
34256
- const X = m[0] * ag + m[3] * bg + m[6] * cg;
34257
- const Y = m[1] * ag + m[4] * bg + m[7] * cg;
34258
- const Z = m[2] * ag + m[5] * bg + m[8] * cg;
34259
- const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
34260
- const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
34261
- const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
34262
- rgba[p * 4] = toSrgbByte(linR);
34263
- rgba[p * 4 + 1] = toSrgbByte(linG);
34264
- rgba[p * 4 + 2] = toSrgbByte(linB);
34265
- rgba[p * 4 + 3] = 255;
34266
- return;
34267
- }
34268
- rU = ag;
34269
- gU = bg;
34270
- bU = cg;
37453
+ const rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
37454
+ const gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
37455
+ const bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
37456
+ if (csInfo.calibrated) {
37457
+ rgba.set(csInfo.calibrated.getRgb([rU, gU, bU], 0), p * 4);
37458
+ rgba[p * 4 + 3] = 255;
37459
+ return;
34271
37460
  }
34272
37461
  rgba[p * 4] = Math.round(rU * 255);
34273
37462
  rgba[p * 4 + 1] = Math.round(gU * 255);
@@ -34287,10 +37476,11 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
34287
37476
  }
34288
37477
  } else if (csInfo.colorSpace === "gray") {
34289
37478
  const writeGrayPixel = (p, gByte) => {
34290
- let gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
34291
- if (csInfo.calGrayGamma && csInfo.calGrayGamma !== 1) {
34292
- const lin = Math.pow(gU, csInfo.calGrayGamma);
34293
- gU = lin <= 31308e-7 ? 12.92 * lin : 1.055 * Math.pow(lin, 1 / 2.4) - 0.055;
37479
+ const gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
37480
+ if (csInfo.calibrated) {
37481
+ rgba.set(csInfo.calibrated.getRgb([gU], 0), p * 4);
37482
+ rgba[p * 4 + 3] = 255;
37483
+ return;
34294
37484
  }
34295
37485
  const outG = Math.round(Math.max(0, Math.min(1, gU)) * 255);
34296
37486
  rgba[p * 4] = outG;
@@ -34346,9 +37536,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
34346
37536
  const m = remapUnitSampleWithDecode((rawSamples[p * stride + chStep] ?? 0) / 255, 1, decodePairs);
34347
37537
  const y = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 2] ?? 0) / 255, 2, decodePairs);
34348
37538
  const k = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 3] ?? 0) / 255, 3, decodePairs);
34349
- rgba[p * 4] = Math.round((1 - c) * (1 - k) * 255);
34350
- rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
34351
- rgba[p * 4 + 2] = Math.round((1 - y) * (1 - k) * 255);
37539
+ rgba.set(cmykColorSpace.getRgb([c, m, y, k], 0), p * 4);
34352
37540
  rgba[p * 4 + 3] = 255;
34353
37541
  }
34354
37542
  } else if (csInfo.colorSpace === "index") {
@@ -34386,9 +37574,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
34386
37574
  const m = pal[idx * 4 + 1] / 255;
34387
37575
  const yel = pal[idx * 4 + 2] / 255;
34388
37576
  const k = pal[idx * 4 + 3] / 255;
34389
- rgba[p * 4] = Math.round((1 - c) * (1 - k) * 255);
34390
- rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
34391
- rgba[p * 4 + 2] = Math.round((1 - yel) * (1 - k) * 255);
37577
+ rgba.set(cmykColorSpace.getRgb([c, m, yel, k], 0), p * 4);
34392
37578
  } else {
34393
37579
  rgba[p * 4] = pal[idx * baseComp];
34394
37580
  rgba[p * 4 + 1] = pal[idx * baseComp + 1];
@@ -34940,6 +38126,7 @@ function extractDocumentImages(doc, options = {}) {
34940
38126
  }
34941
38127
  return extracted;
34942
38128
  }
38129
+ var cmykColorSpace2 = new DeviceCmykCS();
34943
38130
  function multiplyMatrices(m1, m2) {
34944
38131
  return [
34945
38132
  m1[0] * m2[0] + m1[1] * m2[2],
@@ -35156,193 +38343,7 @@ function resolvePageFonts(doc, resourcesDict) {
35156
38343
  }
35157
38344
  return fonts;
35158
38345
  }
35159
- function evaluateType4PostScriptTokens(tokens, initialStack) {
35160
- const stack = [...initialStack];
35161
- const runRange = (start, end) => {
35162
- let i = start;
35163
- while (i < end) {
35164
- const tok = tokens[i];
35165
- if (tok === "{") {
35166
- let depth = 1;
35167
- let j = i + 1;
35168
- while (j < end && depth > 0) {
35169
- if (tokens[j] === "{") depth++;
35170
- else if (tokens[j] === "}") depth--;
35171
- j++;
35172
- }
35173
- const blockStart = i + 1;
35174
- const blockEnd = j - 1;
35175
- if (j < end && tokens[j] === "{") {
35176
- let depth2 = 1;
35177
- let k = j + 1;
35178
- while (k < end && depth2 > 0) {
35179
- if (tokens[k] === "{") depth2++;
35180
- else if (tokens[k] === "}") depth2--;
35181
- k++;
35182
- }
35183
- if (k < end && tokens[k] === "ifelse") {
35184
- const cond = stack.pop() ?? 0;
35185
- if (cond !== 0) runRange(blockStart, blockEnd);
35186
- else runRange(j + 1, k - 1);
35187
- i = k + 1;
35188
- continue;
35189
- }
35190
- }
35191
- if (j < end && tokens[j] === "if") {
35192
- const cond = stack.pop() ?? 0;
35193
- if (cond !== 0) runRange(blockStart, blockEnd);
35194
- i = j + 1;
35195
- continue;
35196
- }
35197
- runRange(blockStart, blockEnd);
35198
- i = j;
35199
- continue;
35200
- }
35201
- if (tok === "}") {
35202
- i++;
35203
- continue;
35204
- }
35205
- const numVal2 = Number(tok);
35206
- if (tok.length > 0 && !Number.isNaN(numVal2)) {
35207
- stack.push(numVal2);
35208
- } else if (tok === "true") {
35209
- stack.push(1);
35210
- } else if (tok === "false") {
35211
- stack.push(0);
35212
- } else if (tok === "add") {
35213
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35214
- stack.push(a + b);
35215
- } else if (tok === "sub") {
35216
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35217
- stack.push(a - b);
35218
- } else if (tok === "mul") {
35219
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35220
- stack.push(a * b);
35221
- } else if (tok === "div") {
35222
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
35223
- stack.push(Math.abs(b) > 1e-12 ? a / b : 0);
35224
- } else if (tok === "idiv") {
35225
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
35226
- stack.push(Math.abs(b) > 1e-12 ? Math.trunc(a / b) : 0);
35227
- } else if (tok === "mod") {
35228
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
35229
- stack.push(Math.abs(b) > 1e-12 ? a % b : 0);
35230
- } else if (tok === "neg") {
35231
- stack.push(-(stack.pop() ?? 0));
35232
- } else if (tok === "abs") {
35233
- stack.push(Math.abs(stack.pop() ?? 0));
35234
- } else if (tok === "ceiling") {
35235
- stack.push(Math.ceil(stack.pop() ?? 0));
35236
- } else if (tok === "floor") {
35237
- stack.push(Math.floor(stack.pop() ?? 0));
35238
- } else if (tok === "round") {
35239
- stack.push(Math.round(stack.pop() ?? 0));
35240
- } else if (tok === "truncate" || tok === "cvi") {
35241
- stack.push(Math.trunc(stack.pop() ?? 0));
35242
- } else if (tok === "sqrt") {
35243
- stack.push(Math.sqrt(Math.max(0, stack.pop() ?? 0)));
35244
- } else if (tok === "sin") {
35245
- stack.push(Math.sin((stack.pop() ?? 0) * Math.PI / 180));
35246
- } else if (tok === "cos") {
35247
- stack.push(Math.cos((stack.pop() ?? 0) * Math.PI / 180));
35248
- } else if (tok === "atan") {
35249
- const dx = stack.pop() ?? 1, dy = stack.pop() ?? 0;
35250
- let deg = Math.atan2(dy, dx) * 180 / Math.PI;
35251
- if (deg < 0) deg += 360;
35252
- stack.push(deg);
35253
- } else if (tok === "exp") {
35254
- const exp = stack.pop() ?? 1, base = stack.pop() ?? 0;
35255
- stack.push(Math.pow(base, exp));
35256
- } else if (tok === "ln") {
35257
- stack.push(Math.log(Math.max(1e-12, stack.pop() ?? 1)));
35258
- } else if (tok === "log") {
35259
- stack.push(Math.log10(Math.max(1e-12, stack.pop() ?? 1)));
35260
- } else if (tok === "dup") {
35261
- if (stack.length > 0) stack.push(stack[stack.length - 1]);
35262
- } else if (tok === "exch") {
35263
- if (stack.length >= 2) {
35264
- const b = stack.pop(), a = stack.pop();
35265
- stack.push(b, a);
35266
- }
35267
- } else if (tok === "pop") {
35268
- stack.pop();
35269
- } else if (tok === "copy") {
35270
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
35271
- const slice = stack.slice(Math.max(0, stack.length - n));
35272
- stack.push(...slice);
35273
- } else if (tok === "index") {
35274
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
35275
- const idx = stack.length - 1 - n;
35276
- if (idx >= 0 && idx < stack.length) stack.push(stack[idx]);
35277
- } else if (tok === "roll") {
35278
- const jShift = Math.trunc(stack.pop() ?? 0);
35279
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
35280
- if (n > 0 && stack.length >= n) {
35281
- const sub = stack.splice(stack.length - n, n);
35282
- const modShift = (jShift % n + n) % n;
35283
- const rolled = [...sub.slice(n - modShift), ...sub.slice(0, n - modShift)];
35284
- stack.push(...rolled);
35285
- }
35286
- } else if (tok === "eq") {
35287
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35288
- stack.push(Math.abs(a - b) < 1e-9 ? 1 : 0);
35289
- } else if (tok === "ne") {
35290
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35291
- stack.push(Math.abs(a - b) >= 1e-9 ? 1 : 0);
35292
- } else if (tok === "gt") {
35293
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35294
- stack.push(a > b ? 1 : 0);
35295
- } else if (tok === "ge") {
35296
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35297
- stack.push(a >= b ? 1 : 0);
35298
- } else if (tok === "lt") {
35299
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35300
- stack.push(a < b ? 1 : 0);
35301
- } else if (tok === "le") {
35302
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35303
- stack.push(a <= b ? 1 : 0);
35304
- } else if (tok === "and") {
35305
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35306
- stack.push(a !== 0 && b !== 0 ? 1 : 0);
35307
- } else if (tok === "or") {
35308
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35309
- stack.push(a !== 0 || b !== 0 ? 1 : 0);
35310
- } else if (tok === "not") {
35311
- const a = stack.pop() ?? 0;
35312
- stack.push(a === 0 ? 1 : 0);
35313
- }
35314
- i++;
35315
- }
35316
- };
35317
- runRange(0, tokens.length);
35318
- return stack;
35319
- }
35320
- function tokenizePostScriptCode(bytes) {
35321
- const tokens = [];
35322
- let cur = "";
35323
- for (let i = 0; i < bytes.length; i++) {
35324
- const ch3 = String.fromCharCode(bytes[i]);
35325
- if (ch3 === "{" || ch3 === "}") {
35326
- if (cur.length > 0) {
35327
- tokens.push(cur);
35328
- cur = "";
35329
- }
35330
- tokens.push(ch3);
35331
- } else if (ch3 === " " || ch3 === " " || ch3 === "\n" || ch3 === "\r") {
35332
- if (cur.length > 0) {
35333
- tokens.push(cur);
35334
- cur = "";
35335
- }
35336
- } else {
35337
- cur += ch3;
35338
- }
35339
- }
35340
- if (cur.length > 0) tokens.push(cur);
35341
- if (tokens[0] === "{" && tokens[tokens.length - 1] === "}") {
35342
- return tokens.slice(1, -1);
35343
- }
35344
- return tokens;
35345
- }
38346
+ var postScriptFunctions = /* @__PURE__ */ new WeakMap();
35346
38347
  function evalShadingFunctionToComponents(doc, fnNode, inputs) {
35347
38348
  const inArr = typeof inputs === "number" ? [inputs] : inputs;
35348
38349
  const t = inArr[0] ?? 0;
@@ -35389,35 +38390,50 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
35389
38390
  const decode = getNums("Decode", range);
35390
38391
  const nOut = Math.max(1, Math.floor((decode.length || range.length || 6) / 2));
35391
38392
  const mIn = Math.max(1, size.length);
35392
- let flatGridIndex = 0;
38393
+ const streamBytes = doc.decodeStream(resolved);
38394
+ let vertices = [{ index: 0, weight: 1 }];
35393
38395
  let stride = 1;
35394
38396
  for (let i = 0; i < mIn; i++) {
35395
38397
  const d02 = dom[i * 2] ?? 0;
35396
38398
  const d12 = dom[i * 2 + 1] ?? 1;
35397
- const sMax = Math.max(1, (size[i] ?? 2) - 1);
38399
+ const sMax = Math.max(0, (size[i] ?? 2) - 1);
35398
38400
  const e0 = encode[i * 2] ?? 0;
35399
38401
  const e1 = encode[i * 2 + 1] ?? sMax;
35400
38402
  const x = Math.max(d02, Math.min(d12, inArr[i] ?? 0));
35401
- const u = Math.abs(d12 - d02) > 1e-8 ? (x - d02) / (d12 - d02) : 0;
35402
- const idx = Math.round(Math.max(0, Math.min(sMax, e0 + u * (e1 - e0))));
35403
- flatGridIndex += idx * stride;
38403
+ const u = d12 === d02 ? 0 : (x - d02) / (d12 - d02);
38404
+ const e = Math.max(0, Math.min(sMax, e0 + u * (e1 - e0)));
38405
+ const low = Math.floor(e), fraction = e - low;
38406
+ const next = [];
38407
+ for (const vertex of vertices) {
38408
+ const index = vertex.index + low * stride;
38409
+ if (index * nOut * bps < streamBytes.length * 8) next.push({ index, weight: vertex.weight * (1 - fraction) });
38410
+ if (fraction && (index + stride) * nOut * bps < streamBytes.length * 8) {
38411
+ next.push({ index: index + stride, weight: vertex.weight * fraction });
38412
+ }
38413
+ }
38414
+ vertices = next;
35404
38415
  stride *= size[i] ?? 2;
35405
38416
  }
35406
- const streamBytes = doc.decodeStream(resolved);
38417
+ const maxSample = 2 ** bps - 1;
38418
+ const readSample = (index) => {
38419
+ let bitOffset = index * bps, remaining = bps, value = 0;
38420
+ while (remaining > 0) {
38421
+ const bitInByte = bitOffset % 8;
38422
+ const take = Math.min(remaining, 8 - bitInByte);
38423
+ const byte = streamBytes[Math.floor(bitOffset / 8)] ?? 0;
38424
+ value = value * 2 ** take + (byte >> 8 - bitInByte - take & (1 << take) - 1);
38425
+ bitOffset += take;
38426
+ remaining -= take;
38427
+ }
38428
+ return value / maxSample;
38429
+ };
35407
38430
  const out2 = [];
35408
- const maxSample = bps === 16 ? 65535 : 255;
35409
38431
  for (let j = 0; j < nOut; j++) {
35410
- const sampleIdx = flatGridIndex * nOut + j;
35411
- let rawVal = 0;
35412
- if (bps === 16) {
35413
- rawVal = (streamBytes[sampleIdx * 2] ?? 0) << 8 | (streamBytes[sampleIdx * 2 + 1] ?? 0);
35414
- } else {
35415
- rawVal = streamBytes[sampleIdx] ?? 0;
35416
- }
35417
- const frac = rawVal / maxSample;
38432
+ let value = 0;
38433
+ for (const vertex of vertices) value += readSample(vertex.index * nOut + j) * vertex.weight;
35418
38434
  const dec0 = decode[j * 2] ?? 0;
35419
38435
  const dec1 = decode[j * 2 + 1] ?? 1;
35420
- out2.push(dec0 + frac * (dec1 - dec0));
38436
+ out2.push(dec0 + value * (dec1 - dec0));
35421
38437
  }
35422
38438
  return clampRange(out2);
35423
38439
  }
@@ -35427,34 +38443,40 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
35427
38443
  const d12 = dom[i * 2 + 1] ?? 1;
35428
38444
  return Math.max(d02, Math.min(d12, v));
35429
38445
  });
35430
- const tokens = tokenizePostScriptCode(doc.decodeStream(resolved));
35431
- const stackOut = evaluateType4PostScriptTokens(tokens, clampedInputs);
35432
- return clampRange(stackOut);
38446
+ const source = bytesToString3(doc.decodeStream(resolved));
38447
+ let cached = postScriptFunctions.get(resolved);
38448
+ 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])) {
38449
+ cached = { source, domain: dom, range, evaluate: buildPostScriptJsFunction(source, dom, range) };
38450
+ postScriptFunctions.set(resolved, cached);
38451
+ }
38452
+ const output = [];
38453
+ cached.evaluate(clampedInputs, 0, output, 0);
38454
+ return output;
35433
38455
  }
35434
38456
  if (ft === 3) {
35435
38457
  const fnsArr = doc.resolveArray(dictGet(fnDict, "Functions"));
35436
38458
  const bounds = getNums("Bounds", []);
35437
38459
  const encode = getNums("Encode", []);
35438
38460
  if (fnsArr && fnsArr.items.length > 0) {
38461
+ const input = Math.max(dom[0] ?? 0, Math.min(dom[1] ?? 1, t));
35439
38462
  let segIdx = 0;
35440
- while (segIdx < bounds.length && t >= bounds[segIdx]) segIdx++;
38463
+ while (segIdx < bounds.length && input >= bounds[segIdx]) segIdx++;
35441
38464
  segIdx = Math.min(fnsArr.items.length - 1, segIdx);
35442
38465
  const b0 = segIdx === 0 ? dom[0] ?? 0 : bounds[segIdx - 1];
35443
38466
  const b1 = segIdx < bounds.length ? bounds[segIdx] : dom[1] ?? 1;
35444
38467
  const e0 = encode[segIdx * 2] ?? 0;
35445
38468
  const e1 = encode[segIdx * 2 + 1] ?? 1;
35446
- const localT = Math.abs(b1 - b0) > 1e-8 ? e0 + (t - b0) / (b1 - b0) * (e1 - e0) : e0;
35447
- return evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], Math.max(0, Math.min(1, localT)));
38469
+ const localT = b1 !== b0 ? e0 + (input - b0) / (b1 - b0) * (e1 - e0) : e0;
38470
+ return clampRange(evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], localT));
35448
38471
  }
35449
38472
  }
35450
- const c0 = getNums("C0", [0, 0, 0]);
35451
- const c1 = getNums("C1", [1, 1, 1]);
38473
+ const c0 = getNums("C0", [0]);
38474
+ const c1 = getNums("C1", [1]);
35452
38475
  const nNode = doc.resolve(dictGet(fnDict, "N"));
35453
- const expN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
38476
+ const expN = nNode?.kind === "number" ? nNode.value : 1;
35454
38477
  const d0 = dom[0] ?? 0;
35455
38478
  const d1 = dom[1] ?? 1;
35456
- const normT = Math.abs(d1 - d0) > 1e-8 ? (t - d0) / (d1 - d0) : t;
35457
- const w = Math.pow(Math.max(0, Math.min(1, normT)), expN);
38479
+ const w = Math.pow(Math.max(d0, Math.min(d1, t)), expN);
35458
38480
  const len = Math.max(c0.length, c1.length);
35459
38481
  const out = [];
35460
38482
  for (let i = 0; i < len; i++) {
@@ -35470,30 +38492,14 @@ function shadingComponentsToRgb(csName, comps) {
35470
38492
  return [v, v, v];
35471
38493
  }
35472
38494
  if (csName === "DeviceCMYK" || csName === "CMYK" || comps.length >= 4) {
35473
- const cc = comps[0] ?? 0, cm = comps[1] ?? 0, cy = comps[2] ?? 0, ck = comps[3] ?? 0;
35474
- return [(1 - cc) * (1 - ck), (1 - cm) * (1 - kClamp(ck)), (1 - cy) * (1 - kClamp(ck))];
38495
+ const rgb2 = cmykColorSpace2.getRgb([comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0, comps[3] ?? 0], 0);
38496
+ return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
35475
38497
  }
35476
38498
  return [comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0];
35477
38499
  }
35478
38500
  function kClamp(v) {
35479
38501
  return Math.max(0, Math.min(1, v));
35480
38502
  }
35481
- function xyzToSrgb(X, Y, Z, Xw = 0.95047, Yw = 1, Zw = 1.08883) {
35482
- const scaleX = Xw > 1e-6 ? 0.95047 / Xw : 1;
35483
- const scaleY = Yw > 1e-6 ? 1 / Yw : 1;
35484
- const scaleZ = Zw > 1e-6 ? 1.08883 / Zw : 1;
35485
- const x = X * scaleX;
35486
- const y = Y * scaleY;
35487
- const z = Z * scaleZ;
35488
- const rl = 3.2404542 * x - 1.5371385 * y - 0.4985314 * z;
35489
- const gl = -0.969266 * x + 1.8760108 * y + 0.041556 * z;
35490
- const bl = 0.0556434 * x - 0.2040259 * y + 1.0572252 * z;
35491
- const toGamma = (u) => {
35492
- const c = Math.max(0, Math.min(1, u));
35493
- return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
35494
- };
35495
- return [toGamma(rl), toGamma(gl), toGamma(bl)];
35496
- }
35497
38503
  function getColorSpaceComponentCount(doc, csNode, activeResources, depth = 0) {
35498
38504
  if (!csNode || depth > 4) return 3;
35499
38505
  const resolved = doc ? doc.resolve(csNode) : csNode;
@@ -35550,63 +38556,10 @@ function convertColorSpaceComponentsToRgb(doc, csNode, csNameFallback, comps, ac
35550
38556
  if (resolved.kind === "array" && resolved.items.length > 0 && doc) {
35551
38557
  const familyNode = doc.resolve(resolved.items[0]);
35552
38558
  const family = familyNode?.kind === "name" ? familyNode.decoded : "";
35553
- if (family === "CalGray") {
35554
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
35555
- const gNode = paramDict ? doc.resolve(dictGet(paramDict, "Gamma")) : void 0;
35556
- const gamma = gNode?.kind === "number" && gNode.value > 0 ? gNode.value : 1;
35557
- const a = Math.pow(kClamp(comps[0] ?? 0), gamma);
35558
- return [a, a, a];
35559
- }
35560
- if (family === "CalRGB") {
35561
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
35562
- const gammaArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Gamma")) : void 0;
35563
- const getArrNum = (arr, idx, fb) => {
35564
- const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
35565
- return r?.kind === "number" ? r.value : fb;
35566
- };
35567
- const gr = getArrNum(gammaArr, 0, 1);
35568
- const gg = getArrNum(gammaArr, 1, 1);
35569
- const gb = getArrNum(gammaArr, 2, 1);
35570
- const ag = Math.pow(kClamp(comps[0] ?? 0), gr > 0 ? gr : 1);
35571
- const bg = Math.pow(kClamp(comps[1] ?? 0), gg > 0 ? gg : 1);
35572
- const cg = Math.pow(kClamp(comps[2] ?? 0), gb > 0 ? gb : 1);
35573
- const matArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Matrix")) : void 0;
35574
- if (matArr && matArr.items.length >= 9) {
35575
- const m = (i) => getArrNum(matArr, i, 0);
35576
- const X = m(0) * ag + m(3) * bg + m(6) * cg;
35577
- const Y = m(1) * ag + m(4) * bg + m(7) * cg;
35578
- const Z = m(2) * ag + m(5) * bg + m(8) * cg;
35579
- const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
35580
- const Xw = getArrNum(wpArr, 0, 0.95047);
35581
- const Yw = getArrNum(wpArr, 1, 1);
35582
- const Zw = getArrNum(wpArr, 2, 1.08883);
35583
- return xyzToSrgb(X, Y, Z, Xw, Yw, Zw);
35584
- }
35585
- return [ag, bg, cg];
35586
- }
35587
- if (family === "Lab") {
35588
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
35589
- const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
35590
- const rangeArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Range")) : void 0;
35591
- const getNum = (arr, idx, fb) => {
35592
- const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
35593
- return r?.kind === "number" ? r.value : fb;
35594
- };
35595
- const Xw = getNum(wpArr, 0, 0.95047);
35596
- const Yw = getNum(wpArr, 1, 1);
35597
- const Zw = getNum(wpArr, 2, 1.08883);
35598
- const amin = getNum(rangeArr, 0, -100);
35599
- const amax = getNum(rangeArr, 1, 100);
35600
- const bmin = getNum(rangeArr, 2, -100);
35601
- const bmax = getNum(rangeArr, 3, 100);
35602
- const Lstar = Math.max(0, Math.min(100, comps[0] ?? 0));
35603
- const astar = Math.max(amin, Math.min(amax, comps[1] ?? 0));
35604
- const bstar = Math.max(bmin, Math.min(bmax, comps[2] ?? 0));
35605
- const M = (Lstar + 16) / 116;
35606
- const L = M + astar / 500;
35607
- const N = M - bstar / 200;
35608
- const gFn = (x) => x >= 6 / 29 ? x * x * x : 108 / 841 * (x - 4 / 29);
35609
- return xyzToSrgb(Xw * gFn(L), Yw * gFn(M), Zw * gFn(N), Xw, Yw, Zw);
38559
+ if (family === "CalGray" || family === "CalRGB" || family === "Lab") {
38560
+ const colorSpace = createCalibratedColorSpace(doc, family, resolved.items[1]);
38561
+ const rgb2 = colorSpace.getRgb(comps, 0);
38562
+ return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
35610
38563
  }
35611
38564
  if (family === "ICCBased" && resolved.items[1]) {
35612
38565
  const iccNode = doc.resolve(resolved.items[1]);
@@ -35687,143 +38640,28 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
35687
38640
  const r = doc.resolve(it);
35688
38641
  return r?.kind === "number" ? r.value : 0;
35689
38642
  });
35690
- const xmin = decodeNums[0], xmax = decodeNums[1], ymin = decodeNums[2], ymax = decodeNums[3];
35691
- const numColorParams = Math.max(1, Math.floor((decodeNums.length - 4) / 2));
35692
38643
  const fnNode = dictGet(shDict, "Function");
35693
38644
  const csNode = doc.resolve(dictGet(shDict, "ColorSpace"));
35694
38645
  const csName = csNode?.kind === "name" ? csNode.decoded : "DeviceRGB";
35695
- let bitPos = 0;
35696
- const totalBits = bytes.length * 8;
35697
- const readBits = (n) => {
35698
- let val = 0;
35699
- for (let i = 0; i < n; i++) {
35700
- if (bitPos >= totalBits) return val;
35701
- const byteIdx = bitPos >> 3;
35702
- const bitIdx = 7 - (bitPos & 7);
35703
- val = val * 2 + (bytes[byteIdx] >> bitIdx & 1);
35704
- bitPos++;
35705
- }
35706
- return val;
35707
- };
35708
- const coordMax = Math.pow(2, bpcCoord) - 1 || 1;
35709
- const compMax = Math.pow(2, bpcComp) - 1 || 1;
35710
- const readCoord = () => {
35711
- const rx = readBits(bpcCoord) / coordMax;
35712
- const ry = readBits(bpcCoord) / coordMax;
35713
- return [xmin + rx * (xmax - xmin), ymin + ry * (ymax - ymin)];
35714
- };
35715
- const readColorRgb = () => {
35716
- const params = [];
35717
- for (let c = 0; c < numColorParams; c++) {
35718
- const rc = readBits(bpcComp) / compMax;
35719
- const cMin = decodeNums[4 + c * 2] ?? 0;
35720
- const cMax = decodeNums[4 + c * 2 + 1] ?? 1;
35721
- params.push(cMin + rc * (cMax - cMin));
35722
- }
35723
- const comps = fnNode ? evalShadingFunctionToComponents(doc, fnNode, params) : params;
35724
- return convertColorSpaceComponentsToRgb(doc, csNode, csName, comps);
35725
- };
35726
- const triangles = [];
35727
- if (shType === 4) {
35728
- const minBitsPerVert = bpcFlag + 2 * bpcCoord + numColorParams * bpcComp;
35729
- let triVerts;
35730
- while (bitPos + minBitsPerVert <= totalBits) {
35731
- const flag = readBits(bpcFlag) & 3;
35732
- const [x, y] = readCoord();
35733
- const rgb2 = readColorRgb();
35734
- const vNew = { x, y, rgb: rgb2 };
35735
- if (flag === 0 || !triVerts) {
35736
- if (bitPos + 2 * minBitsPerVert > totalBits) break;
35737
- readBits(bpcFlag);
35738
- const [x1, y1] = readCoord();
35739
- const rgb1 = readColorRgb();
35740
- readBits(bpcFlag);
35741
- const [x2, y2] = readCoord();
35742
- const rgb22 = readColorRgb();
35743
- triVerts = [vNew, { x: x1, y: y1, rgb: rgb1 }, { x: x2, y: y2, rgb: rgb22 }];
35744
- triangles.push(triVerts);
35745
- } else if (flag === 1) {
35746
- triVerts = [triVerts[1], triVerts[2], vNew];
35747
- triangles.push(triVerts);
35748
- } else if (flag === 2) {
35749
- triVerts = [triVerts[0], triVerts[2], vNew];
35750
- triangles.push(triVerts);
35751
- }
35752
- }
35753
- } else if (shType === 5) {
35754
- const minBitsPerVert = 2 * bpcCoord + numColorParams * bpcComp;
35755
- const verts = [];
35756
- while (bitPos + minBitsPerVert <= totalBits) {
35757
- const [x, y] = readCoord();
35758
- const rgb2 = readColorRgb();
35759
- verts.push({ x, y, rgb: rgb2 });
35760
- }
35761
- const numRows = Math.floor(verts.length / vPerRow);
35762
- for (let r = 0; r + 1 < numRows; r++) {
35763
- for (let c = 0; c + 1 < vPerRow; c++) {
35764
- const v00 = verts[r * vPerRow + c];
35765
- const v01 = verts[r * vPerRow + c + 1];
35766
- const v11 = verts[(r + 1) * vPerRow + c + 1];
35767
- const v10 = verts[(r + 1) * vPerRow + c];
35768
- triangles.push([v00, v01, v11], [v00, v11, v10]);
35769
- }
35770
- }
35771
- } else if (shType === 6 || shType === 7) {
35772
- const numCtrl = shType === 6 ? 12 : 16;
35773
- const minBitsPatch = bpcFlag + (numCtrl - 4) * 2 * bpcCoord + 2 * numColorParams * bpcComp;
35774
- let prevPts;
35775
- let prevColors;
35776
- while (bitPos + minBitsPatch <= totalBits) {
35777
- const flag = readBits(bpcFlag) & 3;
35778
- let pts = [];
35779
- let cols = [];
35780
- if (flag === 0 || !prevPts || !prevColors) {
35781
- for (let i = 0; i < numCtrl; i++) pts.push(readCoord());
35782
- for (let i = 0; i < 4; i++) cols.push(readColorRgb());
35783
- } else {
35784
- const extraCtrl = numCtrl - 4;
35785
- const readExtra = [];
35786
- for (let i = 0; i < extraCtrl; i++) readExtra.push(readCoord());
35787
- const c2 = readColorRgb();
35788
- const c3 = readColorRgb();
35789
- pts = [prevPts[3], prevPts[4], prevPts[5], prevPts[6], ...readExtra];
35790
- cols = [prevColors[1], prevColors[2], c2, c3];
35791
- }
35792
- prevPts = pts;
35793
- prevColors = cols;
35794
- const p00 = pts[0];
35795
- const p03 = pts[3];
35796
- const p33 = pts[6];
35797
- const p30 = pts[9];
35798
- const c00 = cols[0], c03 = cols[1], c33 = cols[2], c30 = cols[3];
35799
- const steps = 4;
35800
- const grid = [];
35801
- for (let iu = 0; iu <= steps; iu++) {
35802
- const u = iu / steps;
35803
- const row = [];
35804
- for (let iv = 0; iv <= steps; iv++) {
35805
- const v = iv / steps;
35806
- const x = (1 - u) * (1 - v) * p00[0] + (1 - u) * v * p03[0] + u * v * p33[0] + u * (1 - v) * p30[0];
35807
- const y = (1 - u) * (1 - v) * p00[1] + (1 - u) * v * p03[1] + u * v * p33[1] + u * (1 - v) * p30[1];
35808
- const r = (1 - u) * (1 - v) * c00[0] + (1 - u) * v * c03[0] + u * v * c33[0] + u * (1 - v) * c30[0];
35809
- const g = (1 - u) * (1 - v) * c00[1] + (1 - u) * v * c03[1] + u * v * c33[1] + u * (1 - v) * c30[1];
35810
- const b = (1 - u) * (1 - v) * c00[2] + (1 - u) * v * c03[2] + u * v * c33[2] + u * (1 - v) * c30[2];
35811
- row.push({ x, y, rgb: [r, g, b] });
35812
- }
35813
- grid.push(row);
35814
- }
35815
- for (let iu = 0; iu < steps; iu++) {
35816
- for (let iv = 0; iv < steps; iv++) {
35817
- const g00 = grid[iu][iv];
35818
- const g01 = grid[iu][iv + 1];
35819
- const g11 = grid[iu + 1][iv + 1];
35820
- const g10 = grid[iu + 1][iv];
35821
- triangles.push([g00, g01, g11], [g00, g11, g10]);
35822
- }
35823
- }
35824
- }
35825
- }
35826
- if (triangles.length === 0) return void 0;
38646
+ const numComps = fnNode ? 1 : getColorSpaceComponentCount(doc, csNode);
38647
+ const mesh = new MeshShading(shType, new Stream(bytes), {
38648
+ bitsPerCoordinate: bpcCoord,
38649
+ bitsPerComponent: bpcComp,
38650
+ bitsPerFlag: bpcFlag,
38651
+ decode: decodeNums,
38652
+ numComps,
38653
+ colorFn: null,
38654
+ colorSpace: {
38655
+ numComps,
38656
+ getRgb(components) {
38657
+ const params = Array.from(components);
38658
+ const values = fnNode ? evalShadingFunctionToComponents(doc, fnNode, params) : params;
38659
+ return new Uint8Array(convertColorSpaceComponentsToRgb(doc, csNode, csName, values).map((value) => Math.round(Math.max(0, Math.min(1, value)) * 255)));
38660
+ }
38661
+ }
38662
+ }, vPerRow);
38663
+ const [, , positions, colors, vertexCount] = mesh.getIR();
38664
+ if (vertexCount === 0) return void 0;
35827
38665
  const [bx0, by0, bx1, by1] = targetBox;
35828
38666
  const boxW = Math.max(1, bx1 - bx0);
35829
38667
  const boxH = Math.max(1, by1 - by0);
@@ -35835,10 +38673,10 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
35835
38673
  const [px, py] = transformPoint(effectiveCtm, vx, vy);
35836
38674
  return [(px - bx0) / boxW * imgW, (by1 - py) / boxH * imgH];
35837
38675
  };
35838
- for (const [v0, v1, v2] of triangles) {
35839
- const [x0, y0] = toImgCoords(v0.x, v0.y);
35840
- const [x1, y1] = toImgCoords(v1.x, v1.y);
35841
- const [x2, y2] = toImgCoords(v2.x, v2.y);
38676
+ for (let vertex = 0; vertex < vertexCount; vertex += 3) {
38677
+ const [x0, y0] = toImgCoords(positions[vertex * 2], positions[vertex * 2 + 1]);
38678
+ const [x1, y1] = toImgCoords(positions[vertex * 2 + 2], positions[vertex * 2 + 3]);
38679
+ const [x2, y2] = toImgCoords(positions[vertex * 2 + 4], positions[vertex * 2 + 5]);
35842
38680
  const denom = (y1 - y2) * (x0 - x2) + (x2 - x1) * (y0 - y2);
35843
38681
  if (Math.abs(denom) < 1e-6) continue;
35844
38682
  const minX = Math.max(0, Math.floor(Math.min(x0, x1, x2)));
@@ -35853,13 +38691,12 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
35853
38691
  const w1 = ((y2 - y0) * (px - x2) + (x0 - x2) * (py - y2)) / denom;
35854
38692
  const w2 = 1 - w0 - w1;
35855
38693
  if (w0 >= -1e-4 && w1 >= -1e-4 && w2 >= -1e-4) {
35856
- const r = w0 * v0.rgb[0] + w1 * v1.rgb[0] + w2 * v2.rgb[0];
35857
- const g = w0 * v0.rgb[1] + w1 * v1.rgb[1] + w2 * v2.rgb[1];
35858
- const b = w0 * v0.rgb[2] + w1 * v1.rgb[2] + w2 * v2.rgb[2];
35859
38694
  const pIdx = (iy * imgW + ix) * 4;
35860
- rgba[pIdx] = Math.round(Math.max(0, Math.min(1, r)) * 255);
35861
- rgba[pIdx + 1] = Math.round(Math.max(0, Math.min(1, g)) * 255);
35862
- rgba[pIdx + 2] = Math.round(Math.max(0, Math.min(1, b)) * 255);
38695
+ for (let channel = 0; channel < 3; channel++) {
38696
+ rgba[pIdx + channel] = Math.round(
38697
+ w0 * colors[vertex * 4 + channel] + w1 * colors[vertex * 4 + 4 + channel] + w2 * colors[vertex * 4 + 8 + channel]
38698
+ );
38699
+ }
35863
38700
  rgba[pIdx + 3] = a8;
35864
38701
  }
35865
38702
  }
@@ -35946,6 +38783,8 @@ function renderShadingDictToImage(doc, shDict, shadingCtm, targetBox, fillAlpha,
35946
38783
  const [a, b, c, d, e, f] = effectiveCtm;
35947
38784
  const det = a * d - b * c;
35948
38785
  if (Math.abs(det) <= 1e-8) return void 0;
38786
+ const [sa, sb, sc, sd, se, sf] = shadingCtm;
38787
+ const shadingDet = sa * sd - sb * sc;
35949
38788
  const t0Dom = shDomain[0] ?? 0;
35950
38789
  const t1Dom = shDomain[1] ?? 1;
35951
38790
  for (let iy = 0; iy < imgH; iy++) {
@@ -35956,8 +38795,10 @@ function renderShadingDictToImage(doc, shDict, shadingCtm, targetBox, fillAlpha,
35956
38795
  const dxPdf = xPdf - e;
35957
38796
  const xs = (d * dxPdf - c * dyPdf) / det;
35958
38797
  const ys = (-b * dxPdf + a * dyPdf) / det;
35959
- if (shBBox && (xs < shBBox[0] || xs > shBBox[2] || ys < shBBox[1] || ys > shBBox[3])) {
35960
- continue;
38798
+ if (shBBox) {
38799
+ const bboxX = (sd * (xPdf - se) - sc * (yPdf - sf)) / shadingDet;
38800
+ const bboxY = (-sb * (xPdf - se) + sa * (yPdf - sf)) / shadingDet;
38801
+ if (bboxX < shBBox[0] || bboxX > shBBox[2] || bboxY < shBBox[1] || bboxY > shBBox[3]) continue;
35961
38802
  }
35962
38803
  let comps;
35963
38804
  if (shType === 1) {
@@ -36257,7 +39098,8 @@ function evaluateContentStreamToDisplayList(params) {
36257
39098
  const shDict = shNode?.kind === "dict" ? shNode : shNode?.kind === "stream" ? shNode.dict : void 0;
36258
39099
  const shStream = shNode?.kind === "stream" ? shNode : void 0;
36259
39100
  if (shDict) {
36260
- const targetBox = st.clipRect ?? [0, 0, params.width, params.height];
39101
+ const [originX, originY] = params.origin ?? [0, 0];
39102
+ const targetBox = st.clipRect ?? [originX, originY, originX + params.width, originY + params.height];
36261
39103
  const img = renderShadingDictToImage(
36262
39104
  params.cosDoc,
36263
39105
  shDict,
@@ -36296,12 +39138,10 @@ function evaluateContentStreamToDisplayList(params) {
36296
39138
  } else if (operator === "RG" || operator === "SC" || operator === "SCN") {
36297
39139
  st.strokeColor = resolveScColorOperands(operator === "RG" ? "DeviceRGB" : st.strokeColorSpaceName, ops, activeResources);
36298
39140
  } else if (operator === "k") {
36299
- const c = num(0), m = num(1), y = num(2), k = num(3);
36300
- st.fillColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
39141
+ st.fillColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
36301
39142
  st.fillPatternName = void 0;
36302
39143
  } else if (operator === "K") {
36303
- const c = num(0), m = num(1), y = num(2), k = num(3);
36304
- st.strokeColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
39144
+ st.strokeColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
36305
39145
  } else if (operator === "gs" && params.cosDoc && activeResources && ops[0]?.kind === "name") {
36306
39146
  const extDict = params.cosDoc.resolveDict(dictGet(activeResources, "ExtGState"));
36307
39147
  const gsDict = extDict ? params.cosDoc.resolveDict(dictGet(extDict, ops[0].decoded)) : void 0;
@@ -36510,7 +39350,7 @@ function evaluateContentStreamToDisplayList(params) {
36510
39350
  stateStack.pop();
36511
39351
  capturedOperations = parentOperations;
36512
39352
  }
36513
- if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
39353
+ if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, isolated, bboxClip: nextClipPaths?.[0], blendMode: st.blendMode, clipRect: st.clipRect } });
36514
39354
  };
36515
39355
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
36516
39356
  for (const node of nodes) {
@@ -37094,6 +39934,7 @@ function evaluateContentStreamToDisplayList(params) {
37094
39934
  pageIndex: params.pageIndex,
37095
39935
  width: params.width,
37096
39936
  height: params.height,
39937
+ ...params.origin ? { origin: params.origin } : {},
37097
39938
  rotation: params.rotation ?? 0,
37098
39939
  glyphs,
37099
39940
  paths,
@@ -38564,7 +41405,7 @@ var PdfPage = class {
38564
41405
  return [n0.value, n1.value, n2.value, n3.value];
38565
41406
  }
38566
41407
  }
38567
- return [0, 0, 612, 792];
41408
+ return key === "MediaBox" ? [0, 0, 612, 792] : this.resolveBox("MediaBox");
38568
41409
  }
38569
41410
  getMediaBox() {
38570
41411
  return this.resolveBox("MediaBox");
@@ -39237,16 +42078,19 @@ var PdfPage = class {
39237
42078
  });
39238
42079
  }
39239
42080
  }
39240
- return evaluateContentStreamToDisplayList({
42081
+ const mediaBox = this.getMediaBox(), cropBox = this.getCropBox();
42082
+ const originX = Math.min(mediaBox[0], mediaBox[2]), originY = Math.min(mediaBox[1], mediaBox[3]);
42083
+ return { ...evaluateContentStreamToDisplayList({
39241
42084
  pageIndex: this.index,
39242
42085
  width,
39243
42086
  height,
42087
+ origin: [originX, originY],
39244
42088
  rotation: this.getRotation(),
39245
42089
  nodes: baseNodes,
39246
42090
  cosDoc: this.cosDoc,
39247
42091
  resourcesDict: evalResourcesDict,
39248
42092
  annotations: extractPageAnnotations(this.cosDoc, this.pageDict)
39249
- });
42093
+ }), cropBox: [cropBox[0] - originX, cropBox[1] - originY, cropBox[2] - originX, cropBox[3] - originY] };
39250
42094
  }
39251
42095
  extractPage(options) {
39252
42096
  const dl = this.evaluateDisplayList();
@@ -39264,10 +42108,10 @@ var PdfPage = class {
39264
42108
  return extractTablesFromDisplayList(this.evaluateDisplayList());
39265
42109
  }
39266
42110
  renderToBitmap(options) {
39267
- return renderDisplayListToBitmap(this.evaluateDisplayList(), options);
42111
+ return renderDisplayListToBitmap(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
39268
42112
  }
39269
42113
  renderToPng(options) {
39270
- return renderDisplayListToPng(this.evaluateDisplayList(), options);
42114
+ return renderDisplayListToPng(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
39271
42115
  }
39272
42116
  };
39273
42117
  function createStandardFontHandle(standardName) {
@@ -40713,7 +43557,7 @@ function prepareStroke(path, scale) {
40713
43557
  }
40714
43558
  return { matrix, width, dashArray, dashPhase };
40715
43559
  }
40716
- function strokeContours(path, pageHeight, scale) {
43560
+ function strokeContours(path, pageHeight, scale, originX = 0, originY = 0) {
40717
43561
  const stroke = prepareStroke(path, scale);
40718
43562
  if (!stroke) return [];
40719
43563
  const inverse = inverseStrokeMatrix(stroke.matrix);
@@ -40725,8 +43569,8 @@ function strokeContours(path, pageHeight, scale) {
40725
43569
  (inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
40726
43570
  ];
40727
43571
  const toScreen = ([x, y]) => [
40728
- (a * x / strokeScale + c * y / strokeScale + e) * scale,
40729
- (pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
43572
+ (a * x / strokeScale + c * y / strokeScale + e - originX) * scale,
43573
+ (pageHeight + originY - b * x / strokeScale - d * y / strokeScale - f) * scale
40730
43574
  ];
40731
43575
  const contours = strokeOutlines(
40732
43576
  segmentsToScreenPaths(path.segments, pageHeight, scale, project),
@@ -40884,18 +43728,37 @@ function renderSoftMask(mask, displayList, scale) {
40884
43728
  }
40885
43729
  return bitmap;
40886
43730
  }
40887
- function hasBlendModes(operations) {
40888
- return operations.some((operation) => !!operation.value.blendMode && operation.value.blendMode !== "Normal" && operation.value.blendMode !== "Compatible" || operation.kind === "group" && hasBlendModes(operation.value.operations));
43731
+ function getDisplayListCropBox(list) {
43732
+ const full = [0, 0, list.width, list.height];
43733
+ const box = list.cropBox;
43734
+ if (!box || !box.every(Number.isFinite)) return full;
43735
+ const x0 = Math.max(0, Math.min(box[0], box[2]));
43736
+ const y0 = Math.max(0, Math.min(box[1], box[3]));
43737
+ const x1 = Math.min(list.width, Math.max(box[0], box[2]));
43738
+ const y1 = Math.min(list.height, Math.max(box[1], box[3]));
43739
+ return x1 > x0 && y1 > y0 ? [x0, y0, x1, y1] : full;
43740
+ }
43741
+ function hasCompositingEffects(operations, includeSoftMasks = false) {
43742
+ 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));
43743
+ }
43744
+ function needsGroupBackdrop(group) {
43745
+ return group.isolated === false && !!group.softMask && hasCompositingEffects(group.operations, true);
43746
+ }
43747
+ function containsBackdropGroup(operations) {
43748
+ return operations.some((operation) => operation.kind === "group" && (needsGroupBackdrop(operation.value) || containsBackdropGroup(operation.value.operations)));
40889
43749
  }
40890
43750
  function renderDisplayListToBitmap(displayList, options = {}) {
40891
43751
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
40892
43752
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
40893
43753
  const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
40894
43754
  const scale = scaleX;
43755
+ const [originX, originY] = displayList.origin ?? [0, 0];
43756
+ const pageTop = originY + displayList.height;
43757
+ const toScreen = (x, y) => [(x - originX) * scale, (pageTop - y) * scale];
40895
43758
  const width = Math.max(1, Math.round(displayList.width * scale));
40896
43759
  const height = Math.max(1, Math.round(displayList.height * scale));
40897
43760
  const rgba = new Uint8Array(width * height * 4);
40898
- const deferBackground = !options.transparent && hasBlendModes(paintOperations(displayList));
43761
+ const deferBackground = !options.transparent && hasCompositingEffects(paintOperations(displayList));
40899
43762
  const transparent = options.transparent || deferBackground;
40900
43763
  const bg = options.background ?? { r: 1, g: 1, b: 1 };
40901
43764
  const bgR = transparent ? 0 : Math.round(bg.r * 255);
@@ -40920,14 +43783,27 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40920
43783
  let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
40921
43784
  if (operation.kind === "group") {
40922
43785
  const group = operation.value;
40923
- const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations: group.operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, transparent: true });
43786
+ let operations = group.operations;
43787
+ if (needsGroupBackdrop(group)) {
43788
+ operations = [{ kind: "image", value: {
43789
+ name: "GroupBackdrop",
43790
+ width,
43791
+ height,
43792
+ decodedRgba: rgba.slice(),
43793
+ matrix: [width / scale, 0, 0, height / scale, originX, pageTop - height / scale],
43794
+ colorSpace: "DeviceRGB",
43795
+ bitsPerComponent: 8,
43796
+ ...group.bboxClip ? { clipPaths: [group.bboxClip] } : {}
43797
+ } }, ...operations];
43798
+ }
43799
+ const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, useCropBox: false, transparent: true });
40924
43800
  for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
40925
43801
  operation = { kind: "image", value: {
40926
43802
  name: "TransparencyGroup",
40927
43803
  width: bitmap.width,
40928
43804
  height: bitmap.height,
40929
43805
  decodedRgba: bitmap.data,
40930
- matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, 0, displayList.height - bitmap.height / scale],
43806
+ matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, originX, pageTop - bitmap.height / scale],
40931
43807
  colorSpace: "DeviceRGB",
40932
43808
  bitsPerComponent: 8,
40933
43809
  blendMode: group.blendMode,
@@ -40941,7 +43817,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40941
43817
  for (const clip of clips) {
40942
43818
  const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
40943
43819
  const layer = new Uint8Array(width * height * 4);
40944
- fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
43820
+ fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale, toScreen), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
40945
43821
  for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
40946
43822
  }
40947
43823
  cachedClips = clips;
@@ -40988,15 +43864,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40988
43864
  if (operation.kind === "path") {
40989
43865
  const path = operation.value;
40990
43866
  if (path.fillColor) {
40991
- const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale), true);
40992
- const clipScreen = path.clipRect ? [path.clipRect[0] * scale, (displayList.height - path.clipRect[3]) * scale, path.clipRect[2] * scale, (displayList.height - path.clipRect[1]) * scale] : void 0;
43867
+ const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale, toScreen), true);
43868
+ const clipScreen = path.clipRect ? [(path.clipRect[0] - originX) * scale, (pageTop - path.clipRect[3]) * scale, (path.clipRect[2] - originX) * scale, (pageTop - path.clipRect[1]) * scale] : void 0;
40993
43869
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
40994
43870
  }
40995
43871
  if (path.strokeColor) {
40996
43872
  const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
40997
43873
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
40998
- const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
40999
- const clipScreen = path.clipRect ? [path.clipRect[0] * scale, (displayList.height - path.clipRect[3]) * scale, path.clipRect[2] * scale, (displayList.height - path.clipRect[1]) * scale] : void 0;
43874
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale, originX, originY).map((points) => ({ points, closed: true })));
43875
+ const clipScreen = path.clipRect ? [(path.clipRect[0] - originX) * scale, (pageTop - path.clipRect[3]) * scale, (path.clipRect[2] - originX) * scale, (pageTop - path.clipRect[1]) * scale] : void 0;
41000
43876
  fillEdgesScanline4x4(
41001
43877
  rgba,
41002
43878
  width,
@@ -41019,12 +43895,12 @@ function renderDisplayListToBitmap(displayList, options = {}) {
41019
43895
  if (Math.abs(det) <= 1e-8) continue;
41020
43896
  const cornersPdfX = [e, a + e, a + c + e, c + e];
41021
43897
  const cornersPdfY = [f, b + f, b + d + f, d + f];
41022
- const cornersPx = cornersPdfX.map((cx) => cx * scale);
41023
- const cornersPy = cornersPdfY.map((cy) => (displayList.height - cy) * scale);
41024
- const clipMinPx = img.clipRect ? Math.floor(img.clipRect[0] * scale) : 0;
41025
- const clipMaxPx = img.clipRect ? Math.ceil(img.clipRect[2] * scale) - 1 : width - 1;
41026
- const clipMinPy = img.clipRect ? Math.floor((displayList.height - img.clipRect[3]) * scale) : 0;
41027
- const clipMaxPy = img.clipRect ? Math.ceil((displayList.height - img.clipRect[1]) * scale) - 1 : height - 1;
43898
+ const cornersPx = cornersPdfX.map((cx) => (cx - originX) * scale);
43899
+ const cornersPy = cornersPdfY.map((cy) => (pageTop - cy) * scale);
43900
+ const clipMinPx = img.clipRect ? Math.floor((img.clipRect[0] - originX) * scale) : 0;
43901
+ const clipMaxPx = img.clipRect ? Math.ceil((img.clipRect[2] - originX) * scale) - 1 : width - 1;
43902
+ const clipMinPy = img.clipRect ? Math.floor((pageTop - img.clipRect[3]) * scale) : 0;
43903
+ const clipMaxPy = img.clipRect ? Math.ceil((pageTop - img.clipRect[1]) * scale) - 1 : height - 1;
41028
43904
  const minPx = Math.max(0, clipMinPx, Math.floor(Math.min(...cornersPx)));
41029
43905
  const maxPx = Math.min(width - 1, clipMaxPx, Math.ceil(Math.max(...cornersPx)) - 1);
41030
43906
  const minPy = Math.max(0, clipMinPy, Math.floor(Math.min(...cornersPy)));
@@ -41041,11 +43917,11 @@ function renderDisplayListToBitmap(displayList, options = {}) {
41041
43917
  const smooth = Math.fround((s1 + s2 + Math.hypot(s1 - s2, 2 * cross)) / 2) <= 1;
41042
43918
  const sample = new Float64Array(4);
41043
43919
  for (let py = minPy; py <= maxPy; py++) {
41044
- const yPdf = displayList.height - (py + 0.5) / scale;
43920
+ const yPdf = pageTop - (py + 0.5) / scale;
41045
43921
  if (img.clipRect && (yPdf < img.clipRect[1] || yPdf > img.clipRect[3])) continue;
41046
43922
  const dyPdf = yPdf - f;
41047
43923
  for (let px = minPx; px <= maxPx; px++) {
41048
- const xPdf = (px + 0.5) / scale;
43924
+ const xPdf = originX + (px + 0.5) / scale;
41049
43925
  if (img.clipRect && (xPdf < img.clipRect[0] || xPdf > img.clipRect[2])) continue;
41050
43926
  const dxPdf = xPdf - e;
41051
43927
  const u = (d * dxPdf - c * dyPdf) / det;
@@ -41106,6 +43982,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
41106
43982
  }
41107
43983
  result = { width: targetW, height: targetH, data: resampled };
41108
43984
  }
43985
+ if (options.useCropBox) {
43986
+ const box = getDisplayListCropBox(displayList);
43987
+ result = cropRgbaBitmap(result, {
43988
+ x: box[0] * scaleX,
43989
+ y: (displayList.height - box[3]) * scaleY,
43990
+ width: (box[2] - box[0]) * scaleX,
43991
+ height: (box[3] - box[1]) * scaleY
43992
+ });
43993
+ }
41109
43994
  result = rotateRgbaBitmapQuarterTurns(result, displayList.rotation ?? 0);
41110
43995
  if (options.cropRect) {
41111
43996
  result = cropRgbaBitmap(result, options.cropRect);
@@ -41175,18 +44060,44 @@ function svgPathData(segments, height, matrix) {
41175
44060
  }
41176
44061
  function renderDisplayListToSvg(displayList, options = {}) {
41177
44062
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1);
44063
+ if (containsBackdropGroup(paintOperations(displayList))) {
44064
+ const bitmap = renderDisplayListToBitmap(displayList, { ...options, scale: baseScale });
44065
+ const embedded = svgImage({
44066
+ name: "PageComposite",
44067
+ width: bitmap.width,
44068
+ height: bitmap.height,
44069
+ decodedRgba: bitmap.data,
44070
+ matrix: [bitmap.width, 0, 0, bitmap.height, 0, 0],
44071
+ colorSpace: "DeviceRGB",
44072
+ bitsPerComponent: 8
44073
+ }, bitmap.height);
44074
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${bitmap.width}" height="${bitmap.height}" viewBox="0 0 ${bitmap.width} ${bitmap.height}">${embedded}</svg>
44075
+ `;
44076
+ }
41178
44077
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
41179
44078
  const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
41180
- const viewport = new PageViewport({ viewBox: [0, 0, displayList.width, displayList.height], userUnit: 1, scale: 1, rotation: displayList.rotation ?? 0 });
44079
+ const [originX, originY] = displayList.origin ?? [0, 0];
44080
+ const viewport = new PageViewport({ viewBox: [originX, originY, originX + displayList.width, originY + displayList.height], userUnit: 1, scale: 1, rotation: displayList.rotation ?? 0 });
41181
44081
  const quarterTurn = displayList.rotation === 90 || displayList.rotation === 270;
41182
44082
  const outputScaleX = quarterTurn ? scaleY : scaleX;
41183
44083
  const outputScaleY = quarterTurn ? scaleX : scaleY;
41184
- const fullW = Math.max(1, Math.round(viewport.width * outputScaleX));
41185
- const fullH = Math.max(1, Math.round(viewport.height * outputScaleY));
41186
- const vbX = options.cropRect ? options.cropRect.x / outputScaleX : 0;
41187
- const vbY = options.cropRect ? options.cropRect.y / outputScaleY : 0;
41188
- const vbW = options.cropRect && options.cropRect.width > 0 ? options.cropRect.width / outputScaleX : Math.max(1, viewport.width - vbX);
41189
- const vbH = options.cropRect && options.cropRect.height > 0 ? options.cropRect.height / outputScaleY : Math.max(1, viewport.height - vbY);
44084
+ let bounds = [0, 0, viewport.width, viewport.height];
44085
+ if (options.useCropBox) {
44086
+ const box = getDisplayListCropBox(displayList);
44087
+ const [x0, y0, x1, y1] = [box[0] + originX, box[1] + originY, box[2] + originX, box[3] + originY];
44088
+ const [a, b, c, d, e, f] = viewport.transform;
44089
+ bounds = [a * x0 + c * y0 + e, b * x0 + d * y0 + f, a * x1 + c * y1 + e, b * x1 + d * y1 + f];
44090
+ }
44091
+ const viewX = Math.min(bounds[0], bounds[2]), viewY = Math.min(bounds[1], bounds[3]);
44092
+ const viewWidth = Math.abs(bounds[2] - bounds[0]), viewHeight = Math.abs(bounds[3] - bounds[1]);
44093
+ const fullW = Math.max(1, Math.round(viewWidth * outputScaleX));
44094
+ const fullH = Math.max(1, Math.round(viewHeight * outputScaleY));
44095
+ const cropX = options.cropRect ? options.cropRect.x / outputScaleX : 0;
44096
+ const vbX = viewX + cropX;
44097
+ const cropY = options.cropRect ? options.cropRect.y / outputScaleY : 0;
44098
+ const vbY = viewY + cropY;
44099
+ const vbW = options.cropRect && options.cropRect.width > 0 ? options.cropRect.width / outputScaleX : Math.max(1, viewWidth - cropX);
44100
+ const vbH = options.cropRect && options.cropRect.height > 0 ? options.cropRect.height / outputScaleY : Math.max(1, viewHeight - cropY);
41190
44101
  const outW = options.cropRect && options.cropRect.width > 0 ? Math.round(options.cropRect.width) : Math.max(1, fullW - Math.round(options.cropRect?.x ?? 0));
41191
44102
  const outH = options.cropRect && options.cropRect.height > 0 ? Math.round(options.cropRect.height) : Math.max(1, fullH - Math.round(options.cropRect?.y ?? 0));
41192
44103
  const parts = [
@@ -41196,7 +44107,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
41196
44107
  parts.push(` <rect x="${vbX}" y="${vbY}" width="${vbW}" height="${vbH}" fill="#ffffff"/>`);
41197
44108
  }
41198
44109
  parts.push('<g style="isolation:isolate">');
41199
- if (displayList.rotation) {
44110
+ if (displayList.rotation || originX || originY) {
41200
44111
  const [a, b, c, d, e, f] = viewport.transform;
41201
44112
  parts.push(`<g transform="matrix(${a} ${b} ${-c} ${-d} ${e + c * displayList.height} ${f + d * displayList.height})">`);
41202
44113
  }
@@ -41222,11 +44133,11 @@ function renderDisplayListToSvg(displayList, options = {}) {
41222
44133
  width: bitmap.width,
41223
44134
  height: bitmap.height,
41224
44135
  decodedRgba: bitmap.data,
41225
- matrix: [displayList.width, 0, 0, displayList.height, 0, 0],
44136
+ matrix: [displayList.width, 0, 0, displayList.height, originX, originY],
41226
44137
  colorSpace: "DeviceGray",
41227
44138
  bitsPerComponent: 8
41228
44139
  };
41229
- parts.push(`<defs><mask id="${id}" maskUnits="userSpaceOnUse" x="0" y="0" width="${displayList.width}" height="${displayList.height}" style="mask-type:alpha">${svgImage(image, displayList.height)}</mask></defs>`);
44140
+ parts.push(`<defs><mask id="${id}" maskUnits="userSpaceOnUse" x="${originX}" y="${-originY}" width="${displayList.width}" height="${displayList.height}" style="mask-type:alpha">${svgImage(image, displayList.height)}</mask></defs>`);
41230
44141
  }
41231
44142
  parts.push(`<g mask="url(#${id})">`);
41232
44143
  }
@@ -41238,7 +44149,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
41238
44149
  }
41239
44150
  for (const image of imageClips) {
41240
44151
  const id = `image-clip-${clipId++}`;
41241
- parts.push(`<defs><mask id="${id}" maskUnits="userSpaceOnUse" x="0" y="0" width="${displayList.width}" height="${displayList.height}" style="mask-type:alpha">${svgImage(image, displayList.height)}</mask></defs><g mask="url(#${id})">`);
44152
+ parts.push(`<defs><mask id="${id}" maskUnits="userSpaceOnUse" x="${originX}" y="${-originY}" width="${displayList.width}" height="${displayList.height}" style="mask-type:alpha">${svgImage(image, displayList.height)}</mask></defs><g mask="url(#${id})">`);
41242
44153
  }
41243
44154
  if (operation.kind === "group") {
41244
44155
  parts.push(`<g opacity="${operation.value.alpha}" style="isolation:isolate">`);
@@ -41282,7 +44193,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
41282
44193
  }
41283
44194
  };
41284
44195
  appendOperations(paintOperations(displayList));
41285
- if (displayList.rotation) parts.push("</g>");
44196
+ if (displayList.rotation || originX || originY) parts.push("</g>");
41286
44197
  parts.push("</g>");
41287
44198
  parts.push("</svg>\n");
41288
44199
  return parts.join("\n");
@@ -41305,23 +44216,6 @@ function collectLeavesForRaster(cosDoc, node, out = [], visited = /* @__PURE__ *
41305
44216
  }
41306
44217
  return out;
41307
44218
  }
41308
- function extractBoxArray(cosDoc, dict, key) {
41309
- let cur = dict;
41310
- const visited = /* @__PURE__ */ new Set();
41311
- while (cur && !visited.has(cur)) {
41312
- visited.add(cur);
41313
- const arr = cosDoc.resolveArray(dictGet(cur, key));
41314
- if (arr && arr.items.length >= 4) {
41315
- const nums = arr.items.slice(0, 4).map((item) => {
41316
- const r = cosDoc.resolve(item);
41317
- return r?.kind === "number" ? r.value : 0;
41318
- });
41319
- return [nums[0], nums[1], nums[2], nums[3]];
41320
- }
41321
- cur = cosDoc.resolveDict(dictGet(cur, "Parent"));
41322
- }
41323
- return void 0;
41324
- }
41325
44219
  function renderPdfPageToBitmap(pdfBytes, pageIndex = 0, options) {
41326
44220
  const cos = pdfBytes instanceof Uint8Array ? parseCosDocument(pdfBytes) : pdfBytes;
41327
44221
  const catalog = cos.resolveDict(cos.rootRef);
@@ -41330,35 +44224,7 @@ function renderPdfPageToBitmap(pdfBytes, pageIndex = 0, options) {
41330
44224
  if (!leaf) throw new Error(`Page index ${pageIndex} out of bounds`);
41331
44225
  const resolvedIndex = leaves.indexOf(leaf);
41332
44226
  const page = new PdfPage(cos, leaf.ref, leaf.dict, resolvedIndex);
41333
- const { cropRect, ...restOptions } = options ?? {};
41334
- let bitmap = renderDisplayListToBitmap(
41335
- // CropBox is in unrotated page coordinates. Apply page rotation after it.
41336
- { ...page.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), rotation: 0 },
41337
- restOptions
41338
- );
41339
- if (options?.useCropBox) {
41340
- const cropBox = extractBoxArray(cos, leaf.dict, "CropBox");
41341
- if (cropBox) {
41342
- const mediaBox = extractBoxArray(cos, leaf.dict, "MediaBox") ?? [0, 0, page.getSize().width, page.getSize().height];
41343
- const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
41344
- const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
41345
- const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
41346
- const mediaH = mediaBox[3] - mediaBox[1];
41347
- const bx = Math.round((cropBox[0] - mediaBox[0]) * scaleX);
41348
- const by = Math.round((mediaH - (cropBox[3] - mediaBox[1])) * scaleY);
41349
- const bw = Math.max(1, Math.round(Math.abs(cropBox[2] - cropBox[0]) * scaleX));
41350
- const bh = Math.max(1, Math.round(Math.abs(cropBox[3] - cropBox[1]) * scaleY));
41351
- bitmap = cropRgbaBitmap(bitmap, { x: bx, y: by, width: bw, height: bh });
41352
- }
41353
- }
41354
- const rotation = page.getRotation();
41355
- if (rotation === 90 || rotation === 180 || rotation === 270) {
41356
- bitmap = rotateRgbaBitmapQuarterTurns(bitmap, rotation);
41357
- }
41358
- if (cropRect) {
41359
- bitmap = cropRgbaBitmap(bitmap, cropRect);
41360
- }
41361
- return bitmap;
44227
+ return page.renderToBitmap(options);
41362
44228
  }
41363
44229
  function discardUnreachableObjects(doc) {
41364
44230
  const reachable = /* @__PURE__ */ new Set();