@poe-platform/safe-bash 0.1.772 → 0.1.774

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/image-ast/index.browser.js +3543 -706
  2. package/dist/image-ast/index.js +3543 -706
  3. package/dist/pdf-ast/ast.d.ts +7 -0
  4. package/dist/pdf-ast/content/evaluator.d.ts +1 -0
  5. package/dist/pdf-ast/index.js +3587 -718
  6. package/dist/pdf-ast/render/raster.d.ts +1 -0
  7. package/dist/pdf-ast/vendor/pdfjs-fonts.d.mts +36 -0
  8. package/dist/pdf-ast/vendor/pdfjs-fonts.mjs +3323 -0
  9. package/dist/safe-bash/command-chunks/{chunk-M2XU2YCK.js → chunk-4ZHDCMQX.js} +2 -2
  10. package/dist/safe-bash/command-chunks/{chunk-NBENXODJ.js → chunk-HH5QPKIN.js} +1 -1
  11. package/dist/safe-bash/command-chunks/{chunk-C4AAJTXF.js → chunk-PM63UJE6.js} +3546 -706
  12. package/dist/safe-bash/core.browser.js +101 -45
  13. package/dist/safe-bash/core.d.ts +1 -1
  14. package/dist/safe-bash/plugins/composition.d.ts +2 -0
  15. package/dist/safe-bash/plugins/composition.js +2 -1
  16. package/dist/safe-bash/shell/runtime.js +17 -9
  17. package/dist/safe-bash/shell/sync-posix-regex.d.ts +3 -0
  18. package/dist/safe-bash/shell/sync-posix-regex.js +48 -0
  19. package/dist/safe-bash-command-ffmpeg/index.js +11032 -9579
  20. package/dist/safe-bash-command-gh/index.d.ts +1 -0
  21. package/dist/safe-bash-command-gh/index.js +43 -13
  22. package/dist/safe-bash-command-gh/types.d.ts +1 -0
  23. package/dist/safe-bash-command-git/git_rust.wasm +0 -0
  24. package/dist/safe-bash-command-git/index.js +22 -15
  25. package/dist/safe-bash-command-git/wasm.generated.js +1 -1
  26. package/dist/safe-bash-command-gpg/index.js +28 -7
  27. package/dist/safe-bash-command-imagemagick/index.js +2 -2
  28. package/dist/safe-bash-command-openssl/index.js +24 -6
  29. package/dist/safe-bash-command-pandoc/command.js +3 -3
  30. package/dist/safe-bash-command-pandoc/index.js +3 -3
  31. package/dist/safe-bash-command-pdfimages/index.js +3542 -660
  32. package/dist/safe-bash-command-pdfinfo/index.js +3584 -718
  33. package/dist/safe-bash-command-pdftk/index.js +3542 -660
  34. package/dist/safe-bash-command-pdftoppm/index.js +3589 -787
  35. package/dist/safe-bash-command-pdftotext/index.js +3542 -660
  36. package/dist/safe-bash-command-qpdf/index.js +3542 -660
  37. package/dist/safe-bash-command-sips/index.js +2 -2
  38. package/dist/safe-bash-command-soffice/index.js +1 -1
  39. package/dist/safe-bash-command-ssconvert/index.js +3553 -716
  40. package/dist/safe-bash-command-ssh/index.js +124 -23
  41. package/dist/safe-bash-command-wkhtmltopdf/index.js +3581 -660
  42. package/dist/safe-bash-mcp/index.d.ts +8 -2
  43. package/dist/safe-bash-mcp/index.js +13 -6
  44. package/package.json +7 -7
  45. package/third-party/pdf-ast/THIRD_PARTY_NOTICES.md +84 -1
@@ -144,6 +144,11 @@ var FONT_IDENTITY_MATRIX = [1e-3, 0, 0, 1e-3, 0, 0];
144
144
  var LINE_FACTOR = 1.35;
145
145
  var LINE_DESCENT_FACTOR = 0.35;
146
146
  var BASELINE_FACTOR = LINE_DESCENT_FACTOR / LINE_FACTOR;
147
+ var MeshFigureType = {
148
+ TRIANGLES: 1,
149
+ LATTICE: 2,
150
+ PATCH: 3
151
+ };
147
152
  var VerbosityLevel = {
148
153
  ERRORS: 0,
149
154
  WARNINGS: 1,
@@ -19321,16 +19326,3333 @@ var PageViewport = class _PageViewport {
19321
19326
  return p;
19322
19327
  }
19323
19328
  };
