@poe-platform/safe-bash 0.1.771 → 0.1.773

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/image-ast/index.browser.js +2801 -556
  2. package/dist/image-ast/index.js +2801 -556
  3. package/dist/pdf-ast/ast.d.ts +7 -0
  4. package/dist/pdf-ast/content/evaluator.d.ts +1 -0
  5. package/dist/pdf-ast/index.js +2845 -568
  6. package/dist/pdf-ast/render/raster.d.ts +1 -0
  7. package/dist/pdf-ast/vendor/pdfjs-fonts.d.mts +24 -0
  8. package/dist/pdf-ast/vendor/pdfjs-fonts.mjs +2621 -0
  9. package/dist/safe-bash/chunks/{chunk-FSH7QRIC.js → chunk-Z3HX3ZBA.js} +10 -4
  10. package/dist/safe-bash/command-chunks/{chunk-M2XU2YCK.js → chunk-5VXZSNM2.js} +2 -2
  11. package/dist/safe-bash/command-chunks/{chunk-C4AAJTXF.js → chunk-B2MM5DIT.js} +2804 -556
  12. package/dist/safe-bash/command-chunks/{chunk-NBENXODJ.js → chunk-G3NVK25P.js} +1 -1
  13. package/dist/safe-bash/commands/python/host-capabilities.js +15 -6
  14. package/dist/safe-bash/commands/python/index.browser.js +1 -1
  15. package/dist/safe-bash/core.browser.js +39 -39
  16. package/dist/safe-bash/core.d.ts +1 -1
  17. package/dist/safe-bash/plugins/composition.d.ts +2 -0
  18. package/dist/safe-bash/plugins/composition.js +2 -1
  19. package/dist/safe-bash-command-ffmpeg/index.js +10968 -9719
  20. package/dist/safe-bash-command-gh/index.d.ts +1 -0
  21. package/dist/safe-bash-command-gh/index.js +43 -13
  22. package/dist/safe-bash-command-gh/types.d.ts +1 -0
  23. package/dist/safe-bash-command-git/git_rust.wasm +0 -0
  24. package/dist/safe-bash-command-git/index.js +22 -15
  25. package/dist/safe-bash-command-git/wasm.generated.js +1 -1
  26. package/dist/safe-bash-command-imagemagick/index.js +2 -2
  27. package/dist/safe-bash-command-pandoc/command.js +3 -3
  28. package/dist/safe-bash-command-pandoc/index.js +3 -3
  29. package/dist/safe-bash-command-pdfimages/index.js +2800 -510
  30. package/dist/safe-bash-command-pdfinfo/index.js +2842 -568
  31. package/dist/safe-bash-command-pdftk/index.js +2800 -510
  32. package/dist/safe-bash-command-pdftoppm/index.js +2847 -637
  33. package/dist/safe-bash-command-pdftotext/index.js +2800 -510
  34. package/dist/safe-bash-command-qpdf/index.js +2800 -510
  35. package/dist/safe-bash-command-sips/index.js +2 -2
  36. package/dist/safe-bash-command-soffice/index.js +1 -1
  37. package/dist/safe-bash-command-ssconvert/index.js +2811 -566
  38. package/dist/safe-bash-command-wkhtmltopdf/index.js +2833 -510
  39. package/dist/safe-bash-mcp/index.d.ts +8 -2
  40. package/dist/safe-bash-mcp/index.js +13 -6
  41. package/package.json +7 -7
  42. package/third-party/pdf-ast/THIRD_PARTY_NOTICES.md +62 -1
@@ -30510,6 +30510,2614 @@ var getFontBasicMetrics = getLookupTableFactory(function(t) {
30510
30510
  xHeight: Math.NaN
30511
30511
  };
30512
30512
  });
