@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.
- package/dist/image-ast/index.browser.js +3543 -706
- package/dist/image-ast/index.js +3543 -706
- package/dist/pdf-ast/ast.d.ts +7 -0
- package/dist/pdf-ast/content/evaluator.d.ts +1 -0
- package/dist/pdf-ast/index.js +3587 -718
- package/dist/pdf-ast/render/raster.d.ts +1 -0
- package/dist/pdf-ast/vendor/pdfjs-fonts.d.mts +36 -0
- package/dist/pdf-ast/vendor/pdfjs-fonts.mjs +3323 -0
- package/dist/safe-bash/command-chunks/{chunk-M2XU2YCK.js → chunk-4ZHDCMQX.js} +2 -2
- package/dist/safe-bash/command-chunks/{chunk-NBENXODJ.js → chunk-HH5QPKIN.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-C4AAJTXF.js → chunk-PM63UJE6.js} +3546 -706
- package/dist/safe-bash/core.browser.js +101 -45
- package/dist/safe-bash/core.d.ts +1 -1
- package/dist/safe-bash/plugins/composition.d.ts +2 -0
- package/dist/safe-bash/plugins/composition.js +2 -1
- package/dist/safe-bash/shell/runtime.js +17 -9
- package/dist/safe-bash/shell/sync-posix-regex.d.ts +3 -0
- package/dist/safe-bash/shell/sync-posix-regex.js +48 -0
- package/dist/safe-bash-command-ffmpeg/index.js +11032 -9579
- package/dist/safe-bash-command-gh/index.d.ts +1 -0
- package/dist/safe-bash-command-gh/index.js +43 -13
- package/dist/safe-bash-command-gh/types.d.ts +1 -0
- package/dist/safe-bash-command-git/git_rust.wasm +0 -0
- package/dist/safe-bash-command-git/index.js +22 -15
- package/dist/safe-bash-command-git/wasm.generated.js +1 -1
- package/dist/safe-bash-command-gpg/index.js +28 -7
- package/dist/safe-bash-command-imagemagick/index.js +2 -2
- package/dist/safe-bash-command-openssl/index.js +24 -6
- package/dist/safe-bash-command-pandoc/command.js +3 -3
- package/dist/safe-bash-command-pandoc/index.js +3 -3
- package/dist/safe-bash-command-pdfimages/index.js +3542 -660
- package/dist/safe-bash-command-pdfinfo/index.js +3584 -718
- package/dist/safe-bash-command-pdftk/index.js +3542 -660
- package/dist/safe-bash-command-pdftoppm/index.js +3589 -787
- package/dist/safe-bash-command-pdftotext/index.js +3542 -660
- package/dist/safe-bash-command-qpdf/index.js +3542 -660
- package/dist/safe-bash-command-sips/index.js +2 -2
- package/dist/safe-bash-command-soffice/index.js +1 -1
- package/dist/safe-bash-command-ssconvert/index.js +3553 -716
- package/dist/safe-bash-command-ssh/index.js +124 -23
- package/dist/safe-bash-command-wkhtmltopdf/index.js +3581 -660
- package/dist/safe-bash-mcp/index.d.ts +8 -2
- package/dist/safe-bash-mcp/index.js +13 -6
- package/package.json +7 -7
- package/third-party/pdf-ast/THIRD_PARTY_NOTICES.md +84 -1
package/dist/image-ast/index.js
CHANGED
|
@@ -11586,6 +11586,11 @@ var FONT_IDENTITY_MATRIX = [1e-3, 0, 0, 1e-3, 0, 0];
|
|
|
11586
11586
|
var LINE_FACTOR = 1.35;
|
|
11587
11587
|
var LINE_DESCENT_FACTOR = 0.35;
|
|
11588
11588
|
var BASELINE_FACTOR = LINE_DESCENT_FACTOR / LINE_FACTOR;
|
|
11589
|
+
var MeshFigureType = {
|
|
11590
|
+
TRIANGLES: 1,
|
|
11591
|
+
LATTICE: 2,
|
|
11592
|
+
PATCH: 3
|
|
11593
|
+
};
|
|
11589
11594
|
var VerbosityLevel = {
|
|
11590
11595
|
ERRORS: 0,
|
|
11591
11596
|
WARNINGS: 1,
|
|
@@ -30510,6 +30515,3308 @@ var getFontBasicMetrics = getLookupTableFactory(function(t) {
|
|
|
30510
30515
|
xHeight: Math.NaN
|
|
30511
30516
|
};
|
|
30512
30517
|
});
|
|
30518
|
+
function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
|
|
30519
|
+
const COMPONENTS = 3;
|
|
30520
|
+
alpha01 = alpha01 !== 1 ? 0 : alpha01;
|
|
30521
|
+
const xRatio = w1 / w2;
|
|
30522
|
+
const yRatio = h1 / h2;
|
|
30523
|
+
let newIndex = 0, oldIndex;
|
|
30524
|
+
const xScaled = new Uint16Array(w2);
|
|
30525
|
+
const w1Scanline = w1 * COMPONENTS;
|
|
30526
|
+
for (let i = 0; i < w2; i++) {
|
|
30527
|
+
xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
|
|
30528
|
+
}
|
|
30529
|
+
for (let i = 0; i < h2; i++) {
|
|
30530
|
+
const py = Math.floor(i * yRatio) * w1Scanline;
|
|
30531
|
+
for (let j = 0; j < w2; j++) {
|
|
30532
|
+
oldIndex = py + xScaled[j];
|
|
30533
|
+
dest[newIndex++] = src[oldIndex++];
|
|
30534
|
+
dest[newIndex++] = src[oldIndex++];
|
|
30535
|
+
dest[newIndex++] = src[oldIndex++];
|
|
30536
|
+
newIndex += alpha01;
|
|
30537
|
+
}
|
|
30538
|
+
}
|
|
30539
|
+
}
|
|
30540
|
+
function isDefaultDecodeHelper(decode, expectedLen) {
|
|
30541
|
+
if (!Array.isArray(decode)) {
|
|
30542
|
+
return true;
|
|
30543
|
+
}
|
|
30544
|
+
const decodeLen = decode.length;
|
|
30545
|
+
if (decodeLen < expectedLen) {
|
|
30546
|
+
warn2("Decode map length is too short.");
|
|
30547
|
+
return true;
|
|
30548
|
+
}
|
|
30549
|
+
if (decodeLen > expectedLen) {
|
|
30550
|
+
info("Truncating too long decode map.");
|
|
30551
|
+
decode.length = expectedLen;
|
|
30552
|
+
}
|
|
30553
|
+
return false;
|
|
30554
|
+
}
|
|
30555
|
+
var ColorSpace = class _ColorSpace {
|
|
30556
|
+
static #rgbBuf = new Uint8ClampedArray(3);
|
|
30557
|
+
constructor(name, numComps) {
|
|
30558
|
+
if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _ColorSpace) {
|
|
30559
|
+
unreachable2("Cannot initialize ColorSpace.");
|
|
30560
|
+
}
|
|
30561
|
+
this.name = name;
|
|
30562
|
+
this.numComps = numComps;
|
|
30563
|
+
}
|
|
30564
|
+
/**
|
|
30565
|
+
* Converts the color value to the RGB color. The color components are
|
|
30566
|
+
* located in the src array starting from the srcOffset. Returns the array
|
|
30567
|
+
* of the rgb components, each value ranging from [0,255].
|
|
30568
|
+
*/
|
|
30569
|
+
getRgb(src, srcOffset, output = new Uint8ClampedArray(3)) {
|
|
30570
|
+
this.getRgbItem(src, srcOffset, output, 0);
|
|
30571
|
+
return output;
|
|
30572
|
+
}
|
|
30573
|
+
getRgbHex(src, srcOffset) {
|
|
30574
|
+
const buffer = this.getRgb(src, srcOffset, _ColorSpace.#rgbBuf);
|
|
30575
|
+
return Util.makeHexColor(buffer[0], buffer[1], buffer[2]);
|
|
30576
|
+
}
|
|
30577
|
+
/**
|
|
30578
|
+
* Converts the color value to the RGB color, similar to the getRgb method.
|
|
30579
|
+
* The result placed into the dest array starting from the destOffset.
|
|
30580
|
+
*/
|
|
30581
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
30582
|
+
unreachable2("Should not call ColorSpace.getRgbItem");
|
|
30583
|
+
}
|
|
30584
|
+
/**
|
|
30585
|
+
* Converts the specified number of the color values to the RGB colors.
|
|
30586
|
+
* The colors are located in the src array starting from the srcOffset.
|
|
30587
|
+
* The result is placed into the dest array starting from the destOffset.
|
|
30588
|
+
* The src array items shall be in [0,2^bits) range, the dest array items
|
|
30589
|
+
* will be in [0,255] range. alpha01 indicates how many alpha components
|
|
30590
|
+
* there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
|
|
30591
|
+
* array).
|
|
30592
|
+
*/
|
|
30593
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
30594
|
+
unreachable2("Should not call ColorSpace.getRgbBuffer");
|
|
30595
|
+
}
|
|
30596
|
+
/**
|
|
30597
|
+
* Converts `count` unscaled colors to RGB, starting at `destOffset`.
|
|
30598
|
+
* Components use the native color-space ranges expected by `getRgbItem`,
|
|
30599
|
+
* and each output has a `3 + alpha01` byte stride.
|
|
30600
|
+
* Subclasses may override this to batch expensive conversions.
|
|
30601
|
+
*/
|
|
30602
|
+
getRgbItems(src, count, dest, destOffset, alpha01) {
|
|
30603
|
+
const { numComps } = this;
|
|
30604
|
+
for (let i = 0, srcOffset = 0; i < count; i++, srcOffset += numComps) {
|
|
30605
|
+
this.getRgbItem(src, srcOffset, dest, destOffset);
|
|
30606
|
+
destOffset += 3 + alpha01;
|
|
30607
|
+
}
|
|
30608
|
+
}
|
|
30609
|
+
/**
|
|
30610
|
+
* Returns true if source data will be equal the result/output data.
|
|
30611
|
+
*/
|
|
30612
|
+
isPassthrough(bits) {
|
|
30613
|
+
return false;
|
|
30614
|
+
}
|
|
30615
|
+
/**
|
|
30616
|
+
* Refer to the static `ColorSpace.isDefaultDecode` method below.
|
|
30617
|
+
*/
|
|
30618
|
+
isDefaultDecode(decode, bpc) {
|
|
30619
|
+
return _ColorSpace.isDefaultDecode(decode, this.numComps);
|
|
30620
|
+
}
|
|
30621
|
+
/**
|
|
30622
|
+
* Fills in the RGB colors in the destination buffer. alpha01 indicates
|
|
30623
|
+
* how many alpha components there are in the dest array; it will be either
|
|
30624
|
+
* 0 (RGB array) or 1 (RGBA array).
|
|
30625
|
+
*/
|
|
30626
|
+
fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {
|
|
30627
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
30628
|
+
assert2(
|
|
30629
|
+
dest instanceof Uint8ClampedArray,
|
|
30630
|
+
'ColorSpace.fillRgb: Unsupported "dest" type.'
|
|
30631
|
+
);
|
|
30632
|
+
}
|
|
30633
|
+
const count = originalWidth * originalHeight;
|
|
30634
|
+
let rgbBuf = null;
|
|
30635
|
+
const numComponentColors = 1 << bpc;
|
|
30636
|
+
const needsResizing = originalHeight !== height || originalWidth !== width;
|
|
30637
|
+
if (this.isPassthrough(bpc)) {
|
|
30638
|
+
rgbBuf = comps;
|
|
30639
|
+
} else if (this.numComps === 1 && count > numComponentColors && this.name !== "DeviceGray" && this.name !== "DeviceRGB") {
|
|
30640
|
+
const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);
|
|
30641
|
+
for (let i = 0; i < numComponentColors; i++) {
|
|
30642
|
+
allColors[i] = i;
|
|
30643
|
+
}
|
|
30644
|
+
const colorMap = new Uint8ClampedArray(numComponentColors * 3);
|
|
30645
|
+
this.getRgbBuffer(
|
|
30646
|
+
allColors,
|
|
30647
|
+
0,
|
|
30648
|
+
numComponentColors,
|
|
30649
|
+
colorMap,
|
|
30650
|
+
0,
|
|
30651
|
+
bpc,
|
|
30652
|
+
/* alpha01 = */
|
|
30653
|
+
0
|
|
30654
|
+
);
|
|
30655
|
+
if (!needsResizing) {
|
|
30656
|
+
let destPos = 0;
|
|
30657
|
+
for (let i = 0; i < count; ++i) {
|
|
30658
|
+
const key = comps[i] * 3;
|
|
30659
|
+
dest[destPos++] = colorMap[key];
|
|
30660
|
+
dest[destPos++] = colorMap[key + 1];
|
|
30661
|
+
dest[destPos++] = colorMap[key + 2];
|
|
30662
|
+
destPos += alpha01;
|
|
30663
|
+
}
|
|
30664
|
+
} else {
|
|
30665
|
+
rgbBuf = new Uint8Array(count * 3);
|
|
30666
|
+
let rgbPos = 0;
|
|
30667
|
+
for (let i = 0; i < count; ++i) {
|
|
30668
|
+
const key = comps[i] * 3;
|
|
30669
|
+
rgbBuf[rgbPos++] = colorMap[key];
|
|
30670
|
+
rgbBuf[rgbPos++] = colorMap[key + 1];
|
|
30671
|
+
rgbBuf[rgbPos++] = colorMap[key + 2];
|
|
30672
|
+
}
|
|
30673
|
+
}
|
|
30674
|
+
} else if (!needsResizing) {
|
|
30675
|
+
this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);
|
|
30676
|
+
} else {
|
|
30677
|
+
rgbBuf = new Uint8ClampedArray(count * 3);
|
|
30678
|
+
this.getRgbBuffer(
|
|
30679
|
+
comps,
|
|
30680
|
+
0,
|
|
30681
|
+
count,
|
|
30682
|
+
rgbBuf,
|
|
30683
|
+
0,
|
|
30684
|
+
bpc,
|
|
30685
|
+
/* alpha01 = */
|
|
30686
|
+
0
|
|
30687
|
+
);
|
|
30688
|
+
}
|
|
30689
|
+
if (rgbBuf) {
|
|
30690
|
+
if (needsResizing) {
|
|
30691
|
+
resizeRgbImage(
|
|
30692
|
+
rgbBuf,
|
|
30693
|
+
dest,
|
|
30694
|
+
originalWidth,
|
|
30695
|
+
originalHeight,
|
|
30696
|
+
width,
|
|
30697
|
+
height,
|
|
30698
|
+
alpha01
|
|
30699
|
+
);
|
|
30700
|
+
} else {
|
|
30701
|
+
let destPos = 0, rgbPos = 0;
|
|
30702
|
+
for (let i = 0, ii = width * actualHeight; i < ii; i++) {
|
|
30703
|
+
dest[destPos++] = rgbBuf[rgbPos++];
|
|
30704
|
+
dest[destPos++] = rgbBuf[rgbPos++];
|
|
30705
|
+
dest[destPos++] = rgbBuf[rgbPos++];
|
|
30706
|
+
destPos += alpha01;
|
|
30707
|
+
}
|
|
30708
|
+
}
|
|
30709
|
+
}
|
|
30710
|
+
}
|
|
30711
|
+
/**
|
|
30712
|
+
* True if the colorspace has components in the default range of [0, 1].
|
|
30713
|
+
* This should be true for all colorspaces except for lab color spaces
|
|
30714
|
+
* which are [0,100], [-128, 127], [-128, 127].
|
|
30715
|
+
*/
|
|
30716
|
+
get usesZeroToOneRange() {
|
|
30717
|
+
return shadow2(this, "usesZeroToOneRange", true);
|
|
30718
|
+
}
|
|
30719
|
+
/**
|
|
30720
|
+
* Checks if a decode map matches the default decode map for a color space.
|
|
30721
|
+
* This handles the general decode maps where there are two values per
|
|
30722
|
+
* component, e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
|
|
30723
|
+
* This does not handle Lab, Indexed, or Pattern decode maps since they are
|
|
30724
|
+
* slightly different.
|
|
30725
|
+
* @param {Array} decode - Decode map (usually from an image).
|
|
30726
|
+
* @param {number} numComps - Number of components the color space has.
|
|
30727
|
+
*/
|
|
30728
|
+
static isDefaultDecode(decode, numComps) {
|
|
30729
|
+
if (isDefaultDecodeHelper(decode, numComps * 2)) {
|
|
30730
|
+
return true;
|
|
30731
|
+
}
|
|
30732
|
+
for (let i = 0, ii = decode.length; i < ii; i += 2) {
|
|
30733
|
+
if (decode[i] !== 0 || decode[i + 1] !== 1) {
|
|
30734
|
+
return false;
|
|
30735
|
+
}
|
|
30736
|
+
}
|
|
30737
|
+
return true;
|
|
30738
|
+
}
|
|
30739
|
+
};
|
|
30740
|
+
var DeviceCmykCS = class extends ColorSpace {
|
|
30741
|
+
constructor() {
|
|
30742
|
+
super("DeviceCMYK", 4);
|
|
30743
|
+
}
|
|
30744
|
+
// The coefficients below was found using numerical analysis: the method of
|
|
30745
|
+
// steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
|
|
30746
|
+
// where color_value is the tabular value from the table of sampled RGB colors
|
|
30747
|
+
// from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
|
|
30748
|
+
// CMYK color conversion using the estimation below:
|
|
30749
|
+
// f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
|
|
30750
|
+
#toRgb(src, srcOffset, srcScale, dest, destOffset) {
|
|
30751
|
+
const c = src[srcOffset] * srcScale;
|
|
30752
|
+
const m = src[srcOffset + 1] * srcScale;
|
|
30753
|
+
const y = src[srcOffset + 2] * srcScale;
|
|
30754
|
+
const k = src[srcOffset + 3] * srcScale;
|
|
30755
|
+
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);
|
|
30756
|
+
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);
|
|
30757
|
+
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);
|
|
30758
|
+
}
|
|
30759
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
30760
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
30761
|
+
assert2(
|
|
30762
|
+
dest instanceof Uint8ClampedArray,
|
|
30763
|
+
'DeviceCmykCS.getRgbItem: Unsupported "dest" type.'
|
|
30764
|
+
);
|
|
30765
|
+
}
|
|
30766
|
+
this.#toRgb(src, srcOffset, 1, dest, destOffset);
|
|
30767
|
+
}
|
|
30768
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
30769
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
30770
|
+
assert2(
|
|
30771
|
+
dest instanceof Uint8ClampedArray,
|
|
30772
|
+
'DeviceCmykCS.getRgbBuffer: Unsupported "dest" type.'
|
|
30773
|
+
);
|
|
30774
|
+
}
|
|
30775
|
+
const scale = 1 / ((1 << bits) - 1);
|
|
30776
|
+
for (let i = 0; i < count; i++) {
|
|
30777
|
+
this.#toRgb(src, srcOffset, scale, dest, destOffset);
|
|
30778
|
+
srcOffset += 4;
|
|
30779
|
+
destOffset += 3 + alpha01;
|
|
30780
|
+
}
|
|
30781
|
+
}
|
|
30782
|
+
};
|
|
30783
|
+
var CalGrayCS = class extends ColorSpace {
|
|
30784
|
+
constructor(whitePoint, blackPoint, gamma) {
|
|
30785
|
+
super("CalGray", 1);
|
|
30786
|
+
if (!whitePoint) {
|
|
30787
|
+
throw new FormatError(
|
|
30788
|
+
"WhitePoint missing - required for color space CalGray"
|
|
30789
|
+
);
|
|
30790
|
+
}
|
|
30791
|
+
[this.XW, this.YW, this.ZW] = whitePoint;
|
|
30792
|
+
[this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
|
|
30793
|
+
this.G = gamma || 1;
|
|
30794
|
+
if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
|
|
30795
|
+
throw new FormatError(
|
|
30796
|
+
`Invalid WhitePoint components for ${this.name}, no fallback available`
|
|
30797
|
+
);
|
|
30798
|
+
}
|
|
30799
|
+
if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
|
|
30800
|
+
info(`Invalid BlackPoint for ${this.name}, falling back to default.`);
|
|
30801
|
+
this.XB = this.YB = this.ZB = 0;
|
|
30802
|
+
}
|
|
30803
|
+
if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
|
|
30804
|
+
warn2(
|
|
30805
|
+
`${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ZB: ${this.ZB}, only default values are supported.`
|
|
30806
|
+
);
|
|
30807
|
+
}
|
|
30808
|
+
if (this.G < 1) {
|
|
30809
|
+
info(
|
|
30810
|
+
`Invalid Gamma: ${this.G} for ${this.name}, falling back to default.`
|
|
30811
|
+
);
|
|
30812
|
+
this.G = 1;
|
|
30813
|
+
}
|
|
30814
|
+
}
|
|
30815
|
+
#toRgb(src, srcOffset, dest, destOffset, scale) {
|
|
30816
|
+
const A = src[srcOffset] * scale;
|
|
30817
|
+
const AG = A ** this.G;
|
|
30818
|
+
const L = this.YW * AG;
|
|
30819
|
+
const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0);
|
|
30820
|
+
dest[destOffset] = val;
|
|
30821
|
+
dest[destOffset + 1] = val;
|
|
30822
|
+
dest[destOffset + 2] = val;
|
|
30823
|
+
}
|
|
30824
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
30825
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
30826
|
+
assert2(
|
|
30827
|
+
dest instanceof Uint8ClampedArray,
|
|
30828
|
+
'CalGrayCS.getRgbItem: Unsupported "dest" type.'
|
|
30829
|
+
);
|
|
30830
|
+
}
|
|
30831
|
+
this.#toRgb(src, srcOffset, dest, destOffset, 1);
|
|
30832
|
+
}
|
|
30833
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
30834
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
30835
|
+
assert2(
|
|
30836
|
+
dest instanceof Uint8ClampedArray,
|
|
30837
|
+
'CalGrayCS.getRgbBuffer: Unsupported "dest" type.'
|
|
30838
|
+
);
|
|
30839
|
+
}
|
|
30840
|
+
const scale = 1 / ((1 << bits) - 1);
|
|
30841
|
+
for (let i = 0; i < count; ++i) {
|
|
30842
|
+
this.#toRgb(src, srcOffset, dest, destOffset, scale);
|
|
30843
|
+
srcOffset += 1;
|
|
30844
|
+
destOffset += 3 + alpha01;
|
|
30845
|
+
}
|
|
30846
|
+
}
|
|
30847
|
+
};
|
|
30848
|
+
var CalRGBCS = class _CalRGBCS extends ColorSpace {
|
|
30849
|
+
// See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these
|
|
30850
|
+
// matrices.
|
|
30851
|
+
// prettier-ignore
|
|
30852
|
+
static #BRADFORD_SCALE_MATRIX = new Float32Array([
|
|
30853
|
+
0.8951,
|
|
30854
|
+
0.2664,
|
|
30855
|
+
-0.1614,
|
|
30856
|
+
-0.7502,
|
|
30857
|
+
1.7135,
|
|
30858
|
+
0.0367,
|
|
30859
|
+
0.0389,
|
|
30860
|
+
-0.0685,
|
|
30861
|
+
1.0296
|
|
30862
|
+
]);
|
|
30863
|
+
// prettier-ignore
|
|
30864
|
+
static #BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([
|
|
30865
|
+
0.9869929,
|
|
30866
|
+
-0.1470543,
|
|
30867
|
+
0.1599627,
|
|
30868
|
+
0.4323053,
|
|
30869
|
+
0.5183603,
|
|
30870
|
+
0.0492912,
|
|
30871
|
+
-85287e-7,
|
|
30872
|
+
0.0400428,
|
|
30873
|
+
0.9684867
|
|
30874
|
+
]);
|
|
30875
|
+
// See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html.
|
|
30876
|
+
// prettier-ignore
|
|
30877
|
+
static #SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([
|
|
30878
|
+
3.2404542,
|
|
30879
|
+
-1.5371385,
|
|
30880
|
+
-0.4985314,
|
|
30881
|
+
-0.969266,
|
|
30882
|
+
1.8760108,
|
|
30883
|
+
0.041556,
|
|
30884
|
+
0.0556434,
|
|
30885
|
+
-0.2040259,
|
|
30886
|
+
1.0572252
|
|
30887
|
+
]);
|
|
30888
|
+
static #FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);
|
|
30889
|
+
static #tempNormalizeMatrix = new Float32Array(3);
|
|
30890
|
+
static #tempConvertMatrix1 = new Float32Array(3);
|
|
30891
|
+
static #tempConvertMatrix2 = new Float32Array(3);
|
|
30892
|
+
static #DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8;
|
|
30893
|
+
constructor(whitePoint, blackPoint, gamma, matrix) {
|
|
30894
|
+
super("CalRGB", 3);
|
|
30895
|
+
if (!whitePoint) {
|
|
30896
|
+
throw new FormatError(
|
|
30897
|
+
"WhitePoint missing - required for color space CalRGB"
|
|
30898
|
+
);
|
|
30899
|
+
}
|
|
30900
|
+
const [XW, YW, ZW] = this.whitePoint = whitePoint;
|
|
30901
|
+
const [XB, YB, ZB] = this.blackPoint = blackPoint || new Float32Array(3);
|
|
30902
|
+
[this.GR, this.GG, this.GB] = gamma || new Float32Array([1, 1, 1]);
|
|
30903
|
+
[
|
|
30904
|
+
this.MXA,
|
|
30905
|
+
this.MYA,
|
|
30906
|
+
this.MZA,
|
|
30907
|
+
this.MXB,
|
|
30908
|
+
this.MYB,
|
|
30909
|
+
this.MZB,
|
|
30910
|
+
this.MXC,
|
|
30911
|
+
this.MYC,
|
|
30912
|
+
this.MZC
|
|
30913
|
+
] = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
|
|
30914
|
+
if (XW < 0 || ZW < 0 || YW !== 1) {
|
|
30915
|
+
throw new FormatError(
|
|
30916
|
+
`Invalid WhitePoint components for ${this.name}, no fallback available`
|
|
30917
|
+
);
|
|
30918
|
+
}
|
|
30919
|
+
if (XB < 0 || YB < 0 || ZB < 0) {
|
|
30920
|
+
info(
|
|
30921
|
+
`Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], falling back to default.`
|
|
30922
|
+
);
|
|
30923
|
+
this.blackPoint = new Float32Array(3);
|
|
30924
|
+
}
|
|
30925
|
+
if (this.GR < 0 || this.GG < 0 || this.GB < 0) {
|
|
30926
|
+
info(
|
|
30927
|
+
`Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ${this.name}, falling back to default.`
|
|
30928
|
+
);
|
|
30929
|
+
this.GR = this.GG = this.GB = 1;
|
|
30930
|
+
}
|
|
30931
|
+
}
|
|
30932
|
+
#matrixProduct(a, b, result) {
|
|
30933
|
+
result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
30934
|
+
result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
|
|
30935
|
+
result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
|
|
30936
|
+
}
|
|
30937
|
+
#toFlat(sourceWhitePoint, LMS, result) {
|
|
30938
|
+
result[0] = LMS[0] * 1 / sourceWhitePoint[0];
|
|
30939
|
+
result[1] = LMS[1] * 1 / sourceWhitePoint[1];
|
|
30940
|
+
result[2] = LMS[2] * 1 / sourceWhitePoint[2];
|
|
30941
|
+
}
|
|
30942
|
+
#toD65(sourceWhitePoint, LMS, result) {
|
|
30943
|
+
const D65X = 0.95047;
|
|
30944
|
+
const D65Y = 1;
|
|
30945
|
+
const D65Z = 1.08883;
|
|
30946
|
+
result[0] = LMS[0] * D65X / sourceWhitePoint[0];
|
|
30947
|
+
result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
|
|
30948
|
+
result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
|
|
30949
|
+
}
|
|
30950
|
+
#sRGBTransferFunction(color) {
|
|
30951
|
+
if (color <= 31308e-7) {
|
|
30952
|
+
return MathClamp(12.92 * color, 0, 1);
|
|
30953
|
+
}
|
|
30954
|
+
return color >= 0.99554525 ? 1 : MathClamp((1 + 0.055) * color ** (1 / 2.4) - 0.055, 0, 1);
|
|
30955
|
+
}
|
|
30956
|
+
#decodeL(L) {
|
|
30957
|
+
if (L < 0) {
|
|
30958
|
+
return -this.#decodeL(-L);
|
|
30959
|
+
}
|
|
30960
|
+
return L > 8 ? ((L + 16) / 116) ** 3 : L * _CalRGBCS.#DECODE_L_CONSTANT;
|
|
30961
|
+
}
|
|
30962
|
+
#compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
|
|
30963
|
+
if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {
|
|
30964
|
+
result[0] = XYZ_Flat[0];
|
|
30965
|
+
result[1] = XYZ_Flat[1];
|
|
30966
|
+
result[2] = XYZ_Flat[2];
|
|
30967
|
+
return;
|
|
30968
|
+
}
|
|
30969
|
+
const zeroDecodeL = this.#decodeL(0);
|
|
30970
|
+
const X_DST = zeroDecodeL;
|
|
30971
|
+
const X_SRC = this.#decodeL(sourceBlackPoint[0]);
|
|
30972
|
+
const Y_DST = zeroDecodeL;
|
|
30973
|
+
const Y_SRC = this.#decodeL(sourceBlackPoint[1]);
|
|
30974
|
+
const Z_DST = zeroDecodeL;
|
|
30975
|
+
const Z_SRC = this.#decodeL(sourceBlackPoint[2]);
|
|
30976
|
+
const X_Scale = (1 - X_DST) / (1 - X_SRC);
|
|
30977
|
+
const X_Offset = 1 - X_Scale;
|
|
30978
|
+
const Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
|
|
30979
|
+
const Y_Offset = 1 - Y_Scale;
|
|
30980
|
+
const Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
|
|
30981
|
+
const Z_Offset = 1 - Z_Scale;
|
|
30982
|
+
result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
|
|
30983
|
+
result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
|
|
30984
|
+
result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
|
|
30985
|
+
}
|
|
30986
|
+
#normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
|
|
30987
|
+
if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
|
|
30988
|
+
result[0] = XYZ_In[0];
|
|
30989
|
+
result[1] = XYZ_In[1];
|
|
30990
|
+
result[2] = XYZ_In[2];
|
|
30991
|
+
return;
|
|
30992
|
+
}
|
|
30993
|
+
const LMS = result;
|
|
30994
|
+
this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
|
|
30995
|
+
const LMS_Flat = _CalRGBCS.#tempNormalizeMatrix;
|
|
30996
|
+
this.#toFlat(sourceWhitePoint, LMS, LMS_Flat);
|
|
30997
|
+
this.#matrixProduct(
|
|
30998
|
+
_CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
|
|
30999
|
+
LMS_Flat,
|
|
31000
|
+
result
|
|
31001
|
+
);
|
|
31002
|
+
}
|
|
31003
|
+
#normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
|
|
31004
|
+
const LMS = result;
|
|
31005
|
+
this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
|
|
31006
|
+
const LMS_D65 = _CalRGBCS.#tempNormalizeMatrix;
|
|
31007
|
+
this.#toD65(sourceWhitePoint, LMS, LMS_D65);
|
|
31008
|
+
this.#matrixProduct(
|
|
31009
|
+
_CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
|
|
31010
|
+
LMS_D65,
|
|
31011
|
+
result
|
|
31012
|
+
);
|
|
31013
|
+
}
|
|
31014
|
+
#toRgb(src, srcOffset, dest, destOffset, scale) {
|
|
31015
|
+
const A = MathClamp(src[srcOffset] * scale, 0, 1);
|
|
31016
|
+
const B = MathClamp(src[srcOffset + 1] * scale, 0, 1);
|
|
31017
|
+
const C = MathClamp(src[srcOffset + 2] * scale, 0, 1);
|
|
31018
|
+
const AGR = A === 1 ? 1 : A ** this.GR;
|
|
31019
|
+
const BGG = B === 1 ? 1 : B ** this.GG;
|
|
31020
|
+
const CGB = C === 1 ? 1 : C ** this.GB;
|
|
31021
|
+
const X = this.MXA * AGR + this.MXB * BGG + this.MXC * CGB;
|
|
31022
|
+
const Y = this.MYA * AGR + this.MYB * BGG + this.MYC * CGB;
|
|
31023
|
+
const Z = this.MZA * AGR + this.MZB * BGG + this.MZC * CGB;
|
|
31024
|
+
const XYZ = _CalRGBCS.#tempConvertMatrix1;
|
|
31025
|
+
XYZ[0] = X;
|
|
31026
|
+
XYZ[1] = Y;
|
|
31027
|
+
XYZ[2] = Z;
|
|
31028
|
+
const XYZ_Flat = _CalRGBCS.#tempConvertMatrix2;
|
|
31029
|
+
this.#normalizeWhitePointToFlat(this.whitePoint, XYZ, XYZ_Flat);
|
|
31030
|
+
const XYZ_Black = _CalRGBCS.#tempConvertMatrix1;
|
|
31031
|
+
this.#compensateBlackPoint(this.blackPoint, XYZ_Flat, XYZ_Black);
|
|
31032
|
+
const XYZ_D65 = _CalRGBCS.#tempConvertMatrix2;
|
|
31033
|
+
this.#normalizeWhitePointToD65(
|
|
31034
|
+
_CalRGBCS.#FLAT_WHITEPOINT_MATRIX,
|
|
31035
|
+
XYZ_Black,
|
|
31036
|
+
XYZ_D65
|
|
31037
|
+
);
|
|
31038
|
+
const SRGB = _CalRGBCS.#tempConvertMatrix1;
|
|
31039
|
+
this.#matrixProduct(_CalRGBCS.#SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
|
|
31040
|
+
dest[destOffset] = this.#sRGBTransferFunction(SRGB[0]) * 255;
|
|
31041
|
+
dest[destOffset + 1] = this.#sRGBTransferFunction(SRGB[1]) * 255;
|
|
31042
|
+
dest[destOffset + 2] = this.#sRGBTransferFunction(SRGB[2]) * 255;
|
|
31043
|
+
}
|
|
31044
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
31045
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
31046
|
+
assert2(
|
|
31047
|
+
dest instanceof Uint8ClampedArray,
|
|
31048
|
+
'CalRGBCS.getRgbItem: Unsupported "dest" type.'
|
|
31049
|
+
);
|
|
31050
|
+
}
|
|
31051
|
+
this.#toRgb(src, srcOffset, dest, destOffset, 1);
|
|
31052
|
+
}
|
|
31053
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
31054
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
31055
|
+
assert2(
|
|
31056
|
+
dest instanceof Uint8ClampedArray,
|
|
31057
|
+
'CalRGBCS.getRgbBuffer: Unsupported "dest" type.'
|
|
31058
|
+
);
|
|
31059
|
+
}
|
|
31060
|
+
const scale = 1 / ((1 << bits) - 1);
|
|
31061
|
+
for (let i = 0; i < count; ++i) {
|
|
31062
|
+
this.#toRgb(src, srcOffset, dest, destOffset, scale);
|
|
31063
|
+
srcOffset += 3;
|
|
31064
|
+
destOffset += 3 + alpha01;
|
|
31065
|
+
}
|
|
31066
|
+
}
|
|
31067
|
+
};
|
|
31068
|
+
var LabCS = class extends ColorSpace {
|
|
31069
|
+
constructor(whitePoint, blackPoint, range) {
|
|
31070
|
+
super("Lab", 3);
|
|
31071
|
+
if (!whitePoint) {
|
|
31072
|
+
throw new FormatError(
|
|
31073
|
+
"WhitePoint missing - required for color space Lab"
|
|
31074
|
+
);
|
|
31075
|
+
}
|
|
31076
|
+
[this.XW, this.YW, this.ZW] = whitePoint;
|
|
31077
|
+
[this.amin, this.amax, this.bmin, this.bmax] = range || [
|
|
31078
|
+
-100,
|
|
31079
|
+
100,
|
|
31080
|
+
-100,
|
|
31081
|
+
100
|
|
31082
|
+
];
|
|
31083
|
+
[this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
|
|
31084
|
+
if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
|
|
31085
|
+
throw new FormatError(
|
|
31086
|
+
"Invalid WhitePoint components, no fallback available"
|
|
31087
|
+
);
|
|
31088
|
+
}
|
|
31089
|
+
if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
|
|
31090
|
+
info("Invalid BlackPoint, falling back to default");
|
|
31091
|
+
this.XB = this.YB = this.ZB = 0;
|
|
31092
|
+
}
|
|
31093
|
+
if (this.amin > this.amax || this.bmin > this.bmax) {
|
|
31094
|
+
info("Invalid Range, falling back to defaults");
|
|
31095
|
+
this.amin = -100;
|
|
31096
|
+
this.amax = 100;
|
|
31097
|
+
this.bmin = -100;
|
|
31098
|
+
this.bmax = 100;
|
|
31099
|
+
}
|
|
31100
|
+
}
|
|
31101
|
+
// Function g(x) from spec
|
|
31102
|
+
#fn_g(x) {
|
|
31103
|
+
return x >= 6 / 29 ? x ** 3 : 108 / 841 * (x - 4 / 29);
|
|
31104
|
+
}
|
|
31105
|
+
#decode(value, high1, low2, high2) {
|
|
31106
|
+
return low2 + value * (high2 - low2) / high1;
|
|
31107
|
+
}
|
|
31108
|
+
// If decoding is needed maxVal should be 2^bits per component - 1.
|
|
31109
|
+
#toRgb(src, srcOffset, maxVal, dest, destOffset) {
|
|
31110
|
+
let Ls = src[srcOffset];
|
|
31111
|
+
let as = src[srcOffset + 1];
|
|
31112
|
+
let bs = src[srcOffset + 2];
|
|
31113
|
+
if (maxVal !== false) {
|
|
31114
|
+
Ls = this.#decode(Ls, maxVal, 0, 100);
|
|
31115
|
+
as = this.#decode(as, maxVal, this.amin, this.amax);
|
|
31116
|
+
bs = this.#decode(bs, maxVal, this.bmin, this.bmax);
|
|
31117
|
+
}
|
|
31118
|
+
if (as > this.amax) {
|
|
31119
|
+
as = this.amax;
|
|
31120
|
+
} else if (as < this.amin) {
|
|
31121
|
+
as = this.amin;
|
|
31122
|
+
}
|
|
31123
|
+
if (bs > this.bmax) {
|
|
31124
|
+
bs = this.bmax;
|
|
31125
|
+
} else if (bs < this.bmin) {
|
|
31126
|
+
bs = this.bmin;
|
|
31127
|
+
}
|
|
31128
|
+
const M = (Ls + 16) / 116;
|
|
31129
|
+
const L = M + as / 500;
|
|
31130
|
+
const N = M - bs / 200;
|
|
31131
|
+
const X = this.XW * this.#fn_g(L);
|
|
31132
|
+
const Y = this.YW * this.#fn_g(M);
|
|
31133
|
+
const Z = this.ZW * this.#fn_g(N);
|
|
31134
|
+
let r, g, b;
|
|
31135
|
+
if (this.ZW < 1) {
|
|
31136
|
+
r = X * 3.1339 + Y * -1.617 + Z * -0.4906;
|
|
31137
|
+
g = X * -0.9785 + Y * 1.916 + Z * 0.0333;
|
|
31138
|
+
b = X * 0.072 + Y * -0.229 + Z * 1.4057;
|
|
31139
|
+
} else {
|
|
31140
|
+
r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
|
|
31141
|
+
g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
|
|
31142
|
+
b = X * 0.0557 + Y * -0.204 + Z * 1.057;
|
|
31143
|
+
}
|
|
31144
|
+
dest[destOffset] = Math.sqrt(r) * 255;
|
|
31145
|
+
dest[destOffset + 1] = Math.sqrt(g) * 255;
|
|
31146
|
+
dest[destOffset + 2] = Math.sqrt(b) * 255;
|
|
31147
|
+
}
|
|
31148
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
31149
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
31150
|
+
assert2(
|
|
31151
|
+
dest instanceof Uint8ClampedArray,
|
|
31152
|
+
'LabCS.getRgbItem: Unsupported "dest" type.'
|
|
31153
|
+
);
|
|
31154
|
+
}
|
|
31155
|
+
this.#toRgb(src, srcOffset, false, dest, destOffset);
|
|
31156
|
+
}
|
|
31157
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
31158
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
31159
|
+
assert2(
|
|
31160
|
+
dest instanceof Uint8ClampedArray,
|
|
31161
|
+
'LabCS.getRgbBuffer: Unsupported "dest" type.'
|
|
31162
|
+
);
|
|
31163
|
+
}
|
|
31164
|
+
const maxVal = (1 << bits) - 1;
|
|
31165
|
+
for (let i = 0; i < count; i++) {
|
|
31166
|
+
this.#toRgb(src, srcOffset, maxVal, dest, destOffset);
|
|
31167
|
+
srcOffset += 3;
|
|
31168
|
+
destOffset += 3 + alpha01;
|
|
31169
|
+
}
|
|
31170
|
+
}
|
|
31171
|
+
isDefaultDecode(decode, bpc) {
|
|
31172
|
+
return true;
|
|
31173
|
+
}
|
|
31174
|
+
get usesZeroToOneRange() {
|
|
31175
|
+
return shadow2(this, "usesZeroToOneRange", false);
|
|
31176
|
+
}
|
|
31177
|
+
};
|
|
31178
|
+
var TOKEN = {
|
|
31179
|
+
// Structural tokens — not keyword operators
|
|
31180
|
+
number: 0,
|
|
31181
|
+
lbrace: 1,
|
|
31182
|
+
rbrace: 2,
|
|
31183
|
+
// Boolean literals
|
|
31184
|
+
true: 3,
|
|
31185
|
+
false: 4,
|
|
31186
|
+
// Arithmetic binary operators
|
|
31187
|
+
add: 5,
|
|
31188
|
+
sub: 6,
|
|
31189
|
+
mul: 7,
|
|
31190
|
+
div: 8,
|
|
31191
|
+
idiv: 9,
|
|
31192
|
+
mod: 10,
|
|
31193
|
+
exp: 11,
|
|
31194
|
+
// Comparison binary operators
|
|
31195
|
+
eq: 12,
|
|
31196
|
+
ne: 13,
|
|
31197
|
+
gt: 14,
|
|
31198
|
+
ge: 15,
|
|
31199
|
+
lt: 16,
|
|
31200
|
+
le: 17,
|
|
31201
|
+
// Bitwise / boolean binary operators
|
|
31202
|
+
and: 18,
|
|
31203
|
+
or: 19,
|
|
31204
|
+
xor: 20,
|
|
31205
|
+
bitshift: 21,
|
|
31206
|
+
// Unary arithmetic operators
|
|
31207
|
+
abs: 22,
|
|
31208
|
+
neg: 23,
|
|
31209
|
+
ceiling: 24,
|
|
31210
|
+
floor: 25,
|
|
31211
|
+
round: 26,
|
|
31212
|
+
truncate: 27,
|
|
31213
|
+
// Unary boolean / bitwise operator
|
|
31214
|
+
not: 28,
|
|
31215
|
+
// Mathematical functions — unary
|
|
31216
|
+
sqrt: 29,
|
|
31217
|
+
sin: 30,
|
|
31218
|
+
cos: 31,
|
|
31219
|
+
ln: 32,
|
|
31220
|
+
log: 33,
|
|
31221
|
+
// Mathematical function — binary
|
|
31222
|
+
atan: 34,
|
|
31223
|
+
// Type conversion operators
|
|
31224
|
+
cvi: 35,
|
|
31225
|
+
cvr: 36,
|
|
31226
|
+
// Stack operators
|
|
31227
|
+
dup: 37,
|
|
31228
|
+
exch: 38,
|
|
31229
|
+
pop: 39,
|
|
31230
|
+
copy: 40,
|
|
31231
|
+
index: 41,
|
|
31232
|
+
roll: 42,
|
|
31233
|
+
// Control flow
|
|
31234
|
+
if: 43,
|
|
31235
|
+
ifelse: 44,
|
|
31236
|
+
// End of input
|
|
31237
|
+
eof: 45,
|
|
31238
|
+
// Synthetic: produced by the optimizer, never emitted by the lexer.
|
|
31239
|
+
min: 46,
|
|
31240
|
+
max: 47
|
|
31241
|
+
};
|
|
31242
|
+
var Token = class {
|
|
31243
|
+
constructor(id, value = null) {
|
|
31244
|
+
this.id = id;
|
|
31245
|
+
this.value = value;
|
|
31246
|
+
}
|
|
31247
|
+
};
|
|
31248
|
+
var Lexer = class _Lexer {
|
|
31249
|
+
// Singletons for every non-number token, built lazily on first construction.
|
|
31250
|
+
// Keyword operator tokens carry their name as `value`; structural tokens
|
|
31251
|
+
// (lbrace, rbrace, eof) carry null.
|
|
31252
|
+
static #singletons = null;
|
|
31253
|
+
static #operatorSingletons = null;
|
|
31254
|
+
static #initSingletons() {
|
|
31255
|
+
const singletons = /* @__PURE__ */ Object.create(null);
|
|
31256
|
+
const operatorSingletons = /* @__PURE__ */ Object.create(null);
|
|
31257
|
+
for (const [name, id] of Object.entries(TOKEN)) {
|
|
31258
|
+
if (name === "number") {
|
|
31259
|
+
continue;
|
|
31260
|
+
}
|
|
31261
|
+
const isOperator = id >= TOKEN.true && id <= TOKEN.ifelse;
|
|
31262
|
+
const token = new Token(id, isOperator ? name : null);
|
|
31263
|
+
singletons[name] = token;
|
|
31264
|
+
if (isOperator) {
|
|
31265
|
+
operatorSingletons[name] = token;
|
|
31266
|
+
}
|
|
31267
|
+
}
|
|
31268
|
+
this.#singletons = singletons;
|
|
31269
|
+
this.#operatorSingletons = operatorSingletons;
|
|
31270
|
+
}
|
|
31271
|
+
constructor(data) {
|
|
31272
|
+
if (!_Lexer.#singletons) {
|
|
31273
|
+
_Lexer.#initSingletons();
|
|
31274
|
+
}
|
|
31275
|
+
this.data = data;
|
|
31276
|
+
this.pos = 0;
|
|
31277
|
+
this.len = data.length;
|
|
31278
|
+
this._numberPattern = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/iy;
|
|
31279
|
+
this._identifierPattern = /[a-z]+/y;
|
|
31280
|
+
}
|
|
31281
|
+
// Skip a % comment, advancing past the next \n or \r (or to EOF).
|
|
31282
|
+
_skipComment() {
|
|
31283
|
+
const lf = this.data.indexOf("\n", this.pos);
|
|
31284
|
+
const cr = this.data.indexOf("\r", this.pos);
|
|
31285
|
+
const eol = Math.min(lf < 0 ? this.len : lf, cr < 0 ? this.len : cr);
|
|
31286
|
+
this.pos = Math.min(eol + 1, this.len);
|
|
31287
|
+
}
|
|
31288
|
+
_getNumber() {
|
|
31289
|
+
this._numberPattern.lastIndex = this.pos;
|
|
31290
|
+
const match = this._numberPattern.exec(this.data);
|
|
31291
|
+
if (!match) {
|
|
31292
|
+
return new Token(TOKEN.number, 0);
|
|
31293
|
+
}
|
|
31294
|
+
const number = parseFloat(match[0]);
|
|
31295
|
+
if (!Number.isFinite(number)) {
|
|
31296
|
+
return new Token(TOKEN.number, 0);
|
|
31297
|
+
}
|
|
31298
|
+
this.pos = this._numberPattern.lastIndex;
|
|
31299
|
+
return new Token(TOKEN.number, number);
|
|
31300
|
+
}
|
|
31301
|
+
_getOperator() {
|
|
31302
|
+
this._identifierPattern.lastIndex = this.pos;
|
|
31303
|
+
const match = this._identifierPattern.exec(this.data);
|
|
31304
|
+
if (!match) {
|
|
31305
|
+
return new Token(TOKEN.number, 0);
|
|
31306
|
+
}
|
|
31307
|
+
this.pos = this._identifierPattern.lastIndex;
|
|
31308
|
+
const op = match[0];
|
|
31309
|
+
const token = _Lexer.#operatorSingletons[op];
|
|
31310
|
+
return token ?? new Token(TOKEN.number, 0);
|
|
31311
|
+
}
|
|
31312
|
+
// Return the next token, or Lexer.#singletons.eof at end of input.
|
|
31313
|
+
next() {
|
|
31314
|
+
while (this.pos < this.len) {
|
|
31315
|
+
const ch3 = this.data.charCodeAt(this.pos++);
|
|
31316
|
+
switch (ch3) {
|
|
31317
|
+
// PostScript white-space characters (PDF32000 §7.2.2)
|
|
31318
|
+
case 0:
|
|
31319
|
+
case 9:
|
|
31320
|
+
case 10:
|
|
31321
|
+
case 12:
|
|
31322
|
+
case 13:
|
|
31323
|
+
case 32:
|
|
31324
|
+
break;
|
|
31325
|
+
case 37:
|
|
31326
|
+
this._skipComment();
|
|
31327
|
+
break;
|
|
31328
|
+
case 123:
|
|
31329
|
+
return _Lexer.#singletons.lbrace;
|
|
31330
|
+
case 125:
|
|
31331
|
+
return _Lexer.#singletons.rbrace;
|
|
31332
|
+
case 43:
|
|
31333
|
+
case 45:
|
|
31334
|
+
this.pos--;
|
|
31335
|
+
return this._getNumber();
|
|
31336
|
+
case 46:
|
|
31337
|
+
this.pos--;
|
|
31338
|
+
return this._getNumber();
|
|
31339
|
+
default:
|
|
31340
|
+
if (ch3 >= 48 && ch3 <= 57) {
|
|
31341
|
+
this.pos--;
|
|
31342
|
+
return this._getNumber();
|
|
31343
|
+
}
|
|
31344
|
+
if (ch3 >= 97 && ch3 <= 122) {
|
|
31345
|
+
this.pos--;
|
|
31346
|
+
return this._getOperator();
|
|
31347
|
+
}
|
|
31348
|
+
return new Token(TOKEN.number, 0);
|
|
31349
|
+
}
|
|
31350
|
+
}
|
|
31351
|
+
return _Lexer.#singletons.eof;
|
|
31352
|
+
}
|
|
31353
|
+
};
|
|
31354
|
+
var PS_VALUE_TYPE = {
|
|
31355
|
+
numeric: 0,
|
|
31356
|
+
// known to be a number (f64 in Wasm)
|
|
31357
|
+
boolean: 1,
|
|
31358
|
+
// known to be a boolean (0.0 = false, 1.0 = true in f64)
|
|
31359
|
+
unknown: 2
|
|
31360
|
+
// indeterminate at compile time
|
|
31361
|
+
};
|
|
31362
|
+
var PS_NODE = {
|
|
31363
|
+
// Parser AST node types (produced by Parser / parsePostScriptFunction)
|
|
31364
|
+
program: 0,
|
|
31365
|
+
block: 1,
|
|
31366
|
+
number: 2,
|
|
31367
|
+
operator: 3,
|
|
31368
|
+
if: 4,
|
|
31369
|
+
ifelse: 5,
|
|
31370
|
+
// Tree AST node types (produced by PSStackToTree)
|
|
31371
|
+
arg: 6,
|
|
31372
|
+
const: 7,
|
|
31373
|
+
unary: 8,
|
|
31374
|
+
binary: 9,
|
|
31375
|
+
ternary: 10
|
|
31376
|
+
};
|
|
31377
|
+
var PsNode = class {
|
|
31378
|
+
constructor(type) {
|
|
31379
|
+
this.type = type;
|
|
31380
|
+
}
|
|
31381
|
+
};
|
|
31382
|
+
var PsProgram = class extends PsNode {
|
|
31383
|
+
constructor(body) {
|
|
31384
|
+
super(PS_NODE.program);
|
|
31385
|
+
this.body = body;
|
|
31386
|
+
}
|
|
31387
|
+
};
|
|
31388
|
+
var PsBlock = class extends PsNode {
|
|
31389
|
+
constructor(instructions) {
|
|
31390
|
+
super(PS_NODE.block);
|
|
31391
|
+
this.instructions = instructions;
|
|
31392
|
+
}
|
|
31393
|
+
};
|
|
31394
|
+
var PsNumber = class extends PsNode {
|
|
31395
|
+
/** @param {number} value */
|
|
31396
|
+
constructor(value) {
|
|
31397
|
+
super(PS_NODE.number);
|
|
31398
|
+
this.value = value;
|
|
31399
|
+
}
|
|
31400
|
+
};
|
|
31401
|
+
var PsOperator = class extends PsNode {
|
|
31402
|
+
/** @param {number} op — one of the TOKEN.* constants from lexer.js */
|
|
31403
|
+
constructor(op) {
|
|
31404
|
+
super(PS_NODE.operator);
|
|
31405
|
+
this.op = op;
|
|
31406
|
+
}
|
|
31407
|
+
};
|
|
31408
|
+
var PsIf = class extends PsNode {
|
|
31409
|
+
/** @param {PsBlock} then */
|
|
31410
|
+
constructor(then) {
|
|
31411
|
+
super(PS_NODE.if);
|
|
31412
|
+
this.then = then;
|
|
31413
|
+
}
|
|
31414
|
+
};
|
|
31415
|
+
var PsIfElse = class extends PsNode {
|
|
31416
|
+
/**
|
|
31417
|
+
* @param {PsBlock} then
|
|
31418
|
+
* @param {PsBlock} otherwise
|
|
31419
|
+
*/
|
|
31420
|
+
constructor(then, otherwise) {
|
|
31421
|
+
super(PS_NODE.ifelse);
|
|
31422
|
+
this.then = then;
|
|
31423
|
+
this.otherwise = otherwise;
|
|
31424
|
+
}
|
|
31425
|
+
};
|
|
31426
|
+
var PsArgNode = class extends PsNode {
|
|
31427
|
+
/** @param {number} index */
|
|
31428
|
+
constructor(index) {
|
|
31429
|
+
super(PS_NODE.arg);
|
|
31430
|
+
this.index = index;
|
|
31431
|
+
this.valueType = PS_VALUE_TYPE.numeric;
|
|
31432
|
+
}
|
|
31433
|
+
};
|
|
31434
|
+
var PsConstNode = class extends PsNode {
|
|
31435
|
+
/** @param {number|boolean} value */
|
|
31436
|
+
constructor(value) {
|
|
31437
|
+
super(PS_NODE.const);
|
|
31438
|
+
this.value = value;
|
|
31439
|
+
this.valueType = typeof value === "boolean" ? PS_VALUE_TYPE.boolean : PS_VALUE_TYPE.numeric;
|
|
31440
|
+
}
|
|
31441
|
+
};
|
|
31442
|
+
var PsUnaryNode = class extends PsNode {
|
|
31443
|
+
/**
|
|
31444
|
+
* @param {number} op — TOKEN.* constant
|
|
31445
|
+
* @param {PsNode} operand
|
|
31446
|
+
* @param {number} [valueType]
|
|
31447
|
+
*/
|
|
31448
|
+
constructor(op, operand, valueType = PS_VALUE_TYPE.unknown) {
|
|
31449
|
+
super(PS_NODE.unary);
|
|
31450
|
+
this.op = op;
|
|
31451
|
+
this.operand = operand;
|
|
31452
|
+
this.valueType = valueType;
|
|
31453
|
+
}
|
|
31454
|
+
};
|
|
31455
|
+
var PsBinaryNode = class extends PsNode {
|
|
31456
|
+
/**
|
|
31457
|
+
* @param {number} op — TOKEN.* constant
|
|
31458
|
+
* @param {PsNode} first — was on top of stack
|
|
31459
|
+
* @param {PsNode} second — was below top
|
|
31460
|
+
* @param {number} [valueType]
|
|
31461
|
+
*/
|
|
31462
|
+
constructor(op, first, second, valueType = PS_VALUE_TYPE.unknown) {
|
|
31463
|
+
super(PS_NODE.binary);
|
|
31464
|
+
this.op = op;
|
|
31465
|
+
this.first = first;
|
|
31466
|
+
this.second = second;
|
|
31467
|
+
this.valueType = valueType;
|
|
31468
|
+
}
|
|
31469
|
+
};
|
|
31470
|
+
var PsTernaryNode = class extends PsNode {
|
|
31471
|
+
/**
|
|
31472
|
+
* @param {PsNode} cond
|
|
31473
|
+
* @param {PsNode} then
|
|
31474
|
+
* @param {PsNode} otherwise
|
|
31475
|
+
* @param {number} [valueType]
|
|
31476
|
+
*/
|
|
31477
|
+
constructor(cond, then, otherwise, valueType = PS_VALUE_TYPE.unknown) {
|
|
31478
|
+
super(PS_NODE.ternary);
|
|
31479
|
+
this.cond = cond;
|
|
31480
|
+
this.then = then;
|
|
31481
|
+
this.otherwise = otherwise;
|
|
31482
|
+
this.valueType = valueType;
|
|
31483
|
+
}
|
|
31484
|
+
};
|
|
31485
|
+
var Parser = class _Parser {
|
|
31486
|
+
constructor(lexer) {
|
|
31487
|
+
this.lexer = lexer;
|
|
31488
|
+
this._token = null;
|
|
31489
|
+
}
|
|
31490
|
+
static _isRegularOperator(id) {
|
|
31491
|
+
return id >= TOKEN.true && id < TOKEN.if;
|
|
31492
|
+
}
|
|
31493
|
+
// Fetch the next token from the lexer.
|
|
31494
|
+
_advance() {
|
|
31495
|
+
this._token = this.lexer.next();
|
|
31496
|
+
}
|
|
31497
|
+
// Assert that the current token has the given id, consume it, and return it.
|
|
31498
|
+
_expect(id) {
|
|
31499
|
+
if (this._token.id !== id) {
|
|
31500
|
+
throw new FormatError(
|
|
31501
|
+
`PostScript function: expected token id ${id}, got ${this._token.id}.`
|
|
31502
|
+
);
|
|
31503
|
+
}
|
|
31504
|
+
const tok = this._token;
|
|
31505
|
+
this._advance();
|
|
31506
|
+
return tok;
|
|
31507
|
+
}
|
|
31508
|
+
/**
|
|
31509
|
+
* Parse the full Type 4 function body.
|
|
31510
|
+
*
|
|
31511
|
+
* Grammar (simplified):
|
|
31512
|
+
* program ::= '{' block '}'
|
|
31513
|
+
* block ::= instruction*
|
|
31514
|
+
* instruction ::= number
|
|
31515
|
+
* | operator (any PS_OPERATOR except if / ifelse)
|
|
31516
|
+
* | '{' block '}' 'if'
|
|
31517
|
+
* | '{' block '}' '{' block '}' 'ifelse'
|
|
31518
|
+
* @returns {PsProgram}
|
|
31519
|
+
*/
|
|
31520
|
+
parse() {
|
|
31521
|
+
this._advance();
|
|
31522
|
+
this._expect(TOKEN.lbrace);
|
|
31523
|
+
const block = this._parseBlock();
|
|
31524
|
+
this._expect(TOKEN.rbrace);
|
|
31525
|
+
if (this._token.id !== TOKEN.eof) {
|
|
31526
|
+
warn2("PostScript function: unexpected content after closing brace.");
|
|
31527
|
+
}
|
|
31528
|
+
return new PsProgram(block);
|
|
31529
|
+
}
|
|
31530
|
+
_parseBlock() {
|
|
31531
|
+
const instructions = [];
|
|
31532
|
+
while (true) {
|
|
31533
|
+
const tok = this._token;
|
|
31534
|
+
switch (tok.id) {
|
|
31535
|
+
case TOKEN.number:
|
|
31536
|
+
instructions.push(new PsNumber(tok.value));
|
|
31537
|
+
this._advance();
|
|
31538
|
+
break;
|
|
31539
|
+
case TOKEN.lbrace: {
|
|
31540
|
+
this._advance();
|
|
31541
|
+
const thenBlock = this._parseBlock();
|
|
31542
|
+
this._expect(TOKEN.rbrace);
|
|
31543
|
+
if (this._token.id === TOKEN.if) {
|
|
31544
|
+
this._advance();
|
|
31545
|
+
instructions.push(new PsIf(thenBlock));
|
|
31546
|
+
} else if (this._token.id === TOKEN.lbrace) {
|
|
31547
|
+
this._advance();
|
|
31548
|
+
const elseBlock = this._parseBlock();
|
|
31549
|
+
this._expect(TOKEN.rbrace);
|
|
31550
|
+
this._expect(TOKEN.ifelse);
|
|
31551
|
+
instructions.push(new PsIfElse(thenBlock, elseBlock));
|
|
31552
|
+
} else {
|
|
31553
|
+
throw new FormatError(
|
|
31554
|
+
"PostScript function: a procedure block must be followed by 'if' or '{\u2026} ifelse'."
|
|
31555
|
+
);
|
|
31556
|
+
}
|
|
31557
|
+
break;
|
|
31558
|
+
}
|
|
31559
|
+
case TOKEN.rbrace:
|
|
31560
|
+
case TOKEN.eof:
|
|
31561
|
+
return new PsBlock(instructions);
|
|
31562
|
+
case TOKEN.if:
|
|
31563
|
+
case TOKEN.ifelse:
|
|
31564
|
+
throw new FormatError(
|
|
31565
|
+
`PostScript function: unexpected '${tok.value}' operator.`
|
|
31566
|
+
);
|
|
31567
|
+
default:
|
|
31568
|
+
if (_Parser._isRegularOperator(tok.id)) {
|
|
31569
|
+
instructions.push(new PsOperator(tok.id));
|
|
31570
|
+
this._advance();
|
|
31571
|
+
break;
|
|
31572
|
+
}
|
|
31573
|
+
throw new FormatError(
|
|
31574
|
+
`PostScript function: unexpected token id ${tok.id}.`
|
|
31575
|
+
);
|
|
31576
|
+
}
|
|
31577
|
+
}
|
|
31578
|
+
}
|
|
31579
|
+
};
|
|
31580
|
+
function parsePostScriptFunction(source) {
|
|
31581
|
+
return new Parser(new Lexer(source)).parse();
|
|
31582
|
+
}
|
|
31583
|
+
function _nodesEqual(a, b) {
|
|
31584
|
+
if (a === b) {
|
|
31585
|
+
return true;
|
|
31586
|
+
}
|
|
31587
|
+
if (a.type !== b.type) {
|
|
31588
|
+
return false;
|
|
31589
|
+
}
|
|
31590
|
+
switch (a.type) {
|
|
31591
|
+
case PS_NODE.arg:
|
|
31592
|
+
return a.index === b.index;
|
|
31593
|
+
case PS_NODE.const:
|
|
31594
|
+
return a.value === b.value;
|
|
31595
|
+
case PS_NODE.unary:
|
|
31596
|
+
return a.op === b.op && _nodesEqual(a.operand, b.operand);
|
|
31597
|
+
case PS_NODE.binary:
|
|
31598
|
+
return a.op === b.op && _nodesEqual(a.first, b.first) && _nodesEqual(a.second, b.second);
|
|
31599
|
+
case PS_NODE.ternary:
|
|
31600
|
+
return _nodesEqual(a.cond, b.cond) && _nodesEqual(a.then, b.then) && _nodesEqual(a.otherwise, b.otherwise);
|
|
31601
|
+
default:
|
|
31602
|
+
return false;
|
|
31603
|
+
}
|
|
31604
|
+
}
|
|
31605
|
+
function _evalBinaryConst(op, a, b) {
|
|
31606
|
+
switch (op) {
|
|
31607
|
+
case TOKEN.add:
|
|
31608
|
+
return a + b;
|
|
31609
|
+
case TOKEN.sub:
|
|
31610
|
+
return a - b;
|
|
31611
|
+
case TOKEN.mul:
|
|
31612
|
+
return a * b;
|
|
31613
|
+
case TOKEN.div:
|
|
31614
|
+
return b !== 0 ? a / b : 0;
|
|
31615
|
+
// div by zero → 0
|
|
31616
|
+
case TOKEN.idiv:
|
|
31617
|
+
return b !== 0 ? Math.trunc(a / b) : 0;
|
|
31618
|
+
// div by zero → 0
|
|
31619
|
+
case TOKEN.mod:
|
|
31620
|
+
return b !== 0 ? a - Math.trunc(a / b) * b : 0;
|
|
31621
|
+
// div by zero → 0
|
|
31622
|
+
case TOKEN.exp: {
|
|
31623
|
+
const r = a ** b;
|
|
31624
|
+
return Number.isFinite(r) ? r : void 0;
|
|
31625
|
+
}
|
|
31626
|
+
case TOKEN.atan: {
|
|
31627
|
+
let deg = Math.atan2(a, b) * (180 / Math.PI);
|
|
31628
|
+
if (deg < 0) {
|
|
31629
|
+
deg += 360;
|
|
31630
|
+
}
|
|
31631
|
+
return deg;
|
|
31632
|
+
}
|
|
31633
|
+
case TOKEN.eq:
|
|
31634
|
+
return a === b;
|
|
31635
|
+
case TOKEN.ne:
|
|
31636
|
+
return a !== b;
|
|
31637
|
+
case TOKEN.gt:
|
|
31638
|
+
return a > b;
|
|
31639
|
+
case TOKEN.ge:
|
|
31640
|
+
return a >= b;
|
|
31641
|
+
case TOKEN.lt:
|
|
31642
|
+
return a < b;
|
|
31643
|
+
case TOKEN.le:
|
|
31644
|
+
return a <= b;
|
|
31645
|
+
case TOKEN.and:
|
|
31646
|
+
return typeof a === "boolean" ? a && b : a & b | 0;
|
|
31647
|
+
case TOKEN.or:
|
|
31648
|
+
return typeof a === "boolean" ? a || b : a | b | 0;
|
|
31649
|
+
case TOKEN.xor:
|
|
31650
|
+
return typeof a === "boolean" ? a !== b : a ^ b | 0;
|
|
31651
|
+
case TOKEN.bitshift:
|
|
31652
|
+
return b >= 0 ? a << b | 0 : a >> -b | 0;
|
|
31653
|
+
case TOKEN.min:
|
|
31654
|
+
return Math.min(a, b);
|
|
31655
|
+
case TOKEN.max:
|
|
31656
|
+
return Math.max(a, b);
|
|
31657
|
+
default:
|
|
31658
|
+
return void 0;
|
|
31659
|
+
}
|
|
31660
|
+
}
|
|
31661
|
+
function _evalUnaryConst(op, v) {
|
|
31662
|
+
switch (op) {
|
|
31663
|
+
case TOKEN.abs:
|
|
31664
|
+
return Math.abs(v);
|
|
31665
|
+
case TOKEN.neg:
|
|
31666
|
+
return -v;
|
|
31667
|
+
case TOKEN.ceiling:
|
|
31668
|
+
return Math.ceil(v);
|
|
31669
|
+
case TOKEN.floor:
|
|
31670
|
+
return Math.floor(v);
|
|
31671
|
+
case TOKEN.round:
|
|
31672
|
+
return Math.round(v);
|
|
31673
|
+
case TOKEN.truncate:
|
|
31674
|
+
return Math.trunc(v);
|
|
31675
|
+
case TOKEN.sqrt: {
|
|
31676
|
+
const r = Math.sqrt(v);
|
|
31677
|
+
return Number.isFinite(r) ? r : void 0;
|
|
31678
|
+
}
|
|
31679
|
+
case TOKEN.sin:
|
|
31680
|
+
return Math.sin(v % 360 * Math.PI / 180);
|
|
31681
|
+
case TOKEN.cos:
|
|
31682
|
+
return Math.cos(v % 360 * Math.PI / 180);
|
|
31683
|
+
case TOKEN.ln: {
|
|
31684
|
+
const r = Math.log(v);
|
|
31685
|
+
return Number.isFinite(r) ? r : void 0;
|
|
31686
|
+
}
|
|
31687
|
+
case TOKEN.log: {
|
|
31688
|
+
const r = Math.log10(v);
|
|
31689
|
+
return Number.isFinite(r) ? r : void 0;
|
|
31690
|
+
}
|
|
31691
|
+
case TOKEN.cvi:
|
|
31692
|
+
return Math.trunc(v);
|
|
31693
|
+
case TOKEN.cvr:
|
|
31694
|
+
return v;
|
|
31695
|
+
case TOKEN.not:
|
|
31696
|
+
return typeof v === "boolean" ? !v : ~v;
|
|
31697
|
+
default:
|
|
31698
|
+
return void 0;
|
|
31699
|
+
}
|
|
31700
|
+
}
|
|
31701
|
+
var MAX_STACK_SIZE = 100;
|
|
31702
|
+
function _unaryValueType(op, operandType) {
|
|
31703
|
+
return op === TOKEN.not ? operandType : PS_VALUE_TYPE.numeric;
|
|
31704
|
+
}
|
|
31705
|
+
function _binaryValueType(op, firstType, secondType) {
|
|
31706
|
+
switch (op) {
|
|
31707
|
+
// Comparison operators always produce a boolean.
|
|
31708
|
+
case TOKEN.eq:
|
|
31709
|
+
case TOKEN.ne:
|
|
31710
|
+
case TOKEN.gt:
|
|
31711
|
+
case TOKEN.ge:
|
|
31712
|
+
case TOKEN.lt:
|
|
31713
|
+
case TOKEN.le:
|
|
31714
|
+
return PS_VALUE_TYPE.boolean;
|
|
31715
|
+
// and / or / xor preserve the type when both operands are the same known
|
|
31716
|
+
// type (both boolean or both numeric); otherwise the type is unknown.
|
|
31717
|
+
case TOKEN.and:
|
|
31718
|
+
case TOKEN.or:
|
|
31719
|
+
case TOKEN.xor:
|
|
31720
|
+
return firstType === secondType && firstType !== PS_VALUE_TYPE.unknown ? firstType : PS_VALUE_TYPE.unknown;
|
|
31721
|
+
// All arithmetic / bitshift operators produce a numeric result.
|
|
31722
|
+
default:
|
|
31723
|
+
return PS_VALUE_TYPE.numeric;
|
|
31724
|
+
}
|
|
31725
|
+
}
|
|
31726
|
+
var PSStackToTree = class _PSStackToTree {
|
|
31727
|
+
static #binaryOps = null;
|
|
31728
|
+
static #unaryOps = null;
|
|
31729
|
+
static #idempotentUnary = null;
|
|
31730
|
+
static #negatedComparison = null;
|
|
31731
|
+
static #init() {
|
|
31732
|
+
this.#binaryOps = /* @__PURE__ */ new Set([
|
|
31733
|
+
TOKEN.add,
|
|
31734
|
+
TOKEN.sub,
|
|
31735
|
+
TOKEN.mul,
|
|
31736
|
+
TOKEN.div,
|
|
31737
|
+
TOKEN.idiv,
|
|
31738
|
+
TOKEN.mod,
|
|
31739
|
+
TOKEN.exp,
|
|
31740
|
+
TOKEN.atan,
|
|
31741
|
+
TOKEN.eq,
|
|
31742
|
+
TOKEN.ne,
|
|
31743
|
+
TOKEN.gt,
|
|
31744
|
+
TOKEN.ge,
|
|
31745
|
+
TOKEN.lt,
|
|
31746
|
+
TOKEN.le,
|
|
31747
|
+
TOKEN.and,
|
|
31748
|
+
TOKEN.or,
|
|
31749
|
+
TOKEN.xor,
|
|
31750
|
+
TOKEN.bitshift
|
|
31751
|
+
]);
|
|
31752
|
+
this.#unaryOps = /* @__PURE__ */ new Set([
|
|
31753
|
+
TOKEN.abs,
|
|
31754
|
+
TOKEN.neg,
|
|
31755
|
+
TOKEN.ceiling,
|
|
31756
|
+
TOKEN.floor,
|
|
31757
|
+
TOKEN.round,
|
|
31758
|
+
TOKEN.truncate,
|
|
31759
|
+
TOKEN.sqrt,
|
|
31760
|
+
TOKEN.sin,
|
|
31761
|
+
TOKEN.cos,
|
|
31762
|
+
TOKEN.ln,
|
|
31763
|
+
TOKEN.log,
|
|
31764
|
+
TOKEN.cvi,
|
|
31765
|
+
TOKEN.cvr,
|
|
31766
|
+
TOKEN.not
|
|
31767
|
+
]);
|
|
31768
|
+
this.#idempotentUnary = /* @__PURE__ */ new Set([
|
|
31769
|
+
TOKEN.abs,
|
|
31770
|
+
TOKEN.ceiling,
|
|
31771
|
+
TOKEN.cvi,
|
|
31772
|
+
TOKEN.cvr,
|
|
31773
|
+
TOKEN.floor,
|
|
31774
|
+
TOKEN.round,
|
|
31775
|
+
TOKEN.truncate
|
|
31776
|
+
]);
|
|
31777
|
+
this.#negatedComparison = /* @__PURE__ */ new Map([
|
|
31778
|
+
[TOKEN.eq, TOKEN.ne],
|
|
31779
|
+
[TOKEN.ne, TOKEN.eq],
|
|
31780
|
+
[TOKEN.lt, TOKEN.ge],
|
|
31781
|
+
[TOKEN.le, TOKEN.gt],
|
|
31782
|
+
[TOKEN.gt, TOKEN.le],
|
|
31783
|
+
[TOKEN.ge, TOKEN.lt]
|
|
31784
|
+
]);
|
|
31785
|
+
}
|
|
31786
|
+
/**
|
|
31787
|
+
* @param {PsProgram} program
|
|
31788
|
+
* @param {number} numInputs — number of domain values placed on the stack
|
|
31789
|
+
* before the program runs (i.e. the length of the domain array / 2).
|
|
31790
|
+
* @returns {Array<PsNode>} — one tree node per output value.
|
|
31791
|
+
*/
|
|
31792
|
+
evaluate(program, numInputs) {
|
|
31793
|
+
if (!_PSStackToTree.#binaryOps) {
|
|
31794
|
+
_PSStackToTree.#init();
|
|
31795
|
+
}
|
|
31796
|
+
this._failed = false;
|
|
31797
|
+
if (numInputs > MAX_STACK_SIZE) {
|
|
31798
|
+
return null;
|
|
31799
|
+
}
|
|
31800
|
+
const stack = [];
|
|
31801
|
+
for (let i = 0; i < numInputs; i++) {
|
|
31802
|
+
stack.push(new PsArgNode(i));
|
|
31803
|
+
}
|
|
31804
|
+
this._evalBlock(program.body, stack);
|
|
31805
|
+
if (this._failed) {
|
|
31806
|
+
return null;
|
|
31807
|
+
}
|
|
31808
|
+
_PSStackToTree.#markShared(stack);
|
|
31809
|
+
return stack;
|
|
31810
|
+
}
|
|
31811
|
+
// Set node.shared / sharedCount on non-atomic nodes referenced more than
|
|
31812
|
+
// once. arg/const are excluded — they are cheap to re-emit inline.
|
|
31813
|
+
static #markShared(outputs) {
|
|
31814
|
+
const refCount = /* @__PURE__ */ new Map();
|
|
31815
|
+
const visit = (node) => {
|
|
31816
|
+
if (!node || node.type === PS_NODE.arg || node.type === PS_NODE.const) {
|
|
31817
|
+
return;
|
|
31818
|
+
}
|
|
31819
|
+
const prev = refCount.get(node) ?? 0;
|
|
31820
|
+
refCount.set(node, prev + 1);
|
|
31821
|
+
if (prev > 0) {
|
|
31822
|
+
return;
|
|
31823
|
+
}
|
|
31824
|
+
switch (node.type) {
|
|
31825
|
+
case PS_NODE.unary:
|
|
31826
|
+
visit(node.operand);
|
|
31827
|
+
break;
|
|
31828
|
+
case PS_NODE.binary:
|
|
31829
|
+
visit(node.first);
|
|
31830
|
+
visit(node.second);
|
|
31831
|
+
break;
|
|
31832
|
+
case PS_NODE.ternary:
|
|
31833
|
+
visit(node.cond);
|
|
31834
|
+
visit(node.then);
|
|
31835
|
+
visit(node.otherwise);
|
|
31836
|
+
break;
|
|
31837
|
+
}
|
|
31838
|
+
};
|
|
31839
|
+
for (const output of outputs) {
|
|
31840
|
+
visit(output);
|
|
31841
|
+
}
|
|
31842
|
+
for (const [node, count] of refCount) {
|
|
31843
|
+
if (count > 1) {
|
|
31844
|
+
node.shared = true;
|
|
31845
|
+
node.sharedCount = count;
|
|
31846
|
+
}
|
|
31847
|
+
}
|
|
31848
|
+
}
|
|
31849
|
+
_evalBlock(block, stack) {
|
|
31850
|
+
this._evalBlockFrom(block.instructions, 0, stack);
|
|
31851
|
+
}
|
|
31852
|
+
/**
|
|
31853
|
+
* Core evaluation loop. Processes `instructions[startIdx…]` in order,
|
|
31854
|
+
* mutating `stack` as each instruction executes.
|
|
31855
|
+
*
|
|
31856
|
+
* When a `{ body } if` instruction grows the stack (the PostScript "early
|
|
31857
|
+
* exit / guard" idiom), the remaining instructions in the current array are
|
|
31858
|
+
* evaluated on **both** the true-branch stack and the false-branch stack,
|
|
31859
|
+
* then the two results are merged into PsTernaryNodes. This handles
|
|
31860
|
+
* patterns like:
|
|
31861
|
+
*
|
|
31862
|
+
* cond { pop R G B sentinel } if
|
|
31863
|
+
* … more guards …
|
|
31864
|
+
* sentinel 0 gt { defaultR defaultG defaultB } if
|
|
31865
|
+
*/
|
|
31866
|
+
_evalBlockFrom(instructions, startIdx, stack) {
|
|
31867
|
+
for (let idx = startIdx; idx < instructions.length; idx++) {
|
|
31868
|
+
if (this._failed) {
|
|
31869
|
+
break;
|
|
31870
|
+
}
|
|
31871
|
+
const instr = instructions[idx];
|
|
31872
|
+
switch (instr.type) {
|
|
31873
|
+
case PS_NODE.number:
|
|
31874
|
+
stack.push(new PsConstNode(instr.value));
|
|
31875
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
31876
|
+
this._failed = true;
|
|
31877
|
+
}
|
|
31878
|
+
break;
|
|
31879
|
+
case PS_NODE.operator:
|
|
31880
|
+
this._evalOp(instr.op, stack);
|
|
31881
|
+
break;
|
|
31882
|
+
case PS_NODE.if: {
|
|
31883
|
+
if (stack.length < 1) {
|
|
31884
|
+
this._failed = true;
|
|
31885
|
+
break;
|
|
31886
|
+
}
|
|
31887
|
+
const cond = stack.pop();
|
|
31888
|
+
const saved = stack.slice();
|
|
31889
|
+
this._evalBlock(instr.then, stack);
|
|
31890
|
+
if (this._failed) {
|
|
31891
|
+
break;
|
|
31892
|
+
}
|
|
31893
|
+
if (stack.length === saved.length) {
|
|
31894
|
+
for (let i = 0; i < stack.length; i++) {
|
|
31895
|
+
if (stack[i] !== saved[i]) {
|
|
31896
|
+
stack[i] = this._makeTernary(cond, stack[i], saved[i]);
|
|
31897
|
+
}
|
|
31898
|
+
}
|
|
31899
|
+
} else if (stack.length > saved.length) {
|
|
31900
|
+
if (cond.type === PS_NODE.const) {
|
|
31901
|
+
if (!cond.value) {
|
|
31902
|
+
stack.length = 0;
|
|
31903
|
+
stack.push(...saved);
|
|
31904
|
+
}
|
|
31905
|
+
break;
|
|
31906
|
+
}
|
|
31907
|
+
const trueStack = stack.slice();
|
|
31908
|
+
this._evalBlockFrom(instructions, idx + 1, trueStack);
|
|
31909
|
+
if (this._failed) {
|
|
31910
|
+
break;
|
|
31911
|
+
}
|
|
31912
|
+
const falseStack = saved;
|
|
31913
|
+
this._evalBlockFrom(instructions, idx + 1, falseStack);
|
|
31914
|
+
if (this._failed) {
|
|
31915
|
+
break;
|
|
31916
|
+
}
|
|
31917
|
+
if (trueStack.length !== falseStack.length) {
|
|
31918
|
+
const zero22 = new PsConstNode(0);
|
|
31919
|
+
while (trueStack.length < falseStack.length) {
|
|
31920
|
+
trueStack.push(zero22);
|
|
31921
|
+
}
|
|
31922
|
+
while (falseStack.length < trueStack.length) {
|
|
31923
|
+
falseStack.push(zero22);
|
|
31924
|
+
}
|
|
31925
|
+
}
|
|
31926
|
+
stack.length = 0;
|
|
31927
|
+
for (let i = 0; i < trueStack.length; i++) {
|
|
31928
|
+
stack.push(this._makeTernary(cond, trueStack[i], falseStack[i]));
|
|
31929
|
+
}
|
|
31930
|
+
return;
|
|
31931
|
+
} else {
|
|
31932
|
+
this._failed = true;
|
|
31933
|
+
}
|
|
31934
|
+
break;
|
|
31935
|
+
}
|
|
31936
|
+
case PS_NODE.ifelse: {
|
|
31937
|
+
if (stack.length < 1) {
|
|
31938
|
+
this._failed = true;
|
|
31939
|
+
break;
|
|
31940
|
+
}
|
|
31941
|
+
const cond = stack.pop();
|
|
31942
|
+
const snapshot = stack.slice();
|
|
31943
|
+
const thenStack = snapshot.slice();
|
|
31944
|
+
this._evalBlock(instr.then, thenStack);
|
|
31945
|
+
if (this._failed) {
|
|
31946
|
+
break;
|
|
31947
|
+
}
|
|
31948
|
+
const elseStack = snapshot.slice();
|
|
31949
|
+
this._evalBlock(instr.otherwise, elseStack);
|
|
31950
|
+
if (this._failed) {
|
|
31951
|
+
break;
|
|
31952
|
+
}
|
|
31953
|
+
if (thenStack.length !== elseStack.length) {
|
|
31954
|
+
const zero22 = new PsConstNode(0);
|
|
31955
|
+
while (thenStack.length < elseStack.length) {
|
|
31956
|
+
thenStack.push(zero22);
|
|
31957
|
+
}
|
|
31958
|
+
while (elseStack.length < thenStack.length) {
|
|
31959
|
+
elseStack.push(zero22);
|
|
31960
|
+
}
|
|
31961
|
+
}
|
|
31962
|
+
stack.length = 0;
|
|
31963
|
+
for (let i = 0; i < thenStack.length; i++) {
|
|
31964
|
+
stack.push(this._makeTernary(cond, thenStack[i], elseStack[i]));
|
|
31965
|
+
}
|
|
31966
|
+
break;
|
|
31967
|
+
}
|
|
31968
|
+
}
|
|
31969
|
+
}
|
|
31970
|
+
}
|
|
31971
|
+
_evalOp(op, stack) {
|
|
31972
|
+
if (_PSStackToTree.#binaryOps.has(op)) {
|
|
31973
|
+
if (stack.length < 2) {
|
|
31974
|
+
this._failed = true;
|
|
31975
|
+
return;
|
|
31976
|
+
}
|
|
31977
|
+
const first = stack.pop();
|
|
31978
|
+
const second = stack.pop();
|
|
31979
|
+
stack.push(this._makeBinary(op, first, second));
|
|
31980
|
+
return;
|
|
31981
|
+
}
|
|
31982
|
+
if (_PSStackToTree.#unaryOps.has(op)) {
|
|
31983
|
+
if (stack.length < 1) {
|
|
31984
|
+
this._failed = true;
|
|
31985
|
+
return;
|
|
31986
|
+
}
|
|
31987
|
+
stack.push(this._makeUnary(op, stack.pop()));
|
|
31988
|
+
return;
|
|
31989
|
+
}
|
|
31990
|
+
switch (op) {
|
|
31991
|
+
case TOKEN.true:
|
|
31992
|
+
stack.push(new PsConstNode(true));
|
|
31993
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
31994
|
+
this._failed = true;
|
|
31995
|
+
}
|
|
31996
|
+
break;
|
|
31997
|
+
case TOKEN.false:
|
|
31998
|
+
stack.push(new PsConstNode(false));
|
|
31999
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
32000
|
+
this._failed = true;
|
|
32001
|
+
}
|
|
32002
|
+
break;
|
|
32003
|
+
case TOKEN.dup:
|
|
32004
|
+
if (stack.length < 1) {
|
|
32005
|
+
this._failed = true;
|
|
32006
|
+
break;
|
|
32007
|
+
}
|
|
32008
|
+
stack.push(stack.at(-1));
|
|
32009
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
32010
|
+
this._failed = true;
|
|
32011
|
+
}
|
|
32012
|
+
break;
|
|
32013
|
+
case TOKEN.exch: {
|
|
32014
|
+
if (stack.length < 2) {
|
|
32015
|
+
this._failed = true;
|
|
32016
|
+
break;
|
|
32017
|
+
}
|
|
32018
|
+
const a = stack.pop();
|
|
32019
|
+
const b = stack.pop();
|
|
32020
|
+
stack.push(a, b);
|
|
32021
|
+
break;
|
|
32022
|
+
}
|
|
32023
|
+
case TOKEN.pop:
|
|
32024
|
+
if (stack.length < 1) {
|
|
32025
|
+
this._failed = true;
|
|
32026
|
+
break;
|
|
32027
|
+
}
|
|
32028
|
+
stack.pop();
|
|
32029
|
+
break;
|
|
32030
|
+
case TOKEN.copy: {
|
|
32031
|
+
if (stack.length < 1) {
|
|
32032
|
+
this._failed = true;
|
|
32033
|
+
break;
|
|
32034
|
+
}
|
|
32035
|
+
const nNode = stack.pop();
|
|
32036
|
+
if (nNode.type === PS_NODE.const) {
|
|
32037
|
+
const n = nNode.value | 0;
|
|
32038
|
+
if (n === 0) {
|
|
32039
|
+
} else if (n < 0 || n > stack.length) {
|
|
32040
|
+
this._failed = true;
|
|
32041
|
+
} else {
|
|
32042
|
+
stack.push(...stack.slice(-n));
|
|
32043
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
32044
|
+
this._failed = true;
|
|
32045
|
+
}
|
|
32046
|
+
}
|
|
32047
|
+
} else {
|
|
32048
|
+
this._failed = true;
|
|
32049
|
+
}
|
|
32050
|
+
break;
|
|
32051
|
+
}
|
|
32052
|
+
case TOKEN.index: {
|
|
32053
|
+
if (stack.length < 1) {
|
|
32054
|
+
this._failed = true;
|
|
32055
|
+
break;
|
|
32056
|
+
}
|
|
32057
|
+
const nNode = stack.pop();
|
|
32058
|
+
if (nNode.type === PS_NODE.const) {
|
|
32059
|
+
const n = nNode.value | 0;
|
|
32060
|
+
if (n < 0 || n >= stack.length) {
|
|
32061
|
+
this._failed = true;
|
|
32062
|
+
} else {
|
|
32063
|
+
stack.push(stack.at(-n - 1));
|
|
32064
|
+
}
|
|
32065
|
+
} else {
|
|
32066
|
+
this._failed = true;
|
|
32067
|
+
}
|
|
32068
|
+
break;
|
|
32069
|
+
}
|
|
32070
|
+
case TOKEN.roll: {
|
|
32071
|
+
if (stack.length < 2) {
|
|
32072
|
+
this._failed = true;
|
|
32073
|
+
break;
|
|
32074
|
+
}
|
|
32075
|
+
const jNode = stack.pop();
|
|
32076
|
+
const nNode = stack.pop();
|
|
32077
|
+
if (nNode.type === PS_NODE.const && jNode.type === PS_NODE.const) {
|
|
32078
|
+
const n = nNode.value | 0;
|
|
32079
|
+
if (n === 0) {
|
|
32080
|
+
} else if (n < 0 || n > stack.length) {
|
|
32081
|
+
this._failed = true;
|
|
32082
|
+
} else {
|
|
32083
|
+
const j = ((jNode.value | 0) % n + n) % n;
|
|
32084
|
+
if (j > 0) {
|
|
32085
|
+
const slice = stack.splice(-n, n);
|
|
32086
|
+
stack.push(...slice.slice(n - j), ...slice.slice(0, n - j));
|
|
32087
|
+
}
|
|
32088
|
+
}
|
|
32089
|
+
} else {
|
|
32090
|
+
this._failed = true;
|
|
32091
|
+
}
|
|
32092
|
+
break;
|
|
32093
|
+
}
|
|
32094
|
+
default:
|
|
32095
|
+
this._failed = true;
|
|
32096
|
+
break;
|
|
32097
|
+
}
|
|
32098
|
+
}
|
|
32099
|
+
/**
|
|
32100
|
+
* Create a binary tree node, applying optimizations eagerly:
|
|
32101
|
+
*
|
|
32102
|
+
* 1. Constant folding — both operands are PsConstNode → fold to PsConstNode.
|
|
32103
|
+
* 2. Reflexive simplifications — x−x→0, x xor x→0, x eq x→true, etc.
|
|
32104
|
+
* 3. Algebraic simplifications with one known operand — identity elements
|
|
32105
|
+
* (x+0→x, x*1→x, …), absorbing elements (x*0→0, x and false→false, …),
|
|
32106
|
+
* and strength reductions (x*-1→neg(x), x^0.5→sqrt(x), x^2→x*x, …).
|
|
32107
|
+
*
|
|
32108
|
+
* Recall: `first` was on top of the stack (right operand for non-commutative
|
|
32109
|
+
* ops), `second` was below (left operand). So `a b sub` → second=a, first=b
|
|
32110
|
+
* → a − b.
|
|
32111
|
+
*/
|
|
32112
|
+
_makeBinary(op, first, second) {
|
|
32113
|
+
if (first.type === PS_NODE.const && second.type === PS_NODE.const) {
|
|
32114
|
+
const v = _evalBinaryConst(op, second.value, first.value);
|
|
32115
|
+
if (v !== void 0) {
|
|
32116
|
+
return new PsConstNode(v);
|
|
32117
|
+
}
|
|
32118
|
+
}
|
|
32119
|
+
if (_nodesEqual(first, second)) {
|
|
32120
|
+
switch (op) {
|
|
32121
|
+
case TOKEN.sub:
|
|
32122
|
+
return new PsConstNode(0);
|
|
32123
|
+
// x − x → 0
|
|
32124
|
+
case TOKEN.xor:
|
|
32125
|
+
return new PsConstNode(
|
|
32126
|
+
/* eslint-disable unicorn/prefer-logical-operator-over-ternary */
|
|
32127
|
+
first.valueType === PS_VALUE_TYPE.boolean ? false : 0
|
|
32128
|
+
/* eslint-enable unicorn/prefer-logical-operator-over-ternary */
|
|
32129
|
+
);
|
|
32130
|
+
// TOKEN.mod, TOKEN.div, TOKEN.idiv are NOT simplified here:
|
|
32131
|
+
// x op x is undefined when x = 0, so we cannot fold without knowing
|
|
32132
|
+
// that x is non-zero.
|
|
32133
|
+
case TOKEN.and:
|
|
32134
|
+
case TOKEN.or:
|
|
32135
|
+
return first;
|
|
32136
|
+
// x and x → x; x or x → x
|
|
32137
|
+
case TOKEN.min:
|
|
32138
|
+
case TOKEN.max:
|
|
32139
|
+
return first;
|
|
32140
|
+
// min(x,x) → x; max(x,x) → x
|
|
32141
|
+
case TOKEN.eq:
|
|
32142
|
+
case TOKEN.ge:
|
|
32143
|
+
case TOKEN.le:
|
|
32144
|
+
return new PsConstNode(true);
|
|
32145
|
+
case TOKEN.ne:
|
|
32146
|
+
case TOKEN.gt:
|
|
32147
|
+
case TOKEN.lt:
|
|
32148
|
+
return new PsConstNode(false);
|
|
32149
|
+
}
|
|
32150
|
+
}
|
|
32151
|
+
if (first.type === PS_NODE.const) {
|
|
32152
|
+
const b = first.value;
|
|
32153
|
+
switch (op) {
|
|
32154
|
+
case TOKEN.add:
|
|
32155
|
+
if (b === 0) {
|
|
32156
|
+
return second;
|
|
32157
|
+
}
|
|
32158
|
+
break;
|
|
32159
|
+
case TOKEN.sub:
|
|
32160
|
+
if (b === 0) {
|
|
32161
|
+
return second;
|
|
32162
|
+
}
|
|
32163
|
+
break;
|
|
32164
|
+
case TOKEN.mul:
|
|
32165
|
+
if (b === 1) {
|
|
32166
|
+
return second;
|
|
32167
|
+
}
|
|
32168
|
+
if (b === 0) {
|
|
32169
|
+
return first;
|
|
32170
|
+
}
|
|
32171
|
+
if (b === -1) {
|
|
32172
|
+
return this._makeUnary(TOKEN.neg, second);
|
|
32173
|
+
}
|
|
32174
|
+
break;
|
|
32175
|
+
case TOKEN.div:
|
|
32176
|
+
if (b !== 0) {
|
|
32177
|
+
return this._makeBinary(TOKEN.mul, new PsConstNode(1 / b), second);
|
|
32178
|
+
}
|
|
32179
|
+
break;
|
|
32180
|
+
case TOKEN.idiv:
|
|
32181
|
+
if (b === 1) {
|
|
32182
|
+
return second;
|
|
32183
|
+
}
|
|
32184
|
+
break;
|
|
32185
|
+
case TOKEN.exp:
|
|
32186
|
+
if (b === 1) {
|
|
32187
|
+
return second;
|
|
32188
|
+
}
|
|
32189
|
+
if (b === -1) {
|
|
32190
|
+
return this._makeBinary(TOKEN.div, second, new PsConstNode(1));
|
|
32191
|
+
}
|
|
32192
|
+
if (b === 0.5) {
|
|
32193
|
+
return this._makeUnary(TOKEN.sqrt, second);
|
|
32194
|
+
}
|
|
32195
|
+
if (b === 0.25) {
|
|
32196
|
+
const sqrtOnce = this._makeUnary(TOKEN.sqrt, second);
|
|
32197
|
+
return this._makeUnary(TOKEN.sqrt, sqrtOnce);
|
|
32198
|
+
}
|
|
32199
|
+
if (b === 2) {
|
|
32200
|
+
return this._makeBinary(TOKEN.mul, second, second);
|
|
32201
|
+
}
|
|
32202
|
+
if (b === 3) {
|
|
32203
|
+
return this._makeBinary(
|
|
32204
|
+
TOKEN.mul,
|
|
32205
|
+
this._makeBinary(TOKEN.mul, second, second),
|
|
32206
|
+
second
|
|
32207
|
+
);
|
|
32208
|
+
}
|
|
32209
|
+
if (b === 4) {
|
|
32210
|
+
const square = this._makeBinary(TOKEN.mul, second, second);
|
|
32211
|
+
return this._makeBinary(TOKEN.mul, square, square);
|
|
32212
|
+
}
|
|
32213
|
+
if (b === 0) {
|
|
32214
|
+
return new PsConstNode(1);
|
|
32215
|
+
}
|
|
32216
|
+
break;
|
|
32217
|
+
case TOKEN.and:
|
|
32218
|
+
if (b === true) {
|
|
32219
|
+
return second;
|
|
32220
|
+
}
|
|
32221
|
+
if (b === false) {
|
|
32222
|
+
return first;
|
|
32223
|
+
}
|
|
32224
|
+
break;
|
|
32225
|
+
case TOKEN.or:
|
|
32226
|
+
if (b === false) {
|
|
32227
|
+
return second;
|
|
32228
|
+
}
|
|
32229
|
+
if (b === true) {
|
|
32230
|
+
return first;
|
|
32231
|
+
}
|
|
32232
|
+
break;
|
|
32233
|
+
case TOKEN.min:
|
|
32234
|
+
if (second.type === PS_NODE.binary && second.op === TOKEN.max && second.first.type === PS_NODE.const && second.first.value >= b) {
|
|
32235
|
+
return first;
|
|
32236
|
+
}
|
|
32237
|
+
break;
|
|
32238
|
+
case TOKEN.max:
|
|
32239
|
+
if (second.type === PS_NODE.binary && second.op === TOKEN.min && second.first.type === PS_NODE.const && second.first.value <= b) {
|
|
32240
|
+
return first;
|
|
32241
|
+
}
|
|
32242
|
+
break;
|
|
32243
|
+
}
|
|
32244
|
+
}
|
|
32245
|
+
if (second.type === PS_NODE.const) {
|
|
32246
|
+
const a = second.value;
|
|
32247
|
+
switch (op) {
|
|
32248
|
+
case TOKEN.add:
|
|
32249
|
+
if (a === 0) {
|
|
32250
|
+
return first;
|
|
32251
|
+
}
|
|
32252
|
+
break;
|
|
32253
|
+
case TOKEN.sub:
|
|
32254
|
+
if (a === 0) {
|
|
32255
|
+
return this._makeUnary(TOKEN.neg, first);
|
|
32256
|
+
}
|
|
32257
|
+
break;
|
|
32258
|
+
case TOKEN.mul:
|
|
32259
|
+
if (a === 1) {
|
|
32260
|
+
return first;
|
|
32261
|
+
}
|
|
32262
|
+
if (a === 0) {
|
|
32263
|
+
return second;
|
|
32264
|
+
}
|
|
32265
|
+
if (a === -1) {
|
|
32266
|
+
return this._makeUnary(TOKEN.neg, first);
|
|
32267
|
+
}
|
|
32268
|
+
break;
|
|
32269
|
+
case TOKEN.and:
|
|
32270
|
+
if (a === true) {
|
|
32271
|
+
return first;
|
|
32272
|
+
}
|
|
32273
|
+
if (a === false) {
|
|
32274
|
+
return second;
|
|
32275
|
+
}
|
|
32276
|
+
break;
|
|
32277
|
+
case TOKEN.or:
|
|
32278
|
+
if (a === false) {
|
|
32279
|
+
return first;
|
|
32280
|
+
}
|
|
32281
|
+
if (a === true) {
|
|
32282
|
+
return second;
|
|
32283
|
+
}
|
|
32284
|
+
break;
|
|
32285
|
+
}
|
|
32286
|
+
}
|
|
32287
|
+
return new PsBinaryNode(
|
|
32288
|
+
op,
|
|
32289
|
+
first,
|
|
32290
|
+
second,
|
|
32291
|
+
_binaryValueType(op, first.valueType, second.valueType)
|
|
32292
|
+
);
|
|
32293
|
+
}
|
|
32294
|
+
/**
|
|
32295
|
+
* Create a unary tree node, applying optimizations eagerly:
|
|
32296
|
+
*
|
|
32297
|
+
* 1. Constant folding.
|
|
32298
|
+
* 2. not(comparison) → negated comparison: not(a eq b) → a ne b, etc.
|
|
32299
|
+
* 3. neg(a − b) → b − a.
|
|
32300
|
+
* 4. Double-negation: neg(neg(x)) → x, not(not(x)) → x.
|
|
32301
|
+
* 5. abs(neg(x)) → abs(x).
|
|
32302
|
+
* 6. Idempotent: f(f(x)) → f(x) for abs, ceiling, floor, round, etc.
|
|
32303
|
+
*/
|
|
32304
|
+
_makeUnary(op, operand) {
|
|
32305
|
+
if (operand.type === PS_NODE.const) {
|
|
32306
|
+
const v = _evalUnaryConst(op, operand.value);
|
|
32307
|
+
if (v !== void 0) {
|
|
32308
|
+
return new PsConstNode(v);
|
|
32309
|
+
}
|
|
32310
|
+
}
|
|
32311
|
+
if (op === TOKEN.not && operand.type === PS_NODE.binary) {
|
|
32312
|
+
const negated = _PSStackToTree.#negatedComparison.get(operand.op);
|
|
32313
|
+
if (negated !== void 0) {
|
|
32314
|
+
return new PsBinaryNode(
|
|
32315
|
+
negated,
|
|
32316
|
+
operand.first,
|
|
32317
|
+
operand.second,
|
|
32318
|
+
PS_VALUE_TYPE.boolean
|
|
32319
|
+
);
|
|
32320
|
+
}
|
|
32321
|
+
}
|
|
32322
|
+
if (op === TOKEN.neg && operand.type === PS_NODE.binary && operand.op === TOKEN.sub) {
|
|
32323
|
+
return this._makeBinary(TOKEN.sub, operand.second, operand.first);
|
|
32324
|
+
}
|
|
32325
|
+
if (operand.type === PS_NODE.unary) {
|
|
32326
|
+
if (op === TOKEN.neg && operand.op === TOKEN.neg || op === TOKEN.not && operand.op === TOKEN.not) {
|
|
32327
|
+
return operand.operand;
|
|
32328
|
+
}
|
|
32329
|
+
if (op === TOKEN.abs && operand.op === TOKEN.neg) {
|
|
32330
|
+
return this._makeUnary(TOKEN.abs, operand.operand);
|
|
32331
|
+
}
|
|
32332
|
+
if (_PSStackToTree.#idempotentUnary.has(op) && op === operand.op) {
|
|
32333
|
+
return operand;
|
|
32334
|
+
}
|
|
32335
|
+
}
|
|
32336
|
+
return new PsUnaryNode(op, operand, _unaryValueType(op, operand.valueType));
|
|
32337
|
+
}
|
|
32338
|
+
/**
|
|
32339
|
+
* Create a ternary node, applying optimizations eagerly:
|
|
32340
|
+
*
|
|
32341
|
+
* 1. Constant condition — fold to the live branch.
|
|
32342
|
+
* 2. Identical branches — the condition is irrelevant, return either branch.
|
|
32343
|
+
* 3. Boolean branch constants — `cond ? true : false` → cond,
|
|
32344
|
+
* `cond ? false : true` → not(cond).
|
|
32345
|
+
* 4. Ternary → branchless min/max when the condition compares two numeric
|
|
32346
|
+
* expressions that are also the two branches.
|
|
32347
|
+
*/
|
|
32348
|
+
_makeTernary(cond, then, otherwise) {
|
|
32349
|
+
if (cond.type === PS_NODE.const) {
|
|
32350
|
+
return cond.value ? then : otherwise;
|
|
32351
|
+
}
|
|
32352
|
+
if (_nodesEqual(then, otherwise)) {
|
|
32353
|
+
return then;
|
|
32354
|
+
}
|
|
32355
|
+
if (then.type === PS_NODE.const && otherwise.type === PS_NODE.const) {
|
|
32356
|
+
if (then.value === true && otherwise.value === false) {
|
|
32357
|
+
return cond;
|
|
32358
|
+
}
|
|
32359
|
+
if (then.value === false && otherwise.value === true) {
|
|
32360
|
+
return this._makeUnary(TOKEN.not, cond);
|
|
32361
|
+
}
|
|
32362
|
+
}
|
|
32363
|
+
if (cond.type === PS_NODE.binary) {
|
|
32364
|
+
const { op: cop, first: cf, second: cs } = cond;
|
|
32365
|
+
if (cop === TOKEN.gt || cop === TOKEN.ge) {
|
|
32366
|
+
if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
|
|
32367
|
+
return this._makeBinary(TOKEN.min, cf, cs);
|
|
32368
|
+
}
|
|
32369
|
+
if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
|
|
32370
|
+
return this._makeBinary(TOKEN.max, cf, cs);
|
|
32371
|
+
}
|
|
32372
|
+
} else if (cop === TOKEN.lt || cop === TOKEN.le) {
|
|
32373
|
+
if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
|
|
32374
|
+
return this._makeBinary(TOKEN.max, cf, cs);
|
|
32375
|
+
}
|
|
32376
|
+
if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
|
|
32377
|
+
return this._makeBinary(TOKEN.min, cf, cs);
|
|
32378
|
+
}
|
|
32379
|
+
}
|
|
32380
|
+
}
|
|
32381
|
+
return new PsTernaryNode(
|
|
32382
|
+
cond,
|
|
32383
|
+
then,
|
|
32384
|
+
otherwise,
|
|
32385
|
+
then.valueType === otherwise.valueType ? then.valueType : PS_VALUE_TYPE.unknown
|
|
32386
|
+
);
|
|
32387
|
+
}
|
|
32388
|
+
};
|
|
32389
|
+
var OP = {
|
|
32390
|
+
ARG: 0,
|
|
32391
|
+
// [ARG, idx]
|
|
32392
|
+
CONST: 1,
|
|
32393
|
+
// [CONST, val]
|
|
32394
|
+
STORE: 2,
|
|
32395
|
+
// [STORE, slot, min, max] clamp(pop()) → mem[slot]
|
|
32396
|
+
IF: 3,
|
|
32397
|
+
// [IF, target] jump when top-of-stack === 0
|
|
32398
|
+
JUMP: 4,
|
|
32399
|
+
// [JUMP, target] unconditional
|
|
32400
|
+
ABS: 5,
|
|
32401
|
+
NEG: 6,
|
|
32402
|
+
CEIL: 7,
|
|
32403
|
+
FLOOR: 8,
|
|
32404
|
+
ROUND: 9,
|
|
32405
|
+
// floor(x + 0.5)
|
|
32406
|
+
TRUNC: 10,
|
|
32407
|
+
NOT_B: 11,
|
|
32408
|
+
// boolean NOT
|
|
32409
|
+
NOT_N: 12,
|
|
32410
|
+
// bitwise NOT
|
|
32411
|
+
SQRT: 13,
|
|
32412
|
+
SIN: 14,
|
|
32413
|
+
// degrees in/out
|
|
32414
|
+
COS: 15,
|
|
32415
|
+
LN: 16,
|
|
32416
|
+
LOG10: 17,
|
|
32417
|
+
CVI: 18,
|
|
32418
|
+
SHIFT: 19,
|
|
32419
|
+
// [SHIFT, amount] +ve = left, −ve = right
|
|
32420
|
+
// Binary ops: second below, first on top; result = second OP first.
|
|
32421
|
+
ADD: 20,
|
|
32422
|
+
SUB: 21,
|
|
32423
|
+
MUL: 22,
|
|
32424
|
+
DIV: 23,
|
|
32425
|
+
// 0 when divisor is 0
|
|
32426
|
+
IDIV: 24,
|
|
32427
|
+
// 0 when divisor is 0
|
|
32428
|
+
MOD: 25,
|
|
32429
|
+
// 0 when divisor is 0
|
|
32430
|
+
POW: 26,
|
|
32431
|
+
EQ: 27,
|
|
32432
|
+
NE: 28,
|
|
32433
|
+
GT: 29,
|
|
32434
|
+
GE: 30,
|
|
32435
|
+
LT: 31,
|
|
32436
|
+
LE: 32,
|
|
32437
|
+
AND: 33,
|
|
32438
|
+
OR: 34,
|
|
32439
|
+
XOR: 35,
|
|
32440
|
+
ATAN: 36,
|
|
32441
|
+
// atan2(second, first) → degrees [0, 360)
|
|
32442
|
+
MIN: 37,
|
|
32443
|
+
MAX: 38,
|
|
32444
|
+
TEE_TMP: 39,
|
|
32445
|
+
// [TEE_TMP, slot] peek top of stack → tmp[slot], leave on stack
|
|
32446
|
+
LOAD_TMP: 40
|
|
32447
|
+
// [LOAD_TMP, slot] push tmp[slot]
|
|
32448
|
+
};
|
|
32449
|
+
var _DEG_TO_RAD = Math.PI / 180;
|
|
32450
|
+
var _RAD_TO_DEG = 180 / Math.PI;
|
|
32451
|
+
var PsJsCompiler = class {
|
|
32452
|
+
// Safe because JS is single-threaded.
|
|
32453
|
+
static #stack = new Float64Array(64);
|
|
32454
|
+
static #tmp = new Float64Array(64);
|
|
32455
|
+
constructor(domain, range) {
|
|
32456
|
+
this.nIn = domain.length >> 1;
|
|
32457
|
+
this.nOut = range.length >> 1;
|
|
32458
|
+
this.range = range;
|
|
32459
|
+
this.ir = [];
|
|
32460
|
+
this._tmpMap = /* @__PURE__ */ new Map();
|
|
32461
|
+
this._nextTmp = 0;
|
|
32462
|
+
}
|
|
32463
|
+
_compileNode(node) {
|
|
32464
|
+
if (node.shared) {
|
|
32465
|
+
const cached = this._tmpMap.get(node);
|
|
32466
|
+
if (cached !== void 0) {
|
|
32467
|
+
this.ir.push(OP.LOAD_TMP, cached);
|
|
32468
|
+
return true;
|
|
32469
|
+
}
|
|
32470
|
+
if (!this._compileNodeImpl(node)) {
|
|
32471
|
+
return false;
|
|
32472
|
+
}
|
|
32473
|
+
const slot = this._nextTmp++;
|
|
32474
|
+
this._tmpMap.set(node, slot);
|
|
32475
|
+
this.ir.push(OP.TEE_TMP, slot);
|
|
32476
|
+
return true;
|
|
32477
|
+
}
|
|
32478
|
+
return this._compileNodeImpl(node);
|
|
32479
|
+
}
|
|
32480
|
+
_compileNodeImpl(node) {
|
|
32481
|
+
switch (node.type) {
|
|
32482
|
+
case PS_NODE.arg:
|
|
32483
|
+
this.ir.push(OP.ARG, node.index);
|
|
32484
|
+
return true;
|
|
32485
|
+
case PS_NODE.const: {
|
|
32486
|
+
const v = node.value;
|
|
32487
|
+
this.ir.push(OP.CONST, typeof v === "boolean" ? Number(v) : v);
|
|
32488
|
+
return true;
|
|
32489
|
+
}
|
|
32490
|
+
case PS_NODE.unary:
|
|
32491
|
+
return this._compileUnary(node);
|
|
32492
|
+
case PS_NODE.binary:
|
|
32493
|
+
return this._compileBinary(node);
|
|
32494
|
+
case PS_NODE.ternary:
|
|
32495
|
+
return this._compileTernary(node);
|
|
32496
|
+
default:
|
|
32497
|
+
return false;
|
|
32498
|
+
}
|
|
32499
|
+
}
|
|
32500
|
+
_compileUnary(node) {
|
|
32501
|
+
const { op, operand, valueType } = node;
|
|
32502
|
+
if (op === TOKEN.cvr) {
|
|
32503
|
+
return this._compileNode(operand);
|
|
32504
|
+
}
|
|
32505
|
+
if (!this._compileNode(operand)) {
|
|
32506
|
+
return false;
|
|
32507
|
+
}
|
|
32508
|
+
switch (op) {
|
|
32509
|
+
case TOKEN.abs:
|
|
32510
|
+
this.ir.push(OP.ABS);
|
|
32511
|
+
break;
|
|
32512
|
+
case TOKEN.neg:
|
|
32513
|
+
this.ir.push(OP.NEG);
|
|
32514
|
+
break;
|
|
32515
|
+
case TOKEN.ceiling:
|
|
32516
|
+
this.ir.push(OP.CEIL);
|
|
32517
|
+
break;
|
|
32518
|
+
case TOKEN.floor:
|
|
32519
|
+
this.ir.push(OP.FLOOR);
|
|
32520
|
+
break;
|
|
32521
|
+
case TOKEN.round:
|
|
32522
|
+
this.ir.push(OP.ROUND);
|
|
32523
|
+
break;
|
|
32524
|
+
case TOKEN.truncate:
|
|
32525
|
+
this.ir.push(OP.TRUNC);
|
|
32526
|
+
break;
|
|
32527
|
+
case TOKEN.sqrt:
|
|
32528
|
+
this.ir.push(OP.SQRT);
|
|
32529
|
+
break;
|
|
32530
|
+
case TOKEN.sin:
|
|
32531
|
+
this.ir.push(OP.SIN);
|
|
32532
|
+
break;
|
|
32533
|
+
case TOKEN.cos:
|
|
32534
|
+
this.ir.push(OP.COS);
|
|
32535
|
+
break;
|
|
32536
|
+
case TOKEN.ln:
|
|
32537
|
+
this.ir.push(OP.LN);
|
|
32538
|
+
break;
|
|
32539
|
+
case TOKEN.log:
|
|
32540
|
+
this.ir.push(OP.LOG10);
|
|
32541
|
+
break;
|
|
32542
|
+
case TOKEN.cvi:
|
|
32543
|
+
this.ir.push(OP.CVI);
|
|
32544
|
+
break;
|
|
32545
|
+
case TOKEN.not:
|
|
32546
|
+
if (valueType === PS_VALUE_TYPE.boolean) {
|
|
32547
|
+
this.ir.push(OP.NOT_B);
|
|
32548
|
+
} else if (valueType === PS_VALUE_TYPE.numeric) {
|
|
32549
|
+
this.ir.push(OP.NOT_N);
|
|
32550
|
+
} else {
|
|
32551
|
+
return false;
|
|
32552
|
+
}
|
|
32553
|
+
break;
|
|
32554
|
+
default:
|
|
32555
|
+
return false;
|
|
32556
|
+
}
|
|
32557
|
+
return true;
|
|
32558
|
+
}
|
|
32559
|
+
_compileBinary(node) {
|
|
32560
|
+
const { op, first, second } = node;
|
|
32561
|
+
if (op === TOKEN.bitshift) {
|
|
32562
|
+
if (first.type !== PS_NODE.const || !Number.isInteger(first.value) || !this._compileNode(second)) {
|
|
32563
|
+
return false;
|
|
32564
|
+
}
|
|
32565
|
+
this.ir.push(OP.SHIFT, first.value);
|
|
32566
|
+
return true;
|
|
32567
|
+
}
|
|
32568
|
+
if (!this._compileNode(second) || !this._compileNode(first)) {
|
|
32569
|
+
return false;
|
|
32570
|
+
}
|
|
32571
|
+
switch (op) {
|
|
32572
|
+
case TOKEN.add:
|
|
32573
|
+
this.ir.push(OP.ADD);
|
|
32574
|
+
break;
|
|
32575
|
+
case TOKEN.sub:
|
|
32576
|
+
this.ir.push(OP.SUB);
|
|
32577
|
+
break;
|
|
32578
|
+
case TOKEN.mul:
|
|
32579
|
+
this.ir.push(OP.MUL);
|
|
32580
|
+
break;
|
|
32581
|
+
case TOKEN.div:
|
|
32582
|
+
this.ir.push(OP.DIV);
|
|
32583
|
+
break;
|
|
32584
|
+
case TOKEN.idiv:
|
|
32585
|
+
this.ir.push(OP.IDIV);
|
|
32586
|
+
break;
|
|
32587
|
+
case TOKEN.mod:
|
|
32588
|
+
this.ir.push(OP.MOD);
|
|
32589
|
+
break;
|
|
32590
|
+
case TOKEN.exp:
|
|
32591
|
+
this.ir.push(OP.POW);
|
|
32592
|
+
break;
|
|
32593
|
+
case TOKEN.eq:
|
|
32594
|
+
this.ir.push(OP.EQ);
|
|
32595
|
+
break;
|
|
32596
|
+
case TOKEN.ne:
|
|
32597
|
+
this.ir.push(OP.NE);
|
|
32598
|
+
break;
|
|
32599
|
+
case TOKEN.gt:
|
|
32600
|
+
this.ir.push(OP.GT);
|
|
32601
|
+
break;
|
|
32602
|
+
case TOKEN.ge:
|
|
32603
|
+
this.ir.push(OP.GE);
|
|
32604
|
+
break;
|
|
32605
|
+
case TOKEN.lt:
|
|
32606
|
+
this.ir.push(OP.LT);
|
|
32607
|
+
break;
|
|
32608
|
+
case TOKEN.le:
|
|
32609
|
+
this.ir.push(OP.LE);
|
|
32610
|
+
break;
|
|
32611
|
+
case TOKEN.and:
|
|
32612
|
+
this.ir.push(OP.AND);
|
|
32613
|
+
break;
|
|
32614
|
+
case TOKEN.or:
|
|
32615
|
+
this.ir.push(OP.OR);
|
|
32616
|
+
break;
|
|
32617
|
+
case TOKEN.xor:
|
|
32618
|
+
this.ir.push(OP.XOR);
|
|
32619
|
+
break;
|
|
32620
|
+
case TOKEN.atan:
|
|
32621
|
+
this.ir.push(OP.ATAN);
|
|
32622
|
+
break;
|
|
32623
|
+
case TOKEN.min:
|
|
32624
|
+
this.ir.push(OP.MIN);
|
|
32625
|
+
break;
|
|
32626
|
+
case TOKEN.max:
|
|
32627
|
+
this.ir.push(OP.MAX);
|
|
32628
|
+
break;
|
|
32629
|
+
default:
|
|
32630
|
+
return false;
|
|
32631
|
+
}
|
|
32632
|
+
return true;
|
|
32633
|
+
}
|
|
32634
|
+
_compileTernary(node) {
|
|
32635
|
+
if (!this._compileNode(node.cond)) {
|
|
32636
|
+
return false;
|
|
32637
|
+
}
|
|
32638
|
+
this.ir.push(OP.IF, 0);
|
|
32639
|
+
const ifPatch = this.ir.length - 1;
|
|
32640
|
+
if (!this._compileNode(node.then)) {
|
|
32641
|
+
return false;
|
|
32642
|
+
}
|
|
32643
|
+
this.ir.push(OP.JUMP, 0);
|
|
32644
|
+
const jumpPatch = this.ir.length - 1;
|
|
32645
|
+
this.ir[ifPatch] = this.ir.length;
|
|
32646
|
+
if (!this._compileNode(node.otherwise)) {
|
|
32647
|
+
return false;
|
|
32648
|
+
}
|
|
32649
|
+
this.ir[jumpPatch] = this.ir.length;
|
|
32650
|
+
return true;
|
|
32651
|
+
}
|
|
32652
|
+
compile(program) {
|
|
32653
|
+
const outputs = new PSStackToTree().evaluate(program, this.nIn);
|
|
32654
|
+
if (!outputs || outputs.length < this.nOut) {
|
|
32655
|
+
return null;
|
|
32656
|
+
}
|
|
32657
|
+
for (let i = 0; i < this.nOut; i++) {
|
|
32658
|
+
if (!this._compileNode(outputs[i])) {
|
|
32659
|
+
return null;
|
|
32660
|
+
}
|
|
32661
|
+
const min = this.range[i * 2];
|
|
32662
|
+
const max = this.range[i * 2 + 1];
|
|
32663
|
+
this.ir.push(OP.STORE, i, min, max);
|
|
32664
|
+
}
|
|
32665
|
+
return new Float64Array(this.ir);
|
|
32666
|
+
}
|
|
32667
|
+
static execute(ir, src, srcOffset, dest, destOffset) {
|
|
32668
|
+
let ip = 0, sp = 0;
|
|
32669
|
+
const n = ir.length;
|
|
32670
|
+
const stack = this.#stack;
|
|
32671
|
+
const tmp = this.#tmp;
|
|
32672
|
+
while (ip < n) {
|
|
32673
|
+
switch (ir[ip++] | 0) {
|
|
32674
|
+
case OP.ARG:
|
|
32675
|
+
stack[sp++] = src[srcOffset + (ir[ip++] | 0)];
|
|
32676
|
+
break;
|
|
32677
|
+
case OP.CONST:
|
|
32678
|
+
stack[sp++] = ir[ip++];
|
|
32679
|
+
break;
|
|
32680
|
+
case OP.STORE: {
|
|
32681
|
+
const slot = ir[ip++] | 0;
|
|
32682
|
+
const min = ir[ip++];
|
|
32683
|
+
const max = ir[ip++];
|
|
32684
|
+
dest[destOffset + slot] = MathClamp(stack[--sp], min, max);
|
|
32685
|
+
break;
|
|
32686
|
+
}
|
|
32687
|
+
case OP.IF: {
|
|
32688
|
+
const tgt = ir[ip++];
|
|
32689
|
+
if (stack[--sp] === 0) {
|
|
32690
|
+
ip = tgt;
|
|
32691
|
+
}
|
|
32692
|
+
break;
|
|
32693
|
+
}
|
|
32694
|
+
case OP.JUMP:
|
|
32695
|
+
ip = ir[ip];
|
|
32696
|
+
break;
|
|
32697
|
+
case OP.ABS:
|
|
32698
|
+
stack[sp - 1] = Math.abs(stack[sp - 1]);
|
|
32699
|
+
break;
|
|
32700
|
+
case OP.NEG:
|
|
32701
|
+
stack[sp - 1] = -stack[sp - 1];
|
|
32702
|
+
break;
|
|
32703
|
+
case OP.CEIL:
|
|
32704
|
+
stack[sp - 1] = Math.ceil(stack[sp - 1]);
|
|
32705
|
+
break;
|
|
32706
|
+
case OP.FLOOR:
|
|
32707
|
+
stack[sp - 1] = Math.floor(stack[sp - 1]);
|
|
32708
|
+
break;
|
|
32709
|
+
case OP.ROUND:
|
|
32710
|
+
stack[sp - 1] = Math.floor(stack[sp - 1] + 0.5);
|
|
32711
|
+
break;
|
|
32712
|
+
case OP.TRUNC:
|
|
32713
|
+
stack[sp - 1] = Math.trunc(stack[sp - 1]);
|
|
32714
|
+
break;
|
|
32715
|
+
case OP.NOT_B:
|
|
32716
|
+
stack[sp - 1] = stack[sp - 1] !== 0 ? 0 : 1;
|
|
32717
|
+
break;
|
|
32718
|
+
case OP.NOT_N:
|
|
32719
|
+
stack[sp - 1] = ~(stack[sp - 1] | 0);
|
|
32720
|
+
break;
|
|
32721
|
+
case OP.SQRT:
|
|
32722
|
+
stack[sp - 1] = Math.sqrt(stack[sp - 1]);
|
|
32723
|
+
break;
|
|
32724
|
+
case OP.SIN:
|
|
32725
|
+
stack[sp - 1] = Math.sin(stack[sp - 1] % 360 * _DEG_TO_RAD);
|
|
32726
|
+
break;
|
|
32727
|
+
case OP.COS:
|
|
32728
|
+
stack[sp - 1] = Math.cos(stack[sp - 1] % 360 * _DEG_TO_RAD);
|
|
32729
|
+
break;
|
|
32730
|
+
case OP.LN:
|
|
32731
|
+
stack[sp - 1] = Math.log(stack[sp - 1]);
|
|
32732
|
+
break;
|
|
32733
|
+
case OP.LOG10:
|
|
32734
|
+
stack[sp - 1] = Math.log10(stack[sp - 1]);
|
|
32735
|
+
break;
|
|
32736
|
+
case OP.CVI:
|
|
32737
|
+
stack[sp - 1] = Math.trunc(stack[sp - 1]) | 0;
|
|
32738
|
+
break;
|
|
32739
|
+
case OP.SHIFT: {
|
|
32740
|
+
const amt = ir[ip++];
|
|
32741
|
+
const v = stack[sp - 1] | 0;
|
|
32742
|
+
if (amt > 0) {
|
|
32743
|
+
stack[sp - 1] = v << amt;
|
|
32744
|
+
} else if (amt < 0) {
|
|
32745
|
+
stack[sp - 1] = v >> -amt;
|
|
32746
|
+
} else {
|
|
32747
|
+
stack[sp - 1] = v;
|
|
32748
|
+
}
|
|
32749
|
+
break;
|
|
32750
|
+
}
|
|
32751
|
+
case OP.ADD: {
|
|
32752
|
+
const b = stack[--sp];
|
|
32753
|
+
stack[sp - 1] += b;
|
|
32754
|
+
break;
|
|
32755
|
+
}
|
|
32756
|
+
case OP.SUB: {
|
|
32757
|
+
const b = stack[--sp];
|
|
32758
|
+
stack[sp - 1] -= b;
|
|
32759
|
+
break;
|
|
32760
|
+
}
|
|
32761
|
+
case OP.MUL: {
|
|
32762
|
+
const b = stack[--sp];
|
|
32763
|
+
stack[sp - 1] *= b;
|
|
32764
|
+
break;
|
|
32765
|
+
}
|
|
32766
|
+
case OP.DIV: {
|
|
32767
|
+
const b = stack[--sp];
|
|
32768
|
+
stack[sp - 1] = b !== 0 ? stack[sp - 1] / b : 0;
|
|
32769
|
+
break;
|
|
32770
|
+
}
|
|
32771
|
+
case OP.IDIV: {
|
|
32772
|
+
const b = stack[--sp];
|
|
32773
|
+
stack[sp - 1] = b !== 0 ? Math.trunc(stack[sp - 1] / b) : 0;
|
|
32774
|
+
break;
|
|
32775
|
+
}
|
|
32776
|
+
case OP.MOD: {
|
|
32777
|
+
const b = stack[--sp];
|
|
32778
|
+
stack[sp - 1] = b !== 0 ? stack[sp - 1] % b : 0;
|
|
32779
|
+
break;
|
|
32780
|
+
}
|
|
32781
|
+
case OP.POW: {
|
|
32782
|
+
const b = stack[--sp];
|
|
32783
|
+
stack[sp - 1] **= b;
|
|
32784
|
+
break;
|
|
32785
|
+
}
|
|
32786
|
+
case OP.EQ: {
|
|
32787
|
+
const b = stack[--sp];
|
|
32788
|
+
stack[sp - 1] = stack[sp - 1] === b ? 1 : 0;
|
|
32789
|
+
break;
|
|
32790
|
+
}
|
|
32791
|
+
case OP.NE: {
|
|
32792
|
+
const b = stack[--sp];
|
|
32793
|
+
stack[sp - 1] = stack[sp - 1] !== b ? 1 : 0;
|
|
32794
|
+
break;
|
|
32795
|
+
}
|
|
32796
|
+
case OP.GT: {
|
|
32797
|
+
const b = stack[--sp];
|
|
32798
|
+
stack[sp - 1] = stack[sp - 1] > b ? 1 : 0;
|
|
32799
|
+
break;
|
|
32800
|
+
}
|
|
32801
|
+
case OP.GE: {
|
|
32802
|
+
const b = stack[--sp];
|
|
32803
|
+
stack[sp - 1] = stack[sp - 1] >= b ? 1 : 0;
|
|
32804
|
+
break;
|
|
32805
|
+
}
|
|
32806
|
+
case OP.LT: {
|
|
32807
|
+
const b = stack[--sp];
|
|
32808
|
+
stack[sp - 1] = stack[sp - 1] < b ? 1 : 0;
|
|
32809
|
+
break;
|
|
32810
|
+
}
|
|
32811
|
+
case OP.LE: {
|
|
32812
|
+
const b = stack[--sp];
|
|
32813
|
+
stack[sp - 1] = stack[sp - 1] <= b ? 1 : 0;
|
|
32814
|
+
break;
|
|
32815
|
+
}
|
|
32816
|
+
case OP.AND: {
|
|
32817
|
+
const b = stack[--sp] | 0;
|
|
32818
|
+
stack[sp - 1] = (stack[sp - 1] | 0) & b;
|
|
32819
|
+
break;
|
|
32820
|
+
}
|
|
32821
|
+
case OP.OR: {
|
|
32822
|
+
const b = stack[--sp] | 0;
|
|
32823
|
+
stack[sp - 1] = stack[sp - 1] | 0 | b;
|
|
32824
|
+
break;
|
|
32825
|
+
}
|
|
32826
|
+
case OP.XOR: {
|
|
32827
|
+
const b = stack[--sp] | 0;
|
|
32828
|
+
stack[sp - 1] = (stack[sp - 1] | 0) ^ b;
|
|
32829
|
+
break;
|
|
32830
|
+
}
|
|
32831
|
+
case OP.ATAN: {
|
|
32832
|
+
const b = stack[--sp];
|
|
32833
|
+
const deg = Math.atan2(stack[sp - 1], b) * _RAD_TO_DEG;
|
|
32834
|
+
stack[sp - 1] = deg < 0 ? deg + 360 : deg;
|
|
32835
|
+
break;
|
|
32836
|
+
}
|
|
32837
|
+
case OP.MIN: {
|
|
32838
|
+
const b = stack[--sp];
|
|
32839
|
+
stack[sp - 1] = Math.min(stack[sp - 1], b);
|
|
32840
|
+
break;
|
|
32841
|
+
}
|
|
32842
|
+
case OP.MAX: {
|
|
32843
|
+
const b = stack[--sp];
|
|
32844
|
+
stack[sp - 1] = Math.max(stack[sp - 1], b);
|
|
32845
|
+
break;
|
|
32846
|
+
}
|
|
32847
|
+
case OP.TEE_TMP:
|
|
32848
|
+
tmp[ir[ip++] | 0] = stack[sp - 1];
|
|
32849
|
+
break;
|
|
32850
|
+
case OP.LOAD_TMP:
|
|
32851
|
+
stack[sp++] = tmp[ir[ip++] | 0];
|
|
32852
|
+
break;
|
|
32853
|
+
}
|
|
32854
|
+
}
|
|
32855
|
+
}
|
|
32856
|
+
};
|
|
32857
|
+
var PSStackBasedInterpreter = class {
|
|
32858
|
+
// Safe: JS is single-threaded.
|
|
32859
|
+
static #stack = new Float64Array(100);
|
|
32860
|
+
static #sp = 0;
|
|
32861
|
+
static #push(v) {
|
|
32862
|
+
if (this.#sp < this.#stack.length) {
|
|
32863
|
+
this.#stack[this.#sp++] = v;
|
|
32864
|
+
}
|
|
32865
|
+
}
|
|
32866
|
+
static #execOp(op) {
|
|
32867
|
+
const stack = this.#stack;
|
|
32868
|
+
switch (op) {
|
|
32869
|
+
case TOKEN.true:
|
|
32870
|
+
this.#push(1);
|
|
32871
|
+
break;
|
|
32872
|
+
case TOKEN.false:
|
|
32873
|
+
this.#push(0);
|
|
32874
|
+
break;
|
|
32875
|
+
case TOKEN.abs:
|
|
32876
|
+
stack[this.#sp - 1] = Math.abs(stack[this.#sp - 1]);
|
|
32877
|
+
break;
|
|
32878
|
+
case TOKEN.neg:
|
|
32879
|
+
stack[this.#sp - 1] = -stack[this.#sp - 1];
|
|
32880
|
+
break;
|
|
32881
|
+
case TOKEN.ceiling:
|
|
32882
|
+
stack[this.#sp - 1] = Math.ceil(stack[this.#sp - 1]);
|
|
32883
|
+
break;
|
|
32884
|
+
case TOKEN.floor:
|
|
32885
|
+
stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1]);
|
|
32886
|
+
break;
|
|
32887
|
+
case TOKEN.round:
|
|
32888
|
+
stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1] + 0.5);
|
|
32889
|
+
break;
|
|
32890
|
+
case TOKEN.truncate:
|
|
32891
|
+
stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]);
|
|
32892
|
+
break;
|
|
32893
|
+
case TOKEN.sqrt:
|
|
32894
|
+
stack[this.#sp - 1] = Math.sqrt(stack[this.#sp - 1]);
|
|
32895
|
+
break;
|
|
32896
|
+
case TOKEN.sin:
|
|
32897
|
+
stack[this.#sp - 1] = Math.sin(
|
|
32898
|
+
stack[this.#sp - 1] % 360 * _DEG_TO_RAD
|
|
32899
|
+
);
|
|
32900
|
+
break;
|
|
32901
|
+
case TOKEN.cos:
|
|
32902
|
+
stack[this.#sp - 1] = Math.cos(
|
|
32903
|
+
stack[this.#sp - 1] % 360 * _DEG_TO_RAD
|
|
32904
|
+
);
|
|
32905
|
+
break;
|
|
32906
|
+
case TOKEN.ln:
|
|
32907
|
+
stack[this.#sp - 1] = Math.log(stack[this.#sp - 1]);
|
|
32908
|
+
break;
|
|
32909
|
+
case TOKEN.log:
|
|
32910
|
+
stack[this.#sp - 1] = Math.log10(stack[this.#sp - 1]);
|
|
32911
|
+
break;
|
|
32912
|
+
case TOKEN.cvi:
|
|
32913
|
+
stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]) | 0;
|
|
32914
|
+
break;
|
|
32915
|
+
case TOKEN.cvr:
|
|
32916
|
+
break;
|
|
32917
|
+
// values are already f64
|
|
32918
|
+
case TOKEN.not: {
|
|
32919
|
+
const v = stack[this.#sp - 1];
|
|
32920
|
+
stack[this.#sp - 1] = v === 0 || v === 1 ? 1 - v : ~(v | 0);
|
|
32921
|
+
break;
|
|
32922
|
+
}
|
|
32923
|
+
case TOKEN.add: {
|
|
32924
|
+
const b = stack[--this.#sp];
|
|
32925
|
+
stack[this.#sp - 1] += b;
|
|
32926
|
+
break;
|
|
32927
|
+
}
|
|
32928
|
+
case TOKEN.sub: {
|
|
32929
|
+
const b = stack[--this.#sp];
|
|
32930
|
+
stack[this.#sp - 1] -= b;
|
|
32931
|
+
break;
|
|
32932
|
+
}
|
|
32933
|
+
case TOKEN.mul: {
|
|
32934
|
+
const b = stack[--this.#sp];
|
|
32935
|
+
stack[this.#sp - 1] *= b;
|
|
32936
|
+
break;
|
|
32937
|
+
}
|
|
32938
|
+
case TOKEN.div: {
|
|
32939
|
+
const b = stack[--this.#sp];
|
|
32940
|
+
stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] / b : 0;
|
|
32941
|
+
break;
|
|
32942
|
+
}
|
|
32943
|
+
case TOKEN.idiv: {
|
|
32944
|
+
const b = stack[--this.#sp];
|
|
32945
|
+
stack[this.#sp - 1] = b !== 0 ? Math.trunc(stack[this.#sp - 1] / b) : 0;
|
|
32946
|
+
break;
|
|
32947
|
+
}
|
|
32948
|
+
case TOKEN.mod: {
|
|
32949
|
+
const b = stack[--this.#sp];
|
|
32950
|
+
stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] % b : 0;
|
|
32951
|
+
break;
|
|
32952
|
+
}
|
|
32953
|
+
case TOKEN.exp: {
|
|
32954
|
+
const b = stack[--this.#sp];
|
|
32955
|
+
stack[this.#sp - 1] **= b;
|
|
32956
|
+
break;
|
|
32957
|
+
}
|
|
32958
|
+
case TOKEN.atan: {
|
|
32959
|
+
const dx = stack[--this.#sp];
|
|
32960
|
+
const deg = Math.atan2(stack[this.#sp - 1], dx) * _RAD_TO_DEG;
|
|
32961
|
+
stack[this.#sp - 1] = deg < 0 ? deg + 360 : deg;
|
|
32962
|
+
break;
|
|
32963
|
+
}
|
|
32964
|
+
case TOKEN.eq: {
|
|
32965
|
+
const b = stack[--this.#sp];
|
|
32966
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] === b ? 1 : 0;
|
|
32967
|
+
break;
|
|
32968
|
+
}
|
|
32969
|
+
case TOKEN.ne: {
|
|
32970
|
+
const b = stack[--this.#sp];
|
|
32971
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] !== b ? 1 : 0;
|
|
32972
|
+
break;
|
|
32973
|
+
}
|
|
32974
|
+
case TOKEN.gt: {
|
|
32975
|
+
const b = stack[--this.#sp];
|
|
32976
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] > b ? 1 : 0;
|
|
32977
|
+
break;
|
|
32978
|
+
}
|
|
32979
|
+
case TOKEN.ge: {
|
|
32980
|
+
const b = stack[--this.#sp];
|
|
32981
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] >= b ? 1 : 0;
|
|
32982
|
+
break;
|
|
32983
|
+
}
|
|
32984
|
+
case TOKEN.lt: {
|
|
32985
|
+
const b = stack[--this.#sp];
|
|
32986
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] < b ? 1 : 0;
|
|
32987
|
+
break;
|
|
32988
|
+
}
|
|
32989
|
+
case TOKEN.le: {
|
|
32990
|
+
const b = stack[--this.#sp];
|
|
32991
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] <= b ? 1 : 0;
|
|
32992
|
+
break;
|
|
32993
|
+
}
|
|
32994
|
+
case TOKEN.and: {
|
|
32995
|
+
const b = stack[--this.#sp] | 0;
|
|
32996
|
+
stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) & b;
|
|
32997
|
+
break;
|
|
32998
|
+
}
|
|
32999
|
+
case TOKEN.or: {
|
|
33000
|
+
const b = stack[--this.#sp] | 0;
|
|
33001
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] | 0 | b;
|
|
33002
|
+
break;
|
|
33003
|
+
}
|
|
33004
|
+
case TOKEN.xor: {
|
|
33005
|
+
const b = stack[--this.#sp] | 0;
|
|
33006
|
+
stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) ^ b;
|
|
33007
|
+
break;
|
|
33008
|
+
}
|
|
33009
|
+
case TOKEN.bitshift: {
|
|
33010
|
+
const amt = stack[--this.#sp] | 0;
|
|
33011
|
+
const v = stack[this.#sp - 1] | 0;
|
|
33012
|
+
stack[this.#sp - 1] = amt > 0 ? v << amt : v >> -amt;
|
|
33013
|
+
break;
|
|
33014
|
+
}
|
|
33015
|
+
case TOKEN.min: {
|
|
33016
|
+
const b = stack[--this.#sp];
|
|
33017
|
+
stack[this.#sp - 1] = Math.min(stack[this.#sp - 1], b);
|
|
33018
|
+
break;
|
|
33019
|
+
}
|
|
33020
|
+
case TOKEN.max: {
|
|
33021
|
+
const b = stack[--this.#sp];
|
|
33022
|
+
stack[this.#sp - 1] = Math.max(stack[this.#sp - 1], b);
|
|
33023
|
+
break;
|
|
33024
|
+
}
|
|
33025
|
+
case TOKEN.dup:
|
|
33026
|
+
this.#push(stack[this.#sp - 1]);
|
|
33027
|
+
break;
|
|
33028
|
+
case TOKEN.exch: {
|
|
33029
|
+
const a = stack[--this.#sp];
|
|
33030
|
+
const b = stack[--this.#sp];
|
|
33031
|
+
this.#push(a);
|
|
33032
|
+
this.#push(b);
|
|
33033
|
+
break;
|
|
33034
|
+
}
|
|
33035
|
+
case TOKEN.pop:
|
|
33036
|
+
this.#sp--;
|
|
33037
|
+
break;
|
|
33038
|
+
case TOKEN.copy: {
|
|
33039
|
+
const n = Math.trunc(stack[--this.#sp]);
|
|
33040
|
+
const base = this.#sp - n;
|
|
33041
|
+
for (let k = 0; k < n; k++) {
|
|
33042
|
+
this.#push(stack[base + k]);
|
|
33043
|
+
}
|
|
33044
|
+
break;
|
|
33045
|
+
}
|
|
33046
|
+
case TOKEN.index: {
|
|
33047
|
+
const i = Math.trunc(stack[--this.#sp]);
|
|
33048
|
+
this.#push(stack[this.#sp - 1 - i]);
|
|
33049
|
+
break;
|
|
33050
|
+
}
|
|
33051
|
+
case TOKEN.roll: {
|
|
33052
|
+
const j = Math.trunc(stack[--this.#sp]);
|
|
33053
|
+
const n = Math.trunc(stack[--this.#sp]);
|
|
33054
|
+
if (n > 1 && j !== 0) {
|
|
33055
|
+
const mod = (j % n + n) % n;
|
|
33056
|
+
if (mod !== 0) {
|
|
33057
|
+
const base = this.#sp - n;
|
|
33058
|
+
const sub = stack.slice(base, this.#sp);
|
|
33059
|
+
for (let k = 0; k < n; k++) {
|
|
33060
|
+
stack[base + k] = sub[(k - mod + n) % n];
|
|
33061
|
+
}
|
|
33062
|
+
}
|
|
33063
|
+
}
|
|
33064
|
+
break;
|
|
33065
|
+
}
|
|
33066
|
+
}
|
|
33067
|
+
}
|
|
33068
|
+
static #execBlock(instructions) {
|
|
33069
|
+
for (const instr of instructions) {
|
|
33070
|
+
switch (instr.type) {
|
|
33071
|
+
case PS_NODE.number:
|
|
33072
|
+
this.#push(instr.value);
|
|
33073
|
+
break;
|
|
33074
|
+
case PS_NODE.operator:
|
|
33075
|
+
this.#execOp(instr.op);
|
|
33076
|
+
break;
|
|
33077
|
+
case PS_NODE.if:
|
|
33078
|
+
if (this.#stack[--this.#sp] !== 0) {
|
|
33079
|
+
this.#execBlock(instr.then.instructions);
|
|
33080
|
+
}
|
|
33081
|
+
break;
|
|
33082
|
+
case PS_NODE.ifelse:
|
|
33083
|
+
if (this.#stack[--this.#sp] !== 0) {
|
|
33084
|
+
this.#execBlock(instr.then.instructions);
|
|
33085
|
+
} else {
|
|
33086
|
+
this.#execBlock(instr.otherwise.instructions);
|
|
33087
|
+
}
|
|
33088
|
+
break;
|
|
33089
|
+
}
|
|
33090
|
+
}
|
|
33091
|
+
}
|
|
33092
|
+
/**
|
|
33093
|
+
* @param {import("./ast.js").PsProgram} program
|
|
33094
|
+
* @param {number[]} domain – flat [min0,max0, …]
|
|
33095
|
+
* @param {number[]} range – flat [min0,max0, …]
|
|
33096
|
+
* @returns {Function} – `(src, srcOffset, dest, destOffset) => void`
|
|
33097
|
+
*/
|
|
33098
|
+
static build(program, domain, range) {
|
|
33099
|
+
const nIn = domain.length >> 1;
|
|
33100
|
+
const nOut = range.length >> 1;
|
|
33101
|
+
const { instructions } = program.body;
|
|
33102
|
+
return (src, srcOffset, dest, destOffset) => {
|
|
33103
|
+
this.#sp = 0;
|
|
33104
|
+
for (let i = 0; i < nIn; i++) {
|
|
33105
|
+
this.#push(src[srcOffset + i]);
|
|
33106
|
+
}
|
|
33107
|
+
this.#execBlock(instructions);
|
|
33108
|
+
const base = this.#sp - nOut;
|
|
33109
|
+
for (let i = 0; i < nOut; i++) {
|
|
33110
|
+
const v = base + i >= 0 ? this.#stack[base + i] : 0;
|
|
33111
|
+
dest[destOffset + i] = MathClamp(v, range[i * 2], range[i * 2 + 1]);
|
|
33112
|
+
}
|
|
33113
|
+
};
|
|
33114
|
+
}
|
|
33115
|
+
};
|
|
33116
|
+
function buildPostScriptJsFunction(source, domain, range, forceInterpreter = false) {
|
|
33117
|
+
const program = parsePostScriptFunction(source);
|
|
33118
|
+
const ir = !forceInterpreter && new PsJsCompiler(domain, range).compile(program);
|
|
33119
|
+
if (ir) {
|
|
33120
|
+
return (src, srcOffset, dest, destOffset) => {
|
|
33121
|
+
PsJsCompiler.execute(ir, src, srcOffset, dest, destOffset);
|
|
33122
|
+
};
|
|
33123
|
+
}
|
|
33124
|
+
return PSStackBasedInterpreter.build(program, domain, range);
|
|
33125
|
+
}
|
|
33126
|
+
var ShadingType = {
|
|
33127
|
+
FUNCTION_BASED: 1,
|
|
33128
|
+
AXIAL: 2,
|
|
33129
|
+
RADIAL: 3,
|
|
33130
|
+
FREE_FORM_MESH: 4,
|
|
33131
|
+
LATTICE_FORM_MESH: 5,
|
|
33132
|
+
COONS_PATCH_MESH: 6,
|
|
33133
|
+
TENSOR_PATCH_MESH: 7
|
|
33134
|
+
};
|
|
33135
|
+
var BaseShading = class _BaseShading {
|
|
33136
|
+
// A small number to offset the first/last color stops so we can insert ones
|
|
33137
|
+
// to support extend. Number.MIN_VALUE is too small and breaks the extend.
|
|
33138
|
+
static SMALL_NUMBER = 1e-6;
|
|
33139
|
+
constructor() {
|
|
33140
|
+
if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _BaseShading) {
|
|
33141
|
+
unreachable2("Cannot initialize BaseShading.");
|
|
33142
|
+
}
|
|
33143
|
+
}
|
|
33144
|
+
getIR() {
|
|
33145
|
+
unreachable2("Abstract method `getIR` called.");
|
|
33146
|
+
}
|
|
33147
|
+
};
|
|
33148
|
+
function meshUpdateBounds(self) {
|
|
33149
|
+
let minX = self.coords[0][0], minY = self.coords[0][1], maxX = minX, maxY = minY;
|
|
33150
|
+
for (let i = 1, ii = self.coords.length; i < ii; i++) {
|
|
33151
|
+
const x = self.coords[i][0], y = self.coords[i][1];
|
|
33152
|
+
minX = minX > x ? x : minX;
|
|
33153
|
+
minY = minY > y ? y : minY;
|
|
33154
|
+
maxX = maxX < x ? x : maxX;
|
|
33155
|
+
maxY = maxY < y ? y : maxY;
|
|
33156
|
+
}
|
|
33157
|
+
self.bounds = [minX, minY, maxX, maxY];
|
|
33158
|
+
}
|
|
33159
|
+
function meshPackData(self) {
|
|
33160
|
+
let i, j, ii;
|
|
33161
|
+
const coords = self.coords;
|
|
33162
|
+
const coordsPacked = new Float32Array(coords.length * 2);
|
|
33163
|
+
for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
|
|
33164
|
+
const xy = coords[i];
|
|
33165
|
+
coordsPacked[j++] = xy[0];
|
|
33166
|
+
coordsPacked[j++] = xy[1];
|
|
33167
|
+
}
|
|
33168
|
+
self.coords = coordsPacked;
|
|
33169
|
+
const colors = self.colors;
|
|
33170
|
+
const colorsPacked = new Uint8Array(colors.length * 4);
|
|
33171
|
+
for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
|
|
33172
|
+
const c = colors[i];
|
|
33173
|
+
colorsPacked[j++] = c[0];
|
|
33174
|
+
colorsPacked[j++] = c[1];
|
|
33175
|
+
colorsPacked[j++] = c[2];
|
|
33176
|
+
j++;
|
|
33177
|
+
}
|
|
33178
|
+
self.colors = colorsPacked;
|
|
33179
|
+
for (const figure of self.figures) {
|
|
33180
|
+
figure.coords = new Uint32Array(figure.coords);
|
|
33181
|
+
figure.colors = new Uint32Array(figure.colors);
|
|
33182
|
+
}
|
|
33183
|
+
}
|
|
33184
|
+
function buildMeshVertexData(coords, colors, figures) {
|
|
33185
|
+
let vertexCount = 0;
|
|
33186
|
+
for (const figure of figures) {
|
|
33187
|
+
if (figure.type === MeshFigureType.TRIANGLES) {
|
|
33188
|
+
vertexCount += figure.coords.length;
|
|
33189
|
+
} else if (figure.type === MeshFigureType.LATTICE) {
|
|
33190
|
+
const vpr = figure.verticesPerRow;
|
|
33191
|
+
vertexCount += (Math.floor(figure.coords.length / vpr) - 1) * (vpr - 1) * 6;
|
|
33192
|
+
}
|
|
33193
|
+
}
|
|
33194
|
+
const posData = new Float32Array(vertexCount * 2);
|
|
33195
|
+
const colData = new Uint8Array(vertexCount * 4);
|
|
33196
|
+
let pOff = 0, cOff = 0;
|
|
33197
|
+
const addVertex = (pi, ci) => {
|
|
33198
|
+
posData[pOff++] = coords[pi * 2];
|
|
33199
|
+
posData[pOff++] = coords[pi * 2 + 1];
|
|
33200
|
+
colData[cOff++] = colors[ci * 4];
|
|
33201
|
+
colData[cOff++] = colors[ci * 4 + 1];
|
|
33202
|
+
colData[cOff++] = colors[ci * 4 + 2];
|
|
33203
|
+
cOff++;
|
|
33204
|
+
};
|
|
33205
|
+
for (const figure of figures) {
|
|
33206
|
+
const ps = figure.coords;
|
|
33207
|
+
const cs = figure.colors;
|
|
33208
|
+
if (figure.type === MeshFigureType.TRIANGLES) {
|
|
33209
|
+
for (let i = 0, ii = ps.length; i < ii; i++) {
|
|
33210
|
+
addVertex(ps[i], cs[i]);
|
|
33211
|
+
}
|
|
33212
|
+
} else if (figure.type === MeshFigureType.LATTICE) {
|
|
33213
|
+
const vpr = figure.verticesPerRow;
|
|
33214
|
+
const rows = Math.floor(ps.length / vpr) - 1;
|
|
33215
|
+
const cols = vpr - 1;
|
|
33216
|
+
for (let i = 0; i < rows; i++) {
|
|
33217
|
+
let q = i * vpr;
|
|
33218
|
+
for (let j = 0; j < cols; j++, q++) {
|
|
33219
|
+
addVertex(ps[q], cs[q]);
|
|
33220
|
+
addVertex(ps[q + 1], cs[q + 1]);
|
|
33221
|
+
addVertex(ps[q + vpr], cs[q + vpr]);
|
|
33222
|
+
addVertex(ps[q + vpr + 1], cs[q + vpr + 1]);
|
|
33223
|
+
addVertex(ps[q + 1], cs[q + 1]);
|
|
33224
|
+
addVertex(ps[q + vpr], cs[q + vpr]);
|
|
33225
|
+
}
|
|
33226
|
+
}
|
|
33227
|
+
}
|
|
33228
|
+
}
|
|
33229
|
+
return { posData, colData, vertexCount };
|
|
33230
|
+
}
|
|
33231
|
+
var MeshStreamReader = class {
|
|
33232
|
+
constructor(stream, context) {
|
|
33233
|
+
this.stream = stream;
|
|
33234
|
+
this.context = context;
|
|
33235
|
+
this.buffer = 0;
|
|
33236
|
+
this.bufferLength = 0;
|
|
33237
|
+
const numComps = context.numComps;
|
|
33238
|
+
this.tmpCompsBuf = new Float32Array(numComps);
|
|
33239
|
+
const csNumComps = context.colorSpace.numComps;
|
|
33240
|
+
this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf;
|
|
33241
|
+
}
|
|
33242
|
+
get hasData() {
|
|
33243
|
+
if (this.stream.end) {
|
|
33244
|
+
return this.stream.pos < this.stream.end;
|
|
33245
|
+
}
|
|
33246
|
+
if (this.bufferLength > 0) {
|
|
33247
|
+
return true;
|
|
33248
|
+
}
|
|
33249
|
+
const nextByte = this.stream.getByte();
|
|
33250
|
+
if (nextByte < 0) {
|
|
33251
|
+
return false;
|
|
33252
|
+
}
|
|
33253
|
+
this.buffer = nextByte;
|
|
33254
|
+
this.bufferLength = 8;
|
|
33255
|
+
return true;
|
|
33256
|
+
}
|
|
33257
|
+
readBits(n) {
|
|
33258
|
+
const { stream } = this;
|
|
33259
|
+
let { buffer, bufferLength } = this;
|
|
33260
|
+
if (n === 32) {
|
|
33261
|
+
if (bufferLength === 0) {
|
|
33262
|
+
return stream.getInt32() >>> 0;
|
|
33263
|
+
}
|
|
33264
|
+
buffer = buffer << 24 | stream.getByte() << 16 | stream.getByte() << 8 | stream.getByte();
|
|
33265
|
+
const nextByte = stream.getByte();
|
|
33266
|
+
this.buffer = nextByte & (1 << bufferLength) - 1;
|
|
33267
|
+
return (buffer << 8 - bufferLength | (nextByte & 255) >> bufferLength) >>> 0;
|
|
33268
|
+
}
|
|
33269
|
+
if (n === 8 && bufferLength === 0) {
|
|
33270
|
+
return stream.getByte();
|
|
33271
|
+
}
|
|
33272
|
+
while (bufferLength < n) {
|
|
33273
|
+
buffer = buffer << 8 | stream.getByte();
|
|
33274
|
+
bufferLength += 8;
|
|
33275
|
+
}
|
|
33276
|
+
bufferLength -= n;
|
|
33277
|
+
this.bufferLength = bufferLength;
|
|
33278
|
+
this.buffer = buffer & (1 << bufferLength) - 1;
|
|
33279
|
+
return buffer >> bufferLength;
|
|
33280
|
+
}
|
|
33281
|
+
align() {
|
|
33282
|
+
this.buffer = 0;
|
|
33283
|
+
this.bufferLength = 0;
|
|
33284
|
+
}
|
|
33285
|
+
readFlag() {
|
|
33286
|
+
return this.readBits(this.context.bitsPerFlag);
|
|
33287
|
+
}
|
|
33288
|
+
readCoordinate() {
|
|
33289
|
+
const { bitsPerCoordinate, decode } = this.context;
|
|
33290
|
+
const xi = this.readBits(bitsPerCoordinate);
|
|
33291
|
+
const yi = this.readBits(bitsPerCoordinate);
|
|
33292
|
+
const scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 23283064365386963e-26;
|
|
33293
|
+
return [
|
|
33294
|
+
xi * scale * (decode[1] - decode[0]) + decode[0],
|
|
33295
|
+
yi * scale * (decode[3] - decode[2]) + decode[2]
|
|
33296
|
+
];
|
|
33297
|
+
}
|
|
33298
|
+
readComponents() {
|
|
33299
|
+
const { bitsPerComponent, colorFn, colorSpace, decode, numComps } = this.context;
|
|
33300
|
+
const scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 23283064365386963e-26;
|
|
33301
|
+
const components2 = this.tmpCompsBuf;
|
|
33302
|
+
for (let i = 0, j = 4; i < numComps; i++, j += 2) {
|
|
33303
|
+
const ci = this.readBits(bitsPerComponent);
|
|
33304
|
+
components2[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j];
|
|
33305
|
+
}
|
|
33306
|
+
const color = this.tmpCsCompsBuf;
|
|
33307
|
+
colorFn?.(components2, 0, color, 0);
|
|
33308
|
+
return colorSpace.getRgb(color, 0);
|
|
33309
|
+
}
|
|
33310
|
+
};
|
|
33311
|
+
var bCache = null;
|
|
33312
|
+
function getB(count) {
|
|
33313
|
+
if (bCache?.has(count)) return bCache.get(count);
|
|
33314
|
+
const values = Array.from({ length: count + 1 }, (_, i) => {
|
|
33315
|
+
const t = i / count, t_ = 1 - t;
|
|
33316
|
+
return new Float32Array([
|
|
33317
|
+
t_ ** 3,
|
|
33318
|
+
3 * t * t_ ** 2,
|
|
33319
|
+
3 * t ** 2 * t_,
|
|
33320
|
+
t ** 3
|
|
33321
|
+
]);
|
|
33322
|
+
});
|
|
33323
|
+
(bCache ??= /* @__PURE__ */ new Map()).set(count, values);
|
|
33324
|
+
return values;
|
|
33325
|
+
}
|
|
33326
|
+
var MeshShading = class _MeshShading extends BaseShading {
|
|
33327
|
+
static MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;
|
|
33328
|
+
static MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;
|
|
33329
|
+
// Count of triangles per entire mesh bounds.
|
|
33330
|
+
static TRIANGLE_DENSITY = 20;
|
|
33331
|
+
constructor(shadingType, stream, context, rowVertices) {
|
|
33332
|
+
super();
|
|
33333
|
+
this.shadingType = shadingType;
|
|
33334
|
+
this.bbox = this.background = null;
|
|
33335
|
+
this.coords = [];
|
|
33336
|
+
this.colors = [];
|
|
33337
|
+
this.figures = [];
|
|
33338
|
+
const reader = new MeshStreamReader(stream, context);
|
|
33339
|
+
let patchMesh = false;
|
|
33340
|
+
switch (this.shadingType) {
|
|
33341
|
+
case ShadingType.FREE_FORM_MESH:
|
|
33342
|
+
this._decodeType4Shading(reader);
|
|
33343
|
+
break;
|
|
33344
|
+
case ShadingType.LATTICE_FORM_MESH:
|
|
33345
|
+
const verticesPerRow = rowVertices | 0;
|
|
33346
|
+
if (verticesPerRow < 2) {
|
|
33347
|
+
throw new FormatError("Invalid VerticesPerRow");
|
|
33348
|
+
}
|
|
33349
|
+
this._decodeType5Shading(reader, verticesPerRow);
|
|
33350
|
+
break;
|
|
33351
|
+
case ShadingType.COONS_PATCH_MESH:
|
|
33352
|
+
this._decodeType6Shading(reader);
|
|
33353
|
+
patchMesh = true;
|
|
33354
|
+
break;
|
|
33355
|
+
case ShadingType.TENSOR_PATCH_MESH:
|
|
33356
|
+
this._decodeType7Shading(reader);
|
|
33357
|
+
patchMesh = true;
|
|
33358
|
+
break;
|
|
33359
|
+
default:
|
|
33360
|
+
unreachable2("Unsupported mesh type.");
|
|
33361
|
+
break;
|
|
33362
|
+
}
|
|
33363
|
+
if (patchMesh) {
|
|
33364
|
+
this._updateBounds();
|
|
33365
|
+
for (let i = 0, ii = this.figures.length; i < ii; i++) {
|
|
33366
|
+
this._buildFigureFromPatch(i);
|
|
33367
|
+
}
|
|
33368
|
+
}
|
|
33369
|
+
this._updateBounds();
|
|
33370
|
+
this._packData();
|
|
33371
|
+
}
|
|
33372
|
+
_decodeType4Shading(reader) {
|
|
33373
|
+
const coords = this.coords;
|
|
33374
|
+
const colors = this.colors;
|
|
33375
|
+
const operators = [];
|
|
33376
|
+
const ps = [];
|
|
33377
|
+
let verticesLeft = 0;
|
|
33378
|
+
while (reader.hasData) {
|
|
33379
|
+
const f = reader.readFlag();
|
|
33380
|
+
const coord = reader.readCoordinate();
|
|
33381
|
+
const color = reader.readComponents();
|
|
33382
|
+
if (verticesLeft === 0) {
|
|
33383
|
+
if (!(0 <= f && f <= 2)) {
|
|
33384
|
+
throw new FormatError("Unknown type4 flag");
|
|
33385
|
+
}
|
|
33386
|
+
switch (f) {
|
|
33387
|
+
case 0:
|
|
33388
|
+
verticesLeft = 3;
|
|
33389
|
+
break;
|
|
33390
|
+
case 1:
|
|
33391
|
+
ps.push(ps.at(-2), ps.at(-1));
|
|
33392
|
+
verticesLeft = 1;
|
|
33393
|
+
break;
|
|
33394
|
+
case 2:
|
|
33395
|
+
ps.push(ps.at(-3), ps.at(-1));
|
|
33396
|
+
verticesLeft = 1;
|
|
33397
|
+
break;
|
|
33398
|
+
}
|
|
33399
|
+
operators.push(f);
|
|
33400
|
+
}
|
|
33401
|
+
ps.push(coords.length);
|
|
33402
|
+
coords.push(coord);
|
|
33403
|
+
colors.push(color);
|
|
33404
|
+
verticesLeft--;
|
|
33405
|
+
reader.align();
|
|
33406
|
+
}
|
|
33407
|
+
this.figures.push({
|
|
33408
|
+
type: MeshFigureType.TRIANGLES,
|
|
33409
|
+
coords: new Int32Array(ps),
|
|
33410
|
+
colors: new Int32Array(ps)
|
|
33411
|
+
});
|
|
33412
|
+
}
|
|
33413
|
+
_decodeType5Shading(reader, verticesPerRow) {
|
|
33414
|
+
const coords = this.coords;
|
|
33415
|
+
const colors = this.colors;
|
|
33416
|
+
const ps = [];
|
|
33417
|
+
while (reader.hasData) {
|
|
33418
|
+
const coord = reader.readCoordinate();
|
|
33419
|
+
const color = reader.readComponents();
|
|
33420
|
+
ps.push(coords.length);
|
|
33421
|
+
coords.push(coord);
|
|
33422
|
+
colors.push(color);
|
|
33423
|
+
}
|
|
33424
|
+
this.figures.push({
|
|
33425
|
+
type: MeshFigureType.LATTICE,
|
|
33426
|
+
coords: new Int32Array(ps),
|
|
33427
|
+
colors: new Int32Array(ps),
|
|
33428
|
+
verticesPerRow
|
|
33429
|
+
});
|
|
33430
|
+
}
|
|
33431
|
+
_decodeType6Shading(reader) {
|
|
33432
|
+
const coords = this.coords;
|
|
33433
|
+
const colors = this.colors;
|
|
33434
|
+
const ps = new Int32Array(16);
|
|
33435
|
+
const cs = new Int32Array(4);
|
|
33436
|
+
while (reader.hasData) {
|
|
33437
|
+
const f = reader.readFlag();
|
|
33438
|
+
if (!(0 <= f && f <= 3)) {
|
|
33439
|
+
throw new FormatError("Unknown type6 flag");
|
|
33440
|
+
}
|
|
33441
|
+
const pi = coords.length;
|
|
33442
|
+
for (let i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) {
|
|
33443
|
+
coords.push(reader.readCoordinate());
|
|
33444
|
+
}
|
|
33445
|
+
const ci = colors.length;
|
|
33446
|
+
for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
|
|
33447
|
+
colors.push(reader.readComponents());
|
|
33448
|
+
}
|
|
33449
|
+
let tmp1, tmp2, tmp3, tmp4;
|
|
33450
|
+
switch (f) {
|
|
33451
|
+
// prettier-ignore
|
|
33452
|
+
case 0:
|
|
33453
|
+
ps[12] = pi + 3;
|
|
33454
|
+
ps[13] = pi + 4;
|
|
33455
|
+
ps[14] = pi + 5;
|
|
33456
|
+
ps[15] = pi + 6;
|
|
33457
|
+
ps[8] = pi + 2;
|
|
33458
|
+
ps[11] = pi + 7;
|
|
33459
|
+
ps[4] = pi + 1;
|
|
33460
|
+
ps[7] = pi + 8;
|
|
33461
|
+
ps[0] = pi;
|
|
33462
|
+
ps[1] = pi + 11;
|
|
33463
|
+
ps[2] = pi + 10;
|
|
33464
|
+
ps[3] = pi + 9;
|
|
33465
|
+
cs[2] = ci + 1;
|
|
33466
|
+
cs[3] = ci + 2;
|
|
33467
|
+
cs[0] = ci;
|
|
33468
|
+
cs[1] = ci + 3;
|
|
33469
|
+
break;
|
|
33470
|
+
// prettier-ignore
|
|
33471
|
+
case 1:
|
|
33472
|
+
tmp1 = ps[12];
|
|
33473
|
+
tmp2 = ps[13];
|
|
33474
|
+
tmp3 = ps[14];
|
|
33475
|
+
tmp4 = ps[15];
|
|
33476
|
+
ps[12] = tmp4;
|
|
33477
|
+
ps[13] = pi + 0;
|
|
33478
|
+
ps[14] = pi + 1;
|
|
33479
|
+
ps[15] = pi + 2;
|
|
33480
|
+
ps[8] = tmp3;
|
|
33481
|
+
ps[11] = pi + 3;
|
|
33482
|
+
ps[4] = tmp2;
|
|
33483
|
+
ps[7] = pi + 4;
|
|
33484
|
+
ps[0] = tmp1;
|
|
33485
|
+
ps[1] = pi + 7;
|
|
33486
|
+
ps[2] = pi + 6;
|
|
33487
|
+
ps[3] = pi + 5;
|
|
33488
|
+
tmp1 = cs[2];
|
|
33489
|
+
tmp2 = cs[3];
|
|
33490
|
+
cs[2] = tmp2;
|
|
33491
|
+
cs[3] = ci;
|
|
33492
|
+
cs[0] = tmp1;
|
|
33493
|
+
cs[1] = ci + 1;
|
|
33494
|
+
break;
|
|
33495
|
+
// prettier-ignore
|
|
33496
|
+
case 2:
|
|
33497
|
+
tmp1 = ps[15];
|
|
33498
|
+
tmp2 = ps[11];
|
|
33499
|
+
ps[12] = ps[3];
|
|
33500
|
+
ps[13] = pi + 0;
|
|
33501
|
+
ps[14] = pi + 1;
|
|
33502
|
+
ps[15] = pi + 2;
|
|
33503
|
+
ps[8] = ps[7];
|
|
33504
|
+
ps[11] = pi + 3;
|
|
33505
|
+
ps[4] = tmp2;
|
|
33506
|
+
ps[7] = pi + 4;
|
|
33507
|
+
ps[0] = tmp1;
|
|
33508
|
+
ps[1] = pi + 7;
|
|
33509
|
+
ps[2] = pi + 6;
|
|
33510
|
+
ps[3] = pi + 5;
|
|
33511
|
+
tmp1 = cs[3];
|
|
33512
|
+
cs[2] = cs[1];
|
|
33513
|
+
cs[3] = ci;
|
|
33514
|
+
cs[0] = tmp1;
|
|
33515
|
+
cs[1] = ci + 1;
|
|
33516
|
+
break;
|
|
33517
|
+
// prettier-ignore
|
|
33518
|
+
case 3:
|
|
33519
|
+
ps[12] = ps[0];
|
|
33520
|
+
ps[13] = pi + 0;
|
|
33521
|
+
ps[14] = pi + 1;
|
|
33522
|
+
ps[15] = pi + 2;
|
|
33523
|
+
ps[8] = ps[1];
|
|
33524
|
+
ps[11] = pi + 3;
|
|
33525
|
+
ps[4] = ps[2];
|
|
33526
|
+
ps[7] = pi + 4;
|
|
33527
|
+
ps[0] = ps[3];
|
|
33528
|
+
ps[1] = pi + 7;
|
|
33529
|
+
ps[2] = pi + 6;
|
|
33530
|
+
ps[3] = pi + 5;
|
|
33531
|
+
cs[2] = cs[0];
|
|
33532
|
+
cs[3] = ci;
|
|
33533
|
+
cs[0] = cs[1];
|
|
33534
|
+
cs[1] = ci + 1;
|
|
33535
|
+
break;
|
|
33536
|
+
}
|
|
33537
|
+
ps[5] = coords.length;
|
|
33538
|
+
coords.push([
|
|
33539
|
+
(-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,
|
|
33540
|
+
(-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
|
|
33541
|
+
]);
|
|
33542
|
+
ps[6] = coords.length;
|
|
33543
|
+
coords.push([
|
|
33544
|
+
(-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,
|
|
33545
|
+
(-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
|
|
33546
|
+
]);
|
|
33547
|
+
ps[9] = coords.length;
|
|
33548
|
+
coords.push([
|
|
33549
|
+
(-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,
|
|
33550
|
+
(-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
|
|
33551
|
+
]);
|
|
33552
|
+
ps[10] = coords.length;
|
|
33553
|
+
coords.push([
|
|
33554
|
+
(-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,
|
|
33555
|
+
(-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
|
|
33556
|
+
]);
|
|
33557
|
+
this.figures.push({
|
|
33558
|
+
type: MeshFigureType.PATCH,
|
|
33559
|
+
coords: new Int32Array(ps),
|
|
33560
|
+
// making copies of ps and cs
|
|
33561
|
+
colors: new Int32Array(cs)
|
|
33562
|
+
});
|
|
33563
|
+
}
|
|
33564
|
+
}
|
|
33565
|
+
_decodeType7Shading(reader) {
|
|
33566
|
+
const coords = this.coords;
|
|
33567
|
+
const colors = this.colors;
|
|
33568
|
+
const ps = new Int32Array(16);
|
|
33569
|
+
const cs = new Int32Array(4);
|
|
33570
|
+
while (reader.hasData) {
|
|
33571
|
+
const f = reader.readFlag();
|
|
33572
|
+
if (!(0 <= f && f <= 3)) {
|
|
33573
|
+
throw new FormatError("Unknown type7 flag");
|
|
33574
|
+
}
|
|
33575
|
+
const pi = coords.length;
|
|
33576
|
+
for (let i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) {
|
|
33577
|
+
coords.push(reader.readCoordinate());
|
|
33578
|
+
}
|
|
33579
|
+
const ci = colors.length;
|
|
33580
|
+
for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
|
|
33581
|
+
colors.push(reader.readComponents());
|
|
33582
|
+
}
|
|
33583
|
+
let tmp1, tmp2, tmp3, tmp4;
|
|
33584
|
+
switch (f) {
|
|
33585
|
+
// prettier-ignore
|
|
33586
|
+
case 0:
|
|
33587
|
+
ps[12] = pi + 3;
|
|
33588
|
+
ps[13] = pi + 4;
|
|
33589
|
+
ps[14] = pi + 5;
|
|
33590
|
+
ps[15] = pi + 6;
|
|
33591
|
+
ps[8] = pi + 2;
|
|
33592
|
+
ps[9] = pi + 13;
|
|
33593
|
+
ps[10] = pi + 14;
|
|
33594
|
+
ps[11] = pi + 7;
|
|
33595
|
+
ps[4] = pi + 1;
|
|
33596
|
+
ps[5] = pi + 12;
|
|
33597
|
+
ps[6] = pi + 15;
|
|
33598
|
+
ps[7] = pi + 8;
|
|
33599
|
+
ps[0] = pi;
|
|
33600
|
+
ps[1] = pi + 11;
|
|
33601
|
+
ps[2] = pi + 10;
|
|
33602
|
+
ps[3] = pi + 9;
|
|
33603
|
+
cs[2] = ci + 1;
|
|
33604
|
+
cs[3] = ci + 2;
|
|
33605
|
+
cs[0] = ci;
|
|
33606
|
+
cs[1] = ci + 3;
|
|
33607
|
+
break;
|
|
33608
|
+
// prettier-ignore
|
|
33609
|
+
case 1:
|
|
33610
|
+
tmp1 = ps[12];
|
|
33611
|
+
tmp2 = ps[13];
|
|
33612
|
+
tmp3 = ps[14];
|
|
33613
|
+
tmp4 = ps[15];
|
|
33614
|
+
ps[12] = tmp4;
|
|
33615
|
+
ps[13] = pi + 0;
|
|
33616
|
+
ps[14] = pi + 1;
|
|
33617
|
+
ps[15] = pi + 2;
|
|
33618
|
+
ps[8] = tmp3;
|
|
33619
|
+
ps[9] = pi + 9;
|
|
33620
|
+
ps[10] = pi + 10;
|
|
33621
|
+
ps[11] = pi + 3;
|
|
33622
|
+
ps[4] = tmp2;
|
|
33623
|
+
ps[5] = pi + 8;
|
|
33624
|
+
ps[6] = pi + 11;
|
|
33625
|
+
ps[7] = pi + 4;
|
|
33626
|
+
ps[0] = tmp1;
|
|
33627
|
+
ps[1] = pi + 7;
|
|
33628
|
+
ps[2] = pi + 6;
|
|
33629
|
+
ps[3] = pi + 5;
|
|
33630
|
+
tmp1 = cs[2];
|
|
33631
|
+
tmp2 = cs[3];
|
|
33632
|
+
cs[2] = tmp2;
|
|
33633
|
+
cs[3] = ci;
|
|
33634
|
+
cs[0] = tmp1;
|
|
33635
|
+
cs[1] = ci + 1;
|
|
33636
|
+
break;
|
|
33637
|
+
// prettier-ignore
|
|
33638
|
+
case 2:
|
|
33639
|
+
tmp1 = ps[15];
|
|
33640
|
+
tmp2 = ps[11];
|
|
33641
|
+
ps[12] = ps[3];
|
|
33642
|
+
ps[13] = pi + 0;
|
|
33643
|
+
ps[14] = pi + 1;
|
|
33644
|
+
ps[15] = pi + 2;
|
|
33645
|
+
ps[8] = ps[7];
|
|
33646
|
+
ps[9] = pi + 9;
|
|
33647
|
+
ps[10] = pi + 10;
|
|
33648
|
+
ps[11] = pi + 3;
|
|
33649
|
+
ps[4] = tmp2;
|
|
33650
|
+
ps[5] = pi + 8;
|
|
33651
|
+
ps[6] = pi + 11;
|
|
33652
|
+
ps[7] = pi + 4;
|
|
33653
|
+
ps[0] = tmp1;
|
|
33654
|
+
ps[1] = pi + 7;
|
|
33655
|
+
ps[2] = pi + 6;
|
|
33656
|
+
ps[3] = pi + 5;
|
|
33657
|
+
tmp1 = cs[3];
|
|
33658
|
+
cs[2] = cs[1];
|
|
33659
|
+
cs[3] = ci;
|
|
33660
|
+
cs[0] = tmp1;
|
|
33661
|
+
cs[1] = ci + 1;
|
|
33662
|
+
break;
|
|
33663
|
+
// prettier-ignore
|
|
33664
|
+
case 3:
|
|
33665
|
+
ps[12] = ps[0];
|
|
33666
|
+
ps[13] = pi + 0;
|
|
33667
|
+
ps[14] = pi + 1;
|
|
33668
|
+
ps[15] = pi + 2;
|
|
33669
|
+
ps[8] = ps[1];
|
|
33670
|
+
ps[9] = pi + 9;
|
|
33671
|
+
ps[10] = pi + 10;
|
|
33672
|
+
ps[11] = pi + 3;
|
|
33673
|
+
ps[4] = ps[2];
|
|
33674
|
+
ps[5] = pi + 8;
|
|
33675
|
+
ps[6] = pi + 11;
|
|
33676
|
+
ps[7] = pi + 4;
|
|
33677
|
+
ps[0] = ps[3];
|
|
33678
|
+
ps[1] = pi + 7;
|
|
33679
|
+
ps[2] = pi + 6;
|
|
33680
|
+
ps[3] = pi + 5;
|
|
33681
|
+
cs[2] = cs[0];
|
|
33682
|
+
cs[3] = ci;
|
|
33683
|
+
cs[0] = cs[1];
|
|
33684
|
+
cs[1] = ci + 1;
|
|
33685
|
+
break;
|
|
33686
|
+
}
|
|
33687
|
+
this.figures.push({
|
|
33688
|
+
type: MeshFigureType.PATCH,
|
|
33689
|
+
coords: new Int32Array(ps),
|
|
33690
|
+
// making copies of ps and cs
|
|
33691
|
+
colors: new Int32Array(cs)
|
|
33692
|
+
});
|
|
33693
|
+
}
|
|
33694
|
+
}
|
|
33695
|
+
_buildFigureFromPatch(index) {
|
|
33696
|
+
const figure = this.figures[index];
|
|
33697
|
+
assert2(
|
|
33698
|
+
figure.type === MeshFigureType.PATCH,
|
|
33699
|
+
"Unexpected patch mesh figure"
|
|
33700
|
+
);
|
|
33701
|
+
const coords = this.coords, colors = this.colors;
|
|
33702
|
+
const pi = figure.coords;
|
|
33703
|
+
const ci = figure.colors;
|
|
33704
|
+
const figureMinX = Math.min(
|
|
33705
|
+
coords[pi[0]][0],
|
|
33706
|
+
coords[pi[3]][0],
|
|
33707
|
+
coords[pi[12]][0],
|
|
33708
|
+
coords[pi[15]][0]
|
|
33709
|
+
);
|
|
33710
|
+
const figureMinY = Math.min(
|
|
33711
|
+
coords[pi[0]][1],
|
|
33712
|
+
coords[pi[3]][1],
|
|
33713
|
+
coords[pi[12]][1],
|
|
33714
|
+
coords[pi[15]][1]
|
|
33715
|
+
);
|
|
33716
|
+
const figureMaxX = Math.max(
|
|
33717
|
+
coords[pi[0]][0],
|
|
33718
|
+
coords[pi[3]][0],
|
|
33719
|
+
coords[pi[12]][0],
|
|
33720
|
+
coords[pi[15]][0]
|
|
33721
|
+
);
|
|
33722
|
+
const figureMaxY = Math.max(
|
|
33723
|
+
coords[pi[0]][1],
|
|
33724
|
+
coords[pi[3]][1],
|
|
33725
|
+
coords[pi[12]][1],
|
|
33726
|
+
coords[pi[15]][1]
|
|
33727
|
+
);
|
|
33728
|
+
let splitXBy = Math.ceil(
|
|
33729
|
+
(figureMaxX - figureMinX) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[2] - this.bounds[0])
|
|
33730
|
+
);
|
|
33731
|
+
splitXBy = MathClamp(
|
|
33732
|
+
splitXBy,
|
|
33733
|
+
_MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
|
|
33734
|
+
_MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT
|
|
33735
|
+
);
|
|
33736
|
+
let splitYBy = Math.ceil(
|
|
33737
|
+
(figureMaxY - figureMinY) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[3] - this.bounds[1])
|
|
33738
|
+
);
|
|
33739
|
+
splitYBy = MathClamp(
|
|
33740
|
+
splitYBy,
|
|
33741
|
+
_MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
|
|
33742
|
+
_MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT
|
|
33743
|
+
);
|
|
33744
|
+
const verticesPerRow = splitXBy + 1;
|
|
33745
|
+
const figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
|
|
33746
|
+
const figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
|
|
33747
|
+
let k = 0;
|
|
33748
|
+
const cl = new Uint8Array(3), cr = new Uint8Array(3);
|
|
33749
|
+
const c0 = colors[ci[0]], c1 = colors[ci[1]], c2 = colors[ci[2]], c3 = colors[ci[3]];
|
|
33750
|
+
const bRow = getB(splitYBy), bCol = getB(splitXBy);
|
|
33751
|
+
for (let row = 0; row <= splitYBy; row++) {
|
|
33752
|
+
cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0;
|
|
33753
|
+
cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0;
|
|
33754
|
+
cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0;
|
|
33755
|
+
cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0;
|
|
33756
|
+
cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0;
|
|
33757
|
+
cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0;
|
|
33758
|
+
for (let col = 0; col <= splitXBy; col++, k++) {
|
|
33759
|
+
if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) {
|
|
33760
|
+
continue;
|
|
33761
|
+
}
|
|
33762
|
+
let x = 0, y = 0;
|
|
33763
|
+
let q = 0;
|
|
33764
|
+
for (let i = 0; i <= 3; i++) {
|
|
33765
|
+
for (let j = 0; j <= 3; j++, q++) {
|
|
33766
|
+
const m = bRow[row][i] * bCol[col][j];
|
|
33767
|
+
x += coords[pi[q]][0] * m;
|
|
33768
|
+
y += coords[pi[q]][1] * m;
|
|
33769
|
+
}
|
|
33770
|
+
}
|
|
33771
|
+
figureCoords[k] = coords.length;
|
|
33772
|
+
coords.push([x, y]);
|
|
33773
|
+
figureColors[k] = colors.length;
|
|
33774
|
+
const newColor = new Uint8Array(3);
|
|
33775
|
+
newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0;
|
|
33776
|
+
newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0;
|
|
33777
|
+
newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0;
|
|
33778
|
+
colors.push(newColor);
|
|
33779
|
+
}
|
|
33780
|
+
}
|
|
33781
|
+
figureCoords[0] = pi[0];
|
|
33782
|
+
figureColors[0] = ci[0];
|
|
33783
|
+
figureCoords[splitXBy] = pi[3];
|
|
33784
|
+
figureColors[splitXBy] = ci[1];
|
|
33785
|
+
figureCoords[verticesPerRow * splitYBy] = pi[12];
|
|
33786
|
+
figureColors[verticesPerRow * splitYBy] = ci[2];
|
|
33787
|
+
figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15];
|
|
33788
|
+
figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
|
|
33789
|
+
this.figures[index] = {
|
|
33790
|
+
type: MeshFigureType.LATTICE,
|
|
33791
|
+
coords: figureCoords,
|
|
33792
|
+
colors: figureColors,
|
|
33793
|
+
verticesPerRow
|
|
33794
|
+
};
|
|
33795
|
+
}
|
|
33796
|
+
_updateBounds() {
|
|
33797
|
+
meshUpdateBounds(this);
|
|
33798
|
+
}
|
|
33799
|
+
_packData() {
|
|
33800
|
+
meshPackData(this);
|
|
33801
|
+
}
|
|
33802
|
+
getIR() {
|
|
33803
|
+
const { posData, colData, vertexCount } = buildMeshVertexData(
|
|
33804
|
+
this.coords,
|
|
33805
|
+
this.colors,
|
|
33806
|
+
this.figures
|
|
33807
|
+
);
|
|
33808
|
+
return [
|
|
33809
|
+
"Mesh",
|
|
33810
|
+
this.shadingType,
|
|
33811
|
+
posData,
|
|
33812
|
+
colData,
|
|
33813
|
+
vertexCount,
|
|
33814
|
+
this.bounds,
|
|
33815
|
+
this.bbox,
|
|
33816
|
+
this.background
|
|
33817
|
+
];
|
|
33818
|
+
}
|
|
33819
|
+
};
|
|
30513
33820
|
var PdfError = class extends Error {
|
|
30514
33821
|
constructor(code, message) {
|
|
30515
33822
|
super(message);
|
|
@@ -33415,11 +36722,16 @@ function parseDictionaryStream(dictNode, lexer, bytes) {
|
|
|
33415
36722
|
let streamEnd = streamStart;
|
|
33416
36723
|
if (resolvedLength !== void 0 && resolvedLength >= 0 && streamStart + resolvedLength <= bytes.length) {
|
|
33417
36724
|
const candidateEnd = streamStart + resolvedLength;
|
|
33418
|
-
const
|
|
33419
|
-
|
|
33420
|
-
|
|
36725
|
+
const tailLexer = new CosByteLexer(bytes, candidateEnd);
|
|
36726
|
+
let endToken;
|
|
36727
|
+
try {
|
|
36728
|
+
endToken = tailLexer.nextToken();
|
|
36729
|
+
} catch (error) {
|
|
36730
|
+
if (!(error instanceof PdfError) || error.code !== "E_PARSE") throw error;
|
|
36731
|
+
}
|
|
36732
|
+
if (endToken?.kind === "keyword" && endToken.value === "endstream") {
|
|
33421
36733
|
rawStreamBytes = bytes.subarray(streamStart, candidateEnd);
|
|
33422
|
-
streamEnd =
|
|
36734
|
+
streamEnd = tailLexer.offset;
|
|
33423
36735
|
}
|
|
33424
36736
|
}
|
|
33425
36737
|
if (!rawStreamBytes) {
|
|
@@ -41590,6 +44902,25 @@ var __webpack_exports__JpxImage = __webpack_exports__.JpxImage;
|
|
|
41590
44902
|
var __webpack_exports__VerbosityLevel = __webpack_exports__.VerbosityLevel;
|
|
41591
44903
|
var __webpack_exports__getVerbosityLevel = __webpack_exports__.getVerbosityLevel;
|
|
41592
44904
|
var __webpack_exports__setVerbosityLevel = __webpack_exports__.setVerbosityLevel;
|
|
44905
|
+
function createCalibratedColorSpace(doc, family, parameters) {
|
|
44906
|
+
const dict = doc.resolveDict(parameters);
|
|
44907
|
+
const array = (key) => {
|
|
44908
|
+
const value = dict ? doc.resolveArray(dictGet(dict, key)) : void 0;
|
|
44909
|
+
return value?.items.map((item) => {
|
|
44910
|
+
const number = doc.resolve(item);
|
|
44911
|
+
return number?.kind === "number" ? number.value : 0;
|
|
44912
|
+
});
|
|
44913
|
+
};
|
|
44914
|
+
const whitePoint = array("WhitePoint") ?? [0.95047, 1, 1.08883];
|
|
44915
|
+
const blackPoint = array("BlackPoint");
|
|
44916
|
+
if (family === "CalGray") {
|
|
44917
|
+
const gamma = dict ? doc.resolve(dictGet(dict, "Gamma")) : void 0;
|
|
44918
|
+
return new CalGrayCS(whitePoint, blackPoint, gamma?.kind === "number" ? gamma.value : void 0);
|
|
44919
|
+
}
|
|
44920
|
+
if (family === "CalRGB") return new CalRGBCS(whitePoint, blackPoint, array("Gamma"), array("Matrix"));
|
|
44921
|
+
return new LabCS(whitePoint, blackPoint, array("Range"));
|
|
44922
|
+
}
|
|
44923
|
+
var cmykColorSpace = new DeviceCmykCS();
|
|
41593
44924
|
function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
41594
44925
|
if (!csNode) return { colorSpace: "rgb", colorSpaceLabel: "rgb", components: 3 };
|
|
41595
44926
|
const resolved = doc.resolve(csNode);
|
|
@@ -41630,7 +44961,7 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
|
41630
44961
|
palette = lookupNode.bytes;
|
|
41631
44962
|
}
|
|
41632
44963
|
let resolvedBaseComp = baseInfo.components;
|
|
41633
|
-
if (palette && (baseInfo.
|
|
44964
|
+
if (palette && (baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calibrated !== void 0)) {
|
|
41634
44965
|
const numEntries = Math.max(1, Math.min(hival + 1, Math.floor(palette.length / Math.max(1, baseInfo.components))));
|
|
41635
44966
|
const rgbaPal = decodeSamplesToRgba(palette, numEntries, 1, 8, baseInfo);
|
|
41636
44967
|
const rgbPal = new Uint8Array(numEntries * 3);
|
|
@@ -41660,74 +44991,21 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
|
41660
44991
|
}
|
|
41661
44992
|
return { colorSpace: "rgb", colorSpaceLabel: "icc", components: 3 };
|
|
41662
44993
|
}
|
|
41663
|
-
if (kindName === "CalGray") {
|
|
41664
|
-
const
|
|
41665
|
-
const gammaNode = calDict ? doc.resolve(dictGet(calDict, "Gamma")) : void 0;
|
|
41666
|
-
const gamma = gammaNode?.kind === "number" && gammaNode.value > 0 ? gammaNode.value : 1;
|
|
41667
|
-
return { colorSpace: "gray", colorSpaceLabel: "cal-gray", components: 1, calGrayGamma: gamma };
|
|
41668
|
-
}
|
|
41669
|
-
if (kindName === "CalRGB") {
|
|
41670
|
-
const calDict = doc.resolveDict(resolved.items[1]);
|
|
41671
|
-
const gammaArr = calDict ? doc.resolveArray(dictGet(calDict, "Gamma")) : void 0;
|
|
41672
|
-
let calRgbGamma = [1, 1, 1];
|
|
41673
|
-
if (gammaArr && gammaArr.items.length >= 3) {
|
|
41674
|
-
const gNums = gammaArr.items.slice(0, 3).map((it) => {
|
|
41675
|
-
const r = doc.resolve(it);
|
|
41676
|
-
return r?.kind === "number" && r.value > 0 ? r.value : 1;
|
|
41677
|
-
});
|
|
41678
|
-
calRgbGamma = [gNums[0], gNums[1], gNums[2]];
|
|
41679
|
-
}
|
|
41680
|
-
const matArr = calDict ? doc.resolveArray(dictGet(calDict, "Matrix")) : void 0;
|
|
41681
|
-
let calRgbMatrix;
|
|
41682
|
-
if (matArr && matArr.items.length >= 9) {
|
|
41683
|
-
calRgbMatrix = matArr.items.slice(0, 9).map((it) => {
|
|
41684
|
-
const r = doc.resolve(it);
|
|
41685
|
-
return r?.kind === "number" ? r.value : 0;
|
|
41686
|
-
});
|
|
41687
|
-
}
|
|
44994
|
+
if (kindName === "CalGray" || kindName === "CalRGB" || kindName === "Lab") {
|
|
44995
|
+
const calibrated = createCalibratedColorSpace(doc, kindName, resolved.items[1]);
|
|
41688
44996
|
return {
|
|
41689
|
-
colorSpace: "rgb",
|
|
41690
|
-
colorSpaceLabel: "cal-rgb",
|
|
41691
|
-
components: 3,
|
|
41692
|
-
|
|
41693
|
-
calRgbMatrix
|
|
44997
|
+
colorSpace: kindName === "CalGray" ? "gray" : "rgb",
|
|
44998
|
+
colorSpaceLabel: kindName === "CalGray" ? "cal-gray" : kindName === "CalRGB" ? "cal-rgb" : "lab",
|
|
44999
|
+
components: kindName === "CalGray" ? 1 : 3,
|
|
45000
|
+
calibrated
|
|
41694
45001
|
};
|
|
41695
45002
|
}
|
|
41696
|
-
if (kindName === "Lab") {
|
|
41697
|
-
const labDict = doc.resolveDict(resolved.items[1]);
|
|
41698
|
-
const rangeArr = labDict ? doc.resolveArray(dictGet(labDict, "Range")) : void 0;
|
|
41699
|
-
let labRange = [-100, 100, -100, 100];
|
|
41700
|
-
if (rangeArr && rangeArr.items.length >= 4) {
|
|
41701
|
-
const nums = rangeArr.items.slice(0, 4).map((it) => {
|
|
41702
|
-
const r = doc.resolve(it);
|
|
41703
|
-
return r?.kind === "number" ? r.value : 0;
|
|
41704
|
-
});
|
|
41705
|
-
labRange = [nums[0], nums[1], nums[2], nums[3]];
|
|
41706
|
-
}
|
|
41707
|
-
return { colorSpace: "rgb", colorSpaceLabel: "lab", components: 3, isLab: true, labRange };
|
|
41708
|
-
}
|
|
41709
45003
|
if (kindName === "Separation" || kindName === "DeviceN") {
|
|
41710
45004
|
const isDevN = kindName === "DeviceN";
|
|
41711
45005
|
const namesArr = isDevN ? doc.resolveArray(resolved.items[1]) : void 0;
|
|
41712
45006
|
const devNComponents = isDevN && namesArr ? Math.max(1, namesArr.items.length) : 1;
|
|
41713
45007
|
const altInfo = resolveColorSpaceInfo(doc, resolved.items[2], resourcesDict);
|
|
41714
45008
|
const altSpace = altInfo.colorSpace === "cmyk" ? "cmyk" : altInfo.colorSpace === "gray" ? "gray" : "rgb";
|
|
41715
|
-
const fnResolved = doc.resolve(resolved.items[3]);
|
|
41716
|
-
const fnDict = fnResolved?.kind === "stream" ? fnResolved.dict : fnResolved?.kind === "dict" ? fnResolved : void 0;
|
|
41717
|
-
const ftNode = fnDict ? doc.resolve(dictGet(fnDict, "FunctionType")) : void 0;
|
|
41718
|
-
const tintFunctionType = ftNode?.kind === "number" ? ftNode.value : 2;
|
|
41719
|
-
const c0Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C0")) : void 0;
|
|
41720
|
-
const c1Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C1")) : void 0;
|
|
41721
|
-
const nNode = fnDict ? doc.resolve(dictGet(fnDict, "N")) : void 0;
|
|
41722
|
-
const c0 = c0Arr ? c0Arr.items.map((it) => {
|
|
41723
|
-
const r = doc.resolve(it);
|
|
41724
|
-
return r?.kind === "number" ? r.value : 0;
|
|
41725
|
-
}) : altSpace === "cmyk" ? [0, 0, 0, 0] : altSpace === "gray" ? [1] : [1, 1, 1];
|
|
41726
|
-
const c1 = c1Arr ? c1Arr.items.map((it) => {
|
|
41727
|
-
const r = doc.resolve(it);
|
|
41728
|
-
return r?.kind === "number" ? r.value : 0;
|
|
41729
|
-
}) : altSpace === "cmyk" ? [0, 0, 0, 1] : altSpace === "gray" ? [0] : [0, 0, 0];
|
|
41730
|
-
const sepN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
|
|
41731
45009
|
return {
|
|
41732
45010
|
colorSpace: altSpace,
|
|
41733
45011
|
colorSpaceLabel: isDevN ? "devn" : "sep",
|
|
@@ -41735,12 +45013,9 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
|
41735
45013
|
isSeparation: !isDevN,
|
|
41736
45014
|
isDeviceN: isDevN,
|
|
41737
45015
|
separationAltSpace: altSpace,
|
|
41738
|
-
|
|
41739
|
-
separationC1: c1,
|
|
41740
|
-
separationN: sepN,
|
|
45016
|
+
alternateCalibrated: altInfo.calibrated,
|
|
41741
45017
|
tintFunctionDoc: doc,
|
|
41742
|
-
tintFunctionNode: resolved.items[3]
|
|
41743
|
-
tintFunctionType
|
|
45018
|
+
tintFunctionNode: resolved.items[3]
|
|
41744
45019
|
};
|
|
41745
45020
|
}
|
|
41746
45021
|
}
|
|
@@ -41890,141 +45165,55 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
41890
45165
|
const rgba = new Uint8Array(width * height * 4);
|
|
41891
45166
|
const pixelCount = width * height;
|
|
41892
45167
|
if (csInfo.isSeparation || csInfo.isDeviceN) {
|
|
41893
|
-
const c0 = csInfo.separationC0 ?? [1, 1, 1];
|
|
41894
|
-
const c1 = csInfo.separationC1 ?? [0, 0, 0];
|
|
41895
|
-
const expN = csInfo.separationN ?? 1;
|
|
41896
45168
|
const alt = csInfo.separationAltSpace ?? "rgb";
|
|
41897
45169
|
const numCh = Math.max(1, csInfo.components);
|
|
41898
45170
|
const step = bpc === 16 ? 2 : 1;
|
|
41899
|
-
const useGenericTintFn = csInfo.tintFunctionDoc !== void 0 && csInfo.tintFunctionNode !== void 0 && (csInfo.tintFunctionType === 0 || csInfo.tintFunctionType === 3 || csInfo.tintFunctionType === 4);
|
|
41900
45171
|
for (let p = 0; p < pixelCount; p++) {
|
|
41901
45172
|
const chVals = [];
|
|
41902
|
-
let wSum = 0;
|
|
41903
45173
|
for (let ch3 = 0; ch3 < numCh; ch3++) {
|
|
41904
45174
|
const sRaw = (rawSamples[(p * numCh + ch3) * step] ?? 0) / 255;
|
|
41905
|
-
|
|
41906
|
-
chVals.push(tRemapped);
|
|
41907
|
-
wSum += Math.pow(Math.max(0, Math.min(1, tRemapped)), expN);
|
|
41908
|
-
}
|
|
41909
|
-
if (useGenericTintFn) {
|
|
41910
|
-
const outComps = evalShadingFunctionToComponents(
|
|
41911
|
-
csInfo.tintFunctionDoc,
|
|
41912
|
-
csInfo.tintFunctionNode,
|
|
41913
|
-
chVals
|
|
41914
|
-
);
|
|
41915
|
-
if (alt === "cmyk") {
|
|
41916
|
-
const c = outComps[0] ?? 0;
|
|
41917
|
-
const m = outComps[1] ?? 0;
|
|
41918
|
-
const y = outComps[2] ?? 0;
|
|
41919
|
-
const k = outComps[3] ?? 0;
|
|
41920
|
-
rgba[p * 4] = Math.round(Math.max(0, Math.min(1, (1 - c) * (1 - k))) * 255);
|
|
41921
|
-
rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, (1 - m) * (1 - k))) * 255);
|
|
41922
|
-
rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, (1 - y) * (1 - k))) * 255);
|
|
41923
|
-
} else if (alt === "gray") {
|
|
41924
|
-
const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
|
|
41925
|
-
rgba[p * 4] = gByte;
|
|
41926
|
-
rgba[p * 4 + 1] = gByte;
|
|
41927
|
-
rgba[p * 4 + 2] = gByte;
|
|
41928
|
-
} else {
|
|
41929
|
-
rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
|
|
41930
|
-
rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
|
|
41931
|
-
rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
|
|
41932
|
-
}
|
|
41933
|
-
rgba[p * 4 + 3] = 255;
|
|
41934
|
-
continue;
|
|
45175
|
+
chVals.push(remapUnitSampleWithDecode(sRaw, ch3, decodePairs));
|
|
41935
45176
|
}
|
|
41936
|
-
const
|
|
41937
|
-
|
|
41938
|
-
|
|
41939
|
-
|
|
41940
|
-
|
|
41941
|
-
|
|
41942
|
-
rgba
|
|
41943
|
-
|
|
41944
|
-
rgba[
|
|
45177
|
+
const outComps = evalShadingFunctionToComponents(
|
|
45178
|
+
csInfo.tintFunctionDoc,
|
|
45179
|
+
csInfo.tintFunctionNode,
|
|
45180
|
+
chVals
|
|
45181
|
+
);
|
|
45182
|
+
if (csInfo.alternateCalibrated) {
|
|
45183
|
+
rgba.set(csInfo.alternateCalibrated.getRgb(outComps, 0), p * 4);
|
|
45184
|
+
} else if (alt === "cmyk") {
|
|
45185
|
+
rgba.set(cmykColorSpace.getRgb([outComps[0] ?? 0, outComps[1] ?? 0, outComps[2] ?? 0, outComps[3] ?? 0], 0), p * 4);
|
|
41945
45186
|
} else if (alt === "gray") {
|
|
41946
|
-
const
|
|
41947
|
-
const gByte = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
|
|
45187
|
+
const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
|
|
41948
45188
|
rgba[p * 4] = gByte;
|
|
41949
45189
|
rgba[p * 4 + 1] = gByte;
|
|
41950
45190
|
rgba[p * 4 + 2] = gByte;
|
|
41951
45191
|
} else {
|
|
41952
|
-
|
|
41953
|
-
|
|
41954
|
-
|
|
41955
|
-
rgba[p * 4] = Math.round(Math.max(0, Math.min(1, rVal)) * 255);
|
|
41956
|
-
rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
|
|
41957
|
-
rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, bVal)) * 255);
|
|
45192
|
+
rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
|
|
45193
|
+
rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
|
|
45194
|
+
rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
|
|
41958
45195
|
}
|
|
41959
45196
|
rgba[p * 4 + 3] = 255;
|
|
41960
45197
|
}
|
|
41961
|
-
} else if (csInfo.
|
|
41962
|
-
const
|
|
41963
|
-
const
|
|
41964
|
-
const toSrgb = (u) => {
|
|
41965
|
-
const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
|
|
41966
|
-
return Math.round(Math.max(0, Math.min(1, c)) * 255);
|
|
41967
|
-
};
|
|
45198
|
+
} else if (csInfo.calibrated?.name === "Lab") {
|
|
45199
|
+
const { amin, amax, bmin, bmax } = csInfo.calibrated;
|
|
45200
|
+
const step = bpc === 16 ? 2 : 1;
|
|
41968
45201
|
for (let p = 0; p < pixelCount; p++) {
|
|
41969
|
-
const
|
|
41970
|
-
const
|
|
41971
|
-
const
|
|
41972
|
-
|
|
41973
|
-
if (L <= 0.01) {
|
|
41974
|
-
rgba[p * 4] = 0;
|
|
41975
|
-
rgba[p * 4 + 1] = 0;
|
|
41976
|
-
rgba[p * 4 + 2] = 0;
|
|
41977
|
-
rgba[p * 4 + 3] = 255;
|
|
41978
|
-
continue;
|
|
41979
|
-
}
|
|
41980
|
-
const a = amin + s1 * (amax - amin);
|
|
41981
|
-
const b = bmin + s2 * (bmax - bmin);
|
|
41982
|
-
const fy = (L + 16) / 116;
|
|
41983
|
-
const fx = fy + a / 500;
|
|
41984
|
-
const fz = fy - b / 200;
|
|
41985
|
-
const X = 0.95047 * invF(fx);
|
|
41986
|
-
const Y = 1 * invF(fy);
|
|
41987
|
-
const Z = 1.08883 * invF(fz);
|
|
41988
|
-
const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
|
|
41989
|
-
const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
|
|
41990
|
-
const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
|
|
41991
|
-
rgba[p * 4] = toSrgb(linR);
|
|
41992
|
-
rgba[p * 4 + 1] = toSrgb(linG);
|
|
41993
|
-
rgba[p * 4 + 2] = toSrgb(linB);
|
|
45202
|
+
const L = (rawSamples[p * 3 * step] ?? 0) / 255 * 100;
|
|
45203
|
+
const a = amin + (rawSamples[(p * 3 + 1) * step] ?? 128) / 255 * (amax - amin);
|
|
45204
|
+
const b = bmin + (rawSamples[(p * 3 + 2) * step] ?? 128) / 255 * (bmax - bmin);
|
|
45205
|
+
rgba.set(csInfo.calibrated.getRgb([L, a, b], 0), p * 4);
|
|
41994
45206
|
rgba[p * 4 + 3] = 255;
|
|
41995
45207
|
}
|
|
41996
45208
|
} else if (csInfo.colorSpace === "rgb") {
|
|
41997
|
-
const hasCalRgb = Boolean(csInfo.calRgbGamma || csInfo.calRgbMatrix);
|
|
41998
|
-
const toSrgbByte = (u) => {
|
|
41999
|
-
const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
|
|
42000
|
-
return Math.round(Math.max(0, Math.min(1, c)) * 255);
|
|
42001
|
-
};
|
|
42002
45209
|
const writeRgbPixel = (p, rByte, gByte, bByte) => {
|
|
42003
|
-
|
|
42004
|
-
|
|
42005
|
-
|
|
42006
|
-
if (
|
|
42007
|
-
|
|
42008
|
-
|
|
42009
|
-
|
|
42010
|
-
const cg = Math.pow(bU, gb);
|
|
42011
|
-
if (csInfo.calRgbMatrix && csInfo.calRgbMatrix.length >= 9) {
|
|
42012
|
-
const m = csInfo.calRgbMatrix;
|
|
42013
|
-
const X = m[0] * ag + m[3] * bg + m[6] * cg;
|
|
42014
|
-
const Y = m[1] * ag + m[4] * bg + m[7] * cg;
|
|
42015
|
-
const Z = m[2] * ag + m[5] * bg + m[8] * cg;
|
|
42016
|
-
const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
|
|
42017
|
-
const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
|
|
42018
|
-
const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
|
|
42019
|
-
rgba[p * 4] = toSrgbByte(linR);
|
|
42020
|
-
rgba[p * 4 + 1] = toSrgbByte(linG);
|
|
42021
|
-
rgba[p * 4 + 2] = toSrgbByte(linB);
|
|
42022
|
-
rgba[p * 4 + 3] = 255;
|
|
42023
|
-
return;
|
|
42024
|
-
}
|
|
42025
|
-
rU = ag;
|
|
42026
|
-
gU = bg;
|
|
42027
|
-
bU = cg;
|
|
45210
|
+
const rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
|
|
45211
|
+
const gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
|
|
45212
|
+
const bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
|
|
45213
|
+
if (csInfo.calibrated) {
|
|
45214
|
+
rgba.set(csInfo.calibrated.getRgb([rU, gU, bU], 0), p * 4);
|
|
45215
|
+
rgba[p * 4 + 3] = 255;
|
|
45216
|
+
return;
|
|
42028
45217
|
}
|
|
42029
45218
|
rgba[p * 4] = Math.round(rU * 255);
|
|
42030
45219
|
rgba[p * 4 + 1] = Math.round(gU * 255);
|
|
@@ -42044,10 +45233,11 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
42044
45233
|
}
|
|
42045
45234
|
} else if (csInfo.colorSpace === "gray") {
|
|
42046
45235
|
const writeGrayPixel = (p, gByte) => {
|
|
42047
|
-
|
|
42048
|
-
if (csInfo.
|
|
42049
|
-
|
|
42050
|
-
|
|
45236
|
+
const gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
|
|
45237
|
+
if (csInfo.calibrated) {
|
|
45238
|
+
rgba.set(csInfo.calibrated.getRgb([gU], 0), p * 4);
|
|
45239
|
+
rgba[p * 4 + 3] = 255;
|
|
45240
|
+
return;
|
|
42051
45241
|
}
|
|
42052
45242
|
const outG = Math.round(Math.max(0, Math.min(1, gU)) * 255);
|
|
42053
45243
|
rgba[p * 4] = outG;
|
|
@@ -42103,9 +45293,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
42103
45293
|
const m = remapUnitSampleWithDecode((rawSamples[p * stride + chStep] ?? 0) / 255, 1, decodePairs);
|
|
42104
45294
|
const y = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 2] ?? 0) / 255, 2, decodePairs);
|
|
42105
45295
|
const k = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 3] ?? 0) / 255, 3, decodePairs);
|
|
42106
|
-
rgba
|
|
42107
|
-
rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
|
|
42108
|
-
rgba[p * 4 + 2] = Math.round((1 - y) * (1 - k) * 255);
|
|
45296
|
+
rgba.set(cmykColorSpace.getRgb([c, m, y, k], 0), p * 4);
|
|
42109
45297
|
rgba[p * 4 + 3] = 255;
|
|
42110
45298
|
}
|
|
42111
45299
|
} else if (csInfo.colorSpace === "index") {
|
|
@@ -42143,9 +45331,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
42143
45331
|
const m = pal[idx * 4 + 1] / 255;
|
|
42144
45332
|
const yel = pal[idx * 4 + 2] / 255;
|
|
42145
45333
|
const k = pal[idx * 4 + 3] / 255;
|
|
42146
|
-
rgba
|
|
42147
|
-
rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
|
|
42148
|
-
rgba[p * 4 + 2] = Math.round((1 - yel) * (1 - k) * 255);
|
|
45334
|
+
rgba.set(cmykColorSpace.getRgb([c, m, yel, k], 0), p * 4);
|
|
42149
45335
|
} else {
|
|
42150
45336
|
rgba[p * 4] = pal[idx * baseComp];
|
|
42151
45337
|
rgba[p * 4 + 1] = pal[idx * baseComp + 1];
|
|
@@ -42400,6 +45586,7 @@ function decodeInlineImageNodeToRgba(doc, dict, rawData, activeRes, fillColor) {
|
|
|
42400
45586
|
});
|
|
42401
45587
|
return decodeXObjectImageToRgba(context, { kind: "stream", dict, rawBytes: rawData }, activeRes, fillColor);
|
|
42402
45588
|
}
|
|
45589
|
+
var cmykColorSpace2 = new DeviceCmykCS();
|
|
42403
45590
|
function multiplyMatrices(m1, m2) {
|
|
42404
45591
|
return [
|
|
42405
45592
|
m1[0] * m2[0] + m1[1] * m2[2],
|
|
@@ -42616,193 +45803,7 @@ function resolvePageFonts(doc, resourcesDict) {
|
|
|
42616
45803
|
}
|
|
42617
45804
|
return fonts;
|
|
42618
45805
|
}
|
|
42619
|
-
|
|
42620
|
-
const stack = [...initialStack];
|
|
42621
|
-
const runRange = (start, end) => {
|
|
42622
|
-
let i = start;
|
|
42623
|
-
while (i < end) {
|
|
42624
|
-
const tok = tokens[i];
|
|
42625
|
-
if (tok === "{") {
|
|
42626
|
-
let depth = 1;
|
|
42627
|
-
let j = i + 1;
|
|
42628
|
-
while (j < end && depth > 0) {
|
|
42629
|
-
if (tokens[j] === "{") depth++;
|
|
42630
|
-
else if (tokens[j] === "}") depth--;
|
|
42631
|
-
j++;
|
|
42632
|
-
}
|
|
42633
|
-
const blockStart = i + 1;
|
|
42634
|
-
const blockEnd = j - 1;
|
|
42635
|
-
if (j < end && tokens[j] === "{") {
|
|
42636
|
-
let depth2 = 1;
|
|
42637
|
-
let k = j + 1;
|
|
42638
|
-
while (k < end && depth2 > 0) {
|
|
42639
|
-
if (tokens[k] === "{") depth2++;
|
|
42640
|
-
else if (tokens[k] === "}") depth2--;
|
|
42641
|
-
k++;
|
|
42642
|
-
}
|
|
42643
|
-
if (k < end && tokens[k] === "ifelse") {
|
|
42644
|
-
const cond = stack.pop() ?? 0;
|
|
42645
|
-
if (cond !== 0) runRange(blockStart, blockEnd);
|
|
42646
|
-
else runRange(j + 1, k - 1);
|
|
42647
|
-
i = k + 1;
|
|
42648
|
-
continue;
|
|
42649
|
-
}
|
|
42650
|
-
}
|
|
42651
|
-
if (j < end && tokens[j] === "if") {
|
|
42652
|
-
const cond = stack.pop() ?? 0;
|
|
42653
|
-
if (cond !== 0) runRange(blockStart, blockEnd);
|
|
42654
|
-
i = j + 1;
|
|
42655
|
-
continue;
|
|
42656
|
-
}
|
|
42657
|
-
runRange(blockStart, blockEnd);
|
|
42658
|
-
i = j;
|
|
42659
|
-
continue;
|
|
42660
|
-
}
|
|
42661
|
-
if (tok === "}") {
|
|
42662
|
-
i++;
|
|
42663
|
-
continue;
|
|
42664
|
-
}
|
|
42665
|
-
const numVal2 = Number(tok);
|
|
42666
|
-
if (tok.length > 0 && !Number.isNaN(numVal2)) {
|
|
42667
|
-
stack.push(numVal2);
|
|
42668
|
-
} else if (tok === "true") {
|
|
42669
|
-
stack.push(1);
|
|
42670
|
-
} else if (tok === "false") {
|
|
42671
|
-
stack.push(0);
|
|
42672
|
-
} else if (tok === "add") {
|
|
42673
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
42674
|
-
stack.push(a + b);
|
|
42675
|
-
} else if (tok === "sub") {
|
|
42676
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
42677
|
-
stack.push(a - b);
|
|
42678
|
-
} else if (tok === "mul") {
|
|
42679
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
42680
|
-
stack.push(a * b);
|
|
42681
|
-
} else if (tok === "div") {
|
|
42682
|
-
const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
|
|
42683
|
-
stack.push(Math.abs(b) > 1e-12 ? a / b : 0);
|
|
42684
|
-
} else if (tok === "idiv") {
|
|
42685
|
-
const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
|
|
42686
|
-
stack.push(Math.abs(b) > 1e-12 ? Math.trunc(a / b) : 0);
|
|
42687
|
-
} else if (tok === "mod") {
|
|
42688
|
-
const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
|
|
42689
|
-
stack.push(Math.abs(b) > 1e-12 ? a % b : 0);
|
|
42690
|
-
} else if (tok === "neg") {
|
|
42691
|
-
stack.push(-(stack.pop() ?? 0));
|
|
42692
|
-
} else if (tok === "abs") {
|
|
42693
|
-
stack.push(Math.abs(stack.pop() ?? 0));
|
|
42694
|
-
} else if (tok === "ceiling") {
|
|
42695
|
-
stack.push(Math.ceil(stack.pop() ?? 0));
|
|
42696
|
-
} else if (tok === "floor") {
|
|
42697
|
-
stack.push(Math.floor(stack.pop() ?? 0));
|
|
42698
|
-
} else if (tok === "round") {
|
|
42699
|
-
stack.push(Math.round(stack.pop() ?? 0));
|
|
42700
|
-
} else if (tok === "truncate" || tok === "cvi") {
|
|
42701
|
-
stack.push(Math.trunc(stack.pop() ?? 0));
|
|
42702
|
-
} else if (tok === "sqrt") {
|
|
42703
|
-
stack.push(Math.sqrt(Math.max(0, stack.pop() ?? 0)));
|
|
42704
|
-
} else if (tok === "sin") {
|
|
42705
|
-
stack.push(Math.sin((stack.pop() ?? 0) * Math.PI / 180));
|
|
42706
|
-
} else if (tok === "cos") {
|
|
42707
|
-
stack.push(Math.cos((stack.pop() ?? 0) * Math.PI / 180));
|
|
42708
|
-
} else if (tok === "atan") {
|
|
42709
|
-
const dx = stack.pop() ?? 1, dy = stack.pop() ?? 0;
|
|
42710
|
-
let deg = Math.atan2(dy, dx) * 180 / Math.PI;
|
|
42711
|
-
if (deg < 0) deg += 360;
|
|
42712
|
-
stack.push(deg);
|
|
42713
|
-
} else if (tok === "exp") {
|
|
42714
|
-
const exp = stack.pop() ?? 1, base = stack.pop() ?? 0;
|
|
42715
|
-
stack.push(Math.pow(base, exp));
|
|
42716
|
-
} else if (tok === "ln") {
|
|
42717
|
-
stack.push(Math.log(Math.max(1e-12, stack.pop() ?? 1)));
|
|
42718
|
-
} else if (tok === "log") {
|
|
42719
|
-
stack.push(Math.log10(Math.max(1e-12, stack.pop() ?? 1)));
|
|
42720
|
-
} else if (tok === "dup") {
|
|
42721
|
-
if (stack.length > 0) stack.push(stack[stack.length - 1]);
|
|
42722
|
-
} else if (tok === "exch") {
|
|
42723
|
-
if (stack.length >= 2) {
|
|
42724
|
-
const b = stack.pop(), a = stack.pop();
|
|
42725
|
-
stack.push(b, a);
|
|
42726
|
-
}
|
|
42727
|
-
} else if (tok === "pop") {
|
|
42728
|
-
stack.pop();
|
|
42729
|
-
} else if (tok === "copy") {
|
|
42730
|
-
const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
|
|
42731
|
-
const slice = stack.slice(Math.max(0, stack.length - n));
|
|
42732
|
-
stack.push(...slice);
|
|
42733
|
-
} else if (tok === "index") {
|
|
42734
|
-
const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
|
|
42735
|
-
const idx = stack.length - 1 - n;
|
|
42736
|
-
if (idx >= 0 && idx < stack.length) stack.push(stack[idx]);
|
|
42737
|
-
} else if (tok === "roll") {
|
|
42738
|
-
const jShift = Math.trunc(stack.pop() ?? 0);
|
|
42739
|
-
const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
|
|
42740
|
-
if (n > 0 && stack.length >= n) {
|
|
42741
|
-
const sub = stack.splice(stack.length - n, n);
|
|
42742
|
-
const modShift = (jShift % n + n) % n;
|
|
42743
|
-
const rolled = [...sub.slice(n - modShift), ...sub.slice(0, n - modShift)];
|
|
42744
|
-
stack.push(...rolled);
|
|
42745
|
-
}
|
|
42746
|
-
} else if (tok === "eq") {
|
|
42747
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
42748
|
-
stack.push(Math.abs(a - b) < 1e-9 ? 1 : 0);
|
|
42749
|
-
} else if (tok === "ne") {
|
|
42750
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
42751
|
-
stack.push(Math.abs(a - b) >= 1e-9 ? 1 : 0);
|
|
42752
|
-
} else if (tok === "gt") {
|
|
42753
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
42754
|
-
stack.push(a > b ? 1 : 0);
|
|
42755
|
-
} else if (tok === "ge") {
|
|
42756
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
42757
|
-
stack.push(a >= b ? 1 : 0);
|
|
42758
|
-
} else if (tok === "lt") {
|
|
42759
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
42760
|
-
stack.push(a < b ? 1 : 0);
|
|
42761
|
-
} else if (tok === "le") {
|
|
42762
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
42763
|
-
stack.push(a <= b ? 1 : 0);
|
|
42764
|
-
} else if (tok === "and") {
|
|
42765
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
42766
|
-
stack.push(a !== 0 && b !== 0 ? 1 : 0);
|
|
42767
|
-
} else if (tok === "or") {
|
|
42768
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
42769
|
-
stack.push(a !== 0 || b !== 0 ? 1 : 0);
|
|
42770
|
-
} else if (tok === "not") {
|
|
42771
|
-
const a = stack.pop() ?? 0;
|
|
42772
|
-
stack.push(a === 0 ? 1 : 0);
|
|
42773
|
-
}
|
|
42774
|
-
i++;
|
|
42775
|
-
}
|
|
42776
|
-
};
|
|
42777
|
-
runRange(0, tokens.length);
|
|
42778
|
-
return stack;
|
|
42779
|
-
}
|
|
42780
|
-
function tokenizePostScriptCode(bytes) {
|
|
42781
|
-
const tokens = [];
|
|
42782
|
-
let cur = "";
|
|
42783
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
42784
|
-
const ch3 = String.fromCharCode(bytes[i]);
|
|
42785
|
-
if (ch3 === "{" || ch3 === "}") {
|
|
42786
|
-
if (cur.length > 0) {
|
|
42787
|
-
tokens.push(cur);
|
|
42788
|
-
cur = "";
|
|
42789
|
-
}
|
|
42790
|
-
tokens.push(ch3);
|
|
42791
|
-
} else if (ch3 === " " || ch3 === " " || ch3 === "\n" || ch3 === "\r") {
|
|
42792
|
-
if (cur.length > 0) {
|
|
42793
|
-
tokens.push(cur);
|
|
42794
|
-
cur = "";
|
|
42795
|
-
}
|
|
42796
|
-
} else {
|
|
42797
|
-
cur += ch3;
|
|
42798
|
-
}
|
|
42799
|
-
}
|
|
42800
|
-
if (cur.length > 0) tokens.push(cur);
|
|
42801
|
-
if (tokens[0] === "{" && tokens[tokens.length - 1] === "}") {
|
|
42802
|
-
return tokens.slice(1, -1);
|
|
42803
|
-
}
|
|
42804
|
-
return tokens;
|
|
42805
|
-
}
|
|
45806
|
+
var postScriptFunctions = /* @__PURE__ */ new WeakMap();
|
|
42806
45807
|
function evalShadingFunctionToComponents(doc, fnNode, inputs) {
|
|
42807
45808
|
const inArr = typeof inputs === "number" ? [inputs] : inputs;
|
|
42808
45809
|
const t = inArr[0] ?? 0;
|
|
@@ -42849,35 +45850,50 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
|
|
|
42849
45850
|
const decode = getNums("Decode", range);
|
|
42850
45851
|
const nOut = Math.max(1, Math.floor((decode.length || range.length || 6) / 2));
|
|
42851
45852
|
const mIn = Math.max(1, size.length);
|
|
42852
|
-
|
|
45853
|
+
const streamBytes = doc.decodeStream(resolved);
|
|
45854
|
+
let vertices = [{ index: 0, weight: 1 }];
|
|
42853
45855
|
let stride = 1;
|
|
42854
45856
|
for (let i = 0; i < mIn; i++) {
|
|
42855
45857
|
const d02 = dom[i * 2] ?? 0;
|
|
42856
45858
|
const d12 = dom[i * 2 + 1] ?? 1;
|
|
42857
|
-
const sMax = Math.max(
|
|
45859
|
+
const sMax = Math.max(0, (size[i] ?? 2) - 1);
|
|
42858
45860
|
const e0 = encode[i * 2] ?? 0;
|
|
42859
45861
|
const e1 = encode[i * 2 + 1] ?? sMax;
|
|
42860
45862
|
const x = Math.max(d02, Math.min(d12, inArr[i] ?? 0));
|
|
42861
|
-
const u =
|
|
42862
|
-
const
|
|
42863
|
-
|
|
45863
|
+
const u = d12 === d02 ? 0 : (x - d02) / (d12 - d02);
|
|
45864
|
+
const e = Math.max(0, Math.min(sMax, e0 + u * (e1 - e0)));
|
|
45865
|
+
const low = Math.floor(e), fraction = e - low;
|
|
45866
|
+
const next = [];
|
|
45867
|
+
for (const vertex of vertices) {
|
|
45868
|
+
const index = vertex.index + low * stride;
|
|
45869
|
+
if (index * nOut * bps < streamBytes.length * 8) next.push({ index, weight: vertex.weight * (1 - fraction) });
|
|
45870
|
+
if (fraction && (index + stride) * nOut * bps < streamBytes.length * 8) {
|
|
45871
|
+
next.push({ index: index + stride, weight: vertex.weight * fraction });
|
|
45872
|
+
}
|
|
45873
|
+
}
|
|
45874
|
+
vertices = next;
|
|
42864
45875
|
stride *= size[i] ?? 2;
|
|
42865
45876
|
}
|
|
42866
|
-
const
|
|
45877
|
+
const maxSample = 2 ** bps - 1;
|
|
45878
|
+
const readSample = (index) => {
|
|
45879
|
+
let bitOffset = index * bps, remaining = bps, value = 0;
|
|
45880
|
+
while (remaining > 0) {
|
|
45881
|
+
const bitInByte = bitOffset % 8;
|
|
45882
|
+
const take = Math.min(remaining, 8 - bitInByte);
|
|
45883
|
+
const byte = streamBytes[Math.floor(bitOffset / 8)] ?? 0;
|
|
45884
|
+
value = value * 2 ** take + (byte >> 8 - bitInByte - take & (1 << take) - 1);
|
|
45885
|
+
bitOffset += take;
|
|
45886
|
+
remaining -= take;
|
|
45887
|
+
}
|
|
45888
|
+
return value / maxSample;
|
|
45889
|
+
};
|
|
42867
45890
|
const out2 = [];
|
|
42868
|
-
const maxSample = bps === 16 ? 65535 : 255;
|
|
42869
45891
|
for (let j = 0; j < nOut; j++) {
|
|
42870
|
-
|
|
42871
|
-
|
|
42872
|
-
if (bps === 16) {
|
|
42873
|
-
rawVal = (streamBytes[sampleIdx * 2] ?? 0) << 8 | (streamBytes[sampleIdx * 2 + 1] ?? 0);
|
|
42874
|
-
} else {
|
|
42875
|
-
rawVal = streamBytes[sampleIdx] ?? 0;
|
|
42876
|
-
}
|
|
42877
|
-
const frac = rawVal / maxSample;
|
|
45892
|
+
let value = 0;
|
|
45893
|
+
for (const vertex of vertices) value += readSample(vertex.index * nOut + j) * vertex.weight;
|
|
42878
45894
|
const dec0 = decode[j * 2] ?? 0;
|
|
42879
45895
|
const dec1 = decode[j * 2 + 1] ?? 1;
|
|
42880
|
-
out2.push(dec0 +
|
|
45896
|
+
out2.push(dec0 + value * (dec1 - dec0));
|
|
42881
45897
|
}
|
|
42882
45898
|
return clampRange(out2);
|
|
42883
45899
|
}
|
|
@@ -42887,34 +45903,40 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
|
|
|
42887
45903
|
const d12 = dom[i * 2 + 1] ?? 1;
|
|
42888
45904
|
return Math.max(d02, Math.min(d12, v));
|
|
42889
45905
|
});
|
|
42890
|
-
const
|
|
42891
|
-
|
|
42892
|
-
|
|
45906
|
+
const source = bytesToString3(doc.decodeStream(resolved));
|
|
45907
|
+
let cached = postScriptFunctions.get(resolved);
|
|
45908
|
+
if (!cached || cached.source !== source || cached.domain.length !== dom.length || cached.domain.some((value, index) => value !== dom[index]) || cached.range.length !== range.length || cached.range.some((value, index) => value !== range[index])) {
|
|
45909
|
+
cached = { source, domain: dom, range, evaluate: buildPostScriptJsFunction(source, dom, range) };
|
|
45910
|
+
postScriptFunctions.set(resolved, cached);
|
|
45911
|
+
}
|
|
45912
|
+
const output = [];
|
|
45913
|
+
cached.evaluate(clampedInputs, 0, output, 0);
|
|
45914
|
+
return output;
|
|
42893
45915
|
}
|
|
42894
45916
|
if (ft === 3) {
|
|
42895
45917
|
const fnsArr = doc.resolveArray(dictGet(fnDict, "Functions"));
|
|
42896
45918
|
const bounds = getNums("Bounds", []);
|
|
42897
45919
|
const encode = getNums("Encode", []);
|
|
42898
45920
|
if (fnsArr && fnsArr.items.length > 0) {
|
|
45921
|
+
const input = Math.max(dom[0] ?? 0, Math.min(dom[1] ?? 1, t));
|
|
42899
45922
|
let segIdx = 0;
|
|
42900
|
-
while (segIdx < bounds.length &&
|
|
45923
|
+
while (segIdx < bounds.length && input >= bounds[segIdx]) segIdx++;
|
|
42901
45924
|
segIdx = Math.min(fnsArr.items.length - 1, segIdx);
|
|
42902
45925
|
const b0 = segIdx === 0 ? dom[0] ?? 0 : bounds[segIdx - 1];
|
|
42903
45926
|
const b1 = segIdx < bounds.length ? bounds[segIdx] : dom[1] ?? 1;
|
|
42904
45927
|
const e0 = encode[segIdx * 2] ?? 0;
|
|
42905
45928
|
const e1 = encode[segIdx * 2 + 1] ?? 1;
|
|
42906
|
-
const localT =
|
|
42907
|
-
return evalShadingFunctionToComponents(doc, fnsArr.items[segIdx],
|
|
45929
|
+
const localT = b1 !== b0 ? e0 + (input - b0) / (b1 - b0) * (e1 - e0) : e0;
|
|
45930
|
+
return clampRange(evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], localT));
|
|
42908
45931
|
}
|
|
42909
45932
|
}
|
|
42910
|
-
const c0 = getNums("C0", [0
|
|
42911
|
-
const c1 = getNums("C1", [1
|
|
45933
|
+
const c0 = getNums("C0", [0]);
|
|
45934
|
+
const c1 = getNums("C1", [1]);
|
|
42912
45935
|
const nNode = doc.resolve(dictGet(fnDict, "N"));
|
|
42913
|
-
const expN = nNode?.kind === "number"
|
|
45936
|
+
const expN = nNode?.kind === "number" ? nNode.value : 1;
|
|
42914
45937
|
const d0 = dom[0] ?? 0;
|
|
42915
45938
|
const d1 = dom[1] ?? 1;
|
|
42916
|
-
const
|
|
42917
|
-
const w = Math.pow(Math.max(0, Math.min(1, normT)), expN);
|
|
45939
|
+
const w = Math.pow(Math.max(d0, Math.min(d1, t)), expN);
|
|
42918
45940
|
const len = Math.max(c0.length, c1.length);
|
|
42919
45941
|
const out = [];
|
|
42920
45942
|
for (let i = 0; i < len; i++) {
|
|
@@ -42930,30 +45952,14 @@ function shadingComponentsToRgb(csName, comps) {
|
|
|
42930
45952
|
return [v, v, v];
|
|
42931
45953
|
}
|
|
42932
45954
|
if (csName === "DeviceCMYK" || csName === "CMYK" || comps.length >= 4) {
|
|
42933
|
-
const
|
|
42934
|
-
return [
|
|
45955
|
+
const rgb2 = cmykColorSpace2.getRgb([comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0, comps[3] ?? 0], 0);
|
|
45956
|
+
return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
|
|
42935
45957
|
}
|
|
42936
45958
|
return [comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0];
|
|
42937
45959
|
}
|
|
42938
45960
|
function kClamp(v) {
|
|
42939
45961
|
return Math.max(0, Math.min(1, v));
|
|
42940
45962
|
}
|
|
42941
|
-
function xyzToSrgb(X, Y, Z, Xw = 0.95047, Yw = 1, Zw = 1.08883) {
|
|
42942
|
-
const scaleX = Xw > 1e-6 ? 0.95047 / Xw : 1;
|
|
42943
|
-
const scaleY = Yw > 1e-6 ? 1 / Yw : 1;
|
|
42944
|
-
const scaleZ = Zw > 1e-6 ? 1.08883 / Zw : 1;
|
|
42945
|
-
const x = X * scaleX;
|
|
42946
|
-
const y = Y * scaleY;
|
|
42947
|
-
const z = Z * scaleZ;
|
|
42948
|
-
const rl = 3.2404542 * x - 1.5371385 * y - 0.4985314 * z;
|
|
42949
|
-
const gl = -0.969266 * x + 1.8760108 * y + 0.041556 * z;
|
|
42950
|
-
const bl = 0.0556434 * x - 0.2040259 * y + 1.0572252 * z;
|
|
42951
|
-
const toGamma = (u) => {
|
|
42952
|
-
const c = Math.max(0, Math.min(1, u));
|
|
42953
|
-
return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
|
|
42954
|
-
};
|
|
42955
|
-
return [toGamma(rl), toGamma(gl), toGamma(bl)];
|
|
42956
|
-
}
|
|
42957
45963
|
function getColorSpaceComponentCount(doc, csNode, activeResources, depth = 0) {
|
|
42958
45964
|
if (!csNode || depth > 4) return 3;
|
|
42959
45965
|
const resolved = doc ? doc.resolve(csNode) : csNode;
|
|
@@ -43010,63 +46016,10 @@ function convertColorSpaceComponentsToRgb(doc, csNode, csNameFallback, comps, ac
|
|
|
43010
46016
|
if (resolved.kind === "array" && resolved.items.length > 0 && doc) {
|
|
43011
46017
|
const familyNode = doc.resolve(resolved.items[0]);
|
|
43012
46018
|
const family = familyNode?.kind === "name" ? familyNode.decoded : "";
|
|
43013
|
-
if (family === "CalGray") {
|
|
43014
|
-
const
|
|
43015
|
-
const
|
|
43016
|
-
|
|
43017
|
-
const a = Math.pow(kClamp(comps[0] ?? 0), gamma);
|
|
43018
|
-
return [a, a, a];
|
|
43019
|
-
}
|
|
43020
|
-
if (family === "CalRGB") {
|
|
43021
|
-
const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
|
|
43022
|
-
const gammaArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Gamma")) : void 0;
|
|
43023
|
-
const getArrNum = (arr, idx, fb) => {
|
|
43024
|
-
const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
|
|
43025
|
-
return r?.kind === "number" ? r.value : fb;
|
|
43026
|
-
};
|
|
43027
|
-
const gr = getArrNum(gammaArr, 0, 1);
|
|
43028
|
-
const gg = getArrNum(gammaArr, 1, 1);
|
|
43029
|
-
const gb = getArrNum(gammaArr, 2, 1);
|
|
43030
|
-
const ag = Math.pow(kClamp(comps[0] ?? 0), gr > 0 ? gr : 1);
|
|
43031
|
-
const bg = Math.pow(kClamp(comps[1] ?? 0), gg > 0 ? gg : 1);
|
|
43032
|
-
const cg = Math.pow(kClamp(comps[2] ?? 0), gb > 0 ? gb : 1);
|
|
43033
|
-
const matArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Matrix")) : void 0;
|
|
43034
|
-
if (matArr && matArr.items.length >= 9) {
|
|
43035
|
-
const m = (i) => getArrNum(matArr, i, 0);
|
|
43036
|
-
const X = m(0) * ag + m(3) * bg + m(6) * cg;
|
|
43037
|
-
const Y = m(1) * ag + m(4) * bg + m(7) * cg;
|
|
43038
|
-
const Z = m(2) * ag + m(5) * bg + m(8) * cg;
|
|
43039
|
-
const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
|
|
43040
|
-
const Xw = getArrNum(wpArr, 0, 0.95047);
|
|
43041
|
-
const Yw = getArrNum(wpArr, 1, 1);
|
|
43042
|
-
const Zw = getArrNum(wpArr, 2, 1.08883);
|
|
43043
|
-
return xyzToSrgb(X, Y, Z, Xw, Yw, Zw);
|
|
43044
|
-
}
|
|
43045
|
-
return [ag, bg, cg];
|
|
43046
|
-
}
|
|
43047
|
-
if (family === "Lab") {
|
|
43048
|
-
const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
|
|
43049
|
-
const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
|
|
43050
|
-
const rangeArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Range")) : void 0;
|
|
43051
|
-
const getNum = (arr, idx, fb) => {
|
|
43052
|
-
const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
|
|
43053
|
-
return r?.kind === "number" ? r.value : fb;
|
|
43054
|
-
};
|
|
43055
|
-
const Xw = getNum(wpArr, 0, 0.95047);
|
|
43056
|
-
const Yw = getNum(wpArr, 1, 1);
|
|
43057
|
-
const Zw = getNum(wpArr, 2, 1.08883);
|
|
43058
|
-
const amin = getNum(rangeArr, 0, -100);
|
|
43059
|
-
const amax = getNum(rangeArr, 1, 100);
|
|
43060
|
-
const bmin = getNum(rangeArr, 2, -100);
|
|
43061
|
-
const bmax = getNum(rangeArr, 3, 100);
|
|
43062
|
-
const Lstar = Math.max(0, Math.min(100, comps[0] ?? 0));
|
|
43063
|
-
const astar = Math.max(amin, Math.min(amax, comps[1] ?? 0));
|
|
43064
|
-
const bstar = Math.max(bmin, Math.min(bmax, comps[2] ?? 0));
|
|
43065
|
-
const M = (Lstar + 16) / 116;
|
|
43066
|
-
const L = M + astar / 500;
|
|
43067
|
-
const N = M - bstar / 200;
|
|
43068
|
-
const gFn = (x) => x >= 6 / 29 ? x * x * x : 108 / 841 * (x - 4 / 29);
|
|
43069
|
-
return xyzToSrgb(Xw * gFn(L), Yw * gFn(M), Zw * gFn(N), Xw, Yw, Zw);
|
|
46019
|
+
if (family === "CalGray" || family === "CalRGB" || family === "Lab") {
|
|
46020
|
+
const colorSpace = createCalibratedColorSpace(doc, family, resolved.items[1]);
|
|
46021
|
+
const rgb2 = colorSpace.getRgb(comps, 0);
|
|
46022
|
+
return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
|
|
43070
46023
|
}
|
|
43071
46024
|
if (family === "ICCBased" && resolved.items[1]) {
|
|
43072
46025
|
const iccNode = doc.resolve(resolved.items[1]);
|
|
@@ -43147,143 +46100,28 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
|
|
|
43147
46100
|
const r = doc.resolve(it);
|
|
43148
46101
|
return r?.kind === "number" ? r.value : 0;
|
|
43149
46102
|
});
|
|
43150
|
-
const xmin = decodeNums[0], xmax = decodeNums[1], ymin = decodeNums[2], ymax = decodeNums[3];
|
|
43151
|
-
const numColorParams = Math.max(1, Math.floor((decodeNums.length - 4) / 2));
|
|
43152
46103
|
const fnNode = dictGet(shDict, "Function");
|
|
43153
46104
|
const csNode = doc.resolve(dictGet(shDict, "ColorSpace"));
|
|
43154
46105
|
const csName = csNode?.kind === "name" ? csNode.decoded : "DeviceRGB";
|
|
43155
|
-
|
|
43156
|
-
const
|
|
43157
|
-
|
|
43158
|
-
|
|
43159
|
-
|
|
43160
|
-
|
|
43161
|
-
|
|
43162
|
-
|
|
43163
|
-
|
|
43164
|
-
|
|
43165
|
-
|
|
43166
|
-
|
|
43167
|
-
|
|
43168
|
-
|
|
43169
|
-
|
|
43170
|
-
|
|
43171
|
-
|
|
43172
|
-
|
|
43173
|
-
|
|
43174
|
-
};
|
|
43175
|
-
const readColorRgb = () => {
|
|
43176
|
-
const params = [];
|
|
43177
|
-
for (let c = 0; c < numColorParams; c++) {
|
|
43178
|
-
const rc = readBits(bpcComp) / compMax;
|
|
43179
|
-
const cMin = decodeNums[4 + c * 2] ?? 0;
|
|
43180
|
-
const cMax = decodeNums[4 + c * 2 + 1] ?? 1;
|
|
43181
|
-
params.push(cMin + rc * (cMax - cMin));
|
|
43182
|
-
}
|
|
43183
|
-
const comps = fnNode ? evalShadingFunctionToComponents(doc, fnNode, params) : params;
|
|
43184
|
-
return convertColorSpaceComponentsToRgb(doc, csNode, csName, comps);
|
|
43185
|
-
};
|
|
43186
|
-
const triangles = [];
|
|
43187
|
-
if (shType === 4) {
|
|
43188
|
-
const minBitsPerVert = bpcFlag + 2 * bpcCoord + numColorParams * bpcComp;
|
|
43189
|
-
let triVerts;
|
|
43190
|
-
while (bitPos + minBitsPerVert <= totalBits) {
|
|
43191
|
-
const flag = readBits(bpcFlag) & 3;
|
|
43192
|
-
const [x, y] = readCoord();
|
|
43193
|
-
const rgb2 = readColorRgb();
|
|
43194
|
-
const vNew = { x, y, rgb: rgb2 };
|
|
43195
|
-
if (flag === 0 || !triVerts) {
|
|
43196
|
-
if (bitPos + 2 * minBitsPerVert > totalBits) break;
|
|
43197
|
-
readBits(bpcFlag);
|
|
43198
|
-
const [x1, y1] = readCoord();
|
|
43199
|
-
const rgb1 = readColorRgb();
|
|
43200
|
-
readBits(bpcFlag);
|
|
43201
|
-
const [x2, y2] = readCoord();
|
|
43202
|
-
const rgb22 = readColorRgb();
|
|
43203
|
-
triVerts = [vNew, { x: x1, y: y1, rgb: rgb1 }, { x: x2, y: y2, rgb: rgb22 }];
|
|
43204
|
-
triangles.push(triVerts);
|
|
43205
|
-
} else if (flag === 1) {
|
|
43206
|
-
triVerts = [triVerts[1], triVerts[2], vNew];
|
|
43207
|
-
triangles.push(triVerts);
|
|
43208
|
-
} else if (flag === 2) {
|
|
43209
|
-
triVerts = [triVerts[0], triVerts[2], vNew];
|
|
43210
|
-
triangles.push(triVerts);
|
|
43211
|
-
}
|
|
43212
|
-
}
|
|
43213
|
-
} else if (shType === 5) {
|
|
43214
|
-
const minBitsPerVert = 2 * bpcCoord + numColorParams * bpcComp;
|
|
43215
|
-
const verts = [];
|
|
43216
|
-
while (bitPos + minBitsPerVert <= totalBits) {
|
|
43217
|
-
const [x, y] = readCoord();
|
|
43218
|
-
const rgb2 = readColorRgb();
|
|
43219
|
-
verts.push({ x, y, rgb: rgb2 });
|
|
43220
|
-
}
|
|
43221
|
-
const numRows = Math.floor(verts.length / vPerRow);
|
|
43222
|
-
for (let r = 0; r + 1 < numRows; r++) {
|
|
43223
|
-
for (let c = 0; c + 1 < vPerRow; c++) {
|
|
43224
|
-
const v00 = verts[r * vPerRow + c];
|
|
43225
|
-
const v01 = verts[r * vPerRow + c + 1];
|
|
43226
|
-
const v11 = verts[(r + 1) * vPerRow + c + 1];
|
|
43227
|
-
const v10 = verts[(r + 1) * vPerRow + c];
|
|
43228
|
-
triangles.push([v00, v01, v11], [v00, v11, v10]);
|
|
43229
|
-
}
|
|
43230
|
-
}
|
|
43231
|
-
} else if (shType === 6 || shType === 7) {
|
|
43232
|
-
const numCtrl = shType === 6 ? 12 : 16;
|
|
43233
|
-
const minBitsPatch = bpcFlag + (numCtrl - 4) * 2 * bpcCoord + 2 * numColorParams * bpcComp;
|
|
43234
|
-
let prevPts;
|
|
43235
|
-
let prevColors;
|
|
43236
|
-
while (bitPos + minBitsPatch <= totalBits) {
|
|
43237
|
-
const flag = readBits(bpcFlag) & 3;
|
|
43238
|
-
let pts = [];
|
|
43239
|
-
let cols = [];
|
|
43240
|
-
if (flag === 0 || !prevPts || !prevColors) {
|
|
43241
|
-
for (let i = 0; i < numCtrl; i++) pts.push(readCoord());
|
|
43242
|
-
for (let i = 0; i < 4; i++) cols.push(readColorRgb());
|
|
43243
|
-
} else {
|
|
43244
|
-
const extraCtrl = numCtrl - 4;
|
|
43245
|
-
const readExtra = [];
|
|
43246
|
-
for (let i = 0; i < extraCtrl; i++) readExtra.push(readCoord());
|
|
43247
|
-
const c2 = readColorRgb();
|
|
43248
|
-
const c3 = readColorRgb();
|
|
43249
|
-
pts = [prevPts[3], prevPts[4], prevPts[5], prevPts[6], ...readExtra];
|
|
43250
|
-
cols = [prevColors[1], prevColors[2], c2, c3];
|
|
43251
|
-
}
|
|
43252
|
-
prevPts = pts;
|
|
43253
|
-
prevColors = cols;
|
|
43254
|
-
const p00 = pts[0];
|
|
43255
|
-
const p03 = pts[3];
|
|
43256
|
-
const p33 = pts[6];
|
|
43257
|
-
const p30 = pts[9];
|
|
43258
|
-
const c00 = cols[0], c03 = cols[1], c33 = cols[2], c30 = cols[3];
|
|
43259
|
-
const steps = 4;
|
|
43260
|
-
const grid = [];
|
|
43261
|
-
for (let iu = 0; iu <= steps; iu++) {
|
|
43262
|
-
const u = iu / steps;
|
|
43263
|
-
const row = [];
|
|
43264
|
-
for (let iv = 0; iv <= steps; iv++) {
|
|
43265
|
-
const v = iv / steps;
|
|
43266
|
-
const x = (1 - u) * (1 - v) * p00[0] + (1 - u) * v * p03[0] + u * v * p33[0] + u * (1 - v) * p30[0];
|
|
43267
|
-
const y = (1 - u) * (1 - v) * p00[1] + (1 - u) * v * p03[1] + u * v * p33[1] + u * (1 - v) * p30[1];
|
|
43268
|
-
const r = (1 - u) * (1 - v) * c00[0] + (1 - u) * v * c03[0] + u * v * c33[0] + u * (1 - v) * c30[0];
|
|
43269
|
-
const g = (1 - u) * (1 - v) * c00[1] + (1 - u) * v * c03[1] + u * v * c33[1] + u * (1 - v) * c30[1];
|
|
43270
|
-
const b = (1 - u) * (1 - v) * c00[2] + (1 - u) * v * c03[2] + u * v * c33[2] + u * (1 - v) * c30[2];
|
|
43271
|
-
row.push({ x, y, rgb: [r, g, b] });
|
|
43272
|
-
}
|
|
43273
|
-
grid.push(row);
|
|
43274
|
-
}
|
|
43275
|
-
for (let iu = 0; iu < steps; iu++) {
|
|
43276
|
-
for (let iv = 0; iv < steps; iv++) {
|
|
43277
|
-
const g00 = grid[iu][iv];
|
|
43278
|
-
const g01 = grid[iu][iv + 1];
|
|
43279
|
-
const g11 = grid[iu + 1][iv + 1];
|
|
43280
|
-
const g10 = grid[iu + 1][iv];
|
|
43281
|
-
triangles.push([g00, g01, g11], [g00, g11, g10]);
|
|
43282
|
-
}
|
|
43283
|
-
}
|
|
43284
|
-
}
|
|
43285
|
-
}
|
|
43286
|
-
if (triangles.length === 0) return void 0;
|
|
46106
|
+
const numComps = fnNode ? 1 : getColorSpaceComponentCount(doc, csNode);
|
|
46107
|
+
const mesh = new MeshShading(shType, new Stream(bytes), {
|
|
46108
|
+
bitsPerCoordinate: bpcCoord,
|
|
46109
|
+
bitsPerComponent: bpcComp,
|
|
46110
|
+
bitsPerFlag: bpcFlag,
|
|
46111
|
+
decode: decodeNums,
|
|
46112
|
+
numComps,
|
|
46113
|
+
colorFn: null,
|
|
46114
|
+
colorSpace: {
|
|
46115
|
+
numComps,
|
|
46116
|
+
getRgb(components2) {
|
|
46117
|
+
const params = Array.from(components2);
|
|
46118
|
+
const values = fnNode ? evalShadingFunctionToComponents(doc, fnNode, params) : params;
|
|
46119
|
+
return new Uint8Array(convertColorSpaceComponentsToRgb(doc, csNode, csName, values).map((value) => Math.round(Math.max(0, Math.min(1, value)) * 255)));
|
|
46120
|
+
}
|
|
46121
|
+
}
|
|
46122
|
+
}, vPerRow);
|
|
46123
|
+
const [, , positions, colors, vertexCount] = mesh.getIR();
|
|
46124
|
+
if (vertexCount === 0) return void 0;
|
|
43287
46125
|
const [bx0, by0, bx1, by1] = targetBox;
|
|
43288
46126
|
const boxW = Math.max(1, bx1 - bx0);
|
|
43289
46127
|
const boxH = Math.max(1, by1 - by0);
|
|
@@ -43295,10 +46133,10 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
|
|
|
43295
46133
|
const [px, py] = transformPoint(effectiveCtm, vx, vy);
|
|
43296
46134
|
return [(px - bx0) / boxW * imgW, (by1 - py) / boxH * imgH];
|
|
43297
46135
|
};
|
|
43298
|
-
for (
|
|
43299
|
-
const [x0, y0] = toImgCoords(
|
|
43300
|
-
const [x1, y1] = toImgCoords(
|
|
43301
|
-
const [x2, y2] = toImgCoords(
|
|
46136
|
+
for (let vertex = 0; vertex < vertexCount; vertex += 3) {
|
|
46137
|
+
const [x0, y0] = toImgCoords(positions[vertex * 2], positions[vertex * 2 + 1]);
|
|
46138
|
+
const [x1, y1] = toImgCoords(positions[vertex * 2 + 2], positions[vertex * 2 + 3]);
|
|
46139
|
+
const [x2, y2] = toImgCoords(positions[vertex * 2 + 4], positions[vertex * 2 + 5]);
|
|
43302
46140
|
const denom = (y1 - y2) * (x0 - x2) + (x2 - x1) * (y0 - y2);
|
|
43303
46141
|
if (Math.abs(denom) < 1e-6) continue;
|
|
43304
46142
|
const minX = Math.max(0, Math.floor(Math.min(x0, x1, x2)));
|
|
@@ -43313,13 +46151,12 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
|
|
|
43313
46151
|
const w1 = ((y2 - y0) * (px - x2) + (x0 - x2) * (py - y2)) / denom;
|
|
43314
46152
|
const w2 = 1 - w0 - w1;
|
|
43315
46153
|
if (w0 >= -1e-4 && w1 >= -1e-4 && w2 >= -1e-4) {
|
|
43316
|
-
const r = w0 * v0.rgb[0] + w1 * v1.rgb[0] + w2 * v2.rgb[0];
|
|
43317
|
-
const g = w0 * v0.rgb[1] + w1 * v1.rgb[1] + w2 * v2.rgb[1];
|
|
43318
|
-
const b = w0 * v0.rgb[2] + w1 * v1.rgb[2] + w2 * v2.rgb[2];
|
|
43319
46154
|
const pIdx = (iy * imgW + ix) * 4;
|
|
43320
|
-
|
|
43321
|
-
|
|
43322
|
-
|
|
46155
|
+
for (let channel = 0; channel < 3; channel++) {
|
|
46156
|
+
rgba[pIdx + channel] = Math.round(
|
|
46157
|
+
w0 * colors[vertex * 4 + channel] + w1 * colors[vertex * 4 + 4 + channel] + w2 * colors[vertex * 4 + 8 + channel]
|
|
46158
|
+
);
|
|
46159
|
+
}
|
|
43323
46160
|
rgba[pIdx + 3] = a8;
|
|
43324
46161
|
}
|
|
43325
46162
|
}
|
|
@@ -43406,6 +46243,8 @@ function renderShadingDictToImage(doc, shDict, shadingCtm, targetBox, fillAlpha,
|
|
|
43406
46243
|
const [a, b, c, d, e, f] = effectiveCtm;
|
|
43407
46244
|
const det = a * d - b * c;
|
|
43408
46245
|
if (Math.abs(det) <= 1e-8) return void 0;
|
|
46246
|
+
const [sa, sb, sc, sd, se, sf] = shadingCtm;
|
|
46247
|
+
const shadingDet = sa * sd - sb * sc;
|
|
43409
46248
|
const t0Dom = shDomain[0] ?? 0;
|
|
43410
46249
|
const t1Dom = shDomain[1] ?? 1;
|
|
43411
46250
|
for (let iy = 0; iy < imgH; iy++) {
|
|
@@ -43416,8 +46255,10 @@ function renderShadingDictToImage(doc, shDict, shadingCtm, targetBox, fillAlpha,
|
|
|
43416
46255
|
const dxPdf = xPdf - e;
|
|
43417
46256
|
const xs = (d * dxPdf - c * dyPdf) / det;
|
|
43418
46257
|
const ys = (-b * dxPdf + a * dyPdf) / det;
|
|
43419
|
-
if (shBBox
|
|
43420
|
-
|
|
46258
|
+
if (shBBox) {
|
|
46259
|
+
const bboxX = (sd * (xPdf - se) - sc * (yPdf - sf)) / shadingDet;
|
|
46260
|
+
const bboxY = (-sb * (xPdf - se) + sa * (yPdf - sf)) / shadingDet;
|
|
46261
|
+
if (bboxX < shBBox[0] || bboxX > shBBox[2] || bboxY < shBBox[1] || bboxY > shBBox[3]) continue;
|
|
43421
46262
|
}
|
|
43422
46263
|
let comps;
|
|
43423
46264
|
if (shType === 1) {
|
|
@@ -43717,7 +46558,8 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
43717
46558
|
const shDict = shNode?.kind === "dict" ? shNode : shNode?.kind === "stream" ? shNode.dict : void 0;
|
|
43718
46559
|
const shStream = shNode?.kind === "stream" ? shNode : void 0;
|
|
43719
46560
|
if (shDict) {
|
|
43720
|
-
const
|
|
46561
|
+
const [originX, originY] = params.origin ?? [0, 0];
|
|
46562
|
+
const targetBox = st.clipRect ?? [originX, originY, originX + params.width, originY + params.height];
|
|
43721
46563
|
const img = renderShadingDictToImage(
|
|
43722
46564
|
params.cosDoc,
|
|
43723
46565
|
shDict,
|
|
@@ -43756,12 +46598,10 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
43756
46598
|
} else if (operator === "RG" || operator === "SC" || operator === "SCN") {
|
|
43757
46599
|
st.strokeColor = resolveScColorOperands(operator === "RG" ? "DeviceRGB" : st.strokeColorSpaceName, ops, activeResources);
|
|
43758
46600
|
} else if (operator === "k") {
|
|
43759
|
-
|
|
43760
|
-
st.fillColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
|
|
46601
|
+
st.fillColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
|
|
43761
46602
|
st.fillPatternName = void 0;
|
|
43762
46603
|
} else if (operator === "K") {
|
|
43763
|
-
|
|
43764
|
-
st.strokeColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
|
|
46604
|
+
st.strokeColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
|
|
43765
46605
|
} else if (operator === "gs" && params.cosDoc && activeResources && ops[0]?.kind === "name") {
|
|
43766
46606
|
const extDict = params.cosDoc.resolveDict(dictGet(activeResources, "ExtGState"));
|
|
43767
46607
|
const gsDict = extDict ? params.cosDoc.resolveDict(dictGet(extDict, ops[0].decoded)) : void 0;
|
|
@@ -43970,7 +46810,7 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
43970
46810
|
stateStack.pop();
|
|
43971
46811
|
capturedOperations = parentOperations;
|
|
43972
46812
|
}
|
|
43973
|
-
if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
|
|
46813
|
+
if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, isolated, bboxClip: nextClipPaths?.[0], blendMode: st.blendMode, clipRect: st.clipRect } });
|
|
43974
46814
|
};
|
|
43975
46815
|
const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
|
|
43976
46816
|
for (const node of nodes) {
|
|
@@ -44554,6 +47394,7 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
44554
47394
|
pageIndex: params.pageIndex,
|
|
44555
47395
|
width: params.width,
|
|
44556
47396
|
height: params.height,
|
|
47397
|
+
...params.origin ? { origin: params.origin } : {},
|
|
44557
47398
|
rotation: params.rotation ?? 0,
|
|
44558
47399
|
glyphs,
|
|
44559
47400
|
paths,
|
|
@@ -46024,7 +48865,7 @@ var PdfPage = class {
|
|
|
46024
48865
|
return [n0.value, n1.value, n2.value, n3.value];
|
|
46025
48866
|
}
|
|
46026
48867
|
}
|
|
46027
|
-
return [0, 0, 612, 792];
|
|
48868
|
+
return key === "MediaBox" ? [0, 0, 612, 792] : this.resolveBox("MediaBox");
|
|
46028
48869
|
}
|
|
46029
48870
|
getMediaBox() {
|
|
46030
48871
|
return this.resolveBox("MediaBox");
|
|
@@ -46697,16 +49538,19 @@ var PdfPage = class {
|
|
|
46697
49538
|
});
|
|
46698
49539
|
}
|
|
46699
49540
|
}
|
|
46700
|
-
|
|
49541
|
+
const mediaBox = this.getMediaBox(), cropBox = this.getCropBox();
|
|
49542
|
+
const originX = Math.min(mediaBox[0], mediaBox[2]), originY = Math.min(mediaBox[1], mediaBox[3]);
|
|
49543
|
+
return { ...evaluateContentStreamToDisplayList({
|
|
46701
49544
|
pageIndex: this.index,
|
|
46702
49545
|
width,
|
|
46703
49546
|
height,
|
|
49547
|
+
origin: [originX, originY],
|
|
46704
49548
|
rotation: this.getRotation(),
|
|
46705
49549
|
nodes: baseNodes,
|
|
46706
49550
|
cosDoc: this.cosDoc,
|
|
46707
49551
|
resourcesDict: evalResourcesDict,
|
|
46708
49552
|
annotations: extractPageAnnotations(this.cosDoc, this.pageDict)
|
|
46709
|
-
});
|
|
49553
|
+
}), cropBox: [cropBox[0] - originX, cropBox[1] - originY, cropBox[2] - originX, cropBox[3] - originY] };
|
|
46710
49554
|
}
|
|
46711
49555
|
extractPage(options) {
|
|
46712
49556
|
const dl = this.evaluateDisplayList();
|
|
@@ -46724,10 +49568,10 @@ var PdfPage = class {
|
|
|
46724
49568
|
return extractTablesFromDisplayList(this.evaluateDisplayList());
|
|
46725
49569
|
}
|
|
46726
49570
|
renderToBitmap(options) {
|
|
46727
|
-
return renderDisplayListToBitmap(this.evaluateDisplayList(), options);
|
|
49571
|
+
return renderDisplayListToBitmap(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
|
|
46728
49572
|
}
|
|
46729
49573
|
renderToPng(options) {
|
|
46730
|
-
return renderDisplayListToPng(this.evaluateDisplayList(), options);
|
|
49574
|
+
return renderDisplayListToPng(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
|
|
46731
49575
|
}
|
|
46732
49576
|
};
|
|
46733
49577
|
function createStandardFontHandle(standardName) {
|
|
@@ -47777,7 +50621,7 @@ function prepareStroke(path, scale) {
|
|
|
47777
50621
|
}
|
|
47778
50622
|
return { matrix, width, dashArray, dashPhase };
|
|
47779
50623
|
}
|
|
47780
|
-
function strokeContours(path, pageHeight, scale) {
|
|
50624
|
+
function strokeContours(path, pageHeight, scale, originX = 0, originY = 0) {
|
|
47781
50625
|
const stroke = prepareStroke(path, scale);
|
|
47782
50626
|
if (!stroke) return [];
|
|
47783
50627
|
const inverse = inverseStrokeMatrix(stroke.matrix);
|
|
@@ -47789,8 +50633,8 @@ function strokeContours(path, pageHeight, scale) {
|
|
|
47789
50633
|
(inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
|
|
47790
50634
|
];
|
|
47791
50635
|
const toScreen = ([x, y]) => [
|
|
47792
|
-
(a * x / strokeScale + c * y / strokeScale + e) * scale,
|
|
47793
|
-
(pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
|
|
50636
|
+
(a * x / strokeScale + c * y / strokeScale + e - originX) * scale,
|
|
50637
|
+
(pageHeight + originY - b * x / strokeScale - d * y / strokeScale - f) * scale
|
|
47794
50638
|
];
|
|
47795
50639
|
const contours = strokeOutlines(
|
|
47796
50640
|
segmentsToScreenPaths(path.segments, pageHeight, scale, project),
|
|
@@ -47948,18 +50792,34 @@ function renderSoftMask(mask, displayList, scale) {
|
|
|
47948
50792
|
}
|
|
47949
50793
|
return bitmap;
|
|
47950
50794
|
}
|
|
47951
|
-
function
|
|
47952
|
-
|
|
50795
|
+
function getDisplayListCropBox(list) {
|
|
50796
|
+
const full = [0, 0, list.width, list.height];
|
|
50797
|
+
const box = list.cropBox;
|
|
50798
|
+
if (!box || !box.every(Number.isFinite)) return full;
|
|
50799
|
+
const x0 = Math.max(0, Math.min(box[0], box[2]));
|
|
50800
|
+
const y0 = Math.max(0, Math.min(box[1], box[3]));
|
|
50801
|
+
const x1 = Math.min(list.width, Math.max(box[0], box[2]));
|
|
50802
|
+
const y1 = Math.min(list.height, Math.max(box[1], box[3]));
|
|
50803
|
+
return x1 > x0 && y1 > y0 ? [x0, y0, x1, y1] : full;
|
|
50804
|
+
}
|
|
50805
|
+
function hasCompositingEffects(operations, includeSoftMasks = false) {
|
|
50806
|
+
return operations.some((operation) => includeSoftMasks && !!operation.value.softMask || !!operation.value.blendMode && operation.value.blendMode !== "Normal" && operation.value.blendMode !== "Compatible" || operation.kind === "group" && hasCompositingEffects(operation.value.operations, includeSoftMasks));
|
|
50807
|
+
}
|
|
50808
|
+
function needsGroupBackdrop(group) {
|
|
50809
|
+
return group.isolated === false && !!group.softMask && hasCompositingEffects(group.operations, true);
|
|
47953
50810
|
}
|
|
47954
50811
|
function renderDisplayListToBitmap(displayList, options = {}) {
|
|
47955
50812
|
const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
|
|
47956
50813
|
const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
|
|
47957
50814
|
const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
|
|
47958
50815
|
const scale = scaleX;
|
|
50816
|
+
const [originX, originY] = displayList.origin ?? [0, 0];
|
|
50817
|
+
const pageTop = originY + displayList.height;
|
|
50818
|
+
const toScreen = (x, y) => [(x - originX) * scale, (pageTop - y) * scale];
|
|
47959
50819
|
const width = Math.max(1, Math.round(displayList.width * scale));
|
|
47960
50820
|
const height = Math.max(1, Math.round(displayList.height * scale));
|
|
47961
50821
|
const rgba = new Uint8Array(width * height * 4);
|
|
47962
|
-
const deferBackground = !options.transparent &&
|
|
50822
|
+
const deferBackground = !options.transparent && hasCompositingEffects(paintOperations(displayList));
|
|
47963
50823
|
const transparent = options.transparent || deferBackground;
|
|
47964
50824
|
const bg = options.background ?? { r: 1, g: 1, b: 1 };
|
|
47965
50825
|
const bgR = transparent ? 0 : Math.round(bg.r * 255);
|
|
@@ -47984,14 +50844,27 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
47984
50844
|
let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
|
|
47985
50845
|
if (operation.kind === "group") {
|
|
47986
50846
|
const group = operation.value;
|
|
47987
|
-
|
|
50847
|
+
let operations = group.operations;
|
|
50848
|
+
if (needsGroupBackdrop(group)) {
|
|
50849
|
+
operations = [{ kind: "image", value: {
|
|
50850
|
+
name: "GroupBackdrop",
|
|
50851
|
+
width,
|
|
50852
|
+
height,
|
|
50853
|
+
decodedRgba: rgba.slice(),
|
|
50854
|
+
matrix: [width / scale, 0, 0, height / scale, originX, pageTop - height / scale],
|
|
50855
|
+
colorSpace: "DeviceRGB",
|
|
50856
|
+
bitsPerComponent: 8,
|
|
50857
|
+
...group.bboxClip ? { clipPaths: [group.bboxClip] } : {}
|
|
50858
|
+
} }, ...operations];
|
|
50859
|
+
}
|
|
50860
|
+
const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, useCropBox: false, transparent: true });
|
|
47988
50861
|
for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
|
|
47989
50862
|
operation = { kind: "image", value: {
|
|
47990
50863
|
name: "TransparencyGroup",
|
|
47991
50864
|
width: bitmap.width,
|
|
47992
50865
|
height: bitmap.height,
|
|
47993
50866
|
decodedRgba: bitmap.data,
|
|
47994
|
-
matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale,
|
|
50867
|
+
matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, originX, pageTop - bitmap.height / scale],
|
|
47995
50868
|
colorSpace: "DeviceRGB",
|
|
47996
50869
|
bitsPerComponent: 8,
|
|
47997
50870
|
blendMode: group.blendMode,
|
|
@@ -48005,7 +50878,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
48005
50878
|
for (const clip of clips) {
|
|
48006
50879
|
const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
|
|
48007
50880
|
const layer = new Uint8Array(width * height * 4);
|
|
48008
|
-
fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
|
|
50881
|
+
fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale, toScreen), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
|
|
48009
50882
|
for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
|
|
48010
50883
|
}
|
|
48011
50884
|
cachedClips = clips;
|
|
@@ -48052,15 +50925,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
48052
50925
|
if (operation.kind === "path") {
|
|
48053
50926
|
const path = operation.value;
|
|
48054
50927
|
if (path.fillColor) {
|
|
48055
|
-
const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale), true);
|
|
48056
|
-
const clipScreen = path.clipRect ? [path.clipRect[0] * scale, (
|
|
50928
|
+
const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale, toScreen), true);
|
|
50929
|
+
const clipScreen = path.clipRect ? [(path.clipRect[0] - originX) * scale, (pageTop - path.clipRect[3]) * scale, (path.clipRect[2] - originX) * scale, (pageTop - path.clipRect[1]) * scale] : void 0;
|
|
48057
50930
|
fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
|
|
48058
50931
|
}
|
|
48059
50932
|
if (path.strokeColor) {
|
|
48060
50933
|
const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
|
|
48061
50934
|
const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
|
|
48062
|
-
const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
|
|
48063
|
-
const clipScreen = path.clipRect ? [path.clipRect[0] * scale, (
|
|
50935
|
+
const edges = pathsToEdges(strokeContours(path, displayList.height, scale, originX, originY).map((points) => ({ points, closed: true })));
|
|
50936
|
+
const clipScreen = path.clipRect ? [(path.clipRect[0] - originX) * scale, (pageTop - path.clipRect[3]) * scale, (path.clipRect[2] - originX) * scale, (pageTop - path.clipRect[1]) * scale] : void 0;
|
|
48064
50937
|
fillEdgesScanline4x4(
|
|
48065
50938
|
rgba,
|
|
48066
50939
|
width,
|
|
@@ -48083,12 +50956,12 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
48083
50956
|
if (Math.abs(det) <= 1e-8) continue;
|
|
48084
50957
|
const cornersPdfX = [e, a + e, a + c + e, c + e];
|
|
48085
50958
|
const cornersPdfY = [f, b + f, b + d + f, d + f];
|
|
48086
|
-
const cornersPx = cornersPdfX.map((cx) => cx * scale);
|
|
48087
|
-
const cornersPy = cornersPdfY.map((cy) => (
|
|
48088
|
-
const clipMinPx = img.clipRect ? Math.floor(img.clipRect[0] * scale) : 0;
|
|
48089
|
-
const clipMaxPx = img.clipRect ? Math.ceil(img.clipRect[2] * scale) - 1 : width - 1;
|
|
48090
|
-
const clipMinPy = img.clipRect ? Math.floor((
|
|
48091
|
-
const clipMaxPy = img.clipRect ? Math.ceil((
|
|
50959
|
+
const cornersPx = cornersPdfX.map((cx) => (cx - originX) * scale);
|
|
50960
|
+
const cornersPy = cornersPdfY.map((cy) => (pageTop - cy) * scale);
|
|
50961
|
+
const clipMinPx = img.clipRect ? Math.floor((img.clipRect[0] - originX) * scale) : 0;
|
|
50962
|
+
const clipMaxPx = img.clipRect ? Math.ceil((img.clipRect[2] - originX) * scale) - 1 : width - 1;
|
|
50963
|
+
const clipMinPy = img.clipRect ? Math.floor((pageTop - img.clipRect[3]) * scale) : 0;
|
|
50964
|
+
const clipMaxPy = img.clipRect ? Math.ceil((pageTop - img.clipRect[1]) * scale) - 1 : height - 1;
|
|
48092
50965
|
const minPx = Math.max(0, clipMinPx, Math.floor(Math.min(...cornersPx)));
|
|
48093
50966
|
const maxPx = Math.min(width - 1, clipMaxPx, Math.ceil(Math.max(...cornersPx)) - 1);
|
|
48094
50967
|
const minPy = Math.max(0, clipMinPy, Math.floor(Math.min(...cornersPy)));
|
|
@@ -48105,11 +50978,11 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
48105
50978
|
const smooth = Math.fround((s1 + s2 + Math.hypot(s1 - s2, 2 * cross)) / 2) <= 1;
|
|
48106
50979
|
const sample = new Float64Array(4);
|
|
48107
50980
|
for (let py = minPy; py <= maxPy; py++) {
|
|
48108
|
-
const yPdf =
|
|
50981
|
+
const yPdf = pageTop - (py + 0.5) / scale;
|
|
48109
50982
|
if (img.clipRect && (yPdf < img.clipRect[1] || yPdf > img.clipRect[3])) continue;
|
|
48110
50983
|
const dyPdf = yPdf - f;
|
|
48111
50984
|
for (let px = minPx; px <= maxPx; px++) {
|
|
48112
|
-
const xPdf = (px + 0.5) / scale;
|
|
50985
|
+
const xPdf = originX + (px + 0.5) / scale;
|
|
48113
50986
|
if (img.clipRect && (xPdf < img.clipRect[0] || xPdf > img.clipRect[2])) continue;
|
|
48114
50987
|
const dxPdf = xPdf - e;
|
|
48115
50988
|
const u = (d * dxPdf - c * dyPdf) / det;
|
|
@@ -48170,6 +51043,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
48170
51043
|
}
|
|
48171
51044
|
result = { width: targetW, height: targetH, data: resampled };
|
|
48172
51045
|
}
|
|
51046
|
+
if (options.useCropBox) {
|
|
51047
|
+
const box = getDisplayListCropBox(displayList);
|
|
51048
|
+
result = cropRgbaBitmap(result, {
|
|
51049
|
+
x: box[0] * scaleX,
|
|
51050
|
+
y: (displayList.height - box[3]) * scaleY,
|
|
51051
|
+
width: (box[2] - box[0]) * scaleX,
|
|
51052
|
+
height: (box[3] - box[1]) * scaleY
|
|
51053
|
+
});
|
|
51054
|
+
}
|
|
48173
51055
|
result = rotateRgbaBitmapQuarterTurns(result, displayList.rotation ?? 0);
|
|
48174
51056
|
if (options.cropRect) {
|
|
48175
51057
|
result = cropRgbaBitmap(result, options.cropRect);
|
|
@@ -48198,23 +51080,6 @@ function collectLeavesForRaster(cosDoc, node, out = [], visited = /* @__PURE__ *
|
|
|
48198
51080
|
}
|
|
48199
51081
|
return out;
|
|
48200
51082
|
}
|
|
48201
|
-
function extractBoxArray(cosDoc, dict, key) {
|
|
48202
|
-
let cur = dict;
|
|
48203
|
-
const visited = /* @__PURE__ */ new Set();
|
|
48204
|
-
while (cur && !visited.has(cur)) {
|
|
48205
|
-
visited.add(cur);
|
|
48206
|
-
const arr = cosDoc.resolveArray(dictGet(cur, key));
|
|
48207
|
-
if (arr && arr.items.length >= 4) {
|
|
48208
|
-
const nums = arr.items.slice(0, 4).map((item) => {
|
|
48209
|
-
const r = cosDoc.resolve(item);
|
|
48210
|
-
return r?.kind === "number" ? r.value : 0;
|
|
48211
|
-
});
|
|
48212
|
-
return [nums[0], nums[1], nums[2], nums[3]];
|
|
48213
|
-
}
|
|
48214
|
-
cur = cosDoc.resolveDict(dictGet(cur, "Parent"));
|
|
48215
|
-
}
|
|
48216
|
-
return void 0;
|
|
48217
|
-
}
|
|
48218
51083
|
function renderPdfPageToBitmap(pdfBytes, pageIndex = 0, options) {
|
|
48219
51084
|
const cos = pdfBytes instanceof Uint8Array ? parseCosDocument(pdfBytes) : pdfBytes;
|
|
48220
51085
|
const catalog = cos.resolveDict(cos.rootRef);
|
|
@@ -48223,35 +51088,7 @@ function renderPdfPageToBitmap(pdfBytes, pageIndex = 0, options) {
|
|
|
48223
51088
|
if (!leaf) throw new Error(`Page index ${pageIndex} out of bounds`);
|
|
48224
51089
|
const resolvedIndex = leaves.indexOf(leaf);
|
|
48225
51090
|
const page = new PdfPage(cos, leaf.ref, leaf.dict, resolvedIndex);
|
|
48226
|
-
|
|
48227
|
-
let bitmap = renderDisplayListToBitmap(
|
|
48228
|
-
// CropBox is in unrotated page coordinates. Apply page rotation after it.
|
|
48229
|
-
{ ...page.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), rotation: 0 },
|
|
48230
|
-
restOptions
|
|
48231
|
-
);
|
|
48232
|
-
if (options?.useCropBox) {
|
|
48233
|
-
const cropBox = extractBoxArray(cos, leaf.dict, "CropBox");
|
|
48234
|
-
if (cropBox) {
|
|
48235
|
-
const mediaBox = extractBoxArray(cos, leaf.dict, "MediaBox") ?? [0, 0, page.getSize().width, page.getSize().height];
|
|
48236
|
-
const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
|
|
48237
|
-
const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
|
|
48238
|
-
const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
|
|
48239
|
-
const mediaH = mediaBox[3] - mediaBox[1];
|
|
48240
|
-
const bx = Math.round((cropBox[0] - mediaBox[0]) * scaleX);
|
|
48241
|
-
const by = Math.round((mediaH - (cropBox[3] - mediaBox[1])) * scaleY);
|
|
48242
|
-
const bw = Math.max(1, Math.round(Math.abs(cropBox[2] - cropBox[0]) * scaleX));
|
|
48243
|
-
const bh = Math.max(1, Math.round(Math.abs(cropBox[3] - cropBox[1]) * scaleY));
|
|
48244
|
-
bitmap = cropRgbaBitmap(bitmap, { x: bx, y: by, width: bw, height: bh });
|
|
48245
|
-
}
|
|
48246
|
-
}
|
|
48247
|
-
const rotation = page.getRotation();
|
|
48248
|
-
if (rotation === 90 || rotation === 180 || rotation === 270) {
|
|
48249
|
-
bitmap = rotateRgbaBitmapQuarterTurns(bitmap, rotation);
|
|
48250
|
-
}
|
|
48251
|
-
if (cropRect) {
|
|
48252
|
-
bitmap = cropRgbaBitmap(bitmap, cropRect);
|
|
48253
|
-
}
|
|
48254
|
-
return bitmap;
|
|
51091
|
+
return page.renderToBitmap(options);
|
|
48255
51092
|
}
|
|
48256
51093
|
function renderPdfPageToPng(pdfBytes, pageIndex = 0, options) {
|
|
48257
51094
|
const bmp = renderPdfPageToBitmap(pdfBytes, pageIndex, options);
|