19329
+
19330
+ // src/core/colorspace.js
19331
+ function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
19332
+ const COMPONENTS = 3;
19333
+ alpha01 = alpha01 !== 1 ? 0 : alpha01;
19334
+ const xRatio = w1 / w2;
19335
+ const yRatio = h1 / h2;
19336
+ let newIndex = 0, oldIndex;
19337
+ const xScaled = new Uint16Array(w2);
19338
+ const w1Scanline = w1 * COMPONENTS;
19339
+ for (let i = 0; i < w2; i++) {
19340
+ xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
19341
+ }
19342
+ for (let i = 0; i < h2; i++) {
19343
+ const py = Math.floor(i * yRatio) * w1Scanline;
19344
+ for (let j = 0; j < w2; j++) {
19345
+ oldIndex = py + xScaled[j];
19346
+ dest[newIndex++] = src[oldIndex++];
19347
+ dest[newIndex++] = src[oldIndex++];
19348
+ dest[newIndex++] = src[oldIndex++];
19349
+ newIndex += alpha01;
19350
+ }
19351
+ }
19352
+ }
19353
+ function isDefaultDecodeHelper(decode, expectedLen) {
19354
+ if (!Array.isArray(decode)) {
19355
+ return true;
19356
+ }
19357
+ const decodeLen = decode.length;
19358
+ if (decodeLen < expectedLen) {
19359
+ warn("Decode map length is too short.");
19360
+ return true;
19361
+ }
19362
+ if (decodeLen > expectedLen) {
19363
+ info("Truncating too long decode map.");
19364
+ decode.length = expectedLen;
19365
+ }
19366
+ return false;
19367
+ }
19368
+ var ColorSpace = class _ColorSpace {
19369
+ static #rgbBuf = new Uint8ClampedArray(3);
19370
+ constructor(name, numComps) {
19371
+ if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _ColorSpace) {
19372
+ unreachable("Cannot initialize ColorSpace.");
19373
+ }
19374
+ this.name = name;
19375
+ this.numComps = numComps;
19376
+ }
19377
+ /**
19378
+ * Converts the color value to the RGB color. The color components are
19379
+ * located in the src array starting from the srcOffset. Returns the array
19380
+ * of the rgb components, each value ranging from [0,255].
19381
+ */
19382
+ getRgb(src, srcOffset, output = new Uint8ClampedArray(3)) {
19383
+ this.getRgbItem(src, srcOffset, output, 0);
19384
+ return output;
19385
+ }
19386
+ getRgbHex(src, srcOffset) {
19387
+ const buffer = this.getRgb(src, srcOffset, _ColorSpace.#rgbBuf);
19388
+ return Util.makeHexColor(buffer[0], buffer[1], buffer[2]);
19389
+ }
19390
+ /**
19391
+ * Converts the color value to the RGB color, similar to the getRgb method.
19392
+ * The result placed into the dest array starting from the destOffset.
19393
+ */
19394
+ getRgbItem(src, srcOffset, dest, destOffset) {
19395
+ unreachable("Should not call ColorSpace.getRgbItem");
19396
+ }
19397
+ /**
19398
+ * Converts the specified number of the color values to the RGB colors.
19399
+ * The colors are located in the src array starting from the srcOffset.
19400
+ * The result is placed into the dest array starting from the destOffset.
19401
+ * The src array items shall be in [0,2^bits) range, the dest array items
19402
+ * will be in [0,255] range. alpha01 indicates how many alpha components
19403
+ * there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
19404
+ * array).
19405
+ */
19406
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
19407
+ unreachable("Should not call ColorSpace.getRgbBuffer");
19408
+ }
19409
+ /**
19410
+ * Converts `count` unscaled colors to RGB, starting at `destOffset`.
19411
+ * Components use the native color-space ranges expected by `getRgbItem`,
19412
+ * and each output has a `3 + alpha01` byte stride.
19413
+ * Subclasses may override this to batch expensive conversions.
19414
+ */
19415
+ getRgbItems(src, count, dest, destOffset, alpha01) {
19416
+ const { numComps } = this;
19417
+ for (let i = 0, srcOffset = 0; i < count; i++, srcOffset += numComps) {
19418
+ this.getRgbItem(src, srcOffset, dest, destOffset);
19419
+ destOffset += 3 + alpha01;
19420
+ }
19421
+ }
19422
+ /**
19423
+ * Returns true if source data will be equal the result/output data.
19424
+ */
19425
+ isPassthrough(bits) {
19426
+ return false;
19427
+ }
19428
+ /**
19429
+ * Refer to the static `ColorSpace.isDefaultDecode` method below.
19430
+ */
19431
+ isDefaultDecode(decode, bpc) {
19432
+ return _ColorSpace.isDefaultDecode(decode, this.numComps);
19433
+ }
19434
+ /**
19435
+ * Fills in the RGB colors in the destination buffer. alpha01 indicates
19436
+ * how many alpha components there are in the dest array; it will be either
19437
+ * 0 (RGB array) or 1 (RGBA array).
19438
+ */
19439
+ fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {
19440
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19441
+ assert(
19442
+ dest instanceof Uint8ClampedArray,
19443
+ 'ColorSpace.fillRgb: Unsupported "dest" type.'
19444
+ );
19445
+ }
19446
+ const count = originalWidth * originalHeight;
19447
+ let rgbBuf = null;
19448
+ const numComponentColors = 1 << bpc;
19449
+ const needsResizing = originalHeight !== height || originalWidth !== width;
19450
+ if (this.isPassthrough(bpc)) {
19451
+ rgbBuf = comps;
19452
+ } else if (this.numComps === 1 && count > numComponentColors && this.name !== "DeviceGray" && this.name !== "DeviceRGB") {
19453
+ const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);
19454
+ for (let i = 0; i < numComponentColors; i++) {
19455
+ allColors[i] = i;
19456
+ }
19457
+ const colorMap = new Uint8ClampedArray(numComponentColors * 3);
19458
+ this.getRgbBuffer(
19459
+ allColors,
19460
+ 0,
19461
+ numComponentColors,
19462
+ colorMap,
19463
+ 0,
19464
+ bpc,
19465
+ /* alpha01 = */
19466
+ 0
19467
+ );
19468
+ if (!needsResizing) {
19469
+ let destPos = 0;
19470
+ for (let i = 0; i < count; ++i) {
19471
+ const key = comps[i] * 3;
19472
+ dest[destPos++] = colorMap[key];
19473
+ dest[destPos++] = colorMap[key + 1];
19474
+ dest[destPos++] = colorMap[key + 2];
19475
+ destPos += alpha01;
19476
+ }
19477
+ } else {
19478
+ rgbBuf = new Uint8Array(count * 3);
19479
+ let rgbPos = 0;
19480
+ for (let i = 0; i < count; ++i) {
19481
+ const key = comps[i] * 3;
19482
+ rgbBuf[rgbPos++] = colorMap[key];
19483
+ rgbBuf[rgbPos++] = colorMap[key + 1];
19484
+ rgbBuf[rgbPos++] = colorMap[key + 2];
19485
+ }
19486
+ }
19487
+ } else if (!needsResizing) {
19488
+ this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);
19489
+ } else {
19490
+ rgbBuf = new Uint8ClampedArray(count * 3);
19491
+ this.getRgbBuffer(
19492
+ comps,
19493
+ 0,
19494
+ count,
19495
+ rgbBuf,
19496
+ 0,
19497
+ bpc,
19498
+ /* alpha01 = */
19499
+ 0
19500
+ );
19501
+ }
19502
+ if (rgbBuf) {
19503
+ if (needsResizing) {
19504
+ resizeRgbImage(
19505
+ rgbBuf,
19506
+ dest,
19507
+ originalWidth,
19508
+ originalHeight,
19509
+ width,
19510
+ height,
19511
+ alpha01
19512
+ );
19513
+ } else {
19514
+ let destPos = 0, rgbPos = 0;
19515
+ for (let i = 0, ii = width * actualHeight; i < ii; i++) {
19516
+ dest[destPos++] = rgbBuf[rgbPos++];
19517
+ dest[destPos++] = rgbBuf[rgbPos++];
19518
+ dest[destPos++] = rgbBuf[rgbPos++];
19519
+ destPos += alpha01;
19520
+ }
19521
+ }
19522
+ }
19523
+ }
19524
+ /**
19525
+ * True if the colorspace has components in the default range of [0, 1].
19526
+ * This should be true for all colorspaces except for lab color spaces
19527
+ * which are [0,100], [-128, 127], [-128, 127].
19528
+ */
19529
+ get usesZeroToOneRange() {
19530
+ return shadow(this, "usesZeroToOneRange", true);
19531
+ }
19532
+ /**
19533
+ * Checks if a decode map matches the default decode map for a color space.
19534
+ * This handles the general decode maps where there are two values per
19535
+ * component, e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
19536
+ * This does not handle Lab, Indexed, or Pattern decode maps since they are
19537
+ * slightly different.
19538
+ * @param {Array} decode - Decode map (usually from an image).
19539
+ * @param {number} numComps - Number of components the color space has.
19540
+ */
19541
+ static isDefaultDecode(decode, numComps) {
19542
+ if (isDefaultDecodeHelper(decode, numComps * 2)) {
19543
+ return true;
19544
+ }
19545
+ for (let i = 0, ii = decode.length; i < ii; i += 2) {
19546
+ if (decode[i] !== 0 || decode[i + 1] !== 1) {
19547
+ return false;
19548
+ }
19549
+ }
19550
+ return true;
19551
+ }
19552
+ };
19553
+ var DeviceCmykCS = class extends ColorSpace {
19554
+ constructor() {
19555
+ super("DeviceCMYK", 4);
19556
+ }
19557
+ // The coefficients below was found using numerical analysis: the method of
19558
+ // steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
19559
+ // where color_value is the tabular value from the table of sampled RGB colors
19560
+ // from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
19561
+ // CMYK color conversion using the estimation below:
19562
+ // f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
19563
+ #toRgb(src, srcOffset, srcScale, dest, destOffset) {
19564
+ const c = src[srcOffset] * srcScale;
19565
+ const m = src[srcOffset + 1] * srcScale;
19566
+ const y = src[srcOffset + 2] * srcScale;
19567
+ const k = src[srcOffset + 3] * srcScale;
19568
+ 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);
19569
+ 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);
19570
+ 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);
19571
+ }
19572
+ getRgbItem(src, srcOffset, dest, destOffset) {
19573
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19574
+ assert(
19575
+ dest instanceof Uint8ClampedArray,
19576
+ 'DeviceCmykCS.getRgbItem: Unsupported "dest" type.'
19577
+ );
19578
+ }
19579
+ this.#toRgb(src, srcOffset, 1, dest, destOffset);
19580
+ }
19581
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
19582
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19583
+ assert(
19584
+ dest instanceof Uint8ClampedArray,
19585
+ 'DeviceCmykCS.getRgbBuffer: Unsupported "dest" type.'
19586
+ );
19587
+ }
19588
+ const scale = 1 / ((1 << bits) - 1);
19589
+ for (let i = 0; i < count; i++) {
19590
+ this.#toRgb(src, srcOffset, scale, dest, destOffset);
19591
+ srcOffset += 4;
19592
+ destOffset += 3 + alpha01;
19593
+ }
19594
+ }
19595
+ };
19596
+ var CalGrayCS = class extends ColorSpace {
19597
+ constructor(whitePoint, blackPoint, gamma) {
19598
+ super("CalGray", 1);
19599
+ if (!whitePoint) {
19600
+ throw new FormatError(
19601
+ "WhitePoint missing - required for color space CalGray"
19602
+ );
19603
+ }
19604
+ [this.XW, this.YW, this.ZW] = whitePoint;
19605
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
19606
+ this.G = gamma || 1;
19607
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
19608
+ throw new FormatError(
19609
+ `Invalid WhitePoint components for ${this.name}, no fallback available`
19610
+ );
19611
+ }
19612
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
19613
+ info(`Invalid BlackPoint for ${this.name}, falling back to default.`);
19614
+ this.XB = this.YB = this.ZB = 0;
19615
+ }
19616
+ if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
19617
+ warn(
19618
+ `${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ZB: ${this.ZB}, only default values are supported.`
19619
+ );
19620
+ }
19621
+ if (this.G < 1) {
19622
+ info(
19623
+ `Invalid Gamma: ${this.G} for ${this.name}, falling back to default.`
19624
+ );
19625
+ this.G = 1;
19626
+ }
19627
+ }
19628
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
19629
+ const A = src[srcOffset] * scale;
19630
+ const AG = A ** this.G;
19631
+ const L = this.YW * AG;
19632
+ const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0);
19633
+ dest[destOffset] = val;
19634
+ dest[destOffset + 1] = val;
19635
+ dest[destOffset + 2] = val;
19636
+ }
19637
+ getRgbItem(src, srcOffset, dest, destOffset) {
19638
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19639
+ assert(
19640
+ dest instanceof Uint8ClampedArray,
19641
+ 'CalGrayCS.getRgbItem: Unsupported "dest" type.'
19642
+ );
19643
+ }
19644
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
19645
+ }
19646
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
19647
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19648
+ assert(
19649
+ dest instanceof Uint8ClampedArray,
19650
+ 'CalGrayCS.getRgbBuffer: Unsupported "dest" type.'
19651
+ );
19652
+ }
19653
+ const scale = 1 / ((1 << bits) - 1);
19654
+ for (let i = 0; i < count; ++i) {
19655
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
19656
+ srcOffset += 1;
19657
+ destOffset += 3 + alpha01;
19658
+ }
19659
+ }
19660
+ };
19661
+ var CalRGBCS = class _CalRGBCS extends ColorSpace {
19662
+ // See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these
19663
+ // matrices.
19664
+ // prettier-ignore
19665
+ static #BRADFORD_SCALE_MATRIX = new Float32Array([
19666
+ 0.8951,
19667
+ 0.2664,
19668
+ -0.1614,
19669
+ -0.7502,
19670
+ 1.7135,
19671
+ 0.0367,
19672
+ 0.0389,
19673
+ -0.0685,
19674
+ 1.0296
19675
+ ]);
19676
+ // prettier-ignore
19677
+ static #BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([
19678
+ 0.9869929,
19679
+ -0.1470543,
19680
+ 0.1599627,
19681
+ 0.4323053,
19682
+ 0.5183603,
19683
+ 0.0492912,
19684
+ -85287e-7,
19685
+ 0.0400428,
19686
+ 0.9684867
19687
+ ]);
19688
+ // See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html.
19689
+ // prettier-ignore
19690
+ static #SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([
19691
+ 3.2404542,
19692
+ -1.5371385,
19693
+ -0.4985314,
19694
+ -0.969266,
19695
+ 1.8760108,
19696
+ 0.041556,
19697
+ 0.0556434,
19698
+ -0.2040259,
19699
+ 1.0572252
19700
+ ]);
19701
+ static #FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);
19702
+ static #tempNormalizeMatrix = new Float32Array(3);
19703
+ static #tempConvertMatrix1 = new Float32Array(3);
19704
+ static #tempConvertMatrix2 = new Float32Array(3);
19705
+ static #DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8;
19706
+ constructor(whitePoint, blackPoint, gamma, matrix) {
19707
+ super("CalRGB", 3);
19708
+ if (!whitePoint) {
19709
+ throw new FormatError(
19710
+ "WhitePoint missing - required for color space CalRGB"
19711
+ );
19712
+ }
19713
+ const [XW, YW, ZW] = this.whitePoint = whitePoint;
19714
+ const [XB, YB, ZB] = this.blackPoint = blackPoint || new Float32Array(3);
19715
+ [this.GR, this.GG, this.GB] = gamma || new Float32Array([1, 1, 1]);
19716
+ [
19717
+ this.MXA,
19718
+ this.MYA,
19719
+ this.MZA,
19720
+ this.MXB,
19721
+ this.MYB,
19722
+ this.MZB,
19723
+ this.MXC,
19724
+ this.MYC,
19725
+ this.MZC
19726
+ ] = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
19727
+ if (XW < 0 || ZW < 0 || YW !== 1) {
19728
+ throw new FormatError(
19729
+ `Invalid WhitePoint components for ${this.name}, no fallback available`
19730
+ );
19731
+ }
19732
+ if (XB < 0 || YB < 0 || ZB < 0) {
19733
+ info(
19734
+ `Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], falling back to default.`
19735
+ );
19736
+ this.blackPoint = new Float32Array(3);
19737
+ }
19738
+ if (this.GR < 0 || this.GG < 0 || this.GB < 0) {
19739
+ info(
19740
+ `Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ${this.name}, falling back to default.`
19741
+ );
19742
+ this.GR = this.GG = this.GB = 1;
19743
+ }
19744
+ }
19745
+ #matrixProduct(a, b, result) {
19746
+ result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
19747
+ result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
19748
+ result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
19749
+ }
19750
+ #toFlat(sourceWhitePoint, LMS, result) {
19751
+ result[0] = LMS[0] * 1 / sourceWhitePoint[0];
19752
+ result[1] = LMS[1] * 1 / sourceWhitePoint[1];
19753
+ result[2] = LMS[2] * 1 / sourceWhitePoint[2];
19754
+ }
19755
+ #toD65(sourceWhitePoint, LMS, result) {
19756
+ const D65X = 0.95047;
19757
+ const D65Y = 1;
19758
+ const D65Z = 1.08883;
19759
+ result[0] = LMS[0] * D65X / sourceWhitePoint[0];
19760
+ result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
19761
+ result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
19762
+ }
19763
+ #sRGBTransferFunction(color) {
19764
+ if (color <= 31308e-7) {
19765
+ return MathClamp(12.92 * color, 0, 1);
19766
+ }
19767
+ return color >= 0.99554525 ? 1 : MathClamp((1 + 0.055) * color ** (1 / 2.4) - 0.055, 0, 1);
19768
+ }
19769
+ #decodeL(L) {
19770
+ if (L < 0) {
19771
+ return -this.#decodeL(-L);
19772
+ }
19773
+ return L > 8 ? ((L + 16) / 116) ** 3 : L * _CalRGBCS.#DECODE_L_CONSTANT;
19774
+ }
19775
+ #compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
19776
+ if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {
19777
+ result[0] = XYZ_Flat[0];
19778
+ result[1] = XYZ_Flat[1];
19779
+ result[2] = XYZ_Flat[2];
19780
+ return;
19781
+ }
19782
+ const zeroDecodeL = this.#decodeL(0);
19783
+ const X_DST = zeroDecodeL;
19784
+ const X_SRC = this.#decodeL(sourceBlackPoint[0]);
19785
+ const Y_DST = zeroDecodeL;
19786
+ const Y_SRC = this.#decodeL(sourceBlackPoint[1]);
19787
+ const Z_DST = zeroDecodeL;
19788
+ const Z_SRC = this.#decodeL(sourceBlackPoint[2]);
19789
+ const X_Scale = (1 - X_DST) / (1 - X_SRC);
19790
+ const X_Offset = 1 - X_Scale;
19791
+ const Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
19792
+ const Y_Offset = 1 - Y_Scale;
19793
+ const Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
19794
+ const Z_Offset = 1 - Z_Scale;
19795
+ result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
19796
+ result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
19797
+ result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
19798
+ }
19799
+ #normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
19800
+ if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
19801
+ result[0] = XYZ_In[0];
19802
+ result[1] = XYZ_In[1];
19803
+ result[2] = XYZ_In[2];
19804
+ return;
19805
+ }
19806
+ const LMS = result;
19807
+ this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
19808
+ const LMS_Flat = _CalRGBCS.#tempNormalizeMatrix;
19809
+ this.#toFlat(sourceWhitePoint, LMS, LMS_Flat);
19810
+ this.#matrixProduct(
19811
+ _CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
19812
+ LMS_Flat,
19813
+ result
19814
+ );
19815
+ }
19816
+ #normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
19817
+ const LMS = result;
19818
+ this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
19819
+ const LMS_D65 = _CalRGBCS.#tempNormalizeMatrix;
19820
+ this.#toD65(sourceWhitePoint, LMS, LMS_D65);
19821
+ this.#matrixProduct(
19822
+ _CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
19823
+ LMS_D65,
19824
+ result
19825
+ );
19826
+ }
19827
+ #toRgb(src, srcOffset, dest, destOffset, scale) {
19828
+ const A = MathClamp(src[srcOffset] * scale, 0, 1);
19829
+ const B = MathClamp(src[srcOffset + 1] * scale, 0, 1);
19830
+ const C = MathClamp(src[srcOffset + 2] * scale, 0, 1);
19831
+ const AGR = A === 1 ? 1 : A ** this.GR;
19832
+ const BGG = B === 1 ? 1 : B ** this.GG;
19833
+ const CGB = C === 1 ? 1 : C ** this.GB;
19834
+ const X = this.MXA * AGR + this.MXB * BGG + this.MXC * CGB;
19835
+ const Y = this.MYA * AGR + this.MYB * BGG + this.MYC * CGB;
19836
+ const Z = this.MZA * AGR + this.MZB * BGG + this.MZC * CGB;
19837
+ const XYZ = _CalRGBCS.#tempConvertMatrix1;
19838
+ XYZ[0] = X;
19839
+ XYZ[1] = Y;
19840
+ XYZ[2] = Z;
19841
+ const XYZ_Flat = _CalRGBCS.#tempConvertMatrix2;
19842
+ this.#normalizeWhitePointToFlat(this.whitePoint, XYZ, XYZ_Flat);
19843
+ const XYZ_Black = _CalRGBCS.#tempConvertMatrix1;
19844
+ this.#compensateBlackPoint(this.blackPoint, XYZ_Flat, XYZ_Black);
19845
+ const XYZ_D65 = _CalRGBCS.#tempConvertMatrix2;
19846
+ this.#normalizeWhitePointToD65(
19847
+ _CalRGBCS.#FLAT_WHITEPOINT_MATRIX,
19848
+ XYZ_Black,
19849
+ XYZ_D65
19850
+ );
19851
+ const SRGB = _CalRGBCS.#tempConvertMatrix1;
19852
+ this.#matrixProduct(_CalRGBCS.#SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
19853
+ dest[destOffset] = this.#sRGBTransferFunction(SRGB[0]) * 255;
19854
+ dest[destOffset + 1] = this.#sRGBTransferFunction(SRGB[1]) * 255;
19855
+ dest[destOffset + 2] = this.#sRGBTransferFunction(SRGB[2]) * 255;
19856
+ }
19857
+ getRgbItem(src, srcOffset, dest, destOffset) {
19858
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19859
+ assert(
19860
+ dest instanceof Uint8ClampedArray,
19861
+ 'CalRGBCS.getRgbItem: Unsupported "dest" type.'
19862
+ );
19863
+ }
19864
+ this.#toRgb(src, srcOffset, dest, destOffset, 1);
19865
+ }
19866
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
19867
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19868
+ assert(
19869
+ dest instanceof Uint8ClampedArray,
19870
+ 'CalRGBCS.getRgbBuffer: Unsupported "dest" type.'
19871
+ );
19872
+ }
19873
+ const scale = 1 / ((1 << bits) - 1);
19874
+ for (let i = 0; i < count; ++i) {
19875
+ this.#toRgb(src, srcOffset, dest, destOffset, scale);
19876
+ srcOffset += 3;
19877
+ destOffset += 3 + alpha01;
19878
+ }
19879
+ }
19880
+ };
19881
+ var LabCS = class extends ColorSpace {
19882
+ constructor(whitePoint, blackPoint, range) {
19883
+ super("Lab", 3);
19884
+ if (!whitePoint) {
19885
+ throw new FormatError(
19886
+ "WhitePoint missing - required for color space Lab"
19887
+ );
19888
+ }
19889
+ [this.XW, this.YW, this.ZW] = whitePoint;
19890
+ [this.amin, this.amax, this.bmin, this.bmax] = range || [
19891
+ -100,
19892
+ 100,
19893
+ -100,
19894
+ 100
19895
+ ];
19896
+ [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
19897
+ if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
19898
+ throw new FormatError(
19899
+ "Invalid WhitePoint components, no fallback available"
19900
+ );
19901
+ }
19902
+ if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
19903
+ info("Invalid BlackPoint, falling back to default");
19904
+ this.XB = this.YB = this.ZB = 0;
19905
+ }
19906
+ if (this.amin > this.amax || this.bmin > this.bmax) {
19907
+ info("Invalid Range, falling back to defaults");
19908
+ this.amin = -100;
19909
+ this.amax = 100;
19910
+ this.bmin = -100;
19911
+ this.bmax = 100;
19912
+ }
19913
+ }
19914
+ // Function g(x) from spec
19915
+ #fn_g(x) {
19916
+ return x >= 6 / 29 ? x ** 3 : 108 / 841 * (x - 4 / 29);
19917
+ }
19918
+ #decode(value, high1, low2, high2) {
19919
+ return low2 + value * (high2 - low2) / high1;
19920
+ }
19921
+ // If decoding is needed maxVal should be 2^bits per component - 1.
19922
+ #toRgb(src, srcOffset, maxVal, dest, destOffset) {
19923
+ let Ls = src[srcOffset];
19924
+ let as = src[srcOffset + 1];
19925
+ let bs = src[srcOffset + 2];
19926
+ if (maxVal !== false) {
19927
+ Ls = this.#decode(Ls, maxVal, 0, 100);
19928
+ as = this.#decode(as, maxVal, this.amin, this.amax);
19929
+ bs = this.#decode(bs, maxVal, this.bmin, this.bmax);
19930
+ }
19931
+ if (as > this.amax) {
19932
+ as = this.amax;
19933
+ } else if (as < this.amin) {
19934
+ as = this.amin;
19935
+ }
19936
+ if (bs > this.bmax) {
19937
+ bs = this.bmax;
19938
+ } else if (bs < this.bmin) {
19939
+ bs = this.bmin;
19940
+ }
19941
+ const M = (Ls + 16) / 116;
19942
+ const L = M + as / 500;
19943
+ const N = M - bs / 200;
19944
+ const X = this.XW * this.#fn_g(L);
19945
+ const Y = this.YW * this.#fn_g(M);
19946
+ const Z = this.ZW * this.#fn_g(N);
19947
+ let r, g, b;
19948
+ if (this.ZW < 1) {
19949
+ r = X * 3.1339 + Y * -1.617 + Z * -0.4906;
19950
+ g = X * -0.9785 + Y * 1.916 + Z * 0.0333;
19951
+ b = X * 0.072 + Y * -0.229 + Z * 1.4057;
19952
+ } else {
19953
+ r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
19954
+ g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
19955
+ b = X * 0.0557 + Y * -0.204 + Z * 1.057;
19956
+ }
19957
+ dest[destOffset] = Math.sqrt(r) * 255;
19958
+ dest[destOffset + 1] = Math.sqrt(g) * 255;
19959
+ dest[destOffset + 2] = Math.sqrt(b) * 255;
19960
+ }
19961
+ getRgbItem(src, srcOffset, dest, destOffset) {
19962
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19963
+ assert(
19964
+ dest instanceof Uint8ClampedArray,
19965
+ 'LabCS.getRgbItem: Unsupported "dest" type.'
19966
+ );
19967
+ }
19968
+ this.#toRgb(src, srcOffset, false, dest, destOffset);
19969
+ }
19970
+ getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
19971
+ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
19972
+ assert(
19973
+ dest instanceof Uint8ClampedArray,
19974
+ 'LabCS.getRgbBuffer: Unsupported "dest" type.'
19975
+ );
19976
+ }
19977
+ const maxVal = (1 << bits) - 1;
19978
+ for (let i = 0; i < count; i++) {
19979
+ this.#toRgb(src, srcOffset, maxVal, dest, destOffset);
19980
+ srcOffset += 3;
19981
+ destOffset += 3 + alpha01;
19982
+ }
19983
+ }
19984
+ isDefaultDecode(decode, bpc) {
19985
+ return true;
19986
+ }
19987
+ get usesZeroToOneRange() {
19988
+ return shadow(this, "usesZeroToOneRange", false);
19989
+ }
19990
+ };
19991
+
19992
+ // src/core/postscript/lexer.js
19993
+ var TOKEN = {
19994
+ // Structural tokens — not keyword operators
19995
+ number: 0,
19996
+ lbrace: 1,
19997
+ rbrace: 2,
19998
+ // Boolean literals
19999
+ true: 3,
20000
+ false: 4,
20001
+ // Arithmetic binary operators
20002
+ add: 5,
20003
+ sub: 6,
20004
+ mul: 7,
20005
+ div: 8,
20006
+ idiv: 9,
20007
+ mod: 10,
20008
+ exp: 11,
20009
+ // Comparison binary operators
20010
+ eq: 12,
20011
+ ne: 13,
20012
+ gt: 14,
20013
+ ge: 15,
20014
+ lt: 16,
20015
+ le: 17,
20016
+ // Bitwise / boolean binary operators
20017
+ and: 18,
20018
+ or: 19,
20019
+ xor: 20,
20020
+ bitshift: 21,
20021
+ // Unary arithmetic operators
20022
+ abs: 22,
20023
+ neg: 23,
20024
+ ceiling: 24,
20025
+ floor: 25,
20026
+ round: 26,
20027
+ truncate: 27,
20028
+ // Unary boolean / bitwise operator
20029
+ not: 28,
20030
+ // Mathematical functions — unary
20031
+ sqrt: 29,
20032
+ sin: 30,
20033
+ cos: 31,
20034
+ ln: 32,
20035
+ log: 33,
20036
+ // Mathematical function — binary
20037
+ atan: 34,
20038
+ // Type conversion operators
20039
+ cvi: 35,
20040
+ cvr: 36,
20041
+ // Stack operators
20042
+ dup: 37,
20043
+ exch: 38,
20044
+ pop: 39,
20045
+ copy: 40,
20046
+ index: 41,
20047
+ roll: 42,
20048
+ // Control flow
20049
+ if: 43,
20050
+ ifelse: 44,
20051
+ // End of input
20052
+ eof: 45,
20053
+ // Synthetic: produced by the optimizer, never emitted by the lexer.
20054
+ min: 46,
20055
+ max: 47
20056
+ };
20057
+ var Token = class {
20058
+ constructor(id, value = null) {
20059
+ this.id = id;
20060
+ this.value = value;
20061
+ }
20062
+ };
20063
+ var Lexer = class _Lexer {
20064
+ // Singletons for every non-number token, built lazily on first construction.
20065
+ // Keyword operator tokens carry their name as `value`; structural tokens
20066
+ // (lbrace, rbrace, eof) carry null.
20067
+ static #singletons = null;
20068
+ static #operatorSingletons = null;
20069
+ static #initSingletons() {
20070
+ const singletons = /* @__PURE__ */ Object.create(null);
20071
+ const operatorSingletons = /* @__PURE__ */ Object.create(null);
20072
+ for (const [name, id] of Object.entries(TOKEN)) {
20073
+ if (name === "number") {
20074
+ continue;
20075
+ }
20076
+ const isOperator = id >= TOKEN.true && id <= TOKEN.ifelse;
20077
+ const token = new Token(id, isOperator ? name : null);
20078
+ singletons[name] = token;
20079
+ if (isOperator) {
20080
+ operatorSingletons[name] = token;
20081
+ }
20082
+ }
20083
+ this.#singletons = singletons;
20084
+ this.#operatorSingletons = operatorSingletons;
20085
+ }
20086
+ constructor(data) {
20087
+ if (!_Lexer.#singletons) {
20088
+ _Lexer.#initSingletons();
20089
+ }
20090
+ this.data = data;
20091
+ this.pos = 0;
20092
+ this.len = data.length;
20093
+ this._numberPattern = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/iy;
20094
+ this._identifierPattern = /[a-z]+/y;
20095
+ }
20096
+ // Skip a % comment, advancing past the next \n or \r (or to EOF).
20097
+ _skipComment() {
20098
+ const lf = this.data.indexOf("\n", this.pos);
20099
+ const cr = this.data.indexOf("\r", this.pos);
20100
+ const eol = Math.min(lf < 0 ? this.len : lf, cr < 0 ? this.len : cr);
20101
+ this.pos = Math.min(eol + 1, this.len);
20102
+ }
20103
+ _getNumber() {
20104
+ this._numberPattern.lastIndex = this.pos;
20105
+ const match = this._numberPattern.exec(this.data);
20106
+ if (!match) {
20107
+ return new Token(TOKEN.number, 0);
20108
+ }
20109
+ const number = parseFloat(match[0]);
20110
+ if (!Number.isFinite(number)) {
20111
+ return new Token(TOKEN.number, 0);
20112
+ }
20113
+ this.pos = this._numberPattern.lastIndex;
20114
+ return new Token(TOKEN.number, number);
20115
+ }
20116
+ _getOperator() {
20117
+ this._identifierPattern.lastIndex = this.pos;
20118
+ const match = this._identifierPattern.exec(this.data);
20119
+ if (!match) {
20120
+ return new Token(TOKEN.number, 0);
20121
+ }
20122
+ this.pos = this._identifierPattern.lastIndex;
20123
+ const op = match[0];
20124
+ const token = _Lexer.#operatorSingletons[op];
20125
+ return token ?? new Token(TOKEN.number, 0);
20126
+ }
20127
+ // Return the next token, or Lexer.#singletons.eof at end of input.
20128
+ next() {
20129
+ while (this.pos < this.len) {
20130
+ const ch3 = this.data.charCodeAt(this.pos++);
20131
+ switch (ch3) {
20132
+ // PostScript white-space characters (PDF32000 §7.2.2)
20133
+ case 0:
20134
+ case 9:
20135
+ case 10:
20136
+ case 12:
20137
+ case 13:
20138
+ case 32:
20139
+ break;
20140
+ case 37:
20141
+ this._skipComment();
20142
+ break;
20143
+ case 123:
20144
+ return _Lexer.#singletons.lbrace;
20145
+ case 125:
20146
+ return _Lexer.#singletons.rbrace;
20147
+ case 43:
20148
+ case 45:
20149
+ this.pos--;
20150
+ return this._getNumber();
20151
+ case 46:
20152
+ this.pos--;
20153
+ return this._getNumber();
20154
+ default:
20155
+ if (ch3 >= 48 && ch3 <= 57) {
20156
+ this.pos--;
20157
+ return this._getNumber();
20158
+ }
20159
+ if (ch3 >= 97 && ch3 <= 122) {
20160
+ this.pos--;
20161
+ return this._getOperator();
20162
+ }
20163
+ return new Token(TOKEN.number, 0);
20164
+ }
20165
+ }
20166
+ return _Lexer.#singletons.eof;
20167
+ }
20168
+ };
20169
+
20170
+ // src/core/postscript/ast.js
20171
+ var PS_VALUE_TYPE = {
20172
+ numeric: 0,
20173
+ // known to be a number (f64 in Wasm)
20174
+ boolean: 1,
20175
+ // known to be a boolean (0.0 = false, 1.0 = true in f64)
20176
+ unknown: 2
20177
+ // indeterminate at compile time
20178
+ };
20179
+ var PS_NODE = {
20180
+ // Parser AST node types (produced by Parser / parsePostScriptFunction)
20181
+ program: 0,
20182
+ block: 1,
20183
+ number: 2,
20184
+ operator: 3,
20185
+ if: 4,
20186
+ ifelse: 5,
20187
+ // Tree AST node types (produced by PSStackToTree)
20188
+ arg: 6,
20189
+ const: 7,
20190
+ unary: 8,
20191
+ binary: 9,
20192
+ ternary: 10
20193
+ };
20194
+ var PsNode = class {
20195
+ constructor(type) {
20196
+ this.type = type;
20197
+ }
20198
+ };
20199
+ var PsProgram = class extends PsNode {
20200
+ constructor(body) {
20201
+ super(PS_NODE.program);
20202
+ this.body = body;
20203
+ }
20204
+ };
20205
+ var PsBlock = class extends PsNode {
20206
+ constructor(instructions) {
20207
+ super(PS_NODE.block);
20208
+ this.instructions = instructions;
20209
+ }
20210
+ };
20211
+ var PsNumber = class extends PsNode {
20212
+ /** @param {number} value */
20213
+ constructor(value) {
20214
+ super(PS_NODE.number);
20215
+ this.value = value;
20216
+ }
20217
+ };
20218
+ var PsOperator = class extends PsNode {
20219
+ /** @param {number} op — one of the TOKEN.* constants from lexer.js */
20220
+ constructor(op) {
20221
+ super(PS_NODE.operator);
20222
+ this.op = op;
20223
+ }
20224
+ };
20225
+ var PsIf = class extends PsNode {
20226
+ /** @param {PsBlock} then */
20227
+ constructor(then) {
20228
+ super(PS_NODE.if);
20229
+ this.then = then;
20230
+ }
20231
+ };
20232
+ var PsIfElse = class extends PsNode {
20233
+ /**
20234
+ * @param {PsBlock} then
20235
+ * @param {PsBlock} otherwise
20236
+ */
20237
+ constructor(then, otherwise) {
20238
+ super(PS_NODE.ifelse);
20239
+ this.then = then;
20240
+ this.otherwise = otherwise;
20241
+ }
20242
+ };
20243
+ var PsArgNode = class extends PsNode {
20244
+ /** @param {number} index */
20245
+ constructor(index) {
20246
+ super(PS_NODE.arg);
20247
+ this.index = index;
20248
+ this.valueType = PS_VALUE_TYPE.numeric;
20249
+ }
20250
+ };
20251
+ var PsConstNode = class extends PsNode {
20252
+ /** @param {number|boolean} value */
20253
+ constructor(value) {
20254
+ super(PS_NODE.const);
20255
+ this.value = value;
20256
+ this.valueType = typeof value === "boolean" ? PS_VALUE_TYPE.boolean : PS_VALUE_TYPE.numeric;
20257
+ }
20258
+ };
20259
+ var PsUnaryNode = class extends PsNode {
20260
+ /**
20261
+ * @param {number} op — TOKEN.* constant
20262
+ * @param {PsNode} operand
20263
+ * @param {number} [valueType]
20264
+ */
20265
+ constructor(op, operand, valueType = PS_VALUE_TYPE.unknown) {
20266
+ super(PS_NODE.unary);
20267
+ this.op = op;
20268
+ this.operand = operand;
20269
+ this.valueType = valueType;
20270
+ }
20271
+ };
20272
+ var PsBinaryNode = class extends PsNode {
20273
+ /**
20274
+ * @param {number} op — TOKEN.* constant
20275
+ * @param {PsNode} first — was on top of stack
20276
+ * @param {PsNode} second — was below top
20277
+ * @param {number} [valueType]
20278
+ */
20279
+ constructor(op, first, second, valueType = PS_VALUE_TYPE.unknown) {
20280
+ super(PS_NODE.binary);
20281
+ this.op = op;
20282
+ this.first = first;
20283
+ this.second = second;
20284
+ this.valueType = valueType;
20285
+ }
20286
+ };
20287
+ var PsTernaryNode = class extends PsNode {
20288
+ /**
20289
+ * @param {PsNode} cond
20290
+ * @param {PsNode} then
20291
+ * @param {PsNode} otherwise
20292
+ * @param {number} [valueType]
20293
+ */
20294
+ constructor(cond, then, otherwise, valueType = PS_VALUE_TYPE.unknown) {
20295
+ super(PS_NODE.ternary);
20296
+ this.cond = cond;
20297
+ this.then = then;
20298
+ this.otherwise = otherwise;
20299
+ this.valueType = valueType;
20300
+ }
20301
+ };
20302
+ var Parser = class _Parser {
20303
+ constructor(lexer) {
20304
+ this.lexer = lexer;
20305
+ this._token = null;
20306
+ }
20307
+ static _isRegularOperator(id) {
20308
+ return id >= TOKEN.true && id < TOKEN.if;
20309
+ }
20310
+ // Fetch the next token from the lexer.
20311
+ _advance() {
20312
+ this._token = this.lexer.next();
20313
+ }
20314
+ // Assert that the current token has the given id, consume it, and return it.
20315
+ _expect(id) {
20316
+ if (this._token.id !== id) {
20317
+ throw new FormatError(
20318
+ `PostScript function: expected token id ${id}, got ${this._token.id}.`
20319
+ );
20320
+ }
20321
+ const tok = this._token;
20322
+ this._advance();
20323
+ return tok;
20324
+ }
20325
+ /**
20326
+ * Parse the full Type 4 function body.
20327
+ *
20328
+ * Grammar (simplified):
20329
+ * program ::= '{' block '}'
20330
+ * block ::= instruction*
20331
+ * instruction ::= number
20332
+ * | operator (any PS_OPERATOR except if / ifelse)
20333
+ * | '{' block '}' 'if'
20334
+ * | '{' block '}' '{' block '}' 'ifelse'
20335
+ * @returns {PsProgram}
20336
+ */
20337
+ parse() {
20338
+ this._advance();
20339
+ this._expect(TOKEN.lbrace);
20340
+ const block = this._parseBlock();
20341
+ this._expect(TOKEN.rbrace);
20342
+ if (this._token.id !== TOKEN.eof) {
20343
+ warn("PostScript function: unexpected content after closing brace.");
20344
+ }
20345
+ return new PsProgram(block);
20346
+ }
20347
+ _parseBlock() {
20348
+ const instructions = [];
20349
+ while (true) {
20350
+ const tok = this._token;
20351
+ switch (tok.id) {
20352
+ case TOKEN.number:
20353
+ instructions.push(new PsNumber(tok.value));
20354
+ this._advance();
20355
+ break;
20356
+ case TOKEN.lbrace: {
20357
+ this._advance();
20358
+ const thenBlock = this._parseBlock();
20359
+ this._expect(TOKEN.rbrace);
20360
+ if (this._token.id === TOKEN.if) {
20361
+ this._advance();
20362
+ instructions.push(new PsIf(thenBlock));
20363
+ } else if (this._token.id === TOKEN.lbrace) {
20364
+ this._advance();
20365
+ const elseBlock = this._parseBlock();
20366
+ this._expect(TOKEN.rbrace);
20367
+ this._expect(TOKEN.ifelse);
20368
+ instructions.push(new PsIfElse(thenBlock, elseBlock));
20369
+ } else {
20370
+ throw new FormatError(
20371
+ "PostScript function: a procedure block must be followed by 'if' or '{\u2026} ifelse'."
20372
+ );
20373
+ }
20374
+ break;
20375
+ }
20376
+ case TOKEN.rbrace:
20377
+ case TOKEN.eof:
20378
+ return new PsBlock(instructions);
20379
+ case TOKEN.if:
20380
+ case TOKEN.ifelse:
20381
+ throw new FormatError(
20382
+ `PostScript function: unexpected '${tok.value}' operator.`
20383
+ );
20384
+ default:
20385
+ if (_Parser._isRegularOperator(tok.id)) {
20386
+ instructions.push(new PsOperator(tok.id));
20387
+ this._advance();
20388
+ break;
20389
+ }
20390
+ throw new FormatError(
20391
+ `PostScript function: unexpected token id ${tok.id}.`
20392
+ );
20393
+ }
20394
+ }
20395
+ }
20396
+ };
20397
+ function parsePostScriptFunction(source) {
20398
+ return new Parser(new Lexer(source)).parse();
20399
+ }
20400
+ function _nodesEqual(a, b) {
20401
+ if (a === b) {
20402
+ return true;
20403
+ }
20404
+ if (a.type !== b.type) {
20405
+ return false;
20406
+ }
20407
+ switch (a.type) {
20408
+ case PS_NODE.arg:
20409
+ return a.index === b.index;
20410
+ case PS_NODE.const:
20411
+ return a.value === b.value;
20412
+ case PS_NODE.unary:
20413
+ return a.op === b.op && _nodesEqual(a.operand, b.operand);
20414
+ case PS_NODE.binary:
20415
+ return a.op === b.op && _nodesEqual(a.first, b.first) && _nodesEqual(a.second, b.second);
20416
+ case PS_NODE.ternary:
20417
+ return _nodesEqual(a.cond, b.cond) && _nodesEqual(a.then, b.then) && _nodesEqual(a.otherwise, b.otherwise);
20418
+ default:
20419
+ return false;
20420
+ }
20421
+ }
20422
+ function _evalBinaryConst(op, a, b) {
20423
+ switch (op) {
20424
+ case TOKEN.add:
20425
+ return a + b;
20426
+ case TOKEN.sub:
20427
+ return a - b;
20428
+ case TOKEN.mul:
20429
+ return a * b;
20430
+ case TOKEN.div:
20431
+ return b !== 0 ? a / b : 0;
20432
+ // div by zero → 0
20433
+ case TOKEN.idiv:
20434
+ return b !== 0 ? Math.trunc(a / b) : 0;
20435
+ // div by zero → 0
20436
+ case TOKEN.mod:
20437
+ return b !== 0 ? a - Math.trunc(a / b) * b : 0;
20438
+ // div by zero → 0
20439
+ case TOKEN.exp: {
20440
+ const r = a ** b;
20441
+ return Number.isFinite(r) ? r : void 0;
20442
+ }
20443
+ case TOKEN.atan: {
20444
+ let deg = Math.atan2(a, b) * (180 / Math.PI);
20445
+ if (deg < 0) {
20446
+ deg += 360;
20447
+ }
20448
+ return deg;
20449
+ }
20450
+ case TOKEN.eq:
20451
+ return a === b;
20452
+ case TOKEN.ne:
20453
+ return a !== b;
20454
+ case TOKEN.gt:
20455
+ return a > b;
20456
+ case TOKEN.ge:
20457
+ return a >= b;
20458
+ case TOKEN.lt:
20459
+ return a < b;
20460
+ case TOKEN.le:
20461
+ return a <= b;
20462
+ case TOKEN.and:
20463
+ return typeof a === "boolean" ? a && b : a & b | 0;
20464
+ case TOKEN.or:
20465
+ return typeof a === "boolean" ? a || b : a | b | 0;
20466
+ case TOKEN.xor:
20467
+ return typeof a === "boolean" ? a !== b : a ^ b | 0;
20468
+ case TOKEN.bitshift:
20469
+ return b >= 0 ? a << b | 0 : a >> -b | 0;
20470
+ case TOKEN.min:
20471
+ return Math.min(a, b);
20472
+ case TOKEN.max:
20473
+ return Math.max(a, b);
20474
+ default:
20475
+ return void 0;
20476
+ }
20477
+ }
20478
+ function _evalUnaryConst(op, v) {
20479
+ switch (op) {
20480
+ case TOKEN.abs:
20481
+ return Math.abs(v);
20482
+ case TOKEN.neg:
20483
+ return -v;
20484
+ case TOKEN.ceiling:
20485
+ return Math.ceil(v);
20486
+ case TOKEN.floor:
20487
+ return Math.floor(v);
20488
+ case TOKEN.round:
20489
+ return Math.round(v);
20490
+ case TOKEN.truncate:
20491
+ return Math.trunc(v);
20492
+ case TOKEN.sqrt: {
20493
+ const r = Math.sqrt(v);
20494
+ return Number.isFinite(r) ? r : void 0;
20495
+ }
20496
+ case TOKEN.sin:
20497
+ return Math.sin(v % 360 * Math.PI / 180);
20498
+ case TOKEN.cos:
20499
+ return Math.cos(v % 360 * Math.PI / 180);
20500
+ case TOKEN.ln: {
20501
+ const r = Math.log(v);
20502
+ return Number.isFinite(r) ? r : void 0;
20503
+ }
20504
+ case TOKEN.log: {
20505
+ const r = Math.log10(v);
20506
+ return Number.isFinite(r) ? r : void 0;
20507
+ }
20508
+ case TOKEN.cvi:
20509
+ return Math.trunc(v);
20510
+ case TOKEN.cvr:
20511
+ return v;
20512
+ case TOKEN.not:
20513
+ return typeof v === "boolean" ? !v : ~v;
20514
+ default:
20515
+ return void 0;
20516
+ }
20517
+ }
20518
+ var MAX_STACK_SIZE = 100;
20519
+ function _unaryValueType(op, operandType) {
20520
+ return op === TOKEN.not ? operandType : PS_VALUE_TYPE.numeric;
20521
+ }
20522
+ function _binaryValueType(op, firstType, secondType) {
20523
+ switch (op) {
20524
+ // Comparison operators always produce a boolean.
20525
+ case TOKEN.eq:
20526
+ case TOKEN.ne:
20527
+ case TOKEN.gt:
20528
+ case TOKEN.ge:
20529
+ case TOKEN.lt:
20530
+ case TOKEN.le:
20531
+ return PS_VALUE_TYPE.boolean;
20532
+ // and / or / xor preserve the type when both operands are the same known
20533
+ // type (both boolean or both numeric); otherwise the type is unknown.
20534
+ case TOKEN.and:
20535
+ case TOKEN.or:
20536
+ case TOKEN.xor:
20537
+ return firstType === secondType && firstType !== PS_VALUE_TYPE.unknown ? firstType : PS_VALUE_TYPE.unknown;
20538
+ // All arithmetic / bitshift operators produce a numeric result.
20539
+ default:
20540
+ return PS_VALUE_TYPE.numeric;
20541
+ }
20542
+ }
20543
+ var PSStackToTree = class _PSStackToTree {
20544
+ static #binaryOps = null;
20545
+ static #unaryOps = null;
20546
+ static #idempotentUnary = null;
20547
+ static #negatedComparison = null;
20548
+ static #init() {
20549
+ this.#binaryOps = /* @__PURE__ */ new Set([
20550
+ TOKEN.add,
20551
+ TOKEN.sub,
20552
+ TOKEN.mul,
20553
+ TOKEN.div,
20554
+ TOKEN.idiv,
20555
+ TOKEN.mod,
20556
+ TOKEN.exp,
20557
+ TOKEN.atan,
20558
+ TOKEN.eq,
20559
+ TOKEN.ne,
20560
+ TOKEN.gt,
20561
+ TOKEN.ge,
20562
+ TOKEN.lt,
20563
+ TOKEN.le,
20564
+ TOKEN.and,
20565
+ TOKEN.or,
20566
+ TOKEN.xor,
20567
+ TOKEN.bitshift
20568
+ ]);
20569
+ this.#unaryOps = /* @__PURE__ */ new Set([
20570
+ TOKEN.abs,
20571
+ TOKEN.neg,
20572
+ TOKEN.ceiling,
20573
+ TOKEN.floor,
20574
+ TOKEN.round,
20575
+ TOKEN.truncate,
20576
+ TOKEN.sqrt,
20577
+ TOKEN.sin,
20578
+ TOKEN.cos,
20579
+ TOKEN.ln,
20580
+ TOKEN.log,
20581
+ TOKEN.cvi,
20582
+ TOKEN.cvr,
20583
+ TOKEN.not
20584
+ ]);
20585
+ this.#idempotentUnary = /* @__PURE__ */ new Set([
20586
+ TOKEN.abs,
20587
+ TOKEN.ceiling,
20588
+ TOKEN.cvi,
20589
+ TOKEN.cvr,
20590
+ TOKEN.floor,
20591
+ TOKEN.round,
20592
+ TOKEN.truncate
20593
+ ]);
20594
+ this.#negatedComparison = /* @__PURE__ */ new Map([
20595
+ [TOKEN.eq, TOKEN.ne],
20596
+ [TOKEN.ne, TOKEN.eq],
20597
+ [TOKEN.lt, TOKEN.ge],
20598
+ [TOKEN.le, TOKEN.gt],
20599
+ [TOKEN.gt, TOKEN.le],
20600
+ [TOKEN.ge, TOKEN.lt]
20601
+ ]);
20602
+ }
20603
+ /**
20604
+ * @param {PsProgram} program
20605
+ * @param {number} numInputs — number of domain values placed on the stack
20606
+ * before the program runs (i.e. the length of the domain array / 2).
20607
+ * @returns {Array<PsNode>} — one tree node per output value.
20608
+ */
20609
+ evaluate(program, numInputs) {
20610
+ if (!_PSStackToTree.#binaryOps) {
20611
+ _PSStackToTree.#init();
20612
+ }
20613
+ this._failed = false;
20614
+ if (numInputs > MAX_STACK_SIZE) {
20615
+ return null;
20616
+ }
20617
+ const stack = [];
20618
+ for (let i = 0; i < numInputs; i++) {
20619
+ stack.push(new PsArgNode(i));
20620
+ }
20621
+ this._evalBlock(program.body, stack);
20622
+ if (this._failed) {
20623
+ return null;
20624
+ }
20625
+ _PSStackToTree.#markShared(stack);
20626
+ return stack;
20627
+ }
20628
+ // Set node.shared / sharedCount on non-atomic nodes referenced more than
20629
+ // once. arg/const are excluded — they are cheap to re-emit inline.
20630
+ static #markShared(outputs) {
20631
+ const refCount = /* @__PURE__ */ new Map();
20632
+ const visit = (node) => {
20633
+ if (!node || node.type === PS_NODE.arg || node.type === PS_NODE.const) {
20634
+ return;
20635
+ }
20636
+ const prev = refCount.get(node) ?? 0;
20637
+ refCount.set(node, prev + 1);
20638
+ if (prev > 0) {
20639
+ return;
20640
+ }
20641
+ switch (node.type) {
20642
+ case PS_NODE.unary:
20643
+ visit(node.operand);
20644
+ break;
20645
+ case PS_NODE.binary:
20646
+ visit(node.first);
20647
+ visit(node.second);
20648
+ break;
20649
+ case PS_NODE.ternary:
20650
+ visit(node.cond);
20651
+ visit(node.then);
20652
+ visit(node.otherwise);
20653
+ break;
20654
+ }
20655
+ };
20656
+ for (const output of outputs) {
20657
+ visit(output);
20658
+ }
20659
+ for (const [node, count] of refCount) {
20660
+ if (count > 1) {
20661
+ node.shared = true;
20662
+ node.sharedCount = count;
20663
+ }
20664
+ }
20665
+ }
20666
+ _evalBlock(block, stack) {
20667
+ this._evalBlockFrom(block.instructions, 0, stack);
20668
+ }
20669
+ /**
20670
+ * Core evaluation loop. Processes `instructions[startIdx…]` in order,
20671
+ * mutating `stack` as each instruction executes.
20672
+ *
20673
+ * When a `{ body } if` instruction grows the stack (the PostScript "early
20674
+ * exit / guard" idiom), the remaining instructions in the current array are
20675
+ * evaluated on **both** the true-branch stack and the false-branch stack,
20676
+ * then the two results are merged into PsTernaryNodes. This handles
20677
+ * patterns like:
20678
+ *
20679
+ * cond { pop R G B sentinel } if
20680
+ * … more guards …
20681
+ * sentinel 0 gt { defaultR defaultG defaultB } if
20682
+ */
20683
+ _evalBlockFrom(instructions, startIdx, stack) {
20684
+ for (let idx = startIdx; idx < instructions.length; idx++) {
20685
+ if (this._failed) {
20686
+ break;
20687
+ }
20688
+ const instr = instructions[idx];
20689
+ switch (instr.type) {
20690
+ case PS_NODE.number:
20691
+ stack.push(new PsConstNode(instr.value));
20692
+ if (stack.length > MAX_STACK_SIZE) {
20693
+ this._failed = true;
20694
+ }
20695
+ break;
20696
+ case PS_NODE.operator:
20697
+ this._evalOp(instr.op, stack);
20698
+ break;
20699
+ case PS_NODE.if: {
20700
+ if (stack.length < 1) {
20701
+ this._failed = true;
20702
+ break;
20703
+ }
20704
+ const cond = stack.pop();
20705
+ const saved = stack.slice();
20706
+ this._evalBlock(instr.then, stack);
20707
+ if (this._failed) {
20708
+ break;
20709
+ }
20710
+ if (stack.length === saved.length) {
20711
+ for (let i = 0; i < stack.length; i++) {
20712
+ if (stack[i] !== saved[i]) {
20713
+ stack[i] = this._makeTernary(cond, stack[i], saved[i]);
20714
+ }
20715
+ }
20716
+ } else if (stack.length > saved.length) {
20717
+ if (cond.type === PS_NODE.const) {
20718
+ if (!cond.value) {
20719
+ stack.length = 0;
20720
+ stack.push(...saved);
20721
+ }
20722
+ break;
20723
+ }
20724
+ const trueStack = stack.slice();
20725
+ this._evalBlockFrom(instructions, idx + 1, trueStack);
20726
+ if (this._failed) {
20727
+ break;
20728
+ }
20729
+ const falseStack = saved;
20730
+ this._evalBlockFrom(instructions, idx + 1, falseStack);
20731
+ if (this._failed) {
20732
+ break;
20733
+ }
20734
+ if (trueStack.length !== falseStack.length) {
20735
+ const zero = new PsConstNode(0);
20736
+ while (trueStack.length < falseStack.length) {
20737
+ trueStack.push(zero);
20738
+ }
20739
+ while (falseStack.length < trueStack.length) {
20740
+ falseStack.push(zero);
20741
+ }
20742
+ }
20743
+ stack.length = 0;
20744
+ for (let i = 0; i < trueStack.length; i++) {
20745
+ stack.push(this._makeTernary(cond, trueStack[i], falseStack[i]));
20746
+ }
20747
+ return;
20748
+ } else {
20749
+ this._failed = true;
20750
+ }
20751
+ break;
20752
+ }
20753
+ case PS_NODE.ifelse: {
20754
+ if (stack.length < 1) {
20755
+ this._failed = true;
20756
+ break;
20757
+ }
20758
+ const cond = stack.pop();
20759
+ const snapshot = stack.slice();
20760
+ const thenStack = snapshot.slice();
20761
+ this._evalBlock(instr.then, thenStack);
20762
+ if (this._failed) {
20763
+ break;
20764
+ }
20765
+ const elseStack = snapshot.slice();
20766
+ this._evalBlock(instr.otherwise, elseStack);
20767
+ if (this._failed) {
20768
+ break;
20769
+ }
20770
+ if (thenStack.length !== elseStack.length) {
20771
+ const zero = new PsConstNode(0);
20772
+ while (thenStack.length < elseStack.length) {
20773
+ thenStack.push(zero);
20774
+ }
20775
+ while (elseStack.length < thenStack.length) {
20776
+ elseStack.push(zero);
20777
+ }
20778
+ }
20779
+ stack.length = 0;
20780
+ for (let i = 0; i < thenStack.length; i++) {
20781
+ stack.push(this._makeTernary(cond, thenStack[i], elseStack[i]));
20782
+ }
20783
+ break;
20784
+ }
20785
+ }
20786
+ }
20787
+ }
20788
+ _evalOp(op, stack) {
20789
+ if (_PSStackToTree.#binaryOps.has(op)) {
20790
+ if (stack.length < 2) {
20791
+ this._failed = true;
20792
+ return;
20793
+ }
20794
+ const first = stack.pop();
20795
+ const second = stack.pop();
20796
+ stack.push(this._makeBinary(op, first, second));
20797
+ return;
20798
+ }
20799
+ if (_PSStackToTree.#unaryOps.has(op)) {
20800
+ if (stack.length < 1) {
20801
+ this._failed = true;
20802
+ return;
20803
+ }
20804
+ stack.push(this._makeUnary(op, stack.pop()));
20805
+ return;
20806
+ }
20807
+ switch (op) {
20808
+ case TOKEN.true:
20809
+ stack.push(new PsConstNode(true));
20810
+ if (stack.length > MAX_STACK_SIZE) {
20811
+ this._failed = true;
20812
+ }
20813
+ break;
20814
+ case TOKEN.false:
20815
+ stack.push(new PsConstNode(false));
20816
+ if (stack.length > MAX_STACK_SIZE) {
20817
+ this._failed = true;
20818
+ }
20819
+ break;
20820
+ case TOKEN.dup:
20821
+ if (stack.length < 1) {
20822
+ this._failed = true;
20823
+ break;
20824
+ }
20825
+ stack.push(stack.at(-1));
20826
+ if (stack.length > MAX_STACK_SIZE) {
20827
+ this._failed = true;
20828
+ }
20829
+ break;
20830
+ case TOKEN.exch: {
20831
+ if (stack.length < 2) {
20832
+ this._failed = true;
20833
+ break;
20834
+ }
20835
+ const a = stack.pop();
20836
+ const b = stack.pop();
20837
+ stack.push(a, b);
20838
+ break;
20839
+ }
20840
+ case TOKEN.pop:
20841
+ if (stack.length < 1) {
20842
+ this._failed = true;
20843
+ break;
20844
+ }
20845
+ stack.pop();
20846
+ break;
20847
+ case TOKEN.copy: {
20848
+ if (stack.length < 1) {
20849
+ this._failed = true;
20850
+ break;
20851
+ }
20852
+ const nNode = stack.pop();
20853
+ if (nNode.type === PS_NODE.const) {
20854
+ const n = nNode.value | 0;
20855
+ if (n === 0) {
20856
+ } else if (n < 0 || n > stack.length) {
20857
+ this._failed = true;
20858
+ } else {
20859
+ stack.push(...stack.slice(-n));
20860
+ if (stack.length > MAX_STACK_SIZE) {
20861
+ this._failed = true;
20862
+ }
20863
+ }
20864
+ } else {
20865
+ this._failed = true;
20866
+ }
20867
+ break;
20868
+ }
20869
+ case TOKEN.index: {
20870
+ if (stack.length < 1) {
20871
+ this._failed = true;
20872
+ break;
20873
+ }
20874
+ const nNode = stack.pop();
20875
+ if (nNode.type === PS_NODE.const) {
20876
+ const n = nNode.value | 0;
20877
+ if (n < 0 || n >= stack.length) {
20878
+ this._failed = true;
20879
+ } else {
20880
+ stack.push(stack.at(-n - 1));
20881
+ }
20882
+ } else {
20883
+ this._failed = true;
20884
+ }
20885
+ break;
20886
+ }
20887
+ case TOKEN.roll: {
20888
+ if (stack.length < 2) {
20889
+ this._failed = true;
20890
+ break;
20891
+ }
20892
+ const jNode = stack.pop();
20893
+ const nNode = stack.pop();
20894
+ if (nNode.type === PS_NODE.const && jNode.type === PS_NODE.const) {
20895
+ const n = nNode.value | 0;
20896
+ if (n === 0) {
20897
+ } else if (n < 0 || n > stack.length) {
20898
+ this._failed = true;
20899
+ } else {
20900
+ const j = ((jNode.value | 0) % n + n) % n;
20901
+ if (j > 0) {
20902
+ const slice = stack.splice(-n, n);
20903
+ stack.push(...slice.slice(n - j), ...slice.slice(0, n - j));
20904
+ }
20905
+ }
20906
+ } else {
20907
+ this._failed = true;
20908
+ }
20909
+ break;
20910
+ }
20911
+ default:
20912
+ this._failed = true;
20913
+ break;
20914
+ }
20915
+ }
20916
+ /**
20917
+ * Create a binary tree node, applying optimizations eagerly:
20918
+ *
20919
+ * 1. Constant folding — both operands are PsConstNode → fold to PsConstNode.
20920
+ * 2. Reflexive simplifications — x−x→0, x xor x→0, x eq x→true, etc.
20921
+ * 3. Algebraic simplifications with one known operand — identity elements
20922
+ * (x+0→x, x*1→x, …), absorbing elements (x*0→0, x and false→false, …),
20923
+ * and strength reductions (x*-1→neg(x), x^0.5→sqrt(x), x^2→x*x, …).
20924
+ *
20925
+ * Recall: `first` was on top of the stack (right operand for non-commutative
20926
+ * ops), `second` was below (left operand). So `a b sub` → second=a, first=b
20927
+ * → a − b.
20928
+ */
20929
+ _makeBinary(op, first, second) {
20930
+ if (first.type === PS_NODE.const && second.type === PS_NODE.const) {
20931
+ const v = _evalBinaryConst(op, second.value, first.value);
20932
+ if (v !== void 0) {
20933
+ return new PsConstNode(v);
20934
+ }
20935
+ }
20936
+ if (_nodesEqual(first, second)) {
20937
+ switch (op) {
20938
+ case TOKEN.sub:
20939
+ return new PsConstNode(0);
20940
+ // x − x → 0
20941
+ case TOKEN.xor:
20942
+ return new PsConstNode(
20943
+ /* eslint-disable unicorn/prefer-logical-operator-over-ternary */
20944
+ first.valueType === PS_VALUE_TYPE.boolean ? false : 0
20945
+ /* eslint-enable unicorn/prefer-logical-operator-over-ternary */
20946
+ );
20947
+ // TOKEN.mod, TOKEN.div, TOKEN.idiv are NOT simplified here:
20948
+ // x op x is undefined when x = 0, so we cannot fold without knowing
20949
+ // that x is non-zero.
20950
+ case TOKEN.and:
20951
+ case TOKEN.or:
20952
+ return first;
20953
+ // x and x → x; x or x → x
20954
+ case TOKEN.min:
20955
+ case TOKEN.max:
20956
+ return first;
20957
+ // min(x,x) → x; max(x,x) → x
20958
+ case TOKEN.eq:
20959
+ case TOKEN.ge:
20960
+ case TOKEN.le:
20961
+ return new PsConstNode(true);
20962
+ case TOKEN.ne:
20963
+ case TOKEN.gt:
20964
+ case TOKEN.lt:
20965
+ return new PsConstNode(false);
20966
+ }
20967
+ }
20968
+ if (first.type === PS_NODE.const) {
20969
+ const b = first.value;
20970
+ switch (op) {
20971
+ case TOKEN.add:
20972
+ if (b === 0) {
20973
+ return second;
20974
+ }
20975
+ break;
20976
+ case TOKEN.sub:
20977
+ if (b === 0) {
20978
+ return second;
20979
+ }
20980
+ break;
20981
+ case TOKEN.mul:
20982
+ if (b === 1) {
20983
+ return second;
20984
+ }
20985
+ if (b === 0) {
20986
+ return first;
20987
+ }
20988
+ if (b === -1) {
20989
+ return this._makeUnary(TOKEN.neg, second);
20990
+ }
20991
+ break;
20992
+ case TOKEN.div:
20993
+ if (b !== 0) {
20994
+ return this._makeBinary(TOKEN.mul, new PsConstNode(1 / b), second);
20995
+ }
20996
+ break;
20997
+ case TOKEN.idiv:
20998
+ if (b === 1) {
20999
+ return second;
21000
+ }
21001
+ break;
21002
+ case TOKEN.exp:
21003
+ if (b === 1) {
21004
+ return second;
21005
+ }
21006
+ if (b === -1) {
21007
+ return this._makeBinary(TOKEN.div, second, new PsConstNode(1));
21008
+ }
21009
+ if (b === 0.5) {
21010
+ return this._makeUnary(TOKEN.sqrt, second);
21011
+ }
21012
+ if (b === 0.25) {
21013
+ const sqrtOnce = this._makeUnary(TOKEN.sqrt, second);
21014
+ return this._makeUnary(TOKEN.sqrt, sqrtOnce);
21015
+ }
21016
+ if (b === 2) {
21017
+ return this._makeBinary(TOKEN.mul, second, second);
21018
+ }
21019
+ if (b === 3) {
21020
+ return this._makeBinary(
21021
+ TOKEN.mul,
21022
+ this._makeBinary(TOKEN.mul, second, second),
21023
+ second
21024
+ );
21025
+ }
21026
+ if (b === 4) {
21027
+ const square = this._makeBinary(TOKEN.mul, second, second);
21028
+ return this._makeBinary(TOKEN.mul, square, square);
21029
+ }
21030
+ if (b === 0) {
21031
+ return new PsConstNode(1);
21032
+ }
21033
+ break;
21034
+ case TOKEN.and:
21035
+ if (b === true) {
21036
+ return second;
21037
+ }
21038
+ if (b === false) {
21039
+ return first;
21040
+ }
21041
+ break;
21042
+ case TOKEN.or:
21043
+ if (b === false) {
21044
+ return second;
21045
+ }
21046
+ if (b === true) {
21047
+ return first;
21048
+ }
21049
+ break;
21050
+ case TOKEN.min:
21051
+ if (second.type === PS_NODE.binary && second.op === TOKEN.max && second.first.type === PS_NODE.const && second.first.value >= b) {
21052
+ return first;
21053
+ }
21054
+ break;
21055
+ case TOKEN.max:
21056
+ if (second.type === PS_NODE.binary && second.op === TOKEN.min && second.first.type === PS_NODE.const && second.first.value <= b) {
21057
+ return first;
21058
+ }
21059
+ break;
21060
+ }
21061
+ }
21062
+ if (second.type === PS_NODE.const) {
21063
+ const a = second.value;
21064
+ switch (op) {
21065
+ case TOKEN.add:
21066
+ if (a === 0) {
21067
+ return first;
21068
+ }
21069
+ break;
21070
+ case TOKEN.sub:
21071
+ if (a === 0) {
21072
+ return this._makeUnary(TOKEN.neg, first);
21073
+ }
21074
+ break;
21075
+ case TOKEN.mul:
21076
+ if (a === 1) {
21077
+ return first;
21078
+ }
21079
+ if (a === 0) {
21080
+ return second;
21081
+ }
21082
+ if (a === -1) {
21083
+ return this._makeUnary(TOKEN.neg, first);
21084
+ }
21085
+ break;
21086
+ case TOKEN.and:
21087
+ if (a === true) {
21088
+ return first;
21089
+ }
21090
+ if (a === false) {
21091
+ return second;
21092
+ }
21093
+ break;
21094
+ case TOKEN.or:
21095
+ if (a === false) {
21096
+ return first;
21097
+ }
21098
+ if (a === true) {
21099
+ return second;
21100
+ }
21101
+ break;
21102
+ }
21103
+ }
21104
+ return new PsBinaryNode(
21105
+ op,
21106
+ first,
21107
+ second,
21108
+ _binaryValueType(op, first.valueType, second.valueType)
21109
+ );
21110
+ }
21111
+ /**
21112
+ * Create a unary tree node, applying optimizations eagerly:
21113
+ *
21114
+ * 1. Constant folding.
21115
+ * 2. not(comparison) → negated comparison: not(a eq b) → a ne b, etc.
21116
+ * 3. neg(a − b) → b − a.
21117
+ * 4. Double-negation: neg(neg(x)) → x, not(not(x)) → x.
21118
+ * 5. abs(neg(x)) → abs(x).
21119
+ * 6. Idempotent: f(f(x)) → f(x) for abs, ceiling, floor, round, etc.
21120
+ */
21121
+ _makeUnary(op, operand) {
21122
+ if (operand.type === PS_NODE.const) {
21123
+ const v = _evalUnaryConst(op, operand.value);
21124
+ if (v !== void 0) {
21125
+ return new PsConstNode(v);
21126
+ }
21127
+ }
21128
+ if (op === TOKEN.not && operand.type === PS_NODE.binary) {
21129
+ const negated = _PSStackToTree.#negatedComparison.get(operand.op);
21130
+ if (negated !== void 0) {
21131
+ return new PsBinaryNode(
21132
+ negated,
21133
+ operand.first,
21134
+ operand.second,
21135
+ PS_VALUE_TYPE.boolean
21136
+ );
21137
+ }
21138
+ }
21139
+ if (op === TOKEN.neg && operand.type === PS_NODE.binary && operand.op === TOKEN.sub) {
21140
+ return this._makeBinary(TOKEN.sub, operand.second, operand.first);
21141
+ }
21142
+ if (operand.type === PS_NODE.unary) {
21143
+ if (op === TOKEN.neg && operand.op === TOKEN.neg || op === TOKEN.not && operand.op === TOKEN.not) {
21144
+ return operand.operand;
21145
+ }
21146
+ if (op === TOKEN.abs && operand.op === TOKEN.neg) {
21147
+ return this._makeUnary(TOKEN.abs, operand.operand);
21148
+ }
21149
+ if (_PSStackToTree.#idempotentUnary.has(op) && op === operand.op) {
21150
+ return operand;
21151
+ }
21152
+ }
21153
+ return new PsUnaryNode(op, operand, _unaryValueType(op, operand.valueType));
21154
+ }
21155
+ /**
21156
+ * Create a ternary node, applying optimizations eagerly:
21157
+ *
21158
+ * 1. Constant condition — fold to the live branch.
21159
+ * 2. Identical branches — the condition is irrelevant, return either branch.
21160
+ * 3. Boolean branch constants — `cond ? true : false` → cond,
21161
+ * `cond ? false : true` → not(cond).
21162
+ * 4. Ternary → branchless min/max when the condition compares two numeric
21163
+ * expressions that are also the two branches.
21164
+ */
21165
+ _makeTernary(cond, then, otherwise) {
21166
+ if (cond.type === PS_NODE.const) {
21167
+ return cond.value ? then : otherwise;
21168
+ }
21169
+ if (_nodesEqual(then, otherwise)) {
21170
+ return then;
21171
+ }
21172
+ if (then.type === PS_NODE.const && otherwise.type === PS_NODE.const) {
21173
+ if (then.value === true && otherwise.value === false) {
21174
+ return cond;
21175
+ }
21176
+ if (then.value === false && otherwise.value === true) {
21177
+ return this._makeUnary(TOKEN.not, cond);
21178
+ }
21179
+ }
21180
+ if (cond.type === PS_NODE.binary) {
21181
+ const { op: cop, first: cf, second: cs } = cond;
21182
+ if (cop === TOKEN.gt || cop === TOKEN.ge) {
21183
+ if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
21184
+ return this._makeBinary(TOKEN.min, cf, cs);
21185
+ }
21186
+ if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
21187
+ return this._makeBinary(TOKEN.max, cf, cs);
21188
+ }
21189
+ } else if (cop === TOKEN.lt || cop === TOKEN.le) {
21190
+ if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
21191
+ return this._makeBinary(TOKEN.max, cf, cs);
21192
+ }
21193
+ if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
21194
+ return this._makeBinary(TOKEN.min, cf, cs);
21195
+ }
21196
+ }
21197
+ }
21198
+ return new PsTernaryNode(
21199
+ cond,
21200
+ then,
21201
+ otherwise,
21202
+ then.valueType === otherwise.valueType ? then.valueType : PS_VALUE_TYPE.unknown
21203
+ );
21204
+ }
21205
+ };
21206
+
21207
+ // src/core/postscript/js_evaluator.js
21208
+ var OP = {
21209
+ ARG: 0,
21210
+ // [ARG, idx]
21211
+ CONST: 1,
21212
+ // [CONST, val]
21213
+ STORE: 2,
21214
+ // [STORE, slot, min, max] clamp(pop()) → mem[slot]
21215
+ IF: 3,
21216
+ // [IF, target] jump when top-of-stack === 0
21217
+ JUMP: 4,
21218
+ // [JUMP, target] unconditional
21219
+ ABS: 5,
21220
+ NEG: 6,
21221
+ CEIL: 7,
21222
+ FLOOR: 8,
21223
+ ROUND: 9,
21224
+ // floor(x + 0.5)
21225
+ TRUNC: 10,
21226
+ NOT_B: 11,
21227
+ // boolean NOT
21228
+ NOT_N: 12,
21229
+ // bitwise NOT
21230
+ SQRT: 13,
21231
+ SIN: 14,
21232
+ // degrees in/out
21233
+ COS: 15,
21234
+ LN: 16,
21235
+ LOG10: 17,
21236
+ CVI: 18,
21237
+ SHIFT: 19,
21238
+ // [SHIFT, amount] +ve = left, −ve = right
21239
+ // Binary ops: second below, first on top; result = second OP first.
21240
+ ADD: 20,
21241
+ SUB: 21,
21242
+ MUL: 22,
21243
+ DIV: 23,
21244
+ // 0 when divisor is 0
21245
+ IDIV: 24,
21246
+ // 0 when divisor is 0
21247
+ MOD: 25,
21248
+ // 0 when divisor is 0
21249
+ POW: 26,
21250
+ EQ: 27,
21251
+ NE: 28,
21252
+ GT: 29,
21253
+ GE: 30,
21254
+ LT: 31,
21255
+ LE: 32,
21256
+ AND: 33,
21257
+ OR: 34,
21258
+ XOR: 35,
21259
+ ATAN: 36,
21260
+ // atan2(second, first) → degrees [0, 360)
21261
+ MIN: 37,
21262
+ MAX: 38,
21263
+ TEE_TMP: 39,
21264
+ // [TEE_TMP, slot] peek top of stack → tmp[slot], leave on stack
21265
+ LOAD_TMP: 40
21266
+ // [LOAD_TMP, slot] push tmp[slot]
21267
+ };
21268
+ var _DEG_TO_RAD = Math.PI / 180;
21269
+ var _RAD_TO_DEG = 180 / Math.PI;
21270
+ var PsJsCompiler = class {
21271
+ // Safe because JS is single-threaded.
21272
+ static #stack = new Float64Array(64);
21273
+ static #tmp = new Float64Array(64);
21274
+ constructor(domain, range) {
21275
+ this.nIn = domain.length >> 1;
21276
+ this.nOut = range.length >> 1;
21277
+ this.range = range;
21278
+ this.ir = [];
21279
+ this._tmpMap = /* @__PURE__ */ new Map();
21280
+ this._nextTmp = 0;
21281
+ }
21282
+ _compileNode(node) {
21283
+ if (node.shared) {
21284
+ const cached = this._tmpMap.get(node);
21285
+ if (cached !== void 0) {
21286
+ this.ir.push(OP.LOAD_TMP, cached);
21287
+ return true;
21288
+ }
21289
+ if (!this._compileNodeImpl(node)) {
21290
+ return false;
21291
+ }
21292
+ const slot = this._nextTmp++;
21293
+ this._tmpMap.set(node, slot);
21294
+ this.ir.push(OP.TEE_TMP, slot);
21295
+ return true;
21296
+ }
21297
+ return this._compileNodeImpl(node);
21298
+ }
21299
+ _compileNodeImpl(node) {
21300
+ switch (node.type) {
21301
+ case PS_NODE.arg:
21302
+ this.ir.push(OP.ARG, node.index);
21303
+ return true;
21304
+ case PS_NODE.const: {
21305
+ const v = node.value;
21306
+ this.ir.push(OP.CONST, typeof v === "boolean" ? Number(v) : v);
21307
+ return true;
21308
+ }
21309
+ case PS_NODE.unary:
21310
+ return this._compileUnary(node);
21311
+ case PS_NODE.binary:
21312
+ return this._compileBinary(node);
21313
+ case PS_NODE.ternary:
21314
+ return this._compileTernary(node);
21315
+ default:
21316
+ return false;
21317
+ }
21318
+ }
21319
+ _compileUnary(node) {
21320
+ const { op, operand, valueType } = node;
21321
+ if (op === TOKEN.cvr) {
21322
+ return this._compileNode(operand);
21323
+ }
21324
+ if (!this._compileNode(operand)) {
21325
+ return false;
21326
+ }
21327
+ switch (op) {
21328
+ case TOKEN.abs:
21329
+ this.ir.push(OP.ABS);
21330
+ break;
21331
+ case TOKEN.neg:
21332
+ this.ir.push(OP.NEG);
21333
+ break;
21334
+ case TOKEN.ceiling:
21335
+ this.ir.push(OP.CEIL);
21336
+ break;
21337
+ case TOKEN.floor:
21338
+ this.ir.push(OP.FLOOR);
21339
+ break;
21340
+ case TOKEN.round:
21341
+ this.ir.push(OP.ROUND);
21342
+ break;
21343
+ case TOKEN.truncate:
21344
+ this.ir.push(OP.TRUNC);
21345
+ break;
21346
+ case TOKEN.sqrt:
21347
+ this.ir.push(OP.SQRT);
21348
+ break;
21349
+ case TOKEN.sin:
21350
+ this.ir.push(OP.SIN);
21351
+ break;
21352
+ case TOKEN.cos:
21353
+ this.ir.push(OP.COS);
21354
+ break;
21355
+ case TOKEN.ln:
21356
+ this.ir.push(OP.LN);
21357
+ break;
21358
+ case TOKEN.log:
21359
+ this.ir.push(OP.LOG10);
21360
+ break;
21361
+ case TOKEN.cvi:
21362
+ this.ir.push(OP.CVI);
21363
+ break;
21364
+ case TOKEN.not:
21365
+ if (valueType === PS_VALUE_TYPE.boolean) {
21366
+ this.ir.push(OP.NOT_B);
21367
+ } else if (valueType === PS_VALUE_TYPE.numeric) {
21368
+ this.ir.push(OP.NOT_N);
21369
+ } else {
21370
+ return false;
21371
+ }
21372
+ break;
21373
+ default:
21374
+ return false;
21375
+ }
21376
+ return true;
21377
+ }
21378
+ _compileBinary(node) {
21379
+ const { op, first, second } = node;
21380
+ if (op === TOKEN.bitshift) {
21381
+ if (first.type !== PS_NODE.const || !Number.isInteger(first.value) || !this._compileNode(second)) {
21382
+ return false;
21383
+ }
21384
+ this.ir.push(OP.SHIFT, first.value);
21385
+ return true;
21386
+ }
21387
+ if (!this._compileNode(second) || !this._compileNode(first)) {
21388
+ return false;
21389
+ }
21390
+ switch (op) {
21391
+ case TOKEN.add:
21392
+ this.ir.push(OP.ADD);
21393
+ break;
21394
+ case TOKEN.sub:
21395
+ this.ir.push(OP.SUB);
21396
+ break;
21397
+ case TOKEN.mul:
21398
+ this.ir.push(OP.MUL);
21399
+ break;
21400
+ case TOKEN.div:
21401
+ this.ir.push(OP.DIV);
21402
+ break;
21403
+ case TOKEN.idiv:
21404
+ this.ir.push(OP.IDIV);
21405
+ break;
21406
+ case TOKEN.mod:
21407
+ this.ir.push(OP.MOD);
21408
+ break;
21409
+ case TOKEN.exp:
21410
+ this.ir.push(OP.POW);
21411
+ break;
21412
+ case TOKEN.eq:
21413
+ this.ir.push(OP.EQ);
21414
+ break;
21415
+ case TOKEN.ne:
21416
+ this.ir.push(OP.NE);
21417
+ break;
21418
+ case TOKEN.gt:
21419
+ this.ir.push(OP.GT);
21420
+ break;
21421
+ case TOKEN.ge:
21422
+ this.ir.push(OP.GE);
21423
+ break;
21424
+ case TOKEN.lt:
21425
+ this.ir.push(OP.LT);
21426
+ break;
21427
+ case TOKEN.le:
21428
+ this.ir.push(OP.LE);
21429
+ break;
21430
+ case TOKEN.and:
21431
+ this.ir.push(OP.AND);
21432
+ break;
21433
+ case TOKEN.or:
21434
+ this.ir.push(OP.OR);
21435
+ break;
21436
+ case TOKEN.xor:
21437
+ this.ir.push(OP.XOR);
21438
+ break;
21439
+ case TOKEN.atan:
21440
+ this.ir.push(OP.ATAN);
21441
+ break;
21442
+ case TOKEN.min:
21443
+ this.ir.push(OP.MIN);
21444
+ break;
21445
+ case TOKEN.max:
21446
+ this.ir.push(OP.MAX);
21447
+ break;
21448
+ default:
21449
+ return false;
21450
+ }
21451
+ return true;
21452
+ }
21453
+ _compileTernary(node) {
21454
+ if (!this._compileNode(node.cond)) {
21455
+ return false;
21456
+ }
21457
+ this.ir.push(OP.IF, 0);
21458
+ const ifPatch = this.ir.length - 1;
21459
+ if (!this._compileNode(node.then)) {
21460
+ return false;
21461
+ }
21462
+ this.ir.push(OP.JUMP, 0);
21463
+ const jumpPatch = this.ir.length - 1;
21464
+ this.ir[ifPatch] = this.ir.length;
21465
+ if (!this._compileNode(node.otherwise)) {
21466
+ return false;
21467
+ }
21468
+ this.ir[jumpPatch] = this.ir.length;
21469
+ return true;
21470
+ }
21471
+ compile(program) {
21472
+ const outputs = new PSStackToTree().evaluate(program, this.nIn);
21473
+ if (!outputs || outputs.length < this.nOut) {
21474
+ return null;
21475
+ }
21476
+ for (let i = 0; i < this.nOut; i++) {
21477
+ if (!this._compileNode(outputs[i])) {
21478
+ return null;
21479
+ }
21480
+ const min = this.range[i * 2];
21481
+ const max = this.range[i * 2 + 1];
21482
+ this.ir.push(OP.STORE, i, min, max);
21483
+ }
21484
+ return new Float64Array(this.ir);
21485
+ }
21486
+ static execute(ir, src, srcOffset, dest, destOffset) {
21487
+ let ip = 0, sp = 0;
21488
+ const n = ir.length;
21489
+ const stack = this.#stack;
21490
+ const tmp = this.#tmp;
21491
+ while (ip < n) {
21492
+ switch (ir[ip++] | 0) {
21493
+ case OP.ARG:
21494
+ stack[sp++] = src[srcOffset + (ir[ip++] | 0)];
21495
+ break;
21496
+ case OP.CONST:
21497
+ stack[sp++] = ir[ip++];
21498
+ break;
21499
+ case OP.STORE: {
21500
+ const slot = ir[ip++] | 0;
21501
+ const min = ir[ip++];
21502
+ const max = ir[ip++];
21503
+ dest[destOffset + slot] = MathClamp(stack[--sp], min, max);
21504
+ break;
21505
+ }
21506
+ case OP.IF: {
21507
+ const tgt = ir[ip++];
21508
+ if (stack[--sp] === 0) {
21509
+ ip = tgt;
21510
+ }
21511
+ break;
21512
+ }
21513
+ case OP.JUMP:
21514
+ ip = ir[ip];
21515
+ break;
21516
+ case OP.ABS:
21517
+ stack[sp - 1] = Math.abs(stack[sp - 1]);
21518
+ break;
21519
+ case OP.NEG:
21520
+ stack[sp - 1] = -stack[sp - 1];
21521
+ break;
21522
+ case OP.CEIL:
21523
+ stack[sp - 1] = Math.ceil(stack[sp - 1]);
21524
+ break;
21525
+ case OP.FLOOR:
21526
+ stack[sp - 1] = Math.floor(stack[sp - 1]);
21527
+ break;
21528
+ case OP.ROUND:
21529
+ stack[sp - 1] = Math.floor(stack[sp - 1] + 0.5);
21530
+ break;
21531
+ case OP.TRUNC:
21532
+ stack[sp - 1] = Math.trunc(stack[sp - 1]);
21533
+ break;
21534
+ case OP.NOT_B:
21535
+ stack[sp - 1] = stack[sp - 1] !== 0 ? 0 : 1;
21536
+ break;
21537
+ case OP.NOT_N:
21538
+ stack[sp - 1] = ~(stack[sp - 1] | 0);
21539
+ break;
21540
+ case OP.SQRT:
21541
+ stack[sp - 1] = Math.sqrt(stack[sp - 1]);
21542
+ break;
21543
+ case OP.SIN:
21544
+ stack[sp - 1] = Math.sin(stack[sp - 1] % 360 * _DEG_TO_RAD);
21545
+ break;
21546
+ case OP.COS:
21547
+ stack[sp - 1] = Math.cos(stack[sp - 1] % 360 * _DEG_TO_RAD);
21548
+ break;
21549
+ case OP.LN:
21550
+ stack[sp - 1] = Math.log(stack[sp - 1]);
21551
+ break;
21552
+ case OP.LOG10:
21553
+ stack[sp - 1] = Math.log10(stack[sp - 1]);
21554
+ break;
21555
+ case OP.CVI:
21556
+ stack[sp - 1] = Math.trunc(stack[sp - 1]) | 0;
21557
+ break;
21558
+ case OP.SHIFT: {
21559
+ const amt = ir[ip++];
21560
+ const v = stack[sp - 1] | 0;
21561
+ if (amt > 0) {
21562
+ stack[sp - 1] = v << amt;
21563
+ } else if (amt < 0) {
21564
+ stack[sp - 1] = v >> -amt;
21565
+ } else {
21566
+ stack[sp - 1] = v;
21567
+ }
21568
+ break;
21569
+ }
21570
+ case OP.ADD: {
21571
+ const b = stack[--sp];
21572
+ stack[sp - 1] += b;
21573
+ break;
21574
+ }
21575
+ case OP.SUB: {
21576
+ const b = stack[--sp];
21577
+ stack[sp - 1] -= b;
21578
+ break;
21579
+ }
21580
+ case OP.MUL: {
21581
+ const b = stack[--sp];
21582
+ stack[sp - 1] *= b;
21583
+ break;
21584
+ }
21585
+ case OP.DIV: {
21586
+ const b = stack[--sp];
21587
+ stack[sp - 1] = b !== 0 ? stack[sp - 1] / b : 0;
21588
+ break;
21589
+ }
21590
+ case OP.IDIV: {
21591
+ const b = stack[--sp];
21592
+ stack[sp - 1] = b !== 0 ? Math.trunc(stack[sp - 1] / b) : 0;
21593
+ break;
21594
+ }
21595
+ case OP.MOD: {
21596
+ const b = stack[--sp];
21597
+ stack[sp - 1] = b !== 0 ? stack[sp - 1] % b : 0;
21598
+ break;
21599
+ }
21600
+ case OP.POW: {
21601
+ const b = stack[--sp];
21602
+ stack[sp - 1] **= b;
21603
+ break;
21604
+ }
21605
+ case OP.EQ: {
21606
+ const b = stack[--sp];
21607
+ stack[sp - 1] = stack[sp - 1] === b ? 1 : 0;
21608
+ break;
21609
+ }
21610
+ case OP.NE: {
21611
+ const b = stack[--sp];
21612
+ stack[sp - 1] = stack[sp - 1] !== b ? 1 : 0;
21613
+ break;
21614
+ }
21615
+ case OP.GT: {
21616
+ const b = stack[--sp];
21617
+ stack[sp - 1] = stack[sp - 1] > b ? 1 : 0;
21618
+ break;
21619
+ }
21620
+ case OP.GE: {
21621
+ const b = stack[--sp];
21622
+ stack[sp - 1] = stack[sp - 1] >= b ? 1 : 0;
21623
+ break;
21624
+ }
21625
+ case OP.LT: {
21626
+ const b = stack[--sp];
21627
+ stack[sp - 1] = stack[sp - 1] < b ? 1 : 0;
21628
+ break;
21629
+ }
21630
+ case OP.LE: {
21631
+ const b = stack[--sp];
21632
+ stack[sp - 1] = stack[sp - 1] <= b ? 1 : 0;
21633
+ break;
21634
+ }
21635
+ case OP.AND: {
21636
+ const b = stack[--sp] | 0;
21637
+ stack[sp - 1] = (stack[sp - 1] | 0) & b;
21638
+ break;
21639
+ }
21640
+ case OP.OR: {
21641
+ const b = stack[--sp] | 0;
21642
+ stack[sp - 1] = stack[sp - 1] | 0 | b;
21643
+ break;
21644
+ }
21645
+ case OP.XOR: {
21646
+ const b = stack[--sp] | 0;
21647
+ stack[sp - 1] = (stack[sp - 1] | 0) ^ b;
21648
+ break;
21649
+ }
21650
+ case OP.ATAN: {
21651
+ const b = stack[--sp];
21652
+ const deg = Math.atan2(stack[sp - 1], b) * _RAD_TO_DEG;
21653
+ stack[sp - 1] = deg < 0 ? deg + 360 : deg;
21654
+ break;
21655
+ }
21656
+ case OP.MIN: {
21657
+ const b = stack[--sp];
21658
+ stack[sp - 1] = Math.min(stack[sp - 1], b);
21659
+ break;
21660
+ }
21661
+ case OP.MAX: {
21662
+ const b = stack[--sp];
21663
+ stack[sp - 1] = Math.max(stack[sp - 1], b);
21664
+ break;
21665
+ }
21666
+ case OP.TEE_TMP:
21667
+ tmp[ir[ip++] | 0] = stack[sp - 1];
21668
+ break;
21669
+ case OP.LOAD_TMP:
21670
+ stack[sp++] = tmp[ir[ip++] | 0];
21671
+ break;
21672
+ }
21673
+ }
21674
+ }
21675
+ };
21676
+ var PSStackBasedInterpreter = class {
21677
+ // Safe: JS is single-threaded.
21678
+ static #stack = new Float64Array(100);
21679
+ static #sp = 0;
21680
+ static #push(v) {
21681
+ if (this.#sp < this.#stack.length) {
21682
+ this.#stack[this.#sp++] = v;
21683
+ }
21684
+ }
21685
+ static #execOp(op) {
21686
+ const stack = this.#stack;
21687
+ switch (op) {
21688
+ case TOKEN.true:
21689
+ this.#push(1);
21690
+ break;
21691
+ case TOKEN.false:
21692
+ this.#push(0);
21693
+ break;
21694
+ case TOKEN.abs:
21695
+ stack[this.#sp - 1] = Math.abs(stack[this.#sp - 1]);
21696
+ break;
21697
+ case TOKEN.neg:
21698
+ stack[this.#sp - 1] = -stack[this.#sp - 1];
21699
+ break;
21700
+ case TOKEN.ceiling:
21701
+ stack[this.#sp - 1] = Math.ceil(stack[this.#sp - 1]);
21702
+ break;
21703
+ case TOKEN.floor:
21704
+ stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1]);
21705
+ break;
21706
+ case TOKEN.round:
21707
+ stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1] + 0.5);
21708
+ break;
21709
+ case TOKEN.truncate:
21710
+ stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]);
21711
+ break;
21712
+ case TOKEN.sqrt:
21713
+ stack[this.#sp - 1] = Math.sqrt(stack[this.#sp - 1]);
21714
+ break;
21715
+ case TOKEN.sin:
21716
+ stack[this.#sp - 1] = Math.sin(
21717
+ stack[this.#sp - 1] % 360 * _DEG_TO_RAD
21718
+ );
21719
+ break;
21720
+ case TOKEN.cos:
21721
+ stack[this.#sp - 1] = Math.cos(
21722
+ stack[this.#sp - 1] % 360 * _DEG_TO_RAD
21723
+ );
21724
+ break;
21725
+ case TOKEN.ln:
21726
+ stack[this.#sp - 1] = Math.log(stack[this.#sp - 1]);
21727
+ break;
21728
+ case TOKEN.log:
21729
+ stack[this.#sp - 1] = Math.log10(stack[this.#sp - 1]);
21730
+ break;
21731
+ case TOKEN.cvi:
21732
+ stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]) | 0;
21733
+ break;
21734
+ case TOKEN.cvr:
21735
+ break;
21736
+ // values are already f64
21737
+ case TOKEN.not: {
21738
+ const v = stack[this.#sp - 1];
21739
+ stack[this.#sp - 1] = v === 0 || v === 1 ? 1 - v : ~(v | 0);
21740
+ break;
21741
+ }
21742
+ case TOKEN.add: {
21743
+ const b = stack[--this.#sp];
21744
+ stack[this.#sp - 1] += b;
21745
+ break;
21746
+ }
21747
+ case TOKEN.sub: {
21748
+ const b = stack[--this.#sp];
21749
+ stack[this.#sp - 1] -= b;
21750
+ break;
21751
+ }
21752
+ case TOKEN.mul: {
21753
+ const b = stack[--this.#sp];
21754
+ stack[this.#sp - 1] *= b;
21755
+ break;
21756
+ }
21757
+ case TOKEN.div: {
21758
+ const b = stack[--this.#sp];
21759
+ stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] / b : 0;
21760
+ break;
21761
+ }
21762
+ case TOKEN.idiv: {
21763
+ const b = stack[--this.#sp];
21764
+ stack[this.#sp - 1] = b !== 0 ? Math.trunc(stack[this.#sp - 1] / b) : 0;
21765
+ break;
21766
+ }
21767
+ case TOKEN.mod: {
21768
+ const b = stack[--this.#sp];
21769
+ stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] % b : 0;
21770
+ break;
21771
+ }
21772
+ case TOKEN.exp: {
21773
+ const b = stack[--this.#sp];
21774
+ stack[this.#sp - 1] **= b;
21775
+ break;
21776
+ }
21777
+ case TOKEN.atan: {
21778
+ const dx = stack[--this.#sp];
21779
+ const deg = Math.atan2(stack[this.#sp - 1], dx) * _RAD_TO_DEG;
21780
+ stack[this.#sp - 1] = deg < 0 ? deg + 360 : deg;
21781
+ break;
21782
+ }
21783
+ case TOKEN.eq: {
21784
+ const b = stack[--this.#sp];
21785
+ stack[this.#sp - 1] = stack[this.#sp - 1] === b ? 1 : 0;
21786
+ break;
21787
+ }
21788
+ case TOKEN.ne: {
21789
+ const b = stack[--this.#sp];
21790
+ stack[this.#sp - 1] = stack[this.#sp - 1] !== b ? 1 : 0;
21791
+ break;
21792
+ }
21793
+ case TOKEN.gt: {
21794
+ const b = stack[--this.#sp];
21795
+ stack[this.#sp - 1] = stack[this.#sp - 1] > b ? 1 : 0;
21796
+ break;
21797
+ }
21798
+ case TOKEN.ge: {
21799
+ const b = stack[--this.#sp];
21800
+ stack[this.#sp - 1] = stack[this.#sp - 1] >= b ? 1 : 0;
21801
+ break;
21802
+ }
21803
+ case TOKEN.lt: {
21804
+ const b = stack[--this.#sp];
21805
+ stack[this.#sp - 1] = stack[this.#sp - 1] < b ? 1 : 0;
21806
+ break;
21807
+ }
21808
+ case TOKEN.le: {
21809
+ const b = stack[--this.#sp];
21810
+ stack[this.#sp - 1] = stack[this.#sp - 1] <= b ? 1 : 0;
21811
+ break;
21812
+ }
21813
+ case TOKEN.and: {
21814
+ const b = stack[--this.#sp] | 0;
21815
+ stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) & b;
21816
+ break;
21817
+ }
21818
+ case TOKEN.or: {
21819
+ const b = stack[--this.#sp] | 0;
21820
+ stack[this.#sp - 1] = stack[this.#sp - 1] | 0 | b;
21821
+ break;
21822
+ }
21823
+ case TOKEN.xor: {
21824
+ const b = stack[--this.#sp] | 0;
21825
+ stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) ^ b;
21826
+ break;
21827
+ }
21828
+ case TOKEN.bitshift: {
21829
+ const amt = stack[--this.#sp] | 0;
21830
+ const v = stack[this.#sp - 1] | 0;
21831
+ stack[this.#sp - 1] = amt > 0 ? v << amt : v >> -amt;
21832
+ break;
21833
+ }
21834
+ case TOKEN.min: {
21835
+ const b = stack[--this.#sp];
21836
+ stack[this.#sp - 1] = Math.min(stack[this.#sp - 1], b);
21837
+ break;
21838
+ }
21839
+ case TOKEN.max: {
21840
+ const b = stack[--this.#sp];
21841
+ stack[this.#sp - 1] = Math.max(stack[this.#sp - 1], b);
21842
+ break;
21843
+ }
21844
+ case TOKEN.dup:
21845
+ this.#push(stack[this.#sp - 1]);
21846
+ break;
21847
+ case TOKEN.exch: {
21848
+ const a = stack[--this.#sp];
21849
+ const b = stack[--this.#sp];
21850
+ this.#push(a);
21851
+ this.#push(b);
21852
+ break;
21853
+ }
21854
+ case TOKEN.pop:
21855
+ this.#sp--;
21856
+ break;
21857
+ case TOKEN.copy: {
21858
+ const n = Math.trunc(stack[--this.#sp]);
21859
+ const base = this.#sp - n;
21860
+ for (let k = 0; k < n; k++) {
21861
+ this.#push(stack[base + k]);
21862
+ }
21863
+ break;
21864
+ }
21865
+ case TOKEN.index: {
21866
+ const i = Math.trunc(stack[--this.#sp]);
21867
+ this.#push(stack[this.#sp - 1 - i]);
21868
+ break;
21869
+ }
21870
+ case TOKEN.roll: {
21871
+ const j = Math.trunc(stack[--this.#sp]);
21872
+ const n = Math.trunc(stack[--this.#sp]);
21873
+ if (n > 1 && j !== 0) {
21874
+ const mod = (j % n + n) % n;
21875
+ if (mod !== 0) {
21876
+ const base = this.#sp - n;
21877
+ const sub = stack.slice(base, this.#sp);
21878
+ for (let k = 0; k < n; k++) {
21879
+ stack[base + k] = sub[(k - mod + n) % n];
21880
+ }
21881
+ }
21882
+ }
21883
+ break;
21884
+ }
21885
+ }
21886
+ }
21887
+ static #execBlock(instructions) {
21888
+ for (const instr of instructions) {
21889
+ switch (instr.type) {
21890
+ case PS_NODE.number:
21891
+ this.#push(instr.value);
21892
+ break;
21893
+ case PS_NODE.operator:
21894
+ this.#execOp(instr.op);
21895
+ break;
21896
+ case PS_NODE.if:
21897
+ if (this.#stack[--this.#sp] !== 0) {
21898
+ this.#execBlock(instr.then.instructions);
21899
+ }
21900
+ break;
21901
+ case PS_NODE.ifelse:
21902
+ if (this.#stack[--this.#sp] !== 0) {
21903
+ this.#execBlock(instr.then.instructions);
21904
+ } else {
21905
+ this.#execBlock(instr.otherwise.instructions);
21906
+ }
21907
+ break;
21908
+ }
21909
+ }
21910
+ }
21911
+ /**
21912
+ * @param {import("./ast.js").PsProgram} program
21913
+ * @param {number[]} domain – flat [min0,max0, …]
21914
+ * @param {number[]} range – flat [min0,max0, …]
21915
+ * @returns {Function} – `(src, srcOffset, dest, destOffset) => void`
21916
+ */
21917
+ static build(program, domain, range) {
21918
+ const nIn = domain.length >> 1;
21919
+ const nOut = range.length >> 1;
21920
+ const { instructions } = program.body;
21921
+ return (src, srcOffset, dest, destOffset) => {
21922
+ this.#sp = 0;
21923
+ for (let i = 0; i < nIn; i++) {
21924
+ this.#push(src[srcOffset + i]);
21925
+ }
21926
+ this.#execBlock(instructions);
21927
+ const base = this.#sp - nOut;
21928
+ for (let i = 0; i < nOut; i++) {
21929
+ const v = base + i >= 0 ? this.#stack[base + i] : 0;
21930
+ dest[destOffset + i] = MathClamp(v, range[i * 2], range[i * 2 + 1]);
21931
+ }
21932
+ };
21933
+ }
21934
+ };
21935
+ function buildPostScriptJsFunction(source, domain, range, forceInterpreter = false) {
21936
+ const program = parsePostScriptFunction(source);
21937
+ const ir = !forceInterpreter && new PsJsCompiler(domain, range).compile(program);
21938
+ if (ir) {
21939
+ return (src, srcOffset, dest, destOffset) => {
21940
+ PsJsCompiler.execute(ir, src, srcOffset, dest, destOffset);
21941
+ };
21942
+ }
21943
+ return PSStackBasedInterpreter.build(program, domain, range);
21944
+ }
21945
+
21946
+ // src/core/pattern.js
21947
+ var ShadingType = {
21948
+ FUNCTION_BASED: 1,
21949
+ AXIAL: 2,
21950
+ RADIAL: 3,
21951
+ FREE_FORM_MESH: 4,
21952
+ LATTICE_FORM_MESH: 5,
21953
+ COONS_PATCH_MESH: 6,
21954
+ TENSOR_PATCH_MESH: 7
21955
+ };
21956
+ var BaseShading = class _BaseShading {
21957
+ // A small number to offset the first/last color stops so we can insert ones
21958
+ // to support extend. Number.MIN_VALUE is too small and breaks the extend.
21959
+ static SMALL_NUMBER = 1e-6;
21960
+ constructor() {
21961
+ if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _BaseShading) {
21962
+ unreachable("Cannot initialize BaseShading.");
21963
+ }
21964
+ }
21965
+ getIR() {
21966
+ unreachable("Abstract method `getIR` called.");
21967
+ }
21968
+ };
21969
+ function meshUpdateBounds(self) {
21970
+ let minX = self.coords[0][0], minY = self.coords[0][1], maxX = minX, maxY = minY;
21971
+ for (let i = 1, ii = self.coords.length; i < ii; i++) {
21972
+ const x = self.coords[i][0], y = self.coords[i][1];
21973
+ minX = minX > x ? x : minX;
21974
+ minY = minY > y ? y : minY;
21975
+ maxX = maxX < x ? x : maxX;
21976
+ maxY = maxY < y ? y : maxY;
21977
+ }
21978
+ self.bounds = [minX, minY, maxX, maxY];
21979
+ }
21980
+ function meshPackData(self) {
21981
+ let i, j, ii;
21982
+ const coords = self.coords;
21983
+ const coordsPacked = new Float32Array(coords.length * 2);
21984
+ for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
21985
+ const xy = coords[i];
21986
+ coordsPacked[j++] = xy[0];
21987
+ coordsPacked[j++] = xy[1];
21988
+ }
21989
+ self.coords = coordsPacked;
21990
+ const colors = self.colors;
21991
+ const colorsPacked = new Uint8Array(colors.length * 4);
21992
+ for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
21993
+ const c = colors[i];
21994
+ colorsPacked[j++] = c[0];
21995
+ colorsPacked[j++] = c[1];
21996
+ colorsPacked[j++] = c[2];
21997
+ j++;
21998
+ }
21999
+ self.colors = colorsPacked;
22000
+ for (const figure of self.figures) {
22001
+ figure.coords = new Uint32Array(figure.coords);
22002
+ figure.colors = new Uint32Array(figure.colors);
22003
+ }
22004
+ }
22005
+ function buildMeshVertexData(coords, colors, figures) {
22006
+ let vertexCount = 0;
22007
+ for (const figure of figures) {
22008
+ if (figure.type === MeshFigureType.TRIANGLES) {
22009
+ vertexCount += figure.coords.length;
22010
+ } else if (figure.type === MeshFigureType.LATTICE) {
22011
+ const vpr = figure.verticesPerRow;
22012
+ vertexCount += (Math.floor(figure.coords.length / vpr) - 1) * (vpr - 1) * 6;
22013
+ }
22014
+ }
22015
+ const posData = new Float32Array(vertexCount * 2);
22016
+ const colData = new Uint8Array(vertexCount * 4);
22017
+ let pOff = 0, cOff = 0;
22018
+ const addVertex = (pi, ci) => {
22019
+ posData[pOff++] = coords[pi * 2];
22020
+ posData[pOff++] = coords[pi * 2 + 1];
22021
+ colData[cOff++] = colors[ci * 4];
22022
+ colData[cOff++] = colors[ci * 4 + 1];
22023
+ colData[cOff++] = colors[ci * 4 + 2];
22024
+ cOff++;
22025
+ };
22026
+ for (const figure of figures) {
22027
+ const ps = figure.coords;
22028
+ const cs = figure.colors;
22029
+ if (figure.type === MeshFigureType.TRIANGLES) {
22030
+ for (let i = 0, ii = ps.length; i < ii; i++) {
22031
+ addVertex(ps[i], cs[i]);
22032
+ }
22033
+ } else if (figure.type === MeshFigureType.LATTICE) {
22034
+ const vpr = figure.verticesPerRow;
22035
+ const rows = Math.floor(ps.length / vpr) - 1;
22036
+ const cols = vpr - 1;
22037
+ for (let i = 0; i < rows; i++) {
22038
+ let q = i * vpr;
22039
+ for (let j = 0; j < cols; j++, q++) {
22040
+ addVertex(ps[q], cs[q]);
22041
+ addVertex(ps[q + 1], cs[q + 1]);
22042
+ addVertex(ps[q + vpr], cs[q + vpr]);
22043
+ addVertex(ps[q + vpr + 1], cs[q + vpr + 1]);
22044
+ addVertex(ps[q + 1], cs[q + 1]);
22045
+ addVertex(ps[q + vpr], cs[q + vpr]);
22046
+ }
22047
+ }
22048
+ }
22049
+ }
22050
+ return { posData, colData, vertexCount };
22051
+ }
22052
+ var MeshStreamReader = class {
22053
+ constructor(stream, context) {
22054
+ this.stream = stream;
22055
+ this.context = context;
22056
+ this.buffer = 0;
22057
+ this.bufferLength = 0;
22058
+ const numComps = context.numComps;
22059
+ this.tmpCompsBuf = new Float32Array(numComps);
22060
+ const csNumComps = context.colorSpace.numComps;
22061
+ this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf;
22062
+ }
22063
+ get hasData() {
22064
+ if (this.stream.end) {
22065
+ return this.stream.pos < this.stream.end;
22066
+ }
22067
+ if (this.bufferLength > 0) {
22068
+ return true;
22069
+ }
22070
+ const nextByte = this.stream.getByte();
22071
+ if (nextByte < 0) {
22072
+ return false;
22073
+ }
22074
+ this.buffer = nextByte;
22075
+ this.bufferLength = 8;
22076
+ return true;
22077
+ }
22078
+ readBits(n) {
22079
+ const { stream } = this;
22080
+ let { buffer, bufferLength } = this;
22081
+ if (n === 32) {
22082
+ if (bufferLength === 0) {
22083
+ return stream.getInt32() >>> 0;
22084
+ }
22085
+ buffer = buffer << 24 | stream.getByte() << 16 | stream.getByte() << 8 | stream.getByte();
22086
+ const nextByte = stream.getByte();
22087
+ this.buffer = nextByte & (1 << bufferLength) - 1;
22088
+ return (buffer << 8 - bufferLength | (nextByte & 255) >> bufferLength) >>> 0;
22089
+ }
22090
+ if (n === 8 && bufferLength === 0) {
22091
+ return stream.getByte();
22092
+ }
22093
+ while (bufferLength < n) {
22094
+ buffer = buffer << 8 | stream.getByte();
22095
+ bufferLength += 8;
22096
+ }
22097
+ bufferLength -= n;
22098
+ this.bufferLength = bufferLength;
22099
+ this.buffer = buffer & (1 << bufferLength) - 1;
22100
+ return buffer >> bufferLength;
22101
+ }
22102
+ align() {
22103
+ this.buffer = 0;
22104
+ this.bufferLength = 0;
22105
+ }
22106
+ readFlag() {
22107
+ return this.readBits(this.context.bitsPerFlag);
22108
+ }
22109
+ readCoordinate() {
22110
+ const { bitsPerCoordinate, decode } = this.context;
22111
+ const xi = this.readBits(bitsPerCoordinate);
22112
+ const yi = this.readBits(bitsPerCoordinate);
22113
+ const scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 23283064365386963e-26;
22114
+ return [
22115
+ xi * scale * (decode[1] - decode[0]) + decode[0],
22116
+ yi * scale * (decode[3] - decode[2]) + decode[2]
22117
+ ];
22118
+ }
22119
+ readComponents() {
22120
+ const { bitsPerComponent, colorFn, colorSpace, decode, numComps } = this.context;
22121
+ const scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 23283064365386963e-26;
22122
+ const components = this.tmpCompsBuf;
22123
+ for (let i = 0, j = 4; i < numComps; i++, j += 2) {
22124
+ const ci = this.readBits(bitsPerComponent);
22125
+ components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j];
22126
+ }
22127
+ const color = this.tmpCsCompsBuf;
22128
+ colorFn?.(components, 0, color, 0);
22129
+ return colorSpace.getRgb(color, 0);
22130
+ }
22131
+ };
22132
+ var bCache = null;
22133
+ function getB(count) {
22134
+ if (bCache?.has(count)) return bCache.get(count);
22135
+ const values = Array.from({ length: count + 1 }, (_, i) => {
22136
+ const t = i / count, t_ = 1 - t;
22137
+ return new Float32Array([
22138
+ t_ ** 3,
22139
+ 3 * t * t_ ** 2,
22140
+ 3 * t ** 2 * t_,
22141
+ t ** 3
22142
+ ]);
22143
+ });
22144
+ (bCache ??= /* @__PURE__ */ new Map()).set(count, values);
22145
+ return values;
22146
+ }
22147
+ var MeshShading = class _MeshShading extends BaseShading {
22148
+ static MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;
22149
+ static MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;
22150
+ // Count of triangles per entire mesh bounds.
22151
+ static TRIANGLE_DENSITY = 20;
22152
+ constructor(shadingType, stream, context, rowVertices) {
22153
+ super();
22154
+ this.shadingType = shadingType;
22155
+ this.bbox = this.background = null;
22156
+ this.coords = [];
22157
+ this.colors = [];
22158
+ this.figures = [];
22159
+ const reader = new MeshStreamReader(stream, context);
22160
+ let patchMesh = false;
22161
+ switch (this.shadingType) {
22162
+ case ShadingType.FREE_FORM_MESH:
22163
+ this._decodeType4Shading(reader);
22164
+ break;
22165
+ case ShadingType.LATTICE_FORM_MESH:
22166
+ const verticesPerRow = rowVertices | 0;
22167
+ if (verticesPerRow < 2) {
22168
+ throw new FormatError("Invalid VerticesPerRow");
22169
+ }
22170
+ this._decodeType5Shading(reader, verticesPerRow);
22171
+ break;
22172
+ case ShadingType.COONS_PATCH_MESH:
22173
+ this._decodeType6Shading(reader);
22174
+ patchMesh = true;
22175
+ break;
22176
+ case ShadingType.TENSOR_PATCH_MESH:
22177
+ this._decodeType7Shading(reader);
22178
+ patchMesh = true;
22179
+ break;
22180
+ default:
22181
+ unreachable("Unsupported mesh type.");
22182
+ break;
22183
+ }
22184
+ if (patchMesh) {
22185
+ this._updateBounds();
22186
+ for (let i = 0, ii = this.figures.length; i < ii; i++) {
22187
+ this._buildFigureFromPatch(i);
22188
+ }
22189
+ }
22190
+ this._updateBounds();
22191
+ this._packData();
22192
+ }
22193
+ _decodeType4Shading(reader) {
22194
+ const coords = this.coords;
22195
+ const colors = this.colors;
22196
+ const operators = [];
22197
+ const ps = [];
22198
+ let verticesLeft = 0;
22199
+ while (reader.hasData) {
22200
+ const f = reader.readFlag();
22201
+ const coord = reader.readCoordinate();
22202
+ const color = reader.readComponents();
22203
+ if (verticesLeft === 0) {
22204
+ if (!(0 <= f && f <= 2)) {
22205
+ throw new FormatError("Unknown type4 flag");
22206
+ }
22207
+ switch (f) {
22208
+ case 0:
22209
+ verticesLeft = 3;
22210
+ break;
22211
+ case 1:
22212
+ ps.push(ps.at(-2), ps.at(-1));
22213
+ verticesLeft = 1;
22214
+ break;
22215
+ case 2:
22216
+ ps.push(ps.at(-3), ps.at(-1));
22217
+ verticesLeft = 1;
22218
+ break;
22219
+ }
22220
+ operators.push(f);
22221
+ }
22222
+ ps.push(coords.length);
22223
+ coords.push(coord);
22224
+ colors.push(color);
22225
+ verticesLeft--;
22226
+ reader.align();
22227
+ }
22228
+ this.figures.push({
22229
+ type: MeshFigureType.TRIANGLES,
22230
+ coords: new Int32Array(ps),
22231
+ colors: new Int32Array(ps)
22232
+ });
22233
+ }
22234
+ _decodeType5Shading(reader, verticesPerRow) {
22235
+ const coords = this.coords;
22236
+ const colors = this.colors;
22237
+ const ps = [];
22238
+ while (reader.hasData) {
22239
+ const coord = reader.readCoordinate();
22240
+ const color = reader.readComponents();
22241
+ ps.push(coords.length);
22242
+ coords.push(coord);
22243
+ colors.push(color);
22244
+ }
22245
+ this.figures.push({
22246
+ type: MeshFigureType.LATTICE,
22247
+ coords: new Int32Array(ps),
22248
+ colors: new Int32Array(ps),
22249
+ verticesPerRow
22250
+ });
22251
+ }
22252
+ _decodeType6Shading(reader) {
22253
+ const coords = this.coords;
22254
+ const colors = this.colors;
22255
+ const ps = new Int32Array(16);
22256
+ const cs = new Int32Array(4);
22257
+ while (reader.hasData) {
22258
+ const f = reader.readFlag();
22259
+ if (!(0 <= f && f <= 3)) {
22260
+ throw new FormatError("Unknown type6 flag");
22261
+ }
22262
+ const pi = coords.length;
22263
+ for (let i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) {
22264
+ coords.push(reader.readCoordinate());
22265
+ }
22266
+ const ci = colors.length;
22267
+ for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
22268
+ colors.push(reader.readComponents());
22269
+ }
22270
+ let tmp1, tmp2, tmp3, tmp4;
22271
+ switch (f) {
22272
+ // prettier-ignore
22273
+ case 0:
22274
+ ps[12] = pi + 3;
22275
+ ps[13] = pi + 4;
22276
+ ps[14] = pi + 5;
22277
+ ps[15] = pi + 6;
22278
+ ps[8] = pi + 2;
22279
+ ps[11] = pi + 7;
22280
+ ps[4] = pi + 1;
22281
+ ps[7] = pi + 8;
22282
+ ps[0] = pi;
22283
+ ps[1] = pi + 11;
22284
+ ps[2] = pi + 10;
22285
+ ps[3] = pi + 9;
22286
+ cs[2] = ci + 1;
22287
+ cs[3] = ci + 2;
22288
+ cs[0] = ci;
22289
+ cs[1] = ci + 3;
22290
+ break;
22291
+ // prettier-ignore
22292
+ case 1:
22293
+ tmp1 = ps[12];
22294
+ tmp2 = ps[13];
22295
+ tmp3 = ps[14];
22296
+ tmp4 = ps[15];
22297
+ ps[12] = tmp4;
22298
+ ps[13] = pi + 0;
22299
+ ps[14] = pi + 1;
22300
+ ps[15] = pi + 2;
22301
+ ps[8] = tmp3;
22302
+ ps[11] = pi + 3;
22303
+ ps[4] = tmp2;
22304
+ ps[7] = pi + 4;
22305
+ ps[0] = tmp1;
22306
+ ps[1] = pi + 7;
22307
+ ps[2] = pi + 6;
22308
+ ps[3] = pi + 5;
22309
+ tmp1 = cs[2];
22310
+ tmp2 = cs[3];
22311
+ cs[2] = tmp2;
22312
+ cs[3] = ci;
22313
+ cs[0] = tmp1;
22314
+ cs[1] = ci + 1;
22315
+ break;
22316
+ // prettier-ignore
22317
+ case 2:
22318
+ tmp1 = ps[15];
22319
+ tmp2 = ps[11];
22320
+ ps[12] = ps[3];
22321
+ ps[13] = pi + 0;
22322
+ ps[14] = pi + 1;
22323
+ ps[15] = pi + 2;
22324
+ ps[8] = ps[7];
22325
+ ps[11] = pi + 3;
22326
+ ps[4] = tmp2;
22327
+ ps[7] = pi + 4;
22328
+ ps[0] = tmp1;
22329
+ ps[1] = pi + 7;
22330
+ ps[2] = pi + 6;
22331
+ ps[3] = pi + 5;
22332
+ tmp1 = cs[3];
22333
+ cs[2] = cs[1];
22334
+ cs[3] = ci;
22335
+ cs[0] = tmp1;
22336
+ cs[1] = ci + 1;
22337
+ break;
22338
+ // prettier-ignore
22339
+ case 3:
22340
+ ps[12] = ps[0];
22341
+ ps[13] = pi + 0;
22342
+ ps[14] = pi + 1;
22343
+ ps[15] = pi + 2;
22344
+ ps[8] = ps[1];
22345
+ ps[11] = pi + 3;
22346
+ ps[4] = ps[2];
22347
+ ps[7] = pi + 4;
22348
+ ps[0] = ps[3];
22349
+ ps[1] = pi + 7;
22350
+ ps[2] = pi + 6;
22351
+ ps[3] = pi + 5;
22352
+ cs[2] = cs[0];
22353
+ cs[3] = ci;
22354
+ cs[0] = cs[1];
22355
+ cs[1] = ci + 1;
22356
+ break;
22357
+ }
22358
+ ps[5] = coords.length;
22359
+ coords.push([
22360
+ (-4 * coords[ps[0]][0] - coords[ps[15]][0] + 6 * (coords[ps[4]][0] + coords[ps[1]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9,
22361
+ (-4 * coords[ps[0]][1] - coords[ps[15]][1] + 6 * (coords[ps[4]][1] + coords[ps[1]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9
22362
+ ]);
22363
+ ps[6] = coords.length;
22364
+ coords.push([
22365
+ (-4 * coords[ps[3]][0] - coords[ps[12]][0] + 6 * (coords[ps[2]][0] + coords[ps[7]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9,
22366
+ (-4 * coords[ps[3]][1] - coords[ps[12]][1] + 6 * (coords[ps[2]][1] + coords[ps[7]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9
22367
+ ]);
22368
+ ps[9] = coords.length;
22369
+ coords.push([
22370
+ (-4 * coords[ps[12]][0] - coords[ps[3]][0] + 6 * (coords[ps[8]][0] + coords[ps[13]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9,
22371
+ (-4 * coords[ps[12]][1] - coords[ps[3]][1] + 6 * (coords[ps[8]][1] + coords[ps[13]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9
22372
+ ]);
22373
+ ps[10] = coords.length;
22374
+ coords.push([
22375
+ (-4 * coords[ps[15]][0] - coords[ps[0]][0] + 6 * (coords[ps[11]][0] + coords[ps[14]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9,
22376
+ (-4 * coords[ps[15]][1] - coords[ps[0]][1] + 6 * (coords[ps[11]][1] + coords[ps[14]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9
22377
+ ]);
22378
+ this.figures.push({
22379
+ type: MeshFigureType.PATCH,
22380
+ coords: new Int32Array(ps),
22381
+ // making copies of ps and cs
22382
+ colors: new Int32Array(cs)
22383
+ });
22384
+ }
22385
+ }
22386
+ _decodeType7Shading(reader) {
22387
+ const coords = this.coords;
22388
+ const colors = this.colors;
22389
+ const ps = new Int32Array(16);
22390
+ const cs = new Int32Array(4);
22391
+ while (reader.hasData) {
22392
+ const f = reader.readFlag();
22393
+ if (!(0 <= f && f <= 3)) {
22394
+ throw new FormatError("Unknown type7 flag");
22395
+ }
22396
+ const pi = coords.length;
22397
+ for (let i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) {
22398
+ coords.push(reader.readCoordinate());
22399
+ }
22400
+ const ci = colors.length;
22401
+ for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
22402
+ colors.push(reader.readComponents());
22403
+ }
22404
+ let tmp1, tmp2, tmp3, tmp4;
22405
+ switch (f) {
22406
+ // prettier-ignore
22407
+ case 0:
22408
+ ps[12] = pi + 3;
22409
+ ps[13] = pi + 4;
22410
+ ps[14] = pi + 5;
22411
+ ps[15] = pi + 6;
22412
+ ps[8] = pi + 2;
22413
+ ps[9] = pi + 13;
22414
+ ps[10] = pi + 14;
22415
+ ps[11] = pi + 7;
22416
+ ps[4] = pi + 1;
22417
+ ps[5] = pi + 12;
22418
+ ps[6] = pi + 15;
22419
+ ps[7] = pi + 8;
22420
+ ps[0] = pi;
22421
+ ps[1] = pi + 11;
22422
+ ps[2] = pi + 10;
22423
+ ps[3] = pi + 9;
22424
+ cs[2] = ci + 1;
22425
+ cs[3] = ci + 2;
22426
+ cs[0] = ci;
22427
+ cs[1] = ci + 3;
22428
+ break;
22429
+ // prettier-ignore
22430
+ case 1:
22431
+ tmp1 = ps[12];
22432
+ tmp2 = ps[13];
22433
+ tmp3 = ps[14];
22434
+ tmp4 = ps[15];
22435
+ ps[12] = tmp4;
22436
+ ps[13] = pi + 0;
22437
+ ps[14] = pi + 1;
22438
+ ps[15] = pi + 2;
22439
+ ps[8] = tmp3;
22440
+ ps[9] = pi + 9;
22441
+ ps[10] = pi + 10;
22442
+ ps[11] = pi + 3;
22443
+ ps[4] = tmp2;
22444
+ ps[5] = pi + 8;
22445
+ ps[6] = pi + 11;
22446
+ ps[7] = pi + 4;
22447
+ ps[0] = tmp1;
22448
+ ps[1] = pi + 7;
22449
+ ps[2] = pi + 6;
22450
+ ps[3] = pi + 5;
22451
+ tmp1 = cs[2];
22452
+ tmp2 = cs[3];
22453
+ cs[2] = tmp2;
22454
+ cs[3] = ci;
22455
+ cs[0] = tmp1;
22456
+ cs[1] = ci + 1;
22457
+ break;
22458
+ // prettier-ignore
22459
+ case 2:
22460
+ tmp1 = ps[15];
22461
+ tmp2 = ps[11];
22462
+ ps[12] = ps[3];
22463
+ ps[13] = pi + 0;
22464
+ ps[14] = pi + 1;
22465
+ ps[15] = pi + 2;
22466
+ ps[8] = ps[7];
22467
+ ps[9] = pi + 9;
22468
+ ps[10] = pi + 10;
22469
+ ps[11] = pi + 3;
22470
+ ps[4] = tmp2;
22471
+ ps[5] = pi + 8;
22472
+ ps[6] = pi + 11;
22473
+ ps[7] = pi + 4;
22474
+ ps[0] = tmp1;
22475
+ ps[1] = pi + 7;
22476
+ ps[2] = pi + 6;
22477
+ ps[3] = pi + 5;
22478
+ tmp1 = cs[3];
22479
+ cs[2] = cs[1];
22480
+ cs[3] = ci;
22481
+ cs[0] = tmp1;
22482
+ cs[1] = ci + 1;
22483
+ break;
22484
+ // prettier-ignore
22485
+ case 3:
22486
+ ps[12] = ps[0];
22487
+ ps[13] = pi + 0;
22488
+ ps[14] = pi + 1;
22489
+ ps[15] = pi + 2;
22490
+ ps[8] = ps[1];
22491
+ ps[9] = pi + 9;
22492
+ ps[10] = pi + 10;
22493
+ ps[11] = pi + 3;
22494
+ ps[4] = ps[2];
22495
+ ps[5] = pi + 8;
22496
+ ps[6] = pi + 11;
22497
+ ps[7] = pi + 4;
22498
+ ps[0] = ps[3];
22499
+ ps[1] = pi + 7;
22500
+ ps[2] = pi + 6;
22501
+ ps[3] = pi + 5;
22502
+ cs[2] = cs[0];
22503
+ cs[3] = ci;
22504
+ cs[0] = cs[1];
22505
+ cs[1] = ci + 1;
22506
+ break;
22507
+ }
22508
+ this.figures.push({
22509
+ type: MeshFigureType.PATCH,
22510
+ coords: new Int32Array(ps),
22511
+ // making copies of ps and cs
22512
+ colors: new Int32Array(cs)
22513
+ });
22514
+ }
22515
+ }
22516
+ _buildFigureFromPatch(index) {
22517
+ const figure = this.figures[index];
22518
+ assert(
22519
+ figure.type === MeshFigureType.PATCH,
22520
+ "Unexpected patch mesh figure"
22521
+ );
22522
+ const coords = this.coords, colors = this.colors;
22523
+ const pi = figure.coords;
22524
+ const ci = figure.colors;
22525
+ const figureMinX = Math.min(
22526
+ coords[pi[0]][0],
22527
+ coords[pi[3]][0],
22528
+ coords[pi[12]][0],
22529
+ coords[pi[15]][0]
22530
+ );
22531
+ const figureMinY = Math.min(
22532
+ coords[pi[0]][1],
22533
+ coords[pi[3]][1],
22534
+ coords[pi[12]][1],
22535
+ coords[pi[15]][1]
22536
+ );
22537
+ const figureMaxX = Math.max(
22538
+ coords[pi[0]][0],
22539
+ coords[pi[3]][0],
22540
+ coords[pi[12]][0],
22541
+ coords[pi[15]][0]
22542
+ );
22543
+ const figureMaxY = Math.max(
22544
+ coords[pi[0]][1],
22545
+ coords[pi[3]][1],
22546
+ coords[pi[12]][1],
22547
+ coords[pi[15]][1]
22548
+ );
22549
+ let splitXBy = Math.ceil(
22550
+ (figureMaxX - figureMinX) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[2] - this.bounds[0])
22551
+ );
22552
+ splitXBy = MathClamp(
22553
+ splitXBy,
22554
+ _MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
22555
+ _MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT
22556
+ );
22557
+ let splitYBy = Math.ceil(
22558
+ (figureMaxY - figureMinY) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[3] - this.bounds[1])
22559
+ );
22560
+ splitYBy = MathClamp(
22561
+ splitYBy,
22562
+ _MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
22563
+ _MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT
22564
+ );
22565
+ const verticesPerRow = splitXBy + 1;
22566
+ const figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
22567
+ const figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
22568
+ let k = 0;
22569
+ const cl = new Uint8Array(3), cr = new Uint8Array(3);
22570
+ const c0 = colors[ci[0]], c1 = colors[ci[1]], c2 = colors[ci[2]], c3 = colors[ci[3]];
22571
+ const bRow = getB(splitYBy), bCol = getB(splitXBy);
22572
+ for (let row = 0; row <= splitYBy; row++) {
22573
+ cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0;
22574
+ cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0;
22575
+ cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0;
22576
+ cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0;
22577
+ cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0;
22578
+ cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0;
22579
+ for (let col = 0; col <= splitXBy; col++, k++) {
22580
+ if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) {
22581
+ continue;
22582
+ }
22583
+ let x = 0, y = 0;
22584
+ let q = 0;
22585
+ for (let i = 0; i <= 3; i++) {
22586
+ for (let j = 0; j <= 3; j++, q++) {
22587
+ const m = bRow[row][i] * bCol[col][j];
22588
+ x += coords[pi[q]][0] * m;
22589
+ y += coords[pi[q]][1] * m;
22590
+ }
22591
+ }
22592
+ figureCoords[k] = coords.length;
22593
+ coords.push([x, y]);
22594
+ figureColors[k] = colors.length;
22595
+ const newColor = new Uint8Array(3);
22596
+ newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0;
22597
+ newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0;
22598
+ newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0;
22599
+ colors.push(newColor);
22600
+ }
22601
+ }
22602
+ figureCoords[0] = pi[0];
22603
+ figureColors[0] = ci[0];
22604
+ figureCoords[splitXBy] = pi[3];
22605
+ figureColors[splitXBy] = ci[1];
22606
+ figureCoords[verticesPerRow * splitYBy] = pi[12];
22607
+ figureColors[verticesPerRow * splitYBy] = ci[2];
22608
+ figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15];
22609
+ figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
22610
+ this.figures[index] = {
22611
+ type: MeshFigureType.LATTICE,
22612
+ coords: figureCoords,
22613
+ colors: figureColors,
22614
+ verticesPerRow
22615
+ };
22616
+ }
22617
+ _updateBounds() {
22618
+ meshUpdateBounds(this);
22619
+ }
22620
+ _packData() {
22621
+ meshPackData(this);
22622
+ }
22623
+ getIR() {
22624
+ const { posData, colData, vertexCount } = buildMeshVertexData(
22625
+ this.coords,
22626
+ this.colors,
22627
+ this.figures
22628
+ );
22629
+ return [
22630
+ "Mesh",
22631
+ this.shadingType,
22632
+ posData,
22633
+ colData,
22634
+ vertexCount,
22635
+ this.bounds,
22636
+ this.bbox,
22637
+ this.background
22638
+ ];
22639
+ }
22640
+ };
19324
22641
  export {
19325
22642
  CFFCompiler,
19326
22643
  CFFParser,
19327
22644
  CFFStrings,
19328
22645
  CMap,
22646
+ CalGrayCS,
22647
+ CalRGBCS,
19329
22648
  CipherTransformFactory,
22649
+ DeviceCmykCS,
19330
22650
  Dict,
19331
22651
  DrawOPS,
19332
22652
  FlateStream,
22653
+ LabCS,
19333
22654
  MacStandardGlyphOrdering,
22655
+ MeshShading,
19334
22656
  Name,
19335
22657
  PDF17,
19336
22658
  PDF20,
@@ -19343,6 +22665,7 @@ export {
19343
22665
  Type2Compiled,
19344
22666
  WinAnsiEncoding,
19345
22667
  ZapfDingbatsEncoding,
22668
+ buildPostScriptJsFunction,
19346
22669
  encodeToXmlString,
19347
22670
  getDingbatsGlyphsUnicode,
19348
22671
  getEncoding,