30513
+ function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
30514
+ const COMPONENTS = 3;
30515
+ alpha01 = alpha01 !== 1 ? 0 : alpha01;
30516
+ const xRatio = w1 / w2;
30517
+ const yRatio = h1 / h2;
30518
+ let newIndex = 0, oldIndex;
30519
+ const xScaled = new Uint16Array(w2);
30520
+ const w1Scanline = w1 * COMPONENTS;
30521
+ for (let i = 0; i < w2; i++) {
30522
+ xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
30523
+ }
30524
+ for (let i = 0; i < h2; i++) {
30525
+ const py = Math.floor(i * yRatio) * w1Scanline;
30526
+ for (let j = 0; j < w2; j++) {
30527
+ oldIndex = py + xScaled[j];
30528
+ dest[newIndex++] = src[oldIndex++];
30529
+ dest[newIndex++] = src[oldIndex++];
30530
+ dest[newIndex++] = src[oldIndex++];
30531
+ newIndex += alpha01;
30532
+ }
30533
+ }
30534
+ }
30535
+ function isDefaultDecodeHelper(decode, expectedLen) {
30536
+ if (!Array.isArray(decode)) {
30537
+ return true;
30538
+ }
30539
+ const decodeLen = decode.length;
30540
+ if (decodeLen < expectedLen) {
30541
+ warn2("Decode map length is too short.");
30542
+ return true;
30543
+ }
30544
+ if (decodeLen > expectedLen) {
30545
+ info("Truncating too long decode map.");
30546
+ decode.length = expectedLen;
30547
+ }
30548
+ return false;
30549
+ }
30550
+ var ColorSpace = class _ColorSpace {
30551
+ static #rgbBuf = new Uint8ClampedArray(3);
30552
+ constructor(name, numComps) {
30553
+ if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _ColorSpace) {
30554
+ unreachable2("Cannot initialize ColorSpace.");
30555
+ }
30556
+ this.name = name;
30557
+ this.numComps = numComps;
30558
+ }
30559
+ /**
30560
+ * Converts the color value to the RGB color. The color components are
30561
+ * located in the src array starting from the srcOffset. Returns the array
30562
+ * of the rgb components, each value ranging from [0,255].
30563
+ */
30564
+ getRgb(src, srcOffset, output = new Uint8ClampedArray(3)) {
30565
+ this.getRgbItem(src, srcOffset, output, 0);
30566
+ return output;
30567
+ }
30568
+ getRgbHex(src, srcOffset) {
30569
+ const buffer = this.getRgb(src, srcOffset, _ColorSpace.#rgbBuf);
30570
+ return Util.makeHexColor(buffer[0], buffer[1], buffer[2]);
30571
+ }
30572
+ /**
30573
+ * Converts the color value to the RGB color, similar to the getRgb method.
30574
+ * The result placed into the dest array starting from the destOffset.
30575
+ */
30576
+ getRgbItem(src, srcOffset, dest, destOffset) {
30577
+ unreachable2("Should not call ColorSpace.getRgbItem");
30578
+ }
30579
+ /**
30580
+ * Converts the specified number of the color values to the RGB colors.
30581
+ * The colors are located in the src array starting from the srcOffset.
30582
+ * The result is placed into the dest array starting from the destOffset.
30583
+ * The src array items shall be in [0,2^bits) range, the dest array items
30584
+ * will be in [0,255] range. alpha01 indicates how many alpha components
30585
+ * there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
30586
+ * array).
30587
+ */
30588
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
30589
+ unreachable2("Should not call ColorSpace.getRgbBuffer");
30590
+ }
30591
+ /**
30592
+ * Converts `count` unscaled colors to RGB, starting at `destOffset`.
30593
+ * Components use the native color-space ranges expected by `getRgbItem`,
30594
+ * and each output has a `3 + alpha01` byte stride.
30595
+ * Subclasses may override this to batch expensive conversions.
30596
+ */
30597
+ getRgbItems(src, count, dest, destOffset, alpha01) {
30598
+ const { numComps } = this;
30599
+ for (let i = 0, srcOffset = 0; i < count; i++, srcOffset += numComps) {
30600
+ this.getRgbItem(src, srcOffset, dest, destOffset);
30601
+ destOffset += 3 + alpha01;
30602
+ }
30603
+ }
30604
+ /**
30605
+ * Returns true if source data will be equal the result/output data.
30606
+ */
30607
+ isPassthrough(bits) {
30608
+ return false;
30609
+ }
30610
+ /**
30611
+ * Refer to the static `ColorSpace.isDefaultDecode` method below.
30612
+ */
30613
+ isDefaultDecode(decode, bpc) {
30614
+ return _ColorSpace.isDefaultDecode(decode, this.numComps);
30615
+ }
30616
+ /**
30617
+ * Fills in the RGB colors in the destination buffer. alpha01 indicates
30618
+ * how many alpha components there are in the dest array; it will be either
30619
+ * 0 (RGB array) or 1 (RGBA array).
30620
+ */
30621
+ fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {
30622
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
30623
+ assert2(
30624
+ dest instanceof Uint8ClampedArray,
30625
+ 'ColorSpace.fillRgb: Unsupported "dest" type.'
30626
+ );
30627
+ }
30628
+ const count = originalWidth * originalHeight;
30629
+ let rgbBuf = null;
30630
+ const numComponentColors = 1 << bpc;
30631
+ const needsResizing = originalHeight !== height || originalWidth !== width;
30632
+ if (this.isPassthrough(bpc)) {
30633
+ rgbBuf = comps;
30634
+ } else if (this.numComps === 1 && count > numComponentColors && this.name !== "DeviceGray" && this.name !== "DeviceRGB") {
30635
+ const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);
30636
+ for (let i = 0; i < numComponentColors; i++) {
30637
+ allColors[i] = i;
30638
+ }
30639
+ const colorMap = new Uint8ClampedArray(numComponentColors * 3);
30640
+ this.getRgbBuffer(
30641
+ allColors,
30642
+ 0,
30643
+ numComponentColors,
30644
+ colorMap,
30645
+ 0,
30646
+ bpc,
30647
+ /* alpha01 = */
30648
+ 0
30649
+ );
30650
+ if (!needsResizing) {
30651
+ let destPos = 0;
30652
+ for (let i = 0; i < count; ++i) {
30653
+ const key = comps[i] * 3;
30654
+ dest[destPos++] = colorMap[key];
30655
+ dest[destPos++] = colorMap[key + 1];
30656
+ dest[destPos++] = colorMap[key + 2];
30657
+ destPos += alpha01;
30658
+ }
30659
+ } else {
30660
+ rgbBuf = new Uint8Array(count * 3);
30661
+ let rgbPos = 0;
30662
+ for (let i = 0; i < count; ++i) {
30663
+ const key = comps[i] * 3;
30664
+ rgbBuf[rgbPos++] = colorMap[key];
30665
+ rgbBuf[rgbPos++] = colorMap[key + 1];
30666
+ rgbBuf[rgbPos++] = colorMap[key + 2];
30667
+ }
30668
+ }
30669
+ } else if (!needsResizing) {
30670
+ this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);
30671
+ } else {
30672
+ rgbBuf = new Uint8ClampedArray(count * 3);
30673
+ this.getRgbBuffer(
30674
+ comps,
30675
+ 0,
30676
+ count,
30677
+ rgbBuf,
30678
+ 0,
30679
+ bpc,
30680
+ /* alpha01 = */
30681
+ 0
30682
+ );
30683
+ }
30684
+ if (rgbBuf) {
30685
+ if (needsResizing) {
30686
+ resizeRgbImage(
30687
+ rgbBuf,
30688
+ dest,
30689
+ originalWidth,
30690
+ originalHeight,
30691
+ width,
30692
+ height,
30693
+ alpha01
30694
+ );
30695
+ } else {
30696
+ let destPos = 0, rgbPos = 0;
30697
+ for (let i = 0, ii = width * actualHeight; i < ii; i++) {
30698
+ dest[destPos++] = rgbBuf[rgbPos++];
30699
+ dest[destPos++] = rgbBuf[rgbPos++];
30700
+ dest[destPos++] = rgbBuf[rgbPos++];
30701
+ destPos += alpha01;
30702
+ }
30703
+ }
30704
+ }
30705
+ }
30706
+ /**
30707
+ * True if the colorspace has components in the default range of [0, 1].
30708
+ * This should be true for all colorspaces except for lab color spaces
30709
+ * which are [0,100], [-128, 127], [-128, 127].
30710
+ */
30711
+ get usesZeroToOneRange() {
30712
+ return shadow2(this, "usesZeroToOneRange", true);
30713
+ }
30714
+ /**
30715
+ * Checks if a decode map matches the default decode map for a color space.
30716
+ * This handles the general decode maps where there are two values per
30717
+ * component, e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
30718
+ * This does not handle Lab, Indexed, or Pattern decode maps since they are
30719
+ * slightly different.
30720
+ * @param {Array} decode - Decode map (usually from an image).
30721
+ * @param {number} numComps - Number of components the color space has.
30722
+ */
30723
+ static isDefaultDecode(decode, numComps) {
30724
+ if (isDefaultDecodeHelper(decode, numComps * 2)) {
30725
+ return true;
30726
+ }
30727
+ for (let i = 0, ii = decode.length; i < ii; i += 2) {
30728
+ if (decode[i] !== 0 || decode[i + 1] !== 1) {
30729
+ return false;
30730
+ }
30731
+ }
30732
+ return true;
30733
+ }
30734
+ };
30735
+ var DeviceCmykCS = class extends ColorSpace {
30736
+ constructor() {
30737
+ super("DeviceCMYK", 4);
30738
+ }
30739
+ // The coefficients below was found using numerical analysis: the method of
30740
+ // steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
30741
+ // where color_value is the tabular value from the table of sampled RGB colors
30742
+ // from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
30743
+ // CMYK color conversion using the estimation below:
30744
+ // f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
30745
+ #toRgb(src, srcOffset, srcScale, dest, destOffset) {
30746
+ const c = src[srcOffset] * srcScale;
30747
+ const m = src[srcOffset + 1] * srcScale;
30748
+ const y = src[srcOffset + 2] * srcScale;
30749
+ const k = src[srcOffset + 3] * srcScale;
30750
+ 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);
30751
+ 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);
30752
+ 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);
30753
+ }
30754
+ getRgbItem(src, srcOffset, dest, destOffset) {
30755
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
30756
+ assert2(
30757
+ dest instanceof Uint8ClampedArray,
30758
+ 'DeviceCmykCS.getRgbItem: Unsupported "dest" type.'
30759
+ );
30760
+ }
30761
+ this.#toRgb(src, srcOffset, 1, dest, destOffset);
30762
+ }
30763
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
30764
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
30765
+ assert2(
30766
+ dest instanceof Uint8ClampedArray,
30767
+ 'DeviceCmykCS.getRgbBuffer: Unsupported "dest" type.'
30768
+ );
30769
+ }
30770
+ const scale = 1 / ((1 << bits) - 1);
30771
+ for (let i = 0; i < count; i++) {
30772
+ this.#toRgb(src, srcOffset, scale, dest, destOffset);
30773
+ srcOffset += 4;
30774
+ destOffset += 3 + alpha01;
30775
+ }
30776
+ }
30777
+ };
30778
+ var CalGrayCS = class extends ColorSpace {
30779
+ constructor(whitePoint, blackPoint, gamma) {
30780
+ super("CalGray", 1);
30781
+ if (!whitePoint) {
30782
+ throw new FormatError(
30783
+ "WhitePoint missing - required for color space CalGray"
30784
+ );
30785
+ }
30786
+ [this.XW, this.YW, this.ZW] = whitePoint;
30787
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
30788
+ this.G = gamma || 1;
30789
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
30790
+ throw new FormatError(
30791
+ `Invalid WhitePoint components for ${this.name}, no fallback available`
30792
+ );
30793
+ }
30794
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
30795
+ info(`Invalid BlackPoint for ${this.name}, falling back to default.`);
30796
+ this.XB = this.YB = this.ZB = 0;
30797
+ }
30798
+ if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
30799
+ warn2(
30800
+ `${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ZB: ${this.ZB}, only default values are supported.`
30801
+ );
30802
+ }
30803
+ if (this.G < 1) {
30804
+ info(
30805
+ `Invalid Gamma: ${this.G} for ${this.name}, falling back to default.`
30806
+ );
30807
+ this.G = 1;
30808
+ }
30809
+ }
30810
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
30811
+ const A = src[srcOffset] * scale;
30812
+ const AG = A ** this.G;
30813
+ const L = this.YW * AG;
30814
+ const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0);
30815
+ dest[destOffset] = val;
30816
+ dest[destOffset + 1] = val;
30817
+ dest[destOffset + 2] = val;
30818
+ }
30819
+ getRgbItem(src, srcOffset, dest, destOffset) {
30820
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
30821
+ assert2(
30822
+ dest instanceof Uint8ClampedArray,
30823
+ 'CalGrayCS.getRgbItem: Unsupported "dest" type.'
30824
+ );
30825
+ }
30826
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
30827
+ }
30828
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
30829
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
30830
+ assert2(
30831
+ dest instanceof Uint8ClampedArray,
30832
+ 'CalGrayCS.getRgbBuffer: Unsupported "dest" type.'
30833
+ );
30834
+ }
30835
+ const scale = 1 / ((1 << bits) - 1);
30836
+ for (let i = 0; i < count; ++i) {
30837
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
30838
+ srcOffset += 1;
30839
+ destOffset += 3 + alpha01;
30840
+ }
30841
+ }
30842
+ };
30843
+ var CalRGBCS = class _CalRGBCS extends ColorSpace {
30844
+ // See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these
30845
+ // matrices.
30846
+ // prettier-ignore
30847
+ static #BRADFORD_SCALE_MATRIX = new Float32Array([
30848
+ 0.8951,
30849
+ 0.2664,
30850
+ -0.1614,
30851
+ -0.7502,
30852
+ 1.7135,
30853
+ 0.0367,
30854
+ 0.0389,
30855
+ -0.0685,
30856
+ 1.0296
30857
+ ]);
30858
+ // prettier-ignore
30859
+ static #BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([
30860
+ 0.9869929,
30861
+ -0.1470543,
30862
+ 0.1599627,
30863
+ 0.4323053,
30864
+ 0.5183603,
30865
+ 0.0492912,
30866
+ -85287e-7,
30867
+ 0.0400428,
30868
+ 0.9684867
30869
+ ]);
30870
+ // See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html.
30871
+ // prettier-ignore
30872
+ static #SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([
30873
+ 3.2404542,
30874
+ -1.5371385,
30875
+ -0.4985314,
30876
+ -0.969266,
30877
+ 1.8760108,
30878
+ 0.041556,
30879
+ 0.0556434,
30880
+ -0.2040259,
30881
+ 1.0572252
30882
+ ]);
30883
+ static #FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);
30884
+ static #tempNormalizeMatrix = new Float32Array(3);
30885
+ static #tempConvertMatrix1 = new Float32Array(3);
30886
+ static #tempConvertMatrix2 = new Float32Array(3);
30887
+ static #DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8;
30888
+ constructor(whitePoint, blackPoint, gamma, matrix) {
30889
+ super("CalRGB", 3);
30890
+ if (!whitePoint) {
30891
+ throw new FormatError(
30892
+ "WhitePoint missing - required for color space CalRGB"
30893
+ );
30894
+ }
30895
+ const [XW, YW, ZW] = this.whitePoint = whitePoint;
30896
+ const [XB, YB, ZB] = this.blackPoint = blackPoint || new Float32Array(3);
30897
+ [this.GR, this.GG, this.GB] = gamma || new Float32Array([1, 1, 1]);
30898
+ [
30899
+ this.MXA,
30900
+ this.MYA,
30901
+ this.MZA,
30902
+ this.MXB,
30903
+ this.MYB,
30904
+ this.MZB,
30905
+ this.MXC,
30906
+ this.MYC,
30907
+ this.MZC
30908
+ ] = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
30909
+ if (XW < 0 || ZW < 0 || YW !== 1) {
30910
+ throw new FormatError(
30911
+ `Invalid WhitePoint components for ${this.name}, no fallback available`
30912
+ );
30913
+ }
30914
+ if (XB < 0 || YB < 0 || ZB < 0) {
30915
+ info(
30916
+ `Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], falling back to default.`
30917
+ );
30918
+ this.blackPoint = new Float32Array(3);
30919
+ }
30920
+ if (this.GR < 0 || this.GG < 0 || this.GB < 0) {
30921
+ info(
30922
+ `Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ${this.name}, falling back to default.`
30923
+ );
30924
+ this.GR = this.GG = this.GB = 1;
30925
+ }
30926
+ }
30927
+ #matrixProduct(a, b, result) {
30928
+ result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
30929
+ result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
30930
+ result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
30931
+ }
30932
+ #toFlat(sourceWhitePoint, LMS, result) {
30933
+ result[0] = LMS[0] * 1 / sourceWhitePoint[0];
30934
+ result[1] = LMS[1] * 1 / sourceWhitePoint[1];
30935
+ result[2] = LMS[2] * 1 / sourceWhitePoint[2];
30936
+ }
30937
+ #toD65(sourceWhitePoint, LMS, result) {
30938
+ const D65X = 0.95047;
30939
+ const D65Y = 1;
30940
+ const D65Z = 1.08883;
30941
+ result[0] = LMS[0] * D65X / sourceWhitePoint[0];
30942
+ result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
30943
+ result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
30944
+ }
30945
+ #sRGBTransferFunction(color) {
30946
+ if (color <= 31308e-7) {
30947
+ return MathClamp(12.92 * color, 0, 1);
30948
+ }
30949
+ return color >= 0.99554525 ? 1 : MathClamp((1 + 0.055) * color ** (1 / 2.4) - 0.055, 0, 1);
30950
+ }
30951
+ #decodeL(L) {
30952
+ if (L < 0) {
30953
+ return -this.#decodeL(-L);
30954
+ }
30955
+ return L > 8 ? ((L + 16) / 116) ** 3 : L * _CalRGBCS.#DECODE_L_CONSTANT;
30956
+ }
30957
+ #compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
30958
+ if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {
30959
+ result[0] = XYZ_Flat[0];
30960
+ result[1] = XYZ_Flat[1];
30961
+ result[2] = XYZ_Flat[2];
30962
+ return;
30963
+ }
30964
+ const zeroDecodeL = this.#decodeL(0);
30965
+ const X_DST = zeroDecodeL;
30966
+ const X_SRC = this.#decodeL(sourceBlackPoint[0]);
30967
+ const Y_DST = zeroDecodeL;
30968
+ const Y_SRC = this.#decodeL(sourceBlackPoint[1]);
30969
+ const Z_DST = zeroDecodeL;
30970
+ const Z_SRC = this.#decodeL(sourceBlackPoint[2]);
30971
+ const X_Scale = (1 - X_DST) / (1 - X_SRC);
30972
+ const X_Offset = 1 - X_Scale;
30973
+ const Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
30974
+ const Y_Offset = 1 - Y_Scale;
30975
+ const Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
30976
+ const Z_Offset = 1 - Z_Scale;
30977
+ result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
30978
+ result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
30979
+ result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
30980
+ }
30981
+ #normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
30982
+ if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
30983
+ result[0] = XYZ_In[0];
30984
+ result[1] = XYZ_In[1];
30985
+ result[2] = XYZ_In[2];
30986
+ return;
30987
+ }
30988
+ const LMS = result;
30989
+ this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
30990
+ const LMS_Flat = _CalRGBCS.#tempNormalizeMatrix;
30991
+ this.#toFlat(sourceWhitePoint, LMS, LMS_Flat);
30992
+ this.#matrixProduct(
30993
+ _CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
30994
+ LMS_Flat,
30995
+ result
30996
+ );
30997
+ }
30998
+ #normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
30999
+ const LMS = result;
31000
+ this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
31001
+ const LMS_D65 = _CalRGBCS.#tempNormalizeMatrix;
31002
+ this.#toD65(sourceWhitePoint, LMS, LMS_D65);
31003
+ this.#matrixProduct(
31004
+ _CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
31005
+ LMS_D65,
31006
+ result
31007
+ );
31008
+ }
31009
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
31010
+ const A = MathClamp(src[srcOffset] * scale, 0, 1);
31011
+ const B = MathClamp(src[srcOffset + 1] * scale, 0, 1);
31012
+ const C = MathClamp(src[srcOffset + 2] * scale, 0, 1);
31013
+ const AGR = A === 1 ? 1 : A ** this.GR;
31014
+ const BGG = B === 1 ? 1 : B ** this.GG;
31015
+ const CGB = C === 1 ? 1 : C ** this.GB;
31016
+ const X = this.MXA * AGR + this.MXB * BGG + this.MXC * CGB;
31017
+ const Y = this.MYA * AGR + this.MYB * BGG + this.MYC * CGB;
31018
+ const Z = this.MZA * AGR + this.MZB * BGG + this.MZC * CGB;
31019
+ const XYZ = _CalRGBCS.#tempConvertMatrix1;
31020
+ XYZ[0] = X;
31021
+ XYZ[1] = Y;
31022
+ XYZ[2] = Z;
31023
+ const XYZ_Flat = _CalRGBCS.#tempConvertMatrix2;
31024
+ this.#normalizeWhitePointToFlat(this.whitePoint, XYZ, XYZ_Flat);
31025
+ const XYZ_Black = _CalRGBCS.#tempConvertMatrix1;
31026
+ this.#compensateBlackPoint(this.blackPoint, XYZ_Flat, XYZ_Black);
31027
+ const XYZ_D65 = _CalRGBCS.#tempConvertMatrix2;
31028
+ this.#normalizeWhitePointToD65(
31029
+ _CalRGBCS.#FLAT_WHITEPOINT_MATRIX,
31030
+ XYZ_Black,
31031
+ XYZ_D65
31032
+ );
31033
+ const SRGB = _CalRGBCS.#tempConvertMatrix1;
31034
+ this.#matrixProduct(_CalRGBCS.#SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
31035
+ dest[destOffset] = this.#sRGBTransferFunction(SRGB[0]) * 255;
31036
+ dest[destOffset + 1] = this.#sRGBTransferFunction(SRGB[1]) * 255;
31037
+ dest[destOffset + 2] = this.#sRGBTransferFunction(SRGB[2]) * 255;
31038
+ }
31039
+ getRgbItem(src, srcOffset, dest, destOffset) {
31040
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
31041
+ assert2(
31042
+ dest instanceof Uint8ClampedArray,
31043
+ 'CalRGBCS.getRgbItem: Unsupported "dest" type.'
31044
+ );
31045
+ }
31046
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
31047
+ }
31048
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
31049
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
31050
+ assert2(
31051
+ dest instanceof Uint8ClampedArray,
31052
+ 'CalRGBCS.getRgbBuffer: Unsupported "dest" type.'
31053
+ );
31054
+ }
31055
+ const scale = 1 / ((1 << bits) - 1);
31056
+ for (let i = 0; i < count; ++i) {
31057
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
31058
+ srcOffset += 3;
31059
+ destOffset += 3 + alpha01;
31060
+ }
31061
+ }
31062
+ };
31063
+ var LabCS = class extends ColorSpace {
31064
+ constructor(whitePoint, blackPoint, range) {
31065
+ super("Lab", 3);
31066
+ if (!whitePoint) {
31067
+ throw new FormatError(
31068
+ "WhitePoint missing - required for color space Lab"
31069
+ );
31070
+ }
31071
+ [this.XW, this.YW, this.ZW] = whitePoint;
31072
+ [this.amin, this.amax, this.bmin, this.bmax] = range || [
31073
+ -100,
31074
+ 100,
31075
+ -100,
31076
+ 100
31077
+ ];
31078
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
31079
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
31080
+ throw new FormatError(
31081
+ "Invalid WhitePoint components, no fallback available"
31082
+ );
31083
+ }
31084
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
31085
+ info("Invalid BlackPoint, falling back to default");
31086
+ this.XB = this.YB = this.ZB = 0;
31087
+ }
31088
+ if (this.amin > this.amax || this.bmin > this.bmax) {
31089
+ info("Invalid Range, falling back to defaults");
31090
+ this.amin = -100;
31091
+ this.amax = 100;
31092
+ this.bmin = -100;
31093
+ this.bmax = 100;
31094
+ }
31095
+ }
31096
+ // Function g(x) from spec
31097
+ #fn_g(x) {
31098
+ return x >= 6 / 29 ? x ** 3 : 108 / 841 * (x - 4 / 29);
31099
+ }
31100
+ #decode(value, high1, low2, high2) {
31101
+ return low2 + value * (high2 - low2) / high1;
31102
+ }
31103
+ // If decoding is needed maxVal should be 2^bits per component - 1.
31104
+ #toRgb(src, srcOffset, maxVal, dest, destOffset) {
31105
+ let Ls = src[srcOffset];
31106
+ let as = src[srcOffset + 1];
31107
+ let bs = src[srcOffset + 2];
31108
+ if (maxVal !== false) {
31109
+ Ls = this.#decode(Ls, maxVal, 0, 100);
31110
+ as = this.#decode(as, maxVal, this.amin, this.amax);
31111
+ bs = this.#decode(bs, maxVal, this.bmin, this.bmax);
31112
+ }
31113
+ if (as > this.amax) {
31114
+ as = this.amax;
31115
+ } else if (as < this.amin) {
31116
+ as = this.amin;
31117
+ }
31118
+ if (bs > this.bmax) {
31119
+ bs = this.bmax;
31120
+ } else if (bs < this.bmin) {
31121
+ bs = this.bmin;
31122
+ }
31123
+ const M = (Ls + 16) / 116;
31124
+ const L = M + as / 500;
31125
+ const N = M - bs / 200;
31126
+ const X = this.XW * this.#fn_g(L);
31127
+ const Y = this.YW * this.#fn_g(M);
31128
+ const Z = this.ZW * this.#fn_g(N);
31129
+ let r, g, b;
31130
+ if (this.ZW < 1) {
31131
+ r = X * 3.1339 + Y * -1.617 + Z * -0.4906;
31132
+ g = X * -0.9785 + Y * 1.916 + Z * 0.0333;
31133
+ b = X * 0.072 + Y * -0.229 + Z * 1.4057;
31134
+ } else {
31135
+ r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
31136
+ g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
31137
+ b = X * 0.0557 + Y * -0.204 + Z * 1.057;
31138
+ }
31139
+ dest[destOffset] = Math.sqrt(r) * 255;
31140
+ dest[destOffset + 1] = Math.sqrt(g) * 255;
31141
+ dest[destOffset + 2] = Math.sqrt(b) * 255;
31142
+ }
31143
+ getRgbItem(src, srcOffset, dest, destOffset) {
31144
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
31145
+ assert2(
31146
+ dest instanceof Uint8ClampedArray,
31147
+ 'LabCS.getRgbItem: Unsupported "dest" type.'
31148
+ );
31149
+ }
31150
+ this.#toRgb(src, srcOffset, false, dest, destOffset);
31151
+ }
31152
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
31153
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
31154
+ assert2(
31155
+ dest instanceof Uint8ClampedArray,
31156
+ 'LabCS.getRgbBuffer: Unsupported "dest" type.'
31157
+ );
31158
+ }
31159
+ const maxVal = (1 << bits) - 1;
31160
+ for (let i = 0; i < count; i++) {
31161
+ this.#toRgb(src, srcOffset, maxVal, dest, destOffset);
31162
+ srcOffset += 3;
31163
+ destOffset += 3 + alpha01;
31164
+ }
31165
+ }
31166
+ isDefaultDecode(decode, bpc) {
31167
+ return true;
31168
+ }
31169
+ get usesZeroToOneRange() {
31170
+ return shadow2(this, "usesZeroToOneRange", false);
31171
+ }
31172
+ };
31173
+ var TOKEN = {
31174
+ // Structural tokens — not keyword operators
31175
+ number: 0,
31176
+ lbrace: 1,
31177
+ rbrace: 2,
31178
+ // Boolean literals
31179
+ true: 3,
31180
+ false: 4,
31181
+ // Arithmetic binary operators
31182
+ add: 5,
31183
+ sub: 6,
31184
+ mul: 7,
31185
+ div: 8,
31186
+ idiv: 9,
31187
+ mod: 10,
31188
+ exp: 11,
31189
+ // Comparison binary operators
31190
+ eq: 12,
31191
+ ne: 13,
31192
+ gt: 14,
31193
+ ge: 15,
31194
+ lt: 16,
31195
+ le: 17,
31196
+ // Bitwise / boolean binary operators
31197
+ and: 18,
31198
+ or: 19,
31199
+ xor: 20,
31200
+ bitshift: 21,
31201
+ // Unary arithmetic operators
31202
+ abs: 22,
31203
+ neg: 23,
31204
+ ceiling: 24,
31205
+ floor: 25,
31206
+ round: 26,
31207
+ truncate: 27,
31208
+ // Unary boolean / bitwise operator
31209
+ not: 28,
31210
+ // Mathematical functions — unary
31211
+ sqrt: 29,
31212
+ sin: 30,
31213
+ cos: 31,
31214
+ ln: 32,
31215
+ log: 33,
31216
+ // Mathematical function — binary
31217
+ atan: 34,
31218
+ // Type conversion operators
31219
+ cvi: 35,
31220
+ cvr: 36,
31221
+ // Stack operators
31222
+ dup: 37,
31223
+ exch: 38,
31224
+ pop: 39,
31225
+ copy: 40,
31226
+ index: 41,
31227
+ roll: 42,
31228
+ // Control flow
31229
+ if: 43,
31230
+ ifelse: 44,
31231
+ // End of input
31232
+ eof: 45,
31233
+ // Synthetic: produced by the optimizer, never emitted by the lexer.
31234
+ min: 46,
31235
+ max: 47
31236
+ };
31237
+ var Token = class {
31238
+ constructor(id, value = null) {
31239
+ this.id = id;
31240
+ this.value = value;
31241
+ }
31242
+ };
31243
+ var Lexer = class _Lexer {
31244
+ // Singletons for every non-number token, built lazily on first construction.
31245
+ // Keyword operator tokens carry their name as `value`; structural tokens
31246
+ // (lbrace, rbrace, eof) carry null.
31247
+ static #singletons = null;
31248
+ static #operatorSingletons = null;
31249
+ static #initSingletons() {
31250
+ const singletons = /* @__PURE__ */ Object.create(null);
31251
+ const operatorSingletons = /* @__PURE__ */ Object.create(null);
31252
+ for (const [name, id] of Object.entries(TOKEN)) {
31253
+ if (name === "number") {
31254
+ continue;
31255
+ }
31256
+ const isOperator = id >= TOKEN.true && id <= TOKEN.ifelse;
31257
+ const token = new Token(id, isOperator ? name : null);
31258
+ singletons[name] = token;
31259
+ if (isOperator) {
31260
+ operatorSingletons[name] = token;
31261
+ }
31262
+ }
31263
+ this.#singletons = singletons;
31264
+ this.#operatorSingletons = operatorSingletons;
31265
+ }
31266
+ constructor(data) {
31267
+ if (!_Lexer.#singletons) {
31268
+ _Lexer.#initSingletons();
31269
+ }
31270
+ this.data = data;
31271
+ this.pos = 0;
31272
+ this.len = data.length;
31273
+ this._numberPattern = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/iy;
31274
+ this._identifierPattern = /[a-z]+/y;
31275
+ }
31276
+ // Skip a % comment, advancing past the next \n or \r (or to EOF).
31277
+ _skipComment() {
31278
+ const lf = this.data.indexOf("\n", this.pos);
31279
+ const cr = this.data.indexOf("\r", this.pos);
31280
+ const eol = Math.min(lf < 0 ? this.len : lf, cr < 0 ? this.len : cr);
31281
+ this.pos = Math.min(eol + 1, this.len);
31282
+ }
31283
+ _getNumber() {
31284
+ this._numberPattern.lastIndex = this.pos;
31285
+ const match = this._numberPattern.exec(this.data);
31286
+ if (!match) {
31287
+ return new Token(TOKEN.number, 0);
31288
+ }
31289
+ const number = parseFloat(match[0]);
31290
+ if (!Number.isFinite(number)) {
31291
+ return new Token(TOKEN.number, 0);
31292
+ }
31293
+ this.pos = this._numberPattern.lastIndex;
31294
+ return new Token(TOKEN.number, number);
31295
+ }
31296
+ _getOperator() {
31297
+ this._identifierPattern.lastIndex = this.pos;
31298
+ const match = this._identifierPattern.exec(this.data);
31299
+ if (!match) {
31300
+ return new Token(TOKEN.number, 0);
31301
+ }
31302
+ this.pos = this._identifierPattern.lastIndex;
31303
+ const op = match[0];
31304
+ const token = _Lexer.#operatorSingletons[op];
31305
+ return token ?? new Token(TOKEN.number, 0);
31306
+ }
31307
+ // Return the next token, or Lexer.#singletons.eof at end of input.
31308
+ next() {
31309
+ while (this.pos < this.len) {
31310
+ const ch3 = this.data.charCodeAt(this.pos++);
31311
+ switch (ch3) {
31312
+ // PostScript white-space characters (PDF32000 §7.2.2)
31313
+ case 0:
31314
+ case 9:
31315
+ case 10:
31316
+ case 12:
31317
+ case 13:
31318
+ case 32:
31319
+ break;
31320
+ case 37:
31321
+ this._skipComment();
31322
+ break;
31323
+ case 123:
31324
+ return _Lexer.#singletons.lbrace;
31325
+ case 125:
31326
+ return _Lexer.#singletons.rbrace;
31327
+ case 43:
31328
+ case 45:
31329
+ this.pos--;
31330
+ return this._getNumber();
31331
+ case 46:
31332
+ this.pos--;
31333
+ return this._getNumber();
31334
+ default:
31335
+ if (ch3 >= 48 && ch3 <= 57) {
31336
+ this.pos--;
31337
+ return this._getNumber();
31338
+ }
31339
+ if (ch3 >= 97 && ch3 <= 122) {
31340
+ this.pos--;
31341
+ return this._getOperator();
31342
+ }
31343
+ return new Token(TOKEN.number, 0);
31344
+ }
31345
+ }
31346
+ return _Lexer.#singletons.eof;
31347
+ }
31348
+ };
31349
+ var PS_VALUE_TYPE = {
31350
+ numeric: 0,
31351
+ // known to be a number (f64 in Wasm)
31352
+ boolean: 1,
31353
+ // known to be a boolean (0.0 = false, 1.0 = true in f64)
31354
+ unknown: 2
31355
+ // indeterminate at compile time
31356
+ };
31357
+ var PS_NODE = {
31358
+ // Parser AST node types (produced by Parser / parsePostScriptFunction)
31359
+ program: 0,
31360
+ block: 1,
31361
+ number: 2,
31362
+ operator: 3,
31363
+ if: 4,
31364
+ ifelse: 5,
31365
+ // Tree AST node types (produced by PSStackToTree)
31366
+ arg: 6,
31367
+ const: 7,
31368
+ unary: 8,
31369
+ binary: 9,
31370
+ ternary: 10
31371
+ };
31372
+ var PsNode = class {
31373
+ constructor(type) {
31374
+ this.type = type;
31375
+ }
31376
+ };
31377
+ var PsProgram = class extends PsNode {
31378
+ constructor(body) {
31379
+ super(PS_NODE.program);
31380
+ this.body = body;
31381
+ }
31382
+ };
31383
+ var PsBlock = class extends PsNode {
31384
+ constructor(instructions) {
31385
+ super(PS_NODE.block);
31386
+ this.instructions = instructions;
31387
+ }
31388
+ };
31389
+ var PsNumber = class extends PsNode {
31390
+ /** @param {number} value */
31391
+ constructor(value) {
31392
+ super(PS_NODE.number);
31393
+ this.value = value;
31394
+ }
31395
+ };
31396
+ var PsOperator = class extends PsNode {
31397
+ /** @param {number} op — one of the TOKEN.* constants from lexer.js */
31398
+ constructor(op) {
31399
+ super(PS_NODE.operator);
31400
+ this.op = op;
31401
+ }
31402
+ };
31403
+ var PsIf = class extends PsNode {
31404
+ /** @param {PsBlock} then */
31405
+ constructor(then) {
31406
+ super(PS_NODE.if);
31407
+ this.then = then;
31408
+ }
31409
+ };
31410
+ var PsIfElse = class extends PsNode {
31411
+ /**
31412
+ * @param {PsBlock} then
31413
+ * @param {PsBlock} otherwise
31414
+ */
31415
+ constructor(then, otherwise) {
31416
+ super(PS_NODE.ifelse);
31417
+ this.then = then;
31418
+ this.otherwise = otherwise;
31419
+ }
31420
+ };
31421
+ var PsArgNode = class extends PsNode {
31422
+ /** @param {number} index */
31423
+ constructor(index) {
31424
+ super(PS_NODE.arg);
31425
+ this.index = index;
31426
+ this.valueType = PS_VALUE_TYPE.numeric;
31427
+ }
31428
+ };
31429
+ var PsConstNode = class extends PsNode {
31430
+ /** @param {number|boolean} value */
31431
+ constructor(value) {
31432
+ super(PS_NODE.const);
31433
+ this.value = value;
31434
+ this.valueType = typeof value === "boolean" ? PS_VALUE_TYPE.boolean : PS_VALUE_TYPE.numeric;
31435
+ }
31436
+ };
31437
+ var PsUnaryNode = class extends PsNode {
31438
+ /**
31439
+ * @param {number} op — TOKEN.* constant
31440
+ * @param {PsNode} operand
31441
+ * @param {number} [valueType]
31442
+ */
31443
+ constructor(op, operand, valueType = PS_VALUE_TYPE.unknown) {
31444
+ super(PS_NODE.unary);
31445
+ this.op = op;
31446
+ this.operand = operand;
31447
+ this.valueType = valueType;
31448
+ }
31449
+ };
31450
+ var PsBinaryNode = class extends PsNode {
31451
+ /**
31452
+ * @param {number} op — TOKEN.* constant
31453
+ * @param {PsNode} first — was on top of stack
31454
+ * @param {PsNode} second — was below top
31455
+ * @param {number} [valueType]
31456
+ */
31457
+ constructor(op, first, second, valueType = PS_VALUE_TYPE.unknown) {
31458
+ super(PS_NODE.binary);
31459
+ this.op = op;
31460
+ this.first = first;
31461
+ this.second = second;
31462
+ this.valueType = valueType;
31463
+ }
31464
+ };
31465
+ var PsTernaryNode = class extends PsNode {
31466
+ /**
31467
+ * @param {PsNode} cond
31468
+ * @param {PsNode} then
31469
+ * @param {PsNode} otherwise
31470
+ * @param {number} [valueType]
31471
+ */
31472
+ constructor(cond, then, otherwise, valueType = PS_VALUE_TYPE.unknown) {
31473
+ super(PS_NODE.ternary);
31474
+ this.cond = cond;
31475
+ this.then = then;
31476
+ this.otherwise = otherwise;
31477
+ this.valueType = valueType;
31478
+ }
31479
+ };
31480
+ var Parser = class _Parser {
31481
+ constructor(lexer) {
31482
+ this.lexer = lexer;
31483
+ this._token = null;
31484
+ }
31485
+ static _isRegularOperator(id) {
31486
+ return id >= TOKEN.true && id < TOKEN.if;
31487
+ }
31488
+ // Fetch the next token from the lexer.
31489
+ _advance() {
31490
+ this._token = this.lexer.next();
31491
+ }
31492
+ // Assert that the current token has the given id, consume it, and return it.
31493
+ _expect(id) {
31494
+ if (this._token.id !== id) {
31495
+ throw new FormatError(
31496
+ `PostScript function: expected token id ${id}, got ${this._token.id}.`
31497
+ );
31498
+ }
31499
+ const tok = this._token;
31500
+ this._advance();
31501
+ return tok;
31502
+ }
31503
+ /**
31504
+ * Parse the full Type 4 function body.
31505
+ *
31506
+ * Grammar (simplified):
31507
+ * program ::= '{' block '}'
31508
+ * block ::= instruction*
31509
+ * instruction ::= number
31510
+ * | operator (any PS_OPERATOR except if / ifelse)
31511
+ * | '{' block '}' 'if'
31512
+ * | '{' block '}' '{' block '}' 'ifelse'
31513
+ * @returns {PsProgram}
31514
+ */
31515
+ parse() {
31516
+ this._advance();
31517
+ this._expect(TOKEN.lbrace);
31518
+ const block = this._parseBlock();
31519
+ this._expect(TOKEN.rbrace);
31520
+ if (this._token.id !== TOKEN.eof) {
31521
+ warn2("PostScript function: unexpected content after closing brace.");
31522
+ }
31523
+ return new PsProgram(block);
31524
+ }
31525
+ _parseBlock() {
31526
+ const instructions = [];
31527
+ while (true) {
31528
+ const tok = this._token;
31529
+ switch (tok.id) {
31530
+ case TOKEN.number:
31531
+ instructions.push(new PsNumber(tok.value));
31532
+ this._advance();
31533
+ break;
31534
+ case TOKEN.lbrace: {
31535
+ this._advance();
31536
+ const thenBlock = this._parseBlock();
31537
+ this._expect(TOKEN.rbrace);
31538
+ if (this._token.id === TOKEN.if) {
31539
+ this._advance();
31540
+ instructions.push(new PsIf(thenBlock));
31541
+ } else if (this._token.id === TOKEN.lbrace) {
31542
+ this._advance();
31543
+ const elseBlock = this._parseBlock();
31544
+ this._expect(TOKEN.rbrace);
31545
+ this._expect(TOKEN.ifelse);
31546
+ instructions.push(new PsIfElse(thenBlock, elseBlock));
31547
+ } else {
31548
+ throw new FormatError(
31549
+ "PostScript function: a procedure block must be followed by 'if' or '{\u2026} ifelse'."
31550
+ );
31551
+ }
31552
+ break;
31553
+ }
31554
+ case TOKEN.rbrace:
31555
+ case TOKEN.eof:
31556
+ return new PsBlock(instructions);
31557
+ case TOKEN.if:
31558
+ case TOKEN.ifelse:
31559
+ throw new FormatError(
31560
+ `PostScript function: unexpected '${tok.value}' operator.`
31561
+ );
31562
+ default:
31563
+ if (_Parser._isRegularOperator(tok.id)) {
31564
+ instructions.push(new PsOperator(tok.id));
31565
+ this._advance();
31566
+ break;
31567
+ }
31568
+ throw new FormatError(
31569
+ `PostScript function: unexpected token id ${tok.id}.`
31570
+ );
31571
+ }
31572
+ }
31573
+ }
31574
+ };
31575
+ function parsePostScriptFunction(source) {
31576
+ return new Parser(new Lexer(source)).parse();
31577
+ }
31578
+ function _nodesEqual(a, b) {
31579
+ if (a === b) {
31580
+ return true;
31581
+ }
31582
+ if (a.type !== b.type) {
31583
+ return false;
31584
+ }
31585
+ switch (a.type) {
31586
+ case PS_NODE.arg:
31587
+ return a.index === b.index;
31588
+ case PS_NODE.const:
31589
+ return a.value === b.value;
31590
+ case PS_NODE.unary:
31591
+ return a.op === b.op && _nodesEqual(a.operand, b.operand);
31592
+ case PS_NODE.binary:
31593
+ return a.op === b.op && _nodesEqual(a.first, b.first) && _nodesEqual(a.second, b.second);
31594
+ case PS_NODE.ternary:
31595
+ return _nodesEqual(a.cond, b.cond) && _nodesEqual(a.then, b.then) && _nodesEqual(a.otherwise, b.otherwise);
31596
+ default:
31597
+ return false;
31598
+ }
31599
+ }
31600
+ function _evalBinaryConst(op, a, b) {
31601
+ switch (op) {
31602
+ case TOKEN.add:
31603
+ return a + b;
31604
+ case TOKEN.sub:
31605
+ return a - b;
31606
+ case TOKEN.mul:
31607
+ return a * b;
31608
+ case TOKEN.div:
31609
+ return b !== 0 ? a / b : 0;
31610
+ // div by zero → 0
31611
+ case TOKEN.idiv:
31612
+ return b !== 0 ? Math.trunc(a / b) : 0;
31613
+ // div by zero → 0
31614
+ case TOKEN.mod:
31615
+ return b !== 0 ? a - Math.trunc(a / b) * b : 0;
31616
+ // div by zero → 0
31617
+ case TOKEN.exp: {
31618
+ const r = a ** b;
31619
+ return Number.isFinite(r) ? r : void 0;
31620
+ }
31621
+ case TOKEN.atan: {
31622
+ let deg = Math.atan2(a, b) * (180 / Math.PI);
31623
+ if (deg < 0) {
31624
+ deg += 360;
31625
+ }
31626
+ return deg;
31627
+ }
31628
+ case TOKEN.eq:
31629
+ return a === b;
31630
+ case TOKEN.ne:
31631
+ return a !== b;
31632
+ case TOKEN.gt:
31633
+ return a > b;
31634
+ case TOKEN.ge:
31635
+ return a >= b;
31636
+ case TOKEN.lt:
31637
+ return a < b;
31638
+ case TOKEN.le:
31639
+ return a <= b;
31640
+ case TOKEN.and:
31641
+ return typeof a === "boolean" ? a && b : a & b | 0;
31642
+ case TOKEN.or:
31643
+ return typeof a === "boolean" ? a || b : a | b | 0;
31644
+ case TOKEN.xor:
31645
+ return typeof a === "boolean" ? a !== b : a ^ b | 0;
31646
+ case TOKEN.bitshift:
31647
+ return b >= 0 ? a << b | 0 : a >> -b | 0;
31648
+ case TOKEN.min:
31649
+ return Math.min(a, b);
31650
+ case TOKEN.max:
31651
+ return Math.max(a, b);
31652
+ default:
31653
+ return void 0;
31654
+ }
31655
+ }
31656
+ function _evalUnaryConst(op, v) {
31657
+ switch (op) {
31658
+ case TOKEN.abs:
31659
+ return Math.abs(v);
31660
+ case TOKEN.neg:
31661
+ return -v;
31662
+ case TOKEN.ceiling:
31663
+ return Math.ceil(v);
31664
+ case TOKEN.floor:
31665
+ return Math.floor(v);
31666
+ case TOKEN.round:
31667
+ return Math.round(v);
31668
+ case TOKEN.truncate:
31669
+ return Math.trunc(v);
31670
+ case TOKEN.sqrt: {
31671
+ const r = Math.sqrt(v);
31672
+ return Number.isFinite(r) ? r : void 0;
31673
+ }
31674
+ case TOKEN.sin:
31675
+ return Math.sin(v % 360 * Math.PI / 180);
31676
+ case TOKEN.cos:
31677
+ return Math.cos(v % 360 * Math.PI / 180);
31678
+ case TOKEN.ln: {
31679
+ const r = Math.log(v);
31680
+ return Number.isFinite(r) ? r : void 0;
31681
+ }
31682
+ case TOKEN.log: {
31683
+ const r = Math.log10(v);
31684
+ return Number.isFinite(r) ? r : void 0;
31685
+ }
31686
+ case TOKEN.cvi:
31687
+ return Math.trunc(v);
31688
+ case TOKEN.cvr:
31689
+ return v;
31690
+ case TOKEN.not:
31691
+ return typeof v === "boolean" ? !v : ~v;
31692
+ default:
31693
+ return void 0;
31694
+ }
31695
+ }
31696
+ var MAX_STACK_SIZE = 100;
31697
+ function _unaryValueType(op, operandType) {
31698
+ return op === TOKEN.not ? operandType : PS_VALUE_TYPE.numeric;
31699
+ }
31700
+ function _binaryValueType(op, firstType, secondType) {
31701
+ switch (op) {
31702
+ // Comparison operators always produce a boolean.
31703
+ case TOKEN.eq:
31704
+ case TOKEN.ne:
31705
+ case TOKEN.gt:
31706
+ case TOKEN.ge:
31707
+ case TOKEN.lt:
31708
+ case TOKEN.le:
31709
+ return PS_VALUE_TYPE.boolean;
31710
+ // and / or / xor preserve the type when both operands are the same known
31711
+ // type (both boolean or both numeric); otherwise the type is unknown.
31712
+ case TOKEN.and:
31713
+ case TOKEN.or:
31714
+ case TOKEN.xor:
31715
+ return firstType === secondType && firstType !== PS_VALUE_TYPE.unknown ? firstType : PS_VALUE_TYPE.unknown;
31716
+ // All arithmetic / bitshift operators produce a numeric result.
31717
+ default:
31718
+ return PS_VALUE_TYPE.numeric;
31719
+ }
31720
+ }
31721
+ var PSStackToTree = class _PSStackToTree {
31722
+ static #binaryOps = null;
31723
+ static #unaryOps = null;
31724
+ static #idempotentUnary = null;
31725
+ static #negatedComparison = null;
31726
+ static #init() {
31727
+ this.#binaryOps = /* @__PURE__ */ new Set([
31728
+ TOKEN.add,
31729
+ TOKEN.sub,
31730
+ TOKEN.mul,
31731
+ TOKEN.div,
31732
+ TOKEN.idiv,
31733
+ TOKEN.mod,
31734
+ TOKEN.exp,
31735
+ TOKEN.atan,
31736
+ TOKEN.eq,
31737
+ TOKEN.ne,
31738
+ TOKEN.gt,
31739
+ TOKEN.ge,
31740
+ TOKEN.lt,
31741
+ TOKEN.le,
31742
+ TOKEN.and,
31743
+ TOKEN.or,
31744
+ TOKEN.xor,
31745
+ TOKEN.bitshift
31746
+ ]);
31747
+ this.#unaryOps = /* @__PURE__ */ new Set([
31748
+ TOKEN.abs,
31749
+ TOKEN.neg,
31750
+ TOKEN.ceiling,
31751
+ TOKEN.floor,
31752
+ TOKEN.round,
31753
+ TOKEN.truncate,
31754
+ TOKEN.sqrt,
31755
+ TOKEN.sin,
31756
+ TOKEN.cos,
31757
+ TOKEN.ln,
31758
+ TOKEN.log,
31759
+ TOKEN.cvi,
31760
+ TOKEN.cvr,
31761
+ TOKEN.not
31762
+ ]);
31763
+ this.#idempotentUnary = /* @__PURE__ */ new Set([
31764
+ TOKEN.abs,
31765
+ TOKEN.ceiling,
31766
+ TOKEN.cvi,
31767
+ TOKEN.cvr,
31768
+ TOKEN.floor,
31769
+ TOKEN.round,
31770
+ TOKEN.truncate
31771
+ ]);
31772
+ this.#negatedComparison = /* @__PURE__ */ new Map([
31773
+ [TOKEN.eq, TOKEN.ne],
31774
+ [TOKEN.ne, TOKEN.eq],
31775
+ [TOKEN.lt, TOKEN.ge],
31776
+ [TOKEN.le, TOKEN.gt],
31777
+ [TOKEN.gt, TOKEN.le],
31778
+ [TOKEN.ge, TOKEN.lt]
31779
+ ]);
31780
+ }
31781
+ /**
31782
+ * @param {PsProgram} program
31783
+ * @param {number} numInputs — number of domain values placed on the stack
31784
+ * before the program runs (i.e. the length of the domain array / 2).
31785
+ * @returns {Array<PsNode>} — one tree node per output value.
31786
+ */
31787
+ evaluate(program, numInputs) {
31788
+ if (!_PSStackToTree.#binaryOps) {
31789
+ _PSStackToTree.#init();
31790
+ }
31791
+ this._failed = false;
31792
+ if (numInputs > MAX_STACK_SIZE) {
31793
+ return null;
31794
+ }
31795
+ const stack = [];
31796
+ for (let i = 0; i < numInputs; i++) {
31797
+ stack.push(new PsArgNode(i));
31798
+ }
31799
+ this._evalBlock(program.body, stack);
31800
+ if (this._failed) {
31801
+ return null;
31802
+ }
31803
+ _PSStackToTree.#markShared(stack);
31804
+ return stack;
31805
+ }
31806
+ // Set node.shared / sharedCount on non-atomic nodes referenced more than
31807
+ // once. arg/const are excluded — they are cheap to re-emit inline.
31808
+ static #markShared(outputs) {
31809
+ const refCount = /* @__PURE__ */ new Map();
31810
+ const visit = (node) => {
31811
+ if (!node || node.type === PS_NODE.arg || node.type === PS_NODE.const) {
31812
+ return;
31813
+ }
31814
+ const prev = refCount.get(node) ?? 0;
31815
+ refCount.set(node, prev + 1);
31816
+ if (prev > 0) {
31817
+ return;
31818
+ }
31819
+ switch (node.type) {
31820
+ case PS_NODE.unary:
31821
+ visit(node.operand);
31822
+ break;
31823
+ case PS_NODE.binary:
31824
+ visit(node.first);
31825
+ visit(node.second);
31826
+ break;
31827
+ case PS_NODE.ternary:
31828
+ visit(node.cond);
31829
+ visit(node.then);
31830
+ visit(node.otherwise);
31831
+ break;
31832
+ }
31833
+ };
31834
+ for (const output of outputs) {
31835
+ visit(output);
31836
+ }
31837
+ for (const [node, count] of refCount) {
31838
+ if (count > 1) {
31839
+ node.shared = true;
31840
+ node.sharedCount = count;
31841
+ }
31842
+ }
31843
+ }
31844
+ _evalBlock(block, stack) {
31845
+ this._evalBlockFrom(block.instructions, 0, stack);
31846
+ }
31847
+ /**
31848
+ * Core evaluation loop. Processes `instructions[startIdx…]` in order,
31849
+ * mutating `stack` as each instruction executes.
31850
+ *
31851
+ * When a `{ body } if` instruction grows the stack (the PostScript "early
31852
+ * exit / guard" idiom), the remaining instructions in the current array are
31853
+ * evaluated on **both** the true-branch stack and the false-branch stack,
31854
+ * then the two results are merged into PsTernaryNodes. This handles
31855
+ * patterns like:
31856
+ *
31857
+ * cond { pop R G B sentinel } if
31858
+ * … more guards …
31859
+ * sentinel 0 gt { defaultR defaultG defaultB } if
31860
+ */
31861
+ _evalBlockFrom(instructions, startIdx, stack) {
31862
+ for (let idx = startIdx; idx < instructions.length; idx++) {
31863
+ if (this._failed) {
31864
+ break;
31865
+ }
31866
+ const instr = instructions[idx];
31867
+ switch (instr.type) {
31868
+ case PS_NODE.number:
31869
+ stack.push(new PsConstNode(instr.value));
31870
+ if (stack.length > MAX_STACK_SIZE) {
31871
+ this._failed = true;
31872
+ }
31873
+ break;
31874
+ case PS_NODE.operator:
31875
+ this._evalOp(instr.op, stack);
31876
+ break;
31877
+ case PS_NODE.if: {
31878
+ if (stack.length < 1) {
31879
+ this._failed = true;
31880
+ break;
31881
+ }
31882
+ const cond = stack.pop();
31883
+ const saved = stack.slice();
31884
+ this._evalBlock(instr.then, stack);
31885
+ if (this._failed) {
31886
+ break;
31887
+ }
31888
+ if (stack.length === saved.length) {
31889
+ for (let i = 0; i < stack.length; i++) {
31890
+ if (stack[i] !== saved[i]) {
31891
+ stack[i] = this._makeTernary(cond, stack[i], saved[i]);
31892
+ }
31893
+ }
31894
+ } else if (stack.length > saved.length) {
31895
+ if (cond.type === PS_NODE.const) {
31896
+ if (!cond.value) {
31897
+ stack.length = 0;
31898
+ stack.push(...saved);
31899
+ }
31900
+ break;
31901
+ }
31902
+ const trueStack = stack.slice();
31903
+ this._evalBlockFrom(instructions, idx + 1, trueStack);
31904
+ if (this._failed) {
31905
+ break;
31906
+ }
31907
+ const falseStack = saved;
31908
+ this._evalBlockFrom(instructions, idx + 1, falseStack);
31909
+ if (this._failed) {
31910
+ break;
31911
+ }
31912
+ if (trueStack.length !== falseStack.length) {
31913
+ const zero22 = new PsConstNode(0);
31914
+ while (trueStack.length < falseStack.length) {
31915
+ trueStack.push(zero22);
31916
+ }
31917
+ while (falseStack.length < trueStack.length) {
31918
+ falseStack.push(zero22);
31919
+ }
31920
+ }
31921
+ stack.length = 0;
31922
+ for (let i = 0; i < trueStack.length; i++) {
31923
+ stack.push(this._makeTernary(cond, trueStack[i], falseStack[i]));
31924
+ }
31925
+ return;
31926
+ } else {
31927
+ this._failed = true;
31928
+ }
31929
+ break;
31930
+ }
31931
+ case PS_NODE.ifelse: {
31932
+ if (stack.length < 1) {
31933
+ this._failed = true;
31934
+ break;
31935
+ }
31936
+ const cond = stack.pop();
31937
+ const snapshot = stack.slice();
31938
+ const thenStack = snapshot.slice();
31939
+ this._evalBlock(instr.then, thenStack);
31940
+ if (this._failed) {
31941
+ break;
31942
+ }
31943
+ const elseStack = snapshot.slice();
31944
+ this._evalBlock(instr.otherwise, elseStack);
31945
+ if (this._failed) {
31946
+ break;
31947
+ }
31948
+ if (thenStack.length !== elseStack.length) {
31949
+ const zero22 = new PsConstNode(0);
31950
+ while (thenStack.length < elseStack.length) {
31951
+ thenStack.push(zero22);
31952
+ }
31953
+ while (elseStack.length < thenStack.length) {
31954
+ elseStack.push(zero22);
31955
+ }
31956
+ }
31957
+ stack.length = 0;
31958
+ for (let i = 0; i < thenStack.length; i++) {
31959
+ stack.push(this._makeTernary(cond, thenStack[i], elseStack[i]));
31960
+ }
31961
+ break;
31962
+ }
31963
+ }
31964
+ }
31965
+ }
31966
+ _evalOp(op, stack) {
31967
+ if (_PSStackToTree.#binaryOps.has(op)) {
31968
+ if (stack.length < 2) {
31969
+ this._failed = true;
31970
+ return;
31971
+ }
31972
+ const first = stack.pop();
31973
+ const second = stack.pop();
31974
+ stack.push(this._makeBinary(op, first, second));
31975
+ return;
31976
+ }
31977
+ if (_PSStackToTree.#unaryOps.has(op)) {
31978
+ if (stack.length < 1) {
31979
+ this._failed = true;
31980
+ return;
31981
+ }
31982
+ stack.push(this._makeUnary(op, stack.pop()));
31983
+ return;
31984
+ }
31985
+ switch (op) {
31986
+ case TOKEN.true:
31987
+ stack.push(new PsConstNode(true));
31988
+ if (stack.length > MAX_STACK_SIZE) {
31989
+ this._failed = true;
31990
+ }
31991
+ break;
31992
+ case TOKEN.false:
31993
+ stack.push(new PsConstNode(false));
31994
+ if (stack.length > MAX_STACK_SIZE) {
31995
+ this._failed = true;
31996
+ }
31997
+ break;
31998
+ case TOKEN.dup:
31999
+ if (stack.length < 1) {
32000
+ this._failed = true;
32001
+ break;
32002
+ }
32003
+ stack.push(stack.at(-1));
32004
+ if (stack.length > MAX_STACK_SIZE) {
32005
+ this._failed = true;
32006
+ }
32007
+ break;
32008
+ case TOKEN.exch: {
32009
+ if (stack.length < 2) {
32010
+ this._failed = true;
32011
+ break;
32012
+ }
32013
+ const a = stack.pop();
32014
+ const b = stack.pop();
32015
+ stack.push(a, b);
32016
+ break;
32017
+ }
32018
+ case TOKEN.pop:
32019
+ if (stack.length < 1) {
32020
+ this._failed = true;
32021
+ break;
32022
+ }
32023
+ stack.pop();
32024
+ break;
32025
+ case TOKEN.copy: {
32026
+ if (stack.length < 1) {
32027
+ this._failed = true;
32028
+ break;
32029
+ }
32030
+ const nNode = stack.pop();
32031
+ if (nNode.type === PS_NODE.const) {
32032
+ const n = nNode.value | 0;
32033
+ if (n === 0) {
32034
+ } else if (n < 0 || n > stack.length) {
32035
+ this._failed = true;
32036
+ } else {
32037
+ stack.push(...stack.slice(-n));
32038
+ if (stack.length > MAX_STACK_SIZE) {
32039
+ this._failed = true;
32040
+ }
32041
+ }
32042
+ } else {
32043
+ this._failed = true;
32044
+ }
32045
+ break;
32046
+ }
32047
+ case TOKEN.index: {
32048
+ if (stack.length < 1) {
32049
+ this._failed = true;
32050
+ break;
32051
+ }
32052
+ const nNode = stack.pop();
32053
+ if (nNode.type === PS_NODE.const) {
32054
+ const n = nNode.value | 0;
32055
+ if (n < 0 || n >= stack.length) {
32056
+ this._failed = true;
32057
+ } else {
32058
+ stack.push(stack.at(-n - 1));
32059
+ }
32060
+ } else {
32061
+ this._failed = true;
32062
+ }
32063
+ break;
32064
+ }
32065
+ case TOKEN.roll: {
32066
+ if (stack.length < 2) {
32067
+ this._failed = true;
32068
+ break;
32069
+ }
32070
+ const jNode = stack.pop();
32071
+ const nNode = stack.pop();
32072
+ if (nNode.type === PS_NODE.const && jNode.type === PS_NODE.const) {
32073
+ const n = nNode.value | 0;
32074
+ if (n === 0) {
32075
+ } else if (n < 0 || n > stack.length) {
32076
+ this._failed = true;
32077
+ } else {
32078
+ const j = ((jNode.value | 0) % n + n) % n;
32079
+ if (j > 0) {
32080
+ const slice = stack.splice(-n, n);
32081
+ stack.push(...slice.slice(n - j), ...slice.slice(0, n - j));
32082
+ }
32083
+ }
32084
+ } else {
32085
+ this._failed = true;
32086
+ }
32087
+ break;
32088
+ }
32089
+ default:
32090
+ this._failed = true;
32091
+ break;
32092
+ }
32093
+ }
32094
+ /**
32095
+ * Create a binary tree node, applying optimizations eagerly:
32096
+ *
32097
+ * 1. Constant folding — both operands are PsConstNode → fold to PsConstNode.
32098
+ * 2. Reflexive simplifications — x−x→0, x xor x→0, x eq x→true, etc.
32099
+ * 3. Algebraic simplifications with one known operand — identity elements
32100
+ * (x+0→x, x*1→x, …), absorbing elements (x*0→0, x and false→false, …),
32101
+ * and strength reductions (x*-1→neg(x), x^0.5→sqrt(x), x^2→x*x, …).
32102
+ *
32103
+ * Recall: `first` was on top of the stack (right operand for non-commutative
32104
+ * ops), `second` was below (left operand). So `a b sub` → second=a, first=b
32105
+ * → a − b.
32106
+ */
32107
+ _makeBinary(op, first, second) {
32108
+ if (first.type === PS_NODE.const && second.type === PS_NODE.const) {
32109
+ const v = _evalBinaryConst(op, second.value, first.value);
32110
+ if (v !== void 0) {
32111
+ return new PsConstNode(v);
32112
+ }
32113
+ }
32114
+ if (_nodesEqual(first, second)) {
32115
+ switch (op) {
32116
+ case TOKEN.sub:
32117
+ return new PsConstNode(0);
32118
+ // x − x → 0
32119
+ case TOKEN.xor:
32120
+ return new PsConstNode(
32121
+ /* eslint-disable unicorn/prefer-logical-operator-over-ternary */
32122
+ first.valueType === PS_VALUE_TYPE.boolean ? false : 0
32123
+ /* eslint-enable unicorn/prefer-logical-operator-over-ternary */
32124
+ );
32125
+ // TOKEN.mod, TOKEN.div, TOKEN.idiv are NOT simplified here:
32126
+ // x op x is undefined when x = 0, so we cannot fold without knowing
32127
+ // that x is non-zero.
32128
+ case TOKEN.and:
32129
+ case TOKEN.or:
32130
+ return first;
32131
+ // x and x → x; x or x → x
32132
+ case TOKEN.min:
32133
+ case TOKEN.max:
32134
+ return first;
32135
+ // min(x,x) → x; max(x,x) → x
32136
+ case TOKEN.eq:
32137
+ case TOKEN.ge:
32138
+ case TOKEN.le:
32139
+ return new PsConstNode(true);
32140
+ case TOKEN.ne:
32141
+ case TOKEN.gt:
32142
+ case TOKEN.lt:
32143
+ return new PsConstNode(false);
32144
+ }
32145
+ }
32146
+ if (first.type === PS_NODE.const) {
32147
+ const b = first.value;
32148
+ switch (op) {
32149
+ case TOKEN.add:
32150
+ if (b === 0) {
32151
+ return second;
32152
+ }
32153
+ break;
32154
+ case TOKEN.sub:
32155
+ if (b === 0) {
32156
+ return second;
32157
+ }
32158
+ break;
32159
+ case TOKEN.mul:
32160
+ if (b === 1) {
32161
+ return second;
32162
+ }
32163
+ if (b === 0) {
32164
+ return first;
32165
+ }
32166
+ if (b === -1) {
32167
+ return this._makeUnary(TOKEN.neg, second);
32168
+ }
32169
+ break;
32170
+ case TOKEN.div:
32171
+ if (b !== 0) {
32172
+ return this._makeBinary(TOKEN.mul, new PsConstNode(1 / b), second);
32173
+ }
32174
+ break;
32175
+ case TOKEN.idiv:
32176
+ if (b === 1) {
32177
+ return second;
32178
+ }
32179
+ break;
32180
+ case TOKEN.exp:
32181
+ if (b === 1) {
32182
+ return second;
32183
+ }
32184
+ if (b === -1) {
32185
+ return this._makeBinary(TOKEN.div, second, new PsConstNode(1));
32186
+ }
32187
+ if (b === 0.5) {
32188
+ return this._makeUnary(TOKEN.sqrt, second);
32189
+ }
32190
+ if (b === 0.25) {
32191
+ const sqrtOnce = this._makeUnary(TOKEN.sqrt, second);
32192
+ return this._makeUnary(TOKEN.sqrt, sqrtOnce);
32193
+ }
32194
+ if (b === 2) {
32195
+ return this._makeBinary(TOKEN.mul, second, second);
32196
+ }
32197
+ if (b === 3) {
32198
+ return this._makeBinary(
32199
+ TOKEN.mul,
32200
+ this._makeBinary(TOKEN.mul, second, second),
32201
+ second
32202
+ );
32203
+ }
32204
+ if (b === 4) {
32205
+ const square = this._makeBinary(TOKEN.mul, second, second);
32206
+ return this._makeBinary(TOKEN.mul, square, square);
32207
+ }
32208
+ if (b === 0) {
32209
+ return new PsConstNode(1);
32210
+ }
32211
+ break;
32212
+ case TOKEN.and:
32213
+ if (b === true) {
32214
+ return second;
32215
+ }
32216
+ if (b === false) {
32217
+ return first;
32218
+ }
32219
+ break;
32220
+ case TOKEN.or:
32221
+ if (b === false) {
32222
+ return second;
32223
+ }
32224
+ if (b === true) {
32225
+ return first;
32226
+ }
32227
+ break;
32228
+ case TOKEN.min:
32229
+ if (second.type === PS_NODE.binary && second.op === TOKEN.max && second.first.type === PS_NODE.const && second.first.value >= b) {
32230
+ return first;
32231
+ }
32232
+ break;
32233
+ case TOKEN.max:
32234
+ if (second.type === PS_NODE.binary && second.op === TOKEN.min && second.first.type === PS_NODE.const && second.first.value <= b) {
32235
+ return first;
32236
+ }
32237
+ break;
32238
+ }
32239
+ }
32240
+ if (second.type === PS_NODE.const) {
32241
+ const a = second.value;
32242
+ switch (op) {
32243
+ case TOKEN.add:
32244
+ if (a === 0) {
32245
+ return first;
32246
+ }
32247
+ break;
32248
+ case TOKEN.sub:
32249
+ if (a === 0) {
32250
+ return this._makeUnary(TOKEN.neg, first);
32251
+ }
32252
+ break;
32253
+ case TOKEN.mul:
32254
+ if (a === 1) {
32255
+ return first;
32256
+ }
32257
+ if (a === 0) {
32258
+ return second;
32259
+ }
32260
+ if (a === -1) {
32261
+ return this._makeUnary(TOKEN.neg, first);
32262
+ }
32263
+ break;
32264
+ case TOKEN.and:
32265
+ if (a === true) {
32266
+ return first;
32267
+ }
32268
+ if (a === false) {
32269
+ return second;
32270
+ }
32271
+ break;
32272
+ case TOKEN.or:
32273
+ if (a === false) {
32274
+ return first;
32275
+ }
32276
+ if (a === true) {
32277
+ return second;
32278
+ }
32279
+ break;
32280
+ }
32281
+ }
32282
+ return new PsBinaryNode(
32283
+ op,
32284
+ first,
32285
+ second,
32286
+ _binaryValueType(op, first.valueType, second.valueType)
32287
+ );
32288
+ }
32289
+ /**
32290
+ * Create a unary tree node, applying optimizations eagerly:
32291
+ *
32292
+ * 1. Constant folding.
32293
+ * 2. not(comparison) → negated comparison: not(a eq b) → a ne b, etc.
32294
+ * 3. neg(a − b) → b − a.
32295
+ * 4. Double-negation: neg(neg(x)) → x, not(not(x)) → x.
32296
+ * 5. abs(neg(x)) → abs(x).
32297
+ * 6. Idempotent: f(f(x)) → f(x) for abs, ceiling, floor, round, etc.
32298
+ */
32299
+ _makeUnary(op, operand) {
32300
+ if (operand.type === PS_NODE.const) {
32301
+ const v = _evalUnaryConst(op, operand.value);
32302
+ if (v !== void 0) {
32303
+ return new PsConstNode(v);
32304
+ }
32305
+ }
32306
+ if (op === TOKEN.not && operand.type === PS_NODE.binary) {
32307
+ const negated = _PSStackToTree.#negatedComparison.get(operand.op);
32308
+ if (negated !== void 0) {
32309
+ return new PsBinaryNode(
32310
+ negated,
32311
+ operand.first,
32312
+ operand.second,
32313
+ PS_VALUE_TYPE.boolean
32314
+ );
32315
+ }
32316
+ }
32317
+ if (op === TOKEN.neg && operand.type === PS_NODE.binary && operand.op === TOKEN.sub) {
32318
+ return this._makeBinary(TOKEN.sub, operand.second, operand.first);
32319
+ }
32320
+ if (operand.type === PS_NODE.unary) {
32321
+ if (op === TOKEN.neg && operand.op === TOKEN.neg || op === TOKEN.not && operand.op === TOKEN.not) {
32322
+ return operand.operand;
32323
+ }
32324
+ if (op === TOKEN.abs && operand.op === TOKEN.neg) {
32325
+ return this._makeUnary(TOKEN.abs, operand.operand);
32326
+ }
32327
+ if (_PSStackToTree.#idempotentUnary.has(op) && op === operand.op) {
32328
+ return operand;
32329
+ }
32330
+ }
32331
+ return new PsUnaryNode(op, operand, _unaryValueType(op, operand.valueType));
32332
+ }
32333
+ /**
32334
+ * Create a ternary node, applying optimizations eagerly:
32335
+ *
32336
+ * 1. Constant condition — fold to the live branch.
32337
+ * 2. Identical branches — the condition is irrelevant, return either branch.
32338
+ * 3. Boolean branch constants — `cond ? true : false` → cond,
32339
+ * `cond ? false : true` → not(cond).
32340
+ * 4. Ternary → branchless min/max when the condition compares two numeric
32341
+ * expressions that are also the two branches.
32342
+ */
32343
+ _makeTernary(cond, then, otherwise) {
32344
+ if (cond.type === PS_NODE.const) {
32345
+ return cond.value ? then : otherwise;
32346
+ }
32347
+ if (_nodesEqual(then, otherwise)) {
32348
+ return then;
32349
+ }
32350
+ if (then.type === PS_NODE.const && otherwise.type === PS_NODE.const) {
32351
+ if (then.value === true && otherwise.value === false) {
32352
+ return cond;
32353
+ }
32354
+ if (then.value === false && otherwise.value === true) {
32355
+ return this._makeUnary(TOKEN.not, cond);
32356
+ }
32357
+ }
32358
+ if (cond.type === PS_NODE.binary) {
32359
+ const { op: cop, first: cf, second: cs } = cond;
32360
+ if (cop === TOKEN.gt || cop === TOKEN.ge) {
32361
+ if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
32362
+ return this._makeBinary(TOKEN.min, cf, cs);
32363
+ }
32364
+ if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
32365
+ return this._makeBinary(TOKEN.max, cf, cs);
32366
+ }
32367
+ } else if (cop === TOKEN.lt || cop === TOKEN.le) {
32368
+ if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
32369
+ return this._makeBinary(TOKEN.max, cf, cs);
32370
+ }
32371
+ if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
32372
+ return this._makeBinary(TOKEN.min, cf, cs);
32373
+ }
32374
+ }
32375
+ }
32376
+ return new PsTernaryNode(
32377
+ cond,
32378
+ then,
32379
+ otherwise,
32380
+ then.valueType === otherwise.valueType ? then.valueType : PS_VALUE_TYPE.unknown
32381
+ );
32382
+ }
32383
+ };
32384
+ var OP = {
32385
+ ARG: 0,
32386
+ // [ARG, idx]
32387
+ CONST: 1,
32388
+ // [CONST, val]
32389
+ STORE: 2,
32390
+ // [STORE, slot, min, max] clamp(pop()) → mem[slot]
32391
+ IF: 3,
32392
+ // [IF, target] jump when top-of-stack === 0
32393
+ JUMP: 4,
32394
+ // [JUMP, target] unconditional
32395
+ ABS: 5,
32396
+ NEG: 6,
32397
+ CEIL: 7,
32398
+ FLOOR: 8,
32399
+ ROUND: 9,
32400
+ // floor(x + 0.5)
32401
+ TRUNC: 10,
32402
+ NOT_B: 11,
32403
+ // boolean NOT
32404
+ NOT_N: 12,
32405
+ // bitwise NOT
32406
+ SQRT: 13,
32407
+ SIN: 14,
32408
+ // degrees in/out
32409
+ COS: 15,
32410
+ LN: 16,
32411
+ LOG10: 17,
32412
+ CVI: 18,
32413
+ SHIFT: 19,
32414
+ // [SHIFT, amount] +ve = left, −ve = right
32415
+ // Binary ops: second below, first on top; result = second OP first.
32416
+ ADD: 20,
32417
+ SUB: 21,
32418
+ MUL: 22,
32419
+ DIV: 23,
32420
+ // 0 when divisor is 0
32421
+ IDIV: 24,
32422
+ // 0 when divisor is 0
32423
+ MOD: 25,
32424
+ // 0 when divisor is 0
32425
+ POW: 26,
32426
+ EQ: 27,
32427
+ NE: 28,
32428
+ GT: 29,
32429
+ GE: 30,
32430
+ LT: 31,
32431
+ LE: 32,
32432
+ AND: 33,
32433
+ OR: 34,
32434
+ XOR: 35,
32435
+ ATAN: 36,
32436
+ // atan2(second, first) → degrees [0, 360)
32437
+ MIN: 37,
32438
+ MAX: 38,
32439
+ TEE_TMP: 39,
32440
+ // [TEE_TMP, slot] peek top of stack → tmp[slot], leave on stack
32441
+ LOAD_TMP: 40
32442
+ // [LOAD_TMP, slot] push tmp[slot]
32443
+ };
32444
+ var _DEG_TO_RAD = Math.PI / 180;
32445
+ var _RAD_TO_DEG = 180 / Math.PI;
32446
+ var PsJsCompiler = class {
32447
+ // Safe because JS is single-threaded.
32448
+ static #stack = new Float64Array(64);
32449
+ static #tmp = new Float64Array(64);
32450
+ constructor(domain, range) {
32451
+ this.nIn = domain.length >> 1;
32452
+ this.nOut = range.length >> 1;
32453
+ this.range = range;
32454
+ this.ir = [];
32455
+ this._tmpMap = /* @__PURE__ */ new Map();
32456
+ this._nextTmp = 0;
32457
+ }
32458
+ _compileNode(node) {
32459
+ if (node.shared) {
32460
+ const cached = this._tmpMap.get(node);
32461
+ if (cached !== void 0) {
32462
+ this.ir.push(OP.LOAD_TMP, cached);
32463
+ return true;
32464
+ }
32465
+ if (!this._compileNodeImpl(node)) {
32466
+ return false;
32467
+ }
32468
+ const slot = this._nextTmp++;
32469
+ this._tmpMap.set(node, slot);
32470
+ this.ir.push(OP.TEE_TMP, slot);
32471
+ return true;
32472
+ }
32473
+ return this._compileNodeImpl(node);
32474
+ }
32475
+ _compileNodeImpl(node) {
32476
+ switch (node.type) {
32477
+ case PS_NODE.arg:
32478
+ this.ir.push(OP.ARG, node.index);
32479
+ return true;
32480
+ case PS_NODE.const: {
32481
+ const v = node.value;
32482
+ this.ir.push(OP.CONST, typeof v === "boolean" ? Number(v) : v);
32483
+ return true;
32484
+ }
32485
+ case PS_NODE.unary:
32486
+ return this._compileUnary(node);
32487
+ case PS_NODE.binary:
32488
+ return this._compileBinary(node);
32489
+ case PS_NODE.ternary:
32490
+ return this._compileTernary(node);
32491
+ default:
32492
+ return false;
32493
+ }
32494
+ }
32495
+ _compileUnary(node) {
32496
+ const { op, operand, valueType } = node;
32497
+ if (op === TOKEN.cvr) {
32498
+ return this._compileNode(operand);
32499
+ }
32500
+ if (!this._compileNode(operand)) {
32501
+ return false;
32502
+ }
32503
+ switch (op) {
32504
+ case TOKEN.abs:
32505
+ this.ir.push(OP.ABS);
32506
+ break;
32507
+ case TOKEN.neg:
32508
+ this.ir.push(OP.NEG);
32509
+ break;
32510
+ case TOKEN.ceiling:
32511
+ this.ir.push(OP.CEIL);
32512
+ break;
32513
+ case TOKEN.floor:
32514
+ this.ir.push(OP.FLOOR);
32515
+ break;
32516
+ case TOKEN.round:
32517
+ this.ir.push(OP.ROUND);
32518
+ break;
32519
+ case TOKEN.truncate:
32520
+ this.ir.push(OP.TRUNC);
32521
+ break;
32522
+ case TOKEN.sqrt:
32523
+ this.ir.push(OP.SQRT);
32524
+ break;
32525
+ case TOKEN.sin:
32526
+ this.ir.push(OP.SIN);
32527
+ break;
32528
+ case TOKEN.cos:
32529
+ this.ir.push(OP.COS);
32530
+ break;
32531
+ case TOKEN.ln:
32532
+ this.ir.push(OP.LN);
32533
+ break;
32534
+ case TOKEN.log:
32535
+ this.ir.push(OP.LOG10);
32536
+ break;
32537
+ case TOKEN.cvi:
32538
+ this.ir.push(OP.CVI);
32539
+ break;
32540
+ case TOKEN.not:
32541
+ if (valueType === PS_VALUE_TYPE.boolean) {
32542
+ this.ir.push(OP.NOT_B);
32543
+ } else if (valueType === PS_VALUE_TYPE.numeric) {
32544
+ this.ir.push(OP.NOT_N);
32545
+ } else {
32546
+ return false;
32547
+ }
32548
+ break;
32549
+ default:
32550
+ return false;
32551
+ }
32552
+ return true;
32553
+ }
32554
+ _compileBinary(node) {
32555
+ const { op, first, second } = node;
32556
+ if (op === TOKEN.bitshift) {
32557
+ if (first.type !== PS_NODE.const || !Number.isInteger(first.value) || !this._compileNode(second)) {
32558
+ return false;
32559
+ }
32560
+ this.ir.push(OP.SHIFT, first.value);
32561
+ return true;
32562
+ }
32563
+ if (!this._compileNode(second) || !this._compileNode(first)) {
32564
+ return false;
32565
+ }
32566
+ switch (op) {
32567
+ case TOKEN.add:
32568
+ this.ir.push(OP.ADD);
32569
+ break;
32570
+ case TOKEN.sub:
32571
+ this.ir.push(OP.SUB);
32572
+ break;
32573
+ case TOKEN.mul:
32574
+ this.ir.push(OP.MUL);
32575
+ break;
32576
+ case TOKEN.div:
32577
+ this.ir.push(OP.DIV);
32578
+ break;
32579
+ case TOKEN.idiv:
32580
+ this.ir.push(OP.IDIV);
32581
+ break;
32582
+ case TOKEN.mod:
32583
+ this.ir.push(OP.MOD);
32584
+ break;
32585
+ case TOKEN.exp:
32586
+ this.ir.push(OP.POW);
32587
+ break;
32588
+ case TOKEN.eq:
32589
+ this.ir.push(OP.EQ);
32590
+ break;
32591
+ case TOKEN.ne:
32592
+ this.ir.push(OP.NE);
32593
+ break;
32594
+ case TOKEN.gt:
32595
+ this.ir.push(OP.GT);
32596
+ break;
32597
+ case TOKEN.ge:
32598
+ this.ir.push(OP.GE);
32599
+ break;
32600
+ case TOKEN.lt:
32601
+ this.ir.push(OP.LT);
32602
+ break;
32603
+ case TOKEN.le:
32604
+ this.ir.push(OP.LE);
32605
+ break;
32606
+ case TOKEN.and:
32607
+ this.ir.push(OP.AND);
32608
+ break;
32609
+ case TOKEN.or:
32610
+ this.ir.push(OP.OR);
32611
+ break;
32612
+ case TOKEN.xor:
32613
+ this.ir.push(OP.XOR);
32614
+ break;
32615
+ case TOKEN.atan:
32616
+ this.ir.push(OP.ATAN);
32617
+ break;
32618
+ case TOKEN.min:
32619
+ this.ir.push(OP.MIN);
32620
+ break;
32621
+ case TOKEN.max:
32622
+ this.ir.push(OP.MAX);
32623
+ break;
32624
+ default:
32625
+ return false;
32626
+ }
32627
+ return true;
32628
+ }
32629
+ _compileTernary(node) {
32630
+ if (!this._compileNode(node.cond)) {
32631
+ return false;
32632
+ }
32633
+ this.ir.push(OP.IF, 0);
32634
+ const ifPatch = this.ir.length - 1;
32635
+ if (!this._compileNode(node.then)) {
32636
+ return false;
32637
+ }
32638
+ this.ir.push(OP.JUMP, 0);
32639
+ const jumpPatch = this.ir.length - 1;
32640
+ this.ir[ifPatch] = this.ir.length;
32641
+ if (!this._compileNode(node.otherwise)) {
32642
+ return false;
32643
+ }
32644
+ this.ir[jumpPatch] = this.ir.length;
32645
+ return true;
32646
+ }
32647
+ compile(program) {
32648
+ const outputs = new PSStackToTree().evaluate(program, this.nIn);
32649
+ if (!outputs || outputs.length < this.nOut) {
32650
+ return null;
32651
+ }
32652
+ for (let i = 0; i < this.nOut; i++) {
32653
+ if (!this._compileNode(outputs[i])) {
32654
+ return null;
32655
+ }
32656
+ const min = this.range[i * 2];
32657
+ const max = this.range[i * 2 + 1];
32658
+ this.ir.push(OP.STORE, i, min, max);
32659
+ }
32660
+ return new Float64Array(this.ir);
32661
+ }
32662
+ static execute(ir, src, srcOffset, dest, destOffset) {
32663
+ let ip = 0, sp = 0;
32664
+ const n = ir.length;
32665
+ const stack = this.#stack;
32666
+ const tmp = this.#tmp;
32667
+ while (ip < n) {
32668
+ switch (ir[ip++] | 0) {
32669
+ case OP.ARG:
32670
+ stack[sp++] = src[srcOffset + (ir[ip++] | 0)];
32671
+ break;
32672
+ case OP.CONST:
32673
+ stack[sp++] = ir[ip++];
32674
+ break;
32675
+ case OP.STORE: {
32676
+ const slot = ir[ip++] | 0;
32677
+ const min = ir[ip++];
32678
+ const max = ir[ip++];
32679
+ dest[destOffset + slot] = MathClamp(stack[--sp], min, max);
32680
+ break;
32681
+ }
32682
+ case OP.IF: {
32683
+ const tgt = ir[ip++];
32684
+ if (stack[--sp] === 0) {
32685
+ ip = tgt;
32686
+ }
32687
+ break;
32688
+ }
32689
+ case OP.JUMP:
32690
+ ip = ir[ip];
32691
+ break;
32692
+ case OP.ABS:
32693
+ stack[sp - 1] = Math.abs(stack[sp - 1]);
32694
+ break;
32695
+ case OP.NEG:
32696
+ stack[sp - 1] = -stack[sp - 1];
32697
+ break;
32698
+ case OP.CEIL:
32699
+ stack[sp - 1] = Math.ceil(stack[sp - 1]);
32700
+ break;
32701
+ case OP.FLOOR:
32702
+ stack[sp - 1] = Math.floor(stack[sp - 1]);
32703
+ break;
32704
+ case OP.ROUND:
32705
+ stack[sp - 1] = Math.floor(stack[sp - 1] + 0.5);
32706
+ break;
32707
+ case OP.TRUNC:
32708
+ stack[sp - 1] = Math.trunc(stack[sp - 1]);
32709
+ break;
32710
+ case OP.NOT_B:
32711
+ stack[sp - 1] = stack[sp - 1] !== 0 ? 0 : 1;
32712
+ break;
32713
+ case OP.NOT_N:
32714
+ stack[sp - 1] = ~(stack[sp - 1] | 0);
32715
+ break;
32716
+ case OP.SQRT:
32717
+ stack[sp - 1] = Math.sqrt(stack[sp - 1]);
32718
+ break;
32719
+ case OP.SIN:
32720
+ stack[sp - 1] = Math.sin(stack[sp - 1] % 360 * _DEG_TO_RAD);
32721
+ break;
32722
+ case OP.COS:
32723
+ stack[sp - 1] = Math.cos(stack[sp - 1] % 360 * _DEG_TO_RAD);
32724
+ break;
32725
+ case OP.LN:
32726
+ stack[sp - 1] = Math.log(stack[sp - 1]);
32727
+ break;
32728
+ case OP.LOG10:
32729
+ stack[sp - 1] = Math.log10(stack[sp - 1]);
32730
+ break;
32731
+ case OP.CVI:
32732
+ stack[sp - 1] = Math.trunc(stack[sp - 1]) | 0;
32733
+ break;
32734
+ case OP.SHIFT: {
32735
+ const amt = ir[ip++];
32736
+ const v = stack[sp - 1] | 0;
32737
+ if (amt > 0) {
32738
+ stack[sp - 1] = v << amt;
32739
+ } else if (amt < 0) {
32740
+ stack[sp - 1] = v >> -amt;
32741
+ } else {
32742
+ stack[sp - 1] = v;
32743
+ }
32744
+ break;
32745
+ }
32746
+ case OP.ADD: {
32747
+ const b = stack[--sp];
32748
+ stack[sp - 1] += b;
32749
+ break;
32750
+ }
32751
+ case OP.SUB: {
32752
+ const b = stack[--sp];
32753
+ stack[sp - 1] -= b;
32754
+ break;
32755
+ }
32756
+ case OP.MUL: {
32757
+ const b = stack[--sp];
32758
+ stack[sp - 1] *= b;
32759
+ break;
32760
+ }
32761
+ case OP.DIV: {
32762
+ const b = stack[--sp];
32763
+ stack[sp - 1] = b !== 0 ? stack[sp - 1] / b : 0;
32764
+ break;
32765
+ }
32766
+ case OP.IDIV: {
32767
+ const b = stack[--sp];
32768
+ stack[sp - 1] = b !== 0 ? Math.trunc(stack[sp - 1] / b) : 0;
32769
+ break;
32770
+ }
32771
+ case OP.MOD: {
32772
+ const b = stack[--sp];
32773
+ stack[sp - 1] = b !== 0 ? stack[sp - 1] % b : 0;
32774
+ break;
32775
+ }
32776
+ case OP.POW: {
32777
+ const b = stack[--sp];
32778
+ stack[sp - 1] **= b;
32779
+ break;
32780
+ }
32781
+ case OP.EQ: {
32782
+ const b = stack[--sp];
32783
+ stack[sp - 1] = stack[sp - 1] === b ? 1 : 0;
32784
+ break;
32785
+ }
32786
+ case OP.NE: {
32787
+ const b = stack[--sp];
32788
+ stack[sp - 1] = stack[sp - 1] !== b ? 1 : 0;
32789
+ break;
32790
+ }
32791
+ case OP.GT: {
32792
+ const b = stack[--sp];
32793
+ stack[sp - 1] = stack[sp - 1] > b ? 1 : 0;
32794
+ break;
32795
+ }
32796
+ case OP.GE: {
32797
+ const b = stack[--sp];
32798
+ stack[sp - 1] = stack[sp - 1] >= b ? 1 : 0;
32799
+ break;
32800
+ }
32801
+ case OP.LT: {
32802
+ const b = stack[--sp];
32803
+ stack[sp - 1] = stack[sp - 1] < b ? 1 : 0;
32804
+ break;
32805
+ }
32806
+ case OP.LE: {
32807
+ const b = stack[--sp];
32808
+ stack[sp - 1] = stack[sp - 1] <= b ? 1 : 0;
32809
+ break;
32810
+ }
32811
+ case OP.AND: {
32812
+ const b = stack[--sp] | 0;
32813
+ stack[sp - 1] = (stack[sp - 1] | 0) & b;
32814
+ break;
32815
+ }
32816
+ case OP.OR: {
32817
+ const b = stack[--sp] | 0;
32818
+ stack[sp - 1] = stack[sp - 1] | 0 | b;
32819
+ break;
32820
+ }
32821
+ case OP.XOR: {
32822
+ const b = stack[--sp] | 0;
32823
+ stack[sp - 1] = (stack[sp - 1] | 0) ^ b;
32824
+ break;
32825
+ }
32826
+ case OP.ATAN: {
32827
+ const b = stack[--sp];
32828
+ const deg = Math.atan2(stack[sp - 1], b) * _RAD_TO_DEG;
32829
+ stack[sp - 1] = deg < 0 ? deg + 360 : deg;
32830
+ break;
32831
+ }
32832
+ case OP.MIN: {
32833
+ const b = stack[--sp];
32834
+ stack[sp - 1] = Math.min(stack[sp - 1], b);
32835
+ break;
32836
+ }
32837
+ case OP.MAX: {
32838
+ const b = stack[--sp];
32839
+ stack[sp - 1] = Math.max(stack[sp - 1], b);
32840
+ break;
32841
+ }
32842
+ case OP.TEE_TMP:
32843
+ tmp[ir[ip++] | 0] = stack[sp - 1];
32844
+ break;
32845
+ case OP.LOAD_TMP:
32846
+ stack[sp++] = tmp[ir[ip++] | 0];
32847
+ break;
32848
+ }
32849
+ }
32850
+ }
32851
+ };
32852
+ var PSStackBasedInterpreter = class {
32853
+ // Safe: JS is single-threaded.
32854
+ static #stack = new Float64Array(100);
32855
+ static #sp = 0;
32856
+ static #push(v) {
32857
+ if (this.#sp < this.#stack.length) {
32858
+ this.#stack[this.#sp++] = v;
32859
+ }
32860
+ }
32861
+ static #execOp(op) {
32862
+ const stack = this.#stack;
32863
+ switch (op) {
32864
+ case TOKEN.true:
32865
+ this.#push(1);
32866
+ break;
32867
+ case TOKEN.false:
32868
+ this.#push(0);
32869
+ break;
32870
+ case TOKEN.abs:
32871
+ stack[this.#sp - 1] = Math.abs(stack[this.#sp - 1]);
32872
+ break;
32873
+ case TOKEN.neg:
32874
+ stack[this.#sp - 1] = -stack[this.#sp - 1];
32875
+ break;
32876
+ case TOKEN.ceiling:
32877
+ stack[this.#sp - 1] = Math.ceil(stack[this.#sp - 1]);
32878
+ break;
32879
+ case TOKEN.floor:
32880
+ stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1]);
32881
+ break;
32882
+ case TOKEN.round:
32883
+ stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1] + 0.5);
32884
+ break;
32885
+ case TOKEN.truncate:
32886
+ stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]);
32887
+ break;
32888
+ case TOKEN.sqrt:
32889
+ stack[this.#sp - 1] = Math.sqrt(stack[this.#sp - 1]);
32890
+ break;
32891
+ case TOKEN.sin:
32892
+ stack[this.#sp - 1] = Math.sin(
32893
+ stack[this.#sp - 1] % 360 * _DEG_TO_RAD
32894
+ );
32895
+ break;
32896
+ case TOKEN.cos:
32897
+ stack[this.#sp - 1] = Math.cos(
32898
+ stack[this.#sp - 1] % 360 * _DEG_TO_RAD
32899
+ );
32900
+ break;
32901
+ case TOKEN.ln:
32902
+ stack[this.#sp - 1] = Math.log(stack[this.#sp - 1]);
32903
+ break;
32904
+ case TOKEN.log:
32905
+ stack[this.#sp - 1] = Math.log10(stack[this.#sp - 1]);
32906
+ break;
32907
+ case TOKEN.cvi:
32908
+ stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]) | 0;
32909
+ break;
32910
+ case TOKEN.cvr:
32911
+ break;
32912
+ // values are already f64
32913
+ case TOKEN.not: {
32914
+ const v = stack[this.#sp - 1];
32915
+ stack[this.#sp - 1] = v === 0 || v === 1 ? 1 - v : ~(v | 0);
32916
+ break;
32917
+ }
32918
+ case TOKEN.add: {
32919
+ const b = stack[--this.#sp];
32920
+ stack[this.#sp - 1] += b;
32921
+ break;
32922
+ }
32923
+ case TOKEN.sub: {
32924
+ const b = stack[--this.#sp];
32925
+ stack[this.#sp - 1] -= b;
32926
+ break;
32927
+ }
32928
+ case TOKEN.mul: {
32929
+ const b = stack[--this.#sp];
32930
+ stack[this.#sp - 1] *= b;
32931
+ break;
32932
+ }
32933
+ case TOKEN.div: {
32934
+ const b = stack[--this.#sp];
32935
+ stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] / b : 0;
32936
+ break;
32937
+ }
32938
+ case TOKEN.idiv: {
32939
+ const b = stack[--this.#sp];
32940
+ stack[this.#sp - 1] = b !== 0 ? Math.trunc(stack[this.#sp - 1] / b) : 0;
32941
+ break;
32942
+ }
32943
+ case TOKEN.mod: {
32944
+ const b = stack[--this.#sp];
32945
+ stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] % b : 0;
32946
+ break;
32947
+ }
32948
+ case TOKEN.exp: {
32949
+ const b = stack[--this.#sp];
32950
+ stack[this.#sp - 1] **= b;
32951
+ break;
32952
+ }
32953
+ case TOKEN.atan: {
32954
+ const dx = stack[--this.#sp];
32955
+ const deg = Math.atan2(stack[this.#sp - 1], dx) * _RAD_TO_DEG;
32956
+ stack[this.#sp - 1] = deg < 0 ? deg + 360 : deg;
32957
+ break;
32958
+ }
32959
+ case TOKEN.eq: {
32960
+ const b = stack[--this.#sp];
32961
+ stack[this.#sp - 1] = stack[this.#sp - 1] === b ? 1 : 0;
32962
+ break;
32963
+ }
32964
+ case TOKEN.ne: {
32965
+ const b = stack[--this.#sp];
32966
+ stack[this.#sp - 1] = stack[this.#sp - 1] !== b ? 1 : 0;
32967
+ break;
32968
+ }
32969
+ case TOKEN.gt: {
32970
+ const b = stack[--this.#sp];
32971
+ stack[this.#sp - 1] = stack[this.#sp - 1] > b ? 1 : 0;
32972
+ break;
32973
+ }
32974
+ case TOKEN.ge: {
32975
+ const b = stack[--this.#sp];
32976
+ stack[this.#sp - 1] = stack[this.#sp - 1] >= b ? 1 : 0;
32977
+ break;
32978
+ }
32979
+ case TOKEN.lt: {
32980
+ const b = stack[--this.#sp];
32981
+ stack[this.#sp - 1] = stack[this.#sp - 1] < b ? 1 : 0;
32982
+ break;
32983
+ }
32984
+ case TOKEN.le: {
32985
+ const b = stack[--this.#sp];
32986
+ stack[this.#sp - 1] = stack[this.#sp - 1] <= b ? 1 : 0;
32987
+ break;
32988
+ }
32989
+ case TOKEN.and: {
32990
+ const b = stack[--this.#sp] | 0;
32991
+ stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) & b;
32992
+ break;
32993
+ }
32994
+ case TOKEN.or: {
32995
+ const b = stack[--this.#sp] | 0;
32996
+ stack[this.#sp - 1] = stack[this.#sp - 1] | 0 | b;
32997
+ break;
32998
+ }
32999
+ case TOKEN.xor: {
33000
+ const b = stack[--this.#sp] | 0;
33001
+ stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) ^ b;
33002
+ break;
33003
+ }
33004
+ case TOKEN.bitshift: {
33005
+ const amt = stack[--this.#sp] | 0;
33006
+ const v = stack[this.#sp - 1] | 0;
33007
+ stack[this.#sp - 1] = amt > 0 ? v << amt : v >> -amt;
33008
+ break;
33009
+ }
33010
+ case TOKEN.min: {
33011
+ const b = stack[--this.#sp];
33012
+ stack[this.#sp - 1] = Math.min(stack[this.#sp - 1], b);
33013
+ break;
33014
+ }
33015
+ case TOKEN.max: {
33016
+ const b = stack[--this.#sp];
33017
+ stack[this.#sp - 1] = Math.max(stack[this.#sp - 1], b);
33018
+ break;
33019
+ }
33020
+ case TOKEN.dup:
33021
+ this.#push(stack[this.#sp - 1]);
33022
+ break;
33023
+ case TOKEN.exch: {
33024
+ const a = stack[--this.#sp];
33025
+ const b = stack[--this.#sp];
33026
+ this.#push(a);
33027
+ this.#push(b);
33028
+ break;
33029
+ }
33030
+ case TOKEN.pop:
33031
+ this.#sp--;
33032
+ break;
33033
+ case TOKEN.copy: {
33034
+ const n = Math.trunc(stack[--this.#sp]);
33035
+ const base = this.#sp - n;
33036
+ for (let k = 0; k < n; k++) {
33037
+ this.#push(stack[base + k]);
33038
+ }
33039
+ break;
33040
+ }
33041
+ case TOKEN.index: {
33042
+ const i = Math.trunc(stack[--this.#sp]);
33043
+ this.#push(stack[this.#sp - 1 - i]);
33044
+ break;
33045
+ }
33046
+ case TOKEN.roll: {
33047
+ const j = Math.trunc(stack[--this.#sp]);
33048
+ const n = Math.trunc(stack[--this.#sp]);
33049
+ if (n > 1 && j !== 0) {
33050
+ const mod = (j % n + n) % n;
33051
+ if (mod !== 0) {
33052
+ const base = this.#sp - n;
33053
+ const sub = stack.slice(base, this.#sp);
33054
+ for (let k = 0; k < n; k++) {
33055
+ stack[base + k] = sub[(k - mod + n) % n];
33056
+ }
33057
+ }
33058
+ }
33059
+ break;
33060
+ }
33061
+ }
33062
+ }
33063
+ static #execBlock(instructions) {
33064
+ for (const instr of instructions) {
33065
+ switch (instr.type) {
33066
+ case PS_NODE.number:
33067
+ this.#push(instr.value);
33068
+ break;
33069
+ case PS_NODE.operator:
33070
+ this.#execOp(instr.op);
33071
+ break;
33072
+ case PS_NODE.if:
33073
+ if (this.#stack[--this.#sp] !== 0) {
33074
+ this.#execBlock(instr.then.instructions);
33075
+ }
33076
+ break;
33077
+ case PS_NODE.ifelse:
33078
+ if (this.#stack[--this.#sp] !== 0) {
33079
+ this.#execBlock(instr.then.instructions);
33080
+ } else {
33081
+ this.#execBlock(instr.otherwise.instructions);
33082
+ }
33083
+ break;
33084
+ }
33085
+ }
33086
+ }
33087
+ /**
33088
+ * @param {import("./ast.js").PsProgram} program
33089
+ * @param {number[]} domain – flat [min0,max0, …]
33090
+ * @param {number[]} range – flat [min0,max0, …]
33091
+ * @returns {Function} – `(src, srcOffset, dest, destOffset) => void`
33092
+ */
33093
+ static build(program, domain, range) {
33094
+ const nIn = domain.length >> 1;
33095
+ const nOut = range.length >> 1;
33096
+ const { instructions } = program.body;
33097
+ return (src, srcOffset, dest, destOffset) => {
33098
+ this.#sp = 0;
33099
+ for (let i = 0; i < nIn; i++) {
33100
+ this.#push(src[srcOffset + i]);
33101
+ }
33102
+ this.#execBlock(instructions);
33103
+ const base = this.#sp - nOut;
33104
+ for (let i = 0; i < nOut; i++) {
33105
+ const v = base + i >= 0 ? this.#stack[base + i] : 0;
33106
+ dest[destOffset + i] = MathClamp(v, range[i * 2], range[i * 2 + 1]);
33107
+ }
33108
+ };
33109
+ }
33110
+ };
33111
+ function buildPostScriptJsFunction(source, domain, range, forceInterpreter = false) {
33112
+ const program = parsePostScriptFunction(source);
33113
+ const ir = !forceInterpreter && new PsJsCompiler(domain, range).compile(program);
33114
+ if (ir) {
33115
+ return (src, srcOffset, dest, destOffset) => {
33116
+ PsJsCompiler.execute(ir, src, srcOffset, dest, destOffset);
33117
+ };
33118
+ }
33119
+ return PSStackBasedInterpreter.build(program, domain, range);
33120
+ }
30513
33121
  var PdfError = class extends Error {
30514
33122
  constructor(code, message) {
30515
33123
  super(message);
@@ -41590,6 +44198,25 @@ var __webpack_exports__JpxImage = __webpack_exports__.JpxImage;
41590
44198
  var __webpack_exports__VerbosityLevel = __webpack_exports__.VerbosityLevel;
41591
44199
  var __webpack_exports__getVerbosityLevel = __webpack_exports__.getVerbosityLevel;
41592
44200
  var __webpack_exports__setVerbosityLevel = __webpack_exports__.setVerbosityLevel;
44201
+ function createCalibratedColorSpace(doc, family, parameters) {
44202
+ const dict = doc.resolveDict(parameters);
44203
+ const array = (key) => {
44204
+ const value = dict ? doc.resolveArray(dictGet(dict, key)) : void 0;
44205
+ return value?.items.map((item) => {
44206
+ const number = doc.resolve(item);
44207
+ return number?.kind === "number" ? number.value : 0;
44208
+ });
44209
+ };
44210
+ const whitePoint = array("WhitePoint") ?? [0.95047, 1, 1.08883];
44211
+ const blackPoint = array("BlackPoint");
44212
+ if (family === "CalGray") {
44213
+ const gamma = dict ? doc.resolve(dictGet(dict, "Gamma")) : void 0;
44214
+ return new CalGrayCS(whitePoint, blackPoint, gamma?.kind === "number" ? gamma.value : void 0);
44215
+ }
44216
+ if (family === "CalRGB") return new CalRGBCS(whitePoint, blackPoint, array("Gamma"), array("Matrix"));
44217
+ return new LabCS(whitePoint, blackPoint, array("Range"));
44218
+ }
44219
+ var cmykColorSpace = new DeviceCmykCS();
41593
44220
  function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
41594
44221
  if (!csNode) return { colorSpace: "rgb", colorSpaceLabel: "rgb", components: 3 };
41595
44222
  const resolved = doc.resolve(csNode);
@@ -41630,7 +44257,7 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
41630
44257
  palette = lookupNode.bytes;
41631
44258
  }
41632
44259
  let resolvedBaseComp = baseInfo.components;
41633
- if (palette && (baseInfo.isLab || baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calRgbGamma !== void 0 || baseInfo.calGrayGamma !== void 0)) {
44260
+ if (palette && (baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calibrated !== void 0)) {
41634
44261
  const numEntries = Math.max(1, Math.min(hival + 1, Math.floor(palette.length / Math.max(1, baseInfo.components))));
41635
44262
  const rgbaPal = decodeSamplesToRgba(palette, numEntries, 1, 8, baseInfo);
41636
44263
  const rgbPal = new Uint8Array(numEntries * 3);
@@ -41660,74 +44287,21 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
41660
44287
  }
41661
44288
  return { colorSpace: "rgb", colorSpaceLabel: "icc", components: 3 };
41662
44289
  }
41663
- if (kindName === "CalGray") {
41664
- const calDict = doc.resolveDict(resolved.items[1]);
41665
- const gammaNode = calDict ? doc.resolve(dictGet(calDict, "Gamma")) : void 0;
41666
- const gamma = gammaNode?.kind === "number" && gammaNode.value > 0 ? gammaNode.value : 1;
41667
- return { colorSpace: "gray", colorSpaceLabel: "cal-gray", components: 1, calGrayGamma: gamma };
41668
- }
41669
- if (kindName === "CalRGB") {
41670
- const calDict = doc.resolveDict(resolved.items[1]);
41671
- const gammaArr = calDict ? doc.resolveArray(dictGet(calDict, "Gamma")) : void 0;
41672
- let calRgbGamma = [1, 1, 1];
41673
- if (gammaArr && gammaArr.items.length >= 3) {
41674
- const gNums = gammaArr.items.slice(0, 3).map((it) => {
41675
- const r = doc.resolve(it);
41676
- return r?.kind === "number" && r.value > 0 ? r.value : 1;
41677
- });
41678
- calRgbGamma = [gNums[0], gNums[1], gNums[2]];
41679
- }
41680
- const matArr = calDict ? doc.resolveArray(dictGet(calDict, "Matrix")) : void 0;
41681
- let calRgbMatrix;
41682
- if (matArr && matArr.items.length >= 9) {
41683
- calRgbMatrix = matArr.items.slice(0, 9).map((it) => {
41684
- const r = doc.resolve(it);
41685
- return r?.kind === "number" ? r.value : 0;
41686
- });
41687
- }
44290
+ if (kindName === "CalGray" || kindName === "CalRGB" || kindName === "Lab") {
44291
+ const calibrated = createCalibratedColorSpace(doc, kindName, resolved.items[1]);
41688
44292
  return {
41689
- colorSpace: "rgb",
41690
- colorSpaceLabel: "cal-rgb",
41691
- components: 3,
41692
- calRgbGamma,
41693
- calRgbMatrix
44293
+ colorSpace: kindName === "CalGray" ? "gray" : "rgb",
44294
+ colorSpaceLabel: kindName === "CalGray" ? "cal-gray" : kindName === "CalRGB" ? "cal-rgb" : "lab",
44295
+ components: kindName === "CalGray" ? 1 : 3,
44296
+ calibrated
41694
44297
  };
41695
44298
  }
41696
- if (kindName === "Lab") {
41697
- const labDict = doc.resolveDict(resolved.items[1]);
41698
- const rangeArr = labDict ? doc.resolveArray(dictGet(labDict, "Range")) : void 0;
41699
- let labRange = [-100, 100, -100, 100];
41700
- if (rangeArr && rangeArr.items.length >= 4) {
41701
- const nums = rangeArr.items.slice(0, 4).map((it) => {
41702
- const r = doc.resolve(it);
41703
- return r?.kind === "number" ? r.value : 0;
41704
- });
41705
- labRange = [nums[0], nums[1], nums[2], nums[3]];
41706
- }
41707
- return { colorSpace: "rgb", colorSpaceLabel: "lab", components: 3, isLab: true, labRange };
41708
- }
41709
44299
  if (kindName === "Separation" || kindName === "DeviceN") {
41710
44300
  const isDevN = kindName === "DeviceN";
41711
44301
  const namesArr = isDevN ? doc.resolveArray(resolved.items[1]) : void 0;
41712
44302
  const devNComponents = isDevN && namesArr ? Math.max(1, namesArr.items.length) : 1;
41713
44303
  const altInfo = resolveColorSpaceInfo(doc, resolved.items[2], resourcesDict);
41714
44304
  const altSpace = altInfo.colorSpace === "cmyk" ? "cmyk" : altInfo.colorSpace === "gray" ? "gray" : "rgb";
41715
- const fnResolved = doc.resolve(resolved.items[3]);
41716
- const fnDict = fnResolved?.kind === "stream" ? fnResolved.dict : fnResolved?.kind === "dict" ? fnResolved : void 0;
41717
- const ftNode = fnDict ? doc.resolve(dictGet(fnDict, "FunctionType")) : void 0;
41718
- const tintFunctionType = ftNode?.kind === "number" ? ftNode.value : 2;
41719
- const c0Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C0")) : void 0;
41720
- const c1Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C1")) : void 0;
41721
- const nNode = fnDict ? doc.resolve(dictGet(fnDict, "N")) : void 0;
41722
- const c0 = c0Arr ? c0Arr.items.map((it) => {
41723
- const r = doc.resolve(it);
41724
- return r?.kind === "number" ? r.value : 0;
41725
- }) : altSpace === "cmyk" ? [0, 0, 0, 0] : altSpace === "gray" ? [1] : [1, 1, 1];
41726
- const c1 = c1Arr ? c1Arr.items.map((it) => {
41727
- const r = doc.resolve(it);
41728
- return r?.kind === "number" ? r.value : 0;
41729
- }) : altSpace === "cmyk" ? [0, 0, 0, 1] : altSpace === "gray" ? [0] : [0, 0, 0];
41730
- const sepN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
41731
44305
  return {
41732
44306
  colorSpace: altSpace,
41733
44307
  colorSpaceLabel: isDevN ? "devn" : "sep",
@@ -41735,12 +44309,9 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
41735
44309
  isSeparation: !isDevN,
41736
44310
  isDeviceN: isDevN,
41737
44311
  separationAltSpace: altSpace,
41738
- separationC0: c0,
41739
- separationC1: c1,
41740
- separationN: sepN,
44312
+ alternateCalibrated: altInfo.calibrated,
41741
44313
  tintFunctionDoc: doc,
41742
- tintFunctionNode: resolved.items[3],
41743
- tintFunctionType
44314
+ tintFunctionNode: resolved.items[3]
41744
44315
  };
41745
44316
  }
41746
44317
  }
@@ -41890,141 +44461,55 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
41890
44461
  const rgba = new Uint8Array(width * height * 4);
41891
44462
  const pixelCount = width * height;
41892
44463
  if (csInfo.isSeparation || csInfo.isDeviceN) {
41893
- const c0 = csInfo.separationC0 ?? [1, 1, 1];
41894
- const c1 = csInfo.separationC1 ?? [0, 0, 0];
41895
- const expN = csInfo.separationN ?? 1;
41896
44464
  const alt = csInfo.separationAltSpace ?? "rgb";
41897
44465
  const numCh = Math.max(1, csInfo.components);
41898
44466
  const step = bpc === 16 ? 2 : 1;
41899
- const useGenericTintFn = csInfo.tintFunctionDoc !== void 0 && csInfo.tintFunctionNode !== void 0 && (csInfo.tintFunctionType === 0 || csInfo.tintFunctionType === 3 || csInfo.tintFunctionType === 4);
41900
44467
  for (let p = 0; p < pixelCount; p++) {
41901
44468
  const chVals = [];
41902
- let wSum = 0;
41903
44469
  for (let ch3 = 0; ch3 < numCh; ch3++) {
41904
44470
  const sRaw = (rawSamples[(p * numCh + ch3) * step] ?? 0) / 255;
41905
- const tRemapped = remapUnitSampleWithDecode(sRaw, ch3, decodePairs);
41906
- chVals.push(tRemapped);
41907
- wSum += Math.pow(Math.max(0, Math.min(1, tRemapped)), expN);
41908
- }
41909
- if (useGenericTintFn) {
41910
- const outComps = evalShadingFunctionToComponents(
41911
- csInfo.tintFunctionDoc,
41912
- csInfo.tintFunctionNode,
41913
- chVals
41914
- );
41915
- if (alt === "cmyk") {
41916
- const c = outComps[0] ?? 0;
41917
- const m = outComps[1] ?? 0;
41918
- const y = outComps[2] ?? 0;
41919
- const k = outComps[3] ?? 0;
41920
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, (1 - c) * (1 - k))) * 255);
41921
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, (1 - m) * (1 - k))) * 255);
41922
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, (1 - y) * (1 - k))) * 255);
41923
- } else if (alt === "gray") {
41924
- const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
41925
- rgba[p * 4] = gByte;
41926
- rgba[p * 4 + 1] = gByte;
41927
- rgba[p * 4 + 2] = gByte;
41928
- } else {
41929
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
41930
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
41931
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
41932
- }
41933
- rgba[p * 4 + 3] = 255;
41934
- continue;
44471
+ chVals.push(remapUnitSampleWithDecode(sRaw, ch3, decodePairs));
41935
44472
  }
41936
- const w = Math.max(0, Math.min(1, wSum));
41937
- if (alt === "cmyk") {
41938
- const c = (c0[0] ?? 0) + w * ((c1[0] ?? 0) - (c0[0] ?? 0));
41939
- const m = (c0[1] ?? 0) + w * ((c1[1] ?? 0) - (c0[1] ?? 0));
41940
- const y = (c0[2] ?? 0) + w * ((c1[2] ?? 0) - (c0[2] ?? 0));
41941
- const k = (c0[3] ?? 0) + w * ((c1[3] ?? 1) - (c0[3] ?? 0));
41942
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, (1 - c) * (1 - k))) * 255);
41943
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, (1 - m) * (1 - k))) * 255);
41944
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, (1 - y) * (1 - k))) * 255);
44473
+ const outComps = evalShadingFunctionToComponents(
44474
+ csInfo.tintFunctionDoc,
44475
+ csInfo.tintFunctionNode,
44476
+ chVals
44477
+ );
44478
+ if (csInfo.alternateCalibrated) {
44479
+ rgba.set(csInfo.alternateCalibrated.getRgb(outComps, 0), p * 4);
44480
+ } else if (alt === "cmyk") {
44481
+ rgba.set(cmykColorSpace.getRgb([outComps[0] ?? 0, outComps[1] ?? 0, outComps[2] ?? 0, outComps[3] ?? 0], 0), p * 4);
41945
44482
  } else if (alt === "gray") {
41946
- const gVal = (c0[0] ?? 1) + w * ((c1[0] ?? 0) - (c0[0] ?? 1));
41947
- const gByte = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
44483
+ const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
41948
44484
  rgba[p * 4] = gByte;
41949
44485
  rgba[p * 4 + 1] = gByte;
41950
44486
  rgba[p * 4 + 2] = gByte;
41951
44487
  } else {
41952
- const rVal = (c0[0] ?? 1) + w * ((c1[0] ?? 0) - (c0[0] ?? 1));
41953
- const gVal = (c0[1] ?? 1) + w * ((c1[1] ?? 0) - (c0[1] ?? 1));
41954
- const bVal = (c0[2] ?? 1) + w * ((c1[2] ?? 0) - (c0[2] ?? 1));
41955
- rgba[p * 4] = Math.round(Math.max(0, Math.min(1, rVal)) * 255);
41956
- rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
41957
- rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, bVal)) * 255);
44488
+ rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
44489
+ rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
44490
+ rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
41958
44491
  }
41959
44492
  rgba[p * 4 + 3] = 255;
41960
44493
  }
41961
- } else if (csInfo.isLab) {
41962
- const [amin, amax, bmin, bmax] = csInfo.labRange ?? [-100, 100, -100, 100];
41963
- const invF = (t) => t > 6 / 29 ? t * t * t : 3 * (6 / 29) * (6 / 29) * (t - 4 / 29);
41964
- const toSrgb = (u) => {
41965
- const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
41966
- return Math.round(Math.max(0, Math.min(1, c)) * 255);
41967
- };
44494
+ } else if (csInfo.calibrated?.name === "Lab") {
44495
+ const { amin, amax, bmin, bmax } = csInfo.calibrated;
44496
+ const step = bpc === 16 ? 2 : 1;
41968
44497
  for (let p = 0; p < pixelCount; p++) {
41969
- const s0 = (rawSamples[p * 3] ?? 0) / 255;
41970
- const s1 = (rawSamples[p * 3 + 1] ?? 128) / 255;
41971
- const s2 = (rawSamples[p * 3 + 2] ?? 128) / 255;
41972
- const L = s0 * 100;
41973
- if (L <= 0.01) {
41974
- rgba[p * 4] = 0;
41975
- rgba[p * 4 + 1] = 0;
41976
- rgba[p * 4 + 2] = 0;
41977
- rgba[p * 4 + 3] = 255;
41978
- continue;
41979
- }
41980
- const a = amin + s1 * (amax - amin);
41981
- const b = bmin + s2 * (bmax - bmin);
41982
- const fy = (L + 16) / 116;
41983
- const fx = fy + a / 500;
41984
- const fz = fy - b / 200;
41985
- const X = 0.95047 * invF(fx);
41986
- const Y = 1 * invF(fy);
41987
- const Z = 1.08883 * invF(fz);
41988
- const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
41989
- const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
41990
- const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
41991
- rgba[p * 4] = toSrgb(linR);
41992
- rgba[p * 4 + 1] = toSrgb(linG);
41993
- rgba[p * 4 + 2] = toSrgb(linB);
44498
+ const L = (rawSamples[p * 3 * step] ?? 0) / 255 * 100;
44499
+ const a = amin + (rawSamples[(p * 3 + 1) * step] ?? 128) / 255 * (amax - amin);
44500
+ const b = bmin + (rawSamples[(p * 3 + 2) * step] ?? 128) / 255 * (bmax - bmin);
44501
+ rgba.set(csInfo.calibrated.getRgb([L, a, b], 0), p * 4);
41994
44502
  rgba[p * 4 + 3] = 255;
41995
44503
  }
41996
44504
  } else if (csInfo.colorSpace === "rgb") {
41997
- const hasCalRgb = Boolean(csInfo.calRgbGamma || csInfo.calRgbMatrix);
41998
- const toSrgbByte = (u) => {
41999
- const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
42000
- return Math.round(Math.max(0, Math.min(1, c)) * 255);
42001
- };
42002
44505
  const writeRgbPixel = (p, rByte, gByte, bByte) => {
42003
- let rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
42004
- let gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
42005
- let bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
42006
- if (hasCalRgb) {
42007
- const [gr, gg, gb] = csInfo.calRgbGamma ?? [1, 1, 1];
42008
- const ag = Math.pow(rU, gr);
42009
- const bg = Math.pow(gU, gg);
42010
- const cg = Math.pow(bU, gb);
42011
- if (csInfo.calRgbMatrix && csInfo.calRgbMatrix.length >= 9) {
42012
- const m = csInfo.calRgbMatrix;
42013
- const X = m[0] * ag + m[3] * bg + m[6] * cg;
42014
- const Y = m[1] * ag + m[4] * bg + m[7] * cg;
42015
- const Z = m[2] * ag + m[5] * bg + m[8] * cg;
42016
- const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
42017
- const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
42018
- const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
42019
- rgba[p * 4] = toSrgbByte(linR);
42020
- rgba[p * 4 + 1] = toSrgbByte(linG);
42021
- rgba[p * 4 + 2] = toSrgbByte(linB);
42022
- rgba[p * 4 + 3] = 255;
42023
- return;
42024
- }
42025
- rU = ag;
42026
- gU = bg;
42027
- bU = cg;
44506
+ const rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
44507
+ const gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
44508
+ const bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
44509
+ if (csInfo.calibrated) {
44510
+ rgba.set(csInfo.calibrated.getRgb([rU, gU, bU], 0), p * 4);
44511
+ rgba[p * 4 + 3] = 255;
44512
+ return;
42028
44513
  }
42029
44514
  rgba[p * 4] = Math.round(rU * 255);
42030
44515
  rgba[p * 4 + 1] = Math.round(gU * 255);
@@ -42044,10 +44529,11 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
42044
44529
  }
42045
44530
  } else if (csInfo.colorSpace === "gray") {
42046
44531
  const writeGrayPixel = (p, gByte) => {
42047
- let gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
42048
- if (csInfo.calGrayGamma && csInfo.calGrayGamma !== 1) {
42049
- const lin = Math.pow(gU, csInfo.calGrayGamma);
42050
- gU = lin <= 31308e-7 ? 12.92 * lin : 1.055 * Math.pow(lin, 1 / 2.4) - 0.055;
44532
+ const gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
44533
+ if (csInfo.calibrated) {
44534
+ rgba.set(csInfo.calibrated.getRgb([gU], 0), p * 4);
44535
+ rgba[p * 4 + 3] = 255;
44536
+ return;
42051
44537
  }
42052
44538
  const outG = Math.round(Math.max(0, Math.min(1, gU)) * 255);
42053
44539
  rgba[p * 4] = outG;
@@ -42103,9 +44589,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
42103
44589
  const m = remapUnitSampleWithDecode((rawSamples[p * stride + chStep] ?? 0) / 255, 1, decodePairs);
42104
44590
  const y = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 2] ?? 0) / 255, 2, decodePairs);
42105
44591
  const k = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 3] ?? 0) / 255, 3, decodePairs);
42106
- rgba[p * 4] = Math.round((1 - c) * (1 - k) * 255);
42107
- rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
42108
- rgba[p * 4 + 2] = Math.round((1 - y) * (1 - k) * 255);
44592
+ rgba.set(cmykColorSpace.getRgb([c, m, y, k], 0), p * 4);
42109
44593
  rgba[p * 4 + 3] = 255;
42110
44594
  }
42111
44595
  } else if (csInfo.colorSpace === "index") {
@@ -42143,9 +44627,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
42143
44627
  const m = pal[idx * 4 + 1] / 255;
42144
44628
  const yel = pal[idx * 4 + 2] / 255;
42145
44629
  const k = pal[idx * 4 + 3] / 255;
42146
- rgba[p * 4] = Math.round((1 - c) * (1 - k) * 255);
42147
- rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
42148
- rgba[p * 4 + 2] = Math.round((1 - yel) * (1 - k) * 255);
44630
+ rgba.set(cmykColorSpace.getRgb([c, m, yel, k], 0), p * 4);
42149
44631
  } else {
42150
44632
  rgba[p * 4] = pal[idx * baseComp];
42151
44633
  rgba[p * 4 + 1] = pal[idx * baseComp + 1];
@@ -42400,6 +44882,7 @@ function decodeInlineImageNodeToRgba(doc, dict, rawData, activeRes, fillColor) {
42400
44882
  });
42401
44883
  return decodeXObjectImageToRgba(context, { kind: "stream", dict, rawBytes: rawData }, activeRes, fillColor);
42402
44884
  }
44885
+ var cmykColorSpace2 = new DeviceCmykCS();
42403
44886
  function multiplyMatrices(m1, m2) {
42404
44887
  return [
42405
44888
  m1[0] * m2[0] + m1[1] * m2[2],
@@ -42616,193 +45099,7 @@ function resolvePageFonts(doc, resourcesDict) {
42616
45099
  }
42617
45100
  return fonts;
42618
45101
  }
42619
- function evaluateType4PostScriptTokens(tokens, initialStack) {
42620
- const stack = [...initialStack];
42621
- const runRange = (start, end) => {
42622
- let i = start;
42623
- while (i < end) {
42624
- const tok = tokens[i];
42625
- if (tok === "{") {
42626
- let depth = 1;
42627
- let j = i + 1;
42628
- while (j < end && depth > 0) {
42629
- if (tokens[j] === "{") depth++;
42630
- else if (tokens[j] === "}") depth--;
42631
- j++;
42632
- }
42633
- const blockStart = i + 1;
42634
- const blockEnd = j - 1;
42635
- if (j < end && tokens[j] === "{") {
42636
- let depth2 = 1;
42637
- let k = j + 1;
42638
- while (k < end && depth2 > 0) {
42639
- if (tokens[k] === "{") depth2++;
42640
- else if (tokens[k] === "}") depth2--;
42641
- k++;
42642
- }
42643
- if (k < end && tokens[k] === "ifelse") {
42644
- const cond = stack.pop() ?? 0;
42645
- if (cond !== 0) runRange(blockStart, blockEnd);
42646
- else runRange(j + 1, k - 1);
42647
- i = k + 1;
42648
- continue;
42649
- }
42650
- }
42651
- if (j < end && tokens[j] === "if") {
42652
- const cond = stack.pop() ?? 0;
42653
- if (cond !== 0) runRange(blockStart, blockEnd);
42654
- i = j + 1;
42655
- continue;
42656
- }
42657
- runRange(blockStart, blockEnd);
42658
- i = j;
42659
- continue;
42660
- }
42661
- if (tok === "}") {
42662
- i++;
42663
- continue;
42664
- }
42665
- const numVal2 = Number(tok);
42666
- if (tok.length > 0 && !Number.isNaN(numVal2)) {
42667
- stack.push(numVal2);
42668
- } else if (tok === "true") {
42669
- stack.push(1);
42670
- } else if (tok === "false") {
42671
- stack.push(0);
42672
- } else if (tok === "add") {
42673
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
42674
- stack.push(a + b);
42675
- } else if (tok === "sub") {
42676
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
42677
- stack.push(a - b);
42678
- } else if (tok === "mul") {
42679
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
42680
- stack.push(a * b);
42681
- } else if (tok === "div") {
42682
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
42683
- stack.push(Math.abs(b) > 1e-12 ? a / b : 0);
42684
- } else if (tok === "idiv") {
42685
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
42686
- stack.push(Math.abs(b) > 1e-12 ? Math.trunc(a / b) : 0);
42687
- } else if (tok === "mod") {
42688
- const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
42689
- stack.push(Math.abs(b) > 1e-12 ? a % b : 0);
42690
- } else if (tok === "neg") {
42691
- stack.push(-(stack.pop() ?? 0));
42692
- } else if (tok === "abs") {
42693
- stack.push(Math.abs(stack.pop() ?? 0));
42694
- } else if (tok === "ceiling") {
42695
- stack.push(Math.ceil(stack.pop() ?? 0));
42696
- } else if (tok === "floor") {
42697
- stack.push(Math.floor(stack.pop() ?? 0));
42698
- } else if (tok === "round") {
42699
- stack.push(Math.round(stack.pop() ?? 0));
42700
- } else if (tok === "truncate" || tok === "cvi") {
42701
- stack.push(Math.trunc(stack.pop() ?? 0));
42702
- } else if (tok === "sqrt") {
42703
- stack.push(Math.sqrt(Math.max(0, stack.pop() ?? 0)));
42704
- } else if (tok === "sin") {
42705
- stack.push(Math.sin((stack.pop() ?? 0) * Math.PI / 180));
42706
- } else if (tok === "cos") {
42707
- stack.push(Math.cos((stack.pop() ?? 0) * Math.PI / 180));
42708
- } else if (tok === "atan") {
42709
- const dx = stack.pop() ?? 1, dy = stack.pop() ?? 0;
42710
- let deg = Math.atan2(dy, dx) * 180 / Math.PI;
42711
- if (deg < 0) deg += 360;
42712
- stack.push(deg);
42713
- } else if (tok === "exp") {
42714
- const exp = stack.pop() ?? 1, base = stack.pop() ?? 0;
42715
- stack.push(Math.pow(base, exp));
42716
- } else if (tok === "ln") {
42717
- stack.push(Math.log(Math.max(1e-12, stack.pop() ?? 1)));
42718
- } else if (tok === "log") {
42719
- stack.push(Math.log10(Math.max(1e-12, stack.pop() ?? 1)));
42720
- } else if (tok === "dup") {
42721
- if (stack.length > 0) stack.push(stack[stack.length - 1]);
42722
- } else if (tok === "exch") {
42723
- if (stack.length >= 2) {
42724
- const b = stack.pop(), a = stack.pop();
42725
- stack.push(b, a);
42726
- }
42727
- } else if (tok === "pop") {
42728
- stack.pop();
42729
- } else if (tok === "copy") {
42730
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
42731
- const slice = stack.slice(Math.max(0, stack.length - n));
42732
- stack.push(...slice);
42733
- } else if (tok === "index") {
42734
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
42735
- const idx = stack.length - 1 - n;
42736
- if (idx >= 0 && idx < stack.length) stack.push(stack[idx]);
42737
- } else if (tok === "roll") {
42738
- const jShift = Math.trunc(stack.pop() ?? 0);
42739
- const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
42740
- if (n > 0 && stack.length >= n) {
42741
- const sub = stack.splice(stack.length - n, n);
42742
- const modShift = (jShift % n + n) % n;
42743
- const rolled = [...sub.slice(n - modShift), ...sub.slice(0, n - modShift)];
42744
- stack.push(...rolled);
42745
- }
42746
- } else if (tok === "eq") {
42747
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
42748
- stack.push(Math.abs(a - b) < 1e-9 ? 1 : 0);
42749
- } else if (tok === "ne") {
42750
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
42751
- stack.push(Math.abs(a - b) >= 1e-9 ? 1 : 0);
42752
- } else if (tok === "gt") {
42753
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
42754
- stack.push(a > b ? 1 : 0);
42755
- } else if (tok === "ge") {
42756
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
42757
- stack.push(a >= b ? 1 : 0);
42758
- } else if (tok === "lt") {
42759
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
42760
- stack.push(a < b ? 1 : 0);
42761
- } else if (tok === "le") {
42762
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
42763
- stack.push(a <= b ? 1 : 0);
42764
- } else if (tok === "and") {
42765
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
42766
- stack.push(a !== 0 && b !== 0 ? 1 : 0);
42767
- } else if (tok === "or") {
42768
- const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
42769
- stack.push(a !== 0 || b !== 0 ? 1 : 0);
42770
- } else if (tok === "not") {
42771
- const a = stack.pop() ?? 0;
42772
- stack.push(a === 0 ? 1 : 0);
42773
- }
42774
- i++;
42775
- }
42776
- };
42777
- runRange(0, tokens.length);
42778
- return stack;
42779
- }
42780
- function tokenizePostScriptCode(bytes) {
42781
- const tokens = [];
42782
- let cur = "";
42783
- for (let i = 0; i < bytes.length; i++) {
42784
- const ch3 = String.fromCharCode(bytes[i]);
42785
- if (ch3 === "{" || ch3 === "}") {
42786
- if (cur.length > 0) {
42787
- tokens.push(cur);
42788
- cur = "";
42789
- }
42790
- tokens.push(ch3);
42791
- } else if (ch3 === " " || ch3 === " " || ch3 === "\n" || ch3 === "\r") {
42792
- if (cur.length > 0) {
42793
- tokens.push(cur);
42794
- cur = "";
42795
- }
42796
- } else {
42797
- cur += ch3;
42798
- }
42799
- }
42800
- if (cur.length > 0) tokens.push(cur);
42801
- if (tokens[0] === "{" && tokens[tokens.length - 1] === "}") {
42802
- return tokens.slice(1, -1);
42803
- }
42804
- return tokens;
42805
- }
45102
+ var postScriptFunctions = /* @__PURE__ */ new WeakMap();
42806
45103
  function evalShadingFunctionToComponents(doc, fnNode, inputs) {
42807
45104
  const inArr = typeof inputs === "number" ? [inputs] : inputs;
42808
45105
  const t = inArr[0] ?? 0;
@@ -42849,35 +45146,50 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
42849
45146
  const decode = getNums("Decode", range);
42850
45147
  const nOut = Math.max(1, Math.floor((decode.length || range.length || 6) / 2));
42851
45148
  const mIn = Math.max(1, size.length);
42852
- let flatGridIndex = 0;
45149
+ const streamBytes = doc.decodeStream(resolved);
45150
+ let vertices = [{ index: 0, weight: 1 }];
42853
45151
  let stride = 1;
42854
45152
  for (let i = 0; i < mIn; i++) {
42855
45153
  const d02 = dom[i * 2] ?? 0;
42856
45154
  const d12 = dom[i * 2 + 1] ?? 1;
42857
- const sMax = Math.max(1, (size[i] ?? 2) - 1);
45155
+ const sMax = Math.max(0, (size[i] ?? 2) - 1);
42858
45156
  const e0 = encode[i * 2] ?? 0;
42859
45157
  const e1 = encode[i * 2 + 1] ?? sMax;
42860
45158
  const x = Math.max(d02, Math.min(d12, inArr[i] ?? 0));
42861
- const u = Math.abs(d12 - d02) > 1e-8 ? (x - d02) / (d12 - d02) : 0;
42862
- const idx = Math.round(Math.max(0, Math.min(sMax, e0 + u * (e1 - e0))));
42863
- flatGridIndex += idx * stride;
45159
+ const u = d12 === d02 ? 0 : (x - d02) / (d12 - d02);
45160
+ const e = Math.max(0, Math.min(sMax, e0 + u * (e1 - e0)));
45161
+ const low = Math.floor(e), fraction = e - low;
45162
+ const next = [];
45163
+ for (const vertex of vertices) {
45164
+ const index = vertex.index + low * stride;
45165
+ if (index * nOut * bps < streamBytes.length * 8) next.push({ index, weight: vertex.weight * (1 - fraction) });
45166
+ if (fraction && (index + stride) * nOut * bps < streamBytes.length * 8) {
45167
+ next.push({ index: index + stride, weight: vertex.weight * fraction });
45168
+ }
45169
+ }
45170
+ vertices = next;
42864
45171
  stride *= size[i] ?? 2;
42865
45172
  }
42866
- const streamBytes = doc.decodeStream(resolved);
45173
+ const maxSample = 2 ** bps - 1;
45174
+ const readSample = (index) => {
45175
+ let bitOffset = index * bps, remaining = bps, value = 0;
45176
+ while (remaining > 0) {
45177
+ const bitInByte = bitOffset % 8;
45178
+ const take = Math.min(remaining, 8 - bitInByte);
45179
+ const byte = streamBytes[Math.floor(bitOffset / 8)] ?? 0;
45180
+ value = value * 2 ** take + (byte >> 8 - bitInByte - take & (1 << take) - 1);
45181
+ bitOffset += take;
45182
+ remaining -= take;
45183
+ }
45184
+ return value / maxSample;
45185
+ };
42867
45186
  const out2 = [];
42868
- const maxSample = bps === 16 ? 65535 : 255;
42869
45187
  for (let j = 0; j < nOut; j++) {
42870
- const sampleIdx = flatGridIndex * nOut + j;
42871
- let rawVal = 0;
42872
- if (bps === 16) {
42873
- rawVal = (streamBytes[sampleIdx * 2] ?? 0) << 8 | (streamBytes[sampleIdx * 2 + 1] ?? 0);
42874
- } else {
42875
- rawVal = streamBytes[sampleIdx] ?? 0;
42876
- }
42877
- const frac = rawVal / maxSample;
45188
+ let value = 0;
45189
+ for (const vertex of vertices) value += readSample(vertex.index * nOut + j) * vertex.weight;
42878
45190
  const dec0 = decode[j * 2] ?? 0;
42879
45191
  const dec1 = decode[j * 2 + 1] ?? 1;
42880
- out2.push(dec0 + frac * (dec1 - dec0));
45192
+ out2.push(dec0 + value * (dec1 - dec0));
42881
45193
  }
42882
45194
  return clampRange(out2);
42883
45195
  }
@@ -42887,34 +45199,40 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
42887
45199
  const d12 = dom[i * 2 + 1] ?? 1;
42888
45200
  return Math.max(d02, Math.min(d12, v));
42889
45201
  });
42890
- const tokens = tokenizePostScriptCode(doc.decodeStream(resolved));
42891
- const stackOut = evaluateType4PostScriptTokens(tokens, clampedInputs);
42892
- return clampRange(stackOut);
45202
+ const source = bytesToString3(doc.decodeStream(resolved));
45203
+ let cached = postScriptFunctions.get(resolved);
45204
+ 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])) {
45205
+ cached = { source, domain: dom, range, evaluate: buildPostScriptJsFunction(source, dom, range) };
45206
+ postScriptFunctions.set(resolved, cached);
45207
+ }
45208
+ const output = [];
45209
+ cached.evaluate(clampedInputs, 0, output, 0);
45210
+ return output;
42893
45211
  }
42894
45212
  if (ft === 3) {
42895
45213
  const fnsArr = doc.resolveArray(dictGet(fnDict, "Functions"));
42896
45214
  const bounds = getNums("Bounds", []);
42897
45215
  const encode = getNums("Encode", []);
42898
45216
  if (fnsArr && fnsArr.items.length > 0) {
45217
+ const input = Math.max(dom[0] ?? 0, Math.min(dom[1] ?? 1, t));
42899
45218
  let segIdx = 0;
42900
- while (segIdx < bounds.length && t >= bounds[segIdx]) segIdx++;
45219
+ while (segIdx < bounds.length && input >= bounds[segIdx]) segIdx++;
42901
45220
  segIdx = Math.min(fnsArr.items.length - 1, segIdx);
42902
45221
  const b0 = segIdx === 0 ? dom[0] ?? 0 : bounds[segIdx - 1];
42903
45222
  const b1 = segIdx < bounds.length ? bounds[segIdx] : dom[1] ?? 1;
42904
45223
  const e0 = encode[segIdx * 2] ?? 0;
42905
45224
  const e1 = encode[segIdx * 2 + 1] ?? 1;
42906
- const localT = Math.abs(b1 - b0) > 1e-8 ? e0 + (t - b0) / (b1 - b0) * (e1 - e0) : e0;
42907
- return evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], Math.max(0, Math.min(1, localT)));
45225
+ const localT = b1 !== b0 ? e0 + (input - b0) / (b1 - b0) * (e1 - e0) : e0;
45226
+ return clampRange(evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], localT));
42908
45227
  }
42909
45228
  }
42910
- const c0 = getNums("C0", [0, 0, 0]);
42911
- const c1 = getNums("C1", [1, 1, 1]);
45229
+ const c0 = getNums("C0", [0]);
45230
+ const c1 = getNums("C1", [1]);
42912
45231
  const nNode = doc.resolve(dictGet(fnDict, "N"));
42913
- const expN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
45232
+ const expN = nNode?.kind === "number" ? nNode.value : 1;
42914
45233
  const d0 = dom[0] ?? 0;
42915
45234
  const d1 = dom[1] ?? 1;
42916
- const normT = Math.abs(d1 - d0) > 1e-8 ? (t - d0) / (d1 - d0) : t;
42917
- const w = Math.pow(Math.max(0, Math.min(1, normT)), expN);
45235
+ const w = Math.pow(Math.max(d0, Math.min(d1, t)), expN);
42918
45236
  const len = Math.max(c0.length, c1.length);
42919
45237
  const out = [];
42920
45238
  for (let i = 0; i < len; i++) {
@@ -42930,30 +45248,14 @@ function shadingComponentsToRgb(csName, comps) {
42930
45248
  return [v, v, v];
42931
45249
  }
42932
45250
  if (csName === "DeviceCMYK" || csName === "CMYK" || comps.length >= 4) {
42933
- const cc = comps[0] ?? 0, cm = comps[1] ?? 0, cy = comps[2] ?? 0, ck = comps[3] ?? 0;
42934
- return [(1 - cc) * (1 - ck), (1 - cm) * (1 - kClamp(ck)), (1 - cy) * (1 - kClamp(ck))];
45251
+ const rgb2 = cmykColorSpace2.getRgb([comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0, comps[3] ?? 0], 0);
45252
+ return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
42935
45253
  }
42936
45254
  return [comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0];
42937
45255
  }
42938
45256
  function kClamp(v) {
42939
45257
  return Math.max(0, Math.min(1, v));
42940
45258
  }
42941
- function xyzToSrgb(X, Y, Z, Xw = 0.95047, Yw = 1, Zw = 1.08883) {
42942
- const scaleX = Xw > 1e-6 ? 0.95047 / Xw : 1;
42943
- const scaleY = Yw > 1e-6 ? 1 / Yw : 1;
42944
- const scaleZ = Zw > 1e-6 ? 1.08883 / Zw : 1;
42945
- const x = X * scaleX;
42946
- const y = Y * scaleY;
42947
- const z = Z * scaleZ;
42948
- const rl = 3.2404542 * x - 1.5371385 * y - 0.4985314 * z;
42949
- const gl = -0.969266 * x + 1.8760108 * y + 0.041556 * z;
42950
- const bl = 0.0556434 * x - 0.2040259 * y + 1.0572252 * z;
42951
- const toGamma = (u) => {
42952
- const c = Math.max(0, Math.min(1, u));
42953
- return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
42954
- };
42955
- return [toGamma(rl), toGamma(gl), toGamma(bl)];
42956
- }
42957
45259
  function getColorSpaceComponentCount(doc, csNode, activeResources, depth = 0) {
42958
45260
  if (!csNode || depth > 4) return 3;
42959
45261
  const resolved = doc ? doc.resolve(csNode) : csNode;
@@ -43010,63 +45312,10 @@ function convertColorSpaceComponentsToRgb(doc, csNode, csNameFallback, comps, ac
43010
45312
  if (resolved.kind === "array" && resolved.items.length > 0 && doc) {
43011
45313
  const familyNode = doc.resolve(resolved.items[0]);
43012
45314
  const family = familyNode?.kind === "name" ? familyNode.decoded : "";
43013
- if (family === "CalGray") {
43014
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
43015
- const gNode = paramDict ? doc.resolve(dictGet(paramDict, "Gamma")) : void 0;
43016
- const gamma = gNode?.kind === "number" && gNode.value > 0 ? gNode.value : 1;
43017
- const a = Math.pow(kClamp(comps[0] ?? 0), gamma);
43018
- return [a, a, a];
43019
- }
43020
- if (family === "CalRGB") {
43021
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
43022
- const gammaArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Gamma")) : void 0;
43023
- const getArrNum = (arr, idx, fb) => {
43024
- const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
43025
- return r?.kind === "number" ? r.value : fb;
43026
- };
43027
- const gr = getArrNum(gammaArr, 0, 1);
43028
- const gg = getArrNum(gammaArr, 1, 1);
43029
- const gb = getArrNum(gammaArr, 2, 1);
43030
- const ag = Math.pow(kClamp(comps[0] ?? 0), gr > 0 ? gr : 1);
43031
- const bg = Math.pow(kClamp(comps[1] ?? 0), gg > 0 ? gg : 1);
43032
- const cg = Math.pow(kClamp(comps[2] ?? 0), gb > 0 ? gb : 1);
43033
- const matArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Matrix")) : void 0;
43034
- if (matArr && matArr.items.length >= 9) {
43035
- const m = (i) => getArrNum(matArr, i, 0);
43036
- const X = m(0) * ag + m(3) * bg + m(6) * cg;
43037
- const Y = m(1) * ag + m(4) * bg + m(7) * cg;
43038
- const Z = m(2) * ag + m(5) * bg + m(8) * cg;
43039
- const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
43040
- const Xw = getArrNum(wpArr, 0, 0.95047);
43041
- const Yw = getArrNum(wpArr, 1, 1);
43042
- const Zw = getArrNum(wpArr, 2, 1.08883);
43043
- return xyzToSrgb(X, Y, Z, Xw, Yw, Zw);
43044
- }
43045
- return [ag, bg, cg];
43046
- }
43047
- if (family === "Lab") {
43048
- const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
43049
- const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
43050
- const rangeArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Range")) : void 0;
43051
- const getNum = (arr, idx, fb) => {
43052
- const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
43053
- return r?.kind === "number" ? r.value : fb;
43054
- };
43055
- const Xw = getNum(wpArr, 0, 0.95047);
43056
- const Yw = getNum(wpArr, 1, 1);
43057
- const Zw = getNum(wpArr, 2, 1.08883);
43058
- const amin = getNum(rangeArr, 0, -100);
43059
- const amax = getNum(rangeArr, 1, 100);
43060
- const bmin = getNum(rangeArr, 2, -100);
43061
- const bmax = getNum(rangeArr, 3, 100);
43062
- const Lstar = Math.max(0, Math.min(100, comps[0] ?? 0));
43063
- const astar = Math.max(amin, Math.min(amax, comps[1] ?? 0));
43064
- const bstar = Math.max(bmin, Math.min(bmax, comps[2] ?? 0));
43065
- const M = (Lstar + 16) / 116;
43066
- const L = M + astar / 500;
43067
- const N = M - bstar / 200;
43068
- const gFn = (x) => x >= 6 / 29 ? x * x * x : 108 / 841 * (x - 4 / 29);
43069
- return xyzToSrgb(Xw * gFn(L), Yw * gFn(M), Zw * gFn(N), Xw, Yw, Zw);
45315
+ if (family === "CalGray" || family === "CalRGB" || family === "Lab") {
45316
+ const colorSpace = createCalibratedColorSpace(doc, family, resolved.items[1]);
45317
+ const rgb2 = colorSpace.getRgb(comps, 0);
45318
+ return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
43070
45319
  }
43071
45320
  if (family === "ICCBased" && resolved.items[1]) {
43072
45321
  const iccNode = doc.resolve(resolved.items[1]);
@@ -43717,7 +45966,8 @@ function evaluateContentStreamToDisplayList(params) {
43717
45966
  const shDict = shNode?.kind === "dict" ? shNode : shNode?.kind === "stream" ? shNode.dict : void 0;
43718
45967
  const shStream = shNode?.kind === "stream" ? shNode : void 0;
43719
45968
  if (shDict) {
43720
- const targetBox = st.clipRect ?? [0, 0, params.width, params.height];
45969
+ const [originX, originY] = params.origin ?? [0, 0];
45970
+ const targetBox = st.clipRect ?? [originX, originY, originX + params.width, originY + params.height];
43721
45971
  const img = renderShadingDictToImage(
43722
45972
  params.cosDoc,
43723
45973
  shDict,
@@ -43756,12 +46006,10 @@ function evaluateContentStreamToDisplayList(params) {
43756
46006
  } else if (operator === "RG" || operator === "SC" || operator === "SCN") {
43757
46007
  st.strokeColor = resolveScColorOperands(operator === "RG" ? "DeviceRGB" : st.strokeColorSpaceName, ops, activeResources);
43758
46008
  } else if (operator === "k") {
43759
- const c = num(0), m = num(1), y = num(2), k = num(3);
43760
- st.fillColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
46009
+ st.fillColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
43761
46010
  st.fillPatternName = void 0;
43762
46011
  } else if (operator === "K") {
43763
- const c = num(0), m = num(1), y = num(2), k = num(3);
43764
- st.strokeColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
46012
+ st.strokeColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
43765
46013
  } else if (operator === "gs" && params.cosDoc && activeResources && ops[0]?.kind === "name") {
43766
46014
  const extDict = params.cosDoc.resolveDict(dictGet(activeResources, "ExtGState"));
43767
46015
  const gsDict = extDict ? params.cosDoc.resolveDict(dictGet(extDict, ops[0].decoded)) : void 0;
@@ -43970,7 +46218,7 @@ function evaluateContentStreamToDisplayList(params) {
43970
46218
  stateStack.pop();
43971
46219
  capturedOperations = parentOperations;
43972
46220
  }
43973
- if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
46221
+ if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, isolated, bboxClip: nextClipPaths?.[0], blendMode: st.blendMode, clipRect: st.clipRect } });
43974
46222
  };
43975
46223
  const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
43976
46224
  for (const node of nodes) {
@@ -44554,6 +46802,7 @@ function evaluateContentStreamToDisplayList(params) {
44554
46802
  pageIndex: params.pageIndex,
44555
46803
  width: params.width,
44556
46804
  height: params.height,
46805
+ ...params.origin ? { origin: params.origin } : {},
44557
46806
  rotation: params.rotation ?? 0,
44558
46807
  glyphs,
44559
46808
  paths,
@@ -46024,7 +48273,7 @@ var PdfPage = class {
46024
48273
  return [n0.value, n1.value, n2.value, n3.value];
46025
48274
  }
46026
48275
  }
46027
- return [0, 0, 612, 792];
48276
+ return key === "MediaBox" ? [0, 0, 612, 792] : this.resolveBox("MediaBox");
46028
48277
  }
46029
48278
  getMediaBox() {
46030
48279
  return this.resolveBox("MediaBox");
@@ -46697,16 +48946,19 @@ var PdfPage = class {
46697
48946
  });
46698
48947
  }
46699
48948
  }
46700
- return evaluateContentStreamToDisplayList({
48949
+ const mediaBox = this.getMediaBox(), cropBox = this.getCropBox();
48950
+ const originX = Math.min(mediaBox[0], mediaBox[2]), originY = Math.min(mediaBox[1], mediaBox[3]);
48951
+ return { ...evaluateContentStreamToDisplayList({
46701
48952
  pageIndex: this.index,
46702
48953
  width,
46703
48954
  height,
48955
+ origin: [originX, originY],
46704
48956
  rotation: this.getRotation(),
46705
48957
  nodes: baseNodes,
46706
48958
  cosDoc: this.cosDoc,
46707
48959
  resourcesDict: evalResourcesDict,
46708
48960
  annotations: extractPageAnnotations(this.cosDoc, this.pageDict)
46709
- });
48961
+ }), cropBox: [cropBox[0] - originX, cropBox[1] - originY, cropBox[2] - originX, cropBox[3] - originY] };
46710
48962
  }
46711
48963
  extractPage(options) {
46712
48964
  const dl = this.evaluateDisplayList();
@@ -46724,10 +48976,10 @@ var PdfPage = class {
46724
48976
  return extractTablesFromDisplayList(this.evaluateDisplayList());
46725
48977
  }
46726
48978
  renderToBitmap(options) {
46727
- return renderDisplayListToBitmap(this.evaluateDisplayList(), options);
48979
+ return renderDisplayListToBitmap(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
46728
48980
  }
46729
48981
  renderToPng(options) {
46730
- return renderDisplayListToPng(this.evaluateDisplayList(), options);
48982
+ return renderDisplayListToPng(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
46731
48983
  }
46732
48984
  };
46733
48985
  function createStandardFontHandle(standardName) {
@@ -47777,7 +50029,7 @@ function prepareStroke(path, scale) {
47777
50029
  }
47778
50030
  return { matrix, width, dashArray, dashPhase };
47779
50031
  }
47780
- function strokeContours(path, pageHeight, scale) {
50032
+ function strokeContours(path, pageHeight, scale, originX = 0, originY = 0) {
47781
50033
  const stroke = prepareStroke(path, scale);
47782
50034
  if (!stroke) return [];
47783
50035
  const inverse = inverseStrokeMatrix(stroke.matrix);
@@ -47789,8 +50041,8 @@ function strokeContours(path, pageHeight, scale) {
47789
50041
  (inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
47790
50042
  ];
47791
50043
  const toScreen = ([x, y]) => [
47792
- (a * x / strokeScale + c * y / strokeScale + e) * scale,
47793
- (pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
50044
+ (a * x / strokeScale + c * y / strokeScale + e - originX) * scale,
50045
+ (pageHeight + originY - b * x / strokeScale - d * y / strokeScale - f) * scale
47794
50046
  ];
47795
50047
  const contours = strokeOutlines(
47796
50048
  segmentsToScreenPaths(path.segments, pageHeight, scale, project),
@@ -47948,18 +50200,34 @@ function renderSoftMask(mask, displayList, scale) {
47948
50200
  }
47949
50201
  return bitmap;
47950
50202
  }
47951
- function hasBlendModes(operations) {
47952
- return operations.some((operation) => !!operation.value.blendMode && operation.value.blendMode !== "Normal" && operation.value.blendMode !== "Compatible" || operation.kind === "group" && hasBlendModes(operation.value.operations));
50203
+ function getDisplayListCropBox(list) {
50204
+ const full = [0, 0, list.width, list.height];
50205
+ const box = list.cropBox;
50206
+ if (!box || !box.every(Number.isFinite)) return full;
50207
+ const x0 = Math.max(0, Math.min(box[0], box[2]));
50208
+ const y0 = Math.max(0, Math.min(box[1], box[3]));
50209
+ const x1 = Math.min(list.width, Math.max(box[0], box[2]));
50210
+ const y1 = Math.min(list.height, Math.max(box[1], box[3]));
50211
+ return x1 > x0 && y1 > y0 ? [x0, y0, x1, y1] : full;
50212
+ }
50213
+ function hasCompositingEffects(operations, includeSoftMasks = false) {
50214
+ 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));
50215
+ }
50216
+ function needsGroupBackdrop(group) {
50217
+ return group.isolated === false && !!group.softMask && hasCompositingEffects(group.operations, true);
47953
50218
  }
47954
50219
  function renderDisplayListToBitmap(displayList, options = {}) {
47955
50220
  const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
47956
50221
  const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
47957
50222
  const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
47958
50223
  const scale = scaleX;
50224
+ const [originX, originY] = displayList.origin ?? [0, 0];
50225
+ const pageTop = originY + displayList.height;
50226
+ const toScreen = (x, y) => [(x - originX) * scale, (pageTop - y) * scale];
47959
50227
  const width = Math.max(1, Math.round(displayList.width * scale));
47960
50228
  const height = Math.max(1, Math.round(displayList.height * scale));
47961
50229
  const rgba = new Uint8Array(width * height * 4);
47962
- const deferBackground = !options.transparent && hasBlendModes(paintOperations(displayList));
50230
+ const deferBackground = !options.transparent && hasCompositingEffects(paintOperations(displayList));
47963
50231
  const transparent = options.transparent || deferBackground;
47964
50232
  const bg = options.background ?? { r: 1, g: 1, b: 1 };
47965
50233
  const bgR = transparent ? 0 : Math.round(bg.r * 255);
@@ -47984,14 +50252,27 @@ function renderDisplayListToBitmap(displayList, options = {}) {
47984
50252
  let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
47985
50253
  if (operation.kind === "group") {
47986
50254
  const group = operation.value;
47987
- const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations: group.operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, transparent: true });
50255
+ let operations = group.operations;
50256
+ if (needsGroupBackdrop(group)) {
50257
+ operations = [{ kind: "image", value: {
50258
+ name: "GroupBackdrop",
50259
+ width,
50260
+ height,
50261
+ decodedRgba: rgba.slice(),
50262
+ matrix: [width / scale, 0, 0, height / scale, originX, pageTop - height / scale],
50263
+ colorSpace: "DeviceRGB",
50264
+ bitsPerComponent: 8,
50265
+ ...group.bboxClip ? { clipPaths: [group.bboxClip] } : {}
50266
+ } }, ...operations];
50267
+ }
50268
+ const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, useCropBox: false, transparent: true });
47988
50269
  for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
47989
50270
  operation = { kind: "image", value: {
47990
50271
  name: "TransparencyGroup",
47991
50272
  width: bitmap.width,
47992
50273
  height: bitmap.height,
47993
50274
  decodedRgba: bitmap.data,
47994
- matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, 0, displayList.height - bitmap.height / scale],
50275
+ matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, originX, pageTop - bitmap.height / scale],
47995
50276
  colorSpace: "DeviceRGB",
47996
50277
  bitsPerComponent: 8,
47997
50278
  blendMode: group.blendMode,
@@ -48005,7 +50286,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
48005
50286
  for (const clip of clips) {
48006
50287
  const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
48007
50288
  const layer = new Uint8Array(width * height * 4);
48008
- fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
50289
+ fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale, toScreen), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
48009
50290
  for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
48010
50291
  }
48011
50292
  cachedClips = clips;
@@ -48052,15 +50333,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
48052
50333
  if (operation.kind === "path") {
48053
50334
  const path = operation.value;
48054
50335
  if (path.fillColor) {
48055
- const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale), true);
48056
- 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;
50336
+ const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale, toScreen), true);
50337
+ 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;
48057
50338
  fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
48058
50339
  }
48059
50340
  if (path.strokeColor) {
48060
50341
  const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
48061
50342
  const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
48062
- const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
48063
- 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;
50343
+ const edges = pathsToEdges(strokeContours(path, displayList.height, scale, originX, originY).map((points) => ({ points, closed: true })));
50344
+ 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;
48064
50345
  fillEdgesScanline4x4(
48065
50346
  rgba,
48066
50347
  width,
@@ -48083,12 +50364,12 @@ function renderDisplayListToBitmap(displayList, options = {}) {
48083
50364
  if (Math.abs(det) <= 1e-8) continue;
48084
50365
  const cornersPdfX = [e, a + e, a + c + e, c + e];
48085
50366
  const cornersPdfY = [f, b + f, b + d + f, d + f];
48086
- const cornersPx = cornersPdfX.map((cx) => cx * scale);
48087
- const cornersPy = cornersPdfY.map((cy) => (displayList.height - cy) * scale);
48088
- const clipMinPx = img.clipRect ? Math.floor(img.clipRect[0] * scale) : 0;
48089
- const clipMaxPx = img.clipRect ? Math.ceil(img.clipRect[2] * scale) - 1 : width - 1;
48090
- const clipMinPy = img.clipRect ? Math.floor((displayList.height - img.clipRect[3]) * scale) : 0;
48091
- const clipMaxPy = img.clipRect ? Math.ceil((displayList.height - img.clipRect[1]) * scale) - 1 : height - 1;
50367
+ const cornersPx = cornersPdfX.map((cx) => (cx - originX) * scale);
50368
+ const cornersPy = cornersPdfY.map((cy) => (pageTop - cy) * scale);
50369
+ const clipMinPx = img.clipRect ? Math.floor((img.clipRect[0] - originX) * scale) : 0;
50370
+ const clipMaxPx = img.clipRect ? Math.ceil((img.clipRect[2] - originX) * scale) - 1 : width - 1;
50371
+ const clipMinPy = img.clipRect ? Math.floor((pageTop - img.clipRect[3]) * scale) : 0;
50372
+ const clipMaxPy = img.clipRect ? Math.ceil((pageTop - img.clipRect[1]) * scale) - 1 : height - 1;
48092
50373
  const minPx = Math.max(0, clipMinPx, Math.floor(Math.min(...cornersPx)));
48093
50374
  const maxPx = Math.min(width - 1, clipMaxPx, Math.ceil(Math.max(...cornersPx)) - 1);
48094
50375
  const minPy = Math.max(0, clipMinPy, Math.floor(Math.min(...cornersPy)));
@@ -48105,11 +50386,11 @@ function renderDisplayListToBitmap(displayList, options = {}) {
48105
50386
  const smooth = Math.fround((s1 + s2 + Math.hypot(s1 - s2, 2 * cross)) / 2) <= 1;
48106
50387
  const sample = new Float64Array(4);
48107
50388
  for (let py = minPy; py <= maxPy; py++) {
48108
- const yPdf = displayList.height - (py + 0.5) / scale;
50389
+ const yPdf = pageTop - (py + 0.5) / scale;
48109
50390
  if (img.clipRect && (yPdf < img.clipRect[1] || yPdf > img.clipRect[3])) continue;
48110
50391
  const dyPdf = yPdf - f;
48111
50392
  for (let px = minPx; px <= maxPx; px++) {
48112
- const xPdf = (px + 0.5) / scale;
50393
+ const xPdf = originX + (px + 0.5) / scale;
48113
50394
  if (img.clipRect && (xPdf < img.clipRect[0] || xPdf > img.clipRect[2])) continue;
48114
50395
  const dxPdf = xPdf - e;
48115
50396
  const u = (d * dxPdf - c * dyPdf) / det;
@@ -48170,6 +50451,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
48170
50451
  }
48171
50452
  result = { width: targetW, height: targetH, data: resampled };
48172
50453
  }
50454
+ if (options.useCropBox) {
50455
+ const box = getDisplayListCropBox(displayList);
50456
+ result = cropRgbaBitmap(result, {
50457
+ x: box[0] * scaleX,
50458
+ y: (displayList.height - box[3]) * scaleY,
50459
+ width: (box[2] - box[0]) * scaleX,
50460
+ height: (box[3] - box[1]) * scaleY
50461
+ });
50462
+ }
48173
50463
  result = rotateRgbaBitmapQuarterTurns(result, displayList.rotation ?? 0);
48174
50464
  if (options.cropRect) {
48175
50465
  result = cropRgbaBitmap(result, options.cropRect);
@@ -48198,23 +50488,6 @@ function collectLeavesForRaster(cosDoc, node, out = [], visited = /* @__PURE__ *
48198
50488
  }
48199
50489
  return out;
48200
50490
  }
48201
- function extractBoxArray(cosDoc, dict, key) {
48202
- let cur = dict;
48203
- const visited = /* @__PURE__ */ new Set();
48204
- while (cur && !visited.has(cur)) {
48205
- visited.add(cur);
48206
- const arr = cosDoc.resolveArray(dictGet(cur, key));
48207
- if (arr && arr.items.length >= 4) {
48208
- const nums = arr.items.slice(0, 4).map((item) => {
48209
- const r = cosDoc.resolve(item);
48210
- return r?.kind === "number" ? r.value : 0;
48211
- });
48212
- return [nums[0], nums[1], nums[2], nums[3]];
48213
- }
48214
- cur = cosDoc.resolveDict(dictGet(cur, "Parent"));
48215
- }
48216
- return void 0;
48217
- }
48218
50491
  function renderPdfPageToBitmap(pdfBytes, pageIndex = 0, options) {
48219
50492
  const cos = pdfBytes instanceof Uint8Array ? parseCosDocument(pdfBytes) : pdfBytes;
48220
50493
  const catalog = cos.resolveDict(cos.rootRef);
@@ -48223,35 +50496,7 @@ function renderPdfPageToBitmap(pdfBytes, pageIndex = 0, options) {
48223
50496
  if (!leaf) throw new Error(`Page index ${pageIndex} out of bounds`);
48224
50497
  const resolvedIndex = leaves.indexOf(leaf);
48225
50498
  const page = new PdfPage(cos, leaf.ref, leaf.dict, resolvedIndex);
48226
- const { cropRect, ...restOptions } = options ?? {};
48227
- let bitmap = renderDisplayListToBitmap(
48228
- // CropBox is in unrotated page coordinates. Apply page rotation after it.
48229
- { ...page.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), rotation: 0 },
48230
- restOptions
48231
- );
48232
- if (options?.useCropBox) {
48233
- const cropBox = extractBoxArray(cos, leaf.dict, "CropBox");
48234
- if (cropBox) {
48235
- const mediaBox = extractBoxArray(cos, leaf.dict, "MediaBox") ?? [0, 0, page.getSize().width, page.getSize().height];
48236
- const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
48237
- const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
48238
- const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
48239
- const mediaH = mediaBox[3] - mediaBox[1];
48240
- const bx = Math.round((cropBox[0] - mediaBox[0]) * scaleX);
48241
- const by = Math.round((mediaH - (cropBox[3] - mediaBox[1])) * scaleY);
48242
- const bw = Math.max(1, Math.round(Math.abs(cropBox[2] - cropBox[0]) * scaleX));
48243
- const bh = Math.max(1, Math.round(Math.abs(cropBox[3] - cropBox[1]) * scaleY));
48244
- bitmap = cropRgbaBitmap(bitmap, { x: bx, y: by, width: bw, height: bh });
48245
- }
48246
- }
48247
- const rotation = page.getRotation();
48248
- if (rotation === 90 || rotation === 180 || rotation === 270) {
48249
- bitmap = rotateRgbaBitmapQuarterTurns(bitmap, rotation);
48250
- }
48251
- if (cropRect) {
48252
- bitmap = cropRgbaBitmap(bitmap, cropRect);
48253
- }
48254
- return bitmap;
50499
+ return page.renderToBitmap(options);
48255
50500
  }
48256
50501
  function renderPdfPageToPng(pdfBytes, pageIndex = 0, options) {
48257
50502
  const bmp = renderPdfPageToBitmap(pdfBytes, pageIndex, options);