@poe-platform/safe-bash 0.1.771 → 0.1.773
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/image-ast/index.browser.js +2801 -556
- package/dist/image-ast/index.js +2801 -556
- 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 +2845 -568
- package/dist/pdf-ast/render/raster.d.ts +1 -0
- package/dist/pdf-ast/vendor/pdfjs-fonts.d.mts +24 -0
- package/dist/pdf-ast/vendor/pdfjs-fonts.mjs +2621 -0
- package/dist/safe-bash/chunks/{chunk-FSH7QRIC.js → chunk-Z3HX3ZBA.js} +10 -4
- package/dist/safe-bash/command-chunks/{chunk-M2XU2YCK.js → chunk-5VXZSNM2.js} +2 -2
- package/dist/safe-bash/command-chunks/{chunk-C4AAJTXF.js → chunk-B2MM5DIT.js} +2804 -556
- package/dist/safe-bash/command-chunks/{chunk-NBENXODJ.js → chunk-G3NVK25P.js} +1 -1
- package/dist/safe-bash/commands/python/host-capabilities.js +15 -6
- package/dist/safe-bash/commands/python/index.browser.js +1 -1
- package/dist/safe-bash/core.browser.js +39 -39
- 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-command-ffmpeg/index.js +10968 -9719
- 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-imagemagick/index.js +2 -2
- 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 +2800 -510
- package/dist/safe-bash-command-pdfinfo/index.js +2842 -568
- package/dist/safe-bash-command-pdftk/index.js +2800 -510
- package/dist/safe-bash-command-pdftoppm/index.js +2847 -637
- package/dist/safe-bash-command-pdftotext/index.js +2800 -510
- package/dist/safe-bash-command-qpdf/index.js +2800 -510
- 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 +2811 -566
- package/dist/safe-bash-command-wkhtmltopdf/index.js +2833 -510
- 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 +62 -1
|
@@ -22706,6 +22706,2614 @@ var PageViewport = class _PageViewport {
|
|
|
22706
22706
|
return p;
|
|
22707
22707
|
}
|
|
22708
22708
|
};
|
|
22709
|
+
function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
|
|
22710
|
+
const COMPONENTS = 3;
|
|
22711
|
+
alpha01 = alpha01 !== 1 ? 0 : alpha01;
|
|
22712
|
+
const xRatio = w1 / w2;
|
|
22713
|
+
const yRatio = h1 / h2;
|
|
22714
|
+
let newIndex = 0, oldIndex;
|
|
22715
|
+
const xScaled = new Uint16Array(w2);
|
|
22716
|
+
const w1Scanline = w1 * COMPONENTS;
|
|
22717
|
+
for (let i = 0; i < w2; i++) {
|
|
22718
|
+
xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
|
|
22719
|
+
}
|
|
22720
|
+
for (let i = 0; i < h2; i++) {
|
|
22721
|
+
const py = Math.floor(i * yRatio) * w1Scanline;
|
|
22722
|
+
for (let j = 0; j < w2; j++) {
|
|
22723
|
+
oldIndex = py + xScaled[j];
|
|
22724
|
+
dest[newIndex++] = src[oldIndex++];
|
|
22725
|
+
dest[newIndex++] = src[oldIndex++];
|
|
22726
|
+
dest[newIndex++] = src[oldIndex++];
|
|
22727
|
+
newIndex += alpha01;
|
|
22728
|
+
}
|
|
22729
|
+
}
|
|
22730
|
+
}
|
|
22731
|
+
function isDefaultDecodeHelper(decode, expectedLen) {
|
|
22732
|
+
if (!Array.isArray(decode)) {
|
|
22733
|
+
return true;
|
|
22734
|
+
}
|
|
22735
|
+
const decodeLen = decode.length;
|
|
22736
|
+
if (decodeLen < expectedLen) {
|
|
22737
|
+
warn2("Decode map length is too short.");
|
|
22738
|
+
return true;
|
|
22739
|
+
}
|
|
22740
|
+
if (decodeLen > expectedLen) {
|
|
22741
|
+
info("Truncating too long decode map.");
|
|
22742
|
+
decode.length = expectedLen;
|
|
22743
|
+
}
|
|
22744
|
+
return false;
|
|
22745
|
+
}
|
|
22746
|
+
var ColorSpace = class _ColorSpace {
|
|
22747
|
+
static #rgbBuf = new Uint8ClampedArray(3);
|
|
22748
|
+
constructor(name, numComps) {
|
|
22749
|
+
if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _ColorSpace) {
|
|
22750
|
+
unreachable2("Cannot initialize ColorSpace.");
|
|
22751
|
+
}
|
|
22752
|
+
this.name = name;
|
|
22753
|
+
this.numComps = numComps;
|
|
22754
|
+
}
|
|
22755
|
+
/**
|
|
22756
|
+
* Converts the color value to the RGB color. The color components are
|
|
22757
|
+
* located in the src array starting from the srcOffset. Returns the array
|
|
22758
|
+
* of the rgb components, each value ranging from [0,255].
|
|
22759
|
+
*/
|
|
22760
|
+
getRgb(src, srcOffset, output = new Uint8ClampedArray(3)) {
|
|
22761
|
+
this.getRgbItem(src, srcOffset, output, 0);
|
|
22762
|
+
return output;
|
|
22763
|
+
}
|
|
22764
|
+
getRgbHex(src, srcOffset) {
|
|
22765
|
+
const buffer = this.getRgb(src, srcOffset, _ColorSpace.#rgbBuf);
|
|
22766
|
+
return Util.makeHexColor(buffer[0], buffer[1], buffer[2]);
|
|
22767
|
+
}
|
|
22768
|
+
/**
|
|
22769
|
+
* Converts the color value to the RGB color, similar to the getRgb method.
|
|
22770
|
+
* The result placed into the dest array starting from the destOffset.
|
|
22771
|
+
*/
|
|
22772
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
22773
|
+
unreachable2("Should not call ColorSpace.getRgbItem");
|
|
22774
|
+
}
|
|
22775
|
+
/**
|
|
22776
|
+
* Converts the specified number of the color values to the RGB colors.
|
|
22777
|
+
* The colors are located in the src array starting from the srcOffset.
|
|
22778
|
+
* The result is placed into the dest array starting from the destOffset.
|
|
22779
|
+
* The src array items shall be in [0,2^bits) range, the dest array items
|
|
22780
|
+
* will be in [0,255] range. alpha01 indicates how many alpha components
|
|
22781
|
+
* there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
|
|
22782
|
+
* array).
|
|
22783
|
+
*/
|
|
22784
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
22785
|
+
unreachable2("Should not call ColorSpace.getRgbBuffer");
|
|
22786
|
+
}
|
|
22787
|
+
/**
|
|
22788
|
+
* Converts `count` unscaled colors to RGB, starting at `destOffset`.
|
|
22789
|
+
* Components use the native color-space ranges expected by `getRgbItem`,
|
|
22790
|
+
* and each output has a `3 + alpha01` byte stride.
|
|
22791
|
+
* Subclasses may override this to batch expensive conversions.
|
|
22792
|
+
*/
|
|
22793
|
+
getRgbItems(src, count, dest, destOffset, alpha01) {
|
|
22794
|
+
const { numComps } = this;
|
|
22795
|
+
for (let i = 0, srcOffset = 0; i < count; i++, srcOffset += numComps) {
|
|
22796
|
+
this.getRgbItem(src, srcOffset, dest, destOffset);
|
|
22797
|
+
destOffset += 3 + alpha01;
|
|
22798
|
+
}
|
|
22799
|
+
}
|
|
22800
|
+
/**
|
|
22801
|
+
* Returns true if source data will be equal the result/output data.
|
|
22802
|
+
*/
|
|
22803
|
+
isPassthrough(bits) {
|
|
22804
|
+
return false;
|
|
22805
|
+
}
|
|
22806
|
+
/**
|
|
22807
|
+
* Refer to the static `ColorSpace.isDefaultDecode` method below.
|
|
22808
|
+
*/
|
|
22809
|
+
isDefaultDecode(decode, bpc) {
|
|
22810
|
+
return _ColorSpace.isDefaultDecode(decode, this.numComps);
|
|
22811
|
+
}
|
|
22812
|
+
/**
|
|
22813
|
+
* Fills in the RGB colors in the destination buffer. alpha01 indicates
|
|
22814
|
+
* how many alpha components there are in the dest array; it will be either
|
|
22815
|
+
* 0 (RGB array) or 1 (RGBA array).
|
|
22816
|
+
*/
|
|
22817
|
+
fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {
|
|
22818
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
22819
|
+
assert2(
|
|
22820
|
+
dest instanceof Uint8ClampedArray,
|
|
22821
|
+
'ColorSpace.fillRgb: Unsupported "dest" type.'
|
|
22822
|
+
);
|
|
22823
|
+
}
|
|
22824
|
+
const count = originalWidth * originalHeight;
|
|
22825
|
+
let rgbBuf = null;
|
|
22826
|
+
const numComponentColors = 1 << bpc;
|
|
22827
|
+
const needsResizing = originalHeight !== height || originalWidth !== width;
|
|
22828
|
+
if (this.isPassthrough(bpc)) {
|
|
22829
|
+
rgbBuf = comps;
|
|
22830
|
+
} else if (this.numComps === 1 && count > numComponentColors && this.name !== "DeviceGray" && this.name !== "DeviceRGB") {
|
|
22831
|
+
const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);
|
|
22832
|
+
for (let i = 0; i < numComponentColors; i++) {
|
|
22833
|
+
allColors[i] = i;
|
|
22834
|
+
}
|
|
22835
|
+
const colorMap = new Uint8ClampedArray(numComponentColors * 3);
|
|
22836
|
+
this.getRgbBuffer(
|
|
22837
|
+
allColors,
|
|
22838
|
+
0,
|
|
22839
|
+
numComponentColors,
|
|
22840
|
+
colorMap,
|
|
22841
|
+
0,
|
|
22842
|
+
bpc,
|
|
22843
|
+
/* alpha01 = */
|
|
22844
|
+
0
|
|
22845
|
+
);
|
|
22846
|
+
if (!needsResizing) {
|
|
22847
|
+
let destPos = 0;
|
|
22848
|
+
for (let i = 0; i < count; ++i) {
|
|
22849
|
+
const key = comps[i] * 3;
|
|
22850
|
+
dest[destPos++] = colorMap[key];
|
|
22851
|
+
dest[destPos++] = colorMap[key + 1];
|
|
22852
|
+
dest[destPos++] = colorMap[key + 2];
|
|
22853
|
+
destPos += alpha01;
|
|
22854
|
+
}
|
|
22855
|
+
} else {
|
|
22856
|
+
rgbBuf = new Uint8Array(count * 3);
|
|
22857
|
+
let rgbPos = 0;
|
|
22858
|
+
for (let i = 0; i < count; ++i) {
|
|
22859
|
+
const key = comps[i] * 3;
|
|
22860
|
+
rgbBuf[rgbPos++] = colorMap[key];
|
|
22861
|
+
rgbBuf[rgbPos++] = colorMap[key + 1];
|
|
22862
|
+
rgbBuf[rgbPos++] = colorMap[key + 2];
|
|
22863
|
+
}
|
|
22864
|
+
}
|
|
22865
|
+
} else if (!needsResizing) {
|
|
22866
|
+
this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);
|
|
22867
|
+
} else {
|
|
22868
|
+
rgbBuf = new Uint8ClampedArray(count * 3);
|
|
22869
|
+
this.getRgbBuffer(
|
|
22870
|
+
comps,
|
|
22871
|
+
0,
|
|
22872
|
+
count,
|
|
22873
|
+
rgbBuf,
|
|
22874
|
+
0,
|
|
22875
|
+
bpc,
|
|
22876
|
+
/* alpha01 = */
|
|
22877
|
+
0
|
|
22878
|
+
);
|
|
22879
|
+
}
|
|
22880
|
+
if (rgbBuf) {
|
|
22881
|
+
if (needsResizing) {
|
|
22882
|
+
resizeRgbImage(
|
|
22883
|
+
rgbBuf,
|
|
22884
|
+
dest,
|
|
22885
|
+
originalWidth,
|
|
22886
|
+
originalHeight,
|
|
22887
|
+
width,
|
|
22888
|
+
height,
|
|
22889
|
+
alpha01
|
|
22890
|
+
);
|
|
22891
|
+
} else {
|
|
22892
|
+
let destPos = 0, rgbPos = 0;
|
|
22893
|
+
for (let i = 0, ii = width * actualHeight; i < ii; i++) {
|
|
22894
|
+
dest[destPos++] = rgbBuf[rgbPos++];
|
|
22895
|
+
dest[destPos++] = rgbBuf[rgbPos++];
|
|
22896
|
+
dest[destPos++] = rgbBuf[rgbPos++];
|
|
22897
|
+
destPos += alpha01;
|
|
22898
|
+
}
|
|
22899
|
+
}
|
|
22900
|
+
}
|
|
22901
|
+
}
|
|
22902
|
+
/**
|
|
22903
|
+
* True if the colorspace has components in the default range of [0, 1].
|
|
22904
|
+
* This should be true for all colorspaces except for lab color spaces
|
|
22905
|
+
* which are [0,100], [-128, 127], [-128, 127].
|
|
22906
|
+
*/
|
|
22907
|
+
get usesZeroToOneRange() {
|
|
22908
|
+
return shadow2(this, "usesZeroToOneRange", true);
|
|
22909
|
+
}
|
|
22910
|
+
/**
|
|
22911
|
+
* Checks if a decode map matches the default decode map for a color space.
|
|
22912
|
+
* This handles the general decode maps where there are two values per
|
|
22913
|
+
* component, e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
|
|
22914
|
+
* This does not handle Lab, Indexed, or Pattern decode maps since they are
|
|
22915
|
+
* slightly different.
|
|
22916
|
+
* @param {Array} decode - Decode map (usually from an image).
|
|
22917
|
+
* @param {number} numComps - Number of components the color space has.
|
|
22918
|
+
*/
|
|
22919
|
+
static isDefaultDecode(decode, numComps) {
|
|
22920
|
+
if (isDefaultDecodeHelper(decode, numComps * 2)) {
|
|
22921
|
+
return true;
|
|
22922
|
+
}
|
|
22923
|
+
for (let i = 0, ii = decode.length; i < ii; i += 2) {
|
|
22924
|
+
if (decode[i] !== 0 || decode[i + 1] !== 1) {
|
|
22925
|
+
return false;
|
|
22926
|
+
}
|
|
22927
|
+
}
|
|
22928
|
+
return true;
|
|
22929
|
+
}
|
|
22930
|
+
};
|
|
22931
|
+
var DeviceCmykCS = class extends ColorSpace {
|
|
22932
|
+
constructor() {
|
|
22933
|
+
super("DeviceCMYK", 4);
|
|
22934
|
+
}
|
|
22935
|
+
// The coefficients below was found using numerical analysis: the method of
|
|
22936
|
+
// steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
|
|
22937
|
+
// where color_value is the tabular value from the table of sampled RGB colors
|
|
22938
|
+
// from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
|
|
22939
|
+
// CMYK color conversion using the estimation below:
|
|
22940
|
+
// f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
|
|
22941
|
+
#toRgb(src, srcOffset, srcScale, dest, destOffset) {
|
|
22942
|
+
const c = src[srcOffset] * srcScale;
|
|
22943
|
+
const m = src[srcOffset + 1] * srcScale;
|
|
22944
|
+
const y = src[srcOffset + 2] * srcScale;
|
|
22945
|
+
const k = src[srcOffset + 3] * srcScale;
|
|
22946
|
+
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);
|
|
22947
|
+
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);
|
|
22948
|
+
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);
|
|
22949
|
+
}
|
|
22950
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
22951
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
22952
|
+
assert2(
|
|
22953
|
+
dest instanceof Uint8ClampedArray,
|
|
22954
|
+
'DeviceCmykCS.getRgbItem: Unsupported "dest" type.'
|
|
22955
|
+
);
|
|
22956
|
+
}
|
|
22957
|
+
this.#toRgb(src, srcOffset, 1, dest, destOffset);
|
|
22958
|
+
}
|
|
22959
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
22960
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
22961
|
+
assert2(
|
|
22962
|
+
dest instanceof Uint8ClampedArray,
|
|
22963
|
+
'DeviceCmykCS.getRgbBuffer: Unsupported "dest" type.'
|
|
22964
|
+
);
|
|
22965
|
+
}
|
|
22966
|
+
const scale = 1 / ((1 << bits) - 1);
|
|
22967
|
+
for (let i = 0; i < count; i++) {
|
|
22968
|
+
this.#toRgb(src, srcOffset, scale, dest, destOffset);
|
|
22969
|
+
srcOffset += 4;
|
|
22970
|
+
destOffset += 3 + alpha01;
|
|
22971
|
+
}
|
|
22972
|
+
}
|
|
22973
|
+
};
|
|
22974
|
+
var CalGrayCS = class extends ColorSpace {
|
|
22975
|
+
constructor(whitePoint, blackPoint, gamma) {
|
|
22976
|
+
super("CalGray", 1);
|
|
22977
|
+
if (!whitePoint) {
|
|
22978
|
+
throw new FormatError(
|
|
22979
|
+
"WhitePoint missing - required for color space CalGray"
|
|
22980
|
+
);
|
|
22981
|
+
}
|
|
22982
|
+
[this.XW, this.YW, this.ZW] = whitePoint;
|
|
22983
|
+
[this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
|
|
22984
|
+
this.G = gamma || 1;
|
|
22985
|
+
if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
|
|
22986
|
+
throw new FormatError(
|
|
22987
|
+
`Invalid WhitePoint components for ${this.name}, no fallback available`
|
|
22988
|
+
);
|
|
22989
|
+
}
|
|
22990
|
+
if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
|
|
22991
|
+
info(`Invalid BlackPoint for ${this.name}, falling back to default.`);
|
|
22992
|
+
this.XB = this.YB = this.ZB = 0;
|
|
22993
|
+
}
|
|
22994
|
+
if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
|
|
22995
|
+
warn2(
|
|
22996
|
+
`${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ZB: ${this.ZB}, only default values are supported.`
|
|
22997
|
+
);
|
|
22998
|
+
}
|
|
22999
|
+
if (this.G < 1) {
|
|
23000
|
+
info(
|
|
23001
|
+
`Invalid Gamma: ${this.G} for ${this.name}, falling back to default.`
|
|
23002
|
+
);
|
|
23003
|
+
this.G = 1;
|
|
23004
|
+
}
|
|
23005
|
+
}
|
|
23006
|
+
#toRgb(src, srcOffset, dest, destOffset, scale) {
|
|
23007
|
+
const A = src[srcOffset] * scale;
|
|
23008
|
+
const AG = A ** this.G;
|
|
23009
|
+
const L = this.YW * AG;
|
|
23010
|
+
const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0);
|
|
23011
|
+
dest[destOffset] = val;
|
|
23012
|
+
dest[destOffset + 1] = val;
|
|
23013
|
+
dest[destOffset + 2] = val;
|
|
23014
|
+
}
|
|
23015
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
23016
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
23017
|
+
assert2(
|
|
23018
|
+
dest instanceof Uint8ClampedArray,
|
|
23019
|
+
'CalGrayCS.getRgbItem: Unsupported "dest" type.'
|
|
23020
|
+
);
|
|
23021
|
+
}
|
|
23022
|
+
this.#toRgb(src, srcOffset, dest, destOffset, 1);
|
|
23023
|
+
}
|
|
23024
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
23025
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
23026
|
+
assert2(
|
|
23027
|
+
dest instanceof Uint8ClampedArray,
|
|
23028
|
+
'CalGrayCS.getRgbBuffer: Unsupported "dest" type.'
|
|
23029
|
+
);
|
|
23030
|
+
}
|
|
23031
|
+
const scale = 1 / ((1 << bits) - 1);
|
|
23032
|
+
for (let i = 0; i < count; ++i) {
|
|
23033
|
+
this.#toRgb(src, srcOffset, dest, destOffset, scale);
|
|
23034
|
+
srcOffset += 1;
|
|
23035
|
+
destOffset += 3 + alpha01;
|
|
23036
|
+
}
|
|
23037
|
+
}
|
|
23038
|
+
};
|
|
23039
|
+
var CalRGBCS = class _CalRGBCS extends ColorSpace {
|
|
23040
|
+
// See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these
|
|
23041
|
+
// matrices.
|
|
23042
|
+
// prettier-ignore
|
|
23043
|
+
static #BRADFORD_SCALE_MATRIX = new Float32Array([
|
|
23044
|
+
0.8951,
|
|
23045
|
+
0.2664,
|
|
23046
|
+
-0.1614,
|
|
23047
|
+
-0.7502,
|
|
23048
|
+
1.7135,
|
|
23049
|
+
0.0367,
|
|
23050
|
+
0.0389,
|
|
23051
|
+
-0.0685,
|
|
23052
|
+
1.0296
|
|
23053
|
+
]);
|
|
23054
|
+
// prettier-ignore
|
|
23055
|
+
static #BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([
|
|
23056
|
+
0.9869929,
|
|
23057
|
+
-0.1470543,
|
|
23058
|
+
0.1599627,
|
|
23059
|
+
0.4323053,
|
|
23060
|
+
0.5183603,
|
|
23061
|
+
0.0492912,
|
|
23062
|
+
-85287e-7,
|
|
23063
|
+
0.0400428,
|
|
23064
|
+
0.9684867
|
|
23065
|
+
]);
|
|
23066
|
+
// See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html.
|
|
23067
|
+
// prettier-ignore
|
|
23068
|
+
static #SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([
|
|
23069
|
+
3.2404542,
|
|
23070
|
+
-1.5371385,
|
|
23071
|
+
-0.4985314,
|
|
23072
|
+
-0.969266,
|
|
23073
|
+
1.8760108,
|
|
23074
|
+
0.041556,
|
|
23075
|
+
0.0556434,
|
|
23076
|
+
-0.2040259,
|
|
23077
|
+
1.0572252
|
|
23078
|
+
]);
|
|
23079
|
+
static #FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);
|
|
23080
|
+
static #tempNormalizeMatrix = new Float32Array(3);
|
|
23081
|
+
static #tempConvertMatrix1 = new Float32Array(3);
|
|
23082
|
+
static #tempConvertMatrix2 = new Float32Array(3);
|
|
23083
|
+
static #DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8;
|
|
23084
|
+
constructor(whitePoint, blackPoint, gamma, matrix) {
|
|
23085
|
+
super("CalRGB", 3);
|
|
23086
|
+
if (!whitePoint) {
|
|
23087
|
+
throw new FormatError(
|
|
23088
|
+
"WhitePoint missing - required for color space CalRGB"
|
|
23089
|
+
);
|
|
23090
|
+
}
|
|
23091
|
+
const [XW, YW, ZW] = this.whitePoint = whitePoint;
|
|
23092
|
+
const [XB, YB, ZB] = this.blackPoint = blackPoint || new Float32Array(3);
|
|
23093
|
+
[this.GR, this.GG, this.GB] = gamma || new Float32Array([1, 1, 1]);
|
|
23094
|
+
[
|
|
23095
|
+
this.MXA,
|
|
23096
|
+
this.MYA,
|
|
23097
|
+
this.MZA,
|
|
23098
|
+
this.MXB,
|
|
23099
|
+
this.MYB,
|
|
23100
|
+
this.MZB,
|
|
23101
|
+
this.MXC,
|
|
23102
|
+
this.MYC,
|
|
23103
|
+
this.MZC
|
|
23104
|
+
] = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
|
|
23105
|
+
if (XW < 0 || ZW < 0 || YW !== 1) {
|
|
23106
|
+
throw new FormatError(
|
|
23107
|
+
`Invalid WhitePoint components for ${this.name}, no fallback available`
|
|
23108
|
+
);
|
|
23109
|
+
}
|
|
23110
|
+
if (XB < 0 || YB < 0 || ZB < 0) {
|
|
23111
|
+
info(
|
|
23112
|
+
`Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], falling back to default.`
|
|
23113
|
+
);
|
|
23114
|
+
this.blackPoint = new Float32Array(3);
|
|
23115
|
+
}
|
|
23116
|
+
if (this.GR < 0 || this.GG < 0 || this.GB < 0) {
|
|
23117
|
+
info(
|
|
23118
|
+
`Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ${this.name}, falling back to default.`
|
|
23119
|
+
);
|
|
23120
|
+
this.GR = this.GG = this.GB = 1;
|
|
23121
|
+
}
|
|
23122
|
+
}
|
|
23123
|
+
#matrixProduct(a, b, result) {
|
|
23124
|
+
result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
23125
|
+
result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
|
|
23126
|
+
result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
|
|
23127
|
+
}
|
|
23128
|
+
#toFlat(sourceWhitePoint, LMS, result) {
|
|
23129
|
+
result[0] = LMS[0] * 1 / sourceWhitePoint[0];
|
|
23130
|
+
result[1] = LMS[1] * 1 / sourceWhitePoint[1];
|
|
23131
|
+
result[2] = LMS[2] * 1 / sourceWhitePoint[2];
|
|
23132
|
+
}
|
|
23133
|
+
#toD65(sourceWhitePoint, LMS, result) {
|
|
23134
|
+
const D65X = 0.95047;
|
|
23135
|
+
const D65Y = 1;
|
|
23136
|
+
const D65Z = 1.08883;
|
|
23137
|
+
result[0] = LMS[0] * D65X / sourceWhitePoint[0];
|
|
23138
|
+
result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
|
|
23139
|
+
result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
|
|
23140
|
+
}
|
|
23141
|
+
#sRGBTransferFunction(color) {
|
|
23142
|
+
if (color <= 31308e-7) {
|
|
23143
|
+
return MathClamp(12.92 * color, 0, 1);
|
|
23144
|
+
}
|
|
23145
|
+
return color >= 0.99554525 ? 1 : MathClamp((1 + 0.055) * color ** (1 / 2.4) - 0.055, 0, 1);
|
|
23146
|
+
}
|
|
23147
|
+
#decodeL(L) {
|
|
23148
|
+
if (L < 0) {
|
|
23149
|
+
return -this.#decodeL(-L);
|
|
23150
|
+
}
|
|
23151
|
+
return L > 8 ? ((L + 16) / 116) ** 3 : L * _CalRGBCS.#DECODE_L_CONSTANT;
|
|
23152
|
+
}
|
|
23153
|
+
#compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
|
|
23154
|
+
if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {
|
|
23155
|
+
result[0] = XYZ_Flat[0];
|
|
23156
|
+
result[1] = XYZ_Flat[1];
|
|
23157
|
+
result[2] = XYZ_Flat[2];
|
|
23158
|
+
return;
|
|
23159
|
+
}
|
|
23160
|
+
const zeroDecodeL = this.#decodeL(0);
|
|
23161
|
+
const X_DST = zeroDecodeL;
|
|
23162
|
+
const X_SRC = this.#decodeL(sourceBlackPoint[0]);
|
|
23163
|
+
const Y_DST = zeroDecodeL;
|
|
23164
|
+
const Y_SRC = this.#decodeL(sourceBlackPoint[1]);
|
|
23165
|
+
const Z_DST = zeroDecodeL;
|
|
23166
|
+
const Z_SRC = this.#decodeL(sourceBlackPoint[2]);
|
|
23167
|
+
const X_Scale = (1 - X_DST) / (1 - X_SRC);
|
|
23168
|
+
const X_Offset = 1 - X_Scale;
|
|
23169
|
+
const Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
|
|
23170
|
+
const Y_Offset = 1 - Y_Scale;
|
|
23171
|
+
const Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
|
|
23172
|
+
const Z_Offset = 1 - Z_Scale;
|
|
23173
|
+
result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
|
|
23174
|
+
result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
|
|
23175
|
+
result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
|
|
23176
|
+
}
|
|
23177
|
+
#normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
|
|
23178
|
+
if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
|
|
23179
|
+
result[0] = XYZ_In[0];
|
|
23180
|
+
result[1] = XYZ_In[1];
|
|
23181
|
+
result[2] = XYZ_In[2];
|
|
23182
|
+
return;
|
|
23183
|
+
}
|
|
23184
|
+
const LMS = result;
|
|
23185
|
+
this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
|
|
23186
|
+
const LMS_Flat = _CalRGBCS.#tempNormalizeMatrix;
|
|
23187
|
+
this.#toFlat(sourceWhitePoint, LMS, LMS_Flat);
|
|
23188
|
+
this.#matrixProduct(
|
|
23189
|
+
_CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
|
|
23190
|
+
LMS_Flat,
|
|
23191
|
+
result
|
|
23192
|
+
);
|
|
23193
|
+
}
|
|
23194
|
+
#normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
|
|
23195
|
+
const LMS = result;
|
|
23196
|
+
this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
|
|
23197
|
+
const LMS_D65 = _CalRGBCS.#tempNormalizeMatrix;
|
|
23198
|
+
this.#toD65(sourceWhitePoint, LMS, LMS_D65);
|
|
23199
|
+
this.#matrixProduct(
|
|
23200
|
+
_CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
|
|
23201
|
+
LMS_D65,
|
|
23202
|
+
result
|
|
23203
|
+
);
|
|
23204
|
+
}
|
|
23205
|
+
#toRgb(src, srcOffset, dest, destOffset, scale) {
|
|
23206
|
+
const A = MathClamp(src[srcOffset] * scale, 0, 1);
|
|
23207
|
+
const B = MathClamp(src[srcOffset + 1] * scale, 0, 1);
|
|
23208
|
+
const C = MathClamp(src[srcOffset + 2] * scale, 0, 1);
|
|
23209
|
+
const AGR = A === 1 ? 1 : A ** this.GR;
|
|
23210
|
+
const BGG = B === 1 ? 1 : B ** this.GG;
|
|
23211
|
+
const CGB = C === 1 ? 1 : C ** this.GB;
|
|
23212
|
+
const X = this.MXA * AGR + this.MXB * BGG + this.MXC * CGB;
|
|
23213
|
+
const Y = this.MYA * AGR + this.MYB * BGG + this.MYC * CGB;
|
|
23214
|
+
const Z = this.MZA * AGR + this.MZB * BGG + this.MZC * CGB;
|
|
23215
|
+
const XYZ = _CalRGBCS.#tempConvertMatrix1;
|
|
23216
|
+
XYZ[0] = X;
|
|
23217
|
+
XYZ[1] = Y;
|
|
23218
|
+
XYZ[2] = Z;
|
|
23219
|
+
const XYZ_Flat = _CalRGBCS.#tempConvertMatrix2;
|
|
23220
|
+
this.#normalizeWhitePointToFlat(this.whitePoint, XYZ, XYZ_Flat);
|
|
23221
|
+
const XYZ_Black = _CalRGBCS.#tempConvertMatrix1;
|
|
23222
|
+
this.#compensateBlackPoint(this.blackPoint, XYZ_Flat, XYZ_Black);
|
|
23223
|
+
const XYZ_D65 = _CalRGBCS.#tempConvertMatrix2;
|
|
23224
|
+
this.#normalizeWhitePointToD65(
|
|
23225
|
+
_CalRGBCS.#FLAT_WHITEPOINT_MATRIX,
|
|
23226
|
+
XYZ_Black,
|
|
23227
|
+
XYZ_D65
|
|
23228
|
+
);
|
|
23229
|
+
const SRGB = _CalRGBCS.#tempConvertMatrix1;
|
|
23230
|
+
this.#matrixProduct(_CalRGBCS.#SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
|
|
23231
|
+
dest[destOffset] = this.#sRGBTransferFunction(SRGB[0]) * 255;
|
|
23232
|
+
dest[destOffset + 1] = this.#sRGBTransferFunction(SRGB[1]) * 255;
|
|
23233
|
+
dest[destOffset + 2] = this.#sRGBTransferFunction(SRGB[2]) * 255;
|
|
23234
|
+
}
|
|
23235
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
23236
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
23237
|
+
assert2(
|
|
23238
|
+
dest instanceof Uint8ClampedArray,
|
|
23239
|
+
'CalRGBCS.getRgbItem: Unsupported "dest" type.'
|
|
23240
|
+
);
|
|
23241
|
+
}
|
|
23242
|
+
this.#toRgb(src, srcOffset, dest, destOffset, 1);
|
|
23243
|
+
}
|
|
23244
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
23245
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
23246
|
+
assert2(
|
|
23247
|
+
dest instanceof Uint8ClampedArray,
|
|
23248
|
+
'CalRGBCS.getRgbBuffer: Unsupported "dest" type.'
|
|
23249
|
+
);
|
|
23250
|
+
}
|
|
23251
|
+
const scale = 1 / ((1 << bits) - 1);
|
|
23252
|
+
for (let i = 0; i < count; ++i) {
|
|
23253
|
+
this.#toRgb(src, srcOffset, dest, destOffset, scale);
|
|
23254
|
+
srcOffset += 3;
|
|
23255
|
+
destOffset += 3 + alpha01;
|
|
23256
|
+
}
|
|
23257
|
+
}
|
|
23258
|
+
};
|
|
23259
|
+
var LabCS = class extends ColorSpace {
|
|
23260
|
+
constructor(whitePoint, blackPoint, range) {
|
|
23261
|
+
super("Lab", 3);
|
|
23262
|
+
if (!whitePoint) {
|
|
23263
|
+
throw new FormatError(
|
|
23264
|
+
"WhitePoint missing - required for color space Lab"
|
|
23265
|
+
);
|
|
23266
|
+
}
|
|
23267
|
+
[this.XW, this.YW, this.ZW] = whitePoint;
|
|
23268
|
+
[this.amin, this.amax, this.bmin, this.bmax] = range || [
|
|
23269
|
+
-100,
|
|
23270
|
+
100,
|
|
23271
|
+
-100,
|
|
23272
|
+
100
|
|
23273
|
+
];
|
|
23274
|
+
[this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
|
|
23275
|
+
if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
|
|
23276
|
+
throw new FormatError(
|
|
23277
|
+
"Invalid WhitePoint components, no fallback available"
|
|
23278
|
+
);
|
|
23279
|
+
}
|
|
23280
|
+
if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
|
|
23281
|
+
info("Invalid BlackPoint, falling back to default");
|
|
23282
|
+
this.XB = this.YB = this.ZB = 0;
|
|
23283
|
+
}
|
|
23284
|
+
if (this.amin > this.amax || this.bmin > this.bmax) {
|
|
23285
|
+
info("Invalid Range, falling back to defaults");
|
|
23286
|
+
this.amin = -100;
|
|
23287
|
+
this.amax = 100;
|
|
23288
|
+
this.bmin = -100;
|
|
23289
|
+
this.bmax = 100;
|
|
23290
|
+
}
|
|
23291
|
+
}
|
|
23292
|
+
// Function g(x) from spec
|
|
23293
|
+
#fn_g(x) {
|
|
23294
|
+
return x >= 6 / 29 ? x ** 3 : 108 / 841 * (x - 4 / 29);
|
|
23295
|
+
}
|
|
23296
|
+
#decode(value, high1, low2, high2) {
|
|
23297
|
+
return low2 + value * (high2 - low2) / high1;
|
|
23298
|
+
}
|
|
23299
|
+
// If decoding is needed maxVal should be 2^bits per component - 1.
|
|
23300
|
+
#toRgb(src, srcOffset, maxVal, dest, destOffset) {
|
|
23301
|
+
let Ls = src[srcOffset];
|
|
23302
|
+
let as = src[srcOffset + 1];
|
|
23303
|
+
let bs = src[srcOffset + 2];
|
|
23304
|
+
if (maxVal !== false) {
|
|
23305
|
+
Ls = this.#decode(Ls, maxVal, 0, 100);
|
|
23306
|
+
as = this.#decode(as, maxVal, this.amin, this.amax);
|
|
23307
|
+
bs = this.#decode(bs, maxVal, this.bmin, this.bmax);
|
|
23308
|
+
}
|
|
23309
|
+
if (as > this.amax) {
|
|
23310
|
+
as = this.amax;
|
|
23311
|
+
} else if (as < this.amin) {
|
|
23312
|
+
as = this.amin;
|
|
23313
|
+
}
|
|
23314
|
+
if (bs > this.bmax) {
|
|
23315
|
+
bs = this.bmax;
|
|
23316
|
+
} else if (bs < this.bmin) {
|
|
23317
|
+
bs = this.bmin;
|
|
23318
|
+
}
|
|
23319
|
+
const M = (Ls + 16) / 116;
|
|
23320
|
+
const L = M + as / 500;
|
|
23321
|
+
const N = M - bs / 200;
|
|
23322
|
+
const X = this.XW * this.#fn_g(L);
|
|
23323
|
+
const Y = this.YW * this.#fn_g(M);
|
|
23324
|
+
const Z = this.ZW * this.#fn_g(N);
|
|
23325
|
+
let r, g, b;
|
|
23326
|
+
if (this.ZW < 1) {
|
|
23327
|
+
r = X * 3.1339 + Y * -1.617 + Z * -0.4906;
|
|
23328
|
+
g = X * -0.9785 + Y * 1.916 + Z * 0.0333;
|
|
23329
|
+
b = X * 0.072 + Y * -0.229 + Z * 1.4057;
|
|
23330
|
+
} else {
|
|
23331
|
+
r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
|
|
23332
|
+
g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
|
|
23333
|
+
b = X * 0.0557 + Y * -0.204 + Z * 1.057;
|
|
23334
|
+
}
|
|
23335
|
+
dest[destOffset] = Math.sqrt(r) * 255;
|
|
23336
|
+
dest[destOffset + 1] = Math.sqrt(g) * 255;
|
|
23337
|
+
dest[destOffset + 2] = Math.sqrt(b) * 255;
|
|
23338
|
+
}
|
|
23339
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
23340
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
23341
|
+
assert2(
|
|
23342
|
+
dest instanceof Uint8ClampedArray,
|
|
23343
|
+
'LabCS.getRgbItem: Unsupported "dest" type.'
|
|
23344
|
+
);
|
|
23345
|
+
}
|
|
23346
|
+
this.#toRgb(src, srcOffset, false, dest, destOffset);
|
|
23347
|
+
}
|
|
23348
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
23349
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
23350
|
+
assert2(
|
|
23351
|
+
dest instanceof Uint8ClampedArray,
|
|
23352
|
+
'LabCS.getRgbBuffer: Unsupported "dest" type.'
|
|
23353
|
+
);
|
|
23354
|
+
}
|
|
23355
|
+
const maxVal = (1 << bits) - 1;
|
|
23356
|
+
for (let i = 0; i < count; i++) {
|
|
23357
|
+
this.#toRgb(src, srcOffset, maxVal, dest, destOffset);
|
|
23358
|
+
srcOffset += 3;
|
|
23359
|
+
destOffset += 3 + alpha01;
|
|
23360
|
+
}
|
|
23361
|
+
}
|
|
23362
|
+
isDefaultDecode(decode, bpc) {
|
|
23363
|
+
return true;
|
|
23364
|
+
}
|
|
23365
|
+
get usesZeroToOneRange() {
|
|
23366
|
+
return shadow2(this, "usesZeroToOneRange", false);
|
|
23367
|
+
}
|
|
23368
|
+
};
|
|
23369
|
+
var TOKEN = {
|
|
23370
|
+
// Structural tokens — not keyword operators
|
|
23371
|
+
number: 0,
|
|
23372
|
+
lbrace: 1,
|
|
23373
|
+
rbrace: 2,
|
|
23374
|
+
// Boolean literals
|
|
23375
|
+
true: 3,
|
|
23376
|
+
false: 4,
|
|
23377
|
+
// Arithmetic binary operators
|
|
23378
|
+
add: 5,
|
|
23379
|
+
sub: 6,
|
|
23380
|
+
mul: 7,
|
|
23381
|
+
div: 8,
|
|
23382
|
+
idiv: 9,
|
|
23383
|
+
mod: 10,
|
|
23384
|
+
exp: 11,
|
|
23385
|
+
// Comparison binary operators
|
|
23386
|
+
eq: 12,
|
|
23387
|
+
ne: 13,
|
|
23388
|
+
gt: 14,
|
|
23389
|
+
ge: 15,
|
|
23390
|
+
lt: 16,
|
|
23391
|
+
le: 17,
|
|
23392
|
+
// Bitwise / boolean binary operators
|
|
23393
|
+
and: 18,
|
|
23394
|
+
or: 19,
|
|
23395
|
+
xor: 20,
|
|
23396
|
+
bitshift: 21,
|
|
23397
|
+
// Unary arithmetic operators
|
|
23398
|
+
abs: 22,
|
|
23399
|
+
neg: 23,
|
|
23400
|
+
ceiling: 24,
|
|
23401
|
+
floor: 25,
|
|
23402
|
+
round: 26,
|
|
23403
|
+
truncate: 27,
|
|
23404
|
+
// Unary boolean / bitwise operator
|
|
23405
|
+
not: 28,
|
|
23406
|
+
// Mathematical functions — unary
|
|
23407
|
+
sqrt: 29,
|
|
23408
|
+
sin: 30,
|
|
23409
|
+
cos: 31,
|
|
23410
|
+
ln: 32,
|
|
23411
|
+
log: 33,
|
|
23412
|
+
// Mathematical function — binary
|
|
23413
|
+
atan: 34,
|
|
23414
|
+
// Type conversion operators
|
|
23415
|
+
cvi: 35,
|
|
23416
|
+
cvr: 36,
|
|
23417
|
+
// Stack operators
|
|
23418
|
+
dup: 37,
|
|
23419
|
+
exch: 38,
|
|
23420
|
+
pop: 39,
|
|
23421
|
+
copy: 40,
|
|
23422
|
+
index: 41,
|
|
23423
|
+
roll: 42,
|
|
23424
|
+
// Control flow
|
|
23425
|
+
if: 43,
|
|
23426
|
+
ifelse: 44,
|
|
23427
|
+
// End of input
|
|
23428
|
+
eof: 45,
|
|
23429
|
+
// Synthetic: produced by the optimizer, never emitted by the lexer.
|
|
23430
|
+
min: 46,
|
|
23431
|
+
max: 47
|
|
23432
|
+
};
|
|
23433
|
+
var Token = class {
|
|
23434
|
+
constructor(id, value = null) {
|
|
23435
|
+
this.id = id;
|
|
23436
|
+
this.value = value;
|
|
23437
|
+
}
|
|
23438
|
+
};
|
|
23439
|
+
var Lexer = class _Lexer {
|
|
23440
|
+
// Singletons for every non-number token, built lazily on first construction.
|
|
23441
|
+
// Keyword operator tokens carry their name as `value`; structural tokens
|
|
23442
|
+
// (lbrace, rbrace, eof) carry null.
|
|
23443
|
+
static #singletons = null;
|
|
23444
|
+
static #operatorSingletons = null;
|
|
23445
|
+
static #initSingletons() {
|
|
23446
|
+
const singletons = /* @__PURE__ */ Object.create(null);
|
|
23447
|
+
const operatorSingletons = /* @__PURE__ */ Object.create(null);
|
|
23448
|
+
for (const [name, id] of Object.entries(TOKEN)) {
|
|
23449
|
+
if (name === "number") {
|
|
23450
|
+
continue;
|
|
23451
|
+
}
|
|
23452
|
+
const isOperator = id >= TOKEN.true && id <= TOKEN.ifelse;
|
|
23453
|
+
const token = new Token(id, isOperator ? name : null);
|
|
23454
|
+
singletons[name] = token;
|
|
23455
|
+
if (isOperator) {
|
|
23456
|
+
operatorSingletons[name] = token;
|
|
23457
|
+
}
|
|
23458
|
+
}
|
|
23459
|
+
this.#singletons = singletons;
|
|
23460
|
+
this.#operatorSingletons = operatorSingletons;
|
|
23461
|
+
}
|
|
23462
|
+
constructor(data) {
|
|
23463
|
+
if (!_Lexer.#singletons) {
|
|
23464
|
+
_Lexer.#initSingletons();
|
|
23465
|
+
}
|
|
23466
|
+
this.data = data;
|
|
23467
|
+
this.pos = 0;
|
|
23468
|
+
this.len = data.length;
|
|
23469
|
+
this._numberPattern = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/iy;
|
|
23470
|
+
this._identifierPattern = /[a-z]+/y;
|
|
23471
|
+
}
|
|
23472
|
+
// Skip a % comment, advancing past the next \n or \r (or to EOF).
|
|
23473
|
+
_skipComment() {
|
|
23474
|
+
const lf = this.data.indexOf("\n", this.pos);
|
|
23475
|
+
const cr = this.data.indexOf("\r", this.pos);
|
|
23476
|
+
const eol = Math.min(lf < 0 ? this.len : lf, cr < 0 ? this.len : cr);
|
|
23477
|
+
this.pos = Math.min(eol + 1, this.len);
|
|
23478
|
+
}
|
|
23479
|
+
_getNumber() {
|
|
23480
|
+
this._numberPattern.lastIndex = this.pos;
|
|
23481
|
+
const match = this._numberPattern.exec(this.data);
|
|
23482
|
+
if (!match) {
|
|
23483
|
+
return new Token(TOKEN.number, 0);
|
|
23484
|
+
}
|
|
23485
|
+
const number = parseFloat(match[0]);
|
|
23486
|
+
if (!Number.isFinite(number)) {
|
|
23487
|
+
return new Token(TOKEN.number, 0);
|
|
23488
|
+
}
|
|
23489
|
+
this.pos = this._numberPattern.lastIndex;
|
|
23490
|
+
return new Token(TOKEN.number, number);
|
|
23491
|
+
}
|
|
23492
|
+
_getOperator() {
|
|
23493
|
+
this._identifierPattern.lastIndex = this.pos;
|
|
23494
|
+
const match = this._identifierPattern.exec(this.data);
|
|
23495
|
+
if (!match) {
|
|
23496
|
+
return new Token(TOKEN.number, 0);
|
|
23497
|
+
}
|
|
23498
|
+
this.pos = this._identifierPattern.lastIndex;
|
|
23499
|
+
const op = match[0];
|
|
23500
|
+
const token = _Lexer.#operatorSingletons[op];
|
|
23501
|
+
return token ?? new Token(TOKEN.number, 0);
|
|
23502
|
+
}
|
|
23503
|
+
// Return the next token, or Lexer.#singletons.eof at end of input.
|
|
23504
|
+
next() {
|
|
23505
|
+
while (this.pos < this.len) {
|
|
23506
|
+
const ch3 = this.data.charCodeAt(this.pos++);
|
|
23507
|
+
switch (ch3) {
|
|
23508
|
+
// PostScript white-space characters (PDF32000 §7.2.2)
|
|
23509
|
+
case 0:
|
|
23510
|
+
case 9:
|
|
23511
|
+
case 10:
|
|
23512
|
+
case 12:
|
|
23513
|
+
case 13:
|
|
23514
|
+
case 32:
|
|
23515
|
+
break;
|
|
23516
|
+
case 37:
|
|
23517
|
+
this._skipComment();
|
|
23518
|
+
break;
|
|
23519
|
+
case 123:
|
|
23520
|
+
return _Lexer.#singletons.lbrace;
|
|
23521
|
+
case 125:
|
|
23522
|
+
return _Lexer.#singletons.rbrace;
|
|
23523
|
+
case 43:
|
|
23524
|
+
case 45:
|
|
23525
|
+
this.pos--;
|
|
23526
|
+
return this._getNumber();
|
|
23527
|
+
case 46:
|
|
23528
|
+
this.pos--;
|
|
23529
|
+
return this._getNumber();
|
|
23530
|
+
default:
|
|
23531
|
+
if (ch3 >= 48 && ch3 <= 57) {
|
|
23532
|
+
this.pos--;
|
|
23533
|
+
return this._getNumber();
|
|
23534
|
+
}
|
|
23535
|
+
if (ch3 >= 97 && ch3 <= 122) {
|
|
23536
|
+
this.pos--;
|
|
23537
|
+
return this._getOperator();
|
|
23538
|
+
}
|
|
23539
|
+
return new Token(TOKEN.number, 0);
|
|
23540
|
+
}
|
|
23541
|
+
}
|
|
23542
|
+
return _Lexer.#singletons.eof;
|
|
23543
|
+
}
|
|
23544
|
+
};
|
|
23545
|
+
var PS_VALUE_TYPE = {
|
|
23546
|
+
numeric: 0,
|
|
23547
|
+
// known to be a number (f64 in Wasm)
|
|
23548
|
+
boolean: 1,
|
|
23549
|
+
// known to be a boolean (0.0 = false, 1.0 = true in f64)
|
|
23550
|
+
unknown: 2
|
|
23551
|
+
// indeterminate at compile time
|
|
23552
|
+
};
|
|
23553
|
+
var PS_NODE = {
|
|
23554
|
+
// Parser AST node types (produced by Parser / parsePostScriptFunction)
|
|
23555
|
+
program: 0,
|
|
23556
|
+
block: 1,
|
|
23557
|
+
number: 2,
|
|
23558
|
+
operator: 3,
|
|
23559
|
+
if: 4,
|
|
23560
|
+
ifelse: 5,
|
|
23561
|
+
// Tree AST node types (produced by PSStackToTree)
|
|
23562
|
+
arg: 6,
|
|
23563
|
+
const: 7,
|
|
23564
|
+
unary: 8,
|
|
23565
|
+
binary: 9,
|
|
23566
|
+
ternary: 10
|
|
23567
|
+
};
|
|
23568
|
+
var PsNode = class {
|
|
23569
|
+
constructor(type) {
|
|
23570
|
+
this.type = type;
|
|
23571
|
+
}
|
|
23572
|
+
};
|
|
23573
|
+
var PsProgram = class extends PsNode {
|
|
23574
|
+
constructor(body) {
|
|
23575
|
+
super(PS_NODE.program);
|
|
23576
|
+
this.body = body;
|
|
23577
|
+
}
|
|
23578
|
+
};
|
|
23579
|
+
var PsBlock = class extends PsNode {
|
|
23580
|
+
constructor(instructions) {
|
|
23581
|
+
super(PS_NODE.block);
|
|
23582
|
+
this.instructions = instructions;
|
|
23583
|
+
}
|
|
23584
|
+
};
|
|
23585
|
+
var PsNumber = class extends PsNode {
|
|
23586
|
+
/** @param {number} value */
|
|
23587
|
+
constructor(value) {
|
|
23588
|
+
super(PS_NODE.number);
|
|
23589
|
+
this.value = value;
|
|
23590
|
+
}
|
|
23591
|
+
};
|
|
23592
|
+
var PsOperator = class extends PsNode {
|
|
23593
|
+
/** @param {number} op — one of the TOKEN.* constants from lexer.js */
|
|
23594
|
+
constructor(op) {
|
|
23595
|
+
super(PS_NODE.operator);
|
|
23596
|
+
this.op = op;
|
|
23597
|
+
}
|
|
23598
|
+
};
|
|
23599
|
+
var PsIf = class extends PsNode {
|
|
23600
|
+
/** @param {PsBlock} then */
|
|
23601
|
+
constructor(then) {
|
|
23602
|
+
super(PS_NODE.if);
|
|
23603
|
+
this.then = then;
|
|
23604
|
+
}
|
|
23605
|
+
};
|
|
23606
|
+
var PsIfElse = class extends PsNode {
|
|
23607
|
+
/**
|
|
23608
|
+
* @param {PsBlock} then
|
|
23609
|
+
* @param {PsBlock} otherwise
|
|
23610
|
+
*/
|
|
23611
|
+
constructor(then, otherwise) {
|
|
23612
|
+
super(PS_NODE.ifelse);
|
|
23613
|
+
this.then = then;
|
|
23614
|
+
this.otherwise = otherwise;
|
|
23615
|
+
}
|
|
23616
|
+
};
|
|
23617
|
+
var PsArgNode = class extends PsNode {
|
|
23618
|
+
/** @param {number} index */
|
|
23619
|
+
constructor(index) {
|
|
23620
|
+
super(PS_NODE.arg);
|
|
23621
|
+
this.index = index;
|
|
23622
|
+
this.valueType = PS_VALUE_TYPE.numeric;
|
|
23623
|
+
}
|
|
23624
|
+
};
|
|
23625
|
+
var PsConstNode = class extends PsNode {
|
|
23626
|
+
/** @param {number|boolean} value */
|
|
23627
|
+
constructor(value) {
|
|
23628
|
+
super(PS_NODE.const);
|
|
23629
|
+
this.value = value;
|
|
23630
|
+
this.valueType = typeof value === "boolean" ? PS_VALUE_TYPE.boolean : PS_VALUE_TYPE.numeric;
|
|
23631
|
+
}
|
|
23632
|
+
};
|
|
23633
|
+
var PsUnaryNode = class extends PsNode {
|
|
23634
|
+
/**
|
|
23635
|
+
* @param {number} op — TOKEN.* constant
|
|
23636
|
+
* @param {PsNode} operand
|
|
23637
|
+
* @param {number} [valueType]
|
|
23638
|
+
*/
|
|
23639
|
+
constructor(op, operand, valueType = PS_VALUE_TYPE.unknown) {
|
|
23640
|
+
super(PS_NODE.unary);
|
|
23641
|
+
this.op = op;
|
|
23642
|
+
this.operand = operand;
|
|
23643
|
+
this.valueType = valueType;
|
|
23644
|
+
}
|
|
23645
|
+
};
|
|
23646
|
+
var PsBinaryNode = class extends PsNode {
|
|
23647
|
+
/**
|
|
23648
|
+
* @param {number} op — TOKEN.* constant
|
|
23649
|
+
* @param {PsNode} first — was on top of stack
|
|
23650
|
+
* @param {PsNode} second — was below top
|
|
23651
|
+
* @param {number} [valueType]
|
|
23652
|
+
*/
|
|
23653
|
+
constructor(op, first, second, valueType = PS_VALUE_TYPE.unknown) {
|
|
23654
|
+
super(PS_NODE.binary);
|
|
23655
|
+
this.op = op;
|
|
23656
|
+
this.first = first;
|
|
23657
|
+
this.second = second;
|
|
23658
|
+
this.valueType = valueType;
|
|
23659
|
+
}
|
|
23660
|
+
};
|
|
23661
|
+
var PsTernaryNode = class extends PsNode {
|
|
23662
|
+
/**
|
|
23663
|
+
* @param {PsNode} cond
|
|
23664
|
+
* @param {PsNode} then
|
|
23665
|
+
* @param {PsNode} otherwise
|
|
23666
|
+
* @param {number} [valueType]
|
|
23667
|
+
*/
|
|
23668
|
+
constructor(cond, then, otherwise, valueType = PS_VALUE_TYPE.unknown) {
|
|
23669
|
+
super(PS_NODE.ternary);
|
|
23670
|
+
this.cond = cond;
|
|
23671
|
+
this.then = then;
|
|
23672
|
+
this.otherwise = otherwise;
|
|
23673
|
+
this.valueType = valueType;
|
|
23674
|
+
}
|
|
23675
|
+
};
|
|
23676
|
+
var Parser = class _Parser {
|
|
23677
|
+
constructor(lexer) {
|
|
23678
|
+
this.lexer = lexer;
|
|
23679
|
+
this._token = null;
|
|
23680
|
+
}
|
|
23681
|
+
static _isRegularOperator(id) {
|
|
23682
|
+
return id >= TOKEN.true && id < TOKEN.if;
|
|
23683
|
+
}
|
|
23684
|
+
// Fetch the next token from the lexer.
|
|
23685
|
+
_advance() {
|
|
23686
|
+
this._token = this.lexer.next();
|
|
23687
|
+
}
|
|
23688
|
+
// Assert that the current token has the given id, consume it, and return it.
|
|
23689
|
+
_expect(id) {
|
|
23690
|
+
if (this._token.id !== id) {
|
|
23691
|
+
throw new FormatError(
|
|
23692
|
+
`PostScript function: expected token id ${id}, got ${this._token.id}.`
|
|
23693
|
+
);
|
|
23694
|
+
}
|
|
23695
|
+
const tok = this._token;
|
|
23696
|
+
this._advance();
|
|
23697
|
+
return tok;
|
|
23698
|
+
}
|
|
23699
|
+
/**
|
|
23700
|
+
* Parse the full Type 4 function body.
|
|
23701
|
+
*
|
|
23702
|
+
* Grammar (simplified):
|
|
23703
|
+
* program ::= '{' block '}'
|
|
23704
|
+
* block ::= instruction*
|
|
23705
|
+
* instruction ::= number
|
|
23706
|
+
* | operator (any PS_OPERATOR except if / ifelse)
|
|
23707
|
+
* | '{' block '}' 'if'
|
|
23708
|
+
* | '{' block '}' '{' block '}' 'ifelse'
|
|
23709
|
+
* @returns {PsProgram}
|
|
23710
|
+
*/
|
|
23711
|
+
parse() {
|
|
23712
|
+
this._advance();
|
|
23713
|
+
this._expect(TOKEN.lbrace);
|
|
23714
|
+
const block = this._parseBlock();
|
|
23715
|
+
this._expect(TOKEN.rbrace);
|
|
23716
|
+
if (this._token.id !== TOKEN.eof) {
|
|
23717
|
+
warn2("PostScript function: unexpected content after closing brace.");
|
|
23718
|
+
}
|
|
23719
|
+
return new PsProgram(block);
|
|
23720
|
+
}
|
|
23721
|
+
_parseBlock() {
|
|
23722
|
+
const instructions = [];
|
|
23723
|
+
while (true) {
|
|
23724
|
+
const tok = this._token;
|
|
23725
|
+
switch (tok.id) {
|
|
23726
|
+
case TOKEN.number:
|
|
23727
|
+
instructions.push(new PsNumber(tok.value));
|
|
23728
|
+
this._advance();
|
|
23729
|
+
break;
|
|
23730
|
+
case TOKEN.lbrace: {
|
|
23731
|
+
this._advance();
|
|
23732
|
+
const thenBlock = this._parseBlock();
|
|
23733
|
+
this._expect(TOKEN.rbrace);
|
|
23734
|
+
if (this._token.id === TOKEN.if) {
|
|
23735
|
+
this._advance();
|
|
23736
|
+
instructions.push(new PsIf(thenBlock));
|
|
23737
|
+
} else if (this._token.id === TOKEN.lbrace) {
|
|
23738
|
+
this._advance();
|
|
23739
|
+
const elseBlock = this._parseBlock();
|
|
23740
|
+
this._expect(TOKEN.rbrace);
|
|
23741
|
+
this._expect(TOKEN.ifelse);
|
|
23742
|
+
instructions.push(new PsIfElse(thenBlock, elseBlock));
|
|
23743
|
+
} else {
|
|
23744
|
+
throw new FormatError(
|
|
23745
|
+
"PostScript function: a procedure block must be followed by 'if' or '{\u2026} ifelse'."
|
|
23746
|
+
);
|
|
23747
|
+
}
|
|
23748
|
+
break;
|
|
23749
|
+
}
|
|
23750
|
+
case TOKEN.rbrace:
|
|
23751
|
+
case TOKEN.eof:
|
|
23752
|
+
return new PsBlock(instructions);
|
|
23753
|
+
case TOKEN.if:
|
|
23754
|
+
case TOKEN.ifelse:
|
|
23755
|
+
throw new FormatError(
|
|
23756
|
+
`PostScript function: unexpected '${tok.value}' operator.`
|
|
23757
|
+
);
|
|
23758
|
+
default:
|
|
23759
|
+
if (_Parser._isRegularOperator(tok.id)) {
|
|
23760
|
+
instructions.push(new PsOperator(tok.id));
|
|
23761
|
+
this._advance();
|
|
23762
|
+
break;
|
|
23763
|
+
}
|
|
23764
|
+
throw new FormatError(
|
|
23765
|
+
`PostScript function: unexpected token id ${tok.id}.`
|
|
23766
|
+
);
|
|
23767
|
+
}
|
|
23768
|
+
}
|
|
23769
|
+
}
|
|
23770
|
+
};
|
|
23771
|
+
function parsePostScriptFunction(source) {
|
|
23772
|
+
return new Parser(new Lexer(source)).parse();
|
|
23773
|
+
}
|
|
23774
|
+
function _nodesEqual(a, b) {
|
|
23775
|
+
if (a === b) {
|
|
23776
|
+
return true;
|
|
23777
|
+
}
|
|
23778
|
+
if (a.type !== b.type) {
|
|
23779
|
+
return false;
|
|
23780
|
+
}
|
|
23781
|
+
switch (a.type) {
|
|
23782
|
+
case PS_NODE.arg:
|
|
23783
|
+
return a.index === b.index;
|
|
23784
|
+
case PS_NODE.const:
|
|
23785
|
+
return a.value === b.value;
|
|
23786
|
+
case PS_NODE.unary:
|
|
23787
|
+
return a.op === b.op && _nodesEqual(a.operand, b.operand);
|
|
23788
|
+
case PS_NODE.binary:
|
|
23789
|
+
return a.op === b.op && _nodesEqual(a.first, b.first) && _nodesEqual(a.second, b.second);
|
|
23790
|
+
case PS_NODE.ternary:
|
|
23791
|
+
return _nodesEqual(a.cond, b.cond) && _nodesEqual(a.then, b.then) && _nodesEqual(a.otherwise, b.otherwise);
|
|
23792
|
+
default:
|
|
23793
|
+
return false;
|
|
23794
|
+
}
|
|
23795
|
+
}
|
|
23796
|
+
function _evalBinaryConst(op, a, b) {
|
|
23797
|
+
switch (op) {
|
|
23798
|
+
case TOKEN.add:
|
|
23799
|
+
return a + b;
|
|
23800
|
+
case TOKEN.sub:
|
|
23801
|
+
return a - b;
|
|
23802
|
+
case TOKEN.mul:
|
|
23803
|
+
return a * b;
|
|
23804
|
+
case TOKEN.div:
|
|
23805
|
+
return b !== 0 ? a / b : 0;
|
|
23806
|
+
// div by zero → 0
|
|
23807
|
+
case TOKEN.idiv:
|
|
23808
|
+
return b !== 0 ? Math.trunc(a / b) : 0;
|
|
23809
|
+
// div by zero → 0
|
|
23810
|
+
case TOKEN.mod:
|
|
23811
|
+
return b !== 0 ? a - Math.trunc(a / b) * b : 0;
|
|
23812
|
+
// div by zero → 0
|
|
23813
|
+
case TOKEN.exp: {
|
|
23814
|
+
const r = a ** b;
|
|
23815
|
+
return Number.isFinite(r) ? r : void 0;
|
|
23816
|
+
}
|
|
23817
|
+
case TOKEN.atan: {
|
|
23818
|
+
let deg = Math.atan2(a, b) * (180 / Math.PI);
|
|
23819
|
+
if (deg < 0) {
|
|
23820
|
+
deg += 360;
|
|
23821
|
+
}
|
|
23822
|
+
return deg;
|
|
23823
|
+
}
|
|
23824
|
+
case TOKEN.eq:
|
|
23825
|
+
return a === b;
|
|
23826
|
+
case TOKEN.ne:
|
|
23827
|
+
return a !== b;
|
|
23828
|
+
case TOKEN.gt:
|
|
23829
|
+
return a > b;
|
|
23830
|
+
case TOKEN.ge:
|
|
23831
|
+
return a >= b;
|
|
23832
|
+
case TOKEN.lt:
|
|
23833
|
+
return a < b;
|
|
23834
|
+
case TOKEN.le:
|
|
23835
|
+
return a <= b;
|
|
23836
|
+
case TOKEN.and:
|
|
23837
|
+
return typeof a === "boolean" ? a && b : a & b | 0;
|
|
23838
|
+
case TOKEN.or:
|
|
23839
|
+
return typeof a === "boolean" ? a || b : a | b | 0;
|
|
23840
|
+
case TOKEN.xor:
|
|
23841
|
+
return typeof a === "boolean" ? a !== b : a ^ b | 0;
|
|
23842
|
+
case TOKEN.bitshift:
|
|
23843
|
+
return b >= 0 ? a << b | 0 : a >> -b | 0;
|
|
23844
|
+
case TOKEN.min:
|
|
23845
|
+
return Math.min(a, b);
|
|
23846
|
+
case TOKEN.max:
|
|
23847
|
+
return Math.max(a, b);
|
|
23848
|
+
default:
|
|
23849
|
+
return void 0;
|
|
23850
|
+
}
|
|
23851
|
+
}
|
|
23852
|
+
function _evalUnaryConst(op, v) {
|
|
23853
|
+
switch (op) {
|
|
23854
|
+
case TOKEN.abs:
|
|
23855
|
+
return Math.abs(v);
|
|
23856
|
+
case TOKEN.neg:
|
|
23857
|
+
return -v;
|
|
23858
|
+
case TOKEN.ceiling:
|
|
23859
|
+
return Math.ceil(v);
|
|
23860
|
+
case TOKEN.floor:
|
|
23861
|
+
return Math.floor(v);
|
|
23862
|
+
case TOKEN.round:
|
|
23863
|
+
return Math.round(v);
|
|
23864
|
+
case TOKEN.truncate:
|
|
23865
|
+
return Math.trunc(v);
|
|
23866
|
+
case TOKEN.sqrt: {
|
|
23867
|
+
const r = Math.sqrt(v);
|
|
23868
|
+
return Number.isFinite(r) ? r : void 0;
|
|
23869
|
+
}
|
|
23870
|
+
case TOKEN.sin:
|
|
23871
|
+
return Math.sin(v % 360 * Math.PI / 180);
|
|
23872
|
+
case TOKEN.cos:
|
|
23873
|
+
return Math.cos(v % 360 * Math.PI / 180);
|
|
23874
|
+
case TOKEN.ln: {
|
|
23875
|
+
const r = Math.log(v);
|
|
23876
|
+
return Number.isFinite(r) ? r : void 0;
|
|
23877
|
+
}
|
|
23878
|
+
case TOKEN.log: {
|
|
23879
|
+
const r = Math.log10(v);
|
|
23880
|
+
return Number.isFinite(r) ? r : void 0;
|
|
23881
|
+
}
|
|
23882
|
+
case TOKEN.cvi:
|
|
23883
|
+
return Math.trunc(v);
|
|
23884
|
+
case TOKEN.cvr:
|
|
23885
|
+
return v;
|
|
23886
|
+
case TOKEN.not:
|
|
23887
|
+
return typeof v === "boolean" ? !v : ~v;
|
|
23888
|
+
default:
|
|
23889
|
+
return void 0;
|
|
23890
|
+
}
|
|
23891
|
+
}
|
|
23892
|
+
var MAX_STACK_SIZE = 100;
|
|
23893
|
+
function _unaryValueType(op, operandType) {
|
|
23894
|
+
return op === TOKEN.not ? operandType : PS_VALUE_TYPE.numeric;
|
|
23895
|
+
}
|
|
23896
|
+
function _binaryValueType(op, firstType, secondType) {
|
|
23897
|
+
switch (op) {
|
|
23898
|
+
// Comparison operators always produce a boolean.
|
|
23899
|
+
case TOKEN.eq:
|
|
23900
|
+
case TOKEN.ne:
|
|
23901
|
+
case TOKEN.gt:
|
|
23902
|
+
case TOKEN.ge:
|
|
23903
|
+
case TOKEN.lt:
|
|
23904
|
+
case TOKEN.le:
|
|
23905
|
+
return PS_VALUE_TYPE.boolean;
|
|
23906
|
+
// and / or / xor preserve the type when both operands are the same known
|
|
23907
|
+
// type (both boolean or both numeric); otherwise the type is unknown.
|
|
23908
|
+
case TOKEN.and:
|
|
23909
|
+
case TOKEN.or:
|
|
23910
|
+
case TOKEN.xor:
|
|
23911
|
+
return firstType === secondType && firstType !== PS_VALUE_TYPE.unknown ? firstType : PS_VALUE_TYPE.unknown;
|
|
23912
|
+
// All arithmetic / bitshift operators produce a numeric result.
|
|
23913
|
+
default:
|
|
23914
|
+
return PS_VALUE_TYPE.numeric;
|
|
23915
|
+
}
|
|
23916
|
+
}
|
|
23917
|
+
var PSStackToTree = class _PSStackToTree {
|
|
23918
|
+
static #binaryOps = null;
|
|
23919
|
+
static #unaryOps = null;
|
|
23920
|
+
static #idempotentUnary = null;
|
|
23921
|
+
static #negatedComparison = null;
|
|
23922
|
+
static #init() {
|
|
23923
|
+
this.#binaryOps = /* @__PURE__ */ new Set([
|
|
23924
|
+
TOKEN.add,
|
|
23925
|
+
TOKEN.sub,
|
|
23926
|
+
TOKEN.mul,
|
|
23927
|
+
TOKEN.div,
|
|
23928
|
+
TOKEN.idiv,
|
|
23929
|
+
TOKEN.mod,
|
|
23930
|
+
TOKEN.exp,
|
|
23931
|
+
TOKEN.atan,
|
|
23932
|
+
TOKEN.eq,
|
|
23933
|
+
TOKEN.ne,
|
|
23934
|
+
TOKEN.gt,
|
|
23935
|
+
TOKEN.ge,
|
|
23936
|
+
TOKEN.lt,
|
|
23937
|
+
TOKEN.le,
|
|
23938
|
+
TOKEN.and,
|
|
23939
|
+
TOKEN.or,
|
|
23940
|
+
TOKEN.xor,
|
|
23941
|
+
TOKEN.bitshift
|
|
23942
|
+
]);
|
|
23943
|
+
this.#unaryOps = /* @__PURE__ */ new Set([
|
|
23944
|
+
TOKEN.abs,
|
|
23945
|
+
TOKEN.neg,
|
|
23946
|
+
TOKEN.ceiling,
|
|
23947
|
+
TOKEN.floor,
|
|
23948
|
+
TOKEN.round,
|
|
23949
|
+
TOKEN.truncate,
|
|
23950
|
+
TOKEN.sqrt,
|
|
23951
|
+
TOKEN.sin,
|
|
23952
|
+
TOKEN.cos,
|
|
23953
|
+
TOKEN.ln,
|
|
23954
|
+
TOKEN.log,
|
|
23955
|
+
TOKEN.cvi,
|
|
23956
|
+
TOKEN.cvr,
|
|
23957
|
+
TOKEN.not
|
|
23958
|
+
]);
|
|
23959
|
+
this.#idempotentUnary = /* @__PURE__ */ new Set([
|
|
23960
|
+
TOKEN.abs,
|
|
23961
|
+
TOKEN.ceiling,
|
|
23962
|
+
TOKEN.cvi,
|
|
23963
|
+
TOKEN.cvr,
|
|
23964
|
+
TOKEN.floor,
|
|
23965
|
+
TOKEN.round,
|
|
23966
|
+
TOKEN.truncate
|
|
23967
|
+
]);
|
|
23968
|
+
this.#negatedComparison = /* @__PURE__ */ new Map([
|
|
23969
|
+
[TOKEN.eq, TOKEN.ne],
|
|
23970
|
+
[TOKEN.ne, TOKEN.eq],
|
|
23971
|
+
[TOKEN.lt, TOKEN.ge],
|
|
23972
|
+
[TOKEN.le, TOKEN.gt],
|
|
23973
|
+
[TOKEN.gt, TOKEN.le],
|
|
23974
|
+
[TOKEN.ge, TOKEN.lt]
|
|
23975
|
+
]);
|
|
23976
|
+
}
|
|
23977
|
+
/**
|
|
23978
|
+
* @param {PsProgram} program
|
|
23979
|
+
* @param {number} numInputs — number of domain values placed on the stack
|
|
23980
|
+
* before the program runs (i.e. the length of the domain array / 2).
|
|
23981
|
+
* @returns {Array<PsNode>} — one tree node per output value.
|
|
23982
|
+
*/
|
|
23983
|
+
evaluate(program, numInputs) {
|
|
23984
|
+
if (!_PSStackToTree.#binaryOps) {
|
|
23985
|
+
_PSStackToTree.#init();
|
|
23986
|
+
}
|
|
23987
|
+
this._failed = false;
|
|
23988
|
+
if (numInputs > MAX_STACK_SIZE) {
|
|
23989
|
+
return null;
|
|
23990
|
+
}
|
|
23991
|
+
const stack = [];
|
|
23992
|
+
for (let i = 0; i < numInputs; i++) {
|
|
23993
|
+
stack.push(new PsArgNode(i));
|
|
23994
|
+
}
|
|
23995
|
+
this._evalBlock(program.body, stack);
|
|
23996
|
+
if (this._failed) {
|
|
23997
|
+
return null;
|
|
23998
|
+
}
|
|
23999
|
+
_PSStackToTree.#markShared(stack);
|
|
24000
|
+
return stack;
|
|
24001
|
+
}
|
|
24002
|
+
// Set node.shared / sharedCount on non-atomic nodes referenced more than
|
|
24003
|
+
// once. arg/const are excluded — they are cheap to re-emit inline.
|
|
24004
|
+
static #markShared(outputs) {
|
|
24005
|
+
const refCount = /* @__PURE__ */ new Map();
|
|
24006
|
+
const visit = (node) => {
|
|
24007
|
+
if (!node || node.type === PS_NODE.arg || node.type === PS_NODE.const) {
|
|
24008
|
+
return;
|
|
24009
|
+
}
|
|
24010
|
+
const prev = refCount.get(node) ?? 0;
|
|
24011
|
+
refCount.set(node, prev + 1);
|
|
24012
|
+
if (prev > 0) {
|
|
24013
|
+
return;
|
|
24014
|
+
}
|
|
24015
|
+
switch (node.type) {
|
|
24016
|
+
case PS_NODE.unary:
|
|
24017
|
+
visit(node.operand);
|
|
24018
|
+
break;
|
|
24019
|
+
case PS_NODE.binary:
|
|
24020
|
+
visit(node.first);
|
|
24021
|
+
visit(node.second);
|
|
24022
|
+
break;
|
|
24023
|
+
case PS_NODE.ternary:
|
|
24024
|
+
visit(node.cond);
|
|
24025
|
+
visit(node.then);
|
|
24026
|
+
visit(node.otherwise);
|
|
24027
|
+
break;
|
|
24028
|
+
}
|
|
24029
|
+
};
|
|
24030
|
+
for (const output of outputs) {
|
|
24031
|
+
visit(output);
|
|
24032
|
+
}
|
|
24033
|
+
for (const [node, count] of refCount) {
|
|
24034
|
+
if (count > 1) {
|
|
24035
|
+
node.shared = true;
|
|
24036
|
+
node.sharedCount = count;
|
|
24037
|
+
}
|
|
24038
|
+
}
|
|
24039
|
+
}
|
|
24040
|
+
_evalBlock(block, stack) {
|
|
24041
|
+
this._evalBlockFrom(block.instructions, 0, stack);
|
|
24042
|
+
}
|
|
24043
|
+
/**
|
|
24044
|
+
* Core evaluation loop. Processes `instructions[startIdx…]` in order,
|
|
24045
|
+
* mutating `stack` as each instruction executes.
|
|
24046
|
+
*
|
|
24047
|
+
* When a `{ body } if` instruction grows the stack (the PostScript "early
|
|
24048
|
+
* exit / guard" idiom), the remaining instructions in the current array are
|
|
24049
|
+
* evaluated on **both** the true-branch stack and the false-branch stack,
|
|
24050
|
+
* then the two results are merged into PsTernaryNodes. This handles
|
|
24051
|
+
* patterns like:
|
|
24052
|
+
*
|
|
24053
|
+
* cond { pop R G B sentinel } if
|
|
24054
|
+
* … more guards …
|
|
24055
|
+
* sentinel 0 gt { defaultR defaultG defaultB } if
|
|
24056
|
+
*/
|
|
24057
|
+
_evalBlockFrom(instructions, startIdx, stack) {
|
|
24058
|
+
for (let idx = startIdx; idx < instructions.length; idx++) {
|
|
24059
|
+
if (this._failed) {
|
|
24060
|
+
break;
|
|
24061
|
+
}
|
|
24062
|
+
const instr = instructions[idx];
|
|
24063
|
+
switch (instr.type) {
|
|
24064
|
+
case PS_NODE.number:
|
|
24065
|
+
stack.push(new PsConstNode(instr.value));
|
|
24066
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
24067
|
+
this._failed = true;
|
|
24068
|
+
}
|
|
24069
|
+
break;
|
|
24070
|
+
case PS_NODE.operator:
|
|
24071
|
+
this._evalOp(instr.op, stack);
|
|
24072
|
+
break;
|
|
24073
|
+
case PS_NODE.if: {
|
|
24074
|
+
if (stack.length < 1) {
|
|
24075
|
+
this._failed = true;
|
|
24076
|
+
break;
|
|
24077
|
+
}
|
|
24078
|
+
const cond = stack.pop();
|
|
24079
|
+
const saved = stack.slice();
|
|
24080
|
+
this._evalBlock(instr.then, stack);
|
|
24081
|
+
if (this._failed) {
|
|
24082
|
+
break;
|
|
24083
|
+
}
|
|
24084
|
+
if (stack.length === saved.length) {
|
|
24085
|
+
for (let i = 0; i < stack.length; i++) {
|
|
24086
|
+
if (stack[i] !== saved[i]) {
|
|
24087
|
+
stack[i] = this._makeTernary(cond, stack[i], saved[i]);
|
|
24088
|
+
}
|
|
24089
|
+
}
|
|
24090
|
+
} else if (stack.length > saved.length) {
|
|
24091
|
+
if (cond.type === PS_NODE.const) {
|
|
24092
|
+
if (!cond.value) {
|
|
24093
|
+
stack.length = 0;
|
|
24094
|
+
stack.push(...saved);
|
|
24095
|
+
}
|
|
24096
|
+
break;
|
|
24097
|
+
}
|
|
24098
|
+
const trueStack = stack.slice();
|
|
24099
|
+
this._evalBlockFrom(instructions, idx + 1, trueStack);
|
|
24100
|
+
if (this._failed) {
|
|
24101
|
+
break;
|
|
24102
|
+
}
|
|
24103
|
+
const falseStack = saved;
|
|
24104
|
+
this._evalBlockFrom(instructions, idx + 1, falseStack);
|
|
24105
|
+
if (this._failed) {
|
|
24106
|
+
break;
|
|
24107
|
+
}
|
|
24108
|
+
if (trueStack.length !== falseStack.length) {
|
|
24109
|
+
const zero2 = new PsConstNode(0);
|
|
24110
|
+
while (trueStack.length < falseStack.length) {
|
|
24111
|
+
trueStack.push(zero2);
|
|
24112
|
+
}
|
|
24113
|
+
while (falseStack.length < trueStack.length) {
|
|
24114
|
+
falseStack.push(zero2);
|
|
24115
|
+
}
|
|
24116
|
+
}
|
|
24117
|
+
stack.length = 0;
|
|
24118
|
+
for (let i = 0; i < trueStack.length; i++) {
|
|
24119
|
+
stack.push(this._makeTernary(cond, trueStack[i], falseStack[i]));
|
|
24120
|
+
}
|
|
24121
|
+
return;
|
|
24122
|
+
} else {
|
|
24123
|
+
this._failed = true;
|
|
24124
|
+
}
|
|
24125
|
+
break;
|
|
24126
|
+
}
|
|
24127
|
+
case PS_NODE.ifelse: {
|
|
24128
|
+
if (stack.length < 1) {
|
|
24129
|
+
this._failed = true;
|
|
24130
|
+
break;
|
|
24131
|
+
}
|
|
24132
|
+
const cond = stack.pop();
|
|
24133
|
+
const snapshot = stack.slice();
|
|
24134
|
+
const thenStack = snapshot.slice();
|
|
24135
|
+
this._evalBlock(instr.then, thenStack);
|
|
24136
|
+
if (this._failed) {
|
|
24137
|
+
break;
|
|
24138
|
+
}
|
|
24139
|
+
const elseStack = snapshot.slice();
|
|
24140
|
+
this._evalBlock(instr.otherwise, elseStack);
|
|
24141
|
+
if (this._failed) {
|
|
24142
|
+
break;
|
|
24143
|
+
}
|
|
24144
|
+
if (thenStack.length !== elseStack.length) {
|
|
24145
|
+
const zero2 = new PsConstNode(0);
|
|
24146
|
+
while (thenStack.length < elseStack.length) {
|
|
24147
|
+
thenStack.push(zero2);
|
|
24148
|
+
}
|
|
24149
|
+
while (elseStack.length < thenStack.length) {
|
|
24150
|
+
elseStack.push(zero2);
|
|
24151
|
+
}
|
|
24152
|
+
}
|
|
24153
|
+
stack.length = 0;
|
|
24154
|
+
for (let i = 0; i < thenStack.length; i++) {
|
|
24155
|
+
stack.push(this._makeTernary(cond, thenStack[i], elseStack[i]));
|
|
24156
|
+
}
|
|
24157
|
+
break;
|
|
24158
|
+
}
|
|
24159
|
+
}
|
|
24160
|
+
}
|
|
24161
|
+
}
|
|
24162
|
+
_evalOp(op, stack) {
|
|
24163
|
+
if (_PSStackToTree.#binaryOps.has(op)) {
|
|
24164
|
+
if (stack.length < 2) {
|
|
24165
|
+
this._failed = true;
|
|
24166
|
+
return;
|
|
24167
|
+
}
|
|
24168
|
+
const first = stack.pop();
|
|
24169
|
+
const second = stack.pop();
|
|
24170
|
+
stack.push(this._makeBinary(op, first, second));
|
|
24171
|
+
return;
|
|
24172
|
+
}
|
|
24173
|
+
if (_PSStackToTree.#unaryOps.has(op)) {
|
|
24174
|
+
if (stack.length < 1) {
|
|
24175
|
+
this._failed = true;
|
|
24176
|
+
return;
|
|
24177
|
+
}
|
|
24178
|
+
stack.push(this._makeUnary(op, stack.pop()));
|
|
24179
|
+
return;
|
|
24180
|
+
}
|
|
24181
|
+
switch (op) {
|
|
24182
|
+
case TOKEN.true:
|
|
24183
|
+
stack.push(new PsConstNode(true));
|
|
24184
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
24185
|
+
this._failed = true;
|
|
24186
|
+
}
|
|
24187
|
+
break;
|
|
24188
|
+
case TOKEN.false:
|
|
24189
|
+
stack.push(new PsConstNode(false));
|
|
24190
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
24191
|
+
this._failed = true;
|
|
24192
|
+
}
|
|
24193
|
+
break;
|
|
24194
|
+
case TOKEN.dup:
|
|
24195
|
+
if (stack.length < 1) {
|
|
24196
|
+
this._failed = true;
|
|
24197
|
+
break;
|
|
24198
|
+
}
|
|
24199
|
+
stack.push(stack.at(-1));
|
|
24200
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
24201
|
+
this._failed = true;
|
|
24202
|
+
}
|
|
24203
|
+
break;
|
|
24204
|
+
case TOKEN.exch: {
|
|
24205
|
+
if (stack.length < 2) {
|
|
24206
|
+
this._failed = true;
|
|
24207
|
+
break;
|
|
24208
|
+
}
|
|
24209
|
+
const a = stack.pop();
|
|
24210
|
+
const b = stack.pop();
|
|
24211
|
+
stack.push(a, b);
|
|
24212
|
+
break;
|
|
24213
|
+
}
|
|
24214
|
+
case TOKEN.pop:
|
|
24215
|
+
if (stack.length < 1) {
|
|
24216
|
+
this._failed = true;
|
|
24217
|
+
break;
|
|
24218
|
+
}
|
|
24219
|
+
stack.pop();
|
|
24220
|
+
break;
|
|
24221
|
+
case TOKEN.copy: {
|
|
24222
|
+
if (stack.length < 1) {
|
|
24223
|
+
this._failed = true;
|
|
24224
|
+
break;
|
|
24225
|
+
}
|
|
24226
|
+
const nNode = stack.pop();
|
|
24227
|
+
if (nNode.type === PS_NODE.const) {
|
|
24228
|
+
const n = nNode.value | 0;
|
|
24229
|
+
if (n === 0) {
|
|
24230
|
+
} else if (n < 0 || n > stack.length) {
|
|
24231
|
+
this._failed = true;
|
|
24232
|
+
} else {
|
|
24233
|
+
stack.push(...stack.slice(-n));
|
|
24234
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
24235
|
+
this._failed = true;
|
|
24236
|
+
}
|
|
24237
|
+
}
|
|
24238
|
+
} else {
|
|
24239
|
+
this._failed = true;
|
|
24240
|
+
}
|
|
24241
|
+
break;
|
|
24242
|
+
}
|
|
24243
|
+
case TOKEN.index: {
|
|
24244
|
+
if (stack.length < 1) {
|
|
24245
|
+
this._failed = true;
|
|
24246
|
+
break;
|
|
24247
|
+
}
|
|
24248
|
+
const nNode = stack.pop();
|
|
24249
|
+
if (nNode.type === PS_NODE.const) {
|
|
24250
|
+
const n = nNode.value | 0;
|
|
24251
|
+
if (n < 0 || n >= stack.length) {
|
|
24252
|
+
this._failed = true;
|
|
24253
|
+
} else {
|
|
24254
|
+
stack.push(stack.at(-n - 1));
|
|
24255
|
+
}
|
|
24256
|
+
} else {
|
|
24257
|
+
this._failed = true;
|
|
24258
|
+
}
|
|
24259
|
+
break;
|
|
24260
|
+
}
|
|
24261
|
+
case TOKEN.roll: {
|
|
24262
|
+
if (stack.length < 2) {
|
|
24263
|
+
this._failed = true;
|
|
24264
|
+
break;
|
|
24265
|
+
}
|
|
24266
|
+
const jNode = stack.pop();
|
|
24267
|
+
const nNode = stack.pop();
|
|
24268
|
+
if (nNode.type === PS_NODE.const && jNode.type === PS_NODE.const) {
|
|
24269
|
+
const n = nNode.value | 0;
|
|
24270
|
+
if (n === 0) {
|
|
24271
|
+
} else if (n < 0 || n > stack.length) {
|
|
24272
|
+
this._failed = true;
|
|
24273
|
+
} else {
|
|
24274
|
+
const j = ((jNode.value | 0) % n + n) % n;
|
|
24275
|
+
if (j > 0) {
|
|
24276
|
+
const slice = stack.splice(-n, n);
|
|
24277
|
+
stack.push(...slice.slice(n - j), ...slice.slice(0, n - j));
|
|
24278
|
+
}
|
|
24279
|
+
}
|
|
24280
|
+
} else {
|
|
24281
|
+
this._failed = true;
|
|
24282
|
+
}
|
|
24283
|
+
break;
|
|
24284
|
+
}
|
|
24285
|
+
default:
|
|
24286
|
+
this._failed = true;
|
|
24287
|
+
break;
|
|
24288
|
+
}
|
|
24289
|
+
}
|
|
24290
|
+
/**
|
|
24291
|
+
* Create a binary tree node, applying optimizations eagerly:
|
|
24292
|
+
*
|
|
24293
|
+
* 1. Constant folding — both operands are PsConstNode → fold to PsConstNode.
|
|
24294
|
+
* 2. Reflexive simplifications — x−x→0, x xor x→0, x eq x→true, etc.
|
|
24295
|
+
* 3. Algebraic simplifications with one known operand — identity elements
|
|
24296
|
+
* (x+0→x, x*1→x, …), absorbing elements (x*0→0, x and false→false, …),
|
|
24297
|
+
* and strength reductions (x*-1→neg(x), x^0.5→sqrt(x), x^2→x*x, …).
|
|
24298
|
+
*
|
|
24299
|
+
* Recall: `first` was on top of the stack (right operand for non-commutative
|
|
24300
|
+
* ops), `second` was below (left operand). So `a b sub` → second=a, first=b
|
|
24301
|
+
* → a − b.
|
|
24302
|
+
*/
|
|
24303
|
+
_makeBinary(op, first, second) {
|
|
24304
|
+
if (first.type === PS_NODE.const && second.type === PS_NODE.const) {
|
|
24305
|
+
const v = _evalBinaryConst(op, second.value, first.value);
|
|
24306
|
+
if (v !== void 0) {
|
|
24307
|
+
return new PsConstNode(v);
|
|
24308
|
+
}
|
|
24309
|
+
}
|
|
24310
|
+
if (_nodesEqual(first, second)) {
|
|
24311
|
+
switch (op) {
|
|
24312
|
+
case TOKEN.sub:
|
|
24313
|
+
return new PsConstNode(0);
|
|
24314
|
+
// x − x → 0
|
|
24315
|
+
case TOKEN.xor:
|
|
24316
|
+
return new PsConstNode(
|
|
24317
|
+
/* eslint-disable unicorn/prefer-logical-operator-over-ternary */
|
|
24318
|
+
first.valueType === PS_VALUE_TYPE.boolean ? false : 0
|
|
24319
|
+
/* eslint-enable unicorn/prefer-logical-operator-over-ternary */
|
|
24320
|
+
);
|
|
24321
|
+
// TOKEN.mod, TOKEN.div, TOKEN.idiv are NOT simplified here:
|
|
24322
|
+
// x op x is undefined when x = 0, so we cannot fold without knowing
|
|
24323
|
+
// that x is non-zero.
|
|
24324
|
+
case TOKEN.and:
|
|
24325
|
+
case TOKEN.or:
|
|
24326
|
+
return first;
|
|
24327
|
+
// x and x → x; x or x → x
|
|
24328
|
+
case TOKEN.min:
|
|
24329
|
+
case TOKEN.max:
|
|
24330
|
+
return first;
|
|
24331
|
+
// min(x,x) → x; max(x,x) → x
|
|
24332
|
+
case TOKEN.eq:
|
|
24333
|
+
case TOKEN.ge:
|
|
24334
|
+
case TOKEN.le:
|
|
24335
|
+
return new PsConstNode(true);
|
|
24336
|
+
case TOKEN.ne:
|
|
24337
|
+
case TOKEN.gt:
|
|
24338
|
+
case TOKEN.lt:
|
|
24339
|
+
return new PsConstNode(false);
|
|
24340
|
+
}
|
|
24341
|
+
}
|
|
24342
|
+
if (first.type === PS_NODE.const) {
|
|
24343
|
+
const b = first.value;
|
|
24344
|
+
switch (op) {
|
|
24345
|
+
case TOKEN.add:
|
|
24346
|
+
if (b === 0) {
|
|
24347
|
+
return second;
|
|
24348
|
+
}
|
|
24349
|
+
break;
|
|
24350
|
+
case TOKEN.sub:
|
|
24351
|
+
if (b === 0) {
|
|
24352
|
+
return second;
|
|
24353
|
+
}
|
|
24354
|
+
break;
|
|
24355
|
+
case TOKEN.mul:
|
|
24356
|
+
if (b === 1) {
|
|
24357
|
+
return second;
|
|
24358
|
+
}
|
|
24359
|
+
if (b === 0) {
|
|
24360
|
+
return first;
|
|
24361
|
+
}
|
|
24362
|
+
if (b === -1) {
|
|
24363
|
+
return this._makeUnary(TOKEN.neg, second);
|
|
24364
|
+
}
|
|
24365
|
+
break;
|
|
24366
|
+
case TOKEN.div:
|
|
24367
|
+
if (b !== 0) {
|
|
24368
|
+
return this._makeBinary(TOKEN.mul, new PsConstNode(1 / b), second);
|
|
24369
|
+
}
|
|
24370
|
+
break;
|
|
24371
|
+
case TOKEN.idiv:
|
|
24372
|
+
if (b === 1) {
|
|
24373
|
+
return second;
|
|
24374
|
+
}
|
|
24375
|
+
break;
|
|
24376
|
+
case TOKEN.exp:
|
|
24377
|
+
if (b === 1) {
|
|
24378
|
+
return second;
|
|
24379
|
+
}
|
|
24380
|
+
if (b === -1) {
|
|
24381
|
+
return this._makeBinary(TOKEN.div, second, new PsConstNode(1));
|
|
24382
|
+
}
|
|
24383
|
+
if (b === 0.5) {
|
|
24384
|
+
return this._makeUnary(TOKEN.sqrt, second);
|
|
24385
|
+
}
|
|
24386
|
+
if (b === 0.25) {
|
|
24387
|
+
const sqrtOnce = this._makeUnary(TOKEN.sqrt, second);
|
|
24388
|
+
return this._makeUnary(TOKEN.sqrt, sqrtOnce);
|
|
24389
|
+
}
|
|
24390
|
+
if (b === 2) {
|
|
24391
|
+
return this._makeBinary(TOKEN.mul, second, second);
|
|
24392
|
+
}
|
|
24393
|
+
if (b === 3) {
|
|
24394
|
+
return this._makeBinary(
|
|
24395
|
+
TOKEN.mul,
|
|
24396
|
+
this._makeBinary(TOKEN.mul, second, second),
|
|
24397
|
+
second
|
|
24398
|
+
);
|
|
24399
|
+
}
|
|
24400
|
+
if (b === 4) {
|
|
24401
|
+
const square = this._makeBinary(TOKEN.mul, second, second);
|
|
24402
|
+
return this._makeBinary(TOKEN.mul, square, square);
|
|
24403
|
+
}
|
|
24404
|
+
if (b === 0) {
|
|
24405
|
+
return new PsConstNode(1);
|
|
24406
|
+
}
|
|
24407
|
+
break;
|
|
24408
|
+
case TOKEN.and:
|
|
24409
|
+
if (b === true) {
|
|
24410
|
+
return second;
|
|
24411
|
+
}
|
|
24412
|
+
if (b === false) {
|
|
24413
|
+
return first;
|
|
24414
|
+
}
|
|
24415
|
+
break;
|
|
24416
|
+
case TOKEN.or:
|
|
24417
|
+
if (b === false) {
|
|
24418
|
+
return second;
|
|
24419
|
+
}
|
|
24420
|
+
if (b === true) {
|
|
24421
|
+
return first;
|
|
24422
|
+
}
|
|
24423
|
+
break;
|
|
24424
|
+
case TOKEN.min:
|
|
24425
|
+
if (second.type === PS_NODE.binary && second.op === TOKEN.max && second.first.type === PS_NODE.const && second.first.value >= b) {
|
|
24426
|
+
return first;
|
|
24427
|
+
}
|
|
24428
|
+
break;
|
|
24429
|
+
case TOKEN.max:
|
|
24430
|
+
if (second.type === PS_NODE.binary && second.op === TOKEN.min && second.first.type === PS_NODE.const && second.first.value <= b) {
|
|
24431
|
+
return first;
|
|
24432
|
+
}
|
|
24433
|
+
break;
|
|
24434
|
+
}
|
|
24435
|
+
}
|
|
24436
|
+
if (second.type === PS_NODE.const) {
|
|
24437
|
+
const a = second.value;
|
|
24438
|
+
switch (op) {
|
|
24439
|
+
case TOKEN.add:
|
|
24440
|
+
if (a === 0) {
|
|
24441
|
+
return first;
|
|
24442
|
+
}
|
|
24443
|
+
break;
|
|
24444
|
+
case TOKEN.sub:
|
|
24445
|
+
if (a === 0) {
|
|
24446
|
+
return this._makeUnary(TOKEN.neg, first);
|
|
24447
|
+
}
|
|
24448
|
+
break;
|
|
24449
|
+
case TOKEN.mul:
|
|
24450
|
+
if (a === 1) {
|
|
24451
|
+
return first;
|
|
24452
|
+
}
|
|
24453
|
+
if (a === 0) {
|
|
24454
|
+
return second;
|
|
24455
|
+
}
|
|
24456
|
+
if (a === -1) {
|
|
24457
|
+
return this._makeUnary(TOKEN.neg, first);
|
|
24458
|
+
}
|
|
24459
|
+
break;
|
|
24460
|
+
case TOKEN.and:
|
|
24461
|
+
if (a === true) {
|
|
24462
|
+
return first;
|
|
24463
|
+
}
|
|
24464
|
+
if (a === false) {
|
|
24465
|
+
return second;
|
|
24466
|
+
}
|
|
24467
|
+
break;
|
|
24468
|
+
case TOKEN.or:
|
|
24469
|
+
if (a === false) {
|
|
24470
|
+
return first;
|
|
24471
|
+
}
|
|
24472
|
+
if (a === true) {
|
|
24473
|
+
return second;
|
|
24474
|
+
}
|
|
24475
|
+
break;
|
|
24476
|
+
}
|
|
24477
|
+
}
|
|
24478
|
+
return new PsBinaryNode(
|
|
24479
|
+
op,
|
|
24480
|
+
first,
|
|
24481
|
+
second,
|
|
24482
|
+
_binaryValueType(op, first.valueType, second.valueType)
|
|
24483
|
+
);
|
|
24484
|
+
}
|
|
24485
|
+
/**
|
|
24486
|
+
* Create a unary tree node, applying optimizations eagerly:
|
|
24487
|
+
*
|
|
24488
|
+
* 1. Constant folding.
|
|
24489
|
+
* 2. not(comparison) → negated comparison: not(a eq b) → a ne b, etc.
|
|
24490
|
+
* 3. neg(a − b) → b − a.
|
|
24491
|
+
* 4. Double-negation: neg(neg(x)) → x, not(not(x)) → x.
|
|
24492
|
+
* 5. abs(neg(x)) → abs(x).
|
|
24493
|
+
* 6. Idempotent: f(f(x)) → f(x) for abs, ceiling, floor, round, etc.
|
|
24494
|
+
*/
|
|
24495
|
+
_makeUnary(op, operand) {
|
|
24496
|
+
if (operand.type === PS_NODE.const) {
|
|
24497
|
+
const v = _evalUnaryConst(op, operand.value);
|
|
24498
|
+
if (v !== void 0) {
|
|
24499
|
+
return new PsConstNode(v);
|
|
24500
|
+
}
|
|
24501
|
+
}
|
|
24502
|
+
if (op === TOKEN.not && operand.type === PS_NODE.binary) {
|
|
24503
|
+
const negated = _PSStackToTree.#negatedComparison.get(operand.op);
|
|
24504
|
+
if (negated !== void 0) {
|
|
24505
|
+
return new PsBinaryNode(
|
|
24506
|
+
negated,
|
|
24507
|
+
operand.first,
|
|
24508
|
+
operand.second,
|
|
24509
|
+
PS_VALUE_TYPE.boolean
|
|
24510
|
+
);
|
|
24511
|
+
}
|
|
24512
|
+
}
|
|
24513
|
+
if (op === TOKEN.neg && operand.type === PS_NODE.binary && operand.op === TOKEN.sub) {
|
|
24514
|
+
return this._makeBinary(TOKEN.sub, operand.second, operand.first);
|
|
24515
|
+
}
|
|
24516
|
+
if (operand.type === PS_NODE.unary) {
|
|
24517
|
+
if (op === TOKEN.neg && operand.op === TOKEN.neg || op === TOKEN.not && operand.op === TOKEN.not) {
|
|
24518
|
+
return operand.operand;
|
|
24519
|
+
}
|
|
24520
|
+
if (op === TOKEN.abs && operand.op === TOKEN.neg) {
|
|
24521
|
+
return this._makeUnary(TOKEN.abs, operand.operand);
|
|
24522
|
+
}
|
|
24523
|
+
if (_PSStackToTree.#idempotentUnary.has(op) && op === operand.op) {
|
|
24524
|
+
return operand;
|
|
24525
|
+
}
|
|
24526
|
+
}
|
|
24527
|
+
return new PsUnaryNode(op, operand, _unaryValueType(op, operand.valueType));
|
|
24528
|
+
}
|
|
24529
|
+
/**
|
|
24530
|
+
* Create a ternary node, applying optimizations eagerly:
|
|
24531
|
+
*
|
|
24532
|
+
* 1. Constant condition — fold to the live branch.
|
|
24533
|
+
* 2. Identical branches — the condition is irrelevant, return either branch.
|
|
24534
|
+
* 3. Boolean branch constants — `cond ? true : false` → cond,
|
|
24535
|
+
* `cond ? false : true` → not(cond).
|
|
24536
|
+
* 4. Ternary → branchless min/max when the condition compares two numeric
|
|
24537
|
+
* expressions that are also the two branches.
|
|
24538
|
+
*/
|
|
24539
|
+
_makeTernary(cond, then, otherwise) {
|
|
24540
|
+
if (cond.type === PS_NODE.const) {
|
|
24541
|
+
return cond.value ? then : otherwise;
|
|
24542
|
+
}
|
|
24543
|
+
if (_nodesEqual(then, otherwise)) {
|
|
24544
|
+
return then;
|
|
24545
|
+
}
|
|
24546
|
+
if (then.type === PS_NODE.const && otherwise.type === PS_NODE.const) {
|
|
24547
|
+
if (then.value === true && otherwise.value === false) {
|
|
24548
|
+
return cond;
|
|
24549
|
+
}
|
|
24550
|
+
if (then.value === false && otherwise.value === true) {
|
|
24551
|
+
return this._makeUnary(TOKEN.not, cond);
|
|
24552
|
+
}
|
|
24553
|
+
}
|
|
24554
|
+
if (cond.type === PS_NODE.binary) {
|
|
24555
|
+
const { op: cop, first: cf, second: cs } = cond;
|
|
24556
|
+
if (cop === TOKEN.gt || cop === TOKEN.ge) {
|
|
24557
|
+
if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
|
|
24558
|
+
return this._makeBinary(TOKEN.min, cf, cs);
|
|
24559
|
+
}
|
|
24560
|
+
if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
|
|
24561
|
+
return this._makeBinary(TOKEN.max, cf, cs);
|
|
24562
|
+
}
|
|
24563
|
+
} else if (cop === TOKEN.lt || cop === TOKEN.le) {
|
|
24564
|
+
if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
|
|
24565
|
+
return this._makeBinary(TOKEN.max, cf, cs);
|
|
24566
|
+
}
|
|
24567
|
+
if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
|
|
24568
|
+
return this._makeBinary(TOKEN.min, cf, cs);
|
|
24569
|
+
}
|
|
24570
|
+
}
|
|
24571
|
+
}
|
|
24572
|
+
return new PsTernaryNode(
|
|
24573
|
+
cond,
|
|
24574
|
+
then,
|
|
24575
|
+
otherwise,
|
|
24576
|
+
then.valueType === otherwise.valueType ? then.valueType : PS_VALUE_TYPE.unknown
|
|
24577
|
+
);
|
|
24578
|
+
}
|
|
24579
|
+
};
|
|
24580
|
+
var OP = {
|
|
24581
|
+
ARG: 0,
|
|
24582
|
+
// [ARG, idx]
|
|
24583
|
+
CONST: 1,
|
|
24584
|
+
// [CONST, val]
|
|
24585
|
+
STORE: 2,
|
|
24586
|
+
// [STORE, slot, min, max] clamp(pop()) → mem[slot]
|
|
24587
|
+
IF: 3,
|
|
24588
|
+
// [IF, target] jump when top-of-stack === 0
|
|
24589
|
+
JUMP: 4,
|
|
24590
|
+
// [JUMP, target] unconditional
|
|
24591
|
+
ABS: 5,
|
|
24592
|
+
NEG: 6,
|
|
24593
|
+
CEIL: 7,
|
|
24594
|
+
FLOOR: 8,
|
|
24595
|
+
ROUND: 9,
|
|
24596
|
+
// floor(x + 0.5)
|
|
24597
|
+
TRUNC: 10,
|
|
24598
|
+
NOT_B: 11,
|
|
24599
|
+
// boolean NOT
|
|
24600
|
+
NOT_N: 12,
|
|
24601
|
+
// bitwise NOT
|
|
24602
|
+
SQRT: 13,
|
|
24603
|
+
SIN: 14,
|
|
24604
|
+
// degrees in/out
|
|
24605
|
+
COS: 15,
|
|
24606
|
+
LN: 16,
|
|
24607
|
+
LOG10: 17,
|
|
24608
|
+
CVI: 18,
|
|
24609
|
+
SHIFT: 19,
|
|
24610
|
+
// [SHIFT, amount] +ve = left, −ve = right
|
|
24611
|
+
// Binary ops: second below, first on top; result = second OP first.
|
|
24612
|
+
ADD: 20,
|
|
24613
|
+
SUB: 21,
|
|
24614
|
+
MUL: 22,
|
|
24615
|
+
DIV: 23,
|
|
24616
|
+
// 0 when divisor is 0
|
|
24617
|
+
IDIV: 24,
|
|
24618
|
+
// 0 when divisor is 0
|
|
24619
|
+
MOD: 25,
|
|
24620
|
+
// 0 when divisor is 0
|
|
24621
|
+
POW: 26,
|
|
24622
|
+
EQ: 27,
|
|
24623
|
+
NE: 28,
|
|
24624
|
+
GT: 29,
|
|
24625
|
+
GE: 30,
|
|
24626
|
+
LT: 31,
|
|
24627
|
+
LE: 32,
|
|
24628
|
+
AND: 33,
|
|
24629
|
+
OR: 34,
|
|
24630
|
+
XOR: 35,
|
|
24631
|
+
ATAN: 36,
|
|
24632
|
+
// atan2(second, first) → degrees [0, 360)
|
|
24633
|
+
MIN: 37,
|
|
24634
|
+
MAX: 38,
|
|
24635
|
+
TEE_TMP: 39,
|
|
24636
|
+
// [TEE_TMP, slot] peek top of stack → tmp[slot], leave on stack
|
|
24637
|
+
LOAD_TMP: 40
|
|
24638
|
+
// [LOAD_TMP, slot] push tmp[slot]
|
|
24639
|
+
};
|
|
24640
|
+
var _DEG_TO_RAD = Math.PI / 180;
|
|
24641
|
+
var _RAD_TO_DEG = 180 / Math.PI;
|
|
24642
|
+
var PsJsCompiler = class {
|
|
24643
|
+
// Safe because JS is single-threaded.
|
|
24644
|
+
static #stack = new Float64Array(64);
|
|
24645
|
+
static #tmp = new Float64Array(64);
|
|
24646
|
+
constructor(domain, range) {
|
|
24647
|
+
this.nIn = domain.length >> 1;
|
|
24648
|
+
this.nOut = range.length >> 1;
|
|
24649
|
+
this.range = range;
|
|
24650
|
+
this.ir = [];
|
|
24651
|
+
this._tmpMap = /* @__PURE__ */ new Map();
|
|
24652
|
+
this._nextTmp = 0;
|
|
24653
|
+
}
|
|
24654
|
+
_compileNode(node) {
|
|
24655
|
+
if (node.shared) {
|
|
24656
|
+
const cached = this._tmpMap.get(node);
|
|
24657
|
+
if (cached !== void 0) {
|
|
24658
|
+
this.ir.push(OP.LOAD_TMP, cached);
|
|
24659
|
+
return true;
|
|
24660
|
+
}
|
|
24661
|
+
if (!this._compileNodeImpl(node)) {
|
|
24662
|
+
return false;
|
|
24663
|
+
}
|
|
24664
|
+
const slot = this._nextTmp++;
|
|
24665
|
+
this._tmpMap.set(node, slot);
|
|
24666
|
+
this.ir.push(OP.TEE_TMP, slot);
|
|
24667
|
+
return true;
|
|
24668
|
+
}
|
|
24669
|
+
return this._compileNodeImpl(node);
|
|
24670
|
+
}
|
|
24671
|
+
_compileNodeImpl(node) {
|
|
24672
|
+
switch (node.type) {
|
|
24673
|
+
case PS_NODE.arg:
|
|
24674
|
+
this.ir.push(OP.ARG, node.index);
|
|
24675
|
+
return true;
|
|
24676
|
+
case PS_NODE.const: {
|
|
24677
|
+
const v = node.value;
|
|
24678
|
+
this.ir.push(OP.CONST, typeof v === "boolean" ? Number(v) : v);
|
|
24679
|
+
return true;
|
|
24680
|
+
}
|
|
24681
|
+
case PS_NODE.unary:
|
|
24682
|
+
return this._compileUnary(node);
|
|
24683
|
+
case PS_NODE.binary:
|
|
24684
|
+
return this._compileBinary(node);
|
|
24685
|
+
case PS_NODE.ternary:
|
|
24686
|
+
return this._compileTernary(node);
|
|
24687
|
+
default:
|
|
24688
|
+
return false;
|
|
24689
|
+
}
|
|
24690
|
+
}
|
|
24691
|
+
_compileUnary(node) {
|
|
24692
|
+
const { op, operand, valueType } = node;
|
|
24693
|
+
if (op === TOKEN.cvr) {
|
|
24694
|
+
return this._compileNode(operand);
|
|
24695
|
+
}
|
|
24696
|
+
if (!this._compileNode(operand)) {
|
|
24697
|
+
return false;
|
|
24698
|
+
}
|
|
24699
|
+
switch (op) {
|
|
24700
|
+
case TOKEN.abs:
|
|
24701
|
+
this.ir.push(OP.ABS);
|
|
24702
|
+
break;
|
|
24703
|
+
case TOKEN.neg:
|
|
24704
|
+
this.ir.push(OP.NEG);
|
|
24705
|
+
break;
|
|
24706
|
+
case TOKEN.ceiling:
|
|
24707
|
+
this.ir.push(OP.CEIL);
|
|
24708
|
+
break;
|
|
24709
|
+
case TOKEN.floor:
|
|
24710
|
+
this.ir.push(OP.FLOOR);
|
|
24711
|
+
break;
|
|
24712
|
+
case TOKEN.round:
|
|
24713
|
+
this.ir.push(OP.ROUND);
|
|
24714
|
+
break;
|
|
24715
|
+
case TOKEN.truncate:
|
|
24716
|
+
this.ir.push(OP.TRUNC);
|
|
24717
|
+
break;
|
|
24718
|
+
case TOKEN.sqrt:
|
|
24719
|
+
this.ir.push(OP.SQRT);
|
|
24720
|
+
break;
|
|
24721
|
+
case TOKEN.sin:
|
|
24722
|
+
this.ir.push(OP.SIN);
|
|
24723
|
+
break;
|
|
24724
|
+
case TOKEN.cos:
|
|
24725
|
+
this.ir.push(OP.COS);
|
|
24726
|
+
break;
|
|
24727
|
+
case TOKEN.ln:
|
|
24728
|
+
this.ir.push(OP.LN);
|
|
24729
|
+
break;
|
|
24730
|
+
case TOKEN.log:
|
|
24731
|
+
this.ir.push(OP.LOG10);
|
|
24732
|
+
break;
|
|
24733
|
+
case TOKEN.cvi:
|
|
24734
|
+
this.ir.push(OP.CVI);
|
|
24735
|
+
break;
|
|
24736
|
+
case TOKEN.not:
|
|
24737
|
+
if (valueType === PS_VALUE_TYPE.boolean) {
|
|
24738
|
+
this.ir.push(OP.NOT_B);
|
|
24739
|
+
} else if (valueType === PS_VALUE_TYPE.numeric) {
|
|
24740
|
+
this.ir.push(OP.NOT_N);
|
|
24741
|
+
} else {
|
|
24742
|
+
return false;
|
|
24743
|
+
}
|
|
24744
|
+
break;
|
|
24745
|
+
default:
|
|
24746
|
+
return false;
|
|
24747
|
+
}
|
|
24748
|
+
return true;
|
|
24749
|
+
}
|
|
24750
|
+
_compileBinary(node) {
|
|
24751
|
+
const { op, first, second } = node;
|
|
24752
|
+
if (op === TOKEN.bitshift) {
|
|
24753
|
+
if (first.type !== PS_NODE.const || !Number.isInteger(first.value) || !this._compileNode(second)) {
|
|
24754
|
+
return false;
|
|
24755
|
+
}
|
|
24756
|
+
this.ir.push(OP.SHIFT, first.value);
|
|
24757
|
+
return true;
|
|
24758
|
+
}
|
|
24759
|
+
if (!this._compileNode(second) || !this._compileNode(first)) {
|
|
24760
|
+
return false;
|
|
24761
|
+
}
|
|
24762
|
+
switch (op) {
|
|
24763
|
+
case TOKEN.add:
|
|
24764
|
+
this.ir.push(OP.ADD);
|
|
24765
|
+
break;
|
|
24766
|
+
case TOKEN.sub:
|
|
24767
|
+
this.ir.push(OP.SUB);
|
|
24768
|
+
break;
|
|
24769
|
+
case TOKEN.mul:
|
|
24770
|
+
this.ir.push(OP.MUL);
|
|
24771
|
+
break;
|
|
24772
|
+
case TOKEN.div:
|
|
24773
|
+
this.ir.push(OP.DIV);
|
|
24774
|
+
break;
|
|
24775
|
+
case TOKEN.idiv:
|
|
24776
|
+
this.ir.push(OP.IDIV);
|
|
24777
|
+
break;
|
|
24778
|
+
case TOKEN.mod:
|
|
24779
|
+
this.ir.push(OP.MOD);
|
|
24780
|
+
break;
|
|
24781
|
+
case TOKEN.exp:
|
|
24782
|
+
this.ir.push(OP.POW);
|
|
24783
|
+
break;
|
|
24784
|
+
case TOKEN.eq:
|
|
24785
|
+
this.ir.push(OP.EQ);
|
|
24786
|
+
break;
|
|
24787
|
+
case TOKEN.ne:
|
|
24788
|
+
this.ir.push(OP.NE);
|
|
24789
|
+
break;
|
|
24790
|
+
case TOKEN.gt:
|
|
24791
|
+
this.ir.push(OP.GT);
|
|
24792
|
+
break;
|
|
24793
|
+
case TOKEN.ge:
|
|
24794
|
+
this.ir.push(OP.GE);
|
|
24795
|
+
break;
|
|
24796
|
+
case TOKEN.lt:
|
|
24797
|
+
this.ir.push(OP.LT);
|
|
24798
|
+
break;
|
|
24799
|
+
case TOKEN.le:
|
|
24800
|
+
this.ir.push(OP.LE);
|
|
24801
|
+
break;
|
|
24802
|
+
case TOKEN.and:
|
|
24803
|
+
this.ir.push(OP.AND);
|
|
24804
|
+
break;
|
|
24805
|
+
case TOKEN.or:
|
|
24806
|
+
this.ir.push(OP.OR);
|
|
24807
|
+
break;
|
|
24808
|
+
case TOKEN.xor:
|
|
24809
|
+
this.ir.push(OP.XOR);
|
|
24810
|
+
break;
|
|
24811
|
+
case TOKEN.atan:
|
|
24812
|
+
this.ir.push(OP.ATAN);
|
|
24813
|
+
break;
|
|
24814
|
+
case TOKEN.min:
|
|
24815
|
+
this.ir.push(OP.MIN);
|
|
24816
|
+
break;
|
|
24817
|
+
case TOKEN.max:
|
|
24818
|
+
this.ir.push(OP.MAX);
|
|
24819
|
+
break;
|
|
24820
|
+
default:
|
|
24821
|
+
return false;
|
|
24822
|
+
}
|
|
24823
|
+
return true;
|
|
24824
|
+
}
|
|
24825
|
+
_compileTernary(node) {
|
|
24826
|
+
if (!this._compileNode(node.cond)) {
|
|
24827
|
+
return false;
|
|
24828
|
+
}
|
|
24829
|
+
this.ir.push(OP.IF, 0);
|
|
24830
|
+
const ifPatch = this.ir.length - 1;
|
|
24831
|
+
if (!this._compileNode(node.then)) {
|
|
24832
|
+
return false;
|
|
24833
|
+
}
|
|
24834
|
+
this.ir.push(OP.JUMP, 0);
|
|
24835
|
+
const jumpPatch = this.ir.length - 1;
|
|
24836
|
+
this.ir[ifPatch] = this.ir.length;
|
|
24837
|
+
if (!this._compileNode(node.otherwise)) {
|
|
24838
|
+
return false;
|
|
24839
|
+
}
|
|
24840
|
+
this.ir[jumpPatch] = this.ir.length;
|
|
24841
|
+
return true;
|
|
24842
|
+
}
|
|
24843
|
+
compile(program) {
|
|
24844
|
+
const outputs = new PSStackToTree().evaluate(program, this.nIn);
|
|
24845
|
+
if (!outputs || outputs.length < this.nOut) {
|
|
24846
|
+
return null;
|
|
24847
|
+
}
|
|
24848
|
+
for (let i = 0; i < this.nOut; i++) {
|
|
24849
|
+
if (!this._compileNode(outputs[i])) {
|
|
24850
|
+
return null;
|
|
24851
|
+
}
|
|
24852
|
+
const min = this.range[i * 2];
|
|
24853
|
+
const max = this.range[i * 2 + 1];
|
|
24854
|
+
this.ir.push(OP.STORE, i, min, max);
|
|
24855
|
+
}
|
|
24856
|
+
return new Float64Array(this.ir);
|
|
24857
|
+
}
|
|
24858
|
+
static execute(ir, src, srcOffset, dest, destOffset) {
|
|
24859
|
+
let ip = 0, sp = 0;
|
|
24860
|
+
const n = ir.length;
|
|
24861
|
+
const stack = this.#stack;
|
|
24862
|
+
const tmp = this.#tmp;
|
|
24863
|
+
while (ip < n) {
|
|
24864
|
+
switch (ir[ip++] | 0) {
|
|
24865
|
+
case OP.ARG:
|
|
24866
|
+
stack[sp++] = src[srcOffset + (ir[ip++] | 0)];
|
|
24867
|
+
break;
|
|
24868
|
+
case OP.CONST:
|
|
24869
|
+
stack[sp++] = ir[ip++];
|
|
24870
|
+
break;
|
|
24871
|
+
case OP.STORE: {
|
|
24872
|
+
const slot = ir[ip++] | 0;
|
|
24873
|
+
const min = ir[ip++];
|
|
24874
|
+
const max = ir[ip++];
|
|
24875
|
+
dest[destOffset + slot] = MathClamp(stack[--sp], min, max);
|
|
24876
|
+
break;
|
|
24877
|
+
}
|
|
24878
|
+
case OP.IF: {
|
|
24879
|
+
const tgt = ir[ip++];
|
|
24880
|
+
if (stack[--sp] === 0) {
|
|
24881
|
+
ip = tgt;
|
|
24882
|
+
}
|
|
24883
|
+
break;
|
|
24884
|
+
}
|
|
24885
|
+
case OP.JUMP:
|
|
24886
|
+
ip = ir[ip];
|
|
24887
|
+
break;
|
|
24888
|
+
case OP.ABS:
|
|
24889
|
+
stack[sp - 1] = Math.abs(stack[sp - 1]);
|
|
24890
|
+
break;
|
|
24891
|
+
case OP.NEG:
|
|
24892
|
+
stack[sp - 1] = -stack[sp - 1];
|
|
24893
|
+
break;
|
|
24894
|
+
case OP.CEIL:
|
|
24895
|
+
stack[sp - 1] = Math.ceil(stack[sp - 1]);
|
|
24896
|
+
break;
|
|
24897
|
+
case OP.FLOOR:
|
|
24898
|
+
stack[sp - 1] = Math.floor(stack[sp - 1]);
|
|
24899
|
+
break;
|
|
24900
|
+
case OP.ROUND:
|
|
24901
|
+
stack[sp - 1] = Math.floor(stack[sp - 1] + 0.5);
|
|
24902
|
+
break;
|
|
24903
|
+
case OP.TRUNC:
|
|
24904
|
+
stack[sp - 1] = Math.trunc(stack[sp - 1]);
|
|
24905
|
+
break;
|
|
24906
|
+
case OP.NOT_B:
|
|
24907
|
+
stack[sp - 1] = stack[sp - 1] !== 0 ? 0 : 1;
|
|
24908
|
+
break;
|
|
24909
|
+
case OP.NOT_N:
|
|
24910
|
+
stack[sp - 1] = ~(stack[sp - 1] | 0);
|
|
24911
|
+
break;
|
|
24912
|
+
case OP.SQRT:
|
|
24913
|
+
stack[sp - 1] = Math.sqrt(stack[sp - 1]);
|
|
24914
|
+
break;
|
|
24915
|
+
case OP.SIN:
|
|
24916
|
+
stack[sp - 1] = Math.sin(stack[sp - 1] % 360 * _DEG_TO_RAD);
|
|
24917
|
+
break;
|
|
24918
|
+
case OP.COS:
|
|
24919
|
+
stack[sp - 1] = Math.cos(stack[sp - 1] % 360 * _DEG_TO_RAD);
|
|
24920
|
+
break;
|
|
24921
|
+
case OP.LN:
|
|
24922
|
+
stack[sp - 1] = Math.log(stack[sp - 1]);
|
|
24923
|
+
break;
|
|
24924
|
+
case OP.LOG10:
|
|
24925
|
+
stack[sp - 1] = Math.log10(stack[sp - 1]);
|
|
24926
|
+
break;
|
|
24927
|
+
case OP.CVI:
|
|
24928
|
+
stack[sp - 1] = Math.trunc(stack[sp - 1]) | 0;
|
|
24929
|
+
break;
|
|
24930
|
+
case OP.SHIFT: {
|
|
24931
|
+
const amt = ir[ip++];
|
|
24932
|
+
const v = stack[sp - 1] | 0;
|
|
24933
|
+
if (amt > 0) {
|
|
24934
|
+
stack[sp - 1] = v << amt;
|
|
24935
|
+
} else if (amt < 0) {
|
|
24936
|
+
stack[sp - 1] = v >> -amt;
|
|
24937
|
+
} else {
|
|
24938
|
+
stack[sp - 1] = v;
|
|
24939
|
+
}
|
|
24940
|
+
break;
|
|
24941
|
+
}
|
|
24942
|
+
case OP.ADD: {
|
|
24943
|
+
const b = stack[--sp];
|
|
24944
|
+
stack[sp - 1] += b;
|
|
24945
|
+
break;
|
|
24946
|
+
}
|
|
24947
|
+
case OP.SUB: {
|
|
24948
|
+
const b = stack[--sp];
|
|
24949
|
+
stack[sp - 1] -= b;
|
|
24950
|
+
break;
|
|
24951
|
+
}
|
|
24952
|
+
case OP.MUL: {
|
|
24953
|
+
const b = stack[--sp];
|
|
24954
|
+
stack[sp - 1] *= b;
|
|
24955
|
+
break;
|
|
24956
|
+
}
|
|
24957
|
+
case OP.DIV: {
|
|
24958
|
+
const b = stack[--sp];
|
|
24959
|
+
stack[sp - 1] = b !== 0 ? stack[sp - 1] / b : 0;
|
|
24960
|
+
break;
|
|
24961
|
+
}
|
|
24962
|
+
case OP.IDIV: {
|
|
24963
|
+
const b = stack[--sp];
|
|
24964
|
+
stack[sp - 1] = b !== 0 ? Math.trunc(stack[sp - 1] / b) : 0;
|
|
24965
|
+
break;
|
|
24966
|
+
}
|
|
24967
|
+
case OP.MOD: {
|
|
24968
|
+
const b = stack[--sp];
|
|
24969
|
+
stack[sp - 1] = b !== 0 ? stack[sp - 1] % b : 0;
|
|
24970
|
+
break;
|
|
24971
|
+
}
|
|
24972
|
+
case OP.POW: {
|
|
24973
|
+
const b = stack[--sp];
|
|
24974
|
+
stack[sp - 1] **= b;
|
|
24975
|
+
break;
|
|
24976
|
+
}
|
|
24977
|
+
case OP.EQ: {
|
|
24978
|
+
const b = stack[--sp];
|
|
24979
|
+
stack[sp - 1] = stack[sp - 1] === b ? 1 : 0;
|
|
24980
|
+
break;
|
|
24981
|
+
}
|
|
24982
|
+
case OP.NE: {
|
|
24983
|
+
const b = stack[--sp];
|
|
24984
|
+
stack[sp - 1] = stack[sp - 1] !== b ? 1 : 0;
|
|
24985
|
+
break;
|
|
24986
|
+
}
|
|
24987
|
+
case OP.GT: {
|
|
24988
|
+
const b = stack[--sp];
|
|
24989
|
+
stack[sp - 1] = stack[sp - 1] > b ? 1 : 0;
|
|
24990
|
+
break;
|
|
24991
|
+
}
|
|
24992
|
+
case OP.GE: {
|
|
24993
|
+
const b = stack[--sp];
|
|
24994
|
+
stack[sp - 1] = stack[sp - 1] >= b ? 1 : 0;
|
|
24995
|
+
break;
|
|
24996
|
+
}
|
|
24997
|
+
case OP.LT: {
|
|
24998
|
+
const b = stack[--sp];
|
|
24999
|
+
stack[sp - 1] = stack[sp - 1] < b ? 1 : 0;
|
|
25000
|
+
break;
|
|
25001
|
+
}
|
|
25002
|
+
case OP.LE: {
|
|
25003
|
+
const b = stack[--sp];
|
|
25004
|
+
stack[sp - 1] = stack[sp - 1] <= b ? 1 : 0;
|
|
25005
|
+
break;
|
|
25006
|
+
}
|
|
25007
|
+
case OP.AND: {
|
|
25008
|
+
const b = stack[--sp] | 0;
|
|
25009
|
+
stack[sp - 1] = (stack[sp - 1] | 0) & b;
|
|
25010
|
+
break;
|
|
25011
|
+
}
|
|
25012
|
+
case OP.OR: {
|
|
25013
|
+
const b = stack[--sp] | 0;
|
|
25014
|
+
stack[sp - 1] = stack[sp - 1] | 0 | b;
|
|
25015
|
+
break;
|
|
25016
|
+
}
|
|
25017
|
+
case OP.XOR: {
|
|
25018
|
+
const b = stack[--sp] | 0;
|
|
25019
|
+
stack[sp - 1] = (stack[sp - 1] | 0) ^ b;
|
|
25020
|
+
break;
|
|
25021
|
+
}
|
|
25022
|
+
case OP.ATAN: {
|
|
25023
|
+
const b = stack[--sp];
|
|
25024
|
+
const deg = Math.atan2(stack[sp - 1], b) * _RAD_TO_DEG;
|
|
25025
|
+
stack[sp - 1] = deg < 0 ? deg + 360 : deg;
|
|
25026
|
+
break;
|
|
25027
|
+
}
|
|
25028
|
+
case OP.MIN: {
|
|
25029
|
+
const b = stack[--sp];
|
|
25030
|
+
stack[sp - 1] = Math.min(stack[sp - 1], b);
|
|
25031
|
+
break;
|
|
25032
|
+
}
|
|
25033
|
+
case OP.MAX: {
|
|
25034
|
+
const b = stack[--sp];
|
|
25035
|
+
stack[sp - 1] = Math.max(stack[sp - 1], b);
|
|
25036
|
+
break;
|
|
25037
|
+
}
|
|
25038
|
+
case OP.TEE_TMP:
|
|
25039
|
+
tmp[ir[ip++] | 0] = stack[sp - 1];
|
|
25040
|
+
break;
|
|
25041
|
+
case OP.LOAD_TMP:
|
|
25042
|
+
stack[sp++] = tmp[ir[ip++] | 0];
|
|
25043
|
+
break;
|
|
25044
|
+
}
|
|
25045
|
+
}
|
|
25046
|
+
}
|
|
25047
|
+
};
|
|
25048
|
+
var PSStackBasedInterpreter = class {
|
|
25049
|
+
// Safe: JS is single-threaded.
|
|
25050
|
+
static #stack = new Float64Array(100);
|
|
25051
|
+
static #sp = 0;
|
|
25052
|
+
static #push(v) {
|
|
25053
|
+
if (this.#sp < this.#stack.length) {
|
|
25054
|
+
this.#stack[this.#sp++] = v;
|
|
25055
|
+
}
|
|
25056
|
+
}
|
|
25057
|
+
static #execOp(op) {
|
|
25058
|
+
const stack = this.#stack;
|
|
25059
|
+
switch (op) {
|
|
25060
|
+
case TOKEN.true:
|
|
25061
|
+
this.#push(1);
|
|
25062
|
+
break;
|
|
25063
|
+
case TOKEN.false:
|
|
25064
|
+
this.#push(0);
|
|
25065
|
+
break;
|
|
25066
|
+
case TOKEN.abs:
|
|
25067
|
+
stack[this.#sp - 1] = Math.abs(stack[this.#sp - 1]);
|
|
25068
|
+
break;
|
|
25069
|
+
case TOKEN.neg:
|
|
25070
|
+
stack[this.#sp - 1] = -stack[this.#sp - 1];
|
|
25071
|
+
break;
|
|
25072
|
+
case TOKEN.ceiling:
|
|
25073
|
+
stack[this.#sp - 1] = Math.ceil(stack[this.#sp - 1]);
|
|
25074
|
+
break;
|
|
25075
|
+
case TOKEN.floor:
|
|
25076
|
+
stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1]);
|
|
25077
|
+
break;
|
|
25078
|
+
case TOKEN.round:
|
|
25079
|
+
stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1] + 0.5);
|
|
25080
|
+
break;
|
|
25081
|
+
case TOKEN.truncate:
|
|
25082
|
+
stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]);
|
|
25083
|
+
break;
|
|
25084
|
+
case TOKEN.sqrt:
|
|
25085
|
+
stack[this.#sp - 1] = Math.sqrt(stack[this.#sp - 1]);
|
|
25086
|
+
break;
|
|
25087
|
+
case TOKEN.sin:
|
|
25088
|
+
stack[this.#sp - 1] = Math.sin(
|
|
25089
|
+
stack[this.#sp - 1] % 360 * _DEG_TO_RAD
|
|
25090
|
+
);
|
|
25091
|
+
break;
|
|
25092
|
+
case TOKEN.cos:
|
|
25093
|
+
stack[this.#sp - 1] = Math.cos(
|
|
25094
|
+
stack[this.#sp - 1] % 360 * _DEG_TO_RAD
|
|
25095
|
+
);
|
|
25096
|
+
break;
|
|
25097
|
+
case TOKEN.ln:
|
|
25098
|
+
stack[this.#sp - 1] = Math.log(stack[this.#sp - 1]);
|
|
25099
|
+
break;
|
|
25100
|
+
case TOKEN.log:
|
|
25101
|
+
stack[this.#sp - 1] = Math.log10(stack[this.#sp - 1]);
|
|
25102
|
+
break;
|
|
25103
|
+
case TOKEN.cvi:
|
|
25104
|
+
stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]) | 0;
|
|
25105
|
+
break;
|
|
25106
|
+
case TOKEN.cvr:
|
|
25107
|
+
break;
|
|
25108
|
+
// values are already f64
|
|
25109
|
+
case TOKEN.not: {
|
|
25110
|
+
const v = stack[this.#sp - 1];
|
|
25111
|
+
stack[this.#sp - 1] = v === 0 || v === 1 ? 1 - v : ~(v | 0);
|
|
25112
|
+
break;
|
|
25113
|
+
}
|
|
25114
|
+
case TOKEN.add: {
|
|
25115
|
+
const b = stack[--this.#sp];
|
|
25116
|
+
stack[this.#sp - 1] += b;
|
|
25117
|
+
break;
|
|
25118
|
+
}
|
|
25119
|
+
case TOKEN.sub: {
|
|
25120
|
+
const b = stack[--this.#sp];
|
|
25121
|
+
stack[this.#sp - 1] -= b;
|
|
25122
|
+
break;
|
|
25123
|
+
}
|
|
25124
|
+
case TOKEN.mul: {
|
|
25125
|
+
const b = stack[--this.#sp];
|
|
25126
|
+
stack[this.#sp - 1] *= b;
|
|
25127
|
+
break;
|
|
25128
|
+
}
|
|
25129
|
+
case TOKEN.div: {
|
|
25130
|
+
const b = stack[--this.#sp];
|
|
25131
|
+
stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] / b : 0;
|
|
25132
|
+
break;
|
|
25133
|
+
}
|
|
25134
|
+
case TOKEN.idiv: {
|
|
25135
|
+
const b = stack[--this.#sp];
|
|
25136
|
+
stack[this.#sp - 1] = b !== 0 ? Math.trunc(stack[this.#sp - 1] / b) : 0;
|
|
25137
|
+
break;
|
|
25138
|
+
}
|
|
25139
|
+
case TOKEN.mod: {
|
|
25140
|
+
const b = stack[--this.#sp];
|
|
25141
|
+
stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] % b : 0;
|
|
25142
|
+
break;
|
|
25143
|
+
}
|
|
25144
|
+
case TOKEN.exp: {
|
|
25145
|
+
const b = stack[--this.#sp];
|
|
25146
|
+
stack[this.#sp - 1] **= b;
|
|
25147
|
+
break;
|
|
25148
|
+
}
|
|
25149
|
+
case TOKEN.atan: {
|
|
25150
|
+
const dx = stack[--this.#sp];
|
|
25151
|
+
const deg = Math.atan2(stack[this.#sp - 1], dx) * _RAD_TO_DEG;
|
|
25152
|
+
stack[this.#sp - 1] = deg < 0 ? deg + 360 : deg;
|
|
25153
|
+
break;
|
|
25154
|
+
}
|
|
25155
|
+
case TOKEN.eq: {
|
|
25156
|
+
const b = stack[--this.#sp];
|
|
25157
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] === b ? 1 : 0;
|
|
25158
|
+
break;
|
|
25159
|
+
}
|
|
25160
|
+
case TOKEN.ne: {
|
|
25161
|
+
const b = stack[--this.#sp];
|
|
25162
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] !== b ? 1 : 0;
|
|
25163
|
+
break;
|
|
25164
|
+
}
|
|
25165
|
+
case TOKEN.gt: {
|
|
25166
|
+
const b = stack[--this.#sp];
|
|
25167
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] > b ? 1 : 0;
|
|
25168
|
+
break;
|
|
25169
|
+
}
|
|
25170
|
+
case TOKEN.ge: {
|
|
25171
|
+
const b = stack[--this.#sp];
|
|
25172
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] >= b ? 1 : 0;
|
|
25173
|
+
break;
|
|
25174
|
+
}
|
|
25175
|
+
case TOKEN.lt: {
|
|
25176
|
+
const b = stack[--this.#sp];
|
|
25177
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] < b ? 1 : 0;
|
|
25178
|
+
break;
|
|
25179
|
+
}
|
|
25180
|
+
case TOKEN.le: {
|
|
25181
|
+
const b = stack[--this.#sp];
|
|
25182
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] <= b ? 1 : 0;
|
|
25183
|
+
break;
|
|
25184
|
+
}
|
|
25185
|
+
case TOKEN.and: {
|
|
25186
|
+
const b = stack[--this.#sp] | 0;
|
|
25187
|
+
stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) & b;
|
|
25188
|
+
break;
|
|
25189
|
+
}
|
|
25190
|
+
case TOKEN.or: {
|
|
25191
|
+
const b = stack[--this.#sp] | 0;
|
|
25192
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] | 0 | b;
|
|
25193
|
+
break;
|
|
25194
|
+
}
|
|
25195
|
+
case TOKEN.xor: {
|
|
25196
|
+
const b = stack[--this.#sp] | 0;
|
|
25197
|
+
stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) ^ b;
|
|
25198
|
+
break;
|
|
25199
|
+
}
|
|
25200
|
+
case TOKEN.bitshift: {
|
|
25201
|
+
const amt = stack[--this.#sp] | 0;
|
|
25202
|
+
const v = stack[this.#sp - 1] | 0;
|
|
25203
|
+
stack[this.#sp - 1] = amt > 0 ? v << amt : v >> -amt;
|
|
25204
|
+
break;
|
|
25205
|
+
}
|
|
25206
|
+
case TOKEN.min: {
|
|
25207
|
+
const b = stack[--this.#sp];
|
|
25208
|
+
stack[this.#sp - 1] = Math.min(stack[this.#sp - 1], b);
|
|
25209
|
+
break;
|
|
25210
|
+
}
|
|
25211
|
+
case TOKEN.max: {
|
|
25212
|
+
const b = stack[--this.#sp];
|
|
25213
|
+
stack[this.#sp - 1] = Math.max(stack[this.#sp - 1], b);
|
|
25214
|
+
break;
|
|
25215
|
+
}
|
|
25216
|
+
case TOKEN.dup:
|
|
25217
|
+
this.#push(stack[this.#sp - 1]);
|
|
25218
|
+
break;
|
|
25219
|
+
case TOKEN.exch: {
|
|
25220
|
+
const a = stack[--this.#sp];
|
|
25221
|
+
const b = stack[--this.#sp];
|
|
25222
|
+
this.#push(a);
|
|
25223
|
+
this.#push(b);
|
|
25224
|
+
break;
|
|
25225
|
+
}
|
|
25226
|
+
case TOKEN.pop:
|
|
25227
|
+
this.#sp--;
|
|
25228
|
+
break;
|
|
25229
|
+
case TOKEN.copy: {
|
|
25230
|
+
const n = Math.trunc(stack[--this.#sp]);
|
|
25231
|
+
const base = this.#sp - n;
|
|
25232
|
+
for (let k = 0; k < n; k++) {
|
|
25233
|
+
this.#push(stack[base + k]);
|
|
25234
|
+
}
|
|
25235
|
+
break;
|
|
25236
|
+
}
|
|
25237
|
+
case TOKEN.index: {
|
|
25238
|
+
const i = Math.trunc(stack[--this.#sp]);
|
|
25239
|
+
this.#push(stack[this.#sp - 1 - i]);
|
|
25240
|
+
break;
|
|
25241
|
+
}
|
|
25242
|
+
case TOKEN.roll: {
|
|
25243
|
+
const j = Math.trunc(stack[--this.#sp]);
|
|
25244
|
+
const n = Math.trunc(stack[--this.#sp]);
|
|
25245
|
+
if (n > 1 && j !== 0) {
|
|
25246
|
+
const mod = (j % n + n) % n;
|
|
25247
|
+
if (mod !== 0) {
|
|
25248
|
+
const base = this.#sp - n;
|
|
25249
|
+
const sub = stack.slice(base, this.#sp);
|
|
25250
|
+
for (let k = 0; k < n; k++) {
|
|
25251
|
+
stack[base + k] = sub[(k - mod + n) % n];
|
|
25252
|
+
}
|
|
25253
|
+
}
|
|
25254
|
+
}
|
|
25255
|
+
break;
|
|
25256
|
+
}
|
|
25257
|
+
}
|
|
25258
|
+
}
|
|
25259
|
+
static #execBlock(instructions) {
|
|
25260
|
+
for (const instr of instructions) {
|
|
25261
|
+
switch (instr.type) {
|
|
25262
|
+
case PS_NODE.number:
|
|
25263
|
+
this.#push(instr.value);
|
|
25264
|
+
break;
|
|
25265
|
+
case PS_NODE.operator:
|
|
25266
|
+
this.#execOp(instr.op);
|
|
25267
|
+
break;
|
|
25268
|
+
case PS_NODE.if:
|
|
25269
|
+
if (this.#stack[--this.#sp] !== 0) {
|
|
25270
|
+
this.#execBlock(instr.then.instructions);
|
|
25271
|
+
}
|
|
25272
|
+
break;
|
|
25273
|
+
case PS_NODE.ifelse:
|
|
25274
|
+
if (this.#stack[--this.#sp] !== 0) {
|
|
25275
|
+
this.#execBlock(instr.then.instructions);
|
|
25276
|
+
} else {
|
|
25277
|
+
this.#execBlock(instr.otherwise.instructions);
|
|
25278
|
+
}
|
|
25279
|
+
break;
|
|
25280
|
+
}
|
|
25281
|
+
}
|
|
25282
|
+
}
|
|
25283
|
+
/**
|
|
25284
|
+
* @param {import("./ast.js").PsProgram} program
|
|
25285
|
+
* @param {number[]} domain – flat [min0,max0, …]
|
|
25286
|
+
* @param {number[]} range – flat [min0,max0, …]
|
|
25287
|
+
* @returns {Function} – `(src, srcOffset, dest, destOffset) => void`
|
|
25288
|
+
*/
|
|
25289
|
+
static build(program, domain, range) {
|
|
25290
|
+
const nIn = domain.length >> 1;
|
|
25291
|
+
const nOut = range.length >> 1;
|
|
25292
|
+
const { instructions } = program.body;
|
|
25293
|
+
return (src, srcOffset, dest, destOffset) => {
|
|
25294
|
+
this.#sp = 0;
|
|
25295
|
+
for (let i = 0; i < nIn; i++) {
|
|
25296
|
+
this.#push(src[srcOffset + i]);
|
|
25297
|
+
}
|
|
25298
|
+
this.#execBlock(instructions);
|
|
25299
|
+
const base = this.#sp - nOut;
|
|
25300
|
+
for (let i = 0; i < nOut; i++) {
|
|
25301
|
+
const v = base + i >= 0 ? this.#stack[base + i] : 0;
|
|
25302
|
+
dest[destOffset + i] = MathClamp(v, range[i * 2], range[i * 2 + 1]);
|
|
25303
|
+
}
|
|
25304
|
+
};
|
|
25305
|
+
}
|
|
25306
|
+
};
|
|
25307
|
+
function buildPostScriptJsFunction(source, domain, range, forceInterpreter = false) {
|
|
25308
|
+
const program = parsePostScriptFunction(source);
|
|
25309
|
+
const ir = !forceInterpreter && new PsJsCompiler(domain, range).compile(program);
|
|
25310
|
+
if (ir) {
|
|
25311
|
+
return (src, srcOffset, dest, destOffset) => {
|
|
25312
|
+
PsJsCompiler.execute(ir, src, srcOffset, dest, destOffset);
|
|
25313
|
+
};
|
|
25314
|
+
}
|
|
25315
|
+
return PSStackBasedInterpreter.build(program, domain, range);
|
|
25316
|
+
}
|
|
22709
25317
|
var PdfError = class extends Error {
|
|
22710
25318
|
constructor(code, message) {
|
|
22711
25319
|
super(message);
|
|
@@ -33785,6 +36393,25 @@ var __webpack_exports__JpxImage = __webpack_exports__.JpxImage;
|
|
|
33785
36393
|
var __webpack_exports__VerbosityLevel = __webpack_exports__.VerbosityLevel;
|
|
33786
36394
|
var __webpack_exports__getVerbosityLevel = __webpack_exports__.getVerbosityLevel;
|
|
33787
36395
|
var __webpack_exports__setVerbosityLevel = __webpack_exports__.setVerbosityLevel;
|
|
36396
|
+
function createCalibratedColorSpace(doc, family, parameters) {
|
|
36397
|
+
const dict = doc.resolveDict(parameters);
|
|
36398
|
+
const array = (key) => {
|
|
36399
|
+
const value = dict ? doc.resolveArray(dictGet(dict, key)) : void 0;
|
|
36400
|
+
return value?.items.map((item) => {
|
|
36401
|
+
const number = doc.resolve(item);
|
|
36402
|
+
return number?.kind === "number" ? number.value : 0;
|
|
36403
|
+
});
|
|
36404
|
+
};
|
|
36405
|
+
const whitePoint = array("WhitePoint") ?? [0.95047, 1, 1.08883];
|
|
36406
|
+
const blackPoint = array("BlackPoint");
|
|
36407
|
+
if (family === "CalGray") {
|
|
36408
|
+
const gamma = dict ? doc.resolve(dictGet(dict, "Gamma")) : void 0;
|
|
36409
|
+
return new CalGrayCS(whitePoint, blackPoint, gamma?.kind === "number" ? gamma.value : void 0);
|
|
36410
|
+
}
|
|
36411
|
+
if (family === "CalRGB") return new CalRGBCS(whitePoint, blackPoint, array("Gamma"), array("Matrix"));
|
|
36412
|
+
return new LabCS(whitePoint, blackPoint, array("Range"));
|
|
36413
|
+
}
|
|
36414
|
+
var cmykColorSpace = new DeviceCmykCS();
|
|
33788
36415
|
function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
33789
36416
|
if (!csNode) return { colorSpace: "rgb", colorSpaceLabel: "rgb", components: 3 };
|
|
33790
36417
|
const resolved = doc.resolve(csNode);
|
|
@@ -33825,7 +36452,7 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
|
33825
36452
|
palette = lookupNode.bytes;
|
|
33826
36453
|
}
|
|
33827
36454
|
let resolvedBaseComp = baseInfo.components;
|
|
33828
|
-
if (palette && (baseInfo.
|
|
36455
|
+
if (palette && (baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calibrated !== void 0)) {
|
|
33829
36456
|
const numEntries = Math.max(1, Math.min(hival + 1, Math.floor(palette.length / Math.max(1, baseInfo.components))));
|
|
33830
36457
|
const rgbaPal = decodeSamplesToRgba(palette, numEntries, 1, 8, baseInfo);
|
|
33831
36458
|
const rgbPal = new Uint8Array(numEntries * 3);
|
|
@@ -33855,74 +36482,21 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
|
33855
36482
|
}
|
|
33856
36483
|
return { colorSpace: "rgb", colorSpaceLabel: "icc", components: 3 };
|
|
33857
36484
|
}
|
|
33858
|
-
if (kindName === "CalGray") {
|
|
33859
|
-
const
|
|
33860
|
-
const gammaNode = calDict ? doc.resolve(dictGet(calDict, "Gamma")) : void 0;
|
|
33861
|
-
const gamma = gammaNode?.kind === "number" && gammaNode.value > 0 ? gammaNode.value : 1;
|
|
33862
|
-
return { colorSpace: "gray", colorSpaceLabel: "cal-gray", components: 1, calGrayGamma: gamma };
|
|
33863
|
-
}
|
|
33864
|
-
if (kindName === "CalRGB") {
|
|
33865
|
-
const calDict = doc.resolveDict(resolved.items[1]);
|
|
33866
|
-
const gammaArr = calDict ? doc.resolveArray(dictGet(calDict, "Gamma")) : void 0;
|
|
33867
|
-
let calRgbGamma = [1, 1, 1];
|
|
33868
|
-
if (gammaArr && gammaArr.items.length >= 3) {
|
|
33869
|
-
const gNums = gammaArr.items.slice(0, 3).map((it) => {
|
|
33870
|
-
const r = doc.resolve(it);
|
|
33871
|
-
return r?.kind === "number" && r.value > 0 ? r.value : 1;
|
|
33872
|
-
});
|
|
33873
|
-
calRgbGamma = [gNums[0], gNums[1], gNums[2]];
|
|
33874
|
-
}
|
|
33875
|
-
const matArr = calDict ? doc.resolveArray(dictGet(calDict, "Matrix")) : void 0;
|
|
33876
|
-
let calRgbMatrix;
|
|
33877
|
-
if (matArr && matArr.items.length >= 9) {
|
|
33878
|
-
calRgbMatrix = matArr.items.slice(0, 9).map((it) => {
|
|
33879
|
-
const r = doc.resolve(it);
|
|
33880
|
-
return r?.kind === "number" ? r.value : 0;
|
|
33881
|
-
});
|
|
33882
|
-
}
|
|
36485
|
+
if (kindName === "CalGray" || kindName === "CalRGB" || kindName === "Lab") {
|
|
36486
|
+
const calibrated = createCalibratedColorSpace(doc, kindName, resolved.items[1]);
|
|
33883
36487
|
return {
|
|
33884
|
-
colorSpace: "rgb",
|
|
33885
|
-
colorSpaceLabel: "cal-rgb",
|
|
33886
|
-
components: 3,
|
|
33887
|
-
|
|
33888
|
-
calRgbMatrix
|
|
36488
|
+
colorSpace: kindName === "CalGray" ? "gray" : "rgb",
|
|
36489
|
+
colorSpaceLabel: kindName === "CalGray" ? "cal-gray" : kindName === "CalRGB" ? "cal-rgb" : "lab",
|
|
36490
|
+
components: kindName === "CalGray" ? 1 : 3,
|
|
36491
|
+
calibrated
|
|
33889
36492
|
};
|
|
33890
36493
|
}
|
|
33891
|
-
if (kindName === "Lab") {
|
|
33892
|
-
const labDict = doc.resolveDict(resolved.items[1]);
|
|
33893
|
-
const rangeArr = labDict ? doc.resolveArray(dictGet(labDict, "Range")) : void 0;
|
|
33894
|
-
let labRange = [-100, 100, -100, 100];
|
|
33895
|
-
if (rangeArr && rangeArr.items.length >= 4) {
|
|
33896
|
-
const nums = rangeArr.items.slice(0, 4).map((it) => {
|
|
33897
|
-
const r = doc.resolve(it);
|
|
33898
|
-
return r?.kind === "number" ? r.value : 0;
|
|
33899
|
-
});
|
|
33900
|
-
labRange = [nums[0], nums[1], nums[2], nums[3]];
|
|
33901
|
-
}
|
|
33902
|
-
return { colorSpace: "rgb", colorSpaceLabel: "lab", components: 3, isLab: true, labRange };
|
|
33903
|
-
}
|
|
33904
36494
|
if (kindName === "Separation" || kindName === "DeviceN") {
|
|
33905
36495
|
const isDevN = kindName === "DeviceN";
|
|
33906
36496
|
const namesArr = isDevN ? doc.resolveArray(resolved.items[1]) : void 0;
|
|
33907
36497
|
const devNComponents = isDevN && namesArr ? Math.max(1, namesArr.items.length) : 1;
|
|
33908
36498
|
const altInfo = resolveColorSpaceInfo(doc, resolved.items[2], resourcesDict);
|
|
33909
36499
|
const altSpace = altInfo.colorSpace === "cmyk" ? "cmyk" : altInfo.colorSpace === "gray" ? "gray" : "rgb";
|
|
33910
|
-
const fnResolved = doc.resolve(resolved.items[3]);
|
|
33911
|
-
const fnDict = fnResolved?.kind === "stream" ? fnResolved.dict : fnResolved?.kind === "dict" ? fnResolved : void 0;
|
|
33912
|
-
const ftNode = fnDict ? doc.resolve(dictGet(fnDict, "FunctionType")) : void 0;
|
|
33913
|
-
const tintFunctionType = ftNode?.kind === "number" ? ftNode.value : 2;
|
|
33914
|
-
const c0Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C0")) : void 0;
|
|
33915
|
-
const c1Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C1")) : void 0;
|
|
33916
|
-
const nNode = fnDict ? doc.resolve(dictGet(fnDict, "N")) : void 0;
|
|
33917
|
-
const c0 = c0Arr ? c0Arr.items.map((it) => {
|
|
33918
|
-
const r = doc.resolve(it);
|
|
33919
|
-
return r?.kind === "number" ? r.value : 0;
|
|
33920
|
-
}) : altSpace === "cmyk" ? [0, 0, 0, 0] : altSpace === "gray" ? [1] : [1, 1, 1];
|
|
33921
|
-
const c1 = c1Arr ? c1Arr.items.map((it) => {
|
|
33922
|
-
const r = doc.resolve(it);
|
|
33923
|
-
return r?.kind === "number" ? r.value : 0;
|
|
33924
|
-
}) : altSpace === "cmyk" ? [0, 0, 0, 1] : altSpace === "gray" ? [0] : [0, 0, 0];
|
|
33925
|
-
const sepN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
|
|
33926
36500
|
return {
|
|
33927
36501
|
colorSpace: altSpace,
|
|
33928
36502
|
colorSpaceLabel: isDevN ? "devn" : "sep",
|
|
@@ -33930,12 +36504,9 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
|
33930
36504
|
isSeparation: !isDevN,
|
|
33931
36505
|
isDeviceN: isDevN,
|
|
33932
36506
|
separationAltSpace: altSpace,
|
|
33933
|
-
|
|
33934
|
-
separationC1: c1,
|
|
33935
|
-
separationN: sepN,
|
|
36507
|
+
alternateCalibrated: altInfo.calibrated,
|
|
33936
36508
|
tintFunctionDoc: doc,
|
|
33937
|
-
tintFunctionNode: resolved.items[3]
|
|
33938
|
-
tintFunctionType
|
|
36509
|
+
tintFunctionNode: resolved.items[3]
|
|
33939
36510
|
};
|
|
33940
36511
|
}
|
|
33941
36512
|
}
|
|
@@ -34085,141 +36656,55 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
34085
36656
|
const rgba = new Uint8Array(width * height * 4);
|
|
34086
36657
|
const pixelCount = width * height;
|
|
34087
36658
|
if (csInfo.isSeparation || csInfo.isDeviceN) {
|
|
34088
|
-
const c0 = csInfo.separationC0 ?? [1, 1, 1];
|
|
34089
|
-
const c1 = csInfo.separationC1 ?? [0, 0, 0];
|
|
34090
|
-
const expN = csInfo.separationN ?? 1;
|
|
34091
36659
|
const alt = csInfo.separationAltSpace ?? "rgb";
|
|
34092
36660
|
const numCh = Math.max(1, csInfo.components);
|
|
34093
36661
|
const step = bpc === 16 ? 2 : 1;
|
|
34094
|
-
const useGenericTintFn = csInfo.tintFunctionDoc !== void 0 && csInfo.tintFunctionNode !== void 0 && (csInfo.tintFunctionType === 0 || csInfo.tintFunctionType === 3 || csInfo.tintFunctionType === 4);
|
|
34095
36662
|
for (let p = 0; p < pixelCount; p++) {
|
|
34096
36663
|
const chVals = [];
|
|
34097
|
-
let wSum = 0;
|
|
34098
36664
|
for (let ch3 = 0; ch3 < numCh; ch3++) {
|
|
34099
36665
|
const sRaw = (rawSamples[(p * numCh + ch3) * step] ?? 0) / 255;
|
|
34100
|
-
|
|
34101
|
-
chVals.push(tRemapped);
|
|
34102
|
-
wSum += Math.pow(Math.max(0, Math.min(1, tRemapped)), expN);
|
|
34103
|
-
}
|
|
34104
|
-
if (useGenericTintFn) {
|
|
34105
|
-
const outComps = evalShadingFunctionToComponents(
|
|
34106
|
-
csInfo.tintFunctionDoc,
|
|
34107
|
-
csInfo.tintFunctionNode,
|
|
34108
|
-
chVals
|
|
34109
|
-
);
|
|
34110
|
-
if (alt === "cmyk") {
|
|
34111
|
-
const c = outComps[0] ?? 0;
|
|
34112
|
-
const m = outComps[1] ?? 0;
|
|
34113
|
-
const y = outComps[2] ?? 0;
|
|
34114
|
-
const k = outComps[3] ?? 0;
|
|
34115
|
-
rgba[p * 4] = Math.round(Math.max(0, Math.min(1, (1 - c) * (1 - k))) * 255);
|
|
34116
|
-
rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, (1 - m) * (1 - k))) * 255);
|
|
34117
|
-
rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, (1 - y) * (1 - k))) * 255);
|
|
34118
|
-
} else if (alt === "gray") {
|
|
34119
|
-
const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
|
|
34120
|
-
rgba[p * 4] = gByte;
|
|
34121
|
-
rgba[p * 4 + 1] = gByte;
|
|
34122
|
-
rgba[p * 4 + 2] = gByte;
|
|
34123
|
-
} else {
|
|
34124
|
-
rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
|
|
34125
|
-
rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
|
|
34126
|
-
rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
|
|
34127
|
-
}
|
|
34128
|
-
rgba[p * 4 + 3] = 255;
|
|
34129
|
-
continue;
|
|
36666
|
+
chVals.push(remapUnitSampleWithDecode(sRaw, ch3, decodePairs));
|
|
34130
36667
|
}
|
|
34131
|
-
const
|
|
34132
|
-
|
|
34133
|
-
|
|
34134
|
-
|
|
34135
|
-
|
|
34136
|
-
|
|
34137
|
-
rgba
|
|
34138
|
-
|
|
34139
|
-
rgba[
|
|
36668
|
+
const outComps = evalShadingFunctionToComponents(
|
|
36669
|
+
csInfo.tintFunctionDoc,
|
|
36670
|
+
csInfo.tintFunctionNode,
|
|
36671
|
+
chVals
|
|
36672
|
+
);
|
|
36673
|
+
if (csInfo.alternateCalibrated) {
|
|
36674
|
+
rgba.set(csInfo.alternateCalibrated.getRgb(outComps, 0), p * 4);
|
|
36675
|
+
} else if (alt === "cmyk") {
|
|
36676
|
+
rgba.set(cmykColorSpace.getRgb([outComps[0] ?? 0, outComps[1] ?? 0, outComps[2] ?? 0, outComps[3] ?? 0], 0), p * 4);
|
|
34140
36677
|
} else if (alt === "gray") {
|
|
34141
|
-
const
|
|
34142
|
-
const gByte = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
|
|
36678
|
+
const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
|
|
34143
36679
|
rgba[p * 4] = gByte;
|
|
34144
36680
|
rgba[p * 4 + 1] = gByte;
|
|
34145
36681
|
rgba[p * 4 + 2] = gByte;
|
|
34146
36682
|
} else {
|
|
34147
|
-
|
|
34148
|
-
|
|
34149
|
-
|
|
34150
|
-
rgba[p * 4] = Math.round(Math.max(0, Math.min(1, rVal)) * 255);
|
|
34151
|
-
rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
|
|
34152
|
-
rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, bVal)) * 255);
|
|
36683
|
+
rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
|
|
36684
|
+
rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
|
|
36685
|
+
rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
|
|
34153
36686
|
}
|
|
34154
36687
|
rgba[p * 4 + 3] = 255;
|
|
34155
36688
|
}
|
|
34156
|
-
} else if (csInfo.
|
|
34157
|
-
const
|
|
34158
|
-
const
|
|
34159
|
-
const toSrgb = (u) => {
|
|
34160
|
-
const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
|
|
34161
|
-
return Math.round(Math.max(0, Math.min(1, c)) * 255);
|
|
34162
|
-
};
|
|
36689
|
+
} else if (csInfo.calibrated?.name === "Lab") {
|
|
36690
|
+
const { amin, amax, bmin, bmax } = csInfo.calibrated;
|
|
36691
|
+
const step = bpc === 16 ? 2 : 1;
|
|
34163
36692
|
for (let p = 0; p < pixelCount; p++) {
|
|
34164
|
-
const
|
|
34165
|
-
const
|
|
34166
|
-
const
|
|
34167
|
-
|
|
34168
|
-
if (L <= 0.01) {
|
|
34169
|
-
rgba[p * 4] = 0;
|
|
34170
|
-
rgba[p * 4 + 1] = 0;
|
|
34171
|
-
rgba[p * 4 + 2] = 0;
|
|
34172
|
-
rgba[p * 4 + 3] = 255;
|
|
34173
|
-
continue;
|
|
34174
|
-
}
|
|
34175
|
-
const a = amin + s1 * (amax - amin);
|
|
34176
|
-
const b = bmin + s2 * (bmax - bmin);
|
|
34177
|
-
const fy = (L + 16) / 116;
|
|
34178
|
-
const fx = fy + a / 500;
|
|
34179
|
-
const fz = fy - b / 200;
|
|
34180
|
-
const X = 0.95047 * invF(fx);
|
|
34181
|
-
const Y = 1 * invF(fy);
|
|
34182
|
-
const Z = 1.08883 * invF(fz);
|
|
34183
|
-
const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
|
|
34184
|
-
const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
|
|
34185
|
-
const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
|
|
34186
|
-
rgba[p * 4] = toSrgb(linR);
|
|
34187
|
-
rgba[p * 4 + 1] = toSrgb(linG);
|
|
34188
|
-
rgba[p * 4 + 2] = toSrgb(linB);
|
|
36693
|
+
const L = (rawSamples[p * 3 * step] ?? 0) / 255 * 100;
|
|
36694
|
+
const a = amin + (rawSamples[(p * 3 + 1) * step] ?? 128) / 255 * (amax - amin);
|
|
36695
|
+
const b = bmin + (rawSamples[(p * 3 + 2) * step] ?? 128) / 255 * (bmax - bmin);
|
|
36696
|
+
rgba.set(csInfo.calibrated.getRgb([L, a, b], 0), p * 4);
|
|
34189
36697
|
rgba[p * 4 + 3] = 255;
|
|
34190
36698
|
}
|
|
34191
36699
|
} else if (csInfo.colorSpace === "rgb") {
|
|
34192
|
-
const hasCalRgb = Boolean(csInfo.calRgbGamma || csInfo.calRgbMatrix);
|
|
34193
|
-
const toSrgbByte = (u) => {
|
|
34194
|
-
const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
|
|
34195
|
-
return Math.round(Math.max(0, Math.min(1, c)) * 255);
|
|
34196
|
-
};
|
|
34197
36700
|
const writeRgbPixel = (p, rByte, gByte, bByte) => {
|
|
34198
|
-
|
|
34199
|
-
|
|
34200
|
-
|
|
34201
|
-
if (
|
|
34202
|
-
|
|
34203
|
-
|
|
34204
|
-
|
|
34205
|
-
const cg = Math.pow(bU, gb);
|
|
34206
|
-
if (csInfo.calRgbMatrix && csInfo.calRgbMatrix.length >= 9) {
|
|
34207
|
-
const m = csInfo.calRgbMatrix;
|
|
34208
|
-
const X = m[0] * ag + m[3] * bg + m[6] * cg;
|
|
34209
|
-
const Y = m[1] * ag + m[4] * bg + m[7] * cg;
|
|
34210
|
-
const Z = m[2] * ag + m[5] * bg + m[8] * cg;
|
|
34211
|
-
const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
|
|
34212
|
-
const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
|
|
34213
|
-
const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
|
|
34214
|
-
rgba[p * 4] = toSrgbByte(linR);
|
|
34215
|
-
rgba[p * 4 + 1] = toSrgbByte(linG);
|
|
34216
|
-
rgba[p * 4 + 2] = toSrgbByte(linB);
|
|
34217
|
-
rgba[p * 4 + 3] = 255;
|
|
34218
|
-
return;
|
|
34219
|
-
}
|
|
34220
|
-
rU = ag;
|
|
34221
|
-
gU = bg;
|
|
34222
|
-
bU = cg;
|
|
36701
|
+
const rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
|
|
36702
|
+
const gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
|
|
36703
|
+
const bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
|
|
36704
|
+
if (csInfo.calibrated) {
|
|
36705
|
+
rgba.set(csInfo.calibrated.getRgb([rU, gU, bU], 0), p * 4);
|
|
36706
|
+
rgba[p * 4 + 3] = 255;
|
|
36707
|
+
return;
|
|
34223
36708
|
}
|
|
34224
36709
|
rgba[p * 4] = Math.round(rU * 255);
|
|
34225
36710
|
rgba[p * 4 + 1] = Math.round(gU * 255);
|
|
@@ -34239,10 +36724,11 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
34239
36724
|
}
|
|
34240
36725
|
} else if (csInfo.colorSpace === "gray") {
|
|
34241
36726
|
const writeGrayPixel = (p, gByte) => {
|
|
34242
|
-
|
|
34243
|
-
if (csInfo.
|
|
34244
|
-
|
|
34245
|
-
|
|
36727
|
+
const gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
|
|
36728
|
+
if (csInfo.calibrated) {
|
|
36729
|
+
rgba.set(csInfo.calibrated.getRgb([gU], 0), p * 4);
|
|
36730
|
+
rgba[p * 4 + 3] = 255;
|
|
36731
|
+
return;
|
|
34246
36732
|
}
|
|
34247
36733
|
const outG = Math.round(Math.max(0, Math.min(1, gU)) * 255);
|
|
34248
36734
|
rgba[p * 4] = outG;
|
|
@@ -34298,9 +36784,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
34298
36784
|
const m = remapUnitSampleWithDecode((rawSamples[p * stride + chStep] ?? 0) / 255, 1, decodePairs);
|
|
34299
36785
|
const y = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 2] ?? 0) / 255, 2, decodePairs);
|
|
34300
36786
|
const k = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 3] ?? 0) / 255, 3, decodePairs);
|
|
34301
|
-
rgba
|
|
34302
|
-
rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
|
|
34303
|
-
rgba[p * 4 + 2] = Math.round((1 - y) * (1 - k) * 255);
|
|
36787
|
+
rgba.set(cmykColorSpace.getRgb([c, m, y, k], 0), p * 4);
|
|
34304
36788
|
rgba[p * 4 + 3] = 255;
|
|
34305
36789
|
}
|
|
34306
36790
|
} else if (csInfo.colorSpace === "index") {
|
|
@@ -34338,9 +36822,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
34338
36822
|
const m = pal[idx * 4 + 1] / 255;
|
|
34339
36823
|
const yel = pal[idx * 4 + 2] / 255;
|
|
34340
36824
|
const k = pal[idx * 4 + 3] / 255;
|
|
34341
|
-
rgba
|
|
34342
|
-
rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
|
|
34343
|
-
rgba[p * 4 + 2] = Math.round((1 - yel) * (1 - k) * 255);
|
|
36825
|
+
rgba.set(cmykColorSpace.getRgb([c, m, yel, k], 0), p * 4);
|
|
34344
36826
|
} else {
|
|
34345
36827
|
rgba[p * 4] = pal[idx * baseComp];
|
|
34346
36828
|
rgba[p * 4 + 1] = pal[idx * baseComp + 1];
|
|
@@ -34595,6 +37077,7 @@ function decodeInlineImageNodeToRgba(doc, dict, rawData, activeRes, fillColor) {
|
|
|
34595
37077
|
});
|
|
34596
37078
|
return decodeXObjectImageToRgba(context, { kind: "stream", dict, rawBytes: rawData }, activeRes, fillColor);
|
|
34597
37079
|
}
|
|
37080
|
+
var cmykColorSpace2 = new DeviceCmykCS();
|
|
34598
37081
|
function multiplyMatrices(m1, m2) {
|
|
34599
37082
|
return [
|
|
34600
37083
|
m1[0] * m2[0] + m1[1] * m2[2],
|
|
@@ -34811,193 +37294,7 @@ function resolvePageFonts(doc, resourcesDict) {
|
|
|
34811
37294
|
}
|
|
34812
37295
|
return fonts;
|
|
34813
37296
|
}
|
|
34814
|
-
|
|
34815
|
-
const stack = [...initialStack];
|
|
34816
|
-
const runRange = (start, end) => {
|
|
34817
|
-
let i = start;
|
|
34818
|
-
while (i < end) {
|
|
34819
|
-
const tok = tokens[i];
|
|
34820
|
-
if (tok === "{") {
|
|
34821
|
-
let depth = 1;
|
|
34822
|
-
let j = i + 1;
|
|
34823
|
-
while (j < end && depth > 0) {
|
|
34824
|
-
if (tokens[j] === "{") depth++;
|
|
34825
|
-
else if (tokens[j] === "}") depth--;
|
|
34826
|
-
j++;
|
|
34827
|
-
}
|
|
34828
|
-
const blockStart = i + 1;
|
|
34829
|
-
const blockEnd = j - 1;
|
|
34830
|
-
if (j < end && tokens[j] === "{") {
|
|
34831
|
-
let depth2 = 1;
|
|
34832
|
-
let k = j + 1;
|
|
34833
|
-
while (k < end && depth2 > 0) {
|
|
34834
|
-
if (tokens[k] === "{") depth2++;
|
|
34835
|
-
else if (tokens[k] === "}") depth2--;
|
|
34836
|
-
k++;
|
|
34837
|
-
}
|
|
34838
|
-
if (k < end && tokens[k] === "ifelse") {
|
|
34839
|
-
const cond = stack.pop() ?? 0;
|
|
34840
|
-
if (cond !== 0) runRange(blockStart, blockEnd);
|
|
34841
|
-
else runRange(j + 1, k - 1);
|
|
34842
|
-
i = k + 1;
|
|
34843
|
-
continue;
|
|
34844
|
-
}
|
|
34845
|
-
}
|
|
34846
|
-
if (j < end && tokens[j] === "if") {
|
|
34847
|
-
const cond = stack.pop() ?? 0;
|
|
34848
|
-
if (cond !== 0) runRange(blockStart, blockEnd);
|
|
34849
|
-
i = j + 1;
|
|
34850
|
-
continue;
|
|
34851
|
-
}
|
|
34852
|
-
runRange(blockStart, blockEnd);
|
|
34853
|
-
i = j;
|
|
34854
|
-
continue;
|
|
34855
|
-
}
|
|
34856
|
-
if (tok === "}") {
|
|
34857
|
-
i++;
|
|
34858
|
-
continue;
|
|
34859
|
-
}
|
|
34860
|
-
const numVal2 = Number(tok);
|
|
34861
|
-
if (tok.length > 0 && !Number.isNaN(numVal2)) {
|
|
34862
|
-
stack.push(numVal2);
|
|
34863
|
-
} else if (tok === "true") {
|
|
34864
|
-
stack.push(1);
|
|
34865
|
-
} else if (tok === "false") {
|
|
34866
|
-
stack.push(0);
|
|
34867
|
-
} else if (tok === "add") {
|
|
34868
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34869
|
-
stack.push(a + b);
|
|
34870
|
-
} else if (tok === "sub") {
|
|
34871
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34872
|
-
stack.push(a - b);
|
|
34873
|
-
} else if (tok === "mul") {
|
|
34874
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34875
|
-
stack.push(a * b);
|
|
34876
|
-
} else if (tok === "div") {
|
|
34877
|
-
const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
|
|
34878
|
-
stack.push(Math.abs(b) > 1e-12 ? a / b : 0);
|
|
34879
|
-
} else if (tok === "idiv") {
|
|
34880
|
-
const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
|
|
34881
|
-
stack.push(Math.abs(b) > 1e-12 ? Math.trunc(a / b) : 0);
|
|
34882
|
-
} else if (tok === "mod") {
|
|
34883
|
-
const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
|
|
34884
|
-
stack.push(Math.abs(b) > 1e-12 ? a % b : 0);
|
|
34885
|
-
} else if (tok === "neg") {
|
|
34886
|
-
stack.push(-(stack.pop() ?? 0));
|
|
34887
|
-
} else if (tok === "abs") {
|
|
34888
|
-
stack.push(Math.abs(stack.pop() ?? 0));
|
|
34889
|
-
} else if (tok === "ceiling") {
|
|
34890
|
-
stack.push(Math.ceil(stack.pop() ?? 0));
|
|
34891
|
-
} else if (tok === "floor") {
|
|
34892
|
-
stack.push(Math.floor(stack.pop() ?? 0));
|
|
34893
|
-
} else if (tok === "round") {
|
|
34894
|
-
stack.push(Math.round(stack.pop() ?? 0));
|
|
34895
|
-
} else if (tok === "truncate" || tok === "cvi") {
|
|
34896
|
-
stack.push(Math.trunc(stack.pop() ?? 0));
|
|
34897
|
-
} else if (tok === "sqrt") {
|
|
34898
|
-
stack.push(Math.sqrt(Math.max(0, stack.pop() ?? 0)));
|
|
34899
|
-
} else if (tok === "sin") {
|
|
34900
|
-
stack.push(Math.sin((stack.pop() ?? 0) * Math.PI / 180));
|
|
34901
|
-
} else if (tok === "cos") {
|
|
34902
|
-
stack.push(Math.cos((stack.pop() ?? 0) * Math.PI / 180));
|
|
34903
|
-
} else if (tok === "atan") {
|
|
34904
|
-
const dx = stack.pop() ?? 1, dy = stack.pop() ?? 0;
|
|
34905
|
-
let deg = Math.atan2(dy, dx) * 180 / Math.PI;
|
|
34906
|
-
if (deg < 0) deg += 360;
|
|
34907
|
-
stack.push(deg);
|
|
34908
|
-
} else if (tok === "exp") {
|
|
34909
|
-
const exp = stack.pop() ?? 1, base = stack.pop() ?? 0;
|
|
34910
|
-
stack.push(Math.pow(base, exp));
|
|
34911
|
-
} else if (tok === "ln") {
|
|
34912
|
-
stack.push(Math.log(Math.max(1e-12, stack.pop() ?? 1)));
|
|
34913
|
-
} else if (tok === "log") {
|
|
34914
|
-
stack.push(Math.log10(Math.max(1e-12, stack.pop() ?? 1)));
|
|
34915
|
-
} else if (tok === "dup") {
|
|
34916
|
-
if (stack.length > 0) stack.push(stack[stack.length - 1]);
|
|
34917
|
-
} else if (tok === "exch") {
|
|
34918
|
-
if (stack.length >= 2) {
|
|
34919
|
-
const b = stack.pop(), a = stack.pop();
|
|
34920
|
-
stack.push(b, a);
|
|
34921
|
-
}
|
|
34922
|
-
} else if (tok === "pop") {
|
|
34923
|
-
stack.pop();
|
|
34924
|
-
} else if (tok === "copy") {
|
|
34925
|
-
const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
|
|
34926
|
-
const slice = stack.slice(Math.max(0, stack.length - n));
|
|
34927
|
-
stack.push(...slice);
|
|
34928
|
-
} else if (tok === "index") {
|
|
34929
|
-
const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
|
|
34930
|
-
const idx = stack.length - 1 - n;
|
|
34931
|
-
if (idx >= 0 && idx < stack.length) stack.push(stack[idx]);
|
|
34932
|
-
} else if (tok === "roll") {
|
|
34933
|
-
const jShift = Math.trunc(stack.pop() ?? 0);
|
|
34934
|
-
const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
|
|
34935
|
-
if (n > 0 && stack.length >= n) {
|
|
34936
|
-
const sub = stack.splice(stack.length - n, n);
|
|
34937
|
-
const modShift = (jShift % n + n) % n;
|
|
34938
|
-
const rolled = [...sub.slice(n - modShift), ...sub.slice(0, n - modShift)];
|
|
34939
|
-
stack.push(...rolled);
|
|
34940
|
-
}
|
|
34941
|
-
} else if (tok === "eq") {
|
|
34942
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34943
|
-
stack.push(Math.abs(a - b) < 1e-9 ? 1 : 0);
|
|
34944
|
-
} else if (tok === "ne") {
|
|
34945
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34946
|
-
stack.push(Math.abs(a - b) >= 1e-9 ? 1 : 0);
|
|
34947
|
-
} else if (tok === "gt") {
|
|
34948
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34949
|
-
stack.push(a > b ? 1 : 0);
|
|
34950
|
-
} else if (tok === "ge") {
|
|
34951
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34952
|
-
stack.push(a >= b ? 1 : 0);
|
|
34953
|
-
} else if (tok === "lt") {
|
|
34954
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34955
|
-
stack.push(a < b ? 1 : 0);
|
|
34956
|
-
} else if (tok === "le") {
|
|
34957
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34958
|
-
stack.push(a <= b ? 1 : 0);
|
|
34959
|
-
} else if (tok === "and") {
|
|
34960
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34961
|
-
stack.push(a !== 0 && b !== 0 ? 1 : 0);
|
|
34962
|
-
} else if (tok === "or") {
|
|
34963
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34964
|
-
stack.push(a !== 0 || b !== 0 ? 1 : 0);
|
|
34965
|
-
} else if (tok === "not") {
|
|
34966
|
-
const a = stack.pop() ?? 0;
|
|
34967
|
-
stack.push(a === 0 ? 1 : 0);
|
|
34968
|
-
}
|
|
34969
|
-
i++;
|
|
34970
|
-
}
|
|
34971
|
-
};
|
|
34972
|
-
runRange(0, tokens.length);
|
|
34973
|
-
return stack;
|
|
34974
|
-
}
|
|
34975
|
-
function tokenizePostScriptCode(bytes) {
|
|
34976
|
-
const tokens = [];
|
|
34977
|
-
let cur = "";
|
|
34978
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
34979
|
-
const ch3 = String.fromCharCode(bytes[i]);
|
|
34980
|
-
if (ch3 === "{" || ch3 === "}") {
|
|
34981
|
-
if (cur.length > 0) {
|
|
34982
|
-
tokens.push(cur);
|
|
34983
|
-
cur = "";
|
|
34984
|
-
}
|
|
34985
|
-
tokens.push(ch3);
|
|
34986
|
-
} else if (ch3 === " " || ch3 === " " || ch3 === "\n" || ch3 === "\r") {
|
|
34987
|
-
if (cur.length > 0) {
|
|
34988
|
-
tokens.push(cur);
|
|
34989
|
-
cur = "";
|
|
34990
|
-
}
|
|
34991
|
-
} else {
|
|
34992
|
-
cur += ch3;
|
|
34993
|
-
}
|
|
34994
|
-
}
|
|
34995
|
-
if (cur.length > 0) tokens.push(cur);
|
|
34996
|
-
if (tokens[0] === "{" && tokens[tokens.length - 1] === "}") {
|
|
34997
|
-
return tokens.slice(1, -1);
|
|
34998
|
-
}
|
|
34999
|
-
return tokens;
|
|
35000
|
-
}
|
|
37297
|
+
var postScriptFunctions = /* @__PURE__ */ new WeakMap();
|
|
35001
37298
|
function evalShadingFunctionToComponents(doc, fnNode, inputs) {
|
|
35002
37299
|
const inArr = typeof inputs === "number" ? [inputs] : inputs;
|
|
35003
37300
|
const t = inArr[0] ?? 0;
|
|
@@ -35044,35 +37341,50 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
|
|
|
35044
37341
|
const decode = getNums("Decode", range);
|
|
35045
37342
|
const nOut = Math.max(1, Math.floor((decode.length || range.length || 6) / 2));
|
|
35046
37343
|
const mIn = Math.max(1, size.length);
|
|
35047
|
-
|
|
37344
|
+
const streamBytes = doc.decodeStream(resolved);
|
|
37345
|
+
let vertices = [{ index: 0, weight: 1 }];
|
|
35048
37346
|
let stride = 1;
|
|
35049
37347
|
for (let i = 0; i < mIn; i++) {
|
|
35050
37348
|
const d02 = dom[i * 2] ?? 0;
|
|
35051
37349
|
const d12 = dom[i * 2 + 1] ?? 1;
|
|
35052
|
-
const sMax = Math.max(
|
|
37350
|
+
const sMax = Math.max(0, (size[i] ?? 2) - 1);
|
|
35053
37351
|
const e0 = encode[i * 2] ?? 0;
|
|
35054
37352
|
const e1 = encode[i * 2 + 1] ?? sMax;
|
|
35055
37353
|
const x = Math.max(d02, Math.min(d12, inArr[i] ?? 0));
|
|
35056
|
-
const u =
|
|
35057
|
-
const
|
|
35058
|
-
|
|
37354
|
+
const u = d12 === d02 ? 0 : (x - d02) / (d12 - d02);
|
|
37355
|
+
const e = Math.max(0, Math.min(sMax, e0 + u * (e1 - e0)));
|
|
37356
|
+
const low = Math.floor(e), fraction = e - low;
|
|
37357
|
+
const next = [];
|
|
37358
|
+
for (const vertex of vertices) {
|
|
37359
|
+
const index = vertex.index + low * stride;
|
|
37360
|
+
if (index * nOut * bps < streamBytes.length * 8) next.push({ index, weight: vertex.weight * (1 - fraction) });
|
|
37361
|
+
if (fraction && (index + stride) * nOut * bps < streamBytes.length * 8) {
|
|
37362
|
+
next.push({ index: index + stride, weight: vertex.weight * fraction });
|
|
37363
|
+
}
|
|
37364
|
+
}
|
|
37365
|
+
vertices = next;
|
|
35059
37366
|
stride *= size[i] ?? 2;
|
|
35060
37367
|
}
|
|
35061
|
-
const
|
|
37368
|
+
const maxSample = 2 ** bps - 1;
|
|
37369
|
+
const readSample = (index) => {
|
|
37370
|
+
let bitOffset = index * bps, remaining = bps, value = 0;
|
|
37371
|
+
while (remaining > 0) {
|
|
37372
|
+
const bitInByte = bitOffset % 8;
|
|
37373
|
+
const take = Math.min(remaining, 8 - bitInByte);
|
|
37374
|
+
const byte = streamBytes[Math.floor(bitOffset / 8)] ?? 0;
|
|
37375
|
+
value = value * 2 ** take + (byte >> 8 - bitInByte - take & (1 << take) - 1);
|
|
37376
|
+
bitOffset += take;
|
|
37377
|
+
remaining -= take;
|
|
37378
|
+
}
|
|
37379
|
+
return value / maxSample;
|
|
37380
|
+
};
|
|
35062
37381
|
const out2 = [];
|
|
35063
|
-
const maxSample = bps === 16 ? 65535 : 255;
|
|
35064
37382
|
for (let j = 0; j < nOut; j++) {
|
|
35065
|
-
|
|
35066
|
-
|
|
35067
|
-
if (bps === 16) {
|
|
35068
|
-
rawVal = (streamBytes[sampleIdx * 2] ?? 0) << 8 | (streamBytes[sampleIdx * 2 + 1] ?? 0);
|
|
35069
|
-
} else {
|
|
35070
|
-
rawVal = streamBytes[sampleIdx] ?? 0;
|
|
35071
|
-
}
|
|
35072
|
-
const frac = rawVal / maxSample;
|
|
37383
|
+
let value = 0;
|
|
37384
|
+
for (const vertex of vertices) value += readSample(vertex.index * nOut + j) * vertex.weight;
|
|
35073
37385
|
const dec0 = decode[j * 2] ?? 0;
|
|
35074
37386
|
const dec1 = decode[j * 2 + 1] ?? 1;
|
|
35075
|
-
out2.push(dec0 +
|
|
37387
|
+
out2.push(dec0 + value * (dec1 - dec0));
|
|
35076
37388
|
}
|
|
35077
37389
|
return clampRange(out2);
|
|
35078
37390
|
}
|
|
@@ -35082,34 +37394,40 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
|
|
|
35082
37394
|
const d12 = dom[i * 2 + 1] ?? 1;
|
|
35083
37395
|
return Math.max(d02, Math.min(d12, v));
|
|
35084
37396
|
});
|
|
35085
|
-
const
|
|
35086
|
-
|
|
35087
|
-
|
|
37397
|
+
const source = bytesToString3(doc.decodeStream(resolved));
|
|
37398
|
+
let cached = postScriptFunctions.get(resolved);
|
|
37399
|
+
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])) {
|
|
37400
|
+
cached = { source, domain: dom, range, evaluate: buildPostScriptJsFunction(source, dom, range) };
|
|
37401
|
+
postScriptFunctions.set(resolved, cached);
|
|
37402
|
+
}
|
|
37403
|
+
const output = [];
|
|
37404
|
+
cached.evaluate(clampedInputs, 0, output, 0);
|
|
37405
|
+
return output;
|
|
35088
37406
|
}
|
|
35089
37407
|
if (ft === 3) {
|
|
35090
37408
|
const fnsArr = doc.resolveArray(dictGet(fnDict, "Functions"));
|
|
35091
37409
|
const bounds = getNums("Bounds", []);
|
|
35092
37410
|
const encode = getNums("Encode", []);
|
|
35093
37411
|
if (fnsArr && fnsArr.items.length > 0) {
|
|
37412
|
+
const input = Math.max(dom[0] ?? 0, Math.min(dom[1] ?? 1, t));
|
|
35094
37413
|
let segIdx = 0;
|
|
35095
|
-
while (segIdx < bounds.length &&
|
|
37414
|
+
while (segIdx < bounds.length && input >= bounds[segIdx]) segIdx++;
|
|
35096
37415
|
segIdx = Math.min(fnsArr.items.length - 1, segIdx);
|
|
35097
37416
|
const b0 = segIdx === 0 ? dom[0] ?? 0 : bounds[segIdx - 1];
|
|
35098
37417
|
const b1 = segIdx < bounds.length ? bounds[segIdx] : dom[1] ?? 1;
|
|
35099
37418
|
const e0 = encode[segIdx * 2] ?? 0;
|
|
35100
37419
|
const e1 = encode[segIdx * 2 + 1] ?? 1;
|
|
35101
|
-
const localT =
|
|
35102
|
-
return evalShadingFunctionToComponents(doc, fnsArr.items[segIdx],
|
|
37420
|
+
const localT = b1 !== b0 ? e0 + (input - b0) / (b1 - b0) * (e1 - e0) : e0;
|
|
37421
|
+
return clampRange(evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], localT));
|
|
35103
37422
|
}
|
|
35104
37423
|
}
|
|
35105
|
-
const c0 = getNums("C0", [0
|
|
35106
|
-
const c1 = getNums("C1", [1
|
|
37424
|
+
const c0 = getNums("C0", [0]);
|
|
37425
|
+
const c1 = getNums("C1", [1]);
|
|
35107
37426
|
const nNode = doc.resolve(dictGet(fnDict, "N"));
|
|
35108
|
-
const expN = nNode?.kind === "number"
|
|
37427
|
+
const expN = nNode?.kind === "number" ? nNode.value : 1;
|
|
35109
37428
|
const d0 = dom[0] ?? 0;
|
|
35110
37429
|
const d1 = dom[1] ?? 1;
|
|
35111
|
-
const
|
|
35112
|
-
const w = Math.pow(Math.max(0, Math.min(1, normT)), expN);
|
|
37430
|
+
const w = Math.pow(Math.max(d0, Math.min(d1, t)), expN);
|
|
35113
37431
|
const len = Math.max(c0.length, c1.length);
|
|
35114
37432
|
const out = [];
|
|
35115
37433
|
for (let i = 0; i < len; i++) {
|
|
@@ -35125,30 +37443,14 @@ function shadingComponentsToRgb(csName, comps) {
|
|
|
35125
37443
|
return [v, v, v];
|
|
35126
37444
|
}
|
|
35127
37445
|
if (csName === "DeviceCMYK" || csName === "CMYK" || comps.length >= 4) {
|
|
35128
|
-
const
|
|
35129
|
-
return [
|
|
37446
|
+
const rgb2 = cmykColorSpace2.getRgb([comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0, comps[3] ?? 0], 0);
|
|
37447
|
+
return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
|
|
35130
37448
|
}
|
|
35131
37449
|
return [comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0];
|
|
35132
37450
|
}
|
|
35133
37451
|
function kClamp(v) {
|
|
35134
37452
|
return Math.max(0, Math.min(1, v));
|
|
35135
37453
|
}
|
|
35136
|
-
function xyzToSrgb(X, Y, Z, Xw = 0.95047, Yw = 1, Zw = 1.08883) {
|
|
35137
|
-
const scaleX = Xw > 1e-6 ? 0.95047 / Xw : 1;
|
|
35138
|
-
const scaleY = Yw > 1e-6 ? 1 / Yw : 1;
|
|
35139
|
-
const scaleZ = Zw > 1e-6 ? 1.08883 / Zw : 1;
|
|
35140
|
-
const x = X * scaleX;
|
|
35141
|
-
const y = Y * scaleY;
|
|
35142
|
-
const z = Z * scaleZ;
|
|
35143
|
-
const rl = 3.2404542 * x - 1.5371385 * y - 0.4985314 * z;
|
|
35144
|
-
const gl = -0.969266 * x + 1.8760108 * y + 0.041556 * z;
|
|
35145
|
-
const bl = 0.0556434 * x - 0.2040259 * y + 1.0572252 * z;
|
|
35146
|
-
const toGamma = (u) => {
|
|
35147
|
-
const c = Math.max(0, Math.min(1, u));
|
|
35148
|
-
return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
|
|
35149
|
-
};
|
|
35150
|
-
return [toGamma(rl), toGamma(gl), toGamma(bl)];
|
|
35151
|
-
}
|
|
35152
37454
|
function getColorSpaceComponentCount(doc, csNode, activeResources, depth = 0) {
|
|
35153
37455
|
if (!csNode || depth > 4) return 3;
|
|
35154
37456
|
const resolved = doc ? doc.resolve(csNode) : csNode;
|
|
@@ -35205,63 +37507,10 @@ function convertColorSpaceComponentsToRgb(doc, csNode, csNameFallback, comps, ac
|
|
|
35205
37507
|
if (resolved.kind === "array" && resolved.items.length > 0 && doc) {
|
|
35206
37508
|
const familyNode = doc.resolve(resolved.items[0]);
|
|
35207
37509
|
const family = familyNode?.kind === "name" ? familyNode.decoded : "";
|
|
35208
|
-
if (family === "CalGray") {
|
|
35209
|
-
const
|
|
35210
|
-
const
|
|
35211
|
-
|
|
35212
|
-
const a = Math.pow(kClamp(comps[0] ?? 0), gamma);
|
|
35213
|
-
return [a, a, a];
|
|
35214
|
-
}
|
|
35215
|
-
if (family === "CalRGB") {
|
|
35216
|
-
const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
|
|
35217
|
-
const gammaArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Gamma")) : void 0;
|
|
35218
|
-
const getArrNum = (arr, idx, fb) => {
|
|
35219
|
-
const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
|
|
35220
|
-
return r?.kind === "number" ? r.value : fb;
|
|
35221
|
-
};
|
|
35222
|
-
const gr = getArrNum(gammaArr, 0, 1);
|
|
35223
|
-
const gg = getArrNum(gammaArr, 1, 1);
|
|
35224
|
-
const gb = getArrNum(gammaArr, 2, 1);
|
|
35225
|
-
const ag = Math.pow(kClamp(comps[0] ?? 0), gr > 0 ? gr : 1);
|
|
35226
|
-
const bg = Math.pow(kClamp(comps[1] ?? 0), gg > 0 ? gg : 1);
|
|
35227
|
-
const cg = Math.pow(kClamp(comps[2] ?? 0), gb > 0 ? gb : 1);
|
|
35228
|
-
const matArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Matrix")) : void 0;
|
|
35229
|
-
if (matArr && matArr.items.length >= 9) {
|
|
35230
|
-
const m = (i) => getArrNum(matArr, i, 0);
|
|
35231
|
-
const X = m(0) * ag + m(3) * bg + m(6) * cg;
|
|
35232
|
-
const Y = m(1) * ag + m(4) * bg + m(7) * cg;
|
|
35233
|
-
const Z = m(2) * ag + m(5) * bg + m(8) * cg;
|
|
35234
|
-
const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
|
|
35235
|
-
const Xw = getArrNum(wpArr, 0, 0.95047);
|
|
35236
|
-
const Yw = getArrNum(wpArr, 1, 1);
|
|
35237
|
-
const Zw = getArrNum(wpArr, 2, 1.08883);
|
|
35238
|
-
return xyzToSrgb(X, Y, Z, Xw, Yw, Zw);
|
|
35239
|
-
}
|
|
35240
|
-
return [ag, bg, cg];
|
|
35241
|
-
}
|
|
35242
|
-
if (family === "Lab") {
|
|
35243
|
-
const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
|
|
35244
|
-
const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
|
|
35245
|
-
const rangeArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Range")) : void 0;
|
|
35246
|
-
const getNum = (arr, idx, fb) => {
|
|
35247
|
-
const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
|
|
35248
|
-
return r?.kind === "number" ? r.value : fb;
|
|
35249
|
-
};
|
|
35250
|
-
const Xw = getNum(wpArr, 0, 0.95047);
|
|
35251
|
-
const Yw = getNum(wpArr, 1, 1);
|
|
35252
|
-
const Zw = getNum(wpArr, 2, 1.08883);
|
|
35253
|
-
const amin = getNum(rangeArr, 0, -100);
|
|
35254
|
-
const amax = getNum(rangeArr, 1, 100);
|
|
35255
|
-
const bmin = getNum(rangeArr, 2, -100);
|
|
35256
|
-
const bmax = getNum(rangeArr, 3, 100);
|
|
35257
|
-
const Lstar = Math.max(0, Math.min(100, comps[0] ?? 0));
|
|
35258
|
-
const astar = Math.max(amin, Math.min(amax, comps[1] ?? 0));
|
|
35259
|
-
const bstar = Math.max(bmin, Math.min(bmax, comps[2] ?? 0));
|
|
35260
|
-
const M = (Lstar + 16) / 116;
|
|
35261
|
-
const L = M + astar / 500;
|
|
35262
|
-
const N = M - bstar / 200;
|
|
35263
|
-
const gFn = (x) => x >= 6 / 29 ? x * x * x : 108 / 841 * (x - 4 / 29);
|
|
35264
|
-
return xyzToSrgb(Xw * gFn(L), Yw * gFn(M), Zw * gFn(N), Xw, Yw, Zw);
|
|
37510
|
+
if (family === "CalGray" || family === "CalRGB" || family === "Lab") {
|
|
37511
|
+
const colorSpace = createCalibratedColorSpace(doc, family, resolved.items[1]);
|
|
37512
|
+
const rgb2 = colorSpace.getRgb(comps, 0);
|
|
37513
|
+
return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
|
|
35265
37514
|
}
|
|
35266
37515
|
if (family === "ICCBased" && resolved.items[1]) {
|
|
35267
37516
|
const iccNode = doc.resolve(resolved.items[1]);
|
|
@@ -35912,7 +38161,8 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
35912
38161
|
const shDict = shNode?.kind === "dict" ? shNode : shNode?.kind === "stream" ? shNode.dict : void 0;
|
|
35913
38162
|
const shStream = shNode?.kind === "stream" ? shNode : void 0;
|
|
35914
38163
|
if (shDict) {
|
|
35915
|
-
const
|
|
38164
|
+
const [originX, originY] = params.origin ?? [0, 0];
|
|
38165
|
+
const targetBox = st.clipRect ?? [originX, originY, originX + params.width, originY + params.height];
|
|
35916
38166
|
const img = renderShadingDictToImage(
|
|
35917
38167
|
params.cosDoc,
|
|
35918
38168
|
shDict,
|
|
@@ -35951,12 +38201,10 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
35951
38201
|
} else if (operator === "RG" || operator === "SC" || operator === "SCN") {
|
|
35952
38202
|
st.strokeColor = resolveScColorOperands(operator === "RG" ? "DeviceRGB" : st.strokeColorSpaceName, ops, activeResources);
|
|
35953
38203
|
} else if (operator === "k") {
|
|
35954
|
-
|
|
35955
|
-
st.fillColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
|
|
38204
|
+
st.fillColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
|
|
35956
38205
|
st.fillPatternName = void 0;
|
|
35957
38206
|
} else if (operator === "K") {
|
|
35958
|
-
|
|
35959
|
-
st.strokeColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
|
|
38207
|
+
st.strokeColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
|
|
35960
38208
|
} else if (operator === "gs" && params.cosDoc && activeResources && ops[0]?.kind === "name") {
|
|
35961
38209
|
const extDict = params.cosDoc.resolveDict(dictGet(activeResources, "ExtGState"));
|
|
35962
38210
|
const gsDict = extDict ? params.cosDoc.resolveDict(dictGet(extDict, ops[0].decoded)) : void 0;
|
|
@@ -36165,7 +38413,7 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
36165
38413
|
stateStack.pop();
|
|
36166
38414
|
capturedOperations = parentOperations;
|
|
36167
38415
|
}
|
|
36168
|
-
if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
|
|
38416
|
+
if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, isolated, bboxClip: nextClipPaths?.[0], blendMode: st.blendMode, clipRect: st.clipRect } });
|
|
36169
38417
|
};
|
|
36170
38418
|
const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
|
|
36171
38419
|
for (const node of nodes) {
|
|
@@ -36749,6 +38997,7 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
36749
38997
|
pageIndex: params.pageIndex,
|
|
36750
38998
|
width: params.width,
|
|
36751
38999
|
height: params.height,
|
|
39000
|
+
...params.origin ? { origin: params.origin } : {},
|
|
36752
39001
|
rotation: params.rotation ?? 0,
|
|
36753
39002
|
glyphs,
|
|
36754
39003
|
paths,
|
|
@@ -38219,7 +40468,7 @@ var PdfPage = class {
|
|
|
38219
40468
|
return [n0.value, n1.value, n2.value, n3.value];
|
|
38220
40469
|
}
|
|
38221
40470
|
}
|
|
38222
|
-
return [0, 0, 612, 792];
|
|
40471
|
+
return key === "MediaBox" ? [0, 0, 612, 792] : this.resolveBox("MediaBox");
|
|
38223
40472
|
}
|
|
38224
40473
|
getMediaBox() {
|
|
38225
40474
|
return this.resolveBox("MediaBox");
|
|
@@ -38892,16 +41141,19 @@ var PdfPage = class {
|
|
|
38892
41141
|
});
|
|
38893
41142
|
}
|
|
38894
41143
|
}
|
|
38895
|
-
|
|
41144
|
+
const mediaBox = this.getMediaBox(), cropBox = this.getCropBox();
|
|
41145
|
+
const originX = Math.min(mediaBox[0], mediaBox[2]), originY = Math.min(mediaBox[1], mediaBox[3]);
|
|
41146
|
+
return { ...evaluateContentStreamToDisplayList({
|
|
38896
41147
|
pageIndex: this.index,
|
|
38897
41148
|
width,
|
|
38898
41149
|
height,
|
|
41150
|
+
origin: [originX, originY],
|
|
38899
41151
|
rotation: this.getRotation(),
|
|
38900
41152
|
nodes: baseNodes,
|
|
38901
41153
|
cosDoc: this.cosDoc,
|
|
38902
41154
|
resourcesDict: evalResourcesDict,
|
|
38903
41155
|
annotations: extractPageAnnotations(this.cosDoc, this.pageDict)
|
|
38904
|
-
});
|
|
41156
|
+
}), cropBox: [cropBox[0] - originX, cropBox[1] - originY, cropBox[2] - originX, cropBox[3] - originY] };
|
|
38905
41157
|
}
|
|
38906
41158
|
extractPage(options) {
|
|
38907
41159
|
const dl = this.evaluateDisplayList();
|
|
@@ -38919,10 +41171,10 @@ var PdfPage = class {
|
|
|
38919
41171
|
return extractTablesFromDisplayList(this.evaluateDisplayList());
|
|
38920
41172
|
}
|
|
38921
41173
|
renderToBitmap(options) {
|
|
38922
|
-
return renderDisplayListToBitmap(this.evaluateDisplayList(), options);
|
|
41174
|
+
return renderDisplayListToBitmap(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
|
|
38923
41175
|
}
|
|
38924
41176
|
renderToPng(options) {
|
|
38925
|
-
return renderDisplayListToPng(this.evaluateDisplayList(), options);
|
|
41177
|
+
return renderDisplayListToPng(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
|
|
38926
41178
|
}
|
|
38927
41179
|
};
|
|
38928
41180
|
function createStandardFontHandle(standardName) {
|
|
@@ -40368,7 +42620,7 @@ function prepareStroke(path, scale) {
|
|
|
40368
42620
|
}
|
|
40369
42621
|
return { matrix, width, dashArray, dashPhase };
|
|
40370
42622
|
}
|
|
40371
|
-
function strokeContours(path, pageHeight, scale) {
|
|
42623
|
+
function strokeContours(path, pageHeight, scale, originX = 0, originY = 0) {
|
|
40372
42624
|
const stroke = prepareStroke(path, scale);
|
|
40373
42625
|
if (!stroke) return [];
|
|
40374
42626
|
const inverse = inverseStrokeMatrix(stroke.matrix);
|
|
@@ -40380,8 +42632,8 @@ function strokeContours(path, pageHeight, scale) {
|
|
|
40380
42632
|
(inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
|
|
40381
42633
|
];
|
|
40382
42634
|
const toScreen = ([x, y]) => [
|
|
40383
|
-
(a * x / strokeScale + c * y / strokeScale + e) * scale,
|
|
40384
|
-
(pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
|
|
42635
|
+
(a * x / strokeScale + c * y / strokeScale + e - originX) * scale,
|
|
42636
|
+
(pageHeight + originY - b * x / strokeScale - d * y / strokeScale - f) * scale
|
|
40385
42637
|
];
|
|
40386
42638
|
const contours = strokeOutlines(
|
|
40387
42639
|
segmentsToScreenPaths(path.segments, pageHeight, scale, project),
|
|
@@ -40539,18 +42791,37 @@ function renderSoftMask(mask, displayList, scale) {
|
|
|
40539
42791
|
}
|
|
40540
42792
|
return bitmap;
|
|
40541
42793
|
}
|
|
40542
|
-
function
|
|
40543
|
-
|
|
42794
|
+
function getDisplayListCropBox(list) {
|
|
42795
|
+
const full = [0, 0, list.width, list.height];
|
|
42796
|
+
const box = list.cropBox;
|
|
42797
|
+
if (!box || !box.every(Number.isFinite)) return full;
|
|
42798
|
+
const x0 = Math.max(0, Math.min(box[0], box[2]));
|
|
42799
|
+
const y0 = Math.max(0, Math.min(box[1], box[3]));
|
|
42800
|
+
const x1 = Math.min(list.width, Math.max(box[0], box[2]));
|
|
42801
|
+
const y1 = Math.min(list.height, Math.max(box[1], box[3]));
|
|
42802
|
+
return x1 > x0 && y1 > y0 ? [x0, y0, x1, y1] : full;
|
|
42803
|
+
}
|
|
42804
|
+
function hasCompositingEffects(operations, includeSoftMasks = false) {
|
|
42805
|
+
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));
|
|
42806
|
+
}
|
|
42807
|
+
function needsGroupBackdrop(group) {
|
|
42808
|
+
return group.isolated === false && !!group.softMask && hasCompositingEffects(group.operations, true);
|
|
42809
|
+
}
|
|
42810
|
+
function containsBackdropGroup(operations) {
|
|
42811
|
+
return operations.some((operation) => operation.kind === "group" && (needsGroupBackdrop(operation.value) || containsBackdropGroup(operation.value.operations)));
|
|
40544
42812
|
}
|
|
40545
42813
|
function renderDisplayListToBitmap(displayList, options = {}) {
|
|
40546
42814
|
const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
|
|
40547
42815
|
const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
|
|
40548
42816
|
const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
|
|
40549
42817
|
const scale = scaleX;
|
|
42818
|
+
const [originX, originY] = displayList.origin ?? [0, 0];
|
|
42819
|
+
const pageTop = originY + displayList.height;
|
|
42820
|
+
const toScreen = (x, y) => [(x - originX) * scale, (pageTop - y) * scale];
|
|
40550
42821
|
const width = Math.max(1, Math.round(displayList.width * scale));
|
|
40551
42822
|
const height = Math.max(1, Math.round(displayList.height * scale));
|
|
40552
42823
|
const rgba = new Uint8Array(width * height * 4);
|
|
40553
|
-
const deferBackground = !options.transparent &&
|
|
42824
|
+
const deferBackground = !options.transparent && hasCompositingEffects(paintOperations(displayList));
|
|
40554
42825
|
const transparent = options.transparent || deferBackground;
|
|
40555
42826
|
const bg = options.background ?? { r: 1, g: 1, b: 1 };
|
|
40556
42827
|
const bgR = transparent ? 0 : Math.round(bg.r * 255);
|
|
@@ -40575,14 +42846,27 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40575
42846
|
let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
|
|
40576
42847
|
if (operation.kind === "group") {
|
|
40577
42848
|
const group = operation.value;
|
|
40578
|
-
|
|
42849
|
+
let operations = group.operations;
|
|
42850
|
+
if (needsGroupBackdrop(group)) {
|
|
42851
|
+
operations = [{ kind: "image", value: {
|
|
42852
|
+
name: "GroupBackdrop",
|
|
42853
|
+
width,
|
|
42854
|
+
height,
|
|
42855
|
+
decodedRgba: rgba.slice(),
|
|
42856
|
+
matrix: [width / scale, 0, 0, height / scale, originX, pageTop - height / scale],
|
|
42857
|
+
colorSpace: "DeviceRGB",
|
|
42858
|
+
bitsPerComponent: 8,
|
|
42859
|
+
...group.bboxClip ? { clipPaths: [group.bboxClip] } : {}
|
|
42860
|
+
} }, ...operations];
|
|
42861
|
+
}
|
|
42862
|
+
const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, useCropBox: false, transparent: true });
|
|
40579
42863
|
for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
|
|
40580
42864
|
operation = { kind: "image", value: {
|
|
40581
42865
|
name: "TransparencyGroup",
|
|
40582
42866
|
width: bitmap.width,
|
|
40583
42867
|
height: bitmap.height,
|
|
40584
42868
|
decodedRgba: bitmap.data,
|
|
40585
|
-
matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale,
|
|
42869
|
+
matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, originX, pageTop - bitmap.height / scale],
|
|
40586
42870
|
colorSpace: "DeviceRGB",
|
|
40587
42871
|
bitsPerComponent: 8,
|
|
40588
42872
|
blendMode: group.blendMode,
|
|
@@ -40596,7 +42880,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40596
42880
|
for (const clip of clips) {
|
|
40597
42881
|
const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
|
|
40598
42882
|
const layer = new Uint8Array(width * height * 4);
|
|
40599
|
-
fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
|
|
42883
|
+
fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale, toScreen), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
|
|
40600
42884
|
for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
|
|
40601
42885
|
}
|
|
40602
42886
|
cachedClips = clips;
|
|
@@ -40643,15 +42927,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40643
42927
|
if (operation.kind === "path") {
|
|
40644
42928
|
const path = operation.value;
|
|
40645
42929
|
if (path.fillColor) {
|
|
40646
|
-
const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale), true);
|
|
40647
|
-
const clipScreen = path.clipRect ? [path.clipRect[0] * scale, (
|
|
42930
|
+
const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale, toScreen), true);
|
|
42931
|
+
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;
|
|
40648
42932
|
fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
|
|
40649
42933
|
}
|
|
40650
42934
|
if (path.strokeColor) {
|
|
40651
42935
|
const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
|
|
40652
42936
|
const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
|
|
40653
|
-
const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
|
|
40654
|
-
const clipScreen = path.clipRect ? [path.clipRect[0] * scale, (
|
|
42937
|
+
const edges = pathsToEdges(strokeContours(path, displayList.height, scale, originX, originY).map((points) => ({ points, closed: true })));
|
|
42938
|
+
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;
|
|
40655
42939
|
fillEdgesScanline4x4(
|
|
40656
42940
|
rgba,
|
|
40657
42941
|
width,
|
|
@@ -40674,12 +42958,12 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40674
42958
|
if (Math.abs(det) <= 1e-8) continue;
|
|
40675
42959
|
const cornersPdfX = [e, a + e, a + c + e, c + e];
|
|
40676
42960
|
const cornersPdfY = [f, b + f, b + d + f, d + f];
|
|
40677
|
-
const cornersPx = cornersPdfX.map((cx) => cx * scale);
|
|
40678
|
-
const cornersPy = cornersPdfY.map((cy) => (
|
|
40679
|
-
const clipMinPx = img.clipRect ? Math.floor(img.clipRect[0] * scale) : 0;
|
|
40680
|
-
const clipMaxPx = img.clipRect ? Math.ceil(img.clipRect[2] * scale) - 1 : width - 1;
|
|
40681
|
-
const clipMinPy = img.clipRect ? Math.floor((
|
|
40682
|
-
const clipMaxPy = img.clipRect ? Math.ceil((
|
|
42961
|
+
const cornersPx = cornersPdfX.map((cx) => (cx - originX) * scale);
|
|
42962
|
+
const cornersPy = cornersPdfY.map((cy) => (pageTop - cy) * scale);
|
|
42963
|
+
const clipMinPx = img.clipRect ? Math.floor((img.clipRect[0] - originX) * scale) : 0;
|
|
42964
|
+
const clipMaxPx = img.clipRect ? Math.ceil((img.clipRect[2] - originX) * scale) - 1 : width - 1;
|
|
42965
|
+
const clipMinPy = img.clipRect ? Math.floor((pageTop - img.clipRect[3]) * scale) : 0;
|
|
42966
|
+
const clipMaxPy = img.clipRect ? Math.ceil((pageTop - img.clipRect[1]) * scale) - 1 : height - 1;
|
|
40683
42967
|
const minPx = Math.max(0, clipMinPx, Math.floor(Math.min(...cornersPx)));
|
|
40684
42968
|
const maxPx = Math.min(width - 1, clipMaxPx, Math.ceil(Math.max(...cornersPx)) - 1);
|
|
40685
42969
|
const minPy = Math.max(0, clipMinPy, Math.floor(Math.min(...cornersPy)));
|
|
@@ -40696,11 +42980,11 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40696
42980
|
const smooth = Math.fround((s1 + s2 + Math.hypot(s1 - s2, 2 * cross)) / 2) <= 1;
|
|
40697
42981
|
const sample = new Float64Array(4);
|
|
40698
42982
|
for (let py = minPy; py <= maxPy; py++) {
|
|
40699
|
-
const yPdf =
|
|
42983
|
+
const yPdf = pageTop - (py + 0.5) / scale;
|
|
40700
42984
|
if (img.clipRect && (yPdf < img.clipRect[1] || yPdf > img.clipRect[3])) continue;
|
|
40701
42985
|
const dyPdf = yPdf - f;
|
|
40702
42986
|
for (let px = minPx; px <= maxPx; px++) {
|
|
40703
|
-
const xPdf = (px + 0.5) / scale;
|
|
42987
|
+
const xPdf = originX + (px + 0.5) / scale;
|
|
40704
42988
|
if (img.clipRect && (xPdf < img.clipRect[0] || xPdf > img.clipRect[2])) continue;
|
|
40705
42989
|
const dxPdf = xPdf - e;
|
|
40706
42990
|
const u = (d * dxPdf - c * dyPdf) / det;
|
|
@@ -40761,6 +43045,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40761
43045
|
}
|
|
40762
43046
|
result = { width: targetW, height: targetH, data: resampled };
|
|
40763
43047
|
}
|
|
43048
|
+
if (options.useCropBox) {
|
|
43049
|
+
const box = getDisplayListCropBox(displayList);
|
|
43050
|
+
result = cropRgbaBitmap(result, {
|
|
43051
|
+
x: box[0] * scaleX,
|
|
43052
|
+
y: (displayList.height - box[3]) * scaleY,
|
|
43053
|
+
width: (box[2] - box[0]) * scaleX,
|
|
43054
|
+
height: (box[3] - box[1]) * scaleY
|
|
43055
|
+
});
|
|
43056
|
+
}
|
|
40764
43057
|
result = rotateRgbaBitmapQuarterTurns(result, displayList.rotation ?? 0);
|
|
40765
43058
|
if (options.cropRect) {
|
|
40766
43059
|
result = cropRgbaBitmap(result, options.cropRect);
|
|
@@ -40830,18 +43123,44 @@ function svgPathData(segments, height, matrix) {
|
|
|
40830
43123
|
}
|
|
40831
43124
|
function renderDisplayListToSvg(displayList, options = {}) {
|
|
40832
43125
|
const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1);
|
|
43126
|
+
if (containsBackdropGroup(paintOperations(displayList))) {
|
|
43127
|
+
const bitmap = renderDisplayListToBitmap(displayList, { ...options, scale: baseScale });
|
|
43128
|
+
const embedded = svgImage({
|
|
43129
|
+
name: "PageComposite",
|
|
43130
|
+
width: bitmap.width,
|
|
43131
|
+
height: bitmap.height,
|
|
43132
|
+
decodedRgba: bitmap.data,
|
|
43133
|
+
matrix: [bitmap.width, 0, 0, bitmap.height, 0, 0],
|
|
43134
|
+
colorSpace: "DeviceRGB",
|
|
43135
|
+
bitsPerComponent: 8
|
|
43136
|
+
}, bitmap.height);
|
|
43137
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${bitmap.width}" height="${bitmap.height}" viewBox="0 0 ${bitmap.width} ${bitmap.height}">${embedded}</svg>
|
|
43138
|
+
`;
|
|
43139
|
+
}
|
|
40833
43140
|
const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
|
|
40834
43141
|
const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
|
|
40835
|
-
const
|
|
43142
|
+
const [originX, originY] = displayList.origin ?? [0, 0];
|
|
43143
|
+
const viewport = new PageViewport({ viewBox: [originX, originY, originX + displayList.width, originY + displayList.height], userUnit: 1, scale: 1, rotation: displayList.rotation ?? 0 });
|
|
40836
43144
|
const quarterTurn = displayList.rotation === 90 || displayList.rotation === 270;
|
|
40837
43145
|
const outputScaleX = quarterTurn ? scaleY : scaleX;
|
|
40838
43146
|
const outputScaleY = quarterTurn ? scaleX : scaleY;
|
|
40839
|
-
|
|
40840
|
-
|
|
40841
|
-
|
|
40842
|
-
|
|
40843
|
-
|
|
40844
|
-
|
|
43147
|
+
let bounds = [0, 0, viewport.width, viewport.height];
|
|
43148
|
+
if (options.useCropBox) {
|
|
43149
|
+
const box = getDisplayListCropBox(displayList);
|
|
43150
|
+
const [x0, y0, x1, y1] = [box[0] + originX, box[1] + originY, box[2] + originX, box[3] + originY];
|
|
43151
|
+
const [a, b, c, d, e, f] = viewport.transform;
|
|
43152
|
+
bounds = [a * x0 + c * y0 + e, b * x0 + d * y0 + f, a * x1 + c * y1 + e, b * x1 + d * y1 + f];
|
|
43153
|
+
}
|
|
43154
|
+
const viewX = Math.min(bounds[0], bounds[2]), viewY = Math.min(bounds[1], bounds[3]);
|
|
43155
|
+
const viewWidth = Math.abs(bounds[2] - bounds[0]), viewHeight = Math.abs(bounds[3] - bounds[1]);
|
|
43156
|
+
const fullW = Math.max(1, Math.round(viewWidth * outputScaleX));
|
|
43157
|
+
const fullH = Math.max(1, Math.round(viewHeight * outputScaleY));
|
|
43158
|
+
const cropX = options.cropRect ? options.cropRect.x / outputScaleX : 0;
|
|
43159
|
+
const vbX = viewX + cropX;
|
|
43160
|
+
const cropY = options.cropRect ? options.cropRect.y / outputScaleY : 0;
|
|
43161
|
+
const vbY = viewY + cropY;
|
|
43162
|
+
const vbW = options.cropRect && options.cropRect.width > 0 ? options.cropRect.width / outputScaleX : Math.max(1, viewWidth - cropX);
|
|
43163
|
+
const vbH = options.cropRect && options.cropRect.height > 0 ? options.cropRect.height / outputScaleY : Math.max(1, viewHeight - cropY);
|
|
40845
43164
|
const outW = options.cropRect && options.cropRect.width > 0 ? Math.round(options.cropRect.width) : Math.max(1, fullW - Math.round(options.cropRect?.x ?? 0));
|
|
40846
43165
|
const outH = options.cropRect && options.cropRect.height > 0 ? Math.round(options.cropRect.height) : Math.max(1, fullH - Math.round(options.cropRect?.y ?? 0));
|
|
40847
43166
|
const parts = [
|
|
@@ -40851,7 +43170,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
|
|
|
40851
43170
|
parts.push(` <rect x="${vbX}" y="${vbY}" width="${vbW}" height="${vbH}" fill="#ffffff"/>`);
|
|
40852
43171
|
}
|
|
40853
43172
|
parts.push('<g style="isolation:isolate">');
|
|
40854
|
-
if (displayList.rotation) {
|
|
43173
|
+
if (displayList.rotation || originX || originY) {
|
|
40855
43174
|
const [a, b, c, d, e, f] = viewport.transform;
|
|
40856
43175
|
parts.push(`<g transform="matrix(${a} ${b} ${-c} ${-d} ${e + c * displayList.height} ${f + d * displayList.height})">`);
|
|
40857
43176
|
}
|
|
@@ -40877,11 +43196,11 @@ function renderDisplayListToSvg(displayList, options = {}) {
|
|
|
40877
43196
|
width: bitmap.width,
|
|
40878
43197
|
height: bitmap.height,
|
|
40879
43198
|
decodedRgba: bitmap.data,
|
|
40880
|
-
matrix: [displayList.width, 0, 0, displayList.height,
|
|
43199
|
+
matrix: [displayList.width, 0, 0, displayList.height, originX, originY],
|
|
40881
43200
|
colorSpace: "DeviceGray",
|
|
40882
43201
|
bitsPerComponent: 8
|
|
40883
43202
|
};
|
|
40884
|
-
parts.push(`<defs><mask id="${id}" maskUnits="userSpaceOnUse" x="
|
|
43203
|
+
parts.push(`<defs><mask id="${id}" maskUnits="userSpaceOnUse" x="${originX}" y="${-originY}" width="${displayList.width}" height="${displayList.height}" style="mask-type:alpha">${svgImage(image, displayList.height)}</mask></defs>`);
|
|
40885
43204
|
}
|
|
40886
43205
|
parts.push(`<g mask="url(#${id})">`);
|
|
40887
43206
|
}
|
|
@@ -40893,7 +43212,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
|
|
|
40893
43212
|
}
|
|
40894
43213
|
for (const image of imageClips) {
|
|
40895
43214
|
const id = `image-clip-${clipId++}`;
|
|
40896
|
-
parts.push(`<defs><mask id="${id}" maskUnits="userSpaceOnUse" x="
|
|
43215
|
+
parts.push(`<defs><mask id="${id}" maskUnits="userSpaceOnUse" x="${originX}" y="${-originY}" width="${displayList.width}" height="${displayList.height}" style="mask-type:alpha">${svgImage(image, displayList.height)}</mask></defs><g mask="url(#${id})">`);
|
|
40897
43216
|
}
|
|
40898
43217
|
if (operation.kind === "group") {
|
|
40899
43218
|
parts.push(`<g opacity="${operation.value.alpha}" style="isolation:isolate">`);
|
|
@@ -40937,84 +43256,11 @@ function renderDisplayListToSvg(displayList, options = {}) {
|
|
|
40937
43256
|
}
|
|
40938
43257
|
};
|
|
40939
43258
|
appendOperations(paintOperations(displayList));
|
|
40940
|
-
if (displayList.rotation) parts.push("</g>");
|
|
43259
|
+
if (displayList.rotation || originX || originY) parts.push("</g>");
|
|
40941
43260
|
parts.push("</g>");
|
|
40942
43261
|
parts.push("</svg>\n");
|
|
40943
43262
|
return parts.join("\n");
|
|
40944
43263
|
}
|
|
40945
|
-
function collectLeavesForRaster(cosDoc, node, out = [], visited = /* @__PURE__ */ new Set()) {
|
|
40946
|
-
if (!node) return out;
|
|
40947
|
-
let ref;
|
|
40948
|
-
if (node.kind === "ref") {
|
|
40949
|
-
if (visited.has(node.objectNumber)) return out;
|
|
40950
|
-
visited.add(node.objectNumber);
|
|
40951
|
-
ref = node;
|
|
40952
|
-
}
|
|
40953
|
-
const dict = cosDoc.resolveDict(node);
|
|
40954
|
-
if (!dict) return out;
|
|
40955
|
-
const kids = cosDoc.resolveArray(dictGet(dict, "Kids"));
|
|
40956
|
-
if (kids) {
|
|
40957
|
-
for (const k of kids.items) collectLeavesForRaster(cosDoc, k, out, visited);
|
|
40958
|
-
} else {
|
|
40959
|
-
out.push({ ref: ref ?? cosDoc.allocateObject(dict), dict });
|
|
40960
|
-
}
|
|
40961
|
-
return out;
|
|
40962
|
-
}
|
|
40963
|
-
function extractBoxArray(cosDoc, dict, key) {
|
|
40964
|
-
let cur = dict;
|
|
40965
|
-
const visited = /* @__PURE__ */ new Set();
|
|
40966
|
-
while (cur && !visited.has(cur)) {
|
|
40967
|
-
visited.add(cur);
|
|
40968
|
-
const arr = cosDoc.resolveArray(dictGet(cur, key));
|
|
40969
|
-
if (arr && arr.items.length >= 4) {
|
|
40970
|
-
const nums = arr.items.slice(0, 4).map((item) => {
|
|
40971
|
-
const r = cosDoc.resolve(item);
|
|
40972
|
-
return r?.kind === "number" ? r.value : 0;
|
|
40973
|
-
});
|
|
40974
|
-
return [nums[0], nums[1], nums[2], nums[3]];
|
|
40975
|
-
}
|
|
40976
|
-
cur = cosDoc.resolveDict(dictGet(cur, "Parent"));
|
|
40977
|
-
}
|
|
40978
|
-
return void 0;
|
|
40979
|
-
}
|
|
40980
|
-
function renderPdfPageToBitmap(pdfBytes, pageIndex = 0, options) {
|
|
40981
|
-
const cos = pdfBytes instanceof Uint8Array ? parseCosDocument(pdfBytes) : pdfBytes;
|
|
40982
|
-
const catalog = cos.resolveDict(cos.rootRef);
|
|
40983
|
-
const leaves = collectLeavesForRaster(cos, catalog ? dictGet(catalog, "Pages") : void 0);
|
|
40984
|
-
const leaf = leaves[pageIndex] ?? (pageIndex >= 1 ? leaves[pageIndex - 1] : void 0);
|
|
40985
|
-
if (!leaf) throw new Error(`Page index ${pageIndex} out of bounds`);
|
|
40986
|
-
const resolvedIndex = leaves.indexOf(leaf);
|
|
40987
|
-
const page = new PdfPage(cos, leaf.ref, leaf.dict, resolvedIndex);
|
|
40988
|
-
const { cropRect, ...restOptions } = options ?? {};
|
|
40989
|
-
let bitmap = renderDisplayListToBitmap(
|
|
40990
|
-
// CropBox is in unrotated page coordinates. Apply page rotation after it.
|
|
40991
|
-
{ ...page.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), rotation: 0 },
|
|
40992
|
-
restOptions
|
|
40993
|
-
);
|
|
40994
|
-
if (options?.useCropBox) {
|
|
40995
|
-
const cropBox = extractBoxArray(cos, leaf.dict, "CropBox");
|
|
40996
|
-
if (cropBox) {
|
|
40997
|
-
const mediaBox = extractBoxArray(cos, leaf.dict, "MediaBox") ?? [0, 0, page.getSize().width, page.getSize().height];
|
|
40998
|
-
const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
|
|
40999
|
-
const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
|
|
41000
|
-
const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
|
|
41001
|
-
const mediaH = mediaBox[3] - mediaBox[1];
|
|
41002
|
-
const bx = Math.round((cropBox[0] - mediaBox[0]) * scaleX);
|
|
41003
|
-
const by = Math.round((mediaH - (cropBox[3] - mediaBox[1])) * scaleY);
|
|
41004
|
-
const bw = Math.max(1, Math.round(Math.abs(cropBox[2] - cropBox[0]) * scaleX));
|
|
41005
|
-
const bh = Math.max(1, Math.round(Math.abs(cropBox[3] - cropBox[1]) * scaleY));
|
|
41006
|
-
bitmap = cropRgbaBitmap(bitmap, { x: bx, y: by, width: bw, height: bh });
|
|
41007
|
-
}
|
|
41008
|
-
}
|
|
41009
|
-
const rotation = page.getRotation();
|
|
41010
|
-
if (rotation === 90 || rotation === 180 || rotation === 270) {
|
|
41011
|
-
bitmap = rotateRgbaBitmapQuarterTurns(bitmap, rotation);
|
|
41012
|
-
}
|
|
41013
|
-
if (cropRect) {
|
|
41014
|
-
bitmap = cropRgbaBitmap(bitmap, cropRect);
|
|
41015
|
-
}
|
|
41016
|
-
return bitmap;
|
|
41017
|
-
}
|
|
41018
43264
|
function discardUnreachableObjects(doc) {
|
|
41019
43265
|
const reachable = /* @__PURE__ */ new Set();
|
|
41020
43266
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -41925,29 +44171,9 @@ function runPdftoppmCliSync(argv, files, options = {}) {
|
|
|
41925
44171
|
if (oddOnly && p % 2 === 0) continue;
|
|
41926
44172
|
if (evenOnly && p % 2 === 1) continue;
|
|
41927
44173
|
const page = doc.getPage(p - 1);
|
|
41928
|
-
|
|
41929
|
-
|
|
41930
|
-
|
|
41931
|
-
let cur = page.pageDict;
|
|
41932
|
-
const visited = /* @__PURE__ */ new Set();
|
|
41933
|
-
while (cur && !visited.has(cur)) {
|
|
41934
|
-
visited.add(cur);
|
|
41935
|
-
const cb = doc.cos.resolveArray(dictGet(cur, "CropBox"));
|
|
41936
|
-
if (cb && cb.items.length >= 4) {
|
|
41937
|
-
const nums = cb.items.slice(0, 4).map((it) => {
|
|
41938
|
-
const r = doc.cos.resolve(it);
|
|
41939
|
-
return r?.kind === "number" ? r.value : 0;
|
|
41940
|
-
});
|
|
41941
|
-
resolvedCropBox = [nums[0], nums[1], nums[2], nums[3]];
|
|
41942
|
-
rawSize = {
|
|
41943
|
-
width: Math.max(1, Math.abs(nums[2] - nums[0])),
|
|
41944
|
-
height: Math.max(1, Math.abs(nums[3] - nums[1]))
|
|
41945
|
-
};
|
|
41946
|
-
break;
|
|
41947
|
-
}
|
|
41948
|
-
cur = doc.cos.resolveDict(dictGet(cur, "Parent"));
|
|
41949
|
-
}
|
|
41950
|
-
}
|
|
44174
|
+
const displayList = page.evaluateDisplayList({ hideAnnotations });
|
|
44175
|
+
const box = useCropBox ? getDisplayListCropBox(displayList) : [0, 0, displayList.width, displayList.height];
|
|
44176
|
+
const rawSize = { width: box[2] - box[0], height: box[3] - box[1] };
|
|
41951
44177
|
const rot = page.getRotation();
|
|
41952
44178
|
const ptW = rot === 90 || rot === 270 ? rawSize.height : rawSize.width;
|
|
41953
44179
|
const ptH = rot === 90 || rot === 270 ? rawSize.width : rawSize.height;
|
|
@@ -41970,33 +44196,17 @@ function runPdftoppmCliSync(argv, files, options = {}) {
|
|
|
41970
44196
|
const cropRect = hasCrop ? { x: cropX, y: cropY, width: cropW, height: cropH } : void 0;
|
|
41971
44197
|
let renderedBytes;
|
|
41972
44198
|
if (format === "svg") {
|
|
41973
|
-
|
|
41974
|
-
if (useCropBox && resolvedCropBox) {
|
|
41975
|
-
const fullMediaSize = page.getSize();
|
|
41976
|
-
const scaleX = effDpiX / 72;
|
|
41977
|
-
const scaleY = effDpiY / 72;
|
|
41978
|
-
const cbScreenX = resolvedCropBox[0] * scaleX;
|
|
41979
|
-
const cbScreenY = (fullMediaSize.height - resolvedCropBox[3]) * scaleY;
|
|
41980
|
-
const cbScreenW = Math.abs(resolvedCropBox[2] - resolvedCropBox[0]) * scaleX;
|
|
41981
|
-
const cbScreenH = Math.abs(resolvedCropBox[3] - resolvedCropBox[1]) * scaleY;
|
|
41982
|
-
svgCropRect = hasCrop ? {
|
|
41983
|
-
x: cbScreenX + cropX,
|
|
41984
|
-
y: cbScreenY + cropY,
|
|
41985
|
-
width: cropW || Math.max(1, cbScreenW - cropX),
|
|
41986
|
-
height: cropH || Math.max(1, cbScreenH - cropY)
|
|
41987
|
-
} : { x: cbScreenX, y: cbScreenY, width: cbScreenW, height: cbScreenH };
|
|
41988
|
-
}
|
|
41989
|
-
const svgText = renderDisplayListToSvg(page.evaluateDisplayList({ hideAnnotations }), {
|
|
44199
|
+
const svgText = renderDisplayListToSvg(displayList, {
|
|
41990
44200
|
dpiX: effDpiX,
|
|
41991
44201
|
dpiY: effDpiY,
|
|
41992
44202
|
useCropBox,
|
|
41993
|
-
cropRect
|
|
44203
|
+
cropRect,
|
|
41994
44204
|
hideAnnotations,
|
|
41995
44205
|
transparent
|
|
41996
44206
|
});
|
|
41997
44207
|
renderedBytes = new TextEncoder().encode(svgText);
|
|
41998
44208
|
} else {
|
|
41999
|
-
const bitmap =
|
|
44209
|
+
const bitmap = renderDisplayListToBitmap(displayList, {
|
|
42000
44210
|
dpiX: effDpiX,
|
|
42001
44211
|
dpiY: effDpiY,
|
|
42002
44212
|
useCropBox,
|