@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,
@@ -22512,6 +22517,3308 @@ var getFontBasicMetrics = getLookupTableFactory(function(t) {
22512
22517
  xHeight: Math.NaN
22513
22518
  };
22514
22519
  });
22520
+ function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
22521
+ const COMPONENTS = 3;
22522
+ alpha01 = alpha01 !== 1 ? 0 : alpha01;
22523
+ const xRatio = w1 / w2;
22524
+ const yRatio = h1 / h2;
22525
+ let newIndex = 0, oldIndex;
22526
+ const xScaled = new Uint16Array(w2);
22527
+ const w1Scanline = w1 * COMPONENTS;
22528
+ for (let i = 0; i < w2; i++) {
22529
+ xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
22530
+ }
22531
+ for (let i = 0; i < h2; i++) {
22532
+ const py = Math.floor(i * yRatio) * w1Scanline;
22533
+ for (let j = 0; j < w2; j++) {
22534
+ oldIndex = py + xScaled[j];
22535
+ dest[newIndex++] = src[oldIndex++];
22536
+ dest[newIndex++] = src[oldIndex++];
22537
+ dest[newIndex++] = src[oldIndex++];
22538
+ newIndex += alpha01;
22539
+ }
22540
+ }
22541
+ }
22542
+ function isDefaultDecodeHelper(decode, expectedLen) {
22543
+ if (!Array.isArray(decode)) {
22544
+ return true;
22545
+ }
22546
+ const decodeLen = decode.length;
22547
+ if (decodeLen < expectedLen) {
22548
+ warn2("Decode map length is too short.");
22549
+ return true;
22550
+ }
22551
+ if (decodeLen > expectedLen) {
22552
+ info("Truncating too long decode map.");
22553
+ decode.length = expectedLen;
22554
+ }
22555
+ return false;
22556
+ }
22557
+ var ColorSpace = class _ColorSpace {
22558
+ static #rgbBuf = new Uint8ClampedArray(3);
22559
+ constructor(name, numComps) {
22560
+ if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _ColorSpace) {
22561
+ unreachable2("Cannot initialize ColorSpace.");
22562
+ }
22563
+ this.name = name;
22564
+ this.numComps = numComps;
22565
+ }
22566
+ /**
22567
+ * Converts the color value to the RGB color. The color components are
22568
+ * located in the src array starting from the srcOffset. Returns the array
22569
+ * of the rgb components, each value ranging from [0,255].
22570
+ */
22571
+ getRgb(src, srcOffset, output = new Uint8ClampedArray(3)) {
22572
+ this.getRgbItem(src, srcOffset, output, 0);
22573
+ return output;
22574
+ }
22575
+ getRgbHex(src, srcOffset) {
22576
+ const buffer = this.getRgb(src, srcOffset, _ColorSpace.#rgbBuf);
22577
+ return Util.makeHexColor(buffer[0], buffer[1], buffer[2]);
22578
+ }
22579
+ /**
22580
+ * Converts the color value to the RGB color, similar to the getRgb method.
22581
+ * The result placed into the dest array starting from the destOffset.
22582
+ */
22583
+ getRgbItem(src, srcOffset, dest, destOffset) {
22584
+ unreachable2("Should not call ColorSpace.getRgbItem");
22585
+ }
22586
+ /**
22587
+ * Converts the specified number of the color values to the RGB colors.
22588
+ * The colors are located in the src array starting from the srcOffset.
22589
+ * The result is placed into the dest array starting from the destOffset.
22590
+ * The src array items shall be in [0,2^bits) range, the dest array items
22591
+ * will be in [0,255] range. alpha01 indicates how many alpha components
22592
+ * there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
22593
+ * array).
22594
+ */
22595
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
22596
+ unreachable2("Should not call ColorSpace.getRgbBuffer");
22597
+ }
22598
+ /**
22599
+ * Converts `count` unscaled colors to RGB, starting at `destOffset`.
22600
+ * Components use the native color-space ranges expected by `getRgbItem`,
22601
+ * and each output has a `3 + alpha01` byte stride.
22602
+ * Subclasses may override this to batch expensive conversions.
22603
+ */
22604
+ getRgbItems(src, count, dest, destOffset, alpha01) {
22605
+ const { numComps } = this;
22606
+ for (let i = 0, srcOffset = 0; i < count; i++, srcOffset += numComps) {
22607
+ this.getRgbItem(src, srcOffset, dest, destOffset);
22608
+ destOffset += 3 + alpha01;
22609
+ }
22610
+ }
22611
+ /**
22612
+ * Returns true if source data will be equal the result/output data.
22613
+ */
22614
+ isPassthrough(bits) {
22615
+ return false;
22616
+ }
22617
+ /**
22618
+ * Refer to the static `ColorSpace.isDefaultDecode` method below.
22619
+ */
22620
+ isDefaultDecode(decode, bpc) {
22621
+ return _ColorSpace.isDefaultDecode(decode, this.numComps);
22622
+ }
22623
+ /**
22624
+ * Fills in the RGB colors in the destination buffer. alpha01 indicates
22625
+ * how many alpha components there are in the dest array; it will be either
22626
+ * 0 (RGB array) or 1 (RGBA array).
22627
+ */
22628
+ fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {
22629
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22630
+ assert2(
22631
+ dest instanceof Uint8ClampedArray,
22632
+ 'ColorSpace.fillRgb: Unsupported "dest" type.'
22633
+ );
22634
+ }
22635
+ const count = originalWidth * originalHeight;
22636
+ let rgbBuf = null;
22637
+ const numComponentColors = 1 << bpc;
22638
+ const needsResizing = originalHeight !== height || originalWidth !== width;
22639
+ if (this.isPassthrough(bpc)) {
22640
+ rgbBuf = comps;
22641
+ } else if (this.numComps === 1 && count > numComponentColors && this.name !== "DeviceGray" && this.name !== "DeviceRGB") {
22642
+ const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);
22643
+ for (let i = 0; i < numComponentColors; i++) {
22644
+ allColors[i] = i;
22645
+ }
22646
+ const colorMap = new Uint8ClampedArray(numComponentColors * 3);
22647
+ this.getRgbBuffer(
22648
+ allColors,
22649
+ 0,
22650
+ numComponentColors,
22651
+ colorMap,
22652
+ 0,
22653
+ bpc,
22654
+ /* alpha01 = */
22655
+ 0
22656
+ );
22657
+ if (!needsResizing) {
22658
+ let destPos = 0;
22659
+ for (let i = 0; i < count; ++i) {
22660
+ const key = comps[i] * 3;
22661
+ dest[destPos++] = colorMap[key];
22662
+ dest[destPos++] = colorMap[key + 1];
22663
+ dest[destPos++] = colorMap[key + 2];
22664
+ destPos += alpha01;
22665
+ }
22666
+ } else {
22667
+ rgbBuf = new Uint8Array(count * 3);
22668
+ let rgbPos = 0;
22669
+ for (let i = 0; i < count; ++i) {
22670
+ const key = comps[i] * 3;
22671
+ rgbBuf[rgbPos++] = colorMap[key];
22672
+ rgbBuf[rgbPos++] = colorMap[key + 1];
22673
+ rgbBuf[rgbPos++] = colorMap[key + 2];
22674
+ }
22675
+ }
22676
+ } else if (!needsResizing) {
22677
+ this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);
22678
+ } else {
22679
+ rgbBuf = new Uint8ClampedArray(count * 3);
22680
+ this.getRgbBuffer(
22681
+ comps,
22682
+ 0,
22683
+ count,
22684
+ rgbBuf,
22685
+ 0,
22686
+ bpc,
22687
+ /* alpha01 = */
22688
+ 0
22689
+ );
22690
+ }
22691
+ if (rgbBuf) {
22692
+ if (needsResizing) {
22693
+ resizeRgbImage(
22694
+ rgbBuf,
22695
+ dest,
22696
+ originalWidth,
22697
+ originalHeight,
22698
+ width,
22699
+ height,
22700
+ alpha01
22701
+ );
22702
+ } else {
22703
+ let destPos = 0, rgbPos = 0;
22704
+ for (let i = 0, ii = width * actualHeight; i < ii; i++) {
22705
+ dest[destPos++] = rgbBuf[rgbPos++];
22706
+ dest[destPos++] = rgbBuf[rgbPos++];
22707
+ dest[destPos++] = rgbBuf[rgbPos++];
22708
+ destPos += alpha01;
22709
+ }
22710
+ }
22711
+ }
22712
+ }
22713
+ /**
22714
+ * True if the colorspace has components in the default range of [0, 1].
22715
+ * This should be true for all colorspaces except for lab color spaces
22716
+ * which are [0,100], [-128, 127], [-128, 127].
22717
+ */
22718
+ get usesZeroToOneRange() {
22719
+ return shadow2(this, "usesZeroToOneRange", true);
22720
+ }
22721
+ /**
22722
+ * Checks if a decode map matches the default decode map for a color space.
22723
+ * This handles the general decode maps where there are two values per
22724
+ * component, e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
22725
+ * This does not handle Lab, Indexed, or Pattern decode maps since they are
22726
+ * slightly different.
22727
+ * @param {Array} decode - Decode map (usually from an image).
22728
+ * @param {number} numComps - Number of components the color space has.
22729
+ */
22730
+ static isDefaultDecode(decode, numComps) {
22731
+ if (isDefaultDecodeHelper(decode, numComps * 2)) {
22732
+ return true;
22733
+ }
22734
+ for (let i = 0, ii = decode.length; i < ii; i += 2) {
22735
+ if (decode[i] !== 0 || decode[i + 1] !== 1) {
22736
+ return false;
22737
+ }
22738
+ }
22739
+ return true;
22740
+ }
22741
+ };
22742
+ var DeviceCmykCS = class extends ColorSpace {
22743
+ constructor() {
22744
+ super("DeviceCMYK", 4);
22745
+ }
22746
+ // The coefficients below was found using numerical analysis: the method of
22747
+ // steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
22748
+ // where color_value is the tabular value from the table of sampled RGB colors
22749
+ // from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
22750
+ // CMYK color conversion using the estimation below:
22751
+ // f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
22752
+ #toRgb(src, srcOffset, srcScale, dest, destOffset) {
22753
+ const c = src[srcOffset] * srcScale;
22754
+ const m = src[srcOffset + 1] * srcScale;
22755
+ const y = src[srcOffset + 2] * srcScale;
22756
+ const k = src[srcOffset + 3] * srcScale;
22757
+ 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);
22758
+ 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);
22759
+ 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);
22760
+ }
22761
+ getRgbItem(src, srcOffset, dest, destOffset) {
22762
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22763
+ assert2(
22764
+ dest instanceof Uint8ClampedArray,
22765
+ 'DeviceCmykCS.getRgbItem: Unsupported "dest" type.'
22766
+ );
22767
+ }
22768
+ this.#toRgb(src, srcOffset, 1, dest, destOffset);
22769
+ }
22770
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
22771
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22772
+ assert2(
22773
+ dest instanceof Uint8ClampedArray,
22774
+ 'DeviceCmykCS.getRgbBuffer: Unsupported "dest" type.'
22775
+ );
22776
+ }
22777
+ const scale = 1 / ((1 << bits) - 1);
22778
+ for (let i = 0; i < count; i++) {
22779
+ this.#toRgb(src, srcOffset, scale, dest, destOffset);
22780
+ srcOffset += 4;
22781
+ destOffset += 3 + alpha01;
22782
+ }
22783
+ }
22784
+ };
22785
+ var CalGrayCS = class extends ColorSpace {
22786
+ constructor(whitePoint, blackPoint, gamma) {
22787
+ super("CalGray", 1);
22788
+ if (!whitePoint) {
22789
+ throw new FormatError(
22790
+ "WhitePoint missing - required for color space CalGray"
22791
+ );
22792
+ }
22793
+ [this.XW, this.YW, this.ZW] = whitePoint;
22794
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
22795
+ this.G = gamma || 1;
22796
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
22797
+ throw new FormatError(
22798
+ `Invalid WhitePoint components for ${this.name}, no fallback available`
22799
+ );
22800
+ }
22801
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
22802
+ info(`Invalid BlackPoint for ${this.name}, falling back to default.`);
22803
+ this.XB = this.YB = this.ZB = 0;
22804
+ }
22805
+ if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
22806
+ warn2(
22807
+ `${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ZB: ${this.ZB}, only default values are supported.`
22808
+ );
22809
+ }
22810
+ if (this.G < 1) {
22811
+ info(
22812
+ `Invalid Gamma: ${this.G} for ${this.name}, falling back to default.`
22813
+ );
22814
+ this.G = 1;
22815
+ }
22816
+ }
22817
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
22818
+ const A = src[srcOffset] * scale;
22819
+ const AG = A ** this.G;
22820
+ const L = this.YW * AG;
22821
+ const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0);
22822
+ dest[destOffset] = val;
22823
+ dest[destOffset + 1] = val;
22824
+ dest[destOffset + 2] = val;
22825
+ }
22826
+ getRgbItem(src, srcOffset, dest, destOffset) {
22827
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22828
+ assert2(
22829
+ dest instanceof Uint8ClampedArray,
22830
+ 'CalGrayCS.getRgbItem: Unsupported "dest" type.'
22831
+ );
22832
+ }
22833
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
22834
+ }
22835
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
22836
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
22837
+ assert2(
22838
+ dest instanceof Uint8ClampedArray,
22839
+ 'CalGrayCS.getRgbBuffer: Unsupported "dest" type.'
22840
+ );
22841
+ }
22842
+ const scale = 1 / ((1 << bits) - 1);
22843
+ for (let i = 0; i < count; ++i) {
22844
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
22845
+ srcOffset += 1;
22846
+ destOffset += 3 + alpha01;
22847
+ }
22848
+ }
22849
+ };
22850
+ var CalRGBCS = class _CalRGBCS extends ColorSpace {
22851
+ // See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these
22852
+ // matrices.
22853
+ // prettier-ignore
22854
+ static #BRADFORD_SCALE_MATRIX = new Float32Array([
22855
+ 0.8951,
22856
+ 0.2664,
22857
+ -0.1614,
22858
+ -0.7502,
22859
+ 1.7135,
22860
+ 0.0367,
22861
+ 0.0389,
22862
+ -0.0685,
22863
+ 1.0296
22864
+ ]);
22865
+ // prettier-ignore
22866
+ static #BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([
22867
+ 0.9869929,
22868
+ -0.1470543,
22869
+ 0.1599627,
22870
+ 0.4323053,
22871
+ 0.5183603,
22872
+ 0.0492912,
22873
+ -85287e-7,
22874
+ 0.0400428,
22875
+ 0.9684867
22876
+ ]);
22877
+ // See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html.
22878
+ // prettier-ignore
22879
+ static #SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([
22880
+ 3.2404542,
22881
+ -1.5371385,
22882
+ -0.4985314,
22883
+ -0.969266,
22884
+ 1.8760108,
22885
+ 0.041556,
22886
+ 0.0556434,
22887
+ -0.2040259,
22888
+ 1.0572252
22889
+ ]);
22890
+ static #FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);
22891
+ static #tempNormalizeMatrix = new Float32Array(3);
22892
+ static #tempConvertMatrix1 = new Float32Array(3);
22893
+ static #tempConvertMatrix2 = new Float32Array(3);
22894
+ static #DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8;
22895
+ constructor(whitePoint, blackPoint, gamma, matrix) {
22896
+ super("CalRGB", 3);
22897
+ if (!whitePoint) {
22898
+ throw new FormatError(
22899
+ "WhitePoint missing - required for color space CalRGB"
22900
+ );
22901
+ }
22902
+ const [XW, YW, ZW] = this.whitePoint = whitePoint;
22903
+ const [XB, YB, ZB] = this.blackPoint = blackPoint || new Float32Array(3);
22904
+ [this.GR, this.GG, this.GB] = gamma || new Float32Array([1, 1, 1]);
22905
+ [
22906
+ this.MXA,
22907
+ this.MYA,
22908
+ this.MZA,
22909
+ this.MXB,
22910
+ this.MYB,
22911
+ this.MZB,
22912
+ this.MXC,
22913
+ this.MYC,
22914
+ this.MZC
22915
+ ] = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
22916
+ if (XW < 0 || ZW < 0 || YW !== 1) {
22917
+ throw new FormatError(
22918
+ `Invalid WhitePoint components for ${this.name}, no fallback available`
22919
+ );
22920
+ }
22921
+ if (XB < 0 || YB < 0 || ZB < 0) {
22922
+ info(
22923
+ `Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], falling back to default.`
22924
+ );
22925
+ this.blackPoint = new Float32Array(3);
22926
+ }
22927
+ if (this.GR < 0 || this.GG < 0 || this.GB < 0) {
22928
+ info(
22929
+ `Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ${this.name}, falling back to default.`
22930
+ );
22931
+ this.GR = this.GG = this.GB = 1;
22932
+ }
22933
+ }
22934
+ #matrixProduct(a, b, result) {
22935
+ result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
22936
+ result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
22937
+ result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
22938
+ }
22939
+ #toFlat(sourceWhitePoint, LMS, result) {
22940
+ result[0] = LMS[0] * 1 / sourceWhitePoint[0];
22941
+ result[1] = LMS[1] * 1 / sourceWhitePoint[1];
22942
+ result[2] = LMS[2] * 1 / sourceWhitePoint[2];
22943
+ }
22944
+ #toD65(sourceWhitePoint, LMS, result) {
22945
+ const D65X = 0.95047;
22946
+ const D65Y = 1;
22947
+ const D65Z = 1.08883;
22948
+ result[0] = LMS[0] * D65X / sourceWhitePoint[0];
22949
+ result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
22950
+ result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
22951
+ }
22952
+ #sRGBTransferFunction(color) {
22953
+ if (color <= 31308e-7) {
22954
+ return MathClamp(12.92 * color, 0, 1);
22955
+ }
22956
+ return color >= 0.99554525 ? 1 : MathClamp((1 + 0.055) * color ** (1 / 2.4) - 0.055, 0, 1);
22957
+ }
22958
+ #decodeL(L) {
22959
+ if (L < 0) {
22960
+ return -this.#decodeL(-L);
22961
+ }
22962
+ return L > 8 ? ((L + 16) / 116) ** 3 : L * _CalRGBCS.#DECODE_L_CONSTANT;
22963
+ }
22964
+ #compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
22965
+ if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {
22966
+ result[0] = XYZ_Flat[0];
22967
+ result[1] = XYZ_Flat[1];
22968
+ result[2] = XYZ_Flat[2];
22969
+ return;
22970
+ }
22971
+ const zeroDecodeL = this.#decodeL(0);
22972
+ const X_DST = zeroDecodeL;
22973
+ const X_SRC = this.#decodeL(sourceBlackPoint[0]);
22974
+ const Y_DST = zeroDecodeL;
22975
+ const Y_SRC = this.#decodeL(sourceBlackPoint[1]);
22976
+ const Z_DST = zeroDecodeL;
22977
+ const Z_SRC = this.#decodeL(sourceBlackPoint[2]);
22978
+ const X_Scale = (1 - X_DST) / (1 - X_SRC);
22979
+ const X_Offset = 1 - X_Scale;
22980
+ const Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
22981
+ const Y_Offset = 1 - Y_Scale;
22982
+ const Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
22983
+ const Z_Offset = 1 - Z_Scale;
22984
+ result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
22985
+ result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
22986
+ result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
22987
+ }
22988
+ #normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
22989
+ if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
22990
+ result[0] = XYZ_In[0];
22991
+ result[1] = XYZ_In[1];
22992
+ result[2] = XYZ_In[2];
22993
+ return;
22994
+ }
22995
+ const LMS = result;
22996
+ this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
22997
+ const LMS_Flat = _CalRGBCS.#tempNormalizeMatrix;
22998
+ this.#toFlat(sourceWhitePoint, LMS, LMS_Flat);
22999
+ this.#matrixProduct(
23000
+ _CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
23001
+ LMS_Flat,
23002
+ result
23003
+ );
23004
+ }
23005
+ #normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
23006
+ const LMS = result;
23007
+ this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
23008
+ const LMS_D65 = _CalRGBCS.#tempNormalizeMatrix;
23009
+ this.#toD65(sourceWhitePoint, LMS, LMS_D65);
23010
+ this.#matrixProduct(
23011
+ _CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
23012
+ LMS_D65,
23013
+ result
23014
+ );
23015
+ }
23016
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
23017
+ const A = MathClamp(src[srcOffset] * scale, 0, 1);
23018
+ const B = MathClamp(src[srcOffset + 1] * scale, 0, 1);
23019
+ const C = MathClamp(src[srcOffset + 2] * scale, 0, 1);
23020
+ const AGR = A === 1 ? 1 : A ** this.GR;
23021
+ const BGG = B === 1 ? 1 : B ** this.GG;
23022
+ const CGB = C === 1 ? 1 : C ** this.GB;
23023
+ const X = this.MXA * AGR + this.MXB * BGG + this.MXC * CGB;
23024
+ const Y = this.MYA * AGR + this.MYB * BGG + this.MYC * CGB;
23025
+ const Z = this.MZA * AGR + this.MZB * BGG + this.MZC * CGB;
23026
+ const XYZ = _CalRGBCS.#tempConvertMatrix1;
23027
+ XYZ[0] = X;
23028
+ XYZ[1] = Y;
23029
+ XYZ[2] = Z;
23030
+ const XYZ_Flat = _CalRGBCS.#tempConvertMatrix2;
23031
+ this.#normalizeWhitePointToFlat(this.whitePoint, XYZ, XYZ_Flat);
23032
+ const XYZ_Black = _CalRGBCS.#tempConvertMatrix1;
23033
+ this.#compensateBlackPoint(this.blackPoint, XYZ_Flat, XYZ_Black);
23034
+ const XYZ_D65 = _CalRGBCS.#tempConvertMatrix2;
23035
+ this.#normalizeWhitePointToD65(
23036
+ _CalRGBCS.#FLAT_WHITEPOINT_MATRIX,
23037
+ XYZ_Black,
23038
+ XYZ_D65
23039
+ );
23040
+ const SRGB = _CalRGBCS.#tempConvertMatrix1;
23041
+ this.#matrixProduct(_CalRGBCS.#SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
23042
+ dest[destOffset] = this.#sRGBTransferFunction(SRGB[0]) * 255;
23043
+ dest[destOffset + 1] = this.#sRGBTransferFunction(SRGB[1]) * 255;
23044
+ dest[destOffset + 2] = this.#sRGBTransferFunction(SRGB[2]) * 255;
23045
+ }
23046
+ getRgbItem(src, srcOffset, dest, destOffset) {
23047
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23048
+ assert2(
23049
+ dest instanceof Uint8ClampedArray,
23050
+ 'CalRGBCS.getRgbItem: Unsupported "dest" type.'
23051
+ );
23052
+ }
23053
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
23054
+ }
23055
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
23056
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23057
+ assert2(
23058
+ dest instanceof Uint8ClampedArray,
23059
+ 'CalRGBCS.getRgbBuffer: Unsupported "dest" type.'
23060
+ );
23061
+ }
23062
+ const scale = 1 / ((1 << bits) - 1);
23063
+ for (let i = 0; i < count; ++i) {
23064
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
23065
+ srcOffset += 3;
23066
+ destOffset += 3 + alpha01;
23067
+ }
23068
+ }
23069
+ };
23070
+ var LabCS = class extends ColorSpace {
23071
+ constructor(whitePoint, blackPoint, range) {
23072
+ super("Lab", 3);
23073
+ if (!whitePoint) {
23074
+ throw new FormatError(
23075
+ "WhitePoint missing - required for color space Lab"
23076
+ );
23077
+ }
23078
+ [this.XW, this.YW, this.ZW] = whitePoint;
23079
+ [this.amin, this.amax, this.bmin, this.bmax] = range || [
23080
+ -100,
23081
+ 100,
23082
+ -100,
23083
+ 100
23084
+ ];
23085
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
23086
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
23087
+ throw new FormatError(
23088
+ "Invalid WhitePoint components, no fallback available"
23089
+ );
23090
+ }
23091
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
23092
+ info("Invalid BlackPoint, falling back to default");
23093
+ this.XB = this.YB = this.ZB = 0;
23094
+ }
23095
+ if (this.amin > this.amax || this.bmin > this.bmax) {
23096
+ info("Invalid Range, falling back to defaults");
23097
+ this.amin = -100;
23098
+ this.amax = 100;
23099
+ this.bmin = -100;
23100
+ this.bmax = 100;
23101
+ }
23102
+ }
23103
+ // Function g(x) from spec
23104
+ #fn_g(x) {
23105
+ return x >= 6 / 29 ? x ** 3 : 108 / 841 * (x - 4 / 29);
23106
+ }
23107
+ #decode(value, high1, low2, high2) {
23108
+ return low2 + value * (high2 - low2) / high1;
23109
+ }
23110
+ // If decoding is needed maxVal should be 2^bits per component - 1.
23111
+ #toRgb(src, srcOffset, maxVal, dest, destOffset) {
23112
+ let Ls = src[srcOffset];
23113
+ let as = src[srcOffset + 1];
23114
+ let bs = src[srcOffset + 2];
23115
+ if (maxVal !== false) {
23116
+ Ls = this.#decode(Ls, maxVal, 0, 100);
23117
+ as = this.#decode(as, maxVal, this.amin, this.amax);
23118
+ bs = this.#decode(bs, maxVal, this.bmin, this.bmax);
23119
+ }
23120
+ if (as > this.amax) {
23121
+ as = this.amax;
23122
+ } else if (as < this.amin) {
23123
+ as = this.amin;
23124
+ }
23125
+ if (bs > this.bmax) {
23126
+ bs = this.bmax;
23127
+ } else if (bs < this.bmin) {
23128
+ bs = this.bmin;
23129
+ }
23130
+ const M = (Ls + 16) / 116;
23131
+ const L = M + as / 500;
23132
+ const N = M - bs / 200;
23133
+ const X = this.XW * this.#fn_g(L);
23134
+ const Y = this.YW * this.#fn_g(M);
23135
+ const Z = this.ZW * this.#fn_g(N);
23136
+ let r, g, b;
23137
+ if (this.ZW < 1) {
23138
+ r = X * 3.1339 + Y * -1.617 + Z * -0.4906;
23139
+ g = X * -0.9785 + Y * 1.916 + Z * 0.0333;
23140
+ b = X * 0.072 + Y * -0.229 + Z * 1.4057;
23141
+ } else {
23142
+ r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
23143
+ g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
23144
+ b = X * 0.0557 + Y * -0.204 + Z * 1.057;
23145
+ }
23146
+ dest[destOffset] = Math.sqrt(r) * 255;
23147
+ dest[destOffset + 1] = Math.sqrt(g) * 255;
23148
+ dest[destOffset + 2] = Math.sqrt(b) * 255;
23149
+ }
23150
+ getRgbItem(src, srcOffset, dest, destOffset) {
23151
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23152
+ assert2(
23153
+ dest instanceof Uint8ClampedArray,
23154
+ 'LabCS.getRgbItem: Unsupported "dest" type.'
23155
+ );
23156
+ }
23157
+ this.#toRgb(src, srcOffset, false, dest, destOffset);
23158
+ }
23159
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
23160
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
23161
+ assert2(
23162
+ dest instanceof Uint8ClampedArray,
23163
+ 'LabCS.getRgbBuffer: Unsupported "dest" type.'
23164
+ );
23165
+ }
23166
+ const maxVal = (1 << bits) - 1;
23167
+ for (let i = 0; i < count; i++) {
23168
+ this.#toRgb(src, srcOffset, maxVal, dest, destOffset);
23169
+ srcOffset += 3;
23170
+ destOffset += 3 + alpha01;
23171
+ }
23172
+ }
23173
+ isDefaultDecode(decode, bpc) {
23174
+ return true;
23175
+ }
23176
+ get usesZeroToOneRange() {
23177
+ return shadow2(this, "usesZeroToOneRange", false);
23178
+ }
23179
+ };
23180
+ var TOKEN = {
23181
+ // Structural tokens — not keyword operators
23182
+ number: 0,
23183
+ lbrace: 1,
23184
+ rbrace: 2,
23185
+ // Boolean literals
23186
+ true: 3,
23187
+ false: 4,
23188
+ // Arithmetic binary operators
23189
+ add: 5,
23190
+ sub: 6,
23191
+ mul: 7,
23192
+ div: 8,
23193
+ idiv: 9,
23194
+ mod: 10,
23195
+ exp: 11,
23196
+ // Comparison binary operators
23197
+ eq: 12,
23198
+ ne: 13,
23199
+ gt: 14,
23200
+ ge: 15,
23201
+ lt: 16,
23202
+ le: 17,
23203
+ // Bitwise / boolean binary operators
23204
+ and: 18,
23205
+ or: 19,
23206
+ xor: 20,
23207
+ bitshift: 21,
23208
+ // Unary arithmetic operators
23209
+ abs: 22,
23210
+ neg: 23,
23211
+ ceiling: 24,
23212
+ floor: 25,
23213
+ round: 26,
23214
+ truncate: 27,
23215
+ // Unary boolean / bitwise operator
23216
+ not: 28,
23217
+ // Mathematical functions — unary
23218
+ sqrt: 29,
23219
+ sin: 30,
23220
+ cos: 31,
23221
+ ln: 32,
23222
+ log: 33,
23223
+ // Mathematical function — binary
23224
+ atan: 34,
23225
+ // Type conversion operators
23226
+ cvi: 35,
23227
+ cvr: 36,
23228
+ // Stack operators
23229
+ dup: 37,
23230
+ exch: 38,
23231
+ pop: 39,
23232
+ copy: 40,
23233
+ index: 41,
23234
+ roll: 42,
23235
+ // Control flow
23236
+ if: 43,
23237
+ ifelse: 44,
23238
+ // End of input
23239
+ eof: 45,
23240
+ // Synthetic: produced by the optimizer, never emitted by the lexer.
23241
+ min: 46,
23242
+ max: 47
23243
+ };
23244
+ var Token = class {
23245
+ constructor(id, value = null) {
23246
+ this.id = id;
23247
+ this.value = value;
23248
+ }
23249
+ };
23250
+ var Lexer = class _Lexer {
23251
+ // Singletons for every non-number token, built lazily on first construction.
23252
+ // Keyword operator tokens carry their name as `value`; structural tokens
23253
+ // (lbrace, rbrace, eof) carry null.
23254
+ static #singletons = null;
23255
+ static #operatorSingletons = null;
23256
+ static #initSingletons() {
23257
+ const singletons = /* @__PURE__ */ Object.create(null);
23258
+ const operatorSingletons = /* @__PURE__ */ Object.create(null);
23259
+ for (const [name, id] of Object.entries(TOKEN)) {
23260
+ if (name === "number") {
23261
+ continue;
23262
+ }
23263
+ const isOperator = id >= TOKEN.true && id <= TOKEN.ifelse;
23264
+ const token = new Token(id, isOperator ? name : null);
23265
+ singletons[name] = token;
23266
+ if (isOperator) {
23267
+ operatorSingletons[name] = token;
23268
+ }
23269
+ }
23270
+ this.#singletons = singletons;
23271
+ this.#operatorSingletons = operatorSingletons;
23272
+ }
23273
+ constructor(data) {
23274
+ if (!_Lexer.#singletons) {
23275
+ _Lexer.#initSingletons();
23276
+ }
23277
+ this.data = data;
23278
+ this.pos = 0;
23279
+ this.len = data.length;
23280
+ this._numberPattern = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/iy;
23281
+ this._identifierPattern = /[a-z]+/y;
23282
+ }
23283
+ // Skip a % comment, advancing past the next \n or \r (or to EOF).
23284
+ _skipComment() {
23285
+ const lf = this.data.indexOf("\n", this.pos);
23286
+ const cr = this.data.indexOf("\r", this.pos);
23287
+ const eol = Math.min(lf < 0 ? this.len : lf, cr < 0 ? this.len : cr);
23288
+ this.pos = Math.min(eol + 1, this.len);
23289
+ }
23290
+ _getNumber() {
23291
+ this._numberPattern.lastIndex = this.pos;
23292
+ const match = this._numberPattern.exec(this.data);
23293
+ if (!match) {
23294
+ return new Token(TOKEN.number, 0);
23295
+ }
23296
+ const number = parseFloat(match[0]);
23297
+ if (!Number.isFinite(number)) {
23298
+ return new Token(TOKEN.number, 0);
23299
+ }
23300
+ this.pos = this._numberPattern.lastIndex;
23301
+ return new Token(TOKEN.number, number);
23302
+ }
23303
+ _getOperator() {
23304
+ this._identifierPattern.lastIndex = this.pos;
23305
+ const match = this._identifierPattern.exec(this.data);
23306
+ if (!match) {
23307
+ return new Token(TOKEN.number, 0);
23308
+ }
23309
+ this.pos = this._identifierPattern.lastIndex;
23310
+ const op = match[0];
23311
+ const token = _Lexer.#operatorSingletons[op];
23312
+ return token ?? new Token(TOKEN.number, 0);
23313
+ }
23314
+ // Return the next token, or Lexer.#singletons.eof at end of input.
23315
+ next() {
23316
+ while (this.pos < this.len) {
23317
+ const ch3 = this.data.charCodeAt(this.pos++);
23318
+ switch (ch3) {
23319
+ // PostScript white-space characters (PDF32000 §7.2.2)
23320
+ case 0:
23321
+ case 9:
23322
+ case 10:
23323
+ case 12:
23324
+ case 13:
23325
+ case 32:
23326
+ break;
23327
+ case 37:
23328
+ this._skipComment();
23329
+ break;
23330
+ case 123:
23331
+ return _Lexer.#singletons.lbrace;
23332
+ case 125:
23333
+ return _Lexer.#singletons.rbrace;
23334
+ case 43:
23335
+ case 45:
23336
+ this.pos--;
23337
+ return this._getNumber();
23338
+ case 46:
23339
+ this.pos--;
23340
+ return this._getNumber();
23341
+ default:
23342
+ if (ch3 >= 48 && ch3 <= 57) {
23343
+ this.pos--;
23344
+ return this._getNumber();
23345
+ }
23346
+ if (ch3 >= 97 && ch3 <= 122) {
23347
+ this.pos--;
23348
+ return this._getOperator();
23349
+ }
23350
+ return new Token(TOKEN.number, 0);
23351
+ }
23352
+ }
23353
+ return _Lexer.#singletons.eof;
23354
+ }
23355
+ };
23356
+ var PS_VALUE_TYPE = {
23357
+ numeric: 0,
23358
+ // known to be a number (f64 in Wasm)
23359
+ boolean: 1,
23360
+ // known to be a boolean (0.0 = false, 1.0 = true in f64)
23361
+ unknown: 2
23362
+ // indeterminate at compile time
23363
+ };
23364
+ var PS_NODE = {
23365
+ // Parser AST node types (produced by Parser / parsePostScriptFunction)
23366
+ program: 0,
23367
+ block: 1,
23368
+ number: 2,
23369
+ operator: 3,
23370
+ if: 4,
23371
+ ifelse: 5,
23372
+ // Tree AST node types (produced by PSStackToTree)
23373
+ arg: 6,
23374
+ const: 7,
23375
+ unary: 8,
23376
+ binary: 9,
23377
+ ternary: 10
23378
+ };
23379
+ var PsNode = class {
23380
+ constructor(type) {
23381
+ this.type = type;
23382
+ }
23383
+ };
23384
+ var PsProgram = class extends PsNode {
23385
+ constructor(body) {
23386
+ super(PS_NODE.program);
23387
+ this.body = body;
23388
+ }
23389
+ };
23390
+ var PsBlock = class extends PsNode {
23391
+ constructor(instructions) {
23392
+ super(PS_NODE.block);
23393
+ this.instructions = instructions;
23394
+ }
23395
+ };
23396
+ var PsNumber = class extends PsNode {
23397
+ /** @param {number} value */
23398
+ constructor(value) {
23399
+ super(PS_NODE.number);
23400
+ this.value = value;
23401
+ }
23402
+ };
23403
+ var PsOperator = class extends PsNode {
23404
+ /** @param {number} op — one of the TOKEN.* constants from lexer.js */
23405
+ constructor(op) {
23406
+ super(PS_NODE.operator);
23407
+ this.op = op;
23408
+ }
23409
+ };
23410
+ var PsIf = class extends PsNode {
23411
+ /** @param {PsBlock} then */
23412
+ constructor(then) {
23413
+ super(PS_NODE.if);
23414
+ this.then = then;
23415
+ }
23416
+ };
23417
+ var PsIfElse = class extends PsNode {
23418
+ /**
23419
+ * @param {PsBlock} then
23420
+ * @param {PsBlock} otherwise
23421
+ */
23422
+ constructor(then, otherwise) {
23423
+ super(PS_NODE.ifelse);
23424
+ this.then = then;
23425
+ this.otherwise = otherwise;
23426
+ }
23427
+ };
23428
+ var PsArgNode = class extends PsNode {
23429
+ /** @param {number} index */
23430
+ constructor(index) {
23431
+ super(PS_NODE.arg);
23432
+ this.index = index;
23433
+ this.valueType = PS_VALUE_TYPE.numeric;
23434
+ }
23435
+ };
23436
+ var PsConstNode = class extends PsNode {
23437
+ /** @param {number|boolean} value */
23438
+ constructor(value) {
23439
+ super(PS_NODE.const);
23440
+ this.value = value;
23441
+ this.valueType = typeof value === "boolean" ? PS_VALUE_TYPE.boolean : PS_VALUE_TYPE.numeric;
23442
+ }
23443
+ };
23444
+ var PsUnaryNode = class extends PsNode {
23445
+ /**
23446
+ * @param {number} op — TOKEN.* constant
23447
+ * @param {PsNode} operand
23448
+ * @param {number} [valueType]
23449
+ */
23450
+ constructor(op, operand, valueType = PS_VALUE_TYPE.unknown) {
23451
+ super(PS_NODE.unary);
23452
+ this.op = op;
23453
+ this.operand = operand;
23454
+ this.valueType = valueType;
23455
+ }
23456
+ };
23457
+ var PsBinaryNode = class extends PsNode {
23458
+ /**
23459
+ * @param {number} op — TOKEN.* constant
23460
+ * @param {PsNode} first — was on top of stack
23461
+ * @param {PsNode} second — was below top
23462
+ * @param {number} [valueType]
23463
+ */
23464
+ constructor(op, first, second, valueType = PS_VALUE_TYPE.unknown) {
23465
+ super(PS_NODE.binary);
23466
+ this.op = op;
23467
+ this.first = first;
23468
+ this.second = second;
23469
+ this.valueType = valueType;
23470
+ }
23471
+ };
23472
+ var PsTernaryNode = class extends PsNode {
23473
+ /**
23474
+ * @param {PsNode} cond
23475
+ * @param {PsNode} then
23476
+ * @param {PsNode} otherwise
23477
+ * @param {number} [valueType]
23478
+ */
23479
+ constructor(cond, then, otherwise, valueType = PS_VALUE_TYPE.unknown) {
23480
+ super(PS_NODE.ternary);
23481
+ this.cond = cond;
23482
+ this.then = then;
23483
+ this.otherwise = otherwise;
23484
+ this.valueType = valueType;
23485
+ }
23486
+ };
23487
+ var Parser = class _Parser {
23488
+ constructor(lexer) {
23489
+ this.lexer = lexer;
23490
+ this._token = null;
23491
+ }
23492
+ static _isRegularOperator(id) {
23493
+ return id >= TOKEN.true && id < TOKEN.if;
23494
+ }
23495
+ // Fetch the next token from the lexer.
23496
+ _advance() {
23497
+ this._token = this.lexer.next();
23498
+ }
23499
+ // Assert that the current token has the given id, consume it, and return it.
23500
+ _expect(id) {
23501
+ if (this._token.id !== id) {
23502
+ throw new FormatError(
23503
+ `PostScript function: expected token id ${id}, got ${this._token.id}.`
23504
+ );
23505
+ }
23506
+ const tok = this._token;
23507
+ this._advance();
23508
+ return tok;
23509
+ }
23510
+ /**
23511
+ * Parse the full Type 4 function body.
23512
+ *
23513
+ * Grammar (simplified):
23514
+ * program ::= '{' block '}'
23515
+ * block ::= instruction*
23516
+ * instruction ::= number
23517
+ * | operator (any PS_OPERATOR except if / ifelse)
23518
+ * | '{' block '}' 'if'
23519
+ * | '{' block '}' '{' block '}' 'ifelse'
23520
+ * @returns {PsProgram}
23521
+ */
23522
+ parse() {
23523
+ this._advance();
23524
+ this._expect(TOKEN.lbrace);
23525
+ const block = this._parseBlock();
23526
+ this._expect(TOKEN.rbrace);
23527
+ if (this._token.id !== TOKEN.eof) {
23528
+ warn2("PostScript function: unexpected content after closing brace.");
23529
+ }
23530
+ return new PsProgram(block);
23531
+ }
23532
+ _parseBlock() {
23533
+ const instructions = [];
23534
+ while (true) {
23535
+ const tok = this._token;
23536
+ switch (tok.id) {
23537
+ case TOKEN.number:
23538
+ instructions.push(new PsNumber(tok.value));
23539
+ this._advance();
23540
+ break;
23541
+ case TOKEN.lbrace: {
23542
+ this._advance();
23543
+ const thenBlock = this._parseBlock();
23544
+ this._expect(TOKEN.rbrace);
23545
+ if (this._token.id === TOKEN.if) {
23546
+ this._advance();
23547
+ instructions.push(new PsIf(thenBlock));
23548
+ } else if (this._token.id === TOKEN.lbrace) {
23549
+ this._advance();
23550
+ const elseBlock = this._parseBlock();
23551
+ this._expect(TOKEN.rbrace);
23552
+ this._expect(TOKEN.ifelse);
23553
+ instructions.push(new PsIfElse(thenBlock, elseBlock));
23554
+ } else {
23555
+ throw new FormatError(
23556
+ "PostScript function: a procedure block must be followed by 'if' or '{\u2026} ifelse'."
23557
+ );
23558
+ }
23559
+ break;
23560
+ }
23561
+ case TOKEN.rbrace:
23562
+ case TOKEN.eof:
23563
+ return new PsBlock(instructions);
23564
+ case TOKEN.if:
23565
+ case TOKEN.ifelse:
23566
+ throw new FormatError(
23567
+ `PostScript function: unexpected '${tok.value}' operator.`
23568
+ );
23569
+ default:
23570
+ if (_Parser._isRegularOperator(tok.id)) {
23571
+ instructions.push(new PsOperator(tok.id));
23572
+ this._advance();
23573
+ break;
23574
+ }
23575
+ throw new FormatError(
23576
+ `PostScript function: unexpected token id ${tok.id}.`
23577
+ );
23578
+ }
23579
+ }
23580
+ }
23581
+ };
23582
+ function parsePostScriptFunction(source) {
23583
+ return new Parser(new Lexer(source)).parse();
23584
+ }
23585
+ function _nodesEqual(a, b) {
23586
+ if (a === b) {
23587
+ return true;
23588
+ }
23589
+ if (a.type !== b.type) {
23590
+ return false;
23591
+ }
23592
+ switch (a.type) {
23593
+ case PS_NODE.arg:
23594
+ return a.index === b.index;
23595
+ case PS_NODE.const:
23596
+ return a.value === b.value;
23597
+ case PS_NODE.unary:
23598
+ return a.op === b.op && _nodesEqual(a.operand, b.operand);
23599
+ case PS_NODE.binary:
23600
+ return a.op === b.op && _nodesEqual(a.first, b.first) && _nodesEqual(a.second, b.second);
23601
+ case PS_NODE.ternary:
23602
+ return _nodesEqual(a.cond, b.cond) && _nodesEqual(a.then, b.then) && _nodesEqual(a.otherwise, b.otherwise);
23603
+ default:
23604
+ return false;
23605
+ }
23606
+ }
23607
+ function _evalBinaryConst(op, a, b) {
23608
+ switch (op) {
23609
+ case TOKEN.add:
23610
+ return a + b;
23611
+ case TOKEN.sub:
23612
+ return a - b;
23613
+ case TOKEN.mul:
23614
+ return a * b;
23615
+ case TOKEN.div:
23616
+ return b !== 0 ? a / b : 0;
23617
+ // div by zero → 0
23618
+ case TOKEN.idiv:
23619
+ return b !== 0 ? Math.trunc(a / b) : 0;
23620
+ // div by zero → 0
23621
+ case TOKEN.mod:
23622
+ return b !== 0 ? a - Math.trunc(a / b) * b : 0;
23623
+ // div by zero → 0
23624
+ case TOKEN.exp: {
23625
+ const r = a ** b;
23626
+ return Number.isFinite(r) ? r : void 0;
23627
+ }
23628
+ case TOKEN.atan: {
23629
+ let deg = Math.atan2(a, b) * (180 / Math.PI);
23630
+ if (deg < 0) {
23631
+ deg += 360;
23632
+ }
23633
+ return deg;
23634
+ }
23635
+ case TOKEN.eq:
23636
+ return a === b;
23637
+ case TOKEN.ne:
23638
+ return a !== b;
23639
+ case TOKEN.gt:
23640
+ return a > b;
23641
+ case TOKEN.ge:
23642
+ return a >= b;
23643
+ case TOKEN.lt:
23644
+ return a < b;
23645
+ case TOKEN.le:
23646
+ return a <= b;
23647
+ case TOKEN.and:
23648
+ return typeof a === "boolean" ? a && b : a & b | 0;
23649
+ case TOKEN.or:
23650
+ return typeof a === "boolean" ? a || b : a | b | 0;
23651
+ case TOKEN.xor:
23652
+ return typeof a === "boolean" ? a !== b : a ^ b | 0;
23653
+ case TOKEN.bitshift:
23654
+ return b >= 0 ? a << b | 0 : a >> -b | 0;
23655
+ case TOKEN.min:
23656
+ return Math.min(a, b);
23657
+ case TOKEN.max:
23658
+ return Math.max(a, b);
23659
+ default:
23660
+ return void 0;
23661
+ }
23662
+ }
23663
+ function _evalUnaryConst(op, v) {
23664
+ switch (op) {
23665
+ case TOKEN.abs:
23666
+ return Math.abs(v);
23667
+ case TOKEN.neg:
23668
+ return -v;
23669
+ case TOKEN.ceiling:
23670
+ return Math.ceil(v);
23671
+ case TOKEN.floor:
23672
+ return Math.floor(v);
23673
+ case TOKEN.round:
23674
+ return Math.round(v);
23675
+ case TOKEN.truncate:
23676
+ return Math.trunc(v);
23677
+ case TOKEN.sqrt: {
23678
+ const r = Math.sqrt(v);
23679
+ return Number.isFinite(r) ? r : void 0;
23680
+ }
23681
+ case TOKEN.sin:
23682
+ return Math.sin(v % 360 * Math.PI / 180);
23683
+ case TOKEN.cos:
23684
+ return Math.cos(v % 360 * Math.PI / 180);
23685
+ case TOKEN.ln: {
23686
+ const r = Math.log(v);
23687
+ return Number.isFinite(r) ? r : void 0;
23688
+ }
23689
+ case TOKEN.log: {
23690
+ const r = Math.log10(v);
23691
+ return Number.isFinite(r) ? r : void 0;
23692
+ }
23693
+ case TOKEN.cvi:
23694
+ return Math.trunc(v);
23695
+ case TOKEN.cvr:
23696
+ return v;
23697
+ case TOKEN.not:
23698
+ return typeof v === "boolean" ? !v : ~v;
23699
+ default:
23700
+ return void 0;
23701
+ }
23702
+ }
23703
+ var MAX_STACK_SIZE = 100;
23704
+ function _unaryValueType(op, operandType) {
23705
+ return op === TOKEN.not ? operandType : PS_VALUE_TYPE.numeric;
23706
+ }
23707
+ function _binaryValueType(op, firstType, secondType) {
23708
+ switch (op) {
23709
+ // Comparison operators always produce a boolean.
23710
+ case TOKEN.eq:
23711
+ case TOKEN.ne:
23712
+ case TOKEN.gt:
23713
+ case TOKEN.ge:
23714
+ case TOKEN.lt:
23715
+ case TOKEN.le:
23716
+ return PS_VALUE_TYPE.boolean;
23717
+ // and / or / xor preserve the type when both operands are the same known
23718
+ // type (both boolean or both numeric); otherwise the type is unknown.
23719
+ case TOKEN.and:
23720
+ case TOKEN.or:
23721
+ case TOKEN.xor:
23722
+ return firstType === secondType && firstType !== PS_VALUE_TYPE.unknown ? firstType : PS_VALUE_TYPE.unknown;
23723
+ // All arithmetic / bitshift operators produce a numeric result.
23724
+ default:
23725
+ return PS_VALUE_TYPE.numeric;
23726
+ }
23727
+ }
23728
+ var PSStackToTree = class _PSStackToTree {
23729
+ static #binaryOps = null;
23730
+ static #unaryOps = null;
23731
+ static #idempotentUnary = null;
23732
+ static #negatedComparison = null;
23733
+ static #init() {
23734
+ this.#binaryOps = /* @__PURE__ */ new Set([
23735
+ TOKEN.add,
23736
+ TOKEN.sub,
23737
+ TOKEN.mul,
23738
+ TOKEN.div,
23739
+ TOKEN.idiv,
23740
+ TOKEN.mod,
23741
+ TOKEN.exp,
23742
+ TOKEN.atan,
23743
+ TOKEN.eq,
23744
+ TOKEN.ne,
23745
+ TOKEN.gt,
23746
+ TOKEN.ge,
23747
+ TOKEN.lt,
23748
+ TOKEN.le,
23749
+ TOKEN.and,
23750
+ TOKEN.or,
23751
+ TOKEN.xor,
23752
+ TOKEN.bitshift
23753
+ ]);
23754
+ this.#unaryOps = /* @__PURE__ */ new Set([
23755
+ TOKEN.abs,
23756
+ TOKEN.neg,
23757
+ TOKEN.ceiling,
23758
+ TOKEN.floor,
23759
+ TOKEN.round,
23760
+ TOKEN.truncate,
23761
+ TOKEN.sqrt,
23762
+ TOKEN.sin,
23763
+ TOKEN.cos,
23764
+ TOKEN.ln,
23765
+ TOKEN.log,
23766
+ TOKEN.cvi,
23767
+ TOKEN.cvr,
23768
+ TOKEN.not
23769
+ ]);
23770
+ this.#idempotentUnary = /* @__PURE__ */ new Set([
23771
+ TOKEN.abs,
23772
+ TOKEN.ceiling,
23773
+ TOKEN.cvi,
23774
+ TOKEN.cvr,
23775
+ TOKEN.floor,
23776
+ TOKEN.round,
23777
+ TOKEN.truncate
23778
+ ]);
23779
+ this.#negatedComparison = /* @__PURE__ */ new Map([
23780
+ [TOKEN.eq, TOKEN.ne],
23781
+ [TOKEN.ne, TOKEN.eq],
23782
+ [TOKEN.lt, TOKEN.ge],
23783
+ [TOKEN.le, TOKEN.gt],
23784
+ [TOKEN.gt, TOKEN.le],
23785
+ [TOKEN.ge, TOKEN.lt]
23786
+ ]);
23787
+ }
23788
+ /**
23789
+ * @param {PsProgram} program
23790
+ * @param {number} numInputs — number of domain values placed on the stack
23791
+ * before the program runs (i.e. the length of the domain array / 2).
23792
+ * @returns {Array<PsNode>} — one tree node per output value.
23793
+ */
23794
+ evaluate(program, numInputs) {
23795
+ if (!_PSStackToTree.#binaryOps) {
23796
+ _PSStackToTree.#init();
23797
+ }
23798
+ this._failed = false;
23799
+ if (numInputs > MAX_STACK_SIZE) {
23800
+ return null;
23801
+ }
23802
+ const stack = [];
23803
+ for (let i = 0; i < numInputs; i++) {
23804
+ stack.push(new PsArgNode(i));
23805
+ }
23806
+ this._evalBlock(program.body, stack);
23807
+ if (this._failed) {
23808
+ return null;
23809
+ }
23810
+ _PSStackToTree.#markShared(stack);
23811
+ return stack;
23812
+ }
23813
+ // Set node.shared / sharedCount on non-atomic nodes referenced more than
23814
+ // once. arg/const are excluded — they are cheap to re-emit inline.
23815
+ static #markShared(outputs) {
23816
+ const refCount = /* @__PURE__ */ new Map();
23817
+ const visit = (node) => {
23818
+ if (!node || node.type === PS_NODE.arg || node.type === PS_NODE.const) {
23819
+ return;
23820
+ }
23821
+ const prev = refCount.get(node) ?? 0;
23822
+ refCount.set(node, prev + 1);
23823
+ if (prev > 0) {
23824
+ return;
23825
+ }
23826
+ switch (node.type) {
23827
+ case PS_NODE.unary:
23828
+ visit(node.operand);
23829
+ break;
23830
+ case PS_NODE.binary:
23831
+ visit(node.first);
23832
+ visit(node.second);
23833
+ break;
23834
+ case PS_NODE.ternary:
23835
+ visit(node.cond);
23836
+ visit(node.then);
23837
+ visit(node.otherwise);
23838
+ break;
23839
+ }
23840
+ };
23841
+ for (const output of outputs) {
23842
+ visit(output);
23843
+ }
23844
+ for (const [node, count] of refCount) {
23845
+ if (count > 1) {
23846
+ node.shared = true;
23847
+ node.sharedCount = count;
23848
+ }
23849
+ }
23850
+ }
23851
+ _evalBlock(block, stack) {
23852
+ this._evalBlockFrom(block.instructions, 0, stack);
23853
+ }
23854
+ /**
23855
+ * Core evaluation loop. Processes `instructions[startIdx…]` in order,
23856
+ * mutating `stack` as each instruction executes.
23857
+ *
23858
+ * When a `{ body } if` instruction grows the stack (the PostScript "early
23859
+ * exit / guard" idiom), the remaining instructions in the current array are
23860
+ * evaluated on **both** the true-branch stack and the false-branch stack,
23861
+ * then the two results are merged into PsTernaryNodes. This handles
23862
+ * patterns like:
23863
+ *
23864
+ * cond { pop R G B sentinel } if
23865
+ * … more guards …
23866
+ * sentinel 0 gt { defaultR defaultG defaultB } if
23867
+ */
23868
+ _evalBlockFrom(instructions, startIdx, stack) {
23869
+ for (let idx = startIdx; idx < instructions.length; idx++) {
23870
+ if (this._failed) {
23871
+ break;
23872
+ }
23873
+ const instr = instructions[idx];
23874
+ switch (instr.type) {
23875
+ case PS_NODE.number:
23876
+ stack.push(new PsConstNode(instr.value));
23877
+ if (stack.length > MAX_STACK_SIZE) {
23878
+ this._failed = true;
23879
+ }
23880
+ break;
23881
+ case PS_NODE.operator:
23882
+ this._evalOp(instr.op, stack);
23883
+ break;
23884
+ case PS_NODE.if: {
23885
+ if (stack.length < 1) {
23886
+ this._failed = true;
23887
+ break;
23888
+ }
23889
+ const cond = stack.pop();
23890
+ const saved = stack.slice();
23891
+ this._evalBlock(instr.then, stack);
23892
+ if (this._failed) {
23893
+ break;
23894
+ }
23895
+ if (stack.length === saved.length) {
23896
+ for (let i = 0; i < stack.length; i++) {
23897
+ if (stack[i] !== saved[i]) {
23898
+ stack[i] = this._makeTernary(cond, stack[i], saved[i]);
23899
+ }
23900
+ }
23901
+ } else if (stack.length > saved.length) {
23902
+ if (cond.type === PS_NODE.const) {
23903
+ if (!cond.value) {
23904
+ stack.length = 0;
23905
+ stack.push(...saved);
23906
+ }
23907
+ break;
23908
+ }
23909
+ const trueStack = stack.slice();
23910
+ this._evalBlockFrom(instructions, idx + 1, trueStack);
23911
+ if (this._failed) {
23912
+ break;
23913
+ }
23914
+ const falseStack = saved;
23915
+ this._evalBlockFrom(instructions, idx + 1, falseStack);
23916
+ if (this._failed) {
23917
+ break;
23918
+ }
23919
+ if (trueStack.length !== falseStack.length) {
23920
+ const zero2 = new PsConstNode(0);
23921
+ while (trueStack.length < falseStack.length) {
23922
+ trueStack.push(zero2);
23923
+ }
23924
+ while (falseStack.length < trueStack.length) {
23925
+ falseStack.push(zero2);
23926
+ }
23927
+ }
23928
+ stack.length = 0;
23929
+ for (let i = 0; i < trueStack.length; i++) {
23930
+ stack.push(this._makeTernary(cond, trueStack[i], falseStack[i]));
23931
+ }
23932
+ return;
23933
+ } else {
23934
+ this._failed = true;
23935
+ }
23936
+ break;
23937
+ }
23938
+ case PS_NODE.ifelse: {
23939
+ if (stack.length < 1) {
23940
+ this._failed = true;
23941
+ break;
23942
+ }
23943
+ const cond = stack.pop();
23944
+ const snapshot = stack.slice();
23945
+ const thenStack = snapshot.slice();
23946
+ this._evalBlock(instr.then, thenStack);
23947
+ if (this._failed) {
23948
+ break;
23949
+ }
23950
+ const elseStack = snapshot.slice();
23951
+ this._evalBlock(instr.otherwise, elseStack);
23952
+ if (this._failed) {
23953
+ break;
23954
+ }
23955
+ if (thenStack.length !== elseStack.length) {
23956
+ const zero2 = new PsConstNode(0);
23957
+ while (thenStack.length < elseStack.length) {
23958
+ thenStack.push(zero2);
23959
+ }
23960
+ while (elseStack.length < thenStack.length) {
23961
+ elseStack.push(zero2);
23962
+ }
23963
+ }
23964
+ stack.length = 0;
23965
+ for (let i = 0; i < thenStack.length; i++) {
23966
+ stack.push(this._makeTernary(cond, thenStack[i], elseStack[i]));
23967
+ }
23968
+ break;
23969
+ }
23970
+ }
23971
+ }
23972
+ }
23973
+ _evalOp(op, stack) {
23974
+ if (_PSStackToTree.#binaryOps.has(op)) {
23975
+ if (stack.length < 2) {
23976
+ this._failed = true;
23977
+ return;
23978
+ }
23979
+ const first = stack.pop();
23980
+ const second = stack.pop();
23981
+ stack.push(this._makeBinary(op, first, second));
23982
+ return;
23983
+ }
23984
+ if (_PSStackToTree.#unaryOps.has(op)) {
23985
+ if (stack.length < 1) {
23986
+ this._failed = true;
23987
+ return;
23988
+ }
23989
+ stack.push(this._makeUnary(op, stack.pop()));
23990
+ return;
23991
+ }
23992
+ switch (op) {
23993
+ case TOKEN.true:
23994
+ stack.push(new PsConstNode(true));
23995
+ if (stack.length > MAX_STACK_SIZE) {
23996
+ this._failed = true;
23997
+ }
23998
+ break;
23999
+ case TOKEN.false:
24000
+ stack.push(new PsConstNode(false));
24001
+ if (stack.length > MAX_STACK_SIZE) {
24002
+ this._failed = true;
24003
+ }
24004
+ break;
24005
+ case TOKEN.dup:
24006
+ if (stack.length < 1) {
24007
+ this._failed = true;
24008
+ break;
24009
+ }
24010
+ stack.push(stack.at(-1));
24011
+ if (stack.length > MAX_STACK_SIZE) {
24012
+ this._failed = true;
24013
+ }
24014
+ break;
24015
+ case TOKEN.exch: {
24016
+ if (stack.length < 2) {
24017
+ this._failed = true;
24018
+ break;
24019
+ }
24020
+ const a = stack.pop();
24021
+ const b = stack.pop();
24022
+ stack.push(a, b);
24023
+ break;
24024
+ }
24025
+ case TOKEN.pop:
24026
+ if (stack.length < 1) {
24027
+ this._failed = true;
24028
+ break;
24029
+ }
24030
+ stack.pop();
24031
+ break;
24032
+ case TOKEN.copy: {
24033
+ if (stack.length < 1) {
24034
+ this._failed = true;
24035
+ break;
24036
+ }
24037
+ const nNode = stack.pop();
24038
+ if (nNode.type === PS_NODE.const) {
24039
+ const n = nNode.value | 0;
24040
+ if (n === 0) {
24041
+ } else if (n < 0 || n > stack.length) {
24042
+ this._failed = true;
24043
+ } else {
24044
+ stack.push(...stack.slice(-n));
24045
+ if (stack.length > MAX_STACK_SIZE) {
24046
+ this._failed = true;
24047
+ }
24048
+ }
24049
+ } else {
24050
+ this._failed = true;
24051
+ }
24052
+ break;
24053
+ }
24054
+ case TOKEN.index: {
24055
+ if (stack.length < 1) {
24056
+ this._failed = true;
24057
+ break;
24058
+ }
24059
+ const nNode = stack.pop();
24060
+ if (nNode.type === PS_NODE.const) {
24061
+ const n = nNode.value | 0;
24062
+ if (n < 0 || n >= stack.length) {
24063
+ this._failed = true;
24064
+ } else {
24065
+ stack.push(stack.at(-n - 1));
24066
+ }
24067
+ } else {
24068
+ this._failed = true;
24069
+ }
24070
+ break;
24071
+ }
24072
+ case TOKEN.roll: {
24073
+ if (stack.length < 2) {
24074
+ this._failed = true;
24075
+ break;
24076
+ }
24077
+ const jNode = stack.pop();
24078
+ const nNode = stack.pop();
24079
+ if (nNode.type === PS_NODE.const && jNode.type === PS_NODE.const) {
24080
+ const n = nNode.value | 0;
24081
+ if (n === 0) {
24082
+ } else if (n < 0 || n > stack.length) {
24083
+ this._failed = true;
24084
+ } else {
24085
+ const j = ((jNode.value | 0) % n + n) % n;
24086
+ if (j > 0) {
24087
+ const slice = stack.splice(-n, n);
24088
+ stack.push(...slice.slice(n - j), ...slice.slice(0, n - j));
24089
+ }
24090
+ }
24091
+ } else {
24092
+ this._failed = true;
24093
+ }
24094
+ break;
24095
+ }
24096
+ default:
24097
+ this._failed = true;
24098
+ break;
24099
+ }
24100
+ }
24101
+ /**
24102
+ * Create a binary tree node, applying optimizations eagerly:
24103
+ *
24104
+ * 1. Constant folding — both operands are PsConstNode → fold to PsConstNode.
24105
+ * 2. Reflexive simplifications — x−x→0, x xor x→0, x eq x→true, etc.
24106
+ * 3. Algebraic simplifications with one known operand — identity elements
24107
+ * (x+0→x, x*1→x, …), absorbing elements (x*0→0, x and false→false, …),
24108
+ * and strength reductions (x*-1→neg(x), x^0.5→sqrt(x), x^2→x*x, …).
24109
+ *
24110
+ * Recall: `first` was on top of the stack (right operand for non-commutative
24111
+ * ops), `second` was below (left operand). So `a b sub` → second=a, first=b
24112
+ * → a − b.
24113
+ */
24114
+ _makeBinary(op, first, second) {
24115
+ if (first.type === PS_NODE.const && second.type === PS_NODE.const) {
24116
+ const v = _evalBinaryConst(op, second.value, first.value);
24117
+ if (v !== void 0) {
24118
+ return new PsConstNode(v);
24119
+ }
24120
+ }
24121
+ if (_nodesEqual(first, second)) {
24122
+ switch (op) {
24123
+ case TOKEN.sub:
24124
+ return new PsConstNode(0);
24125
+ // x − x → 0
24126
+ case TOKEN.xor:
24127
+ return new PsConstNode(
24128
+ /* eslint-disable unicorn/prefer-logical-operator-over-ternary */
24129
+ first.valueType === PS_VALUE_TYPE.boolean ? false : 0
24130
+ /* eslint-enable unicorn/prefer-logical-operator-over-ternary */
24131
+ );
24132
+ // TOKEN.mod, TOKEN.div, TOKEN.idiv are NOT simplified here:
24133
+ // x op x is undefined when x = 0, so we cannot fold without knowing
24134
+ // that x is non-zero.
24135
+ case TOKEN.and:
24136
+ case TOKEN.or:
24137
+ return first;
24138
+ // x and x → x; x or x → x
24139
+ case TOKEN.min:
24140
+ case TOKEN.max:
24141
+ return first;
24142
+ // min(x,x) → x; max(x,x) → x
24143
+ case TOKEN.eq:
24144
+ case TOKEN.ge:
24145
+ case TOKEN.le:
24146
+ return new PsConstNode(true);
24147
+ case TOKEN.ne:
24148
+ case TOKEN.gt:
24149
+ case TOKEN.lt:
24150
+ return new PsConstNode(false);
24151
+ }
24152
+ }
24153
+ if (first.type === PS_NODE.const) {
24154
+ const b = first.value;
24155
+ switch (op) {
24156
+ case TOKEN.add:
24157
+ if (b === 0) {
24158
+ return second;
24159
+ }
24160
+ break;
24161
+ case TOKEN.sub:
24162
+ if (b === 0) {
24163
+ return second;
24164
+ }
24165
+ break;
24166
+ case TOKEN.mul:
24167
+ if (b === 1) {
24168
+ return second;
24169
+ }
24170
+ if (b === 0) {
24171
+ return first;
24172
+ }
24173
+ if (b === -1) {
24174
+ return this._makeUnary(TOKEN.neg, second);
24175
+ }
24176
+ break;
24177
+ case TOKEN.div:
24178
+ if (b !== 0) {
24179
+ return this._makeBinary(TOKEN.mul, new PsConstNode(1 / b), second);
24180
+ }
24181
+ break;
24182
+ case TOKEN.idiv:
24183
+ if (b === 1) {
24184
+ return second;
24185
+ }
24186
+ break;
24187
+ case TOKEN.exp:
24188
+ if (b === 1) {
24189
+ return second;
24190
+ }
24191
+ if (b === -1) {
24192
+ return this._makeBinary(TOKEN.div, second, new PsConstNode(1));
24193
+ }
24194
+ if (b === 0.5) {
24195
+ return this._makeUnary(TOKEN.sqrt, second);
24196
+ }
24197
+ if (b === 0.25) {
24198
+ const sqrtOnce = this._makeUnary(TOKEN.sqrt, second);
24199
+ return this._makeUnary(TOKEN.sqrt, sqrtOnce);
24200
+ }
24201
+ if (b === 2) {
24202
+ return this._makeBinary(TOKEN.mul, second, second);
24203
+ }
24204
+ if (b === 3) {
24205
+ return this._makeBinary(
24206
+ TOKEN.mul,
24207
+ this._makeBinary(TOKEN.mul, second, second),
24208
+ second
24209
+ );
24210
+ }
24211
+ if (b === 4) {
24212
+ const square = this._makeBinary(TOKEN.mul, second, second);
24213
+ return this._makeBinary(TOKEN.mul, square, square);
24214
+ }
24215
+ if (b === 0) {
24216
+ return new PsConstNode(1);
24217
+ }
24218
+ break;
24219
+ case TOKEN.and:
24220
+ if (b === true) {
24221
+ return second;
24222
+ }
24223
+ if (b === false) {
24224
+ return first;
24225
+ }
24226
+ break;
24227
+ case TOKEN.or:
24228
+ if (b === false) {
24229
+ return second;
24230
+ }
24231
+ if (b === true) {
24232
+ return first;
24233
+ }
24234
+ break;
24235
+ case TOKEN.min:
24236
+ if (second.type === PS_NODE.binary && second.op === TOKEN.max && second.first.type === PS_NODE.const && second.first.value >= b) {
24237
+ return first;
24238
+ }
24239
+ break;
24240
+ case TOKEN.max:
24241
+ if (second.type === PS_NODE.binary && second.op === TOKEN.min && second.first.type === PS_NODE.const && second.first.value <= b) {
24242
+ return first;
24243
+ }
24244
+ break;
24245
+ }
24246
+ }
24247
+ if (second.type === PS_NODE.const) {
24248
+ const a = second.value;
24249
+ switch (op) {
24250
+ case TOKEN.add:
24251
+ if (a === 0) {
24252
+ return first;
24253
+ }
24254
+ break;
24255
+ case TOKEN.sub:
24256
+ if (a === 0) {
24257
+ return this._makeUnary(TOKEN.neg, first);
24258
+ }
24259
+ break;
24260
+ case TOKEN.mul:
24261
+ if (a === 1) {
24262
+ return first;
24263
+ }
24264
+ if (a === 0) {
24265
+ return second;
24266
+ }
24267
+ if (a === -1) {
24268
+ return this._makeUnary(TOKEN.neg, first);
24269
+ }
24270
+ break;
24271
+ case TOKEN.and:
24272
+ if (a === true) {
24273
+ return first;
24274
+ }
24275
+ if (a === false) {
24276
+ return second;
24277
+ }
24278
+ break;
24279
+ case TOKEN.or:
24280
+ if (a === false) {
24281
+ return first;
24282
+ }
24283
+ if (a === true) {
24284
+ return second;
24285
+ }
24286
+ break;
24287
+ }
24288
+ }
24289
+ return new PsBinaryNode(
24290
+ op,
24291
+ first,
24292
+ second,
24293
+ _binaryValueType(op, first.valueType, second.valueType)
24294
+ );
24295
+ }
24296
+ /**
24297
+ * Create a unary tree node, applying optimizations eagerly:
24298
+ *
24299
+ * 1. Constant folding.
24300
+ * 2. not(comparison) → negated comparison: not(a eq b) → a ne b, etc.
24301
+ * 3. neg(a − b) → b − a.
24302
+ * 4. Double-negation: neg(neg(x)) → x, not(not(x)) → x.
24303
+ * 5. abs(neg(x)) → abs(x).
24304
+ * 6. Idempotent: f(f(x)) → f(x) for abs, ceiling, floor, round, etc.
24305
+ */
24306
+ _makeUnary(op, operand) {
24307
+ if (operand.type === PS_NODE.const) {
24308
+ const v = _evalUnaryConst(op, operand.value);
24309
+ if (v !== void 0) {
24310
+ return new PsConstNode(v);
24311
+ }
24312
+ }
24313
+ if (op === TOKEN.not && operand.type === PS_NODE.binary) {
24314
+ const negated = _PSStackToTree.#negatedComparison.get(operand.op);
24315
+ if (negated !== void 0) {
24316
+ return new PsBinaryNode(
24317
+ negated,
24318
+ operand.first,
24319
+ operand.second,
24320
+ PS_VALUE_TYPE.boolean
24321
+ );
24322
+ }
24323
+ }
24324
+ if (op === TOKEN.neg && operand.type === PS_NODE.binary && operand.op === TOKEN.sub) {
24325
+ return this._makeBinary(TOKEN.sub, operand.second, operand.first);
24326
+ }
24327
+ if (operand.type === PS_NODE.unary) {
24328
+ if (op === TOKEN.neg && operand.op === TOKEN.neg || op === TOKEN.not && operand.op === TOKEN.not) {
24329
+ return operand.operand;
24330
+ }
24331
+ if (op === TOKEN.abs && operand.op === TOKEN.neg) {
24332
+ return this._makeUnary(TOKEN.abs, operand.operand);
24333
+ }
24334
+ if (_PSStackToTree.#idempotentUnary.has(op) && op === operand.op) {
24335
+ return operand;
24336
+ }
24337
+ }
24338
+ return new PsUnaryNode(op, operand, _unaryValueType(op, operand.valueType));
24339
+ }
24340
+ /**
24341
+ * Create a ternary node, applying optimizations eagerly:
24342
+ *
24343
+ * 1. Constant condition — fold to the live branch.
24344
+ * 2. Identical branches — the condition is irrelevant, return either branch.
24345
+ * 3. Boolean branch constants — `cond ? true : false` → cond,
24346
+ * `cond ? false : true` → not(cond).
24347
+ * 4. Ternary → branchless min/max when the condition compares two numeric
24348
+ * expressions that are also the two branches.
24349
+ */
24350
+ _makeTernary(cond, then, otherwise) {
24351
+ if (cond.type === PS_NODE.const) {
24352
+ return cond.value ? then : otherwise;
24353
+ }
24354
+ if (_nodesEqual(then, otherwise)) {
24355
+ return then;
24356
+ }
24357
+ if (then.type === PS_NODE.const && otherwise.type === PS_NODE.const) {
24358
+ if (then.value === true && otherwise.value === false) {
24359
+ return cond;
24360
+ }
24361
+ if (then.value === false && otherwise.value === true) {
24362
+ return this._makeUnary(TOKEN.not, cond);
24363
+ }
24364
+ }
24365
+ if (cond.type === PS_NODE.binary) {
24366
+ const { op: cop, first: cf, second: cs } = cond;
24367
+ if (cop === TOKEN.gt || cop === TOKEN.ge) {
24368
+ if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
24369
+ return this._makeBinary(TOKEN.min, cf, cs);
24370
+ }
24371
+ if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
24372
+ return this._makeBinary(TOKEN.max, cf, cs);
24373
+ }
24374
+ } else if (cop === TOKEN.lt || cop === TOKEN.le) {
24375
+ if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
24376
+ return this._makeBinary(TOKEN.max, cf, cs);
24377
+ }
24378
+ if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
24379
+ return this._makeBinary(TOKEN.min, cf, cs);
24380
+ }
24381
+ }
24382
+ }
24383
+ return new PsTernaryNode(
24384
+ cond,
24385
+ then,
24386
+ otherwise,
24387
+ then.valueType === otherwise.valueType ? then.valueType : PS_VALUE_TYPE.unknown
24388
+ );
24389
+ }
24390
+ };
24391
+ var OP = {
24392
+ ARG: 0,
24393
+ // [ARG, idx]
24394
+ CONST: 1,
24395
+ // [CONST, val]
24396
+ STORE: 2,
24397
+ // [STORE, slot, min, max] clamp(pop()) → mem[slot]
24398
+ IF: 3,
24399
+ // [IF, target] jump when top-of-stack === 0
24400
+ JUMP: 4,
24401
+ // [JUMP, target] unconditional
24402
+ ABS: 5,
24403
+ NEG: 6,
24404
+ CEIL: 7,
24405
+ FLOOR: 8,
24406
+ ROUND: 9,
24407
+ // floor(x + 0.5)
24408
+ TRUNC: 10,
24409
+ NOT_B: 11,
24410
+ // boolean NOT
24411
+ NOT_N: 12,
24412
+ // bitwise NOT
24413
+ SQRT: 13,
24414
+ SIN: 14,
24415
+ // degrees in/out
24416
+ COS: 15,
24417
+ LN: 16,
24418
+ LOG10: 17,
24419
+ CVI: 18,
24420
+ SHIFT: 19,
24421
+ // [SHIFT, amount] +ve = left, −ve = right
24422
+ // Binary ops: second below, first on top; result = second OP first.
24423
+ ADD: 20,
24424
+ SUB: 21,
24425
+ MUL: 22,
24426
+ DIV: 23,
24427
+ // 0 when divisor is 0
24428
+ IDIV: 24,
24429
+ // 0 when divisor is 0
24430
+ MOD: 25,
24431
+ // 0 when divisor is 0
24432
+ POW: 26,
24433
+ EQ: 27,
24434
+ NE: 28,
24435
+ GT: 29,
24436
+ GE: 30,
24437
+ LT: 31,
24438
+ LE: 32,
24439
+ AND: 33,
24440
+ OR: 34,
24441
+ XOR: 35,
24442
+ ATAN: 36,
24443
+ // atan2(second, first) → degrees [0, 360)
24444
+ MIN: 37,
24445
+ MAX: 38,
24446
+ TEE_TMP: 39,
24447
+ // [TEE_TMP, slot] peek top of stack → tmp[slot], leave on stack
24448
+ LOAD_TMP: 40
24449
+ // [LOAD_TMP, slot] push tmp[slot]
24450
+ };
24451
+ var _DEG_TO_RAD = Math.PI / 180;
24452
+ var _RAD_TO_DEG = 180 / Math.PI;
24453
+ var PsJsCompiler = class {
24454
+ // Safe because JS is single-threaded.
24455
+ static #stack = new Float64Array(64);
24456
+ static #tmp = new Float64Array(64);
24457
+ constructor(domain, range) {
24458
+ this.nIn = domain.length >> 1;
24459
+ this.nOut = range.length >> 1;
24460
+ this.range = range;
24461
+ this.ir = [];
24462
+ this._tmpMap = /* @__PURE__ */ new Map();
24463
+ this._nextTmp = 0;
24464
+ }
24465
+ _compileNode(node) {
24466
+ if (node.shared) {
24467
+ const cached = this._tmpMap.get(node);
24468
+ if (cached !== void 0) {
24469
+ this.ir.push(OP.LOAD_TMP, cached);
24470
+ return true;
24471
+ }
24472
+ if (!this._compileNodeImpl(node)) {
24473
+ return false;
24474
+ }
24475
+ const slot = this._nextTmp++;
24476
+ this._tmpMap.set(node, slot);
24477
+ this.ir.push(OP.TEE_TMP, slot);
24478
+ return true;
24479
+ }
24480
+ return this._compileNodeImpl(node);
24481
+ }
24482
+ _compileNodeImpl(node) {
24483
+ switch (node.type) {
24484
+ case PS_NODE.arg:
24485
+ this.ir.push(OP.ARG, node.index);
24486
+ return true;
24487
+ case PS_NODE.const: {
24488
+ const v = node.value;
24489
+ this.ir.push(OP.CONST, typeof v === "boolean" ? Number(v) : v);
24490
+ return true;
24491
+ }
24492
+ case PS_NODE.unary:
24493
+ return this._compileUnary(node);
24494
+ case PS_NODE.binary:
24495
+ return this._compileBinary(node);
24496
+ case PS_NODE.ternary:
24497
+ return this._compileTernary(node);
24498
+ default:
24499
+ return false;
24500
+ }
24501
+ }
24502
+ _compileUnary(node) {
24503
+ const { op, operand, valueType } = node;
24504
+ if (op === TOKEN.cvr) {
24505
+ return this._compileNode(operand);
24506
+ }
24507
+ if (!this._compileNode(operand)) {
24508
+ return false;
24509
+ }
24510
+ switch (op) {
24511
+ case TOKEN.abs:
24512
+ this.ir.push(OP.ABS);
24513
+ break;
24514
+ case TOKEN.neg:
24515
+ this.ir.push(OP.NEG);
24516
+ break;
24517
+ case TOKEN.ceiling:
24518
+ this.ir.push(OP.CEIL);
24519
+ break;
24520
+ case TOKEN.floor:
24521
+ this.ir.push(OP.FLOOR);
24522
+ break;
24523
+ case TOKEN.round:
24524
+ this.ir.push(OP.ROUND);
24525
+ break;
24526
+ case TOKEN.truncate:
24527
+ this.ir.push(OP.TRUNC);
24528
+ break;
24529
+ case TOKEN.sqrt:
24530
+ this.ir.push(OP.SQRT);
24531
+ break;
24532
+ case TOKEN.sin:
24533
+ this.ir.push(OP.SIN);
24534
+ break;
24535
+ case TOKEN.cos:
24536
+ this.ir.push(OP.COS);
24537
+ break;
24538
+ case TOKEN.ln:
24539
+ this.ir.push(OP.LN);
24540
+ break;
24541
+ case TOKEN.log:
24542
+ this.ir.push(OP.LOG10);
24543
+ break;
24544
+ case TOKEN.cvi:
24545
+ this.ir.push(OP.CVI);
24546
+ break;
24547
+ case TOKEN.not:
24548
+ if (valueType === PS_VALUE_TYPE.boolean) {
24549
+ this.ir.push(OP.NOT_B);
24550
+ } else if (valueType === PS_VALUE_TYPE.numeric) {
24551
+ this.ir.push(OP.NOT_N);
24552
+ } else {
24553
+ return false;
24554
+ }
24555
+ break;
24556
+ default:
24557
+ return false;
24558
+ }
24559
+ return true;
24560
+ }
24561
+ _compileBinary(node) {
24562
+ const { op, first, second } = node;
24563
+ if (op === TOKEN.bitshift) {
24564
+ if (first.type !== PS_NODE.const || !Number.isInteger(first.value) || !this._compileNode(second)) {
24565
+ return false;
24566
+ }
24567
+ this.ir.push(OP.SHIFT, first.value);
24568
+ return true;
24569
+ }
24570
+ if (!this._compileNode(second) || !this._compileNode(first)) {
24571
+ return false;
24572
+ }
24573
+ switch (op) {
24574
+ case TOKEN.add:
24575
+ this.ir.push(OP.ADD);
24576
+ break;
24577
+ case TOKEN.sub:
24578
+ this.ir.push(OP.SUB);
24579
+ break;
24580
+ case TOKEN.mul:
24581
+ this.ir.push(OP.MUL);
24582
+ break;
24583
+ case TOKEN.div:
24584
+ this.ir.push(OP.DIV);
24585
+ break;
24586
+ case TOKEN.idiv:
24587
+ this.ir.push(OP.IDIV);
24588
+ break;
24589
+ case TOKEN.mod:
24590
+ this.ir.push(OP.MOD);
24591
+ break;
24592
+ case TOKEN.exp:
24593
+ this.ir.push(OP.POW);
24594
+ break;
24595
+ case TOKEN.eq:
24596
+ this.ir.push(OP.EQ);
24597
+ break;
24598
+ case TOKEN.ne:
24599
+ this.ir.push(OP.NE);
24600
+ break;
24601
+ case TOKEN.gt:
24602
+ this.ir.push(OP.GT);
24603
+ break;
24604
+ case TOKEN.ge:
24605
+ this.ir.push(OP.GE);
24606
+ break;
24607
+ case TOKEN.lt:
24608
+ this.ir.push(OP.LT);
24609
+ break;
24610
+ case TOKEN.le:
24611
+ this.ir.push(OP.LE);
24612
+ break;
24613
+ case TOKEN.and:
24614
+ this.ir.push(OP.AND);
24615
+ break;
24616
+ case TOKEN.or:
24617
+ this.ir.push(OP.OR);
24618
+ break;
24619
+ case TOKEN.xor:
24620
+ this.ir.push(OP.XOR);
24621
+ break;
24622
+ case TOKEN.atan:
24623
+ this.ir.push(OP.ATAN);
24624
+ break;
24625
+ case TOKEN.min:
24626
+ this.ir.push(OP.MIN);
24627
+ break;
24628
+ case TOKEN.max:
24629
+ this.ir.push(OP.MAX);
24630
+ break;
24631
+ default:
24632
+ return false;
24633
+ }
24634
+ return true;
24635
+ }
24636
+ _compileTernary(node) {
24637
+ if (!this._compileNode(node.cond)) {
24638
+ return false;
24639
+ }
24640
+ this.ir.push(OP.IF, 0);
24641
+ const ifPatch = this.ir.length - 1;
24642
+ if (!this._compileNode(node.then)) {
24643
+ return false;
24644
+ }
24645
+ this.ir.push(OP.JUMP, 0);
24646
+ const jumpPatch = this.ir.length - 1;
24647
+ this.ir[ifPatch] = this.ir.length;
24648
+ if (!this._compileNode(node.otherwise)) {
24649
+ return false;
24650
+ }
24651
+ this.ir[jumpPatch] = this.ir.length;
24652
+ return true;
24653
+ }
24654
+ compile(program) {
24655
+ const outputs = new PSStackToTree().evaluate(program, this.nIn);
24656
+ if (!outputs || outputs.length < this.nOut) {
24657
+ return null;
24658
+ }
24659
+ for (let i = 0; i < this.nOut; i++) {
24660
+ if (!this._compileNode(outputs[i])) {
24661
+ return null;
24662
+ }
24663
+ const min = this.range[i * 2];
24664
+ const max = this.range[i * 2 + 1];
24665
+ this.ir.push(OP.STORE, i, min, max);
24666
+ }
24667
+ return new Float64Array(this.ir);
24668
+ }
24669
+ static execute(ir, src, srcOffset, dest, destOffset) {
24670
+ let ip = 0, sp = 0;
24671
+ const n = ir.length;
24672
+ const stack = this.#stack;
24673
+ const tmp = this.#tmp;
24674
+ while (ip < n) {
24675
+ switch (ir[ip++] | 0) {
24676
+ case OP.ARG:
24677
+ stack[sp++] = src[srcOffset + (ir[ip++] | 0)];
24678
+ break;
24679
+ case OP.CONST:
24680
+ stack[sp++] = ir[ip++];
24681
+ break;
24682
+ case OP.STORE: {
24683
+ const slot = ir[ip++] | 0;
24684
+ const min = ir[ip++];
24685
+ const max = ir[ip++];
24686
+ dest[destOffset + slot] = MathClamp(stack[--sp], min, max);
24687
+ break;
24688
+ }
24689
+ case OP.IF: {
24690
+ const tgt = ir[ip++];
24691
+ if (stack[--sp] === 0) {
24692
+ ip = tgt;
24693
+ }
24694
+ break;
24695
+ }
24696
+ case OP.JUMP:
24697
+ ip = ir[ip];
24698
+ break;
24699
+ case OP.ABS:
24700
+ stack[sp - 1] = Math.abs(stack[sp - 1]);
24701
+ break;
24702
+ case OP.NEG:
24703
+ stack[sp - 1] = -stack[sp - 1];
24704
+ break;
24705
+ case OP.CEIL:
24706
+ stack[sp - 1] = Math.ceil(stack[sp - 1]);
24707
+ break;
24708
+ case OP.FLOOR:
24709
+ stack[sp - 1] = Math.floor(stack[sp - 1]);
24710
+ break;
24711
+ case OP.ROUND:
24712
+ stack[sp - 1] = Math.floor(stack[sp - 1] + 0.5);
24713
+ break;
24714
+ case OP.TRUNC:
24715
+ stack[sp - 1] = Math.trunc(stack[sp - 1]);
24716
+ break;
24717
+ case OP.NOT_B:
24718
+ stack[sp - 1] = stack[sp - 1] !== 0 ? 0 : 1;
24719
+ break;
24720
+ case OP.NOT_N:
24721
+ stack[sp - 1] = ~(stack[sp - 1] | 0);
24722
+ break;
24723
+ case OP.SQRT:
24724
+ stack[sp - 1] = Math.sqrt(stack[sp - 1]);
24725
+ break;
24726
+ case OP.SIN:
24727
+ stack[sp - 1] = Math.sin(stack[sp - 1] % 360 * _DEG_TO_RAD);
24728
+ break;
24729
+ case OP.COS:
24730
+ stack[sp - 1] = Math.cos(stack[sp - 1] % 360 * _DEG_TO_RAD);
24731
+ break;
24732
+ case OP.LN:
24733
+ stack[sp - 1] = Math.log(stack[sp - 1]);
24734
+ break;
24735
+ case OP.LOG10:
24736
+ stack[sp - 1] = Math.log10(stack[sp - 1]);
24737
+ break;
24738
+ case OP.CVI:
24739
+ stack[sp - 1] = Math.trunc(stack[sp - 1]) | 0;
24740
+ break;
24741
+ case OP.SHIFT: {
24742
+ const amt = ir[ip++];
24743
+ const v = stack[sp - 1] | 0;
24744
+ if (amt > 0) {
24745
+ stack[sp - 1] = v << amt;
24746
+ } else if (amt < 0) {
24747
+ stack[sp - 1] = v >> -amt;
24748
+ } else {
24749
+ stack[sp - 1] = v;
24750
+ }
24751
+ break;
24752
+ }
24753
+ case OP.ADD: {
24754
+ const b = stack[--sp];
24755
+ stack[sp - 1] += b;
24756
+ break;
24757
+ }
24758
+ case OP.SUB: {
24759
+ const b = stack[--sp];
24760
+ stack[sp - 1] -= b;
24761
+ break;
24762
+ }
24763
+ case OP.MUL: {
24764
+ const b = stack[--sp];
24765
+ stack[sp - 1] *= b;
24766
+ break;
24767
+ }
24768
+ case OP.DIV: {
24769
+ const b = stack[--sp];
24770
+ stack[sp - 1] = b !== 0 ? stack[sp - 1] / b : 0;
24771
+ break;
24772
+ }
24773
+ case OP.IDIV: {
24774
+ const b = stack[--sp];
24775
+ stack[sp - 1] = b !== 0 ? Math.trunc(stack[sp - 1] / b) : 0;
24776
+ break;
24777
+ }
24778
+ case OP.MOD: {
24779
+ const b = stack[--sp];
24780
+ stack[sp - 1] = b !== 0 ? stack[sp - 1] % b : 0;
24781
+ break;
24782
+ }
24783
+ case OP.POW: {
24784
+ const b = stack[--sp];
24785
+ stack[sp - 1] **= b;
24786
+ break;
24787
+ }
24788
+ case OP.EQ: {
24789
+ const b = stack[--sp];
24790
+ stack[sp - 1] = stack[sp - 1] === b ? 1 : 0;
24791
+ break;
24792
+ }
24793
+ case OP.NE: {
24794
+ const b = stack[--sp];
24795
+ stack[sp - 1] = stack[sp - 1] !== b ? 1 : 0;
24796
+ break;
24797
+ }
24798
+ case OP.GT: {
24799
+ const b = stack[--sp];
24800
+ stack[sp - 1] = stack[sp - 1] > b ? 1 : 0;
24801
+ break;
24802
+ }
24803
+ case OP.GE: {
24804
+ const b = stack[--sp];
24805
+ stack[sp - 1] = stack[sp - 1] >= b ? 1 : 0;
24806
+ break;
24807
+ }
24808
+ case OP.LT: {
24809
+ const b = stack[--sp];
24810
+ stack[sp - 1] = stack[sp - 1] < b ? 1 : 0;
24811
+ break;
24812
+ }
24813
+ case OP.LE: {
24814
+ const b = stack[--sp];
24815
+ stack[sp - 1] = stack[sp - 1] <= b ? 1 : 0;
24816
+ break;
24817
+ }
24818
+ case OP.AND: {
24819
+ const b = stack[--sp] | 0;
24820
+ stack[sp - 1] = (stack[sp - 1] | 0) & b;
24821
+ break;
24822
+ }
24823
+ case OP.OR: {
24824
+ const b = stack[--sp] | 0;
24825
+ stack[sp - 1] = stack[sp - 1] | 0 | b;
24826
+ break;
24827
+ }
24828
+ case OP.XOR: {
24829
+ const b = stack[--sp] | 0;
24830
+ stack[sp - 1] = (stack[sp - 1] | 0) ^ b;
24831
+ break;
24832
+ }
24833
+ case OP.ATAN: {
24834
+ const b = stack[--sp];
24835
+ const deg = Math.atan2(stack[sp - 1], b) * _RAD_TO_DEG;
24836
+ stack[sp - 1] = deg < 0 ? deg + 360 : deg;
24837
+ break;
24838
+ }
24839
+ case OP.MIN: {
24840
+ const b = stack[--sp];
24841
+ stack[sp - 1] = Math.min(stack[sp - 1], b);
24842
+ break;
24843
+ }
24844
+ case OP.MAX: {
24845
+ const b = stack[--sp];
24846
+ stack[sp - 1] = Math.max(stack[sp - 1], b);
24847
+ break;
24848
+ }
24849
+ case OP.TEE_TMP:
24850
+ tmp[ir[ip++] | 0] = stack[sp - 1];
24851
+ break;
24852
+ case OP.LOAD_TMP:
24853
+ stack[sp++] = tmp[ir[ip++] | 0];
24854
+ break;
24855
+ }
24856
+ }
24857
+ }
24858
+ };
24859
+ var PSStackBasedInterpreter = class {
24860
+ // Safe: JS is single-threaded.
24861
+ static #stack = new Float64Array(100);
24862
+ static #sp = 0;
24863
+ static #push(v) {
24864
+ if (this.#sp < this.#stack.length) {
24865
+ this.#stack[this.#sp++] = v;
24866
+ }
24867
+ }
24868
+ static #execOp(op) {
24869
+ const stack = this.#stack;
24870
+ switch (op) {
24871
+ case TOKEN.true:
24872
+ this.#push(1);
24873
+ break;
24874
+ case TOKEN.false:
24875
+ this.#push(0);
24876
+ break;
24877
+ case TOKEN.abs:
24878
+ stack[this.#sp - 1] = Math.abs(stack[this.#sp - 1]);
24879
+ break;
24880
+ case TOKEN.neg:
24881
+ stack[this.#sp - 1] = -stack[this.#sp - 1];
24882
+ break;
24883
+ case TOKEN.ceiling:
24884
+ stack[this.#sp - 1] = Math.ceil(stack[this.#sp - 1]);
24885
+ break;
24886
+ case TOKEN.floor:
24887
+ stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1]);
24888
+ break;
24889
+ case TOKEN.round:
24890
+ stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1] + 0.5);
24891
+ break;
24892
+ case TOKEN.truncate:
24893
+ stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]);
24894
+ break;
24895
+ case TOKEN.sqrt:
24896
+ stack[this.#sp - 1] = Math.sqrt(stack[this.#sp - 1]);
24897
+ break;
24898
+ case TOKEN.sin:
24899
+ stack[this.#sp - 1] = Math.sin(
24900
+ stack[this.#sp - 1] % 360 * _DEG_TO_RAD
24901
+ );
24902
+ break;
24903
+ case TOKEN.cos:
24904
+ stack[this.#sp - 1] = Math.cos(
24905
+ stack[this.#sp - 1] % 360 * _DEG_TO_RAD
24906
+ );
24907
+ break;
24908
+ case TOKEN.ln:
24909
+ stack[this.#sp - 1] = Math.log(stack[this.#sp - 1]);
24910
+ break;
24911
+ case TOKEN.log:
24912
+ stack[this.#sp - 1] = Math.log10(stack[this.#sp - 1]);
24913
+ break;
24914
+ case TOKEN.cvi:
24915
+ stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]) | 0;
24916
+ break;
24917
+ case TOKEN.cvr:
24918
+ break;
24919
+ // values are already f64
24920
+ case TOKEN.not: {
24921
+ const v = stack[this.#sp - 1];
24922
+ stack[this.#sp - 1] = v === 0 || v === 1 ? 1 - v : ~(v | 0);
24923
+ break;
24924
+ }
24925
+ case TOKEN.add: {
24926
+ const b = stack[--this.#sp];
24927
+ stack[this.#sp - 1] += b;
24928
+ break;
24929
+ }
24930
+ case TOKEN.sub: {
24931
+ const b = stack[--this.#sp];
24932
+ stack[this.#sp - 1] -= b;
24933
+ break;
24934
+ }
24935
+ case TOKEN.mul: {
24936
+ const b = stack[--this.#sp];
24937
+ stack[this.#sp - 1] *= b;
24938
+ break;
24939
+ }
24940
+ case TOKEN.div: {
24941
+ const b = stack[--this.#sp];
24942
+ stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] / b : 0;
24943
+ break;
24944
+ }
24945
+ case TOKEN.idiv: {
24946
+ const b = stack[--this.#sp];
24947
+ stack[this.#sp - 1] = b !== 0 ? Math.trunc(stack[this.#sp - 1] / b) : 0;
24948
+ break;
24949
+ }
24950
+ case TOKEN.mod: {
24951
+ const b = stack[--this.#sp];
24952
+ stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] % b : 0;
24953
+ break;
24954
+ }
24955
+ case TOKEN.exp: {
24956
+ const b = stack[--this.#sp];
24957
+ stack[this.#sp - 1] **= b;
24958
+ break;
24959
+ }
24960
+ case TOKEN.atan: {
24961
+ const dx = stack[--this.#sp];
24962
+ const deg = Math.atan2(stack[this.#sp - 1], dx) * _RAD_TO_DEG;
24963
+ stack[this.#sp - 1] = deg < 0 ? deg + 360 : deg;
24964
+ break;
24965
+ }
24966
+ case TOKEN.eq: {
24967
+ const b = stack[--this.#sp];
24968
+ stack[this.#sp - 1] = stack[this.#sp - 1] === b ? 1 : 0;
24969
+ break;
24970
+ }
24971
+ case TOKEN.ne: {
24972
+ const b = stack[--this.#sp];
24973
+ stack[this.#sp - 1] = stack[this.#sp - 1] !== b ? 1 : 0;
24974
+ break;
24975
+ }
24976
+ case TOKEN.gt: {
24977
+ const b = stack[--this.#sp];
24978
+ stack[this.#sp - 1] = stack[this.#sp - 1] > b ? 1 : 0;
24979
+ break;
24980
+ }
24981
+ case TOKEN.ge: {
24982
+ const b = stack[--this.#sp];
24983
+ stack[this.#sp - 1] = stack[this.#sp - 1] >= b ? 1 : 0;
24984
+ break;
24985
+ }
24986
+ case TOKEN.lt: {
24987
+ const b = stack[--this.#sp];
24988
+ stack[this.#sp - 1] = stack[this.#sp - 1] < b ? 1 : 0;
24989
+ break;
24990
+ }
24991
+ case TOKEN.le: {
24992
+ const b = stack[--this.#sp];
24993
+ stack[this.#sp - 1] = stack[this.#sp - 1] <= b ? 1 : 0;
24994
+ break;
24995
+ }
24996
+ case TOKEN.and: {
24997
+ const b = stack[--this.#sp] | 0;
24998
+ stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) & b;
24999
+ break;
25000
+ }
25001
+ case TOKEN.or: {
25002
+ const b = stack[--this.#sp] | 0;
25003
+ stack[this.#sp - 1] = stack[this.#sp - 1] | 0 | b;
25004
+ break;
25005
+ }
25006
+ case TOKEN.xor: {
25007
+ const b = stack[--this.#sp] | 0;
25008
+ stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) ^ b;
25009
+ break;
25010
+ }
25011
+ case TOKEN.bitshift: {
25012
+ const amt = stack[--this.#sp] | 0;
25013
+ const v = stack[this.#sp - 1] | 0;
25014
+ stack[this.#sp - 1] = amt > 0 ? v << amt : v >> -amt;
25015
+ break;
25016
+ }
25017
+ case TOKEN.min: {
25018
+ const b = stack[--this.#sp];
25019
+ stack[this.#sp - 1] = Math.min(stack[this.#sp - 1], b);
25020
+ break;
25021
+ }
25022
+ case TOKEN.max: {
25023
+ const b = stack[--this.#sp];
25024
+ stack[this.#sp - 1] = Math.max(stack[this.#sp - 1], b);
25025
+ break;
25026
+ }
25027
+ case TOKEN.dup:
25028
+ this.#push(stack[this.#sp - 1]);
25029
+ break;
25030
+ case TOKEN.exch: {
25031
+ const a = stack[--this.#sp];
25032
+ const b = stack[--this.#sp];
25033
+ this.#push(a);
25034
+ this.#push(b);
25035
+ break;
25036
+ }
25037
+ case TOKEN.pop:
25038
+ this.#sp--;
25039
+ break;
25040
+ case TOKEN.copy: {
25041
+ const n = Math.trunc(stack[--this.#sp]);
25042
+ const base = this.#sp - n;
25043
+ for (let k = 0; k < n; k++) {
25044
+ this.#push(stack[base + k]);
25045
+ }
25046
+ break;
25047
+ }
25048
+ case TOKEN.index: {
25049
+ const i = Math.trunc(stack[--this.#sp]);
25050
+ this.#push(stack[this.#sp - 1 - i]);
25051
+ break;
25052
+ }
25053
+ case TOKEN.roll: {
25054
+ const j = Math.trunc(stack[--this.#sp]);
25055
+ const n = Math.trunc(stack[--this.#sp]);
25056
+ if (n > 1 && j !== 0) {
25057
+ const mod = (j % n + n) % n;
25058
+ if (mod !== 0) {
25059
+ const base = this.#sp - n;
25060
+ const sub = stack.slice(base, this.#sp);
25061
+ for (let k = 0; k < n; k++) {
25062
+ stack[base + k] = sub[(k - mod + n) % n];
25063
+ }
25064
+ }
25065
+ }
25066
+ break;
25067
+ }
25068
+ }
25069
+ }
25070
+ static #execBlock(instructions) {
25071
+ for (const instr of instructions) {
25072
+ switch (instr.type) {
25073
+ case PS_NODE.number:
25074
+ this.#push(instr.value);
25075
+ break;
25076
+ case PS_NODE.operator:
25077
+ this.#execOp(instr.op);
25078
+ break;
25079
+ case PS_NODE.if:
25080
+ if (this.#stack[--this.#sp] !== 0) {
25081
+ this.#execBlock(instr.then.instructions);
25082
+ }
25083
+ break;
25084
+ case PS_NODE.ifelse:
25085
+ if (this.#stack[--this.#sp] !== 0) {
25086
+ this.#execBlock(instr.then.instructions);
25087
+ } else {
25088
+ this.#execBlock(instr.otherwise.instructions);
25089
+ }
25090
+ break;
25091
+ }
25092
+ }
25093
+ }
25094
+ /**
25095
+ * @param {import("./ast.js").PsProgram} program
25096
+ * @param {number[]} domain – flat [min0,max0, …]
25097
+ * @param {number[]} range – flat [min0,max0, …]
25098
+ * @returns {Function} – `(src, srcOffset, dest, destOffset) => void`
25099
+ */
25100
+ static build(program, domain, range) {
25101
+ const nIn = domain.length >> 1;
25102
+ const nOut = range.length >> 1;
25103
+ const { instructions } = program.body;
25104
+ return (src, srcOffset, dest, destOffset) => {
25105
+ this.#sp = 0;
25106
+ for (let i = 0; i < nIn; i++) {
25107
+ this.#push(src[srcOffset + i]);
25108
+ }
25109
+ this.#execBlock(instructions);
25110
+ const base = this.#sp - nOut;
25111
+ for (let i = 0; i < nOut; i++) {
25112
+ const v = base + i >= 0 ? this.#stack[base + i] : 0;
25113
+ dest[destOffset + i] = MathClamp(v, range[i * 2], range[i * 2 + 1]);
25114
+ }
25115
+ };
25116
+ }
25117
+ };
25118
+ function buildPostScriptJsFunction(source, domain, range, forceInterpreter = false) {
25119
+ const program = parsePostScriptFunction(source);
25120
+ const ir = !forceInterpreter && new PsJsCompiler(domain, range).compile(program);
25121
+ if (ir) {
25122
+ return (src, srcOffset, dest, destOffset) => {
25123
+ PsJsCompiler.execute(ir, src, srcOffset, dest, destOffset);
25124
+ };
25125
+ }
25126
+ return PSStackBasedInterpreter.build(program, domain, range);
25127
+ }
25128
+ var ShadingType = {
25129
+ FUNCTION_BASED: 1,
25130
+ AXIAL: 2,
25131
+ RADIAL: 3,
25132
+ FREE_FORM_MESH: 4,
25133
+ LATTICE_FORM_MESH: 5,
25134
+ COONS_PATCH_MESH: 6,
25135
+ TENSOR_PATCH_MESH: 7
25136
+ };
25137
+ var BaseShading = class _BaseShading {
25138
+ // A small number to offset the first/last color stops so we can insert ones
25139
+ // to support extend. Number.MIN_VALUE is too small and breaks the extend.
25140
+ static SMALL_NUMBER = 1e-6;
25141
+ constructor() {
25142
+ if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _BaseShading) {
25143
+ unreachable2("Cannot initialize BaseShading.");
25144
+ }
25145
+ }
25146
+ getIR() {
25147
+ unreachable2("Abstract method `getIR` called.");
25148
+ }
25149
+ };
25150
+ function meshUpdateBounds(self) {
25151
+ let minX = self.coords[0][0], minY = self.coords[0][1], maxX = minX, maxY = minY;
25152
+ for (let i = 1, ii = self.coords.length; i < ii; i++) {
25153
+ const x = self.coords[i][0], y = self.coords[i][1];
25154
+ minX = minX > x ? x : minX;
25155
+ minY = minY > y ? y : minY;
25156
+ maxX = maxX < x ? x : maxX;
25157
+ maxY = maxY < y ? y : maxY;
25158
+ }
25159
+ self.bounds = [minX, minY, maxX, maxY];
25160
+ }
25161
+ function meshPackData(self) {
25162
+ let i, j, ii;
25163
+ const coords = self.coords;
25164
+ const coordsPacked = new Float32Array(coords.length * 2);
25165
+ for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
25166
+ const xy = coords[i];
25167
+ coordsPacked[j++] = xy[0];
25168
+ coordsPacked[j++] = xy[1];
25169
+ }
25170
+ self.coords = coordsPacked;
25171
+ const colors = self.colors;
25172
+ const colorsPacked = new Uint8Array(colors.length * 4);
25173
+ for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
25174
+ const c = colors[i];
25175
+ colorsPacked[j++] = c[0];
25176
+ colorsPacked[j++] = c[1];
25177
+ colorsPacked[j++] = c[2];
25178
+ j++;
25179
+ }
25180
+ self.colors = colorsPacked;
25181
+ for (const figure of self.figures) {
25182
+ figure.coords = new Uint32Array(figure.coords);
25183
+ figure.colors = new Uint32Array(figure.colors);
25184
+ }
25185
+ }
25186
+ function buildMeshVertexData(coords, colors, figures) {
25187
+ let vertexCount = 0;
25188
+ for (const figure of figures) {
25189
+ if (figure.type === MeshFigureType.TRIANGLES) {
25190
+ vertexCount += figure.coords.length;
25191
+ } else if (figure.type === MeshFigureType.LATTICE) {
25192
+ const vpr = figure.verticesPerRow;
25193
+ vertexCount += (Math.floor(figure.coords.length / vpr) - 1) * (vpr - 1) * 6;
25194
+ }
25195
+ }
25196
+ const posData = new Float32Array(vertexCount * 2);
25197
+ const colData = new Uint8Array(vertexCount * 4);
25198
+ let pOff = 0, cOff = 0;
25199
+ const addVertex = (pi, ci) => {
25200
+ posData[pOff++] = coords[pi * 2];
25201
+ posData[pOff++] = coords[pi * 2 + 1];
25202
+ colData[cOff++] = colors[ci * 4];
25203
+ colData[cOff++] = colors[ci * 4 + 1];
25204
+ colData[cOff++] = colors[ci * 4 + 2];
25205
+ cOff++;
25206
+ };
25207
+ for (const figure of figures) {
25208
+ const ps = figure.coords;
25209
+ const cs = figure.colors;
25210
+ if (figure.type === MeshFigureType.TRIANGLES) {
25211
+ for (let i = 0, ii = ps.length; i < ii; i++) {
25212
+ addVertex(ps[i], cs[i]);
25213
+ }
25214
+ } else if (figure.type === MeshFigureType.LATTICE) {
25215
+ const vpr = figure.verticesPerRow;
25216
+ const rows = Math.floor(ps.length / vpr) - 1;
25217
+ const cols = vpr - 1;
25218
+ for (let i = 0; i < rows; i++) {
25219
+ let q = i * vpr;
25220
+ for (let j = 0; j < cols; j++, q++) {
25221
+ addVertex(ps[q], cs[q]);
25222
+ addVertex(ps[q + 1], cs[q + 1]);
25223
+ addVertex(ps[q + vpr], cs[q + vpr]);
25224
+ addVertex(ps[q + vpr + 1], cs[q + vpr + 1]);
25225
+ addVertex(ps[q + 1], cs[q + 1]);
25226
+ addVertex(ps[q + vpr], cs[q + vpr]);
25227
+ }
25228
+ }
25229
+ }
25230
+ }
25231
+ return { posData, colData, vertexCount };
25232
+ }
25233
+ var MeshStreamReader = class {
25234
+ constructor(stream, context) {
25235
+ this.stream = stream;
25236
+ this.context = context;
25237
+ this.buffer = 0;
25238
+ this.bufferLength = 0;
25239
+ const numComps = context.numComps;
25240
+ this.tmpCompsBuf = new Float32Array(numComps);
25241
+ const csNumComps = context.colorSpace.numComps;
25242
+ this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf;
25243
+ }
25244
+ get hasData() {
25245
+ if (this.stream.end) {
25246
+ return this.stream.pos < this.stream.end;
25247
+ }
25248
+ if (this.bufferLength > 0) {
25249
+ return true;
25250
+ }
25251
+ const nextByte = this.stream.getByte();
25252
+ if (nextByte < 0) {
25253
+ return false;
25254
+ }
25255
+ this.buffer = nextByte;
25256
+ this.bufferLength = 8;
25257
+ return true;
25258
+ }
25259
+ readBits(n) {
25260
+ const { stream } = this;
25261
+ let { buffer, bufferLength } = this;
25262
+ if (n === 32) {
25263
+ if (bufferLength === 0) {
25264
+ return stream.getInt32() >>> 0;
25265
+ }
25266
+ buffer = buffer << 24 | stream.getByte() << 16 | stream.getByte() << 8 | stream.getByte();
25267
+ const nextByte = stream.getByte();
25268
+ this.buffer = nextByte & (1 << bufferLength) - 1;
25269
+ return (buffer << 8 - bufferLength | (nextByte & 255) >> bufferLength) >>> 0;
25270
+ }
25271
+ if (n === 8 && bufferLength === 0) {
25272
+ return stream.getByte();
25273
+ }
25274
+ while (bufferLength < n) {
25275
+ buffer = buffer << 8 | stream.getByte();
25276
+ bufferLength += 8;
25277
+ }
25278
+ bufferLength -= n;
25279
+ this.bufferLength = bufferLength;
25280
+ this.buffer = buffer & (1 << bufferLength) - 1;
25281
+ return buffer >> bufferLength;
25282
+ }
25283
+ align() {
25284
+ this.buffer = 0;
25285
+ this.bufferLength = 0;
25286
+ }
25287
+ readFlag() {
25288
+ return this.readBits(this.context.bitsPerFlag);
25289
+ }
25290
+ readCoordinate() {
25291
+ const { bitsPerCoordinate, decode } = this.context;
25292
+ const xi = this.readBits(bitsPerCoordinate);
25293
+ const yi = this.readBits(bitsPerCoordinate);
25294
+ const scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 23283064365386963e-26;
25295
+ return [
25296
+ xi * scale * (decode[1] - decode[0]) + decode[0],
25297
+ yi * scale * (decode[3] - decode[2]) + decode[2]
25298
+ ];
25299
+ }
25300
+ readComponents() {
25301
+ const { bitsPerComponent, colorFn, colorSpace, decode, numComps } = this.context;
25302
+ const scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 23283064365386963e-26;
25303
+ const components = this.tmpCompsBuf;
25304
+ for (let i = 0, j = 4; i < numComps; i++, j += 2) {
25305
+ const ci = this.readBits(bitsPerComponent);
25306
+ components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j];
25307
+ }
25308
+ const color = this.tmpCsCompsBuf;
25309
+ colorFn?.(components, 0, color, 0);
25310
+ return colorSpace.getRgb(color, 0);
25311
+ }
25312
+ };
25313
+ var bCache = null;
25314
+ function getB(count) {
25315
+ if (bCache?.has(count)) return bCache.get(count);
25316
+ const values = Array.from({ length: count + 1 }, (_, i) => {
25317
+ const t = i / count, t_ = 1 - t;
25318
+ return new Float32Array([
25319
+ t_ ** 3,
25320
+ 3 * t * t_ ** 2,
25321
+ 3 * t ** 2 * t_,
25322
+ t ** 3
25323
+ ]);
25324
+ });
25325
+ (bCache ??= /* @__PURE__ */ new Map()).set(count, values);
25326
+ return values;
25327
+ }
25328
+ var MeshShading = class _MeshShading extends BaseShading {
25329
+ static MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;
25330
+ static MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;
25331
+ // Count of triangles per entire mesh bounds.
25332
+ static TRIANGLE_DENSITY = 20;
25333
+ constructor(shadingType, stream, context, rowVertices) {
25334
+ super();
25335
+ this.shadingType = shadingType;
25336
+ this.bbox = this.background = null;
25337
+ this.coords = [];
25338
+ this.colors = [];
25339
+ this.figures = [];
25340
+ const reader = new MeshStreamReader(stream, context);
25341
+ let patchMesh = false;
25342
+ switch (this.shadingType) {
25343
+ case ShadingType.FREE_FORM_MESH:
25344
+ this._decodeType4Shading(reader);
25345
+ break;
25346
+ case ShadingType.LATTICE_FORM_MESH:
25347
+ const verticesPerRow = rowVertices | 0;
25348
+ if (verticesPerRow < 2) {
25349
+ throw new FormatError("Invalid VerticesPerRow");
25350
+ }
25351
+ this._decodeType5Shading(reader, verticesPerRow);
25352
+ break;
25353
+ case ShadingType.COONS_PATCH_MESH:
25354
+ this._decodeType6Shading(reader);
25355
+ patchMesh = true;
25356
+ break;
25357
+ case ShadingType.TENSOR_PATCH_MESH:
25358
+ this._decodeType7Shading(reader);
25359
+ patchMesh = true;
25360
+ break;
25361
+ default:
25362
+ unreachable2("Unsupported mesh type.");
25363
+ break;
25364
+ }
25365
+ if (patchMesh) {
25366
+ this._updateBounds();
25367
+ for (let i = 0, ii = this.figures.length; i < ii; i++) {
25368
+ this._buildFigureFromPatch(i);
25369
+ }
25370
+ }
25371
+ this._updateBounds();
25372
+ this._packData();
25373
+ }
25374
+ _decodeType4Shading(reader) {
25375
+ const coords = this.coords;
25376
+ const colors = this.colors;
25377
+ const operators = [];
25378
+ const ps = [];
25379
+ let verticesLeft = 0;
25380
+ while (reader.hasData) {
25381
+ const f = reader.readFlag();
25382
+ const coord = reader.readCoordinate();
25383
+ const color = reader.readComponents();
25384
+ if (verticesLeft === 0) {
25385
+ if (!(0 <= f && f <= 2)) {
25386
+ throw new FormatError("Unknown type4 flag");
25387
+ }
25388
+ switch (f) {
25389
+ case 0:
25390
+ verticesLeft = 3;
25391
+ break;
25392
+ case 1:
25393
+ ps.push(ps.at(-2), ps.at(-1));
25394
+ verticesLeft = 1;
25395
+ break;
25396
+ case 2:
25397
+ ps.push(ps.at(-3), ps.at(-1));
25398
+ verticesLeft = 1;
25399
+ break;
25400
+ }
25401
+ operators.push(f);
25402
+ }
25403
+ ps.push(coords.length);
25404
+ coords.push(coord);
25405
+ colors.push(color);
25406
+ verticesLeft--;
25407
+ reader.align();
25408
+ }
25409
+ this.figures.push({
25410
+ type: MeshFigureType.TRIANGLES,
25411
+ coords: new Int32Array(ps),
25412
+ colors: new Int32Array(ps)
25413
+ });
25414
+ }
25415
+ _decodeType5Shading(reader, verticesPerRow) {
25416
+ const coords = this.coords;
25417
+ const colors = this.colors;
25418
+ const ps = [];
25419
+ while (reader.hasData) {
25420
+ const coord = reader.readCoordinate();
25421
+ const color = reader.readComponents();
25422
+ ps.push(coords.length);
25423
+ coords.push(coord);
25424
+ colors.push(color);
25425
+ }
25426
+ this.figures.push({
25427
+ type: MeshFigureType.LATTICE,
25428
+ coords: new Int32Array(ps),
25429
+ colors: new Int32Array(ps),
25430
+ verticesPerRow
25431
+ });
25432
+ }
25433
+ _decodeType6Shading(reader) {
25434
+ const coords = this.coords;
25435
+ const colors = this.colors;
25436
+ const ps = new Int32Array(16);
25437
+ const cs = new Int32Array(4);
25438
+ while (reader.hasData) {
25439
+ const f = reader.readFlag();
25440
+ if (!(0 <= f && f <= 3)) {
25441
+ throw new FormatError("Unknown type6 flag");
25442
+ }
25443
+ const pi = coords.length;
25444
+ for (let i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) {
25445
+ coords.push(reader.readCoordinate());
25446
+ }
25447
+ const ci = colors.length;
25448
+ for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
25449
+ colors.push(reader.readComponents());
25450
+ }
25451
+ let tmp1, tmp2, tmp3, tmp4;
25452
+ switch (f) {
25453
+ // prettier-ignore
25454
+ case 0:
25455
+ ps[12] = pi + 3;
25456
+ ps[13] = pi + 4;
25457
+ ps[14] = pi + 5;
25458
+ ps[15] = pi + 6;
25459
+ ps[8] = pi + 2;
25460
+ ps[11] = pi + 7;
25461
+ ps[4] = pi + 1;
25462
+ ps[7] = pi + 8;
25463
+ ps[0] = pi;
25464
+ ps[1] = pi + 11;
25465
+ ps[2] = pi + 10;
25466
+ ps[3] = pi + 9;
25467
+ cs[2] = ci + 1;
25468
+ cs[3] = ci + 2;
25469
+ cs[0] = ci;
25470
+ cs[1] = ci + 3;
25471
+ break;
25472
+ // prettier-ignore
25473
+ case 1:
25474
+ tmp1 = ps[12];
25475
+ tmp2 = ps[13];
25476
+ tmp3 = ps[14];
25477
+ tmp4 = ps[15];
25478
+ ps[12] = tmp4;
25479
+ ps[13] = pi + 0;
25480
+ ps[14] = pi + 1;
25481
+ ps[15] = pi + 2;
25482
+ ps[8] = tmp3;
25483
+ ps[11] = pi + 3;
25484
+ ps[4] = tmp2;
25485
+ ps[7] = pi + 4;
25486
+ ps[0] = tmp1;
25487
+ ps[1] = pi + 7;
25488
+ ps[2] = pi + 6;
25489
+ ps[3] = pi + 5;
25490
+ tmp1 = cs[2];
25491
+ tmp2 = cs[3];
25492
+ cs[2] = tmp2;
25493
+ cs[3] = ci;
25494
+ cs[0] = tmp1;
25495
+ cs[1] = ci + 1;
25496
+ break;
25497
+ // prettier-ignore
25498
+ case 2:
25499
+ tmp1 = ps[15];
25500
+ tmp2 = ps[11];
25501
+ ps[12] = ps[3];
25502
+ ps[13] = pi + 0;
25503
+ ps[14] = pi + 1;
25504
+ ps[15] = pi + 2;
25505
+ ps[8] = ps[7];
25506
+ ps[11] = pi + 3;
25507
+ ps[4] = tmp2;
25508
+ ps[7] = pi + 4;
25509
+ ps[0] = tmp1;
25510
+ ps[1] = pi + 7;
25511
+ ps[2] = pi + 6;
25512
+ ps[3] = pi + 5;
25513
+ tmp1 = cs[3];
25514
+ cs[2] = cs[1];
25515
+ cs[3] = ci;
25516
+ cs[0] = tmp1;
25517
+ cs[1] = ci + 1;
25518
+ break;
25519
+ // prettier-ignore
25520
+ case 3:
25521
+ ps[12] = ps[0];
25522
+ ps[13] = pi + 0;
25523
+ ps[14] = pi + 1;
25524
+ ps[15] = pi + 2;
25525
+ ps[8] = ps[1];
25526
+ ps[11] = pi + 3;
25527
+ ps[4] = ps[2];
25528
+ ps[7] = pi + 4;
25529
+ ps[0] = ps[3];
25530
+ ps[1] = pi + 7;
25531
+ ps[2] = pi + 6;
25532
+ ps[3] = pi + 5;
25533
+ cs[2] = cs[0];
25534
+ cs[3] = ci;
25535
+ cs[0] = cs[1];
25536
+ cs[1] = ci + 1;
25537
+ break;
25538
+ }
25539
+ ps[5] = coords.length;
25540
+ coords.push([
25541
+ (-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,
25542
+ (-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
25543
+ ]);
25544
+ ps[6] = coords.length;
25545
+ coords.push([
25546
+ (-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,
25547
+ (-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
25548
+ ]);
25549
+ ps[9] = coords.length;
25550
+ coords.push([
25551
+ (-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,
25552
+ (-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
25553
+ ]);
25554
+ ps[10] = coords.length;
25555
+ coords.push([
25556
+ (-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,
25557
+ (-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
25558
+ ]);
25559
+ this.figures.push({
25560
+ type: MeshFigureType.PATCH,
25561
+ coords: new Int32Array(ps),
25562
+ // making copies of ps and cs
25563
+ colors: new Int32Array(cs)
25564
+ });
25565
+ }
25566
+ }
25567
+ _decodeType7Shading(reader) {
25568
+ const coords = this.coords;
25569
+ const colors = this.colors;
25570
+ const ps = new Int32Array(16);
25571
+ const cs = new Int32Array(4);
25572
+ while (reader.hasData) {
25573
+ const f = reader.readFlag();
25574
+ if (!(0 <= f && f <= 3)) {
25575
+ throw new FormatError("Unknown type7 flag");
25576
+ }
25577
+ const pi = coords.length;
25578
+ for (let i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) {
25579
+ coords.push(reader.readCoordinate());
25580
+ }
25581
+ const ci = colors.length;
25582
+ for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
25583
+ colors.push(reader.readComponents());
25584
+ }
25585
+ let tmp1, tmp2, tmp3, tmp4;
25586
+ switch (f) {
25587
+ // prettier-ignore
25588
+ case 0:
25589
+ ps[12] = pi + 3;
25590
+ ps[13] = pi + 4;
25591
+ ps[14] = pi + 5;
25592
+ ps[15] = pi + 6;
25593
+ ps[8] = pi + 2;
25594
+ ps[9] = pi + 13;
25595
+ ps[10] = pi + 14;
25596
+ ps[11] = pi + 7;
25597
+ ps[4] = pi + 1;
25598
+ ps[5] = pi + 12;
25599
+ ps[6] = pi + 15;
25600
+ ps[7] = pi + 8;
25601
+ ps[0] = pi;
25602
+ ps[1] = pi + 11;
25603
+ ps[2] = pi + 10;
25604
+ ps[3] = pi + 9;
25605
+ cs[2] = ci + 1;
25606
+ cs[3] = ci + 2;
25607
+ cs[0] = ci;
25608
+ cs[1] = ci + 3;
25609
+ break;
25610
+ // prettier-ignore
25611
+ case 1:
25612
+ tmp1 = ps[12];
25613
+ tmp2 = ps[13];
25614
+ tmp3 = ps[14];
25615
+ tmp4 = ps[15];
25616
+ ps[12] = tmp4;
25617
+ ps[13] = pi + 0;
25618
+ ps[14] = pi + 1;
25619
+ ps[15] = pi + 2;
25620
+ ps[8] = tmp3;
25621
+ ps[9] = pi + 9;
25622
+ ps[10] = pi + 10;
25623
+ ps[11] = pi + 3;
25624
+ ps[4] = tmp2;
25625
+ ps[5] = pi + 8;
25626
+ ps[6] = pi + 11;
25627
+ ps[7] = pi + 4;
25628
+ ps[0] = tmp1;
25629
+ ps[1] = pi + 7;
25630
+ ps[2] = pi + 6;
25631
+ ps[3] = pi + 5;
25632
+ tmp1 = cs[2];
25633
+ tmp2 = cs[3];
25634
+ cs[2] = tmp2;
25635
+ cs[3] = ci;
25636
+ cs[0] = tmp1;
25637
+ cs[1] = ci + 1;
25638
+ break;
25639
+ // prettier-ignore
25640
+ case 2:
25641
+ tmp1 = ps[15];
25642
+ tmp2 = ps[11];
25643
+ ps[12] = ps[3];
25644
+ ps[13] = pi + 0;
25645
+ ps[14] = pi + 1;
25646
+ ps[15] = pi + 2;
25647
+ ps[8] = ps[7];
25648
+ ps[9] = pi + 9;
25649
+ ps[10] = pi + 10;
25650
+ ps[11] = pi + 3;
25651
+ ps[4] = tmp2;
25652
+ ps[5] = pi + 8;
25653
+ ps[6] = pi + 11;
25654
+ ps[7] = pi + 4;
25655
+ ps[0] = tmp1;
25656
+ ps[1] = pi + 7;
25657
+ ps[2] = pi + 6;
25658
+ ps[3] = pi + 5;
25659
+ tmp1 = cs[3];
25660
+ cs[2] = cs[1];
25661
+ cs[3] = ci;
25662
+ cs[0] = tmp1;
25663
+ cs[1] = ci + 1;
25664
+ break;
25665
+ // prettier-ignore
25666
+ case 3:
25667
+ ps[12] = ps[0];
25668
+ ps[13] = pi + 0;
25669
+ ps[14] = pi + 1;
25670
+ ps[15] = pi + 2;
25671
+ ps[8] = ps[1];
25672
+ ps[9] = pi + 9;
25673
+ ps[10] = pi + 10;
25674
+ ps[11] = pi + 3;
25675
+ ps[4] = ps[2];
25676
+ ps[5] = pi + 8;
25677
+ ps[6] = pi + 11;
25678
+ ps[7] = pi + 4;
25679
+ ps[0] = ps[3];
25680
+ ps[1] = pi + 7;
25681
+ ps[2] = pi + 6;
25682
+ ps[3] = pi + 5;
25683
+ cs[2] = cs[0];
25684
+ cs[3] = ci;
25685
+ cs[0] = cs[1];
25686
+ cs[1] = ci + 1;
25687
+ break;
25688
+ }
25689
+ this.figures.push({
25690
+ type: MeshFigureType.PATCH,
25691
+ coords: new Int32Array(ps),
25692
+ // making copies of ps and cs
25693
+ colors: new Int32Array(cs)
25694
+ });
25695
+ }
25696
+ }
25697
+ _buildFigureFromPatch(index) {
25698
+ const figure = this.figures[index];
25699
+ assert2(
25700
+ figure.type === MeshFigureType.PATCH,
25701
+ "Unexpected patch mesh figure"
25702
+ );
25703
+ const coords = this.coords, colors = this.colors;
25704
+ const pi = figure.coords;
25705
+ const ci = figure.colors;
25706
+ const figureMinX = Math.min(
25707
+ coords[pi[0]][0],
25708
+ coords[pi[3]][0],
25709
+ coords[pi[12]][0],
25710
+ coords[pi[15]][0]
25711
+ );
25712
+ const figureMinY = Math.min(
25713
+ coords[pi[0]][1],
25714
+ coords[pi[3]][1],
25715
+ coords[pi[12]][1],
25716
+ coords[pi[15]][1]
25717
+ );
25718
+ const figureMaxX = Math.max(
25719
+ coords[pi[0]][0],
25720
+ coords[pi[3]][0],
25721
+ coords[pi[12]][0],
25722
+ coords[pi[15]][0]
25723
+ );
25724
+ const figureMaxY = Math.max(
25725
+ coords[pi[0]][1],
25726
+ coords[pi[3]][1],
25727
+ coords[pi[12]][1],
25728
+ coords[pi[15]][1]
25729
+ );
25730
+ let splitXBy = Math.ceil(
25731
+ (figureMaxX - figureMinX) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[2] - this.bounds[0])
25732
+ );
25733
+ splitXBy = MathClamp(
25734
+ splitXBy,
25735
+ _MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
25736
+ _MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT
25737
+ );
25738
+ let splitYBy = Math.ceil(
25739
+ (figureMaxY - figureMinY) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[3] - this.bounds[1])
25740
+ );
25741
+ splitYBy = MathClamp(
25742
+ splitYBy,
25743
+ _MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
25744
+ _MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT
25745
+ );
25746
+ const verticesPerRow = splitXBy + 1;
25747
+ const figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
25748
+ const figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
25749
+ let k = 0;
25750
+ const cl = new Uint8Array(3), cr = new Uint8Array(3);
25751
+ const c0 = colors[ci[0]], c1 = colors[ci[1]], c2 = colors[ci[2]], c3 = colors[ci[3]];
25752
+ const bRow = getB(splitYBy), bCol = getB(splitXBy);
25753
+ for (let row = 0; row <= splitYBy; row++) {
25754
+ cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0;
25755
+ cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0;
25756
+ cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0;
25757
+ cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0;
25758
+ cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0;
25759
+ cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0;
25760
+ for (let col = 0; col <= splitXBy; col++, k++) {
25761
+ if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) {
25762
+ continue;
25763
+ }
25764
+ let x = 0, y = 0;
25765
+ let q = 0;
25766
+ for (let i = 0; i <= 3; i++) {
25767
+ for (let j = 0; j <= 3; j++, q++) {
25768
+ const m = bRow[row][i] * bCol[col][j];
25769
+ x += coords[pi[q]][0] * m;
25770
+ y += coords[pi[q]][1] * m;
25771
+ }
25772
+ }
25773
+ figureCoords[k] = coords.length;
25774
+ coords.push([x, y]);
25775
+ figureColors[k] = colors.length;
25776
+ const newColor = new Uint8Array(3);
25777
+ newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0;
25778
+ newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0;
25779
+ newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0;
25780
+ colors.push(newColor);
25781
+ }
25782
+ }
25783
+ figureCoords[0] = pi[0];
25784
+ figureColors[0] = ci[0];
25785
+ figureCoords[splitXBy] = pi[3];
25786
+ figureColors[splitXBy] = ci[1];
25787
+ figureCoords[verticesPerRow * splitYBy] = pi[12];
25788
+ figureColors[verticesPerRow * splitYBy] = ci[2];
25789
+ figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15];
25790
+ figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
25791
+ this.figures[index] = {
25792
+ type: MeshFigureType.LATTICE,
25793
+ coords: figureCoords,
25794
+ colors: figureColors,
25795
+ verticesPerRow
25796
+ };
25797
+ }
25798
+ _updateBounds() {
25799
+ meshUpdateBounds(this);
25800
+ }
25801
+ _packData() {
25802
+ meshPackData(this);
25803
+ }
25804
+ getIR() {
25805
+ const { posData, colData, vertexCount } = buildMeshVertexData(
25806
+ this.coords,
25807
+ this.colors,
25808
+ this.figures
25809
+ );
25810
+ return [
25811
+ "Mesh",
25812
+ this.shadingType,
25813
+ posData,
25814
+ colData,
25815
+ vertexCount,
25816
+ this.bounds,
25817
+ this.bbox,
25818
+ this.background
25819
+ ];
25820
+ }
25821
+ };
22515
25822
  var PdfError = class extends Error {
22516
25823
  constructor(code, message) {
22517
25824
  super(message);
@@ -25417,11 +28724,16 @@ function parseDictionaryStream(dictNode, lexer, bytes) {
25417
28724
  let streamEnd = streamStart;
25418
28725
  if (resolvedLength !== void 0 && resolvedLength >= 0 && streamStart + resolvedLength <= bytes.length) {
25419
28726
  const candidateEnd = streamStart + resolvedLength;
25420
- const tailSlice = bytes.subarray(candidateEnd, Math.min(bytes.length, candidateEnd + 32));
25421
- const tailStr = new TextDecoder("latin1").decode(tailSlice);
25422
- if (tailStr.includes("endstream")) {
28727
+ const tailLexer = new CosByteLexer(bytes, candidateEnd);
28728
+ let endToken;
28729
+ try {
28730
+ endToken = tailLexer.nextToken();
28731
+ } catch (error) {
28732
+ if (!(error instanceof PdfError) || error.code !== "E_PARSE") throw error;
28733
+ }
28734
+ if (endToken?.kind === "keyword" && endToken.value === "endstream") {
25423
28735
  rawStreamBytes = bytes.subarray(streamStart, candidateEnd);
25424
- streamEnd = candidateEnd + tailStr.indexOf("endstream") + "endstream".length;
28736
+ streamEnd = tailLexer.offset;
25425
28737
  }
25426
28738
  }
25427
28739
  if (!rawStreamBytes) {
@@ -33591,6 +36903,25 @@ var __webpack_exports__JpxImage = __webpack_exports__.JpxImage;
33591
36903
  var __webpack_exports__VerbosityLevel = __webpack_exports__.VerbosityLevel;
33592
36904
  var __webpack_exports__getVerbosityLevel = __webpack_exports__.getVerbosityLevel;
33593
36905
  var __webpack_exports__setVerbosityLevel = __webpack_exports__.setVerbosityLevel;
36906
+ function createCalibratedColorSpace(doc, family, parameters) {
36907
+ const dict = doc.resolveDict(parameters);
36908
+ const array = (key) => {
36909
+ const value = dict ? doc.resolveArray(dictGet(dict, key)) : void 0;
36910
+ return value?.items.map((item) => {
36911
+ const number = doc.resolve(item);
36912
+ return number?.kind === "number" ? number.value : 0;
36913
+ });
36914
+ };
36915
+ const whitePoint = array("WhitePoint") ?? [0.95047, 1, 1.08883];
36916
+ const blackPoint = array("BlackPoint");
36917
+ if (family === "CalGray") {
36918
+ const gamma = dict ? doc.resolve(dictGet(dict, "Gamma")) : void 0;
36919
+ return new CalGrayCS(whitePoint, blackPoint, gamma?.kind === "number" ? gamma.value : void 0);
36920
+ }
36921
+ if (family === "CalRGB") return new CalRGBCS(whitePoint, blackPoint, array("Gamma"), array("Matrix"));
36922
+ return new LabCS(whitePoint, blackPoint, array("Range"));
36923
+ }
36924
+ var cmykColorSpace = new DeviceCmykCS();
33594
36925
  function collectPageLeaves(doc, node, inheritedResources, out = [], visited = /* @__PURE__ */ new Set()) {
33595
36926
  if (!node) return out;
33596
36927
  if (node.kind === "ref") {
@@ -33679,7 +37010,7 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
33679
37010
  palette = lookupNode.bytes;
33680
37011
  }
33681
37012
  let resolvedBaseComp = baseInfo.components;
33682
- if (palette && (baseInfo.isLab || baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calRgbGamma !== void 0 || baseInfo.calGrayGamma !== void 0)) {
37013
+ if (palette && (baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calibrated !== void 0)) {
33683
37014
  const numEntries = Math.max(1, Math.min(hival + 1, Math.floor(palette.length / Math.max(1, baseInfo.components))));
33684
37015
  const rgbaPal = decodeSamplesToRgba(palette, numEntries, 1, 8, baseInfo);
33685
37016
  const rgbPal = new Uint8Array(numEntries * 3);
@@ -33709,74 +37040,21 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
33709
37040
  }
33710
37041
  return { colorSpace: "rgb", colorSpaceLabel: "icc", components: 3 };
33711
37042
  }
33712
- if (kindName === "CalGray") {
33713
- const calDict = doc.resolveDict(resolved.items[1]);
33714
- const gammaNode = calDict ? doc.resolve(dictGet(calDict, "Gamma")) : void 0;
33715
- const gamma = gammaNode?.kind === "number" && gammaNode.value > 0 ? gammaNode.value : 1;
33716
- return { colorSpace: "gray", colorSpaceLabel: "cal-gray", components: 1, calGrayGamma: gamma };
33717
- }
33718
- if (kindName === "CalRGB") {
33719
- const calDict = doc.resolveDict(resolved.items[1]);
33720
- const gammaArr = calDict ? doc.resolveArray(dictGet(calDict, "Gamma")) : void 0;
33721
- let calRgbGamma = [1, 1, 1];
33722
- if (gammaArr && gammaArr.items.length >= 3) {
33723
- const gNums = gammaArr.items.slice(0, 3).map((it) => {
33724
- const r = doc.resolve(it);
33725
- return r?.kind === "number" && r.value > 0 ? r.value : 1;
33726
- });
33727
- calRgbGamma = [gNums[0], gNums[1], gNums[2]];
33728
- }
33729
- const matArr = calDict ? doc.resolveArray(dictGet(calDict, "Matrix")) : void 0;
33730
- let calRgbMatrix;
33731
- if (matArr && matArr.items.length >= 9) {
33732
- calRgbMatrix = matArr.items.slice(0, 9).map((it) => {
33733
- const r = doc.resolve(it);
33734
- return r?.kind === "number" ? r.value : 0;
33735
- });
33736
- }
37043
+ if (kindName === "CalGray" || kindName === "CalRGB" || kindName === "Lab") {
37044
+ const calibrated = createCalibratedColorSpace(doc, kindName, resolved.items[1]);
33737
37045
  return {
33738
- colorSpace: "rgb",
33739
- colorSpaceLabel: "cal-rgb",
33740
- components: 3,
33741
- calRgbGamma,
33742
- calRgbMatrix
37046
+ colorSpace: kindName === "CalGray" ? "gray" : "rgb",
37047
+ colorSpaceLabel: kindName === "CalGray" ? "cal-gray" : kindName === "CalRGB" ? "cal-rgb" : "lab",
37048
+ components: kindName === "CalGray" ? 1 : 3,
37049
+ calibrated
33743
37050
  };
33744
37051
  }
33745
- if (kindName === "Lab") {
33746
- const labDict = doc.resolveDict(resolved.items[1]);
33747
- const rangeArr = labDict ? doc.resolveArray(dictGet(labDict, "Range")) : void 0;
33748
- let labRange = [-100, 100, -100, 100];
33749
- if (rangeArr && rangeArr.items.length >= 4) {
33750
- const nums = rangeArr.items.slice(0, 4).map((it) => {
33751
- const r = doc.resolve(it);
33752
- return r?.kind === "number" ? r.value : 0;
33753
- });
33754
- labRange = [nums[0], nums[1], nums[2], nums[3]];
33755
- }
33756
- return { colorSpace: "rgb", colorSpaceLabel: "lab", components: 3, isLab: true, labRange };
33757
- }
33758
37052
  if (kindName === "Separation" || kindName === "DeviceN") {
33759
37053
  const isDevN = kindName === "DeviceN";
33760
37054
  const namesArr = isDevN ? doc.resolveArray(resolved.items[1]) : void 0;
33761
37055
  const devNComponents = isDevN && namesArr ? Math.max(1, namesArr.items.length) : 1;
33762
37056
  const altInfo = resolveColorSpaceInfo(doc, resolved.items[2], resourcesDict);
33763
37057
  const altSpace = altInfo.colorSpace === "cmyk" ? "cmyk" : altInfo.colorSpace === "gray" ? "gray" : "rgb";
33764
- const fnResolved = doc.resolve(resolved.items[3]);
33765
- const fnDict = fnResolved?.kind === "stream" ? fnResolved.dict : fnResolved?.kind === "dict" ? fnResolved : void 0;
33766
- const ftNode = fnDict ? doc.resolve(dictGet(fnDict, "FunctionType")) : void 0;
33767
- const tintFunctionType = ftNode?.kind === "number" ? ftNode.value : 2;
33768
- const c0Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C0")) : void 0;
33769
- const c1Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C1")) : void 0;
33770
- const nNode = fnDict ? doc.resolve(dictGet(fnDict, "N")) : void 0;
33771
- const c0 = c0Arr ? c0Arr.items.map((it) => {
33772
- const r = doc.resolve(it);
33773
- return r?.kind === "number" ? r.value : 0;
33774
- }) : altSpace === "cmyk" ? [0, 0, 0, 0] : altSpace === "gray" ? [1] : [1, 1, 1];
33775
- const c1 = c1Arr ? c1Arr.items.map((it) => {
33776
- const r = doc.resolve(it);
33777
- return r?.kind === "number" ? r.value : 0;
33778
- }) : altSpace === "cmyk" ? [0, 0, 0, 1] : altSpace === "gray" ? [0] : [0, 0, 0];
33779
- const sepN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
33780
37058
  return {
33781
37059
  colorSpace: altSpace,
33782
37060
  colorSpaceLabel: isDevN ? "devn" : "sep",
@@ -33784,12 +37062,9 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
33784
37062
  isSeparation: !isDevN,
33785
37063
  isDeviceN: isDevN,
33786
37064
  separationAltSpace: altSpace,
33787
- separationC0: c0,
33788
- separationC1: c1,
33789
- separationN: sepN,
37065
+ alternateCalibrated: altInfo.calibrated,
33790
37066
  tintFunctionDoc: doc,
33791
- tintFunctionNode: resolved.items[3],
33792
- tintFunctionType
37067
+ tintFunctionNode: resolved.items[3]
33793
37068
  };
33794
37069
  }
33795
37070
  }
@@ -33939,141 +37214,55 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
33939
37214
  const rgba = new Uint8Array(width * height * 4);
33940
37215
  const pixelCount = width * height;
33941
37216
  if (csInfo.isSeparation || csInfo.isDeviceN) {
33942
- const c0 = csInfo.separationC0 ?? [1, 1, 1];
33943
- const c1 = csInfo.separationC1 ?? [0, 0, 0];
33944
- const expN = csInfo.separationN ?? 1;
33945
37217
  const alt = csInfo.separationAltSpace ?? "rgb";
33946
37218
  const numCh = Math.max(1, csInfo.components);
33947
37219
  const step = bpc === 16 ? 2 : 1;
33948
- const useGenericTintFn = csInfo.tintFunctionDoc !== void 0 && csInfo.tintFunctionNode !== void 0 && (csInfo.tintFunctionType === 0 || csInfo.tintFunctionType === 3 || csInfo.tintFunctionType === 4);
33949
37220
  for (let p = 0; p < pixelCount; p++) {
33950
37221
  const chVals = [];
33951
- let wSum = 0;
33952
37222
  for (let ch3 = 0; ch3 < numCh; ch3++) {
33953
37223
  const sRaw = (rawSamples[(p * numCh + ch3) * step] ?? 0) / 255;
33954
- const tRemapped = remapUnitSampleWithDecode(sRaw, ch3, decodePairs);
33955
- chVals.push(tRemapped);
33956
- wSum += Math.pow(Math.max(0, Math.min(1, tRemapped)), expN);
33957
- }
33958
- if (useGenericTintFn) {
33959
- const outComps = evalShadingFunctionToComponents(
33960
- csInfo.tintFunctionDoc,
33961
- csInfo.tintFunctionNode,
33962
- chVals
33963
- );
33964
- if (alt === "cmyk") {
33965
- const c = outComps[0] ?? 0;
33966
- const m = outComps[1] ?? 0;
33967
- const y = outComps[2] ?? 0;
33968
- const k = outComps[3] ?? 0;
33969
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, (1 - c) * (1 - k))) * 255);
33970
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, (1 - m) * (1 - k))) * 255);
33971
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, (1 - y) * (1 - k))) * 255);
33972
- } else if (alt === "gray") {
33973
- const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
33974
- rgba[p * 4] = gByte;
33975
- rgba[p * 4 + 1] = gByte;
33976
- rgba[p * 4 + 2] = gByte;
33977
- } else {
33978
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
33979
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
33980
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
33981
- }
33982
- rgba[p * 4 + 3] = 255;
33983
- continue;
37224
+ chVals.push(remapUnitSampleWithDecode(sRaw, ch3, decodePairs));
33984
37225
  }
33985
- const w = Math.max(0, Math.min(1, wSum));
33986
- if (alt === "cmyk") {
33987
- const c = (c0[0] ?? 0) + w * ((c1[0] ?? 0) - (c0[0] ?? 0));
33988
- const m = (c0[1] ?? 0) + w * ((c1[1] ?? 0) - (c0[1] ?? 0));
33989
- const y = (c0[2] ?? 0) + w * ((c1[2] ?? 0) - (c0[2] ?? 0));
33990
- const k = (c0[3] ?? 0) + w * ((c1[3] ?? 1) - (c0[3] ?? 0));
33991
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, (1 - c) * (1 - k))) * 255);
33992
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, (1 - m) * (1 - k))) * 255);
33993
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, (1 - y) * (1 - k))) * 255);
37226
+ const outComps = evalShadingFunctionToComponents(
37227
+ csInfo.tintFunctionDoc,
37228
+ csInfo.tintFunctionNode,
37229
+ chVals
37230
+ );
37231
+ if (csInfo.alternateCalibrated) {
37232
+ rgba.set(csInfo.alternateCalibrated.getRgb(outComps, 0), p * 4);
37233
+ } else if (alt === "cmyk") {
37234
+ rgba.set(cmykColorSpace.getRgb([outComps[0] ?? 0, outComps[1] ?? 0, outComps[2] ?? 0, outComps[3] ?? 0], 0), p * 4);
33994
37235
  } else if (alt === "gray") {
33995
- const gVal = (c0[0] ?? 1) + w * ((c1[0] ?? 0) - (c0[0] ?? 1));
33996
- const gByte = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
37236
+ const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
33997
37237
  rgba[p * 4] = gByte;
33998
37238
  rgba[p * 4 + 1] = gByte;
33999
37239
  rgba[p * 4 + 2] = gByte;
34000
37240
  } else {
34001
- const rVal = (c0[0] ?? 1) + w * ((c1[0] ?? 0) - (c0[0] ?? 1));
34002
- const gVal = (c0[1] ?? 1) + w * ((c1[1] ?? 0) - (c0[1] ?? 1));
34003
- const bVal = (c0[2] ?? 1) + w * ((c1[2] ?? 0) - (c0[2] ?? 1));
34004
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, rVal)) * 255);
34005
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
34006
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, bVal)) * 255);
37241
+ rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
37242
+ rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
37243
+ rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
34007
37244
  }
34008
37245
  rgba[p * 4 + 3] = 255;
34009
37246
  }
34010
- } else if (csInfo.isLab) {
34011
- const [amin, amax, bmin, bmax] = csInfo.labRange ?? [-100, 100, -100, 100];
34012
- const invF = (t) => t > 6 / 29 ? t * t * t : 3 * (6 / 29) * (6 / 29) * (t - 4 / 29);
34013
- const toSrgb = (u) => {
34014
- const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
34015
- return Math.round(Math.max(0, Math.min(1, c)) * 255);
34016
- };
37247
+ } else if (csInfo.calibrated?.name === "Lab") {
37248
+ const { amin, amax, bmin, bmax } = csInfo.calibrated;
37249
+ const step = bpc === 16 ? 2 : 1;
34017
37250
  for (let p = 0; p < pixelCount; p++) {
34018
- const s0 = (rawSamples[p * 3] ?? 0) / 255;
34019
- const s1 = (rawSamples[p * 3 + 1] ?? 128) / 255;
34020
- const s2 = (rawSamples[p * 3 + 2] ?? 128) / 255;
34021
- const L = s0 * 100;
34022
- if (L <= 0.01) {
34023
- rgba[p * 4] = 0;
34024
- rgba[p * 4 + 1] = 0;
34025
- rgba[p * 4 + 2] = 0;
34026
- rgba[p * 4 + 3] = 255;
34027
- continue;
34028
- }
34029
- const a = amin + s1 * (amax - amin);
34030
- const b = bmin + s2 * (bmax - bmin);
34031
- const fy = (L + 16) / 116;
34032
- const fx = fy + a / 500;
34033
- const fz = fy - b / 200;
34034
- const X = 0.95047 * invF(fx);
34035
- const Y = 1 * invF(fy);
34036
- const Z = 1.08883 * invF(fz);
34037
- const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
34038
- const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
34039
- const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
34040
- rgba[p * 4] = toSrgb(linR);
34041
- rgba[p * 4 + 1] = toSrgb(linG);
34042
- rgba[p * 4 + 2] = toSrgb(linB);
37251
+ const L = (rawSamples[p * 3 * step] ?? 0) / 255 * 100;
37252
+ const a = amin + (rawSamples[(p * 3 + 1) * step] ?? 128) / 255 * (amax - amin);
37253
+ const b = bmin + (rawSamples[(p * 3 + 2) * step] ?? 128) / 255 * (bmax - bmin);
37254
+ rgba.set(csInfo.calibrated.getRgb([L, a, b], 0), p * 4);
34043
37255
  rgba[p * 4 + 3] = 255;
34044
37256
  }
34045
37257
  } else if (csInfo.colorSpace === "rgb") {
34046
- const hasCalRgb = Boolean(csInfo.calRgbGamma || csInfo.calRgbMatrix);
34047
- const toSrgbByte = (u) => {
34048
- const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
34049
- return Math.round(Math.max(0, Math.min(1, c)) * 255);
34050
- };
34051
37258
  const writeRgbPixel = (p, rByte, gByte, bByte) => {
34052
- let rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
34053
- let gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
34054
- let bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
34055
- if (hasCalRgb) {
34056
- const [gr, gg, gb] = csInfo.calRgbGamma ?? [1, 1, 1];
34057
- const ag = Math.pow(rU, gr);
34058
- const bg = Math.pow(gU, gg);
34059
- const cg = Math.pow(bU, gb);
34060
- if (csInfo.calRgbMatrix && csInfo.calRgbMatrix.length >= 9) {
34061
- const m = csInfo.calRgbMatrix;
34062
- const X = m[0] * ag + m[3] * bg + m[6] * cg;
34063
- const Y = m[1] * ag + m[4] * bg + m[7] * cg;
34064
- const Z = m[2] * ag + m[5] * bg + m[8] * cg;
34065
- const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
34066
- const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
34067
- const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
34068
- rgba[p * 4] = toSrgbByte(linR);
34069
- rgba[p * 4 + 1] = toSrgbByte(linG);
34070
- rgba[p * 4 + 2] = toSrgbByte(linB);
34071
- rgba[p * 4 + 3] = 255;
34072
- return;
34073
- }
34074
- rU = ag;
34075
- gU = bg;
34076
- bU = cg;
37259
+ const rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
37260
+ const gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
37261
+ const bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
37262
+ if (csInfo.calibrated) {
37263
+ rgba.set(csInfo.calibrated.getRgb([rU, gU, bU], 0), p * 4);
37264
+ rgba[p * 4 + 3] = 255;
37265
+ return;
34077
37266
  }
34078
37267
  rgba[p * 4] = Math.round(rU * 255);
34079
37268
  rgba[p * 4 + 1] = Math.round(gU * 255);
@@ -34093,10 +37282,11 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
34093
37282
  }
34094
37283
  } else if (csInfo.colorSpace === "gray") {
34095
37284
  const writeGrayPixel = (p, gByte) => {
34096
- let gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
34097
- if (csInfo.calGrayGamma && csInfo.calGrayGamma !== 1) {
34098
- const lin = Math.pow(gU, csInfo.calGrayGamma);
34099
- gU = lin <= 31308e-7 ? 12.92 * lin : 1.055 * Math.pow(lin, 1 / 2.4) - 0.055;
37285
+ const gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
37286
+ if (csInfo.calibrated) {
37287
+ rgba.set(csInfo.calibrated.getRgb([gU], 0), p * 4);
37288
+ rgba[p * 4 + 3] = 255;
37289
+ return;
34100
37290
  }
34101
37291
  const outG = Math.round(Math.max(0, Math.min(1, gU)) * 255);
34102
37292
  rgba[p * 4] = outG;
@@ -34152,9 +37342,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
34152
37342
  const m = remapUnitSampleWithDecode((rawSamples[p * stride + chStep] ?? 0) / 255, 1, decodePairs);
34153
37343
  const y = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 2] ?? 0) / 255, 2, decodePairs);
34154
37344
  const k = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 3] ?? 0) / 255, 3, decodePairs);
34155
- rgba[p * 4] = Math.round((1 - c) * (1 - k) * 255);
34156
- rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
34157
- rgba[p * 4 + 2] = Math.round((1 - y) * (1 - k) * 255);
37345
+ rgba.set(cmykColorSpace.getRgb([c, m, y, k], 0), p * 4);
34158
37346
  rgba[p * 4 + 3] = 255;
34159
37347
  }
34160
37348
  } else if (csInfo.colorSpace === "index") {
@@ -34192,9 +37380,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
34192
37380
  const m = pal[idx * 4 + 1] / 255;
34193
37381
  const yel = pal[idx * 4 + 2] / 255;
34194
37382
  const k = pal[idx * 4 + 3] / 255;
34195
- rgba[p * 4] = Math.round((1 - c) * (1 - k) * 255);
34196
- rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
34197
- rgba[p * 4 + 2] = Math.round((1 - yel) * (1 - k) * 255);
37383
+ rgba.set(cmykColorSpace.getRgb([c, m, yel, k], 0), p * 4);
34198
37384
  } else {
34199
37385
  rgba[p * 4] = pal[idx * baseComp];
34200
37386
  rgba[p * 4 + 1] = pal[idx * baseComp + 1];
@@ -34746,6 +37932,7 @@ function extractDocumentImages(doc, options = {}) {
34746
37932
  }
34747
37933
  return extracted;
34748
37934
  }
37935
+ var cmykColorSpace2 = new DeviceCmykCS();
34749
37936
  function multiplyMatrices(m1, m2) {
34750
37937
  return [
34751
37938
  m1[0] * m2[0] + m1[1] * m2[2],
@@ -34962,193 +38149,7 @@ function resolvePageFonts(doc, resourcesDict) {
34962
38149
  }
34963
38150
  return fonts;
34964
38151
  }
34965
- function evaluateType4PostScriptTokens(tokens, initialStack) {
34966
- const stack = [...initialStack];
34967
- const runRange = (start, end) => {
34968
- let i = start;
34969
- while (i < end) {
34970
- const tok = tokens[i];
34971
- if (tok === "{") {
34972
- let depth = 1;
34973
- let j = i + 1;
34974
- while (j < end && depth > 0) {
34975
- if (tokens[j] === "{") depth++;
34976
- else if (tokens[j] === "}") depth--;
34977
- j++;
34978
- }
34979
- const blockStart = i + 1;
34980
- const blockEnd = j - 1;
34981
- if (j < end && tokens[j] === "{") {
34982
- let depth2 = 1;
34983
- let k = j + 1;
34984
- while (k < end && depth2 > 0) {
34985
- if (tokens[k] === "{") depth2++;
34986
- else if (tokens[k] === "}") depth2--;
34987
- k++;
34988
- }
34989
- if (k < end && tokens[k] === "ifelse") {
34990
- const cond = stack.pop() ?? 0;
34991
- if (cond !== 0) runRange(blockStart, blockEnd);
34992
- else runRange(j + 1, k - 1);
34993
- i = k + 1;
34994
- continue;
34995
- }
34996
- }
34997
- if (j < end && tokens[j] === "if") {
34998
- const cond = stack.pop() ?? 0;
34999
- if (cond !== 0) runRange(blockStart, blockEnd);
35000
- i = j + 1;
35001
- continue;
35002
- }
35003
- runRange(blockStart, blockEnd);
35004
- i = j;
35005
- continue;
35006
- }
35007
- if (tok === "}") {
35008
- i++;
35009
- continue;
35010
- }
35011
- const numVal2 = Number(tok);
35012
- if (tok.length > 0 && !Number.isNaN(numVal2)) {
35013
- stack.push(numVal2);
35014
- } else if (tok === "true") {
35015
- stack.push(1);
35016
- } else if (tok === "false") {
35017
- stack.push(0);
35018
- } else if (tok === "add") {
35019
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35020
- stack.push(a + b);
35021
- } else if (tok === "sub") {
35022
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35023
- stack.push(a - b);
35024
- } else if (tok === "mul") {
35025
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35026
- stack.push(a * b);
35027
- } else if (tok === "div") {
35028
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
35029
- stack.push(Math.abs(b) > 1e-12 ? a / b : 0);
35030
- } else if (tok === "idiv") {
35031
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
35032
- stack.push(Math.abs(b) > 1e-12 ? Math.trunc(a / b) : 0);
35033
- } else if (tok === "mod") {
35034
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
35035
- stack.push(Math.abs(b) > 1e-12 ? a % b : 0);
35036
- } else if (tok === "neg") {
35037
- stack.push(-(stack.pop() ?? 0));
35038
- } else if (tok === "abs") {
35039
- stack.push(Math.abs(stack.pop() ?? 0));
35040
- } else if (tok === "ceiling") {
35041
- stack.push(Math.ceil(stack.pop() ?? 0));
35042
- } else if (tok === "floor") {
35043
- stack.push(Math.floor(stack.pop() ?? 0));
35044
- } else if (tok === "round") {
35045
- stack.push(Math.round(stack.pop() ?? 0));
35046
- } else if (tok === "truncate" || tok === "cvi") {
35047
- stack.push(Math.trunc(stack.pop() ?? 0));
35048
- } else if (tok === "sqrt") {
35049
- stack.push(Math.sqrt(Math.max(0, stack.pop() ?? 0)));
35050
- } else if (tok === "sin") {
35051
- stack.push(Math.sin((stack.pop() ?? 0) * Math.PI / 180));
35052
- } else if (tok === "cos") {
35053
- stack.push(Math.cos((stack.pop() ?? 0) * Math.PI / 180));
35054
- } else if (tok === "atan") {
35055
- const dx = stack.pop() ?? 1, dy = stack.pop() ?? 0;
35056
- let deg = Math.atan2(dy, dx) * 180 / Math.PI;
35057
- if (deg < 0) deg += 360;
35058
- stack.push(deg);
35059
- } else if (tok === "exp") {
35060
- const exp = stack.pop() ?? 1, base = stack.pop() ?? 0;
35061
- stack.push(Math.pow(base, exp));
35062
- } else if (tok === "ln") {
35063
- stack.push(Math.log(Math.max(1e-12, stack.pop() ?? 1)));
35064
- } else if (tok === "log") {
35065
- stack.push(Math.log10(Math.max(1e-12, stack.pop() ?? 1)));
35066
- } else if (tok === "dup") {
35067
- if (stack.length > 0) stack.push(stack[stack.length - 1]);
35068
- } else if (tok === "exch") {
35069
- if (stack.length >= 2) {
35070
- const b = stack.pop(), a = stack.pop();
35071
- stack.push(b, a);
35072
- }
35073
- } else if (tok === "pop") {
35074
- stack.pop();
35075
- } else if (tok === "copy") {
35076
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
35077
- const slice = stack.slice(Math.max(0, stack.length - n));
35078
- stack.push(...slice);
35079
- } else if (tok === "index") {
35080
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
35081
- const idx = stack.length - 1 - n;
35082
- if (idx >= 0 && idx < stack.length) stack.push(stack[idx]);
35083
- } else if (tok === "roll") {
35084
- const jShift = Math.trunc(stack.pop() ?? 0);
35085
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
35086
- if (n > 0 && stack.length >= n) {
35087
- const sub = stack.splice(stack.length - n, n);
35088
- const modShift = (jShift % n + n) % n;
35089
- const rolled = [...sub.slice(n - modShift), ...sub.slice(0, n - modShift)];
35090
- stack.push(...rolled);
35091
- }
35092
- } else if (tok === "eq") {
35093
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35094
- stack.push(Math.abs(a - b) < 1e-9 ? 1 : 0);
35095
- } else if (tok === "ne") {
35096
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35097
- stack.push(Math.abs(a - b) >= 1e-9 ? 1 : 0);
35098
- } else if (tok === "gt") {
35099
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35100
- stack.push(a > b ? 1 : 0);
35101
- } else if (tok === "ge") {
35102
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35103
- stack.push(a >= b ? 1 : 0);
35104
- } else if (tok === "lt") {
35105
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35106
- stack.push(a < b ? 1 : 0);
35107
- } else if (tok === "le") {
35108
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35109
- stack.push(a <= b ? 1 : 0);
35110
- } else if (tok === "and") {
35111
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35112
- stack.push(a !== 0 && b !== 0 ? 1 : 0);
35113
- } else if (tok === "or") {
35114
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
35115
- stack.push(a !== 0 || b !== 0 ? 1 : 0);
35116
- } else if (tok === "not") {
35117
- const a = stack.pop() ?? 0;
35118
- stack.push(a === 0 ? 1 : 0);
35119
- }
35120
- i++;
35121
- }
35122
- };
35123
- runRange(0, tokens.length);
35124
- return stack;
35125
- }
35126
- function tokenizePostScriptCode(bytes) {
35127
- const tokens = [];
35128
- let cur = "";
35129
- for (let i = 0; i < bytes.length; i++) {
35130
- const ch3 = String.fromCharCode(bytes[i]);
35131
- if (ch3 === "{" || ch3 === "}") {
35132
- if (cur.length > 0) {
35133
- tokens.push(cur);
35134
- cur = "";
35135
- }
35136
- tokens.push(ch3);
35137
- } else if (ch3 === " " || ch3 === " " || ch3 === "\n" || ch3 === "\r") {
35138
- if (cur.length > 0) {
35139
- tokens.push(cur);
35140
- cur = "";
35141
- }
35142
- } else {
35143
- cur += ch3;
35144
- }
35145
- }
35146
- if (cur.length > 0) tokens.push(cur);
35147
- if (tokens[0] === "{" && tokens[tokens.length - 1] === "}") {
35148
- return tokens.slice(1, -1);
35149
- }
35150
- return tokens;
35151
- }
38152
+ var postScriptFunctions = /* @__PURE__ */ new WeakMap();
35152
38153
  function evalShadingFunctionToComponents(doc, fnNode, inputs) {
35153
38154
  const inArr = typeof inputs === "number" ? [inputs] : inputs;
35154
38155
  const t = inArr[0] ?? 0;
@@ -35195,35 +38196,50 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
35195
38196
  const decode = getNums("Decode", range);
35196
38197
  const nOut = Math.max(1, Math.floor((decode.length || range.length || 6) / 2));
35197
38198
  const mIn = Math.max(1, size.length);
35198
- let flatGridIndex = 0;
38199
+ const streamBytes = doc.decodeStream(resolved);
38200
+ let vertices = [{ index: 0, weight: 1 }];
35199
38201
  let stride = 1;
35200
38202
  for (let i = 0; i < mIn; i++) {
35201
38203
  const d02 = dom[i * 2] ?? 0;
35202
38204
  const d12 = dom[i * 2 + 1] ?? 1;
35203
- const sMax = Math.max(1, (size[i] ?? 2) - 1);
38205
+ const sMax = Math.max(0, (size[i] ?? 2) - 1);
35204
38206
  const e0 = encode[i * 2] ?? 0;
35205
38207
  const e1 = encode[i * 2 + 1] ?? sMax;
35206
38208
  const x = Math.max(d02, Math.min(d12, inArr[i] ?? 0));
35207
- const u = Math.abs(d12 - d02) > 1e-8 ? (x - d02) / (d12 - d02) : 0;
35208
- const idx = Math.round(Math.max(0, Math.min(sMax, e0 + u * (e1 - e0))));
35209
- flatGridIndex += idx * stride;
38209
+ const u = d12 === d02 ? 0 : (x - d02) / (d12 - d02);
38210
+ const e = Math.max(0, Math.min(sMax, e0 + u * (e1 - e0)));
38211
+ const low = Math.floor(e), fraction = e - low;
38212
+ const next = [];
38213
+ for (const vertex of vertices) {
38214
+ const index = vertex.index + low * stride;
38215
+ if (index * nOut * bps < streamBytes.length * 8) next.push({ index, weight: vertex.weight * (1 - fraction) });
38216
+ if (fraction && (index + stride) * nOut * bps < streamBytes.length * 8) {
38217
+ next.push({ index: index + stride, weight: vertex.weight * fraction });
38218
+ }
38219
+ }
38220
+ vertices = next;
35210
38221
  stride *= size[i] ?? 2;
35211
38222
  }
35212
- const streamBytes = doc.decodeStream(resolved);
38223
+ const maxSample = 2 ** bps - 1;
38224
+ const readSample = (index) => {
38225
+ let bitOffset = index * bps, remaining = bps, value = 0;
38226
+ while (remaining > 0) {
38227
+ const bitInByte = bitOffset % 8;
38228
+ const take = Math.min(remaining, 8 - bitInByte);
38229
+ const byte = streamBytes[Math.floor(bitOffset / 8)] ?? 0;
38230
+ value = value * 2 ** take + (byte >> 8 - bitInByte - take & (1 << take) - 1);
38231
+ bitOffset += take;
38232
+ remaining -= take;
38233
+ }
38234
+ return value / maxSample;
38235
+ };
35213
38236
  const out2 = [];
35214
- const maxSample = bps === 16 ? 65535 : 255;
35215
38237
  for (let j = 0; j < nOut; j++) {
35216
- const sampleIdx = flatGridIndex * nOut + j;
35217
- let rawVal = 0;
35218
- if (bps === 16) {
35219
- rawVal = (streamBytes[sampleIdx * 2] ?? 0) << 8 | (streamBytes[sampleIdx * 2 + 1] ?? 0);
35220
- } else {
35221
- rawVal = streamBytes[sampleIdx] ?? 0;
35222
- }
35223
- const frac = rawVal / maxSample;
38238
+ let value = 0;
38239
+ for (const vertex of vertices) value += readSample(vertex.index * nOut + j) * vertex.weight;
35224
38240
  const dec0 = decode[j * 2] ?? 0;
35225
38241
  const dec1 = decode[j * 2 + 1] ?? 1;
35226
- out2.push(dec0 + frac * (dec1 - dec0));
38242
+ out2.push(dec0 + value * (dec1 - dec0));
35227
38243
  }
35228
38244
  return clampRange(out2);
35229
38245
  }
@@ -35233,34 +38249,40 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
35233
38249
  const d12 = dom[i * 2 + 1] ?? 1;
35234
38250
  return Math.max(d02, Math.min(d12, v));
35235
38251
  });
35236
- const tokens = tokenizePostScriptCode(doc.decodeStream(resolved));
35237
- const stackOut = evaluateType4PostScriptTokens(tokens, clampedInputs);
35238
- return clampRange(stackOut);
38252
+ const source = bytesToString3(doc.decodeStream(resolved));
38253
+ let cached = postScriptFunctions.get(resolved);
38254
+ 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])) {
38255
+ cached = { source, domain: dom, range, evaluate: buildPostScriptJsFunction(source, dom, range) };
38256
+ postScriptFunctions.set(resolved, cached);
38257
+ }
38258
+ const output = [];
38259
+ cached.evaluate(clampedInputs, 0, output, 0);
38260
+ return output;
35239
38261
  }
35240
38262
  if (ft === 3) {
35241
38263
  const fnsArr = doc.resolveArray(dictGet(fnDict, "Functions"));
35242
38264
  const bounds = getNums("Bounds", []);
35243
38265
  const encode = getNums("Encode", []);
35244
38266
  if (fnsArr && fnsArr.items.length > 0) {
38267
+ const input = Math.max(dom[0] ?? 0, Math.min(dom[1] ?? 1, t));
35245
38268
  let segIdx = 0;
35246
- while (segIdx < bounds.length && t >= bounds[segIdx]) segIdx++;
38269
+ while (segIdx < bounds.length && input >= bounds[segIdx]) segIdx++;
35247
38270
  segIdx = Math.min(fnsArr.items.length - 1, segIdx);
35248
38271
  const b0 = segIdx === 0 ? dom[0] ?? 0 : bounds[segIdx - 1];
35249
38272
  const b1 = segIdx < bounds.length ? bounds[segIdx] : dom[1] ?? 1;
35250
38273
  const e0 = encode[segIdx * 2] ?? 0;
35251
38274
  const e1 = encode[segIdx * 2 + 1] ?? 1;
35252
- const localT = Math.abs(b1 - b0) > 1e-8 ? e0 + (t - b0) / (b1 - b0) * (e1 - e0) : e0;
35253
- return evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], Math.max(0, Math.min(1, localT)));
38275
+ const localT = b1 !== b0 ? e0 + (input - b0) / (b1 - b0) * (e1 - e0) : e0;
38276
+ return clampRange(evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], localT));
35254
38277
  }
35255
38278
  }
35256
- const c0 = getNums("C0", [0, 0, 0]);
35257
- const c1 = getNums("C1", [1, 1, 1]);
38279
+ const c0 = getNums("C0", [0]);
38280
+ const c1 = getNums("C1", [1]);
35258
38281
  const nNode = doc.resolve(dictGet(fnDict, "N"));
35259
- const expN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
38282
+ const expN = nNode?.kind === "number" ? nNode.value : 1;
35260
38283
  const d0 = dom[0] ?? 0;
35261
38284
  const d1 = dom[1] ?? 1;
35262
- const normT = Math.abs(d1 - d0) > 1e-8 ? (t - d0) / (d1 - d0) : t;
35263
- const w = Math.pow(Math.max(0, Math.min(1, normT)), expN);
38285
+ const w = Math.pow(Math.max(d0, Math.min(d1, t)), expN);
35264
38286
  const len = Math.max(c0.length, c1.length);
35265
38287
  const out = [];
35266
38288
  for (let i = 0; i < len; i++) {
@@ -35276,30 +38298,14 @@ function shadingComponentsToRgb(csName, comps) {
35276
38298
  return [v, v, v];
35277
38299
  }
35278
38300
  if (csName === "DeviceCMYK" || csName === "CMYK" || comps.length >= 4) {
35279
- const cc = comps[0] ?? 0, cm = comps[1] ?? 0, cy = comps[2] ?? 0, ck = comps[3] ?? 0;
35280
- return [(1 - cc) * (1 - ck), (1 - cm) * (1 - kClamp(ck)), (1 - cy) * (1 - kClamp(ck))];
38301
+ const rgb2 = cmykColorSpace2.getRgb([comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0, comps[3] ?? 0], 0);
38302
+ return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
35281
38303
  }
35282
38304
  return [comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0];
35283
38305
  }
35284
38306
  function kClamp(v) {
35285
38307
  return Math.max(0, Math.min(1, v));
35286
38308
  }
35287
- function xyzToSrgb(X, Y, Z, Xw = 0.95047, Yw = 1, Zw = 1.08883) {
35288
- const scaleX = Xw > 1e-6 ? 0.95047 / Xw : 1;
35289
- const scaleY = Yw > 1e-6 ? 1 / Yw : 1;
35290
- const scaleZ = Zw > 1e-6 ? 1.08883 / Zw : 1;
35291
- const x = X * scaleX;
35292
- const y = Y * scaleY;
35293
- const z = Z * scaleZ;
35294
- const rl = 3.2404542 * x - 1.5371385 * y - 0.4985314 * z;
35295
- const gl = -0.969266 * x + 1.8760108 * y + 0.041556 * z;
35296
- const bl = 0.0556434 * x - 0.2040259 * y + 1.0572252 * z;
35297
- const toGamma = (u) => {
35298
- const c = Math.max(0, Math.min(1, u));
35299
- return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
35300
- };
35301
- return [toGamma(rl), toGamma(gl), toGamma(bl)];
35302
- }
35303
38309
  function getColorSpaceComponentCount(doc, csNode, activeResources, depth = 0) {
35304
38310
  if (!csNode || depth > 4) return 3;
35305
38311
  const resolved = doc ? doc.resolve(csNode) : csNode;
@@ -35356,63 +38362,10 @@ function convertColorSpaceComponentsToRgb(doc, csNode, csNameFallback, comps, ac
35356
38362
  if (resolved.kind === "array" && resolved.items.length > 0 && doc) {
35357
38363
  const familyNode = doc.resolve(resolved.items[0]);
35358
38364
  const family = familyNode?.kind === "name" ? familyNode.decoded : "";
35359
- if (family === "CalGray") {
35360
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
35361
- const gNode = paramDict ? doc.resolve(dictGet(paramDict, "Gamma")) : void 0;
35362
- const gamma = gNode?.kind === "number" && gNode.value > 0 ? gNode.value : 1;
35363
- const a = Math.pow(kClamp(comps[0] ?? 0), gamma);
35364
- return [a, a, a];
35365
- }
35366
- if (family === "CalRGB") {
35367
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
35368
- const gammaArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Gamma")) : void 0;
35369
- const getArrNum = (arr, idx, fb) => {
35370
- const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
35371
- return r?.kind === "number" ? r.value : fb;
35372
- };
35373
- const gr = getArrNum(gammaArr, 0, 1);
35374
- const gg = getArrNum(gammaArr, 1, 1);
35375
- const gb = getArrNum(gammaArr, 2, 1);
35376
- const ag = Math.pow(kClamp(comps[0] ?? 0), gr > 0 ? gr : 1);
35377
- const bg = Math.pow(kClamp(comps[1] ?? 0), gg > 0 ? gg : 1);
35378
- const cg = Math.pow(kClamp(comps[2] ?? 0), gb > 0 ? gb : 1);
35379
- const matArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Matrix")) : void 0;
35380
- if (matArr && matArr.items.length >= 9) {
35381
- const m = (i) => getArrNum(matArr, i, 0);
35382
- const X = m(0) * ag + m(3) * bg + m(6) * cg;
35383
- const Y = m(1) * ag + m(4) * bg + m(7) * cg;
35384
- const Z = m(2) * ag + m(5) * bg + m(8) * cg;
35385
- const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
35386
- const Xw = getArrNum(wpArr, 0, 0.95047);
35387
- const Yw = getArrNum(wpArr, 1, 1);
35388
- const Zw = getArrNum(wpArr, 2, 1.08883);
35389
- return xyzToSrgb(X, Y, Z, Xw, Yw, Zw);
35390
- }
35391
- return [ag, bg, cg];
35392
- }
35393
- if (family === "Lab") {
35394
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
35395
- const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
35396
- const rangeArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Range")) : void 0;
35397
- const getNum = (arr, idx, fb) => {
35398
- const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
35399
- return r?.kind === "number" ? r.value : fb;
35400
- };
35401
- const Xw = getNum(wpArr, 0, 0.95047);
35402
- const Yw = getNum(wpArr, 1, 1);
35403
- const Zw = getNum(wpArr, 2, 1.08883);
35404
- const amin = getNum(rangeArr, 0, -100);
35405
- const amax = getNum(rangeArr, 1, 100);
35406
- const bmin = getNum(rangeArr, 2, -100);
35407
- const bmax = getNum(rangeArr, 3, 100);
35408
- const Lstar = Math.max(0, Math.min(100, comps[0] ?? 0));
35409
- const astar = Math.max(amin, Math.min(amax, comps[1] ?? 0));
35410
- const bstar = Math.max(bmin, Math.min(bmax, comps[2] ?? 0));
35411
- const M = (Lstar + 16) / 116;
35412
- const L = M + astar / 500;
35413
- const N = M - bstar / 200;
35414
- const gFn = (x) => x >= 6 / 29 ? x * x * x : 108 / 841 * (x - 4 / 29);
35415
- return xyzToSrgb(Xw * gFn(L), Yw * gFn(M), Zw * gFn(N), Xw, Yw, Zw);
38365
+ if (family === "CalGray" || family === "CalRGB" || family === "Lab") {
38366
+ const colorSpace = createCalibratedColorSpace(doc, family, resolved.items[1]);
38367
+ const rgb2 = colorSpace.getRgb(comps, 0);
38368
+ return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
35416
38369
  }
35417
38370
  if (family === "ICCBased" && resolved.items[1]) {
35418
38371
  const iccNode = doc.resolve(resolved.items[1]);
@@ -35493,143 +38446,28 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
35493
38446
  const r = doc.resolve(it);
35494
38447
  return r?.kind === "number" ? r.value : 0;
35495
38448
  });
35496
- const xmin = decodeNums[0], xmax = decodeNums[1], ymin = decodeNums[2], ymax = decodeNums[3];
35497
- const numColorParams = Math.max(1, Math.floor((decodeNums.length - 4) / 2));
35498
38449
  const fnNode = dictGet(shDict, "Function");
35499
38450
  const csNode = doc.resolve(dictGet(shDict, "ColorSpace"));
35500
38451
  const csName = csNode?.kind === "name" ? csNode.decoded : "DeviceRGB";
35501
- let bitPos = 0;
35502
- const totalBits = bytes.length * 8;
35503
- const readBits = (n) => {
35504
- let val = 0;
35505
- for (let i = 0; i < n; i++) {
35506
- if (bitPos >= totalBits) return val;
35507
- const byteIdx = bitPos >> 3;
35508
- const bitIdx = 7 - (bitPos & 7);
35509
- val = val * 2 + (bytes[byteIdx] >> bitIdx & 1);
35510
- bitPos++;
35511
- }
35512
- return val;
35513
- };
35514
- const coordMax = Math.pow(2, bpcCoord) - 1 || 1;
35515
- const compMax = Math.pow(2, bpcComp) - 1 || 1;
35516
- const readCoord = () => {
35517
- const rx = readBits(bpcCoord) / coordMax;
35518
- const ry = readBits(bpcCoord) / coordMax;
35519
- return [xmin + rx * (xmax - xmin), ymin + ry * (ymax - ymin)];
35520
- };
35521
- const readColorRgb = () => {
35522
- const params = [];
35523
- for (let c = 0; c < numColorParams; c++) {
35524
- const rc = readBits(bpcComp) / compMax;
35525
- const cMin = decodeNums[4 + c * 2] ?? 0;
35526
- const cMax = decodeNums[4 + c * 2 + 1] ?? 1;
35527
- params.push(cMin + rc * (cMax - cMin));
35528
- }
35529
- const comps = fnNode ? evalShadingFunctionToComponents(doc, fnNode, params) : params;
35530
- return convertColorSpaceComponentsToRgb(doc, csNode, csName, comps);
35531
- };
35532
- const triangles = [];
35533
- if (shType === 4) {
35534
- const minBitsPerVert = bpcFlag + 2 * bpcCoord + numColorParams * bpcComp;
35535
- let triVerts;
35536
- while (bitPos + minBitsPerVert <= totalBits) {
35537
- const flag = readBits(bpcFlag) & 3;
35538
- const [x, y] = readCoord();
35539
- const rgb2 = readColorRgb();
35540
- const vNew = { x, y, rgb: rgb2 };
35541
- if (flag === 0 || !triVerts) {
35542
- if (bitPos + 2 * minBitsPerVert > totalBits) break;
35543
- readBits(bpcFlag);
35544
- const [x1, y1] = readCoord();
35545
- const rgb1 = readColorRgb();
35546
- readBits(bpcFlag);
35547
- const [x2, y2] = readCoord();
35548
- const rgb22 = readColorRgb();
35549
- triVerts = [vNew, { x: x1, y: y1, rgb: rgb1 }, { x: x2, y: y2, rgb: rgb22 }];
35550
- triangles.push(triVerts);
35551
- } else if (flag === 1) {
35552
- triVerts = [triVerts[1], triVerts[2], vNew];
35553
- triangles.push(triVerts);
35554
- } else if (flag === 2) {
35555
- triVerts = [triVerts[0], triVerts[2], vNew];
35556
- triangles.push(triVerts);
35557
- }
35558
- }
35559
- } else if (shType === 5) {
35560
- const minBitsPerVert = 2 * bpcCoord + numColorParams * bpcComp;
35561
- const verts = [];
35562
- while (bitPos + minBitsPerVert <= totalBits) {
35563
- const [x, y] = readCoord();
35564
- const rgb2 = readColorRgb();
35565
- verts.push({ x, y, rgb: rgb2 });
35566
- }
35567
- const numRows = Math.floor(verts.length / vPerRow);
35568
- for (let r = 0; r + 1 < numRows; r++) {
35569
- for (let c = 0; c + 1 < vPerRow; c++) {
35570
- const v00 = verts[r * vPerRow + c];
35571
- const v01 = verts[r * vPerRow + c + 1];
35572
- const v11 = verts[(r + 1) * vPerRow + c + 1];
35573
- const v10 = verts[(r + 1) * vPerRow + c];
35574
- triangles.push([v00, v01, v11], [v00, v11, v10]);
35575
- }
35576
- }
35577
- } else if (shType === 6 || shType === 7) {
35578
- const numCtrl = shType === 6 ? 12 : 16;
35579
- const minBitsPatch = bpcFlag + (numCtrl - 4) * 2 * bpcCoord + 2 * numColorParams * bpcComp;
35580
- let prevPts;
35581
- let prevColors;
35582
- while (bitPos + minBitsPatch <= totalBits) {
35583
- const flag = readBits(bpcFlag) & 3;
35584
- let pts = [];
35585
- let cols = [];
35586
- if (flag === 0 || !prevPts || !prevColors) {
35587
- for (let i = 0; i < numCtrl; i++) pts.push(readCoord());
35588
- for (let i = 0; i < 4; i++) cols.push(readColorRgb());
35589
- } else {
35590
- const extraCtrl = numCtrl - 4;
35591
- const readExtra = [];
35592
- for (let i = 0; i < extraCtrl; i++) readExtra.push(readCoord());
35593
- const c2 = readColorRgb();
35594
- const c3 = readColorRgb();
35595
- pts = [prevPts[3], prevPts[4], prevPts[5], prevPts[6], ...readExtra];
35596
- cols = [prevColors[1], prevColors[2], c2, c3];
35597
- }
35598
- prevPts = pts;
35599
- prevColors = cols;
35600
- const p00 = pts[0];
35601
- const p03 = pts[3];
35602
- const p33 = pts[6];
35603
- const p30 = pts[9];
35604
- const c00 = cols[0], c03 = cols[1], c33 = cols[2], c30 = cols[3];
35605
- const steps = 4;
35606
- const grid = [];
35607
- for (let iu = 0; iu <= steps; iu++) {
35608
- const u = iu / steps;
35609
- const row = [];
35610
- for (let iv = 0; iv <= steps; iv++) {
35611
- const v = iv / steps;
35612
- const x = (1 - u) * (1 - v) * p00[0] + (1 - u) * v * p03[0] + u * v * p33[0] + u * (1 - v) * p30[0];
35613
- const y = (1 - u) * (1 - v) * p00[1] + (1 - u) * v * p03[1] + u * v * p33[1] + u * (1 - v) * p30[1];
35614
- const r = (1 - u) * (1 - v) * c00[0] + (1 - u) * v * c03[0] + u * v * c33[0] + u * (1 - v) * c30[0];
35615
- const g = (1 - u) * (1 - v) * c00[1] + (1 - u) * v * c03[1] + u * v * c33[1] + u * (1 - v) * c30[1];
35616
- const b = (1 - u) * (1 - v) * c00[2] + (1 - u) * v * c03[2] + u * v * c33[2] + u * (1 - v) * c30[2];
35617
- row.push({ x, y, rgb: [r, g, b] });
35618
- }
35619
- grid.push(row);
35620
- }
35621
- for (let iu = 0; iu < steps; iu++) {
35622
- for (let iv = 0; iv < steps; iv++) {
35623
- const g00 = grid[iu][iv];
35624
- const g01 = grid[iu][iv + 1];
35625
- const g11 = grid[iu + 1][iv + 1];
35626
- const g10 = grid[iu + 1][iv];
35627
- triangles.push([g00, g01, g11], [g00, g11, g10]);
35628
- }
35629
- }
35630
- }
35631
- }
35632
- if (triangles.length === 0) return void 0;
38452
+ const numComps = fnNode ? 1 : getColorSpaceComponentCount(doc, csNode);
38453
+ const mesh = new MeshShading(shType, new Stream(bytes), {
38454
+ bitsPerCoordinate: bpcCoord,
38455
+ bitsPerComponent: bpcComp,
38456
+ bitsPerFlag: bpcFlag,
38457
+ decode: decodeNums,
38458
+ numComps,
38459
+ colorFn: null,
38460
+ colorSpace: {
38461
+ numComps,
38462
+ getRgb(components) {
38463
+ const params = Array.from(components);
38464
+ const values = fnNode ? evalShadingFunctionToComponents(doc, fnNode, params) : params;
38465
+ return new Uint8Array(convertColorSpaceComponentsToRgb(doc, csNode, csName, values).map((value) => Math.round(Math.max(0, Math.min(1, value)) * 255)));
38466
+ }
38467
+ }
38468
+ }, vPerRow);
38469
+ const [, , positions, colors, vertexCount] = mesh.getIR();
38470
+ if (vertexCount === 0) return void 0;
35633
38471
  const [bx0, by0, bx1, by1] = targetBox;
35634
38472
  const boxW = Math.max(1, bx1 - bx0);
35635
38473
  const boxH = Math.max(1, by1 - by0);
@@ -35641,10 +38479,10 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
35641
38479
  const [px, py] = transformPoint(effectiveCtm, vx, vy);
35642
38480
  return [(px - bx0) / boxW * imgW, (by1 - py) / boxH * imgH];
35643
38481
  };
35644
- for (const [v0, v1, v2] of triangles) {
35645
- const [x0, y0] = toImgCoords(v0.x, v0.y);
35646
- const [x1, y1] = toImgCoords(v1.x, v1.y);
35647
- const [x2, y2] = toImgCoords(v2.x, v2.y);
38482
+ for (let vertex = 0; vertex < vertexCount; vertex += 3) {
38483
+ const [x0, y0] = toImgCoords(positions[vertex * 2], positions[vertex * 2 + 1]);
38484
+ const [x1, y1] = toImgCoords(positions[vertex * 2 + 2], positions[vertex * 2 + 3]);
38485
+ const [x2, y2] = toImgCoords(positions[vertex * 2 + 4], positions[vertex * 2 + 5]);
35648
38486
  const denom = (y1 - y2) * (x0 - x2) + (x2 - x1) * (y0 - y2);
35649
38487
  if (Math.abs(denom) < 1e-6) continue;
35650
38488
  const minX = Math.max(0, Math.floor(Math.min(x0, x1, x2)));
@@ -35659,13 +38497,12 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
35659
38497
  const w1 = ((y2 - y0) * (px - x2) + (x0 - x2) * (py - y2)) / denom;
35660
38498
  const w2 = 1 - w0 - w1;
35661
38499
  if (w0 >= -1e-4 && w1 >= -1e-4 && w2 >= -1e-4) {
35662
- const r = w0 * v0.rgb[0] + w1 * v1.rgb[0] + w2 * v2.rgb[0];
35663
- const g = w0 * v0.rgb[1] + w1 * v1.rgb[1] + w2 * v2.rgb[1];
35664
- const b = w0 * v0.rgb[2] + w1 * v1.rgb[2] + w2 * v2.rgb[2];
35665
38500
  const pIdx = (iy * imgW + ix) * 4;
35666
- rgba[pIdx] = Math.round(Math.max(0, Math.min(1, r)) * 255);
35667
- rgba[pIdx + 1] = Math.round(Math.max(0, Math.min(1, g)) * 255);
35668
- rgba[pIdx + 2] = Math.round(Math.max(0, Math.min(1, b)) * 255);
38501
+ for (let channel = 0; channel < 3; channel++) {
38502
+ rgba[pIdx + channel] = Math.round(
38503
+ w0 * colors[vertex * 4 + channel] + w1 * colors[vertex * 4 + 4 + channel] + w2 * colors[vertex * 4 + 8 + channel]
38504
+ );
38505
+ }
35669
38506
  rgba[pIdx + 3] = a8;
35670
38507
  }
35671
38508
  }
@@ -35752,6 +38589,8 @@ function renderShadingDictToImage(doc, shDict, shadingCtm, targetBox, fillAlpha,
35752
38589
  const [a, b, c, d, e, f] = effectiveCtm;
35753
38590
  const det = a * d - b * c;
35754
38591
  if (Math.abs(det) <= 1e-8) return void 0;
38592
+ const [sa, sb, sc, sd, se, sf] = shadingCtm;
38593
+ const shadingDet = sa * sd - sb * sc;
35755
38594
  const t0Dom = shDomain[0] ?? 0;
35756
38595
  const t1Dom = shDomain[1] ?? 1;
35757
38596
  for (let iy = 0; iy < imgH; iy++) {
@@ -35762,8 +38601,10 @@ function renderShadingDictToImage(doc, shDict, shadingCtm, targetBox, fillAlpha,
35762
38601
  const dxPdf = xPdf - e;
35763
38602
  const xs = (d * dxPdf - c * dyPdf) / det;
35764
38603
  const ys = (-b * dxPdf + a * dyPdf) / det;
35765
- if (shBBox && (xs < shBBox[0] || xs > shBBox[2] || ys < shBBox[1] || ys > shBBox[3])) {
35766
- continue;
38604
+ if (shBBox) {
38605
+ const bboxX = (sd * (xPdf - se) - sc * (yPdf - sf)) / shadingDet;
38606
+ const bboxY = (-sb * (xPdf - se) + sa * (yPdf - sf)) / shadingDet;
38607
+ if (bboxX < shBBox[0] || bboxX > shBBox[2] || bboxY < shBBox[1] || bboxY > shBBox[3]) continue;
35767
38608
  }
35768
38609
  let comps;
35769
38610
  if (shType === 1) {
@@ -36063,7 +38904,8 @@ function evaluateContentStreamToDisplayList(params) {
36063
38904
  const shDict = shNode?.kind === "dict" ? shNode : shNode?.kind === "stream" ? shNode.dict : void 0;
36064
38905
  const shStream = shNode?.kind === "stream" ? shNode : void 0;
36065
38906
  if (shDict) {
36066
- const targetBox = st.clipRect ?? [0, 0, params.width, params.height];
38907
+ const [originX, originY] = params.origin ?? [0, 0];
38908
+ const targetBox = st.clipRect ?? [originX, originY, originX + params.width, originY + params.height];
36067
38909
  const img = renderShadingDictToImage(
36068
38910
  params.cosDoc,
36069
38911
  shDict,
@@ -36102,12 +38944,10 @@ function evaluateContentStreamToDisplayList(params) {
36102
38944
  } else if (operator === "RG" || operator === "SC" || operator === "SCN") {
36103
38945
  st.strokeColor = resolveScColorOperands(operator === "RG" ? "DeviceRGB" : st.strokeColorSpaceName, ops, activeResources);
36104
38946
  } else if (operator === "k") {
36105
- const c = num(0), m = num(1), y = num(2), k = num(3);
36106
- st.fillColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
38947
+ st.fillColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
36107
38948
  st.fillPatternName = void 0;
36108
38949
  } else if (operator === "K") {
36109
- const c = num(0), m = num(1), y = num(2), k = num(3);
36110
- st.strokeColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
38950
+ st.strokeColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
36111
38951
  } else if (operator === "gs" && params.cosDoc && activeResources && ops[0]?.kind === "name") {
36112
38952
  const extDict = params.cosDoc.resolveDict(dictGet(activeResources, "ExtGState"));
36113
38953
  const gsDict = extDict ? params.cosDoc.resolveDict(dictGet(extDict, ops[0].decoded)) : void 0;
@@ -36316,7 +39156,7 @@ function evaluateContentStreamToDisplayList(params) {
36316
39156
  stateStack.pop();
36317
39157
  capturedOperations = parentOperations;
36318
39158
  }
36319
- if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
39159
+ if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, isolated, bboxClip: nextClipPaths?.[0], blendMode: st.blendMode, clipRect: st.clipRect } });
36320
39160
  };
36321
39161
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
36322
39162
  for (const node of nodes) {
@@ -36900,6 +39740,7 @@ function evaluateContentStreamToDisplayList(params) {
36900
39740
  pageIndex: params.pageIndex,
36901
39741
  width: params.width,
36902
39742
  height: params.height,
39743
+ ...params.origin ? { origin: params.origin } : {},
36903
39744
  rotation: params.rotation ?? 0,
36904
39745
  glyphs,
36905
39746
  paths,
@@ -38370,7 +41211,7 @@ var PdfPage = class {
38370
41211
  return [n0.value, n1.value, n2.value, n3.value];
38371
41212
  }
38372
41213
  }
38373
- return [0, 0, 612, 792];
41214
+ return key === "MediaBox" ? [0, 0, 612, 792] : this.resolveBox("MediaBox");
38374
41215
  }
38375
41216
  getMediaBox() {
38376
41217
  return this.resolveBox("MediaBox");
@@ -39043,16 +41884,19 @@ var PdfPage = class {
39043
41884
  });
39044
41885
  }
39045
41886
  }
39046
- return evaluateContentStreamToDisplayList({
41887
+ const mediaBox = this.getMediaBox(), cropBox = this.getCropBox();
41888
+ const originX = Math.min(mediaBox[0], mediaBox[2]), originY = Math.min(mediaBox[1], mediaBox[3]);
41889
+ return { ...evaluateContentStreamToDisplayList({
39047
41890
  pageIndex: this.index,
39048
41891
  width,
39049
41892
  height,
41893
+ origin: [originX, originY],
39050
41894
  rotation: this.getRotation(),
39051
41895
  nodes: baseNodes,
39052
41896
  cosDoc: this.cosDoc,
39053
41897
  resourcesDict: evalResourcesDict,
39054
41898
  annotations: extractPageAnnotations(this.cosDoc, this.pageDict)
39055
- });
41899
+ }), cropBox: [cropBox[0] - originX, cropBox[1] - originY, cropBox[2] - originX, cropBox[3] - originY] };
39056
41900
  }
39057
41901
  extractPage(options) {
39058
41902
  const dl = this.evaluateDisplayList();
@@ -39070,10 +41914,10 @@ var PdfPage = class {
39070
41914
  return extractTablesFromDisplayList(this.evaluateDisplayList());
39071
41915
  }
39072
41916
  renderToBitmap(options) {
39073
- return renderDisplayListToBitmap(this.evaluateDisplayList(), options);
41917
+ return renderDisplayListToBitmap(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
39074
41918
  }
39075
41919
  renderToPng(options) {
39076
- return renderDisplayListToPng(this.evaluateDisplayList(), options);
41920
+ return renderDisplayListToPng(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
39077
41921
  }
39078
41922
  };
39079
41923
  function createStandardFontHandle(standardName) {
@@ -40277,7 +43121,7 @@ function prepareStroke(path, scale) {
40277
43121
  }
40278
43122
  return { matrix, width, dashArray, dashPhase };
40279
43123
  }
40280
- function strokeContours(path, pageHeight, scale) {
43124
+ function strokeContours(path, pageHeight, scale, originX = 0, originY = 0) {
40281
43125
  const stroke = prepareStroke(path, scale);
40282
43126
  if (!stroke) return [];
40283
43127
  const inverse = inverseStrokeMatrix(stroke.matrix);
@@ -40289,8 +43133,8 @@ function strokeContours(path, pageHeight, scale) {
40289
43133
  (inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
40290
43134
  ];
40291
43135
  const toScreen = ([x, y]) => [
40292
- (a * x / strokeScale + c * y / strokeScale + e) * scale,
40293
- (pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
43136
+ (a * x / strokeScale + c * y / strokeScale + e - originX) * scale,
43137
+ (pageHeight + originY - b * x / strokeScale - d * y / strokeScale - f) * scale
40294
43138
  ];
40295
43139
  const contours = strokeOutlines(
40296
43140
  segmentsToScreenPaths(path.segments, pageHeight, scale, project),
@@ -40448,18 +43292,34 @@ function renderSoftMask(mask, displayList, scale) {
40448
43292
  }
40449
43293
  return bitmap;
40450
43294
  }
40451
- function hasBlendModes(operations) {
40452
- return operations.some((operation) => !!operation.value.blendMode && operation.value.blendMode !== "Normal" && operation.value.blendMode !== "Compatible" || operation.kind === "group" && hasBlendModes(operation.value.operations));
43295
+ function getDisplayListCropBox(list) {
43296
+ const full = [0, 0, list.width, list.height];
43297
+ const box = list.cropBox;
43298
+ if (!box || !box.every(Number.isFinite)) return full;
43299
+ const x0 = Math.max(0, Math.min(box[0], box[2]));
43300
+ const y0 = Math.max(0, Math.min(box[1], box[3]));
43301
+ const x1 = Math.min(list.width, Math.max(box[0], box[2]));
43302
+ const y1 = Math.min(list.height, Math.max(box[1], box[3]));
43303
+ return x1 > x0 && y1 > y0 ? [x0, y0, x1, y1] : full;
43304
+ }
43305
+ function hasCompositingEffects(operations, includeSoftMasks = false) {
43306
+ 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));
43307
+ }
43308
+ function needsGroupBackdrop(group) {
43309
+ return group.isolated === false && !!group.softMask && hasCompositingEffects(group.operations, true);
40453
43310
  }
40454
43311
  function renderDisplayListToBitmap(displayList, options = {}) {
40455
43312
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
40456
43313
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
40457
43314
  const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
40458
43315
  const scale = scaleX;
43316
+ const [originX, originY] = displayList.origin ?? [0, 0];
43317
+ const pageTop = originY + displayList.height;
43318
+ const toScreen = (x, y) => [(x - originX) * scale, (pageTop - y) * scale];
40459
43319
  const width = Math.max(1, Math.round(displayList.width * scale));
40460
43320
  const height = Math.max(1, Math.round(displayList.height * scale));
40461
43321
  const rgba = new Uint8Array(width * height * 4);
40462
- const deferBackground = !options.transparent && hasBlendModes(paintOperations(displayList));
43322
+ const deferBackground = !options.transparent && hasCompositingEffects(paintOperations(displayList));
40463
43323
  const transparent = options.transparent || deferBackground;
40464
43324
  const bg = options.background ?? { r: 1, g: 1, b: 1 };
40465
43325
  const bgR = transparent ? 0 : Math.round(bg.r * 255);
@@ -40484,14 +43344,27 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40484
43344
  let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
40485
43345
  if (operation.kind === "group") {
40486
43346
  const group = operation.value;
40487
- const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations: group.operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, transparent: true });
43347
+ let operations = group.operations;
43348
+ if (needsGroupBackdrop(group)) {
43349
+ operations = [{ kind: "image", value: {
43350
+ name: "GroupBackdrop",
43351
+ width,
43352
+ height,
43353
+ decodedRgba: rgba.slice(),
43354
+ matrix: [width / scale, 0, 0, height / scale, originX, pageTop - height / scale],
43355
+ colorSpace: "DeviceRGB",
43356
+ bitsPerComponent: 8,
43357
+ ...group.bboxClip ? { clipPaths: [group.bboxClip] } : {}
43358
+ } }, ...operations];
43359
+ }
43360
+ const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, useCropBox: false, transparent: true });
40488
43361
  for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
40489
43362
  operation = { kind: "image", value: {
40490
43363
  name: "TransparencyGroup",
40491
43364
  width: bitmap.width,
40492
43365
  height: bitmap.height,
40493
43366
  decodedRgba: bitmap.data,
40494
- matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, 0, displayList.height - bitmap.height / scale],
43367
+ matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, originX, pageTop - bitmap.height / scale],
40495
43368
  colorSpace: "DeviceRGB",
40496
43369
  bitsPerComponent: 8,
40497
43370
  blendMode: group.blendMode,
@@ -40505,7 +43378,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40505
43378
  for (const clip of clips) {
40506
43379
  const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
40507
43380
  const layer = new Uint8Array(width * height * 4);
40508
- fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
43381
+ fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale, toScreen), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
40509
43382
  for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
40510
43383
  }
40511
43384
  cachedClips = clips;
@@ -40552,15 +43425,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40552
43425
  if (operation.kind === "path") {
40553
43426
  const path = operation.value;
40554
43427
  if (path.fillColor) {
40555
- const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale), true);
40556
- 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;
43428
+ const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale, toScreen), true);
43429
+ 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;
40557
43430
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
40558
43431
  }
40559
43432
  if (path.strokeColor) {
40560
43433
  const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
40561
43434
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
40562
- const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
40563
- 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;
43435
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale, originX, originY).map((points) => ({ points, closed: true })));
43436
+ 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;
40564
43437
  fillEdgesScanline4x4(
40565
43438
  rgba,
40566
43439
  width,
@@ -40583,12 +43456,12 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40583
43456
  if (Math.abs(det) <= 1e-8) continue;
40584
43457
  const cornersPdfX = [e, a + e, a + c + e, c + e];
40585
43458
  const cornersPdfY = [f, b + f, b + d + f, d + f];
40586
- const cornersPx = cornersPdfX.map((cx) => cx * scale);
40587
- const cornersPy = cornersPdfY.map((cy) => (displayList.height - cy) * scale);
40588
- const clipMinPx = img.clipRect ? Math.floor(img.clipRect[0] * scale) : 0;
40589
- const clipMaxPx = img.clipRect ? Math.ceil(img.clipRect[2] * scale) - 1 : width - 1;
40590
- const clipMinPy = img.clipRect ? Math.floor((displayList.height - img.clipRect[3]) * scale) : 0;
40591
- const clipMaxPy = img.clipRect ? Math.ceil((displayList.height - img.clipRect[1]) * scale) - 1 : height - 1;
43459
+ const cornersPx = cornersPdfX.map((cx) => (cx - originX) * scale);
43460
+ const cornersPy = cornersPdfY.map((cy) => (pageTop - cy) * scale);
43461
+ const clipMinPx = img.clipRect ? Math.floor((img.clipRect[0] - originX) * scale) : 0;
43462
+ const clipMaxPx = img.clipRect ? Math.ceil((img.clipRect[2] - originX) * scale) - 1 : width - 1;
43463
+ const clipMinPy = img.clipRect ? Math.floor((pageTop - img.clipRect[3]) * scale) : 0;
43464
+ const clipMaxPy = img.clipRect ? Math.ceil((pageTop - img.clipRect[1]) * scale) - 1 : height - 1;
40592
43465
  const minPx = Math.max(0, clipMinPx, Math.floor(Math.min(...cornersPx)));
40593
43466
  const maxPx = Math.min(width - 1, clipMaxPx, Math.ceil(Math.max(...cornersPx)) - 1);
40594
43467
  const minPy = Math.max(0, clipMinPy, Math.floor(Math.min(...cornersPy)));
@@ -40605,11 +43478,11 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40605
43478
  const smooth = Math.fround((s1 + s2 + Math.hypot(s1 - s2, 2 * cross)) / 2) <= 1;
40606
43479
  const sample = new Float64Array(4);
40607
43480
  for (let py = minPy; py <= maxPy; py++) {
40608
- const yPdf = displayList.height - (py + 0.5) / scale;
43481
+ const yPdf = pageTop - (py + 0.5) / scale;
40609
43482
  if (img.clipRect && (yPdf < img.clipRect[1] || yPdf > img.clipRect[3])) continue;
40610
43483
  const dyPdf = yPdf - f;
40611
43484
  for (let px = minPx; px <= maxPx; px++) {
40612
- const xPdf = (px + 0.5) / scale;
43485
+ const xPdf = originX + (px + 0.5) / scale;
40613
43486
  if (img.clipRect && (xPdf < img.clipRect[0] || xPdf > img.clipRect[2])) continue;
40614
43487
  const dxPdf = xPdf - e;
40615
43488
  const u = (d * dxPdf - c * dyPdf) / det;
@@ -40670,6 +43543,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
40670
43543
  }
40671
43544
  result = { width: targetW, height: targetH, data: resampled };
40672
43545
  }
43546
+ if (options.useCropBox) {
43547
+ const box = getDisplayListCropBox(displayList);
43548
+ result = cropRgbaBitmap(result, {
43549
+ x: box[0] * scaleX,
43550
+ y: (displayList.height - box[3]) * scaleY,
43551
+ width: (box[2] - box[0]) * scaleX,
43552
+ height: (box[3] - box[1]) * scaleY
43553
+ });
43554
+ }
40673
43555
  result = rotateRgbaBitmapQuarterTurns(result, displayList.rotation ?? 0);
40674
43556
  if (options.cropRect) {
40675
43557
  result = cropRgbaBitmap(result, options.cropRect);