@poe-platform/safe-bash 0.1.772 → 0.1.774
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/image-ast/index.browser.js +3543 -706
- package/dist/image-ast/index.js +3543 -706
- package/dist/pdf-ast/ast.d.ts +7 -0
- package/dist/pdf-ast/content/evaluator.d.ts +1 -0
- package/dist/pdf-ast/index.js +3587 -718
- package/dist/pdf-ast/render/raster.d.ts +1 -0
- package/dist/pdf-ast/vendor/pdfjs-fonts.d.mts +36 -0
- package/dist/pdf-ast/vendor/pdfjs-fonts.mjs +3323 -0
- package/dist/safe-bash/command-chunks/{chunk-M2XU2YCK.js → chunk-4ZHDCMQX.js} +2 -2
- package/dist/safe-bash/command-chunks/{chunk-NBENXODJ.js → chunk-HH5QPKIN.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-C4AAJTXF.js → chunk-PM63UJE6.js} +3546 -706
- package/dist/safe-bash/core.browser.js +101 -45
- package/dist/safe-bash/core.d.ts +1 -1
- package/dist/safe-bash/plugins/composition.d.ts +2 -0
- package/dist/safe-bash/plugins/composition.js +2 -1
- package/dist/safe-bash/shell/runtime.js +17 -9
- package/dist/safe-bash/shell/sync-posix-regex.d.ts +3 -0
- package/dist/safe-bash/shell/sync-posix-regex.js +48 -0
- package/dist/safe-bash-command-ffmpeg/index.js +11032 -9579
- package/dist/safe-bash-command-gh/index.d.ts +1 -0
- package/dist/safe-bash-command-gh/index.js +43 -13
- package/dist/safe-bash-command-gh/types.d.ts +1 -0
- package/dist/safe-bash-command-git/git_rust.wasm +0 -0
- package/dist/safe-bash-command-git/index.js +22 -15
- package/dist/safe-bash-command-git/wasm.generated.js +1 -1
- package/dist/safe-bash-command-gpg/index.js +28 -7
- package/dist/safe-bash-command-imagemagick/index.js +2 -2
- package/dist/safe-bash-command-openssl/index.js +24 -6
- package/dist/safe-bash-command-pandoc/command.js +3 -3
- package/dist/safe-bash-command-pandoc/index.js +3 -3
- package/dist/safe-bash-command-pdfimages/index.js +3542 -660
- package/dist/safe-bash-command-pdfinfo/index.js +3584 -718
- package/dist/safe-bash-command-pdftk/index.js +3542 -660
- package/dist/safe-bash-command-pdftoppm/index.js +3589 -787
- package/dist/safe-bash-command-pdftotext/index.js +3542 -660
- package/dist/safe-bash-command-qpdf/index.js +3542 -660
- package/dist/safe-bash-command-sips/index.js +2 -2
- package/dist/safe-bash-command-soffice/index.js +1 -1
- package/dist/safe-bash-command-ssconvert/index.js +3553 -716
- package/dist/safe-bash-command-ssh/index.js +124 -23
- package/dist/safe-bash-command-wkhtmltopdf/index.js +3581 -660
- package/dist/safe-bash-mcp/index.d.ts +8 -2
- package/dist/safe-bash-mcp/index.js +13 -6
- package/package.json +7 -7
- package/third-party/pdf-ast/THIRD_PARTY_NOTICES.md +84 -1
|
@@ -3588,6 +3588,11 @@ var FONT_IDENTITY_MATRIX = [1e-3, 0, 0, 1e-3, 0, 0];
|
|
|
3588
3588
|
var LINE_FACTOR = 1.35;
|
|
3589
3589
|
var LINE_DESCENT_FACTOR = 0.35;
|
|
3590
3590
|
var BASELINE_FACTOR = LINE_DESCENT_FACTOR / LINE_FACTOR;
|
|
3591
|
+
var MeshFigureType = {
|
|
3592
|
+
TRIANGLES: 1,
|
|
3593
|
+
LATTICE: 2,
|
|
3594
|
+
PATCH: 3
|
|
3595
|
+
};
|
|
3591
3596
|
var VerbosityLevel = {
|
|
3592
3597
|
ERRORS: 0,
|
|
3593
3598
|
WARNINGS: 1,
|
|
@@ -22706,6 +22711,3308 @@ var PageViewport = class _PageViewport {
|
|
|
22706
22711
|
return p;
|
|
22707
22712
|
}
|
|
22708
22713
|
};
|
|
22714
|
+
function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
|
|
22715
|
+
const COMPONENTS = 3;
|
|
22716
|
+
alpha01 = alpha01 !== 1 ? 0 : alpha01;
|
|
22717
|
+
const xRatio = w1 / w2;
|
|
22718
|
+
const yRatio = h1 / h2;
|
|
22719
|
+
let newIndex = 0, oldIndex;
|
|
22720
|
+
const xScaled = new Uint16Array(w2);
|
|
22721
|
+
const w1Scanline = w1 * COMPONENTS;
|
|
22722
|
+
for (let i = 0; i < w2; i++) {
|
|
22723
|
+
xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
|
|
22724
|
+
}
|
|
22725
|
+
for (let i = 0; i < h2; i++) {
|
|
22726
|
+
const py = Math.floor(i * yRatio) * w1Scanline;
|
|
22727
|
+
for (let j = 0; j < w2; j++) {
|
|
22728
|
+
oldIndex = py + xScaled[j];
|
|
22729
|
+
dest[newIndex++] = src[oldIndex++];
|
|
22730
|
+
dest[newIndex++] = src[oldIndex++];
|
|
22731
|
+
dest[newIndex++] = src[oldIndex++];
|
|
22732
|
+
newIndex += alpha01;
|
|
22733
|
+
}
|
|
22734
|
+
}
|
|
22735
|
+
}
|
|
22736
|
+
function isDefaultDecodeHelper(decode, expectedLen) {
|
|
22737
|
+
if (!Array.isArray(decode)) {
|
|
22738
|
+
return true;
|
|
22739
|
+
}
|
|
22740
|
+
const decodeLen = decode.length;
|
|
22741
|
+
if (decodeLen < expectedLen) {
|
|
22742
|
+
warn2("Decode map length is too short.");
|
|
22743
|
+
return true;
|
|
22744
|
+
}
|
|
22745
|
+
if (decodeLen > expectedLen) {
|
|
22746
|
+
info("Truncating too long decode map.");
|
|
22747
|
+
decode.length = expectedLen;
|
|
22748
|
+
}
|
|
22749
|
+
return false;
|
|
22750
|
+
}
|
|
22751
|
+
var ColorSpace = class _ColorSpace {
|
|
22752
|
+
static #rgbBuf = new Uint8ClampedArray(3);
|
|
22753
|
+
constructor(name, numComps) {
|
|
22754
|
+
if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _ColorSpace) {
|
|
22755
|
+
unreachable2("Cannot initialize ColorSpace.");
|
|
22756
|
+
}
|
|
22757
|
+
this.name = name;
|
|
22758
|
+
this.numComps = numComps;
|
|
22759
|
+
}
|
|
22760
|
+
/**
|
|
22761
|
+
* Converts the color value to the RGB color. The color components are
|
|
22762
|
+
* located in the src array starting from the srcOffset. Returns the array
|
|
22763
|
+
* of the rgb components, each value ranging from [0,255].
|
|
22764
|
+
*/
|
|
22765
|
+
getRgb(src, srcOffset, output = new Uint8ClampedArray(3)) {
|
|
22766
|
+
this.getRgbItem(src, srcOffset, output, 0);
|
|
22767
|
+
return output;
|
|
22768
|
+
}
|
|
22769
|
+
getRgbHex(src, srcOffset) {
|
|
22770
|
+
const buffer = this.getRgb(src, srcOffset, _ColorSpace.#rgbBuf);
|
|
22771
|
+
return Util.makeHexColor(buffer[0], buffer[1], buffer[2]);
|
|
22772
|
+
}
|
|
22773
|
+
/**
|
|
22774
|
+
* Converts the color value to the RGB color, similar to the getRgb method.
|
|
22775
|
+
* The result placed into the dest array starting from the destOffset.
|
|
22776
|
+
*/
|
|
22777
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
22778
|
+
unreachable2("Should not call ColorSpace.getRgbItem");
|
|
22779
|
+
}
|
|
22780
|
+
/**
|
|
22781
|
+
* Converts the specified number of the color values to the RGB colors.
|
|
22782
|
+
* The colors are located in the src array starting from the srcOffset.
|
|
22783
|
+
* The result is placed into the dest array starting from the destOffset.
|
|
22784
|
+
* The src array items shall be in [0,2^bits) range, the dest array items
|
|
22785
|
+
* will be in [0,255] range. alpha01 indicates how many alpha components
|
|
22786
|
+
* there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
|
|
22787
|
+
* array).
|
|
22788
|
+
*/
|
|
22789
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
22790
|
+
unreachable2("Should not call ColorSpace.getRgbBuffer");
|
|
22791
|
+
}
|
|
22792
|
+
/**
|
|
22793
|
+
* Converts `count` unscaled colors to RGB, starting at `destOffset`.
|
|
22794
|
+
* Components use the native color-space ranges expected by `getRgbItem`,
|
|
22795
|
+
* and each output has a `3 + alpha01` byte stride.
|
|
22796
|
+
* Subclasses may override this to batch expensive conversions.
|
|
22797
|
+
*/
|
|
22798
|
+
getRgbItems(src, count, dest, destOffset, alpha01) {
|
|
22799
|
+
const { numComps } = this;
|
|
22800
|
+
for (let i = 0, srcOffset = 0; i < count; i++, srcOffset += numComps) {
|
|
22801
|
+
this.getRgbItem(src, srcOffset, dest, destOffset);
|
|
22802
|
+
destOffset += 3 + alpha01;
|
|
22803
|
+
}
|
|
22804
|
+
}
|
|
22805
|
+
/**
|
|
22806
|
+
* Returns true if source data will be equal the result/output data.
|
|
22807
|
+
*/
|
|
22808
|
+
isPassthrough(bits) {
|
|
22809
|
+
return false;
|
|
22810
|
+
}
|
|
22811
|
+
/**
|
|
22812
|
+
* Refer to the static `ColorSpace.isDefaultDecode` method below.
|
|
22813
|
+
*/
|
|
22814
|
+
isDefaultDecode(decode, bpc) {
|
|
22815
|
+
return _ColorSpace.isDefaultDecode(decode, this.numComps);
|
|
22816
|
+
}
|
|
22817
|
+
/**
|
|
22818
|
+
* Fills in the RGB colors in the destination buffer. alpha01 indicates
|
|
22819
|
+
* how many alpha components there are in the dest array; it will be either
|
|
22820
|
+
* 0 (RGB array) or 1 (RGBA array).
|
|
22821
|
+
*/
|
|
22822
|
+
fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {
|
|
22823
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
22824
|
+
assert2(
|
|
22825
|
+
dest instanceof Uint8ClampedArray,
|
|
22826
|
+
'ColorSpace.fillRgb: Unsupported "dest" type.'
|
|
22827
|
+
);
|
|
22828
|
+
}
|
|
22829
|
+
const count = originalWidth * originalHeight;
|
|
22830
|
+
let rgbBuf = null;
|
|
22831
|
+
const numComponentColors = 1 << bpc;
|
|
22832
|
+
const needsResizing = originalHeight !== height || originalWidth !== width;
|
|
22833
|
+
if (this.isPassthrough(bpc)) {
|
|
22834
|
+
rgbBuf = comps;
|
|
22835
|
+
} else if (this.numComps === 1 && count > numComponentColors && this.name !== "DeviceGray" && this.name !== "DeviceRGB") {
|
|
22836
|
+
const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);
|
|
22837
|
+
for (let i = 0; i < numComponentColors; i++) {
|
|
22838
|
+
allColors[i] = i;
|
|
22839
|
+
}
|
|
22840
|
+
const colorMap = new Uint8ClampedArray(numComponentColors * 3);
|
|
22841
|
+
this.getRgbBuffer(
|
|
22842
|
+
allColors,
|
|
22843
|
+
0,
|
|
22844
|
+
numComponentColors,
|
|
22845
|
+
colorMap,
|
|
22846
|
+
0,
|
|
22847
|
+
bpc,
|
|
22848
|
+
/* alpha01 = */
|
|
22849
|
+
0
|
|
22850
|
+
);
|
|
22851
|
+
if (!needsResizing) {
|
|
22852
|
+
let destPos = 0;
|
|
22853
|
+
for (let i = 0; i < count; ++i) {
|
|
22854
|
+
const key = comps[i] * 3;
|
|
22855
|
+
dest[destPos++] = colorMap[key];
|
|
22856
|
+
dest[destPos++] = colorMap[key + 1];
|
|
22857
|
+
dest[destPos++] = colorMap[key + 2];
|
|
22858
|
+
destPos += alpha01;
|
|
22859
|
+
}
|
|
22860
|
+
} else {
|
|
22861
|
+
rgbBuf = new Uint8Array(count * 3);
|
|
22862
|
+
let rgbPos = 0;
|
|
22863
|
+
for (let i = 0; i < count; ++i) {
|
|
22864
|
+
const key = comps[i] * 3;
|
|
22865
|
+
rgbBuf[rgbPos++] = colorMap[key];
|
|
22866
|
+
rgbBuf[rgbPos++] = colorMap[key + 1];
|
|
22867
|
+
rgbBuf[rgbPos++] = colorMap[key + 2];
|
|
22868
|
+
}
|
|
22869
|
+
}
|
|
22870
|
+
} else if (!needsResizing) {
|
|
22871
|
+
this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);
|
|
22872
|
+
} else {
|
|
22873
|
+
rgbBuf = new Uint8ClampedArray(count * 3);
|
|
22874
|
+
this.getRgbBuffer(
|
|
22875
|
+
comps,
|
|
22876
|
+
0,
|
|
22877
|
+
count,
|
|
22878
|
+
rgbBuf,
|
|
22879
|
+
0,
|
|
22880
|
+
bpc,
|
|
22881
|
+
/* alpha01 = */
|
|
22882
|
+
0
|
|
22883
|
+
);
|
|
22884
|
+
}
|
|
22885
|
+
if (rgbBuf) {
|
|
22886
|
+
if (needsResizing) {
|
|
22887
|
+
resizeRgbImage(
|
|
22888
|
+
rgbBuf,
|
|
22889
|
+
dest,
|
|
22890
|
+
originalWidth,
|
|
22891
|
+
originalHeight,
|
|
22892
|
+
width,
|
|
22893
|
+
height,
|
|
22894
|
+
alpha01
|
|
22895
|
+
);
|
|
22896
|
+
} else {
|
|
22897
|
+
let destPos = 0, rgbPos = 0;
|
|
22898
|
+
for (let i = 0, ii = width * actualHeight; i < ii; i++) {
|
|
22899
|
+
dest[destPos++] = rgbBuf[rgbPos++];
|
|
22900
|
+
dest[destPos++] = rgbBuf[rgbPos++];
|
|
22901
|
+
dest[destPos++] = rgbBuf[rgbPos++];
|
|
22902
|
+
destPos += alpha01;
|
|
22903
|
+
}
|
|
22904
|
+
}
|
|
22905
|
+
}
|
|
22906
|
+
}
|
|
22907
|
+
/**
|
|
22908
|
+
* True if the colorspace has components in the default range of [0, 1].
|
|
22909
|
+
* This should be true for all colorspaces except for lab color spaces
|
|
22910
|
+
* which are [0,100], [-128, 127], [-128, 127].
|
|
22911
|
+
*/
|
|
22912
|
+
get usesZeroToOneRange() {
|
|
22913
|
+
return shadow2(this, "usesZeroToOneRange", true);
|
|
22914
|
+
}
|
|
22915
|
+
/**
|
|
22916
|
+
* Checks if a decode map matches the default decode map for a color space.
|
|
22917
|
+
* This handles the general decode maps where there are two values per
|
|
22918
|
+
* component, e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
|
|
22919
|
+
* This does not handle Lab, Indexed, or Pattern decode maps since they are
|
|
22920
|
+
* slightly different.
|
|
22921
|
+
* @param {Array} decode - Decode map (usually from an image).
|
|
22922
|
+
* @param {number} numComps - Number of components the color space has.
|
|
22923
|
+
*/
|
|
22924
|
+
static isDefaultDecode(decode, numComps) {
|
|
22925
|
+
if (isDefaultDecodeHelper(decode, numComps * 2)) {
|
|
22926
|
+
return true;
|
|
22927
|
+
}
|
|
22928
|
+
for (let i = 0, ii = decode.length; i < ii; i += 2) {
|
|
22929
|
+
if (decode[i] !== 0 || decode[i + 1] !== 1) {
|
|
22930
|
+
return false;
|
|
22931
|
+
}
|
|
22932
|
+
}
|
|
22933
|
+
return true;
|
|
22934
|
+
}
|
|
22935
|
+
};
|
|
22936
|
+
var DeviceCmykCS = class extends ColorSpace {
|
|
22937
|
+
constructor() {
|
|
22938
|
+
super("DeviceCMYK", 4);
|
|
22939
|
+
}
|
|
22940
|
+
// The coefficients below was found using numerical analysis: the method of
|
|
22941
|
+
// steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
|
|
22942
|
+
// where color_value is the tabular value from the table of sampled RGB colors
|
|
22943
|
+
// from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
|
|
22944
|
+
// CMYK color conversion using the estimation below:
|
|
22945
|
+
// f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
|
|
22946
|
+
#toRgb(src, srcOffset, srcScale, dest, destOffset) {
|
|
22947
|
+
const c = src[srcOffset] * srcScale;
|
|
22948
|
+
const m = src[srcOffset + 1] * srcScale;
|
|
22949
|
+
const y = src[srcOffset + 2] * srcScale;
|
|
22950
|
+
const k = src[srcOffset + 3] * srcScale;
|
|
22951
|
+
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);
|
|
22952
|
+
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);
|
|
22953
|
+
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);
|
|
22954
|
+
}
|
|
22955
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
22956
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
22957
|
+
assert2(
|
|
22958
|
+
dest instanceof Uint8ClampedArray,
|
|
22959
|
+
'DeviceCmykCS.getRgbItem: Unsupported "dest" type.'
|
|
22960
|
+
);
|
|
22961
|
+
}
|
|
22962
|
+
this.#toRgb(src, srcOffset, 1, dest, destOffset);
|
|
22963
|
+
}
|
|
22964
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
22965
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
22966
|
+
assert2(
|
|
22967
|
+
dest instanceof Uint8ClampedArray,
|
|
22968
|
+
'DeviceCmykCS.getRgbBuffer: Unsupported "dest" type.'
|
|
22969
|
+
);
|
|
22970
|
+
}
|
|
22971
|
+
const scale = 1 / ((1 << bits) - 1);
|
|
22972
|
+
for (let i = 0; i < count; i++) {
|
|
22973
|
+
this.#toRgb(src, srcOffset, scale, dest, destOffset);
|
|
22974
|
+
srcOffset += 4;
|
|
22975
|
+
destOffset += 3 + alpha01;
|
|
22976
|
+
}
|
|
22977
|
+
}
|
|
22978
|
+
};
|
|
22979
|
+
var CalGrayCS = class extends ColorSpace {
|
|
22980
|
+
constructor(whitePoint, blackPoint, gamma) {
|
|
22981
|
+
super("CalGray", 1);
|
|
22982
|
+
if (!whitePoint) {
|
|
22983
|
+
throw new FormatError(
|
|
22984
|
+
"WhitePoint missing - required for color space CalGray"
|
|
22985
|
+
);
|
|
22986
|
+
}
|
|
22987
|
+
[this.XW, this.YW, this.ZW] = whitePoint;
|
|
22988
|
+
[this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
|
|
22989
|
+
this.G = gamma || 1;
|
|
22990
|
+
if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
|
|
22991
|
+
throw new FormatError(
|
|
22992
|
+
`Invalid WhitePoint components for ${this.name}, no fallback available`
|
|
22993
|
+
);
|
|
22994
|
+
}
|
|
22995
|
+
if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
|
|
22996
|
+
info(`Invalid BlackPoint for ${this.name}, falling back to default.`);
|
|
22997
|
+
this.XB = this.YB = this.ZB = 0;
|
|
22998
|
+
}
|
|
22999
|
+
if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
|
|
23000
|
+
warn2(
|
|
23001
|
+
`${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ZB: ${this.ZB}, only default values are supported.`
|
|
23002
|
+
);
|
|
23003
|
+
}
|
|
23004
|
+
if (this.G < 1) {
|
|
23005
|
+
info(
|
|
23006
|
+
`Invalid Gamma: ${this.G} for ${this.name}, falling back to default.`
|
|
23007
|
+
);
|
|
23008
|
+
this.G = 1;
|
|
23009
|
+
}
|
|
23010
|
+
}
|
|
23011
|
+
#toRgb(src, srcOffset, dest, destOffset, scale) {
|
|
23012
|
+
const A = src[srcOffset] * scale;
|
|
23013
|
+
const AG = A ** this.G;
|
|
23014
|
+
const L = this.YW * AG;
|
|
23015
|
+
const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0);
|
|
23016
|
+
dest[destOffset] = val;
|
|
23017
|
+
dest[destOffset + 1] = val;
|
|
23018
|
+
dest[destOffset + 2] = val;
|
|
23019
|
+
}
|
|
23020
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
23021
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
23022
|
+
assert2(
|
|
23023
|
+
dest instanceof Uint8ClampedArray,
|
|
23024
|
+
'CalGrayCS.getRgbItem: Unsupported "dest" type.'
|
|
23025
|
+
);
|
|
23026
|
+
}
|
|
23027
|
+
this.#toRgb(src, srcOffset, dest, destOffset, 1);
|
|
23028
|
+
}
|
|
23029
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
23030
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
23031
|
+
assert2(
|
|
23032
|
+
dest instanceof Uint8ClampedArray,
|
|
23033
|
+
'CalGrayCS.getRgbBuffer: Unsupported "dest" type.'
|
|
23034
|
+
);
|
|
23035
|
+
}
|
|
23036
|
+
const scale = 1 / ((1 << bits) - 1);
|
|
23037
|
+
for (let i = 0; i < count; ++i) {
|
|
23038
|
+
this.#toRgb(src, srcOffset, dest, destOffset, scale);
|
|
23039
|
+
srcOffset += 1;
|
|
23040
|
+
destOffset += 3 + alpha01;
|
|
23041
|
+
}
|
|
23042
|
+
}
|
|
23043
|
+
};
|
|
23044
|
+
var CalRGBCS = class _CalRGBCS extends ColorSpace {
|
|
23045
|
+
// See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these
|
|
23046
|
+
// matrices.
|
|
23047
|
+
// prettier-ignore
|
|
23048
|
+
static #BRADFORD_SCALE_MATRIX = new Float32Array([
|
|
23049
|
+
0.8951,
|
|
23050
|
+
0.2664,
|
|
23051
|
+
-0.1614,
|
|
23052
|
+
-0.7502,
|
|
23053
|
+
1.7135,
|
|
23054
|
+
0.0367,
|
|
23055
|
+
0.0389,
|
|
23056
|
+
-0.0685,
|
|
23057
|
+
1.0296
|
|
23058
|
+
]);
|
|
23059
|
+
// prettier-ignore
|
|
23060
|
+
static #BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([
|
|
23061
|
+
0.9869929,
|
|
23062
|
+
-0.1470543,
|
|
23063
|
+
0.1599627,
|
|
23064
|
+
0.4323053,
|
|
23065
|
+
0.5183603,
|
|
23066
|
+
0.0492912,
|
|
23067
|
+
-85287e-7,
|
|
23068
|
+
0.0400428,
|
|
23069
|
+
0.9684867
|
|
23070
|
+
]);
|
|
23071
|
+
// See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html.
|
|
23072
|
+
// prettier-ignore
|
|
23073
|
+
static #SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([
|
|
23074
|
+
3.2404542,
|
|
23075
|
+
-1.5371385,
|
|
23076
|
+
-0.4985314,
|
|
23077
|
+
-0.969266,
|
|
23078
|
+
1.8760108,
|
|
23079
|
+
0.041556,
|
|
23080
|
+
0.0556434,
|
|
23081
|
+
-0.2040259,
|
|
23082
|
+
1.0572252
|
|
23083
|
+
]);
|
|
23084
|
+
static #FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);
|
|
23085
|
+
static #tempNormalizeMatrix = new Float32Array(3);
|
|
23086
|
+
static #tempConvertMatrix1 = new Float32Array(3);
|
|
23087
|
+
static #tempConvertMatrix2 = new Float32Array(3);
|
|
23088
|
+
static #DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8;
|
|
23089
|
+
constructor(whitePoint, blackPoint, gamma, matrix) {
|
|
23090
|
+
super("CalRGB", 3);
|
|
23091
|
+
if (!whitePoint) {
|
|
23092
|
+
throw new FormatError(
|
|
23093
|
+
"WhitePoint missing - required for color space CalRGB"
|
|
23094
|
+
);
|
|
23095
|
+
}
|
|
23096
|
+
const [XW, YW, ZW] = this.whitePoint = whitePoint;
|
|
23097
|
+
const [XB, YB, ZB] = this.blackPoint = blackPoint || new Float32Array(3);
|
|
23098
|
+
[this.GR, this.GG, this.GB] = gamma || new Float32Array([1, 1, 1]);
|
|
23099
|
+
[
|
|
23100
|
+
this.MXA,
|
|
23101
|
+
this.MYA,
|
|
23102
|
+
this.MZA,
|
|
23103
|
+
this.MXB,
|
|
23104
|
+
this.MYB,
|
|
23105
|
+
this.MZB,
|
|
23106
|
+
this.MXC,
|
|
23107
|
+
this.MYC,
|
|
23108
|
+
this.MZC
|
|
23109
|
+
] = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
|
|
23110
|
+
if (XW < 0 || ZW < 0 || YW !== 1) {
|
|
23111
|
+
throw new FormatError(
|
|
23112
|
+
`Invalid WhitePoint components for ${this.name}, no fallback available`
|
|
23113
|
+
);
|
|
23114
|
+
}
|
|
23115
|
+
if (XB < 0 || YB < 0 || ZB < 0) {
|
|
23116
|
+
info(
|
|
23117
|
+
`Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], falling back to default.`
|
|
23118
|
+
);
|
|
23119
|
+
this.blackPoint = new Float32Array(3);
|
|
23120
|
+
}
|
|
23121
|
+
if (this.GR < 0 || this.GG < 0 || this.GB < 0) {
|
|
23122
|
+
info(
|
|
23123
|
+
`Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ${this.name}, falling back to default.`
|
|
23124
|
+
);
|
|
23125
|
+
this.GR = this.GG = this.GB = 1;
|
|
23126
|
+
}
|
|
23127
|
+
}
|
|
23128
|
+
#matrixProduct(a, b, result) {
|
|
23129
|
+
result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
23130
|
+
result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
|
|
23131
|
+
result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
|
|
23132
|
+
}
|
|
23133
|
+
#toFlat(sourceWhitePoint, LMS, result) {
|
|
23134
|
+
result[0] = LMS[0] * 1 / sourceWhitePoint[0];
|
|
23135
|
+
result[1] = LMS[1] * 1 / sourceWhitePoint[1];
|
|
23136
|
+
result[2] = LMS[2] * 1 / sourceWhitePoint[2];
|
|
23137
|
+
}
|
|
23138
|
+
#toD65(sourceWhitePoint, LMS, result) {
|
|
23139
|
+
const D65X = 0.95047;
|
|
23140
|
+
const D65Y = 1;
|
|
23141
|
+
const D65Z = 1.08883;
|
|
23142
|
+
result[0] = LMS[0] * D65X / sourceWhitePoint[0];
|
|
23143
|
+
result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
|
|
23144
|
+
result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
|
|
23145
|
+
}
|
|
23146
|
+
#sRGBTransferFunction(color) {
|
|
23147
|
+
if (color <= 31308e-7) {
|
|
23148
|
+
return MathClamp(12.92 * color, 0, 1);
|
|
23149
|
+
}
|
|
23150
|
+
return color >= 0.99554525 ? 1 : MathClamp((1 + 0.055) * color ** (1 / 2.4) - 0.055, 0, 1);
|
|
23151
|
+
}
|
|
23152
|
+
#decodeL(L) {
|
|
23153
|
+
if (L < 0) {
|
|
23154
|
+
return -this.#decodeL(-L);
|
|
23155
|
+
}
|
|
23156
|
+
return L > 8 ? ((L + 16) / 116) ** 3 : L * _CalRGBCS.#DECODE_L_CONSTANT;
|
|
23157
|
+
}
|
|
23158
|
+
#compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
|
|
23159
|
+
if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {
|
|
23160
|
+
result[0] = XYZ_Flat[0];
|
|
23161
|
+
result[1] = XYZ_Flat[1];
|
|
23162
|
+
result[2] = XYZ_Flat[2];
|
|
23163
|
+
return;
|
|
23164
|
+
}
|
|
23165
|
+
const zeroDecodeL = this.#decodeL(0);
|
|
23166
|
+
const X_DST = zeroDecodeL;
|
|
23167
|
+
const X_SRC = this.#decodeL(sourceBlackPoint[0]);
|
|
23168
|
+
const Y_DST = zeroDecodeL;
|
|
23169
|
+
const Y_SRC = this.#decodeL(sourceBlackPoint[1]);
|
|
23170
|
+
const Z_DST = zeroDecodeL;
|
|
23171
|
+
const Z_SRC = this.#decodeL(sourceBlackPoint[2]);
|
|
23172
|
+
const X_Scale = (1 - X_DST) / (1 - X_SRC);
|
|
23173
|
+
const X_Offset = 1 - X_Scale;
|
|
23174
|
+
const Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
|
|
23175
|
+
const Y_Offset = 1 - Y_Scale;
|
|
23176
|
+
const Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
|
|
23177
|
+
const Z_Offset = 1 - Z_Scale;
|
|
23178
|
+
result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
|
|
23179
|
+
result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
|
|
23180
|
+
result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
|
|
23181
|
+
}
|
|
23182
|
+
#normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
|
|
23183
|
+
if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
|
|
23184
|
+
result[0] = XYZ_In[0];
|
|
23185
|
+
result[1] = XYZ_In[1];
|
|
23186
|
+
result[2] = XYZ_In[2];
|
|
23187
|
+
return;
|
|
23188
|
+
}
|
|
23189
|
+
const LMS = result;
|
|
23190
|
+
this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
|
|
23191
|
+
const LMS_Flat = _CalRGBCS.#tempNormalizeMatrix;
|
|
23192
|
+
this.#toFlat(sourceWhitePoint, LMS, LMS_Flat);
|
|
23193
|
+
this.#matrixProduct(
|
|
23194
|
+
_CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
|
|
23195
|
+
LMS_Flat,
|
|
23196
|
+
result
|
|
23197
|
+
);
|
|
23198
|
+
}
|
|
23199
|
+
#normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
|
|
23200
|
+
const LMS = result;
|
|
23201
|
+
this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
|
|
23202
|
+
const LMS_D65 = _CalRGBCS.#tempNormalizeMatrix;
|
|
23203
|
+
this.#toD65(sourceWhitePoint, LMS, LMS_D65);
|
|
23204
|
+
this.#matrixProduct(
|
|
23205
|
+
_CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
|
|
23206
|
+
LMS_D65,
|
|
23207
|
+
result
|
|
23208
|
+
);
|
|
23209
|
+
}
|
|
23210
|
+
#toRgb(src, srcOffset, dest, destOffset, scale) {
|
|
23211
|
+
const A = MathClamp(src[srcOffset] * scale, 0, 1);
|
|
23212
|
+
const B = MathClamp(src[srcOffset + 1] * scale, 0, 1);
|
|
23213
|
+
const C = MathClamp(src[srcOffset + 2] * scale, 0, 1);
|
|
23214
|
+
const AGR = A === 1 ? 1 : A ** this.GR;
|
|
23215
|
+
const BGG = B === 1 ? 1 : B ** this.GG;
|
|
23216
|
+
const CGB = C === 1 ? 1 : C ** this.GB;
|
|
23217
|
+
const X = this.MXA * AGR + this.MXB * BGG + this.MXC * CGB;
|
|
23218
|
+
const Y = this.MYA * AGR + this.MYB * BGG + this.MYC * CGB;
|
|
23219
|
+
const Z = this.MZA * AGR + this.MZB * BGG + this.MZC * CGB;
|
|
23220
|
+
const XYZ = _CalRGBCS.#tempConvertMatrix1;
|
|
23221
|
+
XYZ[0] = X;
|
|
23222
|
+
XYZ[1] = Y;
|
|
23223
|
+
XYZ[2] = Z;
|
|
23224
|
+
const XYZ_Flat = _CalRGBCS.#tempConvertMatrix2;
|
|
23225
|
+
this.#normalizeWhitePointToFlat(this.whitePoint, XYZ, XYZ_Flat);
|
|
23226
|
+
const XYZ_Black = _CalRGBCS.#tempConvertMatrix1;
|
|
23227
|
+
this.#compensateBlackPoint(this.blackPoint, XYZ_Flat, XYZ_Black);
|
|
23228
|
+
const XYZ_D65 = _CalRGBCS.#tempConvertMatrix2;
|
|
23229
|
+
this.#normalizeWhitePointToD65(
|
|
23230
|
+
_CalRGBCS.#FLAT_WHITEPOINT_MATRIX,
|
|
23231
|
+
XYZ_Black,
|
|
23232
|
+
XYZ_D65
|
|
23233
|
+
);
|
|
23234
|
+
const SRGB = _CalRGBCS.#tempConvertMatrix1;
|
|
23235
|
+
this.#matrixProduct(_CalRGBCS.#SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
|
|
23236
|
+
dest[destOffset] = this.#sRGBTransferFunction(SRGB[0]) * 255;
|
|
23237
|
+
dest[destOffset + 1] = this.#sRGBTransferFunction(SRGB[1]) * 255;
|
|
23238
|
+
dest[destOffset + 2] = this.#sRGBTransferFunction(SRGB[2]) * 255;
|
|
23239
|
+
}
|
|
23240
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
23241
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
23242
|
+
assert2(
|
|
23243
|
+
dest instanceof Uint8ClampedArray,
|
|
23244
|
+
'CalRGBCS.getRgbItem: Unsupported "dest" type.'
|
|
23245
|
+
);
|
|
23246
|
+
}
|
|
23247
|
+
this.#toRgb(src, srcOffset, dest, destOffset, 1);
|
|
23248
|
+
}
|
|
23249
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
23250
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
23251
|
+
assert2(
|
|
23252
|
+
dest instanceof Uint8ClampedArray,
|
|
23253
|
+
'CalRGBCS.getRgbBuffer: Unsupported "dest" type.'
|
|
23254
|
+
);
|
|
23255
|
+
}
|
|
23256
|
+
const scale = 1 / ((1 << bits) - 1);
|
|
23257
|
+
for (let i = 0; i < count; ++i) {
|
|
23258
|
+
this.#toRgb(src, srcOffset, dest, destOffset, scale);
|
|
23259
|
+
srcOffset += 3;
|
|
23260
|
+
destOffset += 3 + alpha01;
|
|
23261
|
+
}
|
|
23262
|
+
}
|
|
23263
|
+
};
|
|
23264
|
+
var LabCS = class extends ColorSpace {
|
|
23265
|
+
constructor(whitePoint, blackPoint, range) {
|
|
23266
|
+
super("Lab", 3);
|
|
23267
|
+
if (!whitePoint) {
|
|
23268
|
+
throw new FormatError(
|
|
23269
|
+
"WhitePoint missing - required for color space Lab"
|
|
23270
|
+
);
|
|
23271
|
+
}
|
|
23272
|
+
[this.XW, this.YW, this.ZW] = whitePoint;
|
|
23273
|
+
[this.amin, this.amax, this.bmin, this.bmax] = range || [
|
|
23274
|
+
-100,
|
|
23275
|
+
100,
|
|
23276
|
+
-100,
|
|
23277
|
+
100
|
|
23278
|
+
];
|
|
23279
|
+
[this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
|
|
23280
|
+
if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
|
|
23281
|
+
throw new FormatError(
|
|
23282
|
+
"Invalid WhitePoint components, no fallback available"
|
|
23283
|
+
);
|
|
23284
|
+
}
|
|
23285
|
+
if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
|
|
23286
|
+
info("Invalid BlackPoint, falling back to default");
|
|
23287
|
+
this.XB = this.YB = this.ZB = 0;
|
|
23288
|
+
}
|
|
23289
|
+
if (this.amin > this.amax || this.bmin > this.bmax) {
|
|
23290
|
+
info("Invalid Range, falling back to defaults");
|
|
23291
|
+
this.amin = -100;
|
|
23292
|
+
this.amax = 100;
|
|
23293
|
+
this.bmin = -100;
|
|
23294
|
+
this.bmax = 100;
|
|
23295
|
+
}
|
|
23296
|
+
}
|
|
23297
|
+
// Function g(x) from spec
|
|
23298
|
+
#fn_g(x) {
|
|
23299
|
+
return x >= 6 / 29 ? x ** 3 : 108 / 841 * (x - 4 / 29);
|
|
23300
|
+
}
|
|
23301
|
+
#decode(value, high1, low2, high2) {
|
|
23302
|
+
return low2 + value * (high2 - low2) / high1;
|
|
23303
|
+
}
|
|
23304
|
+
// If decoding is needed maxVal should be 2^bits per component - 1.
|
|
23305
|
+
#toRgb(src, srcOffset, maxVal, dest, destOffset) {
|
|
23306
|
+
let Ls = src[srcOffset];
|
|
23307
|
+
let as = src[srcOffset + 1];
|
|
23308
|
+
let bs = src[srcOffset + 2];
|
|
23309
|
+
if (maxVal !== false) {
|
|
23310
|
+
Ls = this.#decode(Ls, maxVal, 0, 100);
|
|
23311
|
+
as = this.#decode(as, maxVal, this.amin, this.amax);
|
|
23312
|
+
bs = this.#decode(bs, maxVal, this.bmin, this.bmax);
|
|
23313
|
+
}
|
|
23314
|
+
if (as > this.amax) {
|
|
23315
|
+
as = this.amax;
|
|
23316
|
+
} else if (as < this.amin) {
|
|
23317
|
+
as = this.amin;
|
|
23318
|
+
}
|
|
23319
|
+
if (bs > this.bmax) {
|
|
23320
|
+
bs = this.bmax;
|
|
23321
|
+
} else if (bs < this.bmin) {
|
|
23322
|
+
bs = this.bmin;
|
|
23323
|
+
}
|
|
23324
|
+
const M = (Ls + 16) / 116;
|
|
23325
|
+
const L = M + as / 500;
|
|
23326
|
+
const N = M - bs / 200;
|
|
23327
|
+
const X = this.XW * this.#fn_g(L);
|
|
23328
|
+
const Y = this.YW * this.#fn_g(M);
|
|
23329
|
+
const Z = this.ZW * this.#fn_g(N);
|
|
23330
|
+
let r, g, b;
|
|
23331
|
+
if (this.ZW < 1) {
|
|
23332
|
+
r = X * 3.1339 + Y * -1.617 + Z * -0.4906;
|
|
23333
|
+
g = X * -0.9785 + Y * 1.916 + Z * 0.0333;
|
|
23334
|
+
b = X * 0.072 + Y * -0.229 + Z * 1.4057;
|
|
23335
|
+
} else {
|
|
23336
|
+
r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
|
|
23337
|
+
g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
|
|
23338
|
+
b = X * 0.0557 + Y * -0.204 + Z * 1.057;
|
|
23339
|
+
}
|
|
23340
|
+
dest[destOffset] = Math.sqrt(r) * 255;
|
|
23341
|
+
dest[destOffset + 1] = Math.sqrt(g) * 255;
|
|
23342
|
+
dest[destOffset + 2] = Math.sqrt(b) * 255;
|
|
23343
|
+
}
|
|
23344
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
23345
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
23346
|
+
assert2(
|
|
23347
|
+
dest instanceof Uint8ClampedArray,
|
|
23348
|
+
'LabCS.getRgbItem: Unsupported "dest" type.'
|
|
23349
|
+
);
|
|
23350
|
+
}
|
|
23351
|
+
this.#toRgb(src, srcOffset, false, dest, destOffset);
|
|
23352
|
+
}
|
|
23353
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
23354
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
23355
|
+
assert2(
|
|
23356
|
+
dest instanceof Uint8ClampedArray,
|
|
23357
|
+
'LabCS.getRgbBuffer: Unsupported "dest" type.'
|
|
23358
|
+
);
|
|
23359
|
+
}
|
|
23360
|
+
const maxVal = (1 << bits) - 1;
|
|
23361
|
+
for (let i = 0; i < count; i++) {
|
|
23362
|
+
this.#toRgb(src, srcOffset, maxVal, dest, destOffset);
|
|
23363
|
+
srcOffset += 3;
|
|
23364
|
+
destOffset += 3 + alpha01;
|
|
23365
|
+
}
|
|
23366
|
+
}
|
|
23367
|
+
isDefaultDecode(decode, bpc) {
|
|
23368
|
+
return true;
|
|
23369
|
+
}
|
|
23370
|
+
get usesZeroToOneRange() {
|
|
23371
|
+
return shadow2(this, "usesZeroToOneRange", false);
|
|
23372
|
+
}
|
|
23373
|
+
};
|
|
23374
|
+
var TOKEN = {
|
|
23375
|
+
// Structural tokens — not keyword operators
|
|
23376
|
+
number: 0,
|
|
23377
|
+
lbrace: 1,
|
|
23378
|
+
rbrace: 2,
|
|
23379
|
+
// Boolean literals
|
|
23380
|
+
true: 3,
|
|
23381
|
+
false: 4,
|
|
23382
|
+
// Arithmetic binary operators
|
|
23383
|
+
add: 5,
|
|
23384
|
+
sub: 6,
|
|
23385
|
+
mul: 7,
|
|
23386
|
+
div: 8,
|
|
23387
|
+
idiv: 9,
|
|
23388
|
+
mod: 10,
|
|
23389
|
+
exp: 11,
|
|
23390
|
+
// Comparison binary operators
|
|
23391
|
+
eq: 12,
|
|
23392
|
+
ne: 13,
|
|
23393
|
+
gt: 14,
|
|
23394
|
+
ge: 15,
|
|
23395
|
+
lt: 16,
|
|
23396
|
+
le: 17,
|
|
23397
|
+
// Bitwise / boolean binary operators
|
|
23398
|
+
and: 18,
|
|
23399
|
+
or: 19,
|
|
23400
|
+
xor: 20,
|
|
23401
|
+
bitshift: 21,
|
|
23402
|
+
// Unary arithmetic operators
|
|
23403
|
+
abs: 22,
|
|
23404
|
+
neg: 23,
|
|
23405
|
+
ceiling: 24,
|
|
23406
|
+
floor: 25,
|
|
23407
|
+
round: 26,
|
|
23408
|
+
truncate: 27,
|
|
23409
|
+
// Unary boolean / bitwise operator
|
|
23410
|
+
not: 28,
|
|
23411
|
+
// Mathematical functions — unary
|
|
23412
|
+
sqrt: 29,
|
|
23413
|
+
sin: 30,
|
|
23414
|
+
cos: 31,
|
|
23415
|
+
ln: 32,
|
|
23416
|
+
log: 33,
|
|
23417
|
+
// Mathematical function — binary
|
|
23418
|
+
atan: 34,
|
|
23419
|
+
// Type conversion operators
|
|
23420
|
+
cvi: 35,
|
|
23421
|
+
cvr: 36,
|
|
23422
|
+
// Stack operators
|
|
23423
|
+
dup: 37,
|
|
23424
|
+
exch: 38,
|
|
23425
|
+
pop: 39,
|
|
23426
|
+
copy: 40,
|
|
23427
|
+
index: 41,
|
|
23428
|
+
roll: 42,
|
|
23429
|
+
// Control flow
|
|
23430
|
+
if: 43,
|
|
23431
|
+
ifelse: 44,
|
|
23432
|
+
// End of input
|
|
23433
|
+
eof: 45,
|
|
23434
|
+
// Synthetic: produced by the optimizer, never emitted by the lexer.
|
|
23435
|
+
min: 46,
|
|
23436
|
+
max: 47
|
|
23437
|
+
};
|
|
23438
|
+
var Token = class {
|
|
23439
|
+
constructor(id, value = null) {
|
|
23440
|
+
this.id = id;
|
|
23441
|
+
this.value = value;
|
|
23442
|
+
}
|
|
23443
|
+
};
|
|
23444
|
+
var Lexer = class _Lexer {
|
|
23445
|
+
// Singletons for every non-number token, built lazily on first construction.
|
|
23446
|
+
// Keyword operator tokens carry their name as `value`; structural tokens
|
|
23447
|
+
// (lbrace, rbrace, eof) carry null.
|
|
23448
|
+
static #singletons = null;
|
|
23449
|
+
static #operatorSingletons = null;
|
|
23450
|
+
static #initSingletons() {
|
|
23451
|
+
const singletons = /* @__PURE__ */ Object.create(null);
|
|
23452
|
+
const operatorSingletons = /* @__PURE__ */ Object.create(null);
|
|
23453
|
+
for (const [name, id] of Object.entries(TOKEN)) {
|
|
23454
|
+
if (name === "number") {
|
|
23455
|
+
continue;
|
|
23456
|
+
}
|
|
23457
|
+
const isOperator = id >= TOKEN.true && id <= TOKEN.ifelse;
|
|
23458
|
+
const token = new Token(id, isOperator ? name : null);
|
|
23459
|
+
singletons[name] = token;
|
|
23460
|
+
if (isOperator) {
|
|
23461
|
+
operatorSingletons[name] = token;
|
|
23462
|
+
}
|
|
23463
|
+
}
|
|
23464
|
+
this.#singletons = singletons;
|
|
23465
|
+
this.#operatorSingletons = operatorSingletons;
|
|
23466
|
+
}
|
|
23467
|
+
constructor(data) {
|
|
23468
|
+
if (!_Lexer.#singletons) {
|
|
23469
|
+
_Lexer.#initSingletons();
|
|
23470
|
+
}
|
|
23471
|
+
this.data = data;
|
|
23472
|
+
this.pos = 0;
|
|
23473
|
+
this.len = data.length;
|
|
23474
|
+
this._numberPattern = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/iy;
|
|
23475
|
+
this._identifierPattern = /[a-z]+/y;
|
|
23476
|
+
}
|
|
23477
|
+
// Skip a % comment, advancing past the next \n or \r (or to EOF).
|
|
23478
|
+
_skipComment() {
|
|
23479
|
+
const lf = this.data.indexOf("\n", this.pos);
|
|
23480
|
+
const cr = this.data.indexOf("\r", this.pos);
|
|
23481
|
+
const eol = Math.min(lf < 0 ? this.len : lf, cr < 0 ? this.len : cr);
|
|
23482
|
+
this.pos = Math.min(eol + 1, this.len);
|
|
23483
|
+
}
|
|
23484
|
+
_getNumber() {
|
|
23485
|
+
this._numberPattern.lastIndex = this.pos;
|
|
23486
|
+
const match = this._numberPattern.exec(this.data);
|
|
23487
|
+
if (!match) {
|
|
23488
|
+
return new Token(TOKEN.number, 0);
|
|
23489
|
+
}
|
|
23490
|
+
const number = parseFloat(match[0]);
|
|
23491
|
+
if (!Number.isFinite(number)) {
|
|
23492
|
+
return new Token(TOKEN.number, 0);
|
|
23493
|
+
}
|
|
23494
|
+
this.pos = this._numberPattern.lastIndex;
|
|
23495
|
+
return new Token(TOKEN.number, number);
|
|
23496
|
+
}
|
|
23497
|
+
_getOperator() {
|
|
23498
|
+
this._identifierPattern.lastIndex = this.pos;
|
|
23499
|
+
const match = this._identifierPattern.exec(this.data);
|
|
23500
|
+
if (!match) {
|
|
23501
|
+
return new Token(TOKEN.number, 0);
|
|
23502
|
+
}
|
|
23503
|
+
this.pos = this._identifierPattern.lastIndex;
|
|
23504
|
+
const op = match[0];
|
|
23505
|
+
const token = _Lexer.#operatorSingletons[op];
|
|
23506
|
+
return token ?? new Token(TOKEN.number, 0);
|
|
23507
|
+
}
|
|
23508
|
+
// Return the next token, or Lexer.#singletons.eof at end of input.
|
|
23509
|
+
next() {
|
|
23510
|
+
while (this.pos < this.len) {
|
|
23511
|
+
const ch3 = this.data.charCodeAt(this.pos++);
|
|
23512
|
+
switch (ch3) {
|
|
23513
|
+
// PostScript white-space characters (PDF32000 §7.2.2)
|
|
23514
|
+
case 0:
|
|
23515
|
+
case 9:
|
|
23516
|
+
case 10:
|
|
23517
|
+
case 12:
|
|
23518
|
+
case 13:
|
|
23519
|
+
case 32:
|
|
23520
|
+
break;
|
|
23521
|
+
case 37:
|
|
23522
|
+
this._skipComment();
|
|
23523
|
+
break;
|
|
23524
|
+
case 123:
|
|
23525
|
+
return _Lexer.#singletons.lbrace;
|
|
23526
|
+
case 125:
|
|
23527
|
+
return _Lexer.#singletons.rbrace;
|
|
23528
|
+
case 43:
|
|
23529
|
+
case 45:
|
|
23530
|
+
this.pos--;
|
|
23531
|
+
return this._getNumber();
|
|
23532
|
+
case 46:
|
|
23533
|
+
this.pos--;
|
|
23534
|
+
return this._getNumber();
|
|
23535
|
+
default:
|
|
23536
|
+
if (ch3 >= 48 && ch3 <= 57) {
|
|
23537
|
+
this.pos--;
|
|
23538
|
+
return this._getNumber();
|
|
23539
|
+
}
|
|
23540
|
+
if (ch3 >= 97 && ch3 <= 122) {
|
|
23541
|
+
this.pos--;
|
|
23542
|
+
return this._getOperator();
|
|
23543
|
+
}
|
|
23544
|
+
return new Token(TOKEN.number, 0);
|
|
23545
|
+
}
|
|
23546
|
+
}
|
|
23547
|
+
return _Lexer.#singletons.eof;
|
|
23548
|
+
}
|
|
23549
|
+
};
|
|
23550
|
+
var PS_VALUE_TYPE = {
|
|
23551
|
+
numeric: 0,
|
|
23552
|
+
// known to be a number (f64 in Wasm)
|
|
23553
|
+
boolean: 1,
|
|
23554
|
+
// known to be a boolean (0.0 = false, 1.0 = true in f64)
|
|
23555
|
+
unknown: 2
|
|
23556
|
+
// indeterminate at compile time
|
|
23557
|
+
};
|
|
23558
|
+
var PS_NODE = {
|
|
23559
|
+
// Parser AST node types (produced by Parser / parsePostScriptFunction)
|
|
23560
|
+
program: 0,
|
|
23561
|
+
block: 1,
|
|
23562
|
+
number: 2,
|
|
23563
|
+
operator: 3,
|
|
23564
|
+
if: 4,
|
|
23565
|
+
ifelse: 5,
|
|
23566
|
+
// Tree AST node types (produced by PSStackToTree)
|
|
23567
|
+
arg: 6,
|
|
23568
|
+
const: 7,
|
|
23569
|
+
unary: 8,
|
|
23570
|
+
binary: 9,
|
|
23571
|
+
ternary: 10
|
|
23572
|
+
};
|
|
23573
|
+
var PsNode = class {
|
|
23574
|
+
constructor(type) {
|
|
23575
|
+
this.type = type;
|
|
23576
|
+
}
|
|
23577
|
+
};
|
|
23578
|
+
var PsProgram = class extends PsNode {
|
|
23579
|
+
constructor(body) {
|
|
23580
|
+
super(PS_NODE.program);
|
|
23581
|
+
this.body = body;
|
|
23582
|
+
}
|
|
23583
|
+
};
|
|
23584
|
+
var PsBlock = class extends PsNode {
|
|
23585
|
+
constructor(instructions) {
|
|
23586
|
+
super(PS_NODE.block);
|
|
23587
|
+
this.instructions = instructions;
|
|
23588
|
+
}
|
|
23589
|
+
};
|
|
23590
|
+
var PsNumber = class extends PsNode {
|
|
23591
|
+
/** @param {number} value */
|
|
23592
|
+
constructor(value) {
|
|
23593
|
+
super(PS_NODE.number);
|
|
23594
|
+
this.value = value;
|
|
23595
|
+
}
|
|
23596
|
+
};
|
|
23597
|
+
var PsOperator = class extends PsNode {
|
|
23598
|
+
/** @param {number} op — one of the TOKEN.* constants from lexer.js */
|
|
23599
|
+
constructor(op) {
|
|
23600
|
+
super(PS_NODE.operator);
|
|
23601
|
+
this.op = op;
|
|
23602
|
+
}
|
|
23603
|
+
};
|
|
23604
|
+
var PsIf = class extends PsNode {
|
|
23605
|
+
/** @param {PsBlock} then */
|
|
23606
|
+
constructor(then) {
|
|
23607
|
+
super(PS_NODE.if);
|
|
23608
|
+
this.then = then;
|
|
23609
|
+
}
|
|
23610
|
+
};
|
|
23611
|
+
var PsIfElse = class extends PsNode {
|
|
23612
|
+
/**
|
|
23613
|
+
* @param {PsBlock} then
|
|
23614
|
+
* @param {PsBlock} otherwise
|
|
23615
|
+
*/
|
|
23616
|
+
constructor(then, otherwise) {
|
|
23617
|
+
super(PS_NODE.ifelse);
|
|
23618
|
+
this.then = then;
|
|
23619
|
+
this.otherwise = otherwise;
|
|
23620
|
+
}
|
|
23621
|
+
};
|
|
23622
|
+
var PsArgNode = class extends PsNode {
|
|
23623
|
+
/** @param {number} index */
|
|
23624
|
+
constructor(index) {
|
|
23625
|
+
super(PS_NODE.arg);
|
|
23626
|
+
this.index = index;
|
|
23627
|
+
this.valueType = PS_VALUE_TYPE.numeric;
|
|
23628
|
+
}
|
|
23629
|
+
};
|
|
23630
|
+
var PsConstNode = class extends PsNode {
|
|
23631
|
+
/** @param {number|boolean} value */
|
|
23632
|
+
constructor(value) {
|
|
23633
|
+
super(PS_NODE.const);
|
|
23634
|
+
this.value = value;
|
|
23635
|
+
this.valueType = typeof value === "boolean" ? PS_VALUE_TYPE.boolean : PS_VALUE_TYPE.numeric;
|
|
23636
|
+
}
|
|
23637
|
+
};
|
|
23638
|
+
var PsUnaryNode = class extends PsNode {
|
|
23639
|
+
/**
|
|
23640
|
+
* @param {number} op — TOKEN.* constant
|
|
23641
|
+
* @param {PsNode} operand
|
|
23642
|
+
* @param {number} [valueType]
|
|
23643
|
+
*/
|
|
23644
|
+
constructor(op, operand, valueType = PS_VALUE_TYPE.unknown) {
|
|
23645
|
+
super(PS_NODE.unary);
|
|
23646
|
+
this.op = op;
|
|
23647
|
+
this.operand = operand;
|
|
23648
|
+
this.valueType = valueType;
|
|
23649
|
+
}
|
|
23650
|
+
};
|
|
23651
|
+
var PsBinaryNode = class extends PsNode {
|
|
23652
|
+
/**
|
|
23653
|
+
* @param {number} op — TOKEN.* constant
|
|
23654
|
+
* @param {PsNode} first — was on top of stack
|
|
23655
|
+
* @param {PsNode} second — was below top
|
|
23656
|
+
* @param {number} [valueType]
|
|
23657
|
+
*/
|
|
23658
|
+
constructor(op, first, second, valueType = PS_VALUE_TYPE.unknown) {
|
|
23659
|
+
super(PS_NODE.binary);
|
|
23660
|
+
this.op = op;
|
|
23661
|
+
this.first = first;
|
|
23662
|
+
this.second = second;
|
|
23663
|
+
this.valueType = valueType;
|
|
23664
|
+
}
|
|
23665
|
+
};
|
|
23666
|
+
var PsTernaryNode = class extends PsNode {
|
|
23667
|
+
/**
|
|
23668
|
+
* @param {PsNode} cond
|
|
23669
|
+
* @param {PsNode} then
|
|
23670
|
+
* @param {PsNode} otherwise
|
|
23671
|
+
* @param {number} [valueType]
|
|
23672
|
+
*/
|
|
23673
|
+
constructor(cond, then, otherwise, valueType = PS_VALUE_TYPE.unknown) {
|
|
23674
|
+
super(PS_NODE.ternary);
|
|
23675
|
+
this.cond = cond;
|
|
23676
|
+
this.then = then;
|
|
23677
|
+
this.otherwise = otherwise;
|
|
23678
|
+
this.valueType = valueType;
|
|
23679
|
+
}
|
|
23680
|
+
};
|
|
23681
|
+
var Parser = class _Parser {
|
|
23682
|
+
constructor(lexer) {
|
|
23683
|
+
this.lexer = lexer;
|
|
23684
|
+
this._token = null;
|
|
23685
|
+
}
|
|
23686
|
+
static _isRegularOperator(id) {
|
|
23687
|
+
return id >= TOKEN.true && id < TOKEN.if;
|
|
23688
|
+
}
|
|
23689
|
+
// Fetch the next token from the lexer.
|
|
23690
|
+
_advance() {
|
|
23691
|
+
this._token = this.lexer.next();
|
|
23692
|
+
}
|
|
23693
|
+
// Assert that the current token has the given id, consume it, and return it.
|
|
23694
|
+
_expect(id) {
|
|
23695
|
+
if (this._token.id !== id) {
|
|
23696
|
+
throw new FormatError(
|
|
23697
|
+
`PostScript function: expected token id ${id}, got ${this._token.id}.`
|
|
23698
|
+
);
|
|
23699
|
+
}
|
|
23700
|
+
const tok = this._token;
|
|
23701
|
+
this._advance();
|
|
23702
|
+
return tok;
|
|
23703
|
+
}
|
|
23704
|
+
/**
|
|
23705
|
+
* Parse the full Type 4 function body.
|
|
23706
|
+
*
|
|
23707
|
+
* Grammar (simplified):
|
|
23708
|
+
* program ::= '{' block '}'
|
|
23709
|
+
* block ::= instruction*
|
|
23710
|
+
* instruction ::= number
|
|
23711
|
+
* | operator (any PS_OPERATOR except if / ifelse)
|
|
23712
|
+
* | '{' block '}' 'if'
|
|
23713
|
+
* | '{' block '}' '{' block '}' 'ifelse'
|
|
23714
|
+
* @returns {PsProgram}
|
|
23715
|
+
*/
|
|
23716
|
+
parse() {
|
|
23717
|
+
this._advance();
|
|
23718
|
+
this._expect(TOKEN.lbrace);
|
|
23719
|
+
const block = this._parseBlock();
|
|
23720
|
+
this._expect(TOKEN.rbrace);
|
|
23721
|
+
if (this._token.id !== TOKEN.eof) {
|
|
23722
|
+
warn2("PostScript function: unexpected content after closing brace.");
|
|
23723
|
+
}
|
|
23724
|
+
return new PsProgram(block);
|
|
23725
|
+
}
|
|
23726
|
+
_parseBlock() {
|
|
23727
|
+
const instructions = [];
|
|
23728
|
+
while (true) {
|
|
23729
|
+
const tok = this._token;
|
|
23730
|
+
switch (tok.id) {
|
|
23731
|
+
case TOKEN.number:
|
|
23732
|
+
instructions.push(new PsNumber(tok.value));
|
|
23733
|
+
this._advance();
|
|
23734
|
+
break;
|
|
23735
|
+
case TOKEN.lbrace: {
|
|
23736
|
+
this._advance();
|
|
23737
|
+
const thenBlock = this._parseBlock();
|
|
23738
|
+
this._expect(TOKEN.rbrace);
|
|
23739
|
+
if (this._token.id === TOKEN.if) {
|
|
23740
|
+
this._advance();
|
|
23741
|
+
instructions.push(new PsIf(thenBlock));
|
|
23742
|
+
} else if (this._token.id === TOKEN.lbrace) {
|
|
23743
|
+
this._advance();
|
|
23744
|
+
const elseBlock = this._parseBlock();
|
|
23745
|
+
this._expect(TOKEN.rbrace);
|
|
23746
|
+
this._expect(TOKEN.ifelse);
|
|
23747
|
+
instructions.push(new PsIfElse(thenBlock, elseBlock));
|
|
23748
|
+
} else {
|
|
23749
|
+
throw new FormatError(
|
|
23750
|
+
"PostScript function: a procedure block must be followed by 'if' or '{\u2026} ifelse'."
|
|
23751
|
+
);
|
|
23752
|
+
}
|
|
23753
|
+
break;
|
|
23754
|
+
}
|
|
23755
|
+
case TOKEN.rbrace:
|
|
23756
|
+
case TOKEN.eof:
|
|
23757
|
+
return new PsBlock(instructions);
|
|
23758
|
+
case TOKEN.if:
|
|
23759
|
+
case TOKEN.ifelse:
|
|
23760
|
+
throw new FormatError(
|
|
23761
|
+
`PostScript function: unexpected '${tok.value}' operator.`
|
|
23762
|
+
);
|
|
23763
|
+
default:
|
|
23764
|
+
if (_Parser._isRegularOperator(tok.id)) {
|
|
23765
|
+
instructions.push(new PsOperator(tok.id));
|
|
23766
|
+
this._advance();
|
|
23767
|
+
break;
|
|
23768
|
+
}
|
|
23769
|
+
throw new FormatError(
|
|
23770
|
+
`PostScript function: unexpected token id ${tok.id}.`
|
|
23771
|
+
);
|
|
23772
|
+
}
|
|
23773
|
+
}
|
|
23774
|
+
}
|
|
23775
|
+
};
|
|
23776
|
+
function parsePostScriptFunction(source) {
|
|
23777
|
+
return new Parser(new Lexer(source)).parse();
|
|
23778
|
+
}
|
|
23779
|
+
function _nodesEqual(a, b) {
|
|
23780
|
+
if (a === b) {
|
|
23781
|
+
return true;
|
|
23782
|
+
}
|
|
23783
|
+
if (a.type !== b.type) {
|
|
23784
|
+
return false;
|
|
23785
|
+
}
|
|
23786
|
+
switch (a.type) {
|
|
23787
|
+
case PS_NODE.arg:
|
|
23788
|
+
return a.index === b.index;
|
|
23789
|
+
case PS_NODE.const:
|
|
23790
|
+
return a.value === b.value;
|
|
23791
|
+
case PS_NODE.unary:
|
|
23792
|
+
return a.op === b.op && _nodesEqual(a.operand, b.operand);
|
|
23793
|
+
case PS_NODE.binary:
|
|
23794
|
+
return a.op === b.op && _nodesEqual(a.first, b.first) && _nodesEqual(a.second, b.second);
|
|
23795
|
+
case PS_NODE.ternary:
|
|
23796
|
+
return _nodesEqual(a.cond, b.cond) && _nodesEqual(a.then, b.then) && _nodesEqual(a.otherwise, b.otherwise);
|
|
23797
|
+
default:
|
|
23798
|
+
return false;
|
|
23799
|
+
}
|
|
23800
|
+
}
|
|
23801
|
+
function _evalBinaryConst(op, a, b) {
|
|
23802
|
+
switch (op) {
|
|
23803
|
+
case TOKEN.add:
|
|
23804
|
+
return a + b;
|
|
23805
|
+
case TOKEN.sub:
|
|
23806
|
+
return a - b;
|
|
23807
|
+
case TOKEN.mul:
|
|
23808
|
+
return a * b;
|
|
23809
|
+
case TOKEN.div:
|
|
23810
|
+
return b !== 0 ? a / b : 0;
|
|
23811
|
+
// div by zero → 0
|
|
23812
|
+
case TOKEN.idiv:
|
|
23813
|
+
return b !== 0 ? Math.trunc(a / b) : 0;
|
|
23814
|
+
// div by zero → 0
|
|
23815
|
+
case TOKEN.mod:
|
|
23816
|
+
return b !== 0 ? a - Math.trunc(a / b) * b : 0;
|
|
23817
|
+
// div by zero → 0
|
|
23818
|
+
case TOKEN.exp: {
|
|
23819
|
+
const r = a ** b;
|
|
23820
|
+
return Number.isFinite(r) ? r : void 0;
|
|
23821
|
+
}
|
|
23822
|
+
case TOKEN.atan: {
|
|
23823
|
+
let deg = Math.atan2(a, b) * (180 / Math.PI);
|
|
23824
|
+
if (deg < 0) {
|
|
23825
|
+
deg += 360;
|
|
23826
|
+
}
|
|
23827
|
+
return deg;
|
|
23828
|
+
}
|
|
23829
|
+
case TOKEN.eq:
|
|
23830
|
+
return a === b;
|
|
23831
|
+
case TOKEN.ne:
|
|
23832
|
+
return a !== b;
|
|
23833
|
+
case TOKEN.gt:
|
|
23834
|
+
return a > b;
|
|
23835
|
+
case TOKEN.ge:
|
|
23836
|
+
return a >= b;
|
|
23837
|
+
case TOKEN.lt:
|
|
23838
|
+
return a < b;
|
|
23839
|
+
case TOKEN.le:
|
|
23840
|
+
return a <= b;
|
|
23841
|
+
case TOKEN.and:
|
|
23842
|
+
return typeof a === "boolean" ? a && b : a & b | 0;
|
|
23843
|
+
case TOKEN.or:
|
|
23844
|
+
return typeof a === "boolean" ? a || b : a | b | 0;
|
|
23845
|
+
case TOKEN.xor:
|
|
23846
|
+
return typeof a === "boolean" ? a !== b : a ^ b | 0;
|
|
23847
|
+
case TOKEN.bitshift:
|
|
23848
|
+
return b >= 0 ? a << b | 0 : a >> -b | 0;
|
|
23849
|
+
case TOKEN.min:
|
|
23850
|
+
return Math.min(a, b);
|
|
23851
|
+
case TOKEN.max:
|
|
23852
|
+
return Math.max(a, b);
|
|
23853
|
+
default:
|
|
23854
|
+
return void 0;
|
|
23855
|
+
}
|
|
23856
|
+
}
|
|
23857
|
+
function _evalUnaryConst(op, v) {
|
|
23858
|
+
switch (op) {
|
|
23859
|
+
case TOKEN.abs:
|
|
23860
|
+
return Math.abs(v);
|
|
23861
|
+
case TOKEN.neg:
|
|
23862
|
+
return -v;
|
|
23863
|
+
case TOKEN.ceiling:
|
|
23864
|
+
return Math.ceil(v);
|
|
23865
|
+
case TOKEN.floor:
|
|
23866
|
+
return Math.floor(v);
|
|
23867
|
+
case TOKEN.round:
|
|
23868
|
+
return Math.round(v);
|
|
23869
|
+
case TOKEN.truncate:
|
|
23870
|
+
return Math.trunc(v);
|
|
23871
|
+
case TOKEN.sqrt: {
|
|
23872
|
+
const r = Math.sqrt(v);
|
|
23873
|
+
return Number.isFinite(r) ? r : void 0;
|
|
23874
|
+
}
|
|
23875
|
+
case TOKEN.sin:
|
|
23876
|
+
return Math.sin(v % 360 * Math.PI / 180);
|
|
23877
|
+
case TOKEN.cos:
|
|
23878
|
+
return Math.cos(v % 360 * Math.PI / 180);
|
|
23879
|
+
case TOKEN.ln: {
|
|
23880
|
+
const r = Math.log(v);
|
|
23881
|
+
return Number.isFinite(r) ? r : void 0;
|
|
23882
|
+
}
|
|
23883
|
+
case TOKEN.log: {
|
|
23884
|
+
const r = Math.log10(v);
|
|
23885
|
+
return Number.isFinite(r) ? r : void 0;
|
|
23886
|
+
}
|
|
23887
|
+
case TOKEN.cvi:
|
|
23888
|
+
return Math.trunc(v);
|
|
23889
|
+
case TOKEN.cvr:
|
|
23890
|
+
return v;
|
|
23891
|
+
case TOKEN.not:
|
|
23892
|
+
return typeof v === "boolean" ? !v : ~v;
|
|
23893
|
+
default:
|
|
23894
|
+
return void 0;
|
|
23895
|
+
}
|
|
23896
|
+
}
|
|
23897
|
+
var MAX_STACK_SIZE = 100;
|
|
23898
|
+
function _unaryValueType(op, operandType) {
|
|
23899
|
+
return op === TOKEN.not ? operandType : PS_VALUE_TYPE.numeric;
|
|
23900
|
+
}
|
|
23901
|
+
function _binaryValueType(op, firstType, secondType) {
|
|
23902
|
+
switch (op) {
|
|
23903
|
+
// Comparison operators always produce a boolean.
|
|
23904
|
+
case TOKEN.eq:
|
|
23905
|
+
case TOKEN.ne:
|
|
23906
|
+
case TOKEN.gt:
|
|
23907
|
+
case TOKEN.ge:
|
|
23908
|
+
case TOKEN.lt:
|
|
23909
|
+
case TOKEN.le:
|
|
23910
|
+
return PS_VALUE_TYPE.boolean;
|
|
23911
|
+
// and / or / xor preserve the type when both operands are the same known
|
|
23912
|
+
// type (both boolean or both numeric); otherwise the type is unknown.
|
|
23913
|
+
case TOKEN.and:
|
|
23914
|
+
case TOKEN.or:
|
|
23915
|
+
case TOKEN.xor:
|
|
23916
|
+
return firstType === secondType && firstType !== PS_VALUE_TYPE.unknown ? firstType : PS_VALUE_TYPE.unknown;
|
|
23917
|
+
// All arithmetic / bitshift operators produce a numeric result.
|
|
23918
|
+
default:
|
|
23919
|
+
return PS_VALUE_TYPE.numeric;
|
|
23920
|
+
}
|
|
23921
|
+
}
|
|
23922
|
+
var PSStackToTree = class _PSStackToTree {
|
|
23923
|
+
static #binaryOps = null;
|
|
23924
|
+
static #unaryOps = null;
|
|
23925
|
+
static #idempotentUnary = null;
|
|
23926
|
+
static #negatedComparison = null;
|
|
23927
|
+
static #init() {
|
|
23928
|
+
this.#binaryOps = /* @__PURE__ */ new Set([
|
|
23929
|
+
TOKEN.add,
|
|
23930
|
+
TOKEN.sub,
|
|
23931
|
+
TOKEN.mul,
|
|
23932
|
+
TOKEN.div,
|
|
23933
|
+
TOKEN.idiv,
|
|
23934
|
+
TOKEN.mod,
|
|
23935
|
+
TOKEN.exp,
|
|
23936
|
+
TOKEN.atan,
|
|
23937
|
+
TOKEN.eq,
|
|
23938
|
+
TOKEN.ne,
|
|
23939
|
+
TOKEN.gt,
|
|
23940
|
+
TOKEN.ge,
|
|
23941
|
+
TOKEN.lt,
|
|
23942
|
+
TOKEN.le,
|
|
23943
|
+
TOKEN.and,
|
|
23944
|
+
TOKEN.or,
|
|
23945
|
+
TOKEN.xor,
|
|
23946
|
+
TOKEN.bitshift
|
|
23947
|
+
]);
|
|
23948
|
+
this.#unaryOps = /* @__PURE__ */ new Set([
|
|
23949
|
+
TOKEN.abs,
|
|
23950
|
+
TOKEN.neg,
|
|
23951
|
+
TOKEN.ceiling,
|
|
23952
|
+
TOKEN.floor,
|
|
23953
|
+
TOKEN.round,
|
|
23954
|
+
TOKEN.truncate,
|
|
23955
|
+
TOKEN.sqrt,
|
|
23956
|
+
TOKEN.sin,
|
|
23957
|
+
TOKEN.cos,
|
|
23958
|
+
TOKEN.ln,
|
|
23959
|
+
TOKEN.log,
|
|
23960
|
+
TOKEN.cvi,
|
|
23961
|
+
TOKEN.cvr,
|
|
23962
|
+
TOKEN.not
|
|
23963
|
+
]);
|
|
23964
|
+
this.#idempotentUnary = /* @__PURE__ */ new Set([
|
|
23965
|
+
TOKEN.abs,
|
|
23966
|
+
TOKEN.ceiling,
|
|
23967
|
+
TOKEN.cvi,
|
|
23968
|
+
TOKEN.cvr,
|
|
23969
|
+
TOKEN.floor,
|
|
23970
|
+
TOKEN.round,
|
|
23971
|
+
TOKEN.truncate
|
|
23972
|
+
]);
|
|
23973
|
+
this.#negatedComparison = /* @__PURE__ */ new Map([
|
|
23974
|
+
[TOKEN.eq, TOKEN.ne],
|
|
23975
|
+
[TOKEN.ne, TOKEN.eq],
|
|
23976
|
+
[TOKEN.lt, TOKEN.ge],
|
|
23977
|
+
[TOKEN.le, TOKEN.gt],
|
|
23978
|
+
[TOKEN.gt, TOKEN.le],
|
|
23979
|
+
[TOKEN.ge, TOKEN.lt]
|
|
23980
|
+
]);
|
|
23981
|
+
}
|
|
23982
|
+
/**
|
|
23983
|
+
* @param {PsProgram} program
|
|
23984
|
+
* @param {number} numInputs — number of domain values placed on the stack
|
|
23985
|
+
* before the program runs (i.e. the length of the domain array / 2).
|
|
23986
|
+
* @returns {Array<PsNode>} — one tree node per output value.
|
|
23987
|
+
*/
|
|
23988
|
+
evaluate(program, numInputs) {
|
|
23989
|
+
if (!_PSStackToTree.#binaryOps) {
|
|
23990
|
+
_PSStackToTree.#init();
|
|
23991
|
+
}
|
|
23992
|
+
this._failed = false;
|
|
23993
|
+
if (numInputs > MAX_STACK_SIZE) {
|
|
23994
|
+
return null;
|
|
23995
|
+
}
|
|
23996
|
+
const stack = [];
|
|
23997
|
+
for (let i = 0; i < numInputs; i++) {
|
|
23998
|
+
stack.push(new PsArgNode(i));
|
|
23999
|
+
}
|
|
24000
|
+
this._evalBlock(program.body, stack);
|
|
24001
|
+
if (this._failed) {
|
|
24002
|
+
return null;
|
|
24003
|
+
}
|
|
24004
|
+
_PSStackToTree.#markShared(stack);
|
|
24005
|
+
return stack;
|
|
24006
|
+
}
|
|
24007
|
+
// Set node.shared / sharedCount on non-atomic nodes referenced more than
|
|
24008
|
+
// once. arg/const are excluded — they are cheap to re-emit inline.
|
|
24009
|
+
static #markShared(outputs) {
|
|
24010
|
+
const refCount = /* @__PURE__ */ new Map();
|
|
24011
|
+
const visit = (node) => {
|
|
24012
|
+
if (!node || node.type === PS_NODE.arg || node.type === PS_NODE.const) {
|
|
24013
|
+
return;
|
|
24014
|
+
}
|
|
24015
|
+
const prev = refCount.get(node) ?? 0;
|
|
24016
|
+
refCount.set(node, prev + 1);
|
|
24017
|
+
if (prev > 0) {
|
|
24018
|
+
return;
|
|
24019
|
+
}
|
|
24020
|
+
switch (node.type) {
|
|
24021
|
+
case PS_NODE.unary:
|
|
24022
|
+
visit(node.operand);
|
|
24023
|
+
break;
|
|
24024
|
+
case PS_NODE.binary:
|
|
24025
|
+
visit(node.first);
|
|
24026
|
+
visit(node.second);
|
|
24027
|
+
break;
|
|
24028
|
+
case PS_NODE.ternary:
|
|
24029
|
+
visit(node.cond);
|
|
24030
|
+
visit(node.then);
|
|
24031
|
+
visit(node.otherwise);
|
|
24032
|
+
break;
|
|
24033
|
+
}
|
|
24034
|
+
};
|
|
24035
|
+
for (const output of outputs) {
|
|
24036
|
+
visit(output);
|
|
24037
|
+
}
|
|
24038
|
+
for (const [node, count] of refCount) {
|
|
24039
|
+
if (count > 1) {
|
|
24040
|
+
node.shared = true;
|
|
24041
|
+
node.sharedCount = count;
|
|
24042
|
+
}
|
|
24043
|
+
}
|
|
24044
|
+
}
|
|
24045
|
+
_evalBlock(block, stack) {
|
|
24046
|
+
this._evalBlockFrom(block.instructions, 0, stack);
|
|
24047
|
+
}
|
|
24048
|
+
/**
|
|
24049
|
+
* Core evaluation loop. Processes `instructions[startIdx…]` in order,
|
|
24050
|
+
* mutating `stack` as each instruction executes.
|
|
24051
|
+
*
|
|
24052
|
+
* When a `{ body } if` instruction grows the stack (the PostScript "early
|
|
24053
|
+
* exit / guard" idiom), the remaining instructions in the current array are
|
|
24054
|
+
* evaluated on **both** the true-branch stack and the false-branch stack,
|
|
24055
|
+
* then the two results are merged into PsTernaryNodes. This handles
|
|
24056
|
+
* patterns like:
|
|
24057
|
+
*
|
|
24058
|
+
* cond { pop R G B sentinel } if
|
|
24059
|
+
* … more guards …
|
|
24060
|
+
* sentinel 0 gt { defaultR defaultG defaultB } if
|
|
24061
|
+
*/
|
|
24062
|
+
_evalBlockFrom(instructions, startIdx, stack) {
|
|
24063
|
+
for (let idx = startIdx; idx < instructions.length; idx++) {
|
|
24064
|
+
if (this._failed) {
|
|
24065
|
+
break;
|
|
24066
|
+
}
|
|
24067
|
+
const instr = instructions[idx];
|
|
24068
|
+
switch (instr.type) {
|
|
24069
|
+
case PS_NODE.number:
|
|
24070
|
+
stack.push(new PsConstNode(instr.value));
|
|
24071
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
24072
|
+
this._failed = true;
|
|
24073
|
+
}
|
|
24074
|
+
break;
|
|
24075
|
+
case PS_NODE.operator:
|
|
24076
|
+
this._evalOp(instr.op, stack);
|
|
24077
|
+
break;
|
|
24078
|
+
case PS_NODE.if: {
|
|
24079
|
+
if (stack.length < 1) {
|
|
24080
|
+
this._failed = true;
|
|
24081
|
+
break;
|
|
24082
|
+
}
|
|
24083
|
+
const cond = stack.pop();
|
|
24084
|
+
const saved = stack.slice();
|
|
24085
|
+
this._evalBlock(instr.then, stack);
|
|
24086
|
+
if (this._failed) {
|
|
24087
|
+
break;
|
|
24088
|
+
}
|
|
24089
|
+
if (stack.length === saved.length) {
|
|
24090
|
+
for (let i = 0; i < stack.length; i++) {
|
|
24091
|
+
if (stack[i] !== saved[i]) {
|
|
24092
|
+
stack[i] = this._makeTernary(cond, stack[i], saved[i]);
|
|
24093
|
+
}
|
|
24094
|
+
}
|
|
24095
|
+
} else if (stack.length > saved.length) {
|
|
24096
|
+
if (cond.type === PS_NODE.const) {
|
|
24097
|
+
if (!cond.value) {
|
|
24098
|
+
stack.length = 0;
|
|
24099
|
+
stack.push(...saved);
|
|
24100
|
+
}
|
|
24101
|
+
break;
|
|
24102
|
+
}
|
|
24103
|
+
const trueStack = stack.slice();
|
|
24104
|
+
this._evalBlockFrom(instructions, idx + 1, trueStack);
|
|
24105
|
+
if (this._failed) {
|
|
24106
|
+
break;
|
|
24107
|
+
}
|
|
24108
|
+
const falseStack = saved;
|
|
24109
|
+
this._evalBlockFrom(instructions, idx + 1, falseStack);
|
|
24110
|
+
if (this._failed) {
|
|
24111
|
+
break;
|
|
24112
|
+
}
|
|
24113
|
+
if (trueStack.length !== falseStack.length) {
|
|
24114
|
+
const zero2 = new PsConstNode(0);
|
|
24115
|
+
while (trueStack.length < falseStack.length) {
|
|
24116
|
+
trueStack.push(zero2);
|
|
24117
|
+
}
|
|
24118
|
+
while (falseStack.length < trueStack.length) {
|
|
24119
|
+
falseStack.push(zero2);
|
|
24120
|
+
}
|
|
24121
|
+
}
|
|
24122
|
+
stack.length = 0;
|
|
24123
|
+
for (let i = 0; i < trueStack.length; i++) {
|
|
24124
|
+
stack.push(this._makeTernary(cond, trueStack[i], falseStack[i]));
|
|
24125
|
+
}
|
|
24126
|
+
return;
|
|
24127
|
+
} else {
|
|
24128
|
+
this._failed = true;
|
|
24129
|
+
}
|
|
24130
|
+
break;
|
|
24131
|
+
}
|
|
24132
|
+
case PS_NODE.ifelse: {
|
|
24133
|
+
if (stack.length < 1) {
|
|
24134
|
+
this._failed = true;
|
|
24135
|
+
break;
|
|
24136
|
+
}
|
|
24137
|
+
const cond = stack.pop();
|
|
24138
|
+
const snapshot = stack.slice();
|
|
24139
|
+
const thenStack = snapshot.slice();
|
|
24140
|
+
this._evalBlock(instr.then, thenStack);
|
|
24141
|
+
if (this._failed) {
|
|
24142
|
+
break;
|
|
24143
|
+
}
|
|
24144
|
+
const elseStack = snapshot.slice();
|
|
24145
|
+
this._evalBlock(instr.otherwise, elseStack);
|
|
24146
|
+
if (this._failed) {
|
|
24147
|
+
break;
|
|
24148
|
+
}
|
|
24149
|
+
if (thenStack.length !== elseStack.length) {
|
|
24150
|
+
const zero2 = new PsConstNode(0);
|
|
24151
|
+
while (thenStack.length < elseStack.length) {
|
|
24152
|
+
thenStack.push(zero2);
|
|
24153
|
+
}
|
|
24154
|
+
while (elseStack.length < thenStack.length) {
|
|
24155
|
+
elseStack.push(zero2);
|
|
24156
|
+
}
|
|
24157
|
+
}
|
|
24158
|
+
stack.length = 0;
|
|
24159
|
+
for (let i = 0; i < thenStack.length; i++) {
|
|
24160
|
+
stack.push(this._makeTernary(cond, thenStack[i], elseStack[i]));
|
|
24161
|
+
}
|
|
24162
|
+
break;
|
|
24163
|
+
}
|
|
24164
|
+
}
|
|
24165
|
+
}
|
|
24166
|
+
}
|
|
24167
|
+
_evalOp(op, stack) {
|
|
24168
|
+
if (_PSStackToTree.#binaryOps.has(op)) {
|
|
24169
|
+
if (stack.length < 2) {
|
|
24170
|
+
this._failed = true;
|
|
24171
|
+
return;
|
|
24172
|
+
}
|
|
24173
|
+
const first = stack.pop();
|
|
24174
|
+
const second = stack.pop();
|
|
24175
|
+
stack.push(this._makeBinary(op, first, second));
|
|
24176
|
+
return;
|
|
24177
|
+
}
|
|
24178
|
+
if (_PSStackToTree.#unaryOps.has(op)) {
|
|
24179
|
+
if (stack.length < 1) {
|
|
24180
|
+
this._failed = true;
|
|
24181
|
+
return;
|
|
24182
|
+
}
|
|
24183
|
+
stack.push(this._makeUnary(op, stack.pop()));
|
|
24184
|
+
return;
|
|
24185
|
+
}
|
|
24186
|
+
switch (op) {
|
|
24187
|
+
case TOKEN.true:
|
|
24188
|
+
stack.push(new PsConstNode(true));
|
|
24189
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
24190
|
+
this._failed = true;
|
|
24191
|
+
}
|
|
24192
|
+
break;
|
|
24193
|
+
case TOKEN.false:
|
|
24194
|
+
stack.push(new PsConstNode(false));
|
|
24195
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
24196
|
+
this._failed = true;
|
|
24197
|
+
}
|
|
24198
|
+
break;
|
|
24199
|
+
case TOKEN.dup:
|
|
24200
|
+
if (stack.length < 1) {
|
|
24201
|
+
this._failed = true;
|
|
24202
|
+
break;
|
|
24203
|
+
}
|
|
24204
|
+
stack.push(stack.at(-1));
|
|
24205
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
24206
|
+
this._failed = true;
|
|
24207
|
+
}
|
|
24208
|
+
break;
|
|
24209
|
+
case TOKEN.exch: {
|
|
24210
|
+
if (stack.length < 2) {
|
|
24211
|
+
this._failed = true;
|
|
24212
|
+
break;
|
|
24213
|
+
}
|
|
24214
|
+
const a = stack.pop();
|
|
24215
|
+
const b = stack.pop();
|
|
24216
|
+
stack.push(a, b);
|
|
24217
|
+
break;
|
|
24218
|
+
}
|
|
24219
|
+
case TOKEN.pop:
|
|
24220
|
+
if (stack.length < 1) {
|
|
24221
|
+
this._failed = true;
|
|
24222
|
+
break;
|
|
24223
|
+
}
|
|
24224
|
+
stack.pop();
|
|
24225
|
+
break;
|
|
24226
|
+
case TOKEN.copy: {
|
|
24227
|
+
if (stack.length < 1) {
|
|
24228
|
+
this._failed = true;
|
|
24229
|
+
break;
|
|
24230
|
+
}
|
|
24231
|
+
const nNode = stack.pop();
|
|
24232
|
+
if (nNode.type === PS_NODE.const) {
|
|
24233
|
+
const n = nNode.value | 0;
|
|
24234
|
+
if (n === 0) {
|
|
24235
|
+
} else if (n < 0 || n > stack.length) {
|
|
24236
|
+
this._failed = true;
|
|
24237
|
+
} else {
|
|
24238
|
+
stack.push(...stack.slice(-n));
|
|
24239
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
24240
|
+
this._failed = true;
|
|
24241
|
+
}
|
|
24242
|
+
}
|
|
24243
|
+
} else {
|
|
24244
|
+
this._failed = true;
|
|
24245
|
+
}
|
|
24246
|
+
break;
|
|
24247
|
+
}
|
|
24248
|
+
case TOKEN.index: {
|
|
24249
|
+
if (stack.length < 1) {
|
|
24250
|
+
this._failed = true;
|
|
24251
|
+
break;
|
|
24252
|
+
}
|
|
24253
|
+
const nNode = stack.pop();
|
|
24254
|
+
if (nNode.type === PS_NODE.const) {
|
|
24255
|
+
const n = nNode.value | 0;
|
|
24256
|
+
if (n < 0 || n >= stack.length) {
|
|
24257
|
+
this._failed = true;
|
|
24258
|
+
} else {
|
|
24259
|
+
stack.push(stack.at(-n - 1));
|
|
24260
|
+
}
|
|
24261
|
+
} else {
|
|
24262
|
+
this._failed = true;
|
|
24263
|
+
}
|
|
24264
|
+
break;
|
|
24265
|
+
}
|
|
24266
|
+
case TOKEN.roll: {
|
|
24267
|
+
if (stack.length < 2) {
|
|
24268
|
+
this._failed = true;
|
|
24269
|
+
break;
|
|
24270
|
+
}
|
|
24271
|
+
const jNode = stack.pop();
|
|
24272
|
+
const nNode = stack.pop();
|
|
24273
|
+
if (nNode.type === PS_NODE.const && jNode.type === PS_NODE.const) {
|
|
24274
|
+
const n = nNode.value | 0;
|
|
24275
|
+
if (n === 0) {
|
|
24276
|
+
} else if (n < 0 || n > stack.length) {
|
|
24277
|
+
this._failed = true;
|
|
24278
|
+
} else {
|
|
24279
|
+
const j = ((jNode.value | 0) % n + n) % n;
|
|
24280
|
+
if (j > 0) {
|
|
24281
|
+
const slice = stack.splice(-n, n);
|
|
24282
|
+
stack.push(...slice.slice(n - j), ...slice.slice(0, n - j));
|
|
24283
|
+
}
|
|
24284
|
+
}
|
|
24285
|
+
} else {
|
|
24286
|
+
this._failed = true;
|
|
24287
|
+
}
|
|
24288
|
+
break;
|
|
24289
|
+
}
|
|
24290
|
+
default:
|
|
24291
|
+
this._failed = true;
|
|
24292
|
+
break;
|
|
24293
|
+
}
|
|
24294
|
+
}
|
|
24295
|
+
/**
|
|
24296
|
+
* Create a binary tree node, applying optimizations eagerly:
|
|
24297
|
+
*
|
|
24298
|
+
* 1. Constant folding — both operands are PsConstNode → fold to PsConstNode.
|
|
24299
|
+
* 2. Reflexive simplifications — x−x→0, x xor x→0, x eq x→true, etc.
|
|
24300
|
+
* 3. Algebraic simplifications with one known operand — identity elements
|
|
24301
|
+
* (x+0→x, x*1→x, …), absorbing elements (x*0→0, x and false→false, …),
|
|
24302
|
+
* and strength reductions (x*-1→neg(x), x^0.5→sqrt(x), x^2→x*x, …).
|
|
24303
|
+
*
|
|
24304
|
+
* Recall: `first` was on top of the stack (right operand for non-commutative
|
|
24305
|
+
* ops), `second` was below (left operand). So `a b sub` → second=a, first=b
|
|
24306
|
+
* → a − b.
|
|
24307
|
+
*/
|
|
24308
|
+
_makeBinary(op, first, second) {
|
|
24309
|
+
if (first.type === PS_NODE.const && second.type === PS_NODE.const) {
|
|
24310
|
+
const v = _evalBinaryConst(op, second.value, first.value);
|
|
24311
|
+
if (v !== void 0) {
|
|
24312
|
+
return new PsConstNode(v);
|
|
24313
|
+
}
|
|
24314
|
+
}
|
|
24315
|
+
if (_nodesEqual(first, second)) {
|
|
24316
|
+
switch (op) {
|
|
24317
|
+
case TOKEN.sub:
|
|
24318
|
+
return new PsConstNode(0);
|
|
24319
|
+
// x − x → 0
|
|
24320
|
+
case TOKEN.xor:
|
|
24321
|
+
return new PsConstNode(
|
|
24322
|
+
/* eslint-disable unicorn/prefer-logical-operator-over-ternary */
|
|
24323
|
+
first.valueType === PS_VALUE_TYPE.boolean ? false : 0
|
|
24324
|
+
/* eslint-enable unicorn/prefer-logical-operator-over-ternary */
|
|
24325
|
+
);
|
|
24326
|
+
// TOKEN.mod, TOKEN.div, TOKEN.idiv are NOT simplified here:
|
|
24327
|
+
// x op x is undefined when x = 0, so we cannot fold without knowing
|
|
24328
|
+
// that x is non-zero.
|
|
24329
|
+
case TOKEN.and:
|
|
24330
|
+
case TOKEN.or:
|
|
24331
|
+
return first;
|
|
24332
|
+
// x and x → x; x or x → x
|
|
24333
|
+
case TOKEN.min:
|
|
24334
|
+
case TOKEN.max:
|
|
24335
|
+
return first;
|
|
24336
|
+
// min(x,x) → x; max(x,x) → x
|
|
24337
|
+
case TOKEN.eq:
|
|
24338
|
+
case TOKEN.ge:
|
|
24339
|
+
case TOKEN.le:
|
|
24340
|
+
return new PsConstNode(true);
|
|
24341
|
+
case TOKEN.ne:
|
|
24342
|
+
case TOKEN.gt:
|
|
24343
|
+
case TOKEN.lt:
|
|
24344
|
+
return new PsConstNode(false);
|
|
24345
|
+
}
|
|
24346
|
+
}
|
|
24347
|
+
if (first.type === PS_NODE.const) {
|
|
24348
|
+
const b = first.value;
|
|
24349
|
+
switch (op) {
|
|
24350
|
+
case TOKEN.add:
|
|
24351
|
+
if (b === 0) {
|
|
24352
|
+
return second;
|
|
24353
|
+
}
|
|
24354
|
+
break;
|
|
24355
|
+
case TOKEN.sub:
|
|
24356
|
+
if (b === 0) {
|
|
24357
|
+
return second;
|
|
24358
|
+
}
|
|
24359
|
+
break;
|
|
24360
|
+
case TOKEN.mul:
|
|
24361
|
+
if (b === 1) {
|
|
24362
|
+
return second;
|
|
24363
|
+
}
|
|
24364
|
+
if (b === 0) {
|
|
24365
|
+
return first;
|
|
24366
|
+
}
|
|
24367
|
+
if (b === -1) {
|
|
24368
|
+
return this._makeUnary(TOKEN.neg, second);
|
|
24369
|
+
}
|
|
24370
|
+
break;
|
|
24371
|
+
case TOKEN.div:
|
|
24372
|
+
if (b !== 0) {
|
|
24373
|
+
return this._makeBinary(TOKEN.mul, new PsConstNode(1 / b), second);
|
|
24374
|
+
}
|
|
24375
|
+
break;
|
|
24376
|
+
case TOKEN.idiv:
|
|
24377
|
+
if (b === 1) {
|
|
24378
|
+
return second;
|
|
24379
|
+
}
|
|
24380
|
+
break;
|
|
24381
|
+
case TOKEN.exp:
|
|
24382
|
+
if (b === 1) {
|
|
24383
|
+
return second;
|
|
24384
|
+
}
|
|
24385
|
+
if (b === -1) {
|
|
24386
|
+
return this._makeBinary(TOKEN.div, second, new PsConstNode(1));
|
|
24387
|
+
}
|
|
24388
|
+
if (b === 0.5) {
|
|
24389
|
+
return this._makeUnary(TOKEN.sqrt, second);
|
|
24390
|
+
}
|
|
24391
|
+
if (b === 0.25) {
|
|
24392
|
+
const sqrtOnce = this._makeUnary(TOKEN.sqrt, second);
|
|
24393
|
+
return this._makeUnary(TOKEN.sqrt, sqrtOnce);
|
|
24394
|
+
}
|
|
24395
|
+
if (b === 2) {
|
|
24396
|
+
return this._makeBinary(TOKEN.mul, second, second);
|
|
24397
|
+
}
|
|
24398
|
+
if (b === 3) {
|
|
24399
|
+
return this._makeBinary(
|
|
24400
|
+
TOKEN.mul,
|
|
24401
|
+
this._makeBinary(TOKEN.mul, second, second),
|
|
24402
|
+
second
|
|
24403
|
+
);
|
|
24404
|
+
}
|
|
24405
|
+
if (b === 4) {
|
|
24406
|
+
const square = this._makeBinary(TOKEN.mul, second, second);
|
|
24407
|
+
return this._makeBinary(TOKEN.mul, square, square);
|
|
24408
|
+
}
|
|
24409
|
+
if (b === 0) {
|
|
24410
|
+
return new PsConstNode(1);
|
|
24411
|
+
}
|
|
24412
|
+
break;
|
|
24413
|
+
case TOKEN.and:
|
|
24414
|
+
if (b === true) {
|
|
24415
|
+
return second;
|
|
24416
|
+
}
|
|
24417
|
+
if (b === false) {
|
|
24418
|
+
return first;
|
|
24419
|
+
}
|
|
24420
|
+
break;
|
|
24421
|
+
case TOKEN.or:
|
|
24422
|
+
if (b === false) {
|
|
24423
|
+
return second;
|
|
24424
|
+
}
|
|
24425
|
+
if (b === true) {
|
|
24426
|
+
return first;
|
|
24427
|
+
}
|
|
24428
|
+
break;
|
|
24429
|
+
case TOKEN.min:
|
|
24430
|
+
if (second.type === PS_NODE.binary && second.op === TOKEN.max && second.first.type === PS_NODE.const && second.first.value >= b) {
|
|
24431
|
+
return first;
|
|
24432
|
+
}
|
|
24433
|
+
break;
|
|
24434
|
+
case TOKEN.max:
|
|
24435
|
+
if (second.type === PS_NODE.binary && second.op === TOKEN.min && second.first.type === PS_NODE.const && second.first.value <= b) {
|
|
24436
|
+
return first;
|
|
24437
|
+
}
|
|
24438
|
+
break;
|
|
24439
|
+
}
|
|
24440
|
+
}
|
|
24441
|
+
if (second.type === PS_NODE.const) {
|
|
24442
|
+
const a = second.value;
|
|
24443
|
+
switch (op) {
|
|
24444
|
+
case TOKEN.add:
|
|
24445
|
+
if (a === 0) {
|
|
24446
|
+
return first;
|
|
24447
|
+
}
|
|
24448
|
+
break;
|
|
24449
|
+
case TOKEN.sub:
|
|
24450
|
+
if (a === 0) {
|
|
24451
|
+
return this._makeUnary(TOKEN.neg, first);
|
|
24452
|
+
}
|
|
24453
|
+
break;
|
|
24454
|
+
case TOKEN.mul:
|
|
24455
|
+
if (a === 1) {
|
|
24456
|
+
return first;
|
|
24457
|
+
}
|
|
24458
|
+
if (a === 0) {
|
|
24459
|
+
return second;
|
|
24460
|
+
}
|
|
24461
|
+
if (a === -1) {
|
|
24462
|
+
return this._makeUnary(TOKEN.neg, first);
|
|
24463
|
+
}
|
|
24464
|
+
break;
|
|
24465
|
+
case TOKEN.and:
|
|
24466
|
+
if (a === true) {
|
|
24467
|
+
return first;
|
|
24468
|
+
}
|
|
24469
|
+
if (a === false) {
|
|
24470
|
+
return second;
|
|
24471
|
+
}
|
|
24472
|
+
break;
|
|
24473
|
+
case TOKEN.or:
|
|
24474
|
+
if (a === false) {
|
|
24475
|
+
return first;
|
|
24476
|
+
}
|
|
24477
|
+
if (a === true) {
|
|
24478
|
+
return second;
|
|
24479
|
+
}
|
|
24480
|
+
break;
|
|
24481
|
+
}
|
|
24482
|
+
}
|
|
24483
|
+
return new PsBinaryNode(
|
|
24484
|
+
op,
|
|
24485
|
+
first,
|
|
24486
|
+
second,
|
|
24487
|
+
_binaryValueType(op, first.valueType, second.valueType)
|
|
24488
|
+
);
|
|
24489
|
+
}
|
|
24490
|
+
/**
|
|
24491
|
+
* Create a unary tree node, applying optimizations eagerly:
|
|
24492
|
+
*
|
|
24493
|
+
* 1. Constant folding.
|
|
24494
|
+
* 2. not(comparison) → negated comparison: not(a eq b) → a ne b, etc.
|
|
24495
|
+
* 3. neg(a − b) → b − a.
|
|
24496
|
+
* 4. Double-negation: neg(neg(x)) → x, not(not(x)) → x.
|
|
24497
|
+
* 5. abs(neg(x)) → abs(x).
|
|
24498
|
+
* 6. Idempotent: f(f(x)) → f(x) for abs, ceiling, floor, round, etc.
|
|
24499
|
+
*/
|
|
24500
|
+
_makeUnary(op, operand) {
|
|
24501
|
+
if (operand.type === PS_NODE.const) {
|
|
24502
|
+
const v = _evalUnaryConst(op, operand.value);
|
|
24503
|
+
if (v !== void 0) {
|
|
24504
|
+
return new PsConstNode(v);
|
|
24505
|
+
}
|
|
24506
|
+
}
|
|
24507
|
+
if (op === TOKEN.not && operand.type === PS_NODE.binary) {
|
|
24508
|
+
const negated = _PSStackToTree.#negatedComparison.get(operand.op);
|
|
24509
|
+
if (negated !== void 0) {
|
|
24510
|
+
return new PsBinaryNode(
|
|
24511
|
+
negated,
|
|
24512
|
+
operand.first,
|
|
24513
|
+
operand.second,
|
|
24514
|
+
PS_VALUE_TYPE.boolean
|
|
24515
|
+
);
|
|
24516
|
+
}
|
|
24517
|
+
}
|
|
24518
|
+
if (op === TOKEN.neg && operand.type === PS_NODE.binary && operand.op === TOKEN.sub) {
|
|
24519
|
+
return this._makeBinary(TOKEN.sub, operand.second, operand.first);
|
|
24520
|
+
}
|
|
24521
|
+
if (operand.type === PS_NODE.unary) {
|
|
24522
|
+
if (op === TOKEN.neg && operand.op === TOKEN.neg || op === TOKEN.not && operand.op === TOKEN.not) {
|
|
24523
|
+
return operand.operand;
|
|
24524
|
+
}
|
|
24525
|
+
if (op === TOKEN.abs && operand.op === TOKEN.neg) {
|
|
24526
|
+
return this._makeUnary(TOKEN.abs, operand.operand);
|
|
24527
|
+
}
|
|
24528
|
+
if (_PSStackToTree.#idempotentUnary.has(op) && op === operand.op) {
|
|
24529
|
+
return operand;
|
|
24530
|
+
}
|
|
24531
|
+
}
|
|
24532
|
+
return new PsUnaryNode(op, operand, _unaryValueType(op, operand.valueType));
|
|
24533
|
+
}
|
|
24534
|
+
/**
|
|
24535
|
+
* Create a ternary node, applying optimizations eagerly:
|
|
24536
|
+
*
|
|
24537
|
+
* 1. Constant condition — fold to the live branch.
|
|
24538
|
+
* 2. Identical branches — the condition is irrelevant, return either branch.
|
|
24539
|
+
* 3. Boolean branch constants — `cond ? true : false` → cond,
|
|
24540
|
+
* `cond ? false : true` → not(cond).
|
|
24541
|
+
* 4. Ternary → branchless min/max when the condition compares two numeric
|
|
24542
|
+
* expressions that are also the two branches.
|
|
24543
|
+
*/
|
|
24544
|
+
_makeTernary(cond, then, otherwise) {
|
|
24545
|
+
if (cond.type === PS_NODE.const) {
|
|
24546
|
+
return cond.value ? then : otherwise;
|
|
24547
|
+
}
|
|
24548
|
+
if (_nodesEqual(then, otherwise)) {
|
|
24549
|
+
return then;
|
|
24550
|
+
}
|
|
24551
|
+
if (then.type === PS_NODE.const && otherwise.type === PS_NODE.const) {
|
|
24552
|
+
if (then.value === true && otherwise.value === false) {
|
|
24553
|
+
return cond;
|
|
24554
|
+
}
|
|
24555
|
+
if (then.value === false && otherwise.value === true) {
|
|
24556
|
+
return this._makeUnary(TOKEN.not, cond);
|
|
24557
|
+
}
|
|
24558
|
+
}
|
|
24559
|
+
if (cond.type === PS_NODE.binary) {
|
|
24560
|
+
const { op: cop, first: cf, second: cs } = cond;
|
|
24561
|
+
if (cop === TOKEN.gt || cop === TOKEN.ge) {
|
|
24562
|
+
if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
|
|
24563
|
+
return this._makeBinary(TOKEN.min, cf, cs);
|
|
24564
|
+
}
|
|
24565
|
+
if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
|
|
24566
|
+
return this._makeBinary(TOKEN.max, cf, cs);
|
|
24567
|
+
}
|
|
24568
|
+
} else if (cop === TOKEN.lt || cop === TOKEN.le) {
|
|
24569
|
+
if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
|
|
24570
|
+
return this._makeBinary(TOKEN.max, cf, cs);
|
|
24571
|
+
}
|
|
24572
|
+
if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
|
|
24573
|
+
return this._makeBinary(TOKEN.min, cf, cs);
|
|
24574
|
+
}
|
|
24575
|
+
}
|
|
24576
|
+
}
|
|
24577
|
+
return new PsTernaryNode(
|
|
24578
|
+
cond,
|
|
24579
|
+
then,
|
|
24580
|
+
otherwise,
|
|
24581
|
+
then.valueType === otherwise.valueType ? then.valueType : PS_VALUE_TYPE.unknown
|
|
24582
|
+
);
|
|
24583
|
+
}
|
|
24584
|
+
};
|
|
24585
|
+
var OP = {
|
|
24586
|
+
ARG: 0,
|
|
24587
|
+
// [ARG, idx]
|
|
24588
|
+
CONST: 1,
|
|
24589
|
+
// [CONST, val]
|
|
24590
|
+
STORE: 2,
|
|
24591
|
+
// [STORE, slot, min, max] clamp(pop()) → mem[slot]
|
|
24592
|
+
IF: 3,
|
|
24593
|
+
// [IF, target] jump when top-of-stack === 0
|
|
24594
|
+
JUMP: 4,
|
|
24595
|
+
// [JUMP, target] unconditional
|
|
24596
|
+
ABS: 5,
|
|
24597
|
+
NEG: 6,
|
|
24598
|
+
CEIL: 7,
|
|
24599
|
+
FLOOR: 8,
|
|
24600
|
+
ROUND: 9,
|
|
24601
|
+
// floor(x + 0.5)
|
|
24602
|
+
TRUNC: 10,
|
|
24603
|
+
NOT_B: 11,
|
|
24604
|
+
// boolean NOT
|
|
24605
|
+
NOT_N: 12,
|
|
24606
|
+
// bitwise NOT
|
|
24607
|
+
SQRT: 13,
|
|
24608
|
+
SIN: 14,
|
|
24609
|
+
// degrees in/out
|
|
24610
|
+
COS: 15,
|
|
24611
|
+
LN: 16,
|
|
24612
|
+
LOG10: 17,
|
|
24613
|
+
CVI: 18,
|
|
24614
|
+
SHIFT: 19,
|
|
24615
|
+
// [SHIFT, amount] +ve = left, −ve = right
|
|
24616
|
+
// Binary ops: second below, first on top; result = second OP first.
|
|
24617
|
+
ADD: 20,
|
|
24618
|
+
SUB: 21,
|
|
24619
|
+
MUL: 22,
|
|
24620
|
+
DIV: 23,
|
|
24621
|
+
// 0 when divisor is 0
|
|
24622
|
+
IDIV: 24,
|
|
24623
|
+
// 0 when divisor is 0
|
|
24624
|
+
MOD: 25,
|
|
24625
|
+
// 0 when divisor is 0
|
|
24626
|
+
POW: 26,
|
|
24627
|
+
EQ: 27,
|
|
24628
|
+
NE: 28,
|
|
24629
|
+
GT: 29,
|
|
24630
|
+
GE: 30,
|
|
24631
|
+
LT: 31,
|
|
24632
|
+
LE: 32,
|
|
24633
|
+
AND: 33,
|
|
24634
|
+
OR: 34,
|
|
24635
|
+
XOR: 35,
|
|
24636
|
+
ATAN: 36,
|
|
24637
|
+
// atan2(second, first) → degrees [0, 360)
|
|
24638
|
+
MIN: 37,
|
|
24639
|
+
MAX: 38,
|
|
24640
|
+
TEE_TMP: 39,
|
|
24641
|
+
// [TEE_TMP, slot] peek top of stack → tmp[slot], leave on stack
|
|
24642
|
+
LOAD_TMP: 40
|
|
24643
|
+
// [LOAD_TMP, slot] push tmp[slot]
|
|
24644
|
+
};
|
|
24645
|
+
var _DEG_TO_RAD = Math.PI / 180;
|
|
24646
|
+
var _RAD_TO_DEG = 180 / Math.PI;
|
|
24647
|
+
var PsJsCompiler = class {
|
|
24648
|
+
// Safe because JS is single-threaded.
|
|
24649
|
+
static #stack = new Float64Array(64);
|
|
24650
|
+
static #tmp = new Float64Array(64);
|
|
24651
|
+
constructor(domain, range) {
|
|
24652
|
+
this.nIn = domain.length >> 1;
|
|
24653
|
+
this.nOut = range.length >> 1;
|
|
24654
|
+
this.range = range;
|
|
24655
|
+
this.ir = [];
|
|
24656
|
+
this._tmpMap = /* @__PURE__ */ new Map();
|
|
24657
|
+
this._nextTmp = 0;
|
|
24658
|
+
}
|
|
24659
|
+
_compileNode(node) {
|
|
24660
|
+
if (node.shared) {
|
|
24661
|
+
const cached = this._tmpMap.get(node);
|
|
24662
|
+
if (cached !== void 0) {
|
|
24663
|
+
this.ir.push(OP.LOAD_TMP, cached);
|
|
24664
|
+
return true;
|
|
24665
|
+
}
|
|
24666
|
+
if (!this._compileNodeImpl(node)) {
|
|
24667
|
+
return false;
|
|
24668
|
+
}
|
|
24669
|
+
const slot = this._nextTmp++;
|
|
24670
|
+
this._tmpMap.set(node, slot);
|
|
24671
|
+
this.ir.push(OP.TEE_TMP, slot);
|
|
24672
|
+
return true;
|
|
24673
|
+
}
|
|
24674
|
+
return this._compileNodeImpl(node);
|
|
24675
|
+
}
|
|
24676
|
+
_compileNodeImpl(node) {
|
|
24677
|
+
switch (node.type) {
|
|
24678
|
+
case PS_NODE.arg:
|
|
24679
|
+
this.ir.push(OP.ARG, node.index);
|
|
24680
|
+
return true;
|
|
24681
|
+
case PS_NODE.const: {
|
|
24682
|
+
const v = node.value;
|
|
24683
|
+
this.ir.push(OP.CONST, typeof v === "boolean" ? Number(v) : v);
|
|
24684
|
+
return true;
|
|
24685
|
+
}
|
|
24686
|
+
case PS_NODE.unary:
|
|
24687
|
+
return this._compileUnary(node);
|
|
24688
|
+
case PS_NODE.binary:
|
|
24689
|
+
return this._compileBinary(node);
|
|
24690
|
+
case PS_NODE.ternary:
|
|
24691
|
+
return this._compileTernary(node);
|
|
24692
|
+
default:
|
|
24693
|
+
return false;
|
|
24694
|
+
}
|
|
24695
|
+
}
|
|
24696
|
+
_compileUnary(node) {
|
|
24697
|
+
const { op, operand, valueType } = node;
|
|
24698
|
+
if (op === TOKEN.cvr) {
|
|
24699
|
+
return this._compileNode(operand);
|
|
24700
|
+
}
|
|
24701
|
+
if (!this._compileNode(operand)) {
|
|
24702
|
+
return false;
|
|
24703
|
+
}
|
|
24704
|
+
switch (op) {
|
|
24705
|
+
case TOKEN.abs:
|
|
24706
|
+
this.ir.push(OP.ABS);
|
|
24707
|
+
break;
|
|
24708
|
+
case TOKEN.neg:
|
|
24709
|
+
this.ir.push(OP.NEG);
|
|
24710
|
+
break;
|
|
24711
|
+
case TOKEN.ceiling:
|
|
24712
|
+
this.ir.push(OP.CEIL);
|
|
24713
|
+
break;
|
|
24714
|
+
case TOKEN.floor:
|
|
24715
|
+
this.ir.push(OP.FLOOR);
|
|
24716
|
+
break;
|
|
24717
|
+
case TOKEN.round:
|
|
24718
|
+
this.ir.push(OP.ROUND);
|
|
24719
|
+
break;
|
|
24720
|
+
case TOKEN.truncate:
|
|
24721
|
+
this.ir.push(OP.TRUNC);
|
|
24722
|
+
break;
|
|
24723
|
+
case TOKEN.sqrt:
|
|
24724
|
+
this.ir.push(OP.SQRT);
|
|
24725
|
+
break;
|
|
24726
|
+
case TOKEN.sin:
|
|
24727
|
+
this.ir.push(OP.SIN);
|
|
24728
|
+
break;
|
|
24729
|
+
case TOKEN.cos:
|
|
24730
|
+
this.ir.push(OP.COS);
|
|
24731
|
+
break;
|
|
24732
|
+
case TOKEN.ln:
|
|
24733
|
+
this.ir.push(OP.LN);
|
|
24734
|
+
break;
|
|
24735
|
+
case TOKEN.log:
|
|
24736
|
+
this.ir.push(OP.LOG10);
|
|
24737
|
+
break;
|
|
24738
|
+
case TOKEN.cvi:
|
|
24739
|
+
this.ir.push(OP.CVI);
|
|
24740
|
+
break;
|
|
24741
|
+
case TOKEN.not:
|
|
24742
|
+
if (valueType === PS_VALUE_TYPE.boolean) {
|
|
24743
|
+
this.ir.push(OP.NOT_B);
|
|
24744
|
+
} else if (valueType === PS_VALUE_TYPE.numeric) {
|
|
24745
|
+
this.ir.push(OP.NOT_N);
|
|
24746
|
+
} else {
|
|
24747
|
+
return false;
|
|
24748
|
+
}
|
|
24749
|
+
break;
|
|
24750
|
+
default:
|
|
24751
|
+
return false;
|
|
24752
|
+
}
|
|
24753
|
+
return true;
|
|
24754
|
+
}
|
|
24755
|
+
_compileBinary(node) {
|
|
24756
|
+
const { op, first, second } = node;
|
|
24757
|
+
if (op === TOKEN.bitshift) {
|
|
24758
|
+
if (first.type !== PS_NODE.const || !Number.isInteger(first.value) || !this._compileNode(second)) {
|
|
24759
|
+
return false;
|
|
24760
|
+
}
|
|
24761
|
+
this.ir.push(OP.SHIFT, first.value);
|
|
24762
|
+
return true;
|
|
24763
|
+
}
|
|
24764
|
+
if (!this._compileNode(second) || !this._compileNode(first)) {
|
|
24765
|
+
return false;
|
|
24766
|
+
}
|
|
24767
|
+
switch (op) {
|
|
24768
|
+
case TOKEN.add:
|
|
24769
|
+
this.ir.push(OP.ADD);
|
|
24770
|
+
break;
|
|
24771
|
+
case TOKEN.sub:
|
|
24772
|
+
this.ir.push(OP.SUB);
|
|
24773
|
+
break;
|
|
24774
|
+
case TOKEN.mul:
|
|
24775
|
+
this.ir.push(OP.MUL);
|
|
24776
|
+
break;
|
|
24777
|
+
case TOKEN.div:
|
|
24778
|
+
this.ir.push(OP.DIV);
|
|
24779
|
+
break;
|
|
24780
|
+
case TOKEN.idiv:
|
|
24781
|
+
this.ir.push(OP.IDIV);
|
|
24782
|
+
break;
|
|
24783
|
+
case TOKEN.mod:
|
|
24784
|
+
this.ir.push(OP.MOD);
|
|
24785
|
+
break;
|
|
24786
|
+
case TOKEN.exp:
|
|
24787
|
+
this.ir.push(OP.POW);
|
|
24788
|
+
break;
|
|
24789
|
+
case TOKEN.eq:
|
|
24790
|
+
this.ir.push(OP.EQ);
|
|
24791
|
+
break;
|
|
24792
|
+
case TOKEN.ne:
|
|
24793
|
+
this.ir.push(OP.NE);
|
|
24794
|
+
break;
|
|
24795
|
+
case TOKEN.gt:
|
|
24796
|
+
this.ir.push(OP.GT);
|
|
24797
|
+
break;
|
|
24798
|
+
case TOKEN.ge:
|
|
24799
|
+
this.ir.push(OP.GE);
|
|
24800
|
+
break;
|
|
24801
|
+
case TOKEN.lt:
|
|
24802
|
+
this.ir.push(OP.LT);
|
|
24803
|
+
break;
|
|
24804
|
+
case TOKEN.le:
|
|
24805
|
+
this.ir.push(OP.LE);
|
|
24806
|
+
break;
|
|
24807
|
+
case TOKEN.and:
|
|
24808
|
+
this.ir.push(OP.AND);
|
|
24809
|
+
break;
|
|
24810
|
+
case TOKEN.or:
|
|
24811
|
+
this.ir.push(OP.OR);
|
|
24812
|
+
break;
|
|
24813
|
+
case TOKEN.xor:
|
|
24814
|
+
this.ir.push(OP.XOR);
|
|
24815
|
+
break;
|
|
24816
|
+
case TOKEN.atan:
|
|
24817
|
+
this.ir.push(OP.ATAN);
|
|
24818
|
+
break;
|
|
24819
|
+
case TOKEN.min:
|
|
24820
|
+
this.ir.push(OP.MIN);
|
|
24821
|
+
break;
|
|
24822
|
+
case TOKEN.max:
|
|
24823
|
+
this.ir.push(OP.MAX);
|
|
24824
|
+
break;
|
|
24825
|
+
default:
|
|
24826
|
+
return false;
|
|
24827
|
+
}
|
|
24828
|
+
return true;
|
|
24829
|
+
}
|
|
24830
|
+
_compileTernary(node) {
|
|
24831
|
+
if (!this._compileNode(node.cond)) {
|
|
24832
|
+
return false;
|
|
24833
|
+
}
|
|
24834
|
+
this.ir.push(OP.IF, 0);
|
|
24835
|
+
const ifPatch = this.ir.length - 1;
|
|
24836
|
+
if (!this._compileNode(node.then)) {
|
|
24837
|
+
return false;
|
|
24838
|
+
}
|
|
24839
|
+
this.ir.push(OP.JUMP, 0);
|
|
24840
|
+
const jumpPatch = this.ir.length - 1;
|
|
24841
|
+
this.ir[ifPatch] = this.ir.length;
|
|
24842
|
+
if (!this._compileNode(node.otherwise)) {
|
|
24843
|
+
return false;
|
|
24844
|
+
}
|
|
24845
|
+
this.ir[jumpPatch] = this.ir.length;
|
|
24846
|
+
return true;
|
|
24847
|
+
}
|
|
24848
|
+
compile(program) {
|
|
24849
|
+
const outputs = new PSStackToTree().evaluate(program, this.nIn);
|
|
24850
|
+
if (!outputs || outputs.length < this.nOut) {
|
|
24851
|
+
return null;
|
|
24852
|
+
}
|
|
24853
|
+
for (let i = 0; i < this.nOut; i++) {
|
|
24854
|
+
if (!this._compileNode(outputs[i])) {
|
|
24855
|
+
return null;
|
|
24856
|
+
}
|
|
24857
|
+
const min = this.range[i * 2];
|
|
24858
|
+
const max = this.range[i * 2 + 1];
|
|
24859
|
+
this.ir.push(OP.STORE, i, min, max);
|
|
24860
|
+
}
|
|
24861
|
+
return new Float64Array(this.ir);
|
|
24862
|
+
}
|
|
24863
|
+
static execute(ir, src, srcOffset, dest, destOffset) {
|
|
24864
|
+
let ip = 0, sp = 0;
|
|
24865
|
+
const n = ir.length;
|
|
24866
|
+
const stack = this.#stack;
|
|
24867
|
+
const tmp = this.#tmp;
|
|
24868
|
+
while (ip < n) {
|
|
24869
|
+
switch (ir[ip++] | 0) {
|
|
24870
|
+
case OP.ARG:
|
|
24871
|
+
stack[sp++] = src[srcOffset + (ir[ip++] | 0)];
|
|
24872
|
+
break;
|
|
24873
|
+
case OP.CONST:
|
|
24874
|
+
stack[sp++] = ir[ip++];
|
|
24875
|
+
break;
|
|
24876
|
+
case OP.STORE: {
|
|
24877
|
+
const slot = ir[ip++] | 0;
|
|
24878
|
+
const min = ir[ip++];
|
|
24879
|
+
const max = ir[ip++];
|
|
24880
|
+
dest[destOffset + slot] = MathClamp(stack[--sp], min, max);
|
|
24881
|
+
break;
|
|
24882
|
+
}
|
|
24883
|
+
case OP.IF: {
|
|
24884
|
+
const tgt = ir[ip++];
|
|
24885
|
+
if (stack[--sp] === 0) {
|
|
24886
|
+
ip = tgt;
|
|
24887
|
+
}
|
|
24888
|
+
break;
|
|
24889
|
+
}
|
|
24890
|
+
case OP.JUMP:
|
|
24891
|
+
ip = ir[ip];
|
|
24892
|
+
break;
|
|
24893
|
+
case OP.ABS:
|
|
24894
|
+
stack[sp - 1] = Math.abs(stack[sp - 1]);
|
|
24895
|
+
break;
|
|
24896
|
+
case OP.NEG:
|
|
24897
|
+
stack[sp - 1] = -stack[sp - 1];
|
|
24898
|
+
break;
|
|
24899
|
+
case OP.CEIL:
|
|
24900
|
+
stack[sp - 1] = Math.ceil(stack[sp - 1]);
|
|
24901
|
+
break;
|
|
24902
|
+
case OP.FLOOR:
|
|
24903
|
+
stack[sp - 1] = Math.floor(stack[sp - 1]);
|
|
24904
|
+
break;
|
|
24905
|
+
case OP.ROUND:
|
|
24906
|
+
stack[sp - 1] = Math.floor(stack[sp - 1] + 0.5);
|
|
24907
|
+
break;
|
|
24908
|
+
case OP.TRUNC:
|
|
24909
|
+
stack[sp - 1] = Math.trunc(stack[sp - 1]);
|
|
24910
|
+
break;
|
|
24911
|
+
case OP.NOT_B:
|
|
24912
|
+
stack[sp - 1] = stack[sp - 1] !== 0 ? 0 : 1;
|
|
24913
|
+
break;
|
|
24914
|
+
case OP.NOT_N:
|
|
24915
|
+
stack[sp - 1] = ~(stack[sp - 1] | 0);
|
|
24916
|
+
break;
|
|
24917
|
+
case OP.SQRT:
|
|
24918
|
+
stack[sp - 1] = Math.sqrt(stack[sp - 1]);
|
|
24919
|
+
break;
|
|
24920
|
+
case OP.SIN:
|
|
24921
|
+
stack[sp - 1] = Math.sin(stack[sp - 1] % 360 * _DEG_TO_RAD);
|
|
24922
|
+
break;
|
|
24923
|
+
case OP.COS:
|
|
24924
|
+
stack[sp - 1] = Math.cos(stack[sp - 1] % 360 * _DEG_TO_RAD);
|
|
24925
|
+
break;
|
|
24926
|
+
case OP.LN:
|
|
24927
|
+
stack[sp - 1] = Math.log(stack[sp - 1]);
|
|
24928
|
+
break;
|
|
24929
|
+
case OP.LOG10:
|
|
24930
|
+
stack[sp - 1] = Math.log10(stack[sp - 1]);
|
|
24931
|
+
break;
|
|
24932
|
+
case OP.CVI:
|
|
24933
|
+
stack[sp - 1] = Math.trunc(stack[sp - 1]) | 0;
|
|
24934
|
+
break;
|
|
24935
|
+
case OP.SHIFT: {
|
|
24936
|
+
const amt = ir[ip++];
|
|
24937
|
+
const v = stack[sp - 1] | 0;
|
|
24938
|
+
if (amt > 0) {
|
|
24939
|
+
stack[sp - 1] = v << amt;
|
|
24940
|
+
} else if (amt < 0) {
|
|
24941
|
+
stack[sp - 1] = v >> -amt;
|
|
24942
|
+
} else {
|
|
24943
|
+
stack[sp - 1] = v;
|
|
24944
|
+
}
|
|
24945
|
+
break;
|
|
24946
|
+
}
|
|
24947
|
+
case OP.ADD: {
|
|
24948
|
+
const b = stack[--sp];
|
|
24949
|
+
stack[sp - 1] += b;
|
|
24950
|
+
break;
|
|
24951
|
+
}
|
|
24952
|
+
case OP.SUB: {
|
|
24953
|
+
const b = stack[--sp];
|
|
24954
|
+
stack[sp - 1] -= b;
|
|
24955
|
+
break;
|
|
24956
|
+
}
|
|
24957
|
+
case OP.MUL: {
|
|
24958
|
+
const b = stack[--sp];
|
|
24959
|
+
stack[sp - 1] *= b;
|
|
24960
|
+
break;
|
|
24961
|
+
}
|
|
24962
|
+
case OP.DIV: {
|
|
24963
|
+
const b = stack[--sp];
|
|
24964
|
+
stack[sp - 1] = b !== 0 ? stack[sp - 1] / b : 0;
|
|
24965
|
+
break;
|
|
24966
|
+
}
|
|
24967
|
+
case OP.IDIV: {
|
|
24968
|
+
const b = stack[--sp];
|
|
24969
|
+
stack[sp - 1] = b !== 0 ? Math.trunc(stack[sp - 1] / b) : 0;
|
|
24970
|
+
break;
|
|
24971
|
+
}
|
|
24972
|
+
case OP.MOD: {
|
|
24973
|
+
const b = stack[--sp];
|
|
24974
|
+
stack[sp - 1] = b !== 0 ? stack[sp - 1] % b : 0;
|
|
24975
|
+
break;
|
|
24976
|
+
}
|
|
24977
|
+
case OP.POW: {
|
|
24978
|
+
const b = stack[--sp];
|
|
24979
|
+
stack[sp - 1] **= b;
|
|
24980
|
+
break;
|
|
24981
|
+
}
|
|
24982
|
+
case OP.EQ: {
|
|
24983
|
+
const b = stack[--sp];
|
|
24984
|
+
stack[sp - 1] = stack[sp - 1] === b ? 1 : 0;
|
|
24985
|
+
break;
|
|
24986
|
+
}
|
|
24987
|
+
case OP.NE: {
|
|
24988
|
+
const b = stack[--sp];
|
|
24989
|
+
stack[sp - 1] = stack[sp - 1] !== b ? 1 : 0;
|
|
24990
|
+
break;
|
|
24991
|
+
}
|
|
24992
|
+
case OP.GT: {
|
|
24993
|
+
const b = stack[--sp];
|
|
24994
|
+
stack[sp - 1] = stack[sp - 1] > b ? 1 : 0;
|
|
24995
|
+
break;
|
|
24996
|
+
}
|
|
24997
|
+
case OP.GE: {
|
|
24998
|
+
const b = stack[--sp];
|
|
24999
|
+
stack[sp - 1] = stack[sp - 1] >= b ? 1 : 0;
|
|
25000
|
+
break;
|
|
25001
|
+
}
|
|
25002
|
+
case OP.LT: {
|
|
25003
|
+
const b = stack[--sp];
|
|
25004
|
+
stack[sp - 1] = stack[sp - 1] < b ? 1 : 0;
|
|
25005
|
+
break;
|
|
25006
|
+
}
|
|
25007
|
+
case OP.LE: {
|
|
25008
|
+
const b = stack[--sp];
|
|
25009
|
+
stack[sp - 1] = stack[sp - 1] <= b ? 1 : 0;
|
|
25010
|
+
break;
|
|
25011
|
+
}
|
|
25012
|
+
case OP.AND: {
|
|
25013
|
+
const b = stack[--sp] | 0;
|
|
25014
|
+
stack[sp - 1] = (stack[sp - 1] | 0) & b;
|
|
25015
|
+
break;
|
|
25016
|
+
}
|
|
25017
|
+
case OP.OR: {
|
|
25018
|
+
const b = stack[--sp] | 0;
|
|
25019
|
+
stack[sp - 1] = stack[sp - 1] | 0 | b;
|
|
25020
|
+
break;
|
|
25021
|
+
}
|
|
25022
|
+
case OP.XOR: {
|
|
25023
|
+
const b = stack[--sp] | 0;
|
|
25024
|
+
stack[sp - 1] = (stack[sp - 1] | 0) ^ b;
|
|
25025
|
+
break;
|
|
25026
|
+
}
|
|
25027
|
+
case OP.ATAN: {
|
|
25028
|
+
const b = stack[--sp];
|
|
25029
|
+
const deg = Math.atan2(stack[sp - 1], b) * _RAD_TO_DEG;
|
|
25030
|
+
stack[sp - 1] = deg < 0 ? deg + 360 : deg;
|
|
25031
|
+
break;
|
|
25032
|
+
}
|
|
25033
|
+
case OP.MIN: {
|
|
25034
|
+
const b = stack[--sp];
|
|
25035
|
+
stack[sp - 1] = Math.min(stack[sp - 1], b);
|
|
25036
|
+
break;
|
|
25037
|
+
}
|
|
25038
|
+
case OP.MAX: {
|
|
25039
|
+
const b = stack[--sp];
|
|
25040
|
+
stack[sp - 1] = Math.max(stack[sp - 1], b);
|
|
25041
|
+
break;
|
|
25042
|
+
}
|
|
25043
|
+
case OP.TEE_TMP:
|
|
25044
|
+
tmp[ir[ip++] | 0] = stack[sp - 1];
|
|
25045
|
+
break;
|
|
25046
|
+
case OP.LOAD_TMP:
|
|
25047
|
+
stack[sp++] = tmp[ir[ip++] | 0];
|
|
25048
|
+
break;
|
|
25049
|
+
}
|
|
25050
|
+
}
|
|
25051
|
+
}
|
|
25052
|
+
};
|
|
25053
|
+
var PSStackBasedInterpreter = class {
|
|
25054
|
+
// Safe: JS is single-threaded.
|
|
25055
|
+
static #stack = new Float64Array(100);
|
|
25056
|
+
static #sp = 0;
|
|
25057
|
+
static #push(v) {
|
|
25058
|
+
if (this.#sp < this.#stack.length) {
|
|
25059
|
+
this.#stack[this.#sp++] = v;
|
|
25060
|
+
}
|
|
25061
|
+
}
|
|
25062
|
+
static #execOp(op) {
|
|
25063
|
+
const stack = this.#stack;
|
|
25064
|
+
switch (op) {
|
|
25065
|
+
case TOKEN.true:
|
|
25066
|
+
this.#push(1);
|
|
25067
|
+
break;
|
|
25068
|
+
case TOKEN.false:
|
|
25069
|
+
this.#push(0);
|
|
25070
|
+
break;
|
|
25071
|
+
case TOKEN.abs:
|
|
25072
|
+
stack[this.#sp - 1] = Math.abs(stack[this.#sp - 1]);
|
|
25073
|
+
break;
|
|
25074
|
+
case TOKEN.neg:
|
|
25075
|
+
stack[this.#sp - 1] = -stack[this.#sp - 1];
|
|
25076
|
+
break;
|
|
25077
|
+
case TOKEN.ceiling:
|
|
25078
|
+
stack[this.#sp - 1] = Math.ceil(stack[this.#sp - 1]);
|
|
25079
|
+
break;
|
|
25080
|
+
case TOKEN.floor:
|
|
25081
|
+
stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1]);
|
|
25082
|
+
break;
|
|
25083
|
+
case TOKEN.round:
|
|
25084
|
+
stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1] + 0.5);
|
|
25085
|
+
break;
|
|
25086
|
+
case TOKEN.truncate:
|
|
25087
|
+
stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]);
|
|
25088
|
+
break;
|
|
25089
|
+
case TOKEN.sqrt:
|
|
25090
|
+
stack[this.#sp - 1] = Math.sqrt(stack[this.#sp - 1]);
|
|
25091
|
+
break;
|
|
25092
|
+
case TOKEN.sin:
|
|
25093
|
+
stack[this.#sp - 1] = Math.sin(
|
|
25094
|
+
stack[this.#sp - 1] % 360 * _DEG_TO_RAD
|
|
25095
|
+
);
|
|
25096
|
+
break;
|
|
25097
|
+
case TOKEN.cos:
|
|
25098
|
+
stack[this.#sp - 1] = Math.cos(
|
|
25099
|
+
stack[this.#sp - 1] % 360 * _DEG_TO_RAD
|
|
25100
|
+
);
|
|
25101
|
+
break;
|
|
25102
|
+
case TOKEN.ln:
|
|
25103
|
+
stack[this.#sp - 1] = Math.log(stack[this.#sp - 1]);
|
|
25104
|
+
break;
|
|
25105
|
+
case TOKEN.log:
|
|
25106
|
+
stack[this.#sp - 1] = Math.log10(stack[this.#sp - 1]);
|
|
25107
|
+
break;
|
|
25108
|
+
case TOKEN.cvi:
|
|
25109
|
+
stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]) | 0;
|
|
25110
|
+
break;
|
|
25111
|
+
case TOKEN.cvr:
|
|
25112
|
+
break;
|
|
25113
|
+
// values are already f64
|
|
25114
|
+
case TOKEN.not: {
|
|
25115
|
+
const v = stack[this.#sp - 1];
|
|
25116
|
+
stack[this.#sp - 1] = v === 0 || v === 1 ? 1 - v : ~(v | 0);
|
|
25117
|
+
break;
|
|
25118
|
+
}
|
|
25119
|
+
case TOKEN.add: {
|
|
25120
|
+
const b = stack[--this.#sp];
|
|
25121
|
+
stack[this.#sp - 1] += b;
|
|
25122
|
+
break;
|
|
25123
|
+
}
|
|
25124
|
+
case TOKEN.sub: {
|
|
25125
|
+
const b = stack[--this.#sp];
|
|
25126
|
+
stack[this.#sp - 1] -= b;
|
|
25127
|
+
break;
|
|
25128
|
+
}
|
|
25129
|
+
case TOKEN.mul: {
|
|
25130
|
+
const b = stack[--this.#sp];
|
|
25131
|
+
stack[this.#sp - 1] *= b;
|
|
25132
|
+
break;
|
|
25133
|
+
}
|
|
25134
|
+
case TOKEN.div: {
|
|
25135
|
+
const b = stack[--this.#sp];
|
|
25136
|
+
stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] / b : 0;
|
|
25137
|
+
break;
|
|
25138
|
+
}
|
|
25139
|
+
case TOKEN.idiv: {
|
|
25140
|
+
const b = stack[--this.#sp];
|
|
25141
|
+
stack[this.#sp - 1] = b !== 0 ? Math.trunc(stack[this.#sp - 1] / b) : 0;
|
|
25142
|
+
break;
|
|
25143
|
+
}
|
|
25144
|
+
case TOKEN.mod: {
|
|
25145
|
+
const b = stack[--this.#sp];
|
|
25146
|
+
stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] % b : 0;
|
|
25147
|
+
break;
|
|
25148
|
+
}
|
|
25149
|
+
case TOKEN.exp: {
|
|
25150
|
+
const b = stack[--this.#sp];
|
|
25151
|
+
stack[this.#sp - 1] **= b;
|
|
25152
|
+
break;
|
|
25153
|
+
}
|
|
25154
|
+
case TOKEN.atan: {
|
|
25155
|
+
const dx = stack[--this.#sp];
|
|
25156
|
+
const deg = Math.atan2(stack[this.#sp - 1], dx) * _RAD_TO_DEG;
|
|
25157
|
+
stack[this.#sp - 1] = deg < 0 ? deg + 360 : deg;
|
|
25158
|
+
break;
|
|
25159
|
+
}
|
|
25160
|
+
case TOKEN.eq: {
|
|
25161
|
+
const b = stack[--this.#sp];
|
|
25162
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] === b ? 1 : 0;
|
|
25163
|
+
break;
|
|
25164
|
+
}
|
|
25165
|
+
case TOKEN.ne: {
|
|
25166
|
+
const b = stack[--this.#sp];
|
|
25167
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] !== b ? 1 : 0;
|
|
25168
|
+
break;
|
|
25169
|
+
}
|
|
25170
|
+
case TOKEN.gt: {
|
|
25171
|
+
const b = stack[--this.#sp];
|
|
25172
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] > b ? 1 : 0;
|
|
25173
|
+
break;
|
|
25174
|
+
}
|
|
25175
|
+
case TOKEN.ge: {
|
|
25176
|
+
const b = stack[--this.#sp];
|
|
25177
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] >= b ? 1 : 0;
|
|
25178
|
+
break;
|
|
25179
|
+
}
|
|
25180
|
+
case TOKEN.lt: {
|
|
25181
|
+
const b = stack[--this.#sp];
|
|
25182
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] < b ? 1 : 0;
|
|
25183
|
+
break;
|
|
25184
|
+
}
|
|
25185
|
+
case TOKEN.le: {
|
|
25186
|
+
const b = stack[--this.#sp];
|
|
25187
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] <= b ? 1 : 0;
|
|
25188
|
+
break;
|
|
25189
|
+
}
|
|
25190
|
+
case TOKEN.and: {
|
|
25191
|
+
const b = stack[--this.#sp] | 0;
|
|
25192
|
+
stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) & b;
|
|
25193
|
+
break;
|
|
25194
|
+
}
|
|
25195
|
+
case TOKEN.or: {
|
|
25196
|
+
const b = stack[--this.#sp] | 0;
|
|
25197
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] | 0 | b;
|
|
25198
|
+
break;
|
|
25199
|
+
}
|
|
25200
|
+
case TOKEN.xor: {
|
|
25201
|
+
const b = stack[--this.#sp] | 0;
|
|
25202
|
+
stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) ^ b;
|
|
25203
|
+
break;
|
|
25204
|
+
}
|
|
25205
|
+
case TOKEN.bitshift: {
|
|
25206
|
+
const amt = stack[--this.#sp] | 0;
|
|
25207
|
+
const v = stack[this.#sp - 1] | 0;
|
|
25208
|
+
stack[this.#sp - 1] = amt > 0 ? v << amt : v >> -amt;
|
|
25209
|
+
break;
|
|
25210
|
+
}
|
|
25211
|
+
case TOKEN.min: {
|
|
25212
|
+
const b = stack[--this.#sp];
|
|
25213
|
+
stack[this.#sp - 1] = Math.min(stack[this.#sp - 1], b);
|
|
25214
|
+
break;
|
|
25215
|
+
}
|
|
25216
|
+
case TOKEN.max: {
|
|
25217
|
+
const b = stack[--this.#sp];
|
|
25218
|
+
stack[this.#sp - 1] = Math.max(stack[this.#sp - 1], b);
|
|
25219
|
+
break;
|
|
25220
|
+
}
|
|
25221
|
+
case TOKEN.dup:
|
|
25222
|
+
this.#push(stack[this.#sp - 1]);
|
|
25223
|
+
break;
|
|
25224
|
+
case TOKEN.exch: {
|
|
25225
|
+
const a = stack[--this.#sp];
|
|
25226
|
+
const b = stack[--this.#sp];
|
|
25227
|
+
this.#push(a);
|
|
25228
|
+
this.#push(b);
|
|
25229
|
+
break;
|
|
25230
|
+
}
|
|
25231
|
+
case TOKEN.pop:
|
|
25232
|
+
this.#sp--;
|
|
25233
|
+
break;
|
|
25234
|
+
case TOKEN.copy: {
|
|
25235
|
+
const n = Math.trunc(stack[--this.#sp]);
|
|
25236
|
+
const base = this.#sp - n;
|
|
25237
|
+
for (let k = 0; k < n; k++) {
|
|
25238
|
+
this.#push(stack[base + k]);
|
|
25239
|
+
}
|
|
25240
|
+
break;
|
|
25241
|
+
}
|
|
25242
|
+
case TOKEN.index: {
|
|
25243
|
+
const i = Math.trunc(stack[--this.#sp]);
|
|
25244
|
+
this.#push(stack[this.#sp - 1 - i]);
|
|
25245
|
+
break;
|
|
25246
|
+
}
|
|
25247
|
+
case TOKEN.roll: {
|
|
25248
|
+
const j = Math.trunc(stack[--this.#sp]);
|
|
25249
|
+
const n = Math.trunc(stack[--this.#sp]);
|
|
25250
|
+
if (n > 1 && j !== 0) {
|
|
25251
|
+
const mod = (j % n + n) % n;
|
|
25252
|
+
if (mod !== 0) {
|
|
25253
|
+
const base = this.#sp - n;
|
|
25254
|
+
const sub = stack.slice(base, this.#sp);
|
|
25255
|
+
for (let k = 0; k < n; k++) {
|
|
25256
|
+
stack[base + k] = sub[(k - mod + n) % n];
|
|
25257
|
+
}
|
|
25258
|
+
}
|
|
25259
|
+
}
|
|
25260
|
+
break;
|
|
25261
|
+
}
|
|
25262
|
+
}
|
|
25263
|
+
}
|
|
25264
|
+
static #execBlock(instructions) {
|
|
25265
|
+
for (const instr of instructions) {
|
|
25266
|
+
switch (instr.type) {
|
|
25267
|
+
case PS_NODE.number:
|
|
25268
|
+
this.#push(instr.value);
|
|
25269
|
+
break;
|
|
25270
|
+
case PS_NODE.operator:
|
|
25271
|
+
this.#execOp(instr.op);
|
|
25272
|
+
break;
|
|
25273
|
+
case PS_NODE.if:
|
|
25274
|
+
if (this.#stack[--this.#sp] !== 0) {
|
|
25275
|
+
this.#execBlock(instr.then.instructions);
|
|
25276
|
+
}
|
|
25277
|
+
break;
|
|
25278
|
+
case PS_NODE.ifelse:
|
|
25279
|
+
if (this.#stack[--this.#sp] !== 0) {
|
|
25280
|
+
this.#execBlock(instr.then.instructions);
|
|
25281
|
+
} else {
|
|
25282
|
+
this.#execBlock(instr.otherwise.instructions);
|
|
25283
|
+
}
|
|
25284
|
+
break;
|
|
25285
|
+
}
|
|
25286
|
+
}
|
|
25287
|
+
}
|
|
25288
|
+
/**
|
|
25289
|
+
* @param {import("./ast.js").PsProgram} program
|
|
25290
|
+
* @param {number[]} domain – flat [min0,max0, …]
|
|
25291
|
+
* @param {number[]} range – flat [min0,max0, …]
|
|
25292
|
+
* @returns {Function} – `(src, srcOffset, dest, destOffset) => void`
|
|
25293
|
+
*/
|
|
25294
|
+
static build(program, domain, range) {
|
|
25295
|
+
const nIn = domain.length >> 1;
|
|
25296
|
+
const nOut = range.length >> 1;
|
|
25297
|
+
const { instructions } = program.body;
|
|
25298
|
+
return (src, srcOffset, dest, destOffset) => {
|
|
25299
|
+
this.#sp = 0;
|
|
25300
|
+
for (let i = 0; i < nIn; i++) {
|
|
25301
|
+
this.#push(src[srcOffset + i]);
|
|
25302
|
+
}
|
|
25303
|
+
this.#execBlock(instructions);
|
|
25304
|
+
const base = this.#sp - nOut;
|
|
25305
|
+
for (let i = 0; i < nOut; i++) {
|
|
25306
|
+
const v = base + i >= 0 ? this.#stack[base + i] : 0;
|
|
25307
|
+
dest[destOffset + i] = MathClamp(v, range[i * 2], range[i * 2 + 1]);
|
|
25308
|
+
}
|
|
25309
|
+
};
|
|
25310
|
+
}
|
|
25311
|
+
};
|
|
25312
|
+
function buildPostScriptJsFunction(source, domain, range, forceInterpreter = false) {
|
|
25313
|
+
const program = parsePostScriptFunction(source);
|
|
25314
|
+
const ir = !forceInterpreter && new PsJsCompiler(domain, range).compile(program);
|
|
25315
|
+
if (ir) {
|
|
25316
|
+
return (src, srcOffset, dest, destOffset) => {
|
|
25317
|
+
PsJsCompiler.execute(ir, src, srcOffset, dest, destOffset);
|
|
25318
|
+
};
|
|
25319
|
+
}
|
|
25320
|
+
return PSStackBasedInterpreter.build(program, domain, range);
|
|
25321
|
+
}
|
|
25322
|
+
var ShadingType = {
|
|
25323
|
+
FUNCTION_BASED: 1,
|
|
25324
|
+
AXIAL: 2,
|
|
25325
|
+
RADIAL: 3,
|
|
25326
|
+
FREE_FORM_MESH: 4,
|
|
25327
|
+
LATTICE_FORM_MESH: 5,
|
|
25328
|
+
COONS_PATCH_MESH: 6,
|
|
25329
|
+
TENSOR_PATCH_MESH: 7
|
|
25330
|
+
};
|
|
25331
|
+
var BaseShading = class _BaseShading {
|
|
25332
|
+
// A small number to offset the first/last color stops so we can insert ones
|
|
25333
|
+
// to support extend. Number.MIN_VALUE is too small and breaks the extend.
|
|
25334
|
+
static SMALL_NUMBER = 1e-6;
|
|
25335
|
+
constructor() {
|
|
25336
|
+
if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _BaseShading) {
|
|
25337
|
+
unreachable2("Cannot initialize BaseShading.");
|
|
25338
|
+
}
|
|
25339
|
+
}
|
|
25340
|
+
getIR() {
|
|
25341
|
+
unreachable2("Abstract method `getIR` called.");
|
|
25342
|
+
}
|
|
25343
|
+
};
|
|
25344
|
+
function meshUpdateBounds(self) {
|
|
25345
|
+
let minX = self.coords[0][0], minY = self.coords[0][1], maxX = minX, maxY = minY;
|
|
25346
|
+
for (let i = 1, ii = self.coords.length; i < ii; i++) {
|
|
25347
|
+
const x = self.coords[i][0], y = self.coords[i][1];
|
|
25348
|
+
minX = minX > x ? x : minX;
|
|
25349
|
+
minY = minY > y ? y : minY;
|
|
25350
|
+
maxX = maxX < x ? x : maxX;
|
|
25351
|
+
maxY = maxY < y ? y : maxY;
|
|
25352
|
+
}
|
|
25353
|
+
self.bounds = [minX, minY, maxX, maxY];
|
|
25354
|
+
}
|
|
25355
|
+
function meshPackData(self) {
|
|
25356
|
+
let i, j, ii;
|
|
25357
|
+
const coords = self.coords;
|
|
25358
|
+
const coordsPacked = new Float32Array(coords.length * 2);
|
|
25359
|
+
for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
|
|
25360
|
+
const xy = coords[i];
|
|
25361
|
+
coordsPacked[j++] = xy[0];
|
|
25362
|
+
coordsPacked[j++] = xy[1];
|
|
25363
|
+
}
|
|
25364
|
+
self.coords = coordsPacked;
|
|
25365
|
+
const colors = self.colors;
|
|
25366
|
+
const colorsPacked = new Uint8Array(colors.length * 4);
|
|
25367
|
+
for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
|
|
25368
|
+
const c = colors[i];
|
|
25369
|
+
colorsPacked[j++] = c[0];
|
|
25370
|
+
colorsPacked[j++] = c[1];
|
|
25371
|
+
colorsPacked[j++] = c[2];
|
|
25372
|
+
j++;
|
|
25373
|
+
}
|
|
25374
|
+
self.colors = colorsPacked;
|
|
25375
|
+
for (const figure of self.figures) {
|
|
25376
|
+
figure.coords = new Uint32Array(figure.coords);
|
|
25377
|
+
figure.colors = new Uint32Array(figure.colors);
|
|
25378
|
+
}
|
|
25379
|
+
}
|
|
25380
|
+
function buildMeshVertexData(coords, colors, figures) {
|
|
25381
|
+
let vertexCount = 0;
|
|
25382
|
+
for (const figure of figures) {
|
|
25383
|
+
if (figure.type === MeshFigureType.TRIANGLES) {
|
|
25384
|
+
vertexCount += figure.coords.length;
|
|
25385
|
+
} else if (figure.type === MeshFigureType.LATTICE) {
|
|
25386
|
+
const vpr = figure.verticesPerRow;
|
|
25387
|
+
vertexCount += (Math.floor(figure.coords.length / vpr) - 1) * (vpr - 1) * 6;
|
|
25388
|
+
}
|
|
25389
|
+
}
|
|
25390
|
+
const posData = new Float32Array(vertexCount * 2);
|
|
25391
|
+
const colData = new Uint8Array(vertexCount * 4);
|
|
25392
|
+
let pOff = 0, cOff = 0;
|
|
25393
|
+
const addVertex = (pi, ci) => {
|
|
25394
|
+
posData[pOff++] = coords[pi * 2];
|
|
25395
|
+
posData[pOff++] = coords[pi * 2 + 1];
|
|
25396
|
+
colData[cOff++] = colors[ci * 4];
|
|
25397
|
+
colData[cOff++] = colors[ci * 4 + 1];
|
|
25398
|
+
colData[cOff++] = colors[ci * 4 + 2];
|
|
25399
|
+
cOff++;
|
|
25400
|
+
};
|
|
25401
|
+
for (const figure of figures) {
|
|
25402
|
+
const ps = figure.coords;
|
|
25403
|
+
const cs = figure.colors;
|
|
25404
|
+
if (figure.type === MeshFigureType.TRIANGLES) {
|
|
25405
|
+
for (let i = 0, ii = ps.length; i < ii; i++) {
|
|
25406
|
+
addVertex(ps[i], cs[i]);
|
|
25407
|
+
}
|
|
25408
|
+
} else if (figure.type === MeshFigureType.LATTICE) {
|
|
25409
|
+
const vpr = figure.verticesPerRow;
|
|
25410
|
+
const rows = Math.floor(ps.length / vpr) - 1;
|
|
25411
|
+
const cols = vpr - 1;
|
|
25412
|
+
for (let i = 0; i < rows; i++) {
|
|
25413
|
+
let q = i * vpr;
|
|
25414
|
+
for (let j = 0; j < cols; j++, q++) {
|
|
25415
|
+
addVertex(ps[q], cs[q]);
|
|
25416
|
+
addVertex(ps[q + 1], cs[q + 1]);
|
|
25417
|
+
addVertex(ps[q + vpr], cs[q + vpr]);
|
|
25418
|
+
addVertex(ps[q + vpr + 1], cs[q + vpr + 1]);
|
|
25419
|
+
addVertex(ps[q + 1], cs[q + 1]);
|
|
25420
|
+
addVertex(ps[q + vpr], cs[q + vpr]);
|
|
25421
|
+
}
|
|
25422
|
+
}
|
|
25423
|
+
}
|
|
25424
|
+
}
|
|
25425
|
+
return { posData, colData, vertexCount };
|
|
25426
|
+
}
|
|
25427
|
+
var MeshStreamReader = class {
|
|
25428
|
+
constructor(stream, context) {
|
|
25429
|
+
this.stream = stream;
|
|
25430
|
+
this.context = context;
|
|
25431
|
+
this.buffer = 0;
|
|
25432
|
+
this.bufferLength = 0;
|
|
25433
|
+
const numComps = context.numComps;
|
|
25434
|
+
this.tmpCompsBuf = new Float32Array(numComps);
|
|
25435
|
+
const csNumComps = context.colorSpace.numComps;
|
|
25436
|
+
this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf;
|
|
25437
|
+
}
|
|
25438
|
+
get hasData() {
|
|
25439
|
+
if (this.stream.end) {
|
|
25440
|
+
return this.stream.pos < this.stream.end;
|
|
25441
|
+
}
|
|
25442
|
+
if (this.bufferLength > 0) {
|
|
25443
|
+
return true;
|
|
25444
|
+
}
|
|
25445
|
+
const nextByte = this.stream.getByte();
|
|
25446
|
+
if (nextByte < 0) {
|
|
25447
|
+
return false;
|
|
25448
|
+
}
|
|
25449
|
+
this.buffer = nextByte;
|
|
25450
|
+
this.bufferLength = 8;
|
|
25451
|
+
return true;
|
|
25452
|
+
}
|
|
25453
|
+
readBits(n) {
|
|
25454
|
+
const { stream } = this;
|
|
25455
|
+
let { buffer, bufferLength } = this;
|
|
25456
|
+
if (n === 32) {
|
|
25457
|
+
if (bufferLength === 0) {
|
|
25458
|
+
return stream.getInt32() >>> 0;
|
|
25459
|
+
}
|
|
25460
|
+
buffer = buffer << 24 | stream.getByte() << 16 | stream.getByte() << 8 | stream.getByte();
|
|
25461
|
+
const nextByte = stream.getByte();
|
|
25462
|
+
this.buffer = nextByte & (1 << bufferLength) - 1;
|
|
25463
|
+
return (buffer << 8 - bufferLength | (nextByte & 255) >> bufferLength) >>> 0;
|
|
25464
|
+
}
|
|
25465
|
+
if (n === 8 && bufferLength === 0) {
|
|
25466
|
+
return stream.getByte();
|
|
25467
|
+
}
|
|
25468
|
+
while (bufferLength < n) {
|
|
25469
|
+
buffer = buffer << 8 | stream.getByte();
|
|
25470
|
+
bufferLength += 8;
|
|
25471
|
+
}
|
|
25472
|
+
bufferLength -= n;
|
|
25473
|
+
this.bufferLength = bufferLength;
|
|
25474
|
+
this.buffer = buffer & (1 << bufferLength) - 1;
|
|
25475
|
+
return buffer >> bufferLength;
|
|
25476
|
+
}
|
|
25477
|
+
align() {
|
|
25478
|
+
this.buffer = 0;
|
|
25479
|
+
this.bufferLength = 0;
|
|
25480
|
+
}
|
|
25481
|
+
readFlag() {
|
|
25482
|
+
return this.readBits(this.context.bitsPerFlag);
|
|
25483
|
+
}
|
|
25484
|
+
readCoordinate() {
|
|
25485
|
+
const { bitsPerCoordinate, decode } = this.context;
|
|
25486
|
+
const xi = this.readBits(bitsPerCoordinate);
|
|
25487
|
+
const yi = this.readBits(bitsPerCoordinate);
|
|
25488
|
+
const scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 23283064365386963e-26;
|
|
25489
|
+
return [
|
|
25490
|
+
xi * scale * (decode[1] - decode[0]) + decode[0],
|
|
25491
|
+
yi * scale * (decode[3] - decode[2]) + decode[2]
|
|
25492
|
+
];
|
|
25493
|
+
}
|
|
25494
|
+
readComponents() {
|
|
25495
|
+
const { bitsPerComponent, colorFn, colorSpace, decode, numComps } = this.context;
|
|
25496
|
+
const scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 23283064365386963e-26;
|
|
25497
|
+
const components = this.tmpCompsBuf;
|
|
25498
|
+
for (let i = 0, j = 4; i < numComps; i++, j += 2) {
|
|
25499
|
+
const ci = this.readBits(bitsPerComponent);
|
|
25500
|
+
components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j];
|
|
25501
|
+
}
|
|
25502
|
+
const color = this.tmpCsCompsBuf;
|
|
25503
|
+
colorFn?.(components, 0, color, 0);
|
|
25504
|
+
return colorSpace.getRgb(color, 0);
|
|
25505
|
+
}
|
|
25506
|
+
};
|
|
25507
|
+
var bCache = null;
|
|
25508
|
+
function getB(count) {
|
|
25509
|
+
if (bCache?.has(count)) return bCache.get(count);
|
|
25510
|
+
const values = Array.from({ length: count + 1 }, (_, i) => {
|
|
25511
|
+
const t = i / count, t_ = 1 - t;
|
|
25512
|
+
return new Float32Array([
|
|
25513
|
+
t_ ** 3,
|
|
25514
|
+
3 * t * t_ ** 2,
|
|
25515
|
+
3 * t ** 2 * t_,
|
|
25516
|
+
t ** 3
|
|
25517
|
+
]);
|
|
25518
|
+
});
|
|
25519
|
+
(bCache ??= /* @__PURE__ */ new Map()).set(count, values);
|
|
25520
|
+
return values;
|
|
25521
|
+
}
|
|
25522
|
+
var MeshShading = class _MeshShading extends BaseShading {
|
|
25523
|
+
static MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;
|
|
25524
|
+
static MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;
|
|
25525
|
+
// Count of triangles per entire mesh bounds.
|
|
25526
|
+
static TRIANGLE_DENSITY = 20;
|
|
25527
|
+
constructor(shadingType, stream, context, rowVertices) {
|
|
25528
|
+
super();
|
|
25529
|
+
this.shadingType = shadingType;
|
|
25530
|
+
this.bbox = this.background = null;
|
|
25531
|
+
this.coords = [];
|
|
25532
|
+
this.colors = [];
|
|
25533
|
+
this.figures = [];
|
|
25534
|
+
const reader = new MeshStreamReader(stream, context);
|
|
25535
|
+
let patchMesh = false;
|
|
25536
|
+
switch (this.shadingType) {
|
|
25537
|
+
case ShadingType.FREE_FORM_MESH:
|
|
25538
|
+
this._decodeType4Shading(reader);
|
|
25539
|
+
break;
|
|
25540
|
+
case ShadingType.LATTICE_FORM_MESH:
|
|
25541
|
+
const verticesPerRow = rowVertices | 0;
|
|
25542
|
+
if (verticesPerRow < 2) {
|
|
25543
|
+
throw new FormatError("Invalid VerticesPerRow");
|
|
25544
|
+
}
|
|
25545
|
+
this._decodeType5Shading(reader, verticesPerRow);
|
|
25546
|
+
break;
|
|
25547
|
+
case ShadingType.COONS_PATCH_MESH:
|
|
25548
|
+
this._decodeType6Shading(reader);
|
|
25549
|
+
patchMesh = true;
|
|
25550
|
+
break;
|
|
25551
|
+
case ShadingType.TENSOR_PATCH_MESH:
|
|
25552
|
+
this._decodeType7Shading(reader);
|
|
25553
|
+
patchMesh = true;
|
|
25554
|
+
break;
|
|
25555
|
+
default:
|
|
25556
|
+
unreachable2("Unsupported mesh type.");
|
|
25557
|
+
break;
|
|
25558
|
+
}
|
|
25559
|
+
if (patchMesh) {
|
|
25560
|
+
this._updateBounds();
|
|
25561
|
+
for (let i = 0, ii = this.figures.length; i < ii; i++) {
|
|
25562
|
+
this._buildFigureFromPatch(i);
|
|
25563
|
+
}
|
|
25564
|
+
}
|
|
25565
|
+
this._updateBounds();
|
|
25566
|
+
this._packData();
|
|
25567
|
+
}
|
|
25568
|
+
_decodeType4Shading(reader) {
|
|
25569
|
+
const coords = this.coords;
|
|
25570
|
+
const colors = this.colors;
|
|
25571
|
+
const operators = [];
|
|
25572
|
+
const ps = [];
|
|
25573
|
+
let verticesLeft = 0;
|
|
25574
|
+
while (reader.hasData) {
|
|
25575
|
+
const f = reader.readFlag();
|
|
25576
|
+
const coord = reader.readCoordinate();
|
|
25577
|
+
const color = reader.readComponents();
|
|
25578
|
+
if (verticesLeft === 0) {
|
|
25579
|
+
if (!(0 <= f && f <= 2)) {
|
|
25580
|
+
throw new FormatError("Unknown type4 flag");
|
|
25581
|
+
}
|
|
25582
|
+
switch (f) {
|
|
25583
|
+
case 0:
|
|
25584
|
+
verticesLeft = 3;
|
|
25585
|
+
break;
|
|
25586
|
+
case 1:
|
|
25587
|
+
ps.push(ps.at(-2), ps.at(-1));
|
|
25588
|
+
verticesLeft = 1;
|
|
25589
|
+
break;
|
|
25590
|
+
case 2:
|
|
25591
|
+
ps.push(ps.at(-3), ps.at(-1));
|
|
25592
|
+
verticesLeft = 1;
|
|
25593
|
+
break;
|
|
25594
|
+
}
|
|
25595
|
+
operators.push(f);
|
|
25596
|
+
}
|
|
25597
|
+
ps.push(coords.length);
|
|
25598
|
+
coords.push(coord);
|
|
25599
|
+
colors.push(color);
|
|
25600
|
+
verticesLeft--;
|
|
25601
|
+
reader.align();
|
|
25602
|
+
}
|
|
25603
|
+
this.figures.push({
|
|
25604
|
+
type: MeshFigureType.TRIANGLES,
|
|
25605
|
+
coords: new Int32Array(ps),
|
|
25606
|
+
colors: new Int32Array(ps)
|
|
25607
|
+
});
|
|
25608
|
+
}
|
|
25609
|
+
_decodeType5Shading(reader, verticesPerRow) {
|
|
25610
|
+
const coords = this.coords;
|
|
25611
|
+
const colors = this.colors;
|
|
25612
|
+
const ps = [];
|
|
25613
|
+
while (reader.hasData) {
|
|
25614
|
+
const coord = reader.readCoordinate();
|
|
25615
|
+
const color = reader.readComponents();
|
|
25616
|
+
ps.push(coords.length);
|
|
25617
|
+
coords.push(coord);
|
|
25618
|
+
colors.push(color);
|
|
25619
|
+
}
|
|
25620
|
+
this.figures.push({
|
|
25621
|
+
type: MeshFigureType.LATTICE,
|
|
25622
|
+
coords: new Int32Array(ps),
|
|
25623
|
+
colors: new Int32Array(ps),
|
|
25624
|
+
verticesPerRow
|
|
25625
|
+
});
|
|
25626
|
+
}
|
|
25627
|
+
_decodeType6Shading(reader) {
|
|
25628
|
+
const coords = this.coords;
|
|
25629
|
+
const colors = this.colors;
|
|
25630
|
+
const ps = new Int32Array(16);
|
|
25631
|
+
const cs = new Int32Array(4);
|
|
25632
|
+
while (reader.hasData) {
|
|
25633
|
+
const f = reader.readFlag();
|
|
25634
|
+
if (!(0 <= f && f <= 3)) {
|
|
25635
|
+
throw new FormatError("Unknown type6 flag");
|
|
25636
|
+
}
|
|
25637
|
+
const pi = coords.length;
|
|
25638
|
+
for (let i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) {
|
|
25639
|
+
coords.push(reader.readCoordinate());
|
|
25640
|
+
}
|
|
25641
|
+
const ci = colors.length;
|
|
25642
|
+
for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
|
|
25643
|
+
colors.push(reader.readComponents());
|
|
25644
|
+
}
|
|
25645
|
+
let tmp1, tmp2, tmp3, tmp4;
|
|
25646
|
+
switch (f) {
|
|
25647
|
+
// prettier-ignore
|
|
25648
|
+
case 0:
|
|
25649
|
+
ps[12] = pi + 3;
|
|
25650
|
+
ps[13] = pi + 4;
|
|
25651
|
+
ps[14] = pi + 5;
|
|
25652
|
+
ps[15] = pi + 6;
|
|
25653
|
+
ps[8] = pi + 2;
|
|
25654
|
+
ps[11] = pi + 7;
|
|
25655
|
+
ps[4] = pi + 1;
|
|
25656
|
+
ps[7] = pi + 8;
|
|
25657
|
+
ps[0] = pi;
|
|
25658
|
+
ps[1] = pi + 11;
|
|
25659
|
+
ps[2] = pi + 10;
|
|
25660
|
+
ps[3] = pi + 9;
|
|
25661
|
+
cs[2] = ci + 1;
|
|
25662
|
+
cs[3] = ci + 2;
|
|
25663
|
+
cs[0] = ci;
|
|
25664
|
+
cs[1] = ci + 3;
|
|
25665
|
+
break;
|
|
25666
|
+
// prettier-ignore
|
|
25667
|
+
case 1:
|
|
25668
|
+
tmp1 = ps[12];
|
|
25669
|
+
tmp2 = ps[13];
|
|
25670
|
+
tmp3 = ps[14];
|
|
25671
|
+
tmp4 = ps[15];
|
|
25672
|
+
ps[12] = tmp4;
|
|
25673
|
+
ps[13] = pi + 0;
|
|
25674
|
+
ps[14] = pi + 1;
|
|
25675
|
+
ps[15] = pi + 2;
|
|
25676
|
+
ps[8] = tmp3;
|
|
25677
|
+
ps[11] = pi + 3;
|
|
25678
|
+
ps[4] = tmp2;
|
|
25679
|
+
ps[7] = pi + 4;
|
|
25680
|
+
ps[0] = tmp1;
|
|
25681
|
+
ps[1] = pi + 7;
|
|
25682
|
+
ps[2] = pi + 6;
|
|
25683
|
+
ps[3] = pi + 5;
|
|
25684
|
+
tmp1 = cs[2];
|
|
25685
|
+
tmp2 = cs[3];
|
|
25686
|
+
cs[2] = tmp2;
|
|
25687
|
+
cs[3] = ci;
|
|
25688
|
+
cs[0] = tmp1;
|
|
25689
|
+
cs[1] = ci + 1;
|
|
25690
|
+
break;
|
|
25691
|
+
// prettier-ignore
|
|
25692
|
+
case 2:
|
|
25693
|
+
tmp1 = ps[15];
|
|
25694
|
+
tmp2 = ps[11];
|
|
25695
|
+
ps[12] = ps[3];
|
|
25696
|
+
ps[13] = pi + 0;
|
|
25697
|
+
ps[14] = pi + 1;
|
|
25698
|
+
ps[15] = pi + 2;
|
|
25699
|
+
ps[8] = ps[7];
|
|
25700
|
+
ps[11] = pi + 3;
|
|
25701
|
+
ps[4] = tmp2;
|
|
25702
|
+
ps[7] = pi + 4;
|
|
25703
|
+
ps[0] = tmp1;
|
|
25704
|
+
ps[1] = pi + 7;
|
|
25705
|
+
ps[2] = pi + 6;
|
|
25706
|
+
ps[3] = pi + 5;
|
|
25707
|
+
tmp1 = cs[3];
|
|
25708
|
+
cs[2] = cs[1];
|
|
25709
|
+
cs[3] = ci;
|
|
25710
|
+
cs[0] = tmp1;
|
|
25711
|
+
cs[1] = ci + 1;
|
|
25712
|
+
break;
|
|
25713
|
+
// prettier-ignore
|
|
25714
|
+
case 3:
|
|
25715
|
+
ps[12] = ps[0];
|
|
25716
|
+
ps[13] = pi + 0;
|
|
25717
|
+
ps[14] = pi + 1;
|
|
25718
|
+
ps[15] = pi + 2;
|
|
25719
|
+
ps[8] = ps[1];
|
|
25720
|
+
ps[11] = pi + 3;
|
|
25721
|
+
ps[4] = ps[2];
|
|
25722
|
+
ps[7] = pi + 4;
|
|
25723
|
+
ps[0] = ps[3];
|
|
25724
|
+
ps[1] = pi + 7;
|
|
25725
|
+
ps[2] = pi + 6;
|
|
25726
|
+
ps[3] = pi + 5;
|
|
25727
|
+
cs[2] = cs[0];
|
|
25728
|
+
cs[3] = ci;
|
|
25729
|
+
cs[0] = cs[1];
|
|
25730
|
+
cs[1] = ci + 1;
|
|
25731
|
+
break;
|
|
25732
|
+
}
|
|
25733
|
+
ps[5] = coords.length;
|
|
25734
|
+
coords.push([
|
|
25735
|
+
(-4 * coords[ps[0]][0] - coords[ps[15]][0] + 6 * (coords[ps[4]][0] + coords[ps[1]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9,
|
|
25736
|
+
(-4 * coords[ps[0]][1] - coords[ps[15]][1] + 6 * (coords[ps[4]][1] + coords[ps[1]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9
|
|
25737
|
+
]);
|
|
25738
|
+
ps[6] = coords.length;
|
|
25739
|
+
coords.push([
|
|
25740
|
+
(-4 * coords[ps[3]][0] - coords[ps[12]][0] + 6 * (coords[ps[2]][0] + coords[ps[7]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9,
|
|
25741
|
+
(-4 * coords[ps[3]][1] - coords[ps[12]][1] + 6 * (coords[ps[2]][1] + coords[ps[7]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9
|
|
25742
|
+
]);
|
|
25743
|
+
ps[9] = coords.length;
|
|
25744
|
+
coords.push([
|
|
25745
|
+
(-4 * coords[ps[12]][0] - coords[ps[3]][0] + 6 * (coords[ps[8]][0] + coords[ps[13]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9,
|
|
25746
|
+
(-4 * coords[ps[12]][1] - coords[ps[3]][1] + 6 * (coords[ps[8]][1] + coords[ps[13]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9
|
|
25747
|
+
]);
|
|
25748
|
+
ps[10] = coords.length;
|
|
25749
|
+
coords.push([
|
|
25750
|
+
(-4 * coords[ps[15]][0] - coords[ps[0]][0] + 6 * (coords[ps[11]][0] + coords[ps[14]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9,
|
|
25751
|
+
(-4 * coords[ps[15]][1] - coords[ps[0]][1] + 6 * (coords[ps[11]][1] + coords[ps[14]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9
|
|
25752
|
+
]);
|
|
25753
|
+
this.figures.push({
|
|
25754
|
+
type: MeshFigureType.PATCH,
|
|
25755
|
+
coords: new Int32Array(ps),
|
|
25756
|
+
// making copies of ps and cs
|
|
25757
|
+
colors: new Int32Array(cs)
|
|
25758
|
+
});
|
|
25759
|
+
}
|
|
25760
|
+
}
|
|
25761
|
+
_decodeType7Shading(reader) {
|
|
25762
|
+
const coords = this.coords;
|
|
25763
|
+
const colors = this.colors;
|
|
25764
|
+
const ps = new Int32Array(16);
|
|
25765
|
+
const cs = new Int32Array(4);
|
|
25766
|
+
while (reader.hasData) {
|
|
25767
|
+
const f = reader.readFlag();
|
|
25768
|
+
if (!(0 <= f && f <= 3)) {
|
|
25769
|
+
throw new FormatError("Unknown type7 flag");
|
|
25770
|
+
}
|
|
25771
|
+
const pi = coords.length;
|
|
25772
|
+
for (let i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) {
|
|
25773
|
+
coords.push(reader.readCoordinate());
|
|
25774
|
+
}
|
|
25775
|
+
const ci = colors.length;
|
|
25776
|
+
for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
|
|
25777
|
+
colors.push(reader.readComponents());
|
|
25778
|
+
}
|
|
25779
|
+
let tmp1, tmp2, tmp3, tmp4;
|
|
25780
|
+
switch (f) {
|
|
25781
|
+
// prettier-ignore
|
|
25782
|
+
case 0:
|
|
25783
|
+
ps[12] = pi + 3;
|
|
25784
|
+
ps[13] = pi + 4;
|
|
25785
|
+
ps[14] = pi + 5;
|
|
25786
|
+
ps[15] = pi + 6;
|
|
25787
|
+
ps[8] = pi + 2;
|
|
25788
|
+
ps[9] = pi + 13;
|
|
25789
|
+
ps[10] = pi + 14;
|
|
25790
|
+
ps[11] = pi + 7;
|
|
25791
|
+
ps[4] = pi + 1;
|
|
25792
|
+
ps[5] = pi + 12;
|
|
25793
|
+
ps[6] = pi + 15;
|
|
25794
|
+
ps[7] = pi + 8;
|
|
25795
|
+
ps[0] = pi;
|
|
25796
|
+
ps[1] = pi + 11;
|
|
25797
|
+
ps[2] = pi + 10;
|
|
25798
|
+
ps[3] = pi + 9;
|
|
25799
|
+
cs[2] = ci + 1;
|
|
25800
|
+
cs[3] = ci + 2;
|
|
25801
|
+
cs[0] = ci;
|
|
25802
|
+
cs[1] = ci + 3;
|
|
25803
|
+
break;
|
|
25804
|
+
// prettier-ignore
|
|
25805
|
+
case 1:
|
|
25806
|
+
tmp1 = ps[12];
|
|
25807
|
+
tmp2 = ps[13];
|
|
25808
|
+
tmp3 = ps[14];
|
|
25809
|
+
tmp4 = ps[15];
|
|
25810
|
+
ps[12] = tmp4;
|
|
25811
|
+
ps[13] = pi + 0;
|
|
25812
|
+
ps[14] = pi + 1;
|
|
25813
|
+
ps[15] = pi + 2;
|
|
25814
|
+
ps[8] = tmp3;
|
|
25815
|
+
ps[9] = pi + 9;
|
|
25816
|
+
ps[10] = pi + 10;
|
|
25817
|
+
ps[11] = pi + 3;
|
|
25818
|
+
ps[4] = tmp2;
|
|
25819
|
+
ps[5] = pi + 8;
|
|
25820
|
+
ps[6] = pi + 11;
|
|
25821
|
+
ps[7] = pi + 4;
|
|
25822
|
+
ps[0] = tmp1;
|
|
25823
|
+
ps[1] = pi + 7;
|
|
25824
|
+
ps[2] = pi + 6;
|
|
25825
|
+
ps[3] = pi + 5;
|
|
25826
|
+
tmp1 = cs[2];
|
|
25827
|
+
tmp2 = cs[3];
|
|
25828
|
+
cs[2] = tmp2;
|
|
25829
|
+
cs[3] = ci;
|
|
25830
|
+
cs[0] = tmp1;
|
|
25831
|
+
cs[1] = ci + 1;
|
|
25832
|
+
break;
|
|
25833
|
+
// prettier-ignore
|
|
25834
|
+
case 2:
|
|
25835
|
+
tmp1 = ps[15];
|
|
25836
|
+
tmp2 = ps[11];
|
|
25837
|
+
ps[12] = ps[3];
|
|
25838
|
+
ps[13] = pi + 0;
|
|
25839
|
+
ps[14] = pi + 1;
|
|
25840
|
+
ps[15] = pi + 2;
|
|
25841
|
+
ps[8] = ps[7];
|
|
25842
|
+
ps[9] = pi + 9;
|
|
25843
|
+
ps[10] = pi + 10;
|
|
25844
|
+
ps[11] = pi + 3;
|
|
25845
|
+
ps[4] = tmp2;
|
|
25846
|
+
ps[5] = pi + 8;
|
|
25847
|
+
ps[6] = pi + 11;
|
|
25848
|
+
ps[7] = pi + 4;
|
|
25849
|
+
ps[0] = tmp1;
|
|
25850
|
+
ps[1] = pi + 7;
|
|
25851
|
+
ps[2] = pi + 6;
|
|
25852
|
+
ps[3] = pi + 5;
|
|
25853
|
+
tmp1 = cs[3];
|
|
25854
|
+
cs[2] = cs[1];
|
|
25855
|
+
cs[3] = ci;
|
|
25856
|
+
cs[0] = tmp1;
|
|
25857
|
+
cs[1] = ci + 1;
|
|
25858
|
+
break;
|
|
25859
|
+
// prettier-ignore
|
|
25860
|
+
case 3:
|
|
25861
|
+
ps[12] = ps[0];
|
|
25862
|
+
ps[13] = pi + 0;
|
|
25863
|
+
ps[14] = pi + 1;
|
|
25864
|
+
ps[15] = pi + 2;
|
|
25865
|
+
ps[8] = ps[1];
|
|
25866
|
+
ps[9] = pi + 9;
|
|
25867
|
+
ps[10] = pi + 10;
|
|
25868
|
+
ps[11] = pi + 3;
|
|
25869
|
+
ps[4] = ps[2];
|
|
25870
|
+
ps[5] = pi + 8;
|
|
25871
|
+
ps[6] = pi + 11;
|
|
25872
|
+
ps[7] = pi + 4;
|
|
25873
|
+
ps[0] = ps[3];
|
|
25874
|
+
ps[1] = pi + 7;
|
|
25875
|
+
ps[2] = pi + 6;
|
|
25876
|
+
ps[3] = pi + 5;
|
|
25877
|
+
cs[2] = cs[0];
|
|
25878
|
+
cs[3] = ci;
|
|
25879
|
+
cs[0] = cs[1];
|
|
25880
|
+
cs[1] = ci + 1;
|
|
25881
|
+
break;
|
|
25882
|
+
}
|
|
25883
|
+
this.figures.push({
|
|
25884
|
+
type: MeshFigureType.PATCH,
|
|
25885
|
+
coords: new Int32Array(ps),
|
|
25886
|
+
// making copies of ps and cs
|
|
25887
|
+
colors: new Int32Array(cs)
|
|
25888
|
+
});
|
|
25889
|
+
}
|
|
25890
|
+
}
|
|
25891
|
+
_buildFigureFromPatch(index) {
|
|
25892
|
+
const figure = this.figures[index];
|
|
25893
|
+
assert2(
|
|
25894
|
+
figure.type === MeshFigureType.PATCH,
|
|
25895
|
+
"Unexpected patch mesh figure"
|
|
25896
|
+
);
|
|
25897
|
+
const coords = this.coords, colors = this.colors;
|
|
25898
|
+
const pi = figure.coords;
|
|
25899
|
+
const ci = figure.colors;
|
|
25900
|
+
const figureMinX = Math.min(
|
|
25901
|
+
coords[pi[0]][0],
|
|
25902
|
+
coords[pi[3]][0],
|
|
25903
|
+
coords[pi[12]][0],
|
|
25904
|
+
coords[pi[15]][0]
|
|
25905
|
+
);
|
|
25906
|
+
const figureMinY = Math.min(
|
|
25907
|
+
coords[pi[0]][1],
|
|
25908
|
+
coords[pi[3]][1],
|
|
25909
|
+
coords[pi[12]][1],
|
|
25910
|
+
coords[pi[15]][1]
|
|
25911
|
+
);
|
|
25912
|
+
const figureMaxX = Math.max(
|
|
25913
|
+
coords[pi[0]][0],
|
|
25914
|
+
coords[pi[3]][0],
|
|
25915
|
+
coords[pi[12]][0],
|
|
25916
|
+
coords[pi[15]][0]
|
|
25917
|
+
);
|
|
25918
|
+
const figureMaxY = Math.max(
|
|
25919
|
+
coords[pi[0]][1],
|
|
25920
|
+
coords[pi[3]][1],
|
|
25921
|
+
coords[pi[12]][1],
|
|
25922
|
+
coords[pi[15]][1]
|
|
25923
|
+
);
|
|
25924
|
+
let splitXBy = Math.ceil(
|
|
25925
|
+
(figureMaxX - figureMinX) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[2] - this.bounds[0])
|
|
25926
|
+
);
|
|
25927
|
+
splitXBy = MathClamp(
|
|
25928
|
+
splitXBy,
|
|
25929
|
+
_MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
|
|
25930
|
+
_MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT
|
|
25931
|
+
);
|
|
25932
|
+
let splitYBy = Math.ceil(
|
|
25933
|
+
(figureMaxY - figureMinY) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[3] - this.bounds[1])
|
|
25934
|
+
);
|
|
25935
|
+
splitYBy = MathClamp(
|
|
25936
|
+
splitYBy,
|
|
25937
|
+
_MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
|
|
25938
|
+
_MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT
|
|
25939
|
+
);
|
|
25940
|
+
const verticesPerRow = splitXBy + 1;
|
|
25941
|
+
const figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
|
|
25942
|
+
const figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
|
|
25943
|
+
let k = 0;
|
|
25944
|
+
const cl = new Uint8Array(3), cr = new Uint8Array(3);
|
|
25945
|
+
const c0 = colors[ci[0]], c1 = colors[ci[1]], c2 = colors[ci[2]], c3 = colors[ci[3]];
|
|
25946
|
+
const bRow = getB(splitYBy), bCol = getB(splitXBy);
|
|
25947
|
+
for (let row = 0; row <= splitYBy; row++) {
|
|
25948
|
+
cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0;
|
|
25949
|
+
cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0;
|
|
25950
|
+
cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0;
|
|
25951
|
+
cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0;
|
|
25952
|
+
cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0;
|
|
25953
|
+
cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0;
|
|
25954
|
+
for (let col = 0; col <= splitXBy; col++, k++) {
|
|
25955
|
+
if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) {
|
|
25956
|
+
continue;
|
|
25957
|
+
}
|
|
25958
|
+
let x = 0, y = 0;
|
|
25959
|
+
let q = 0;
|
|
25960
|
+
for (let i = 0; i <= 3; i++) {
|
|
25961
|
+
for (let j = 0; j <= 3; j++, q++) {
|
|
25962
|
+
const m = bRow[row][i] * bCol[col][j];
|
|
25963
|
+
x += coords[pi[q]][0] * m;
|
|
25964
|
+
y += coords[pi[q]][1] * m;
|
|
25965
|
+
}
|
|
25966
|
+
}
|
|
25967
|
+
figureCoords[k] = coords.length;
|
|
25968
|
+
coords.push([x, y]);
|
|
25969
|
+
figureColors[k] = colors.length;
|
|
25970
|
+
const newColor = new Uint8Array(3);
|
|
25971
|
+
newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0;
|
|
25972
|
+
newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0;
|
|
25973
|
+
newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0;
|
|
25974
|
+
colors.push(newColor);
|
|
25975
|
+
}
|
|
25976
|
+
}
|
|
25977
|
+
figureCoords[0] = pi[0];
|
|
25978
|
+
figureColors[0] = ci[0];
|
|
25979
|
+
figureCoords[splitXBy] = pi[3];
|
|
25980
|
+
figureColors[splitXBy] = ci[1];
|
|
25981
|
+
figureCoords[verticesPerRow * splitYBy] = pi[12];
|
|
25982
|
+
figureColors[verticesPerRow * splitYBy] = ci[2];
|
|
25983
|
+
figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15];
|
|
25984
|
+
figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
|
|
25985
|
+
this.figures[index] = {
|
|
25986
|
+
type: MeshFigureType.LATTICE,
|
|
25987
|
+
coords: figureCoords,
|
|
25988
|
+
colors: figureColors,
|
|
25989
|
+
verticesPerRow
|
|
25990
|
+
};
|
|
25991
|
+
}
|
|
25992
|
+
_updateBounds() {
|
|
25993
|
+
meshUpdateBounds(this);
|
|
25994
|
+
}
|
|
25995
|
+
_packData() {
|
|
25996
|
+
meshPackData(this);
|
|
25997
|
+
}
|
|
25998
|
+
getIR() {
|
|
25999
|
+
const { posData, colData, vertexCount } = buildMeshVertexData(
|
|
26000
|
+
this.coords,
|
|
26001
|
+
this.colors,
|
|
26002
|
+
this.figures
|
|
26003
|
+
);
|
|
26004
|
+
return [
|
|
26005
|
+
"Mesh",
|
|
26006
|
+
this.shadingType,
|
|
26007
|
+
posData,
|
|
26008
|
+
colData,
|
|
26009
|
+
vertexCount,
|
|
26010
|
+
this.bounds,
|
|
26011
|
+
this.bbox,
|
|
26012
|
+
this.background
|
|
26013
|
+
];
|
|
26014
|
+
}
|
|
26015
|
+
};
|
|
22709
26016
|
var PdfError = class extends Error {
|
|
22710
26017
|
constructor(code, message) {
|
|
22711
26018
|
super(message);
|
|
@@ -25611,11 +28918,16 @@ function parseDictionaryStream(dictNode, lexer, bytes) {
|
|
|
25611
28918
|
let streamEnd = streamStart;
|
|
25612
28919
|
if (resolvedLength !== void 0 && resolvedLength >= 0 && streamStart + resolvedLength <= bytes.length) {
|
|
25613
28920
|
const candidateEnd = streamStart + resolvedLength;
|
|
25614
|
-
const
|
|
25615
|
-
|
|
25616
|
-
|
|
28921
|
+
const tailLexer = new CosByteLexer(bytes, candidateEnd);
|
|
28922
|
+
let endToken;
|
|
28923
|
+
try {
|
|
28924
|
+
endToken = tailLexer.nextToken();
|
|
28925
|
+
} catch (error) {
|
|
28926
|
+
if (!(error instanceof PdfError) || error.code !== "E_PARSE") throw error;
|
|
28927
|
+
}
|
|
28928
|
+
if (endToken?.kind === "keyword" && endToken.value === "endstream") {
|
|
25617
28929
|
rawStreamBytes = bytes.subarray(streamStart, candidateEnd);
|
|
25618
|
-
streamEnd =
|
|
28930
|
+
streamEnd = tailLexer.offset;
|
|
25619
28931
|
}
|
|
25620
28932
|
}
|
|
25621
28933
|
if (!rawStreamBytes) {
|
|
@@ -33785,6 +37097,25 @@ var __webpack_exports__JpxImage = __webpack_exports__.JpxImage;
|
|
|
33785
37097
|
var __webpack_exports__VerbosityLevel = __webpack_exports__.VerbosityLevel;
|
|
33786
37098
|
var __webpack_exports__getVerbosityLevel = __webpack_exports__.getVerbosityLevel;
|
|
33787
37099
|
var __webpack_exports__setVerbosityLevel = __webpack_exports__.setVerbosityLevel;
|
|
37100
|
+
function createCalibratedColorSpace(doc, family, parameters) {
|
|
37101
|
+
const dict = doc.resolveDict(parameters);
|
|
37102
|
+
const array = (key) => {
|
|
37103
|
+
const value = dict ? doc.resolveArray(dictGet(dict, key)) : void 0;
|
|
37104
|
+
return value?.items.map((item) => {
|
|
37105
|
+
const number = doc.resolve(item);
|
|
37106
|
+
return number?.kind === "number" ? number.value : 0;
|
|
37107
|
+
});
|
|
37108
|
+
};
|
|
37109
|
+
const whitePoint = array("WhitePoint") ?? [0.95047, 1, 1.08883];
|
|
37110
|
+
const blackPoint = array("BlackPoint");
|
|
37111
|
+
if (family === "CalGray") {
|
|
37112
|
+
const gamma = dict ? doc.resolve(dictGet(dict, "Gamma")) : void 0;
|
|
37113
|
+
return new CalGrayCS(whitePoint, blackPoint, gamma?.kind === "number" ? gamma.value : void 0);
|
|
37114
|
+
}
|
|
37115
|
+
if (family === "CalRGB") return new CalRGBCS(whitePoint, blackPoint, array("Gamma"), array("Matrix"));
|
|
37116
|
+
return new LabCS(whitePoint, blackPoint, array("Range"));
|
|
37117
|
+
}
|
|
37118
|
+
var cmykColorSpace = new DeviceCmykCS();
|
|
33788
37119
|
function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
33789
37120
|
if (!csNode) return { colorSpace: "rgb", colorSpaceLabel: "rgb", components: 3 };
|
|
33790
37121
|
const resolved = doc.resolve(csNode);
|
|
@@ -33825,7 +37156,7 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
|
33825
37156
|
palette = lookupNode.bytes;
|
|
33826
37157
|
}
|
|
33827
37158
|
let resolvedBaseComp = baseInfo.components;
|
|
33828
|
-
if (palette && (baseInfo.
|
|
37159
|
+
if (palette && (baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calibrated !== void 0)) {
|
|
33829
37160
|
const numEntries = Math.max(1, Math.min(hival + 1, Math.floor(palette.length / Math.max(1, baseInfo.components))));
|
|
33830
37161
|
const rgbaPal = decodeSamplesToRgba(palette, numEntries, 1, 8, baseInfo);
|
|
33831
37162
|
const rgbPal = new Uint8Array(numEntries * 3);
|
|
@@ -33855,74 +37186,21 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
|
33855
37186
|
}
|
|
33856
37187
|
return { colorSpace: "rgb", colorSpaceLabel: "icc", components: 3 };
|
|
33857
37188
|
}
|
|
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
|
-
}
|
|
37189
|
+
if (kindName === "CalGray" || kindName === "CalRGB" || kindName === "Lab") {
|
|
37190
|
+
const calibrated = createCalibratedColorSpace(doc, kindName, resolved.items[1]);
|
|
33883
37191
|
return {
|
|
33884
|
-
colorSpace: "rgb",
|
|
33885
|
-
colorSpaceLabel: "cal-rgb",
|
|
33886
|
-
components: 3,
|
|
33887
|
-
|
|
33888
|
-
calRgbMatrix
|
|
37192
|
+
colorSpace: kindName === "CalGray" ? "gray" : "rgb",
|
|
37193
|
+
colorSpaceLabel: kindName === "CalGray" ? "cal-gray" : kindName === "CalRGB" ? "cal-rgb" : "lab",
|
|
37194
|
+
components: kindName === "CalGray" ? 1 : 3,
|
|
37195
|
+
calibrated
|
|
33889
37196
|
};
|
|
33890
37197
|
}
|
|
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
37198
|
if (kindName === "Separation" || kindName === "DeviceN") {
|
|
33905
37199
|
const isDevN = kindName === "DeviceN";
|
|
33906
37200
|
const namesArr = isDevN ? doc.resolveArray(resolved.items[1]) : void 0;
|
|
33907
37201
|
const devNComponents = isDevN && namesArr ? Math.max(1, namesArr.items.length) : 1;
|
|
33908
37202
|
const altInfo = resolveColorSpaceInfo(doc, resolved.items[2], resourcesDict);
|
|
33909
37203
|
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
37204
|
return {
|
|
33927
37205
|
colorSpace: altSpace,
|
|
33928
37206
|
colorSpaceLabel: isDevN ? "devn" : "sep",
|
|
@@ -33930,12 +37208,9 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
|
33930
37208
|
isSeparation: !isDevN,
|
|
33931
37209
|
isDeviceN: isDevN,
|
|
33932
37210
|
separationAltSpace: altSpace,
|
|
33933
|
-
|
|
33934
|
-
separationC1: c1,
|
|
33935
|
-
separationN: sepN,
|
|
37211
|
+
alternateCalibrated: altInfo.calibrated,
|
|
33936
37212
|
tintFunctionDoc: doc,
|
|
33937
|
-
tintFunctionNode: resolved.items[3]
|
|
33938
|
-
tintFunctionType
|
|
37213
|
+
tintFunctionNode: resolved.items[3]
|
|
33939
37214
|
};
|
|
33940
37215
|
}
|
|
33941
37216
|
}
|
|
@@ -34085,141 +37360,55 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
34085
37360
|
const rgba = new Uint8Array(width * height * 4);
|
|
34086
37361
|
const pixelCount = width * height;
|
|
34087
37362
|
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
37363
|
const alt = csInfo.separationAltSpace ?? "rgb";
|
|
34092
37364
|
const numCh = Math.max(1, csInfo.components);
|
|
34093
37365
|
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
37366
|
for (let p = 0; p < pixelCount; p++) {
|
|
34096
37367
|
const chVals = [];
|
|
34097
|
-
let wSum = 0;
|
|
34098
37368
|
for (let ch3 = 0; ch3 < numCh; ch3++) {
|
|
34099
37369
|
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;
|
|
37370
|
+
chVals.push(remapUnitSampleWithDecode(sRaw, ch3, decodePairs));
|
|
34130
37371
|
}
|
|
34131
|
-
const
|
|
34132
|
-
|
|
34133
|
-
|
|
34134
|
-
|
|
34135
|
-
|
|
34136
|
-
|
|
34137
|
-
rgba
|
|
34138
|
-
|
|
34139
|
-
rgba[
|
|
37372
|
+
const outComps = evalShadingFunctionToComponents(
|
|
37373
|
+
csInfo.tintFunctionDoc,
|
|
37374
|
+
csInfo.tintFunctionNode,
|
|
37375
|
+
chVals
|
|
37376
|
+
);
|
|
37377
|
+
if (csInfo.alternateCalibrated) {
|
|
37378
|
+
rgba.set(csInfo.alternateCalibrated.getRgb(outComps, 0), p * 4);
|
|
37379
|
+
} else if (alt === "cmyk") {
|
|
37380
|
+
rgba.set(cmykColorSpace.getRgb([outComps[0] ?? 0, outComps[1] ?? 0, outComps[2] ?? 0, outComps[3] ?? 0], 0), p * 4);
|
|
34140
37381
|
} else if (alt === "gray") {
|
|
34141
|
-
const
|
|
34142
|
-
const gByte = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
|
|
37382
|
+
const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
|
|
34143
37383
|
rgba[p * 4] = gByte;
|
|
34144
37384
|
rgba[p * 4 + 1] = gByte;
|
|
34145
37385
|
rgba[p * 4 + 2] = gByte;
|
|
34146
37386
|
} 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);
|
|
37387
|
+
rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
|
|
37388
|
+
rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
|
|
37389
|
+
rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
|
|
34153
37390
|
}
|
|
34154
37391
|
rgba[p * 4 + 3] = 255;
|
|
34155
37392
|
}
|
|
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
|
-
};
|
|
37393
|
+
} else if (csInfo.calibrated?.name === "Lab") {
|
|
37394
|
+
const { amin, amax, bmin, bmax } = csInfo.calibrated;
|
|
37395
|
+
const step = bpc === 16 ? 2 : 1;
|
|
34163
37396
|
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);
|
|
37397
|
+
const L = (rawSamples[p * 3 * step] ?? 0) / 255 * 100;
|
|
37398
|
+
const a = amin + (rawSamples[(p * 3 + 1) * step] ?? 128) / 255 * (amax - amin);
|
|
37399
|
+
const b = bmin + (rawSamples[(p * 3 + 2) * step] ?? 128) / 255 * (bmax - bmin);
|
|
37400
|
+
rgba.set(csInfo.calibrated.getRgb([L, a, b], 0), p * 4);
|
|
34189
37401
|
rgba[p * 4 + 3] = 255;
|
|
34190
37402
|
}
|
|
34191
37403
|
} 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
37404
|
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;
|
|
37405
|
+
const rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
|
|
37406
|
+
const gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
|
|
37407
|
+
const bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
|
|
37408
|
+
if (csInfo.calibrated) {
|
|
37409
|
+
rgba.set(csInfo.calibrated.getRgb([rU, gU, bU], 0), p * 4);
|
|
37410
|
+
rgba[p * 4 + 3] = 255;
|
|
37411
|
+
return;
|
|
34223
37412
|
}
|
|
34224
37413
|
rgba[p * 4] = Math.round(rU * 255);
|
|
34225
37414
|
rgba[p * 4 + 1] = Math.round(gU * 255);
|
|
@@ -34239,10 +37428,11 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
34239
37428
|
}
|
|
34240
37429
|
} else if (csInfo.colorSpace === "gray") {
|
|
34241
37430
|
const writeGrayPixel = (p, gByte) => {
|
|
34242
|
-
|
|
34243
|
-
if (csInfo.
|
|
34244
|
-
|
|
34245
|
-
|
|
37431
|
+
const gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
|
|
37432
|
+
if (csInfo.calibrated) {
|
|
37433
|
+
rgba.set(csInfo.calibrated.getRgb([gU], 0), p * 4);
|
|
37434
|
+
rgba[p * 4 + 3] = 255;
|
|
37435
|
+
return;
|
|
34246
37436
|
}
|
|
34247
37437
|
const outG = Math.round(Math.max(0, Math.min(1, gU)) * 255);
|
|
34248
37438
|
rgba[p * 4] = outG;
|
|
@@ -34298,9 +37488,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
34298
37488
|
const m = remapUnitSampleWithDecode((rawSamples[p * stride + chStep] ?? 0) / 255, 1, decodePairs);
|
|
34299
37489
|
const y = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 2] ?? 0) / 255, 2, decodePairs);
|
|
34300
37490
|
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);
|
|
37491
|
+
rgba.set(cmykColorSpace.getRgb([c, m, y, k], 0), p * 4);
|
|
34304
37492
|
rgba[p * 4 + 3] = 255;
|
|
34305
37493
|
}
|
|
34306
37494
|
} else if (csInfo.colorSpace === "index") {
|
|
@@ -34338,9 +37526,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
34338
37526
|
const m = pal[idx * 4 + 1] / 255;
|
|
34339
37527
|
const yel = pal[idx * 4 + 2] / 255;
|
|
34340
37528
|
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);
|
|
37529
|
+
rgba.set(cmykColorSpace.getRgb([c, m, yel, k], 0), p * 4);
|
|
34344
37530
|
} else {
|
|
34345
37531
|
rgba[p * 4] = pal[idx * baseComp];
|
|
34346
37532
|
rgba[p * 4 + 1] = pal[idx * baseComp + 1];
|
|
@@ -34595,6 +37781,7 @@ function decodeInlineImageNodeToRgba(doc, dict, rawData, activeRes, fillColor) {
|
|
|
34595
37781
|
});
|
|
34596
37782
|
return decodeXObjectImageToRgba(context, { kind: "stream", dict, rawBytes: rawData }, activeRes, fillColor);
|
|
34597
37783
|
}
|
|
37784
|
+
var cmykColorSpace2 = new DeviceCmykCS();
|
|
34598
37785
|
function multiplyMatrices(m1, m2) {
|
|
34599
37786
|
return [
|
|
34600
37787
|
m1[0] * m2[0] + m1[1] * m2[2],
|
|
@@ -34811,193 +37998,7 @@ function resolvePageFonts(doc, resourcesDict) {
|
|
|
34811
37998
|
}
|
|
34812
37999
|
return fonts;
|
|
34813
38000
|
}
|
|
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
|
-
}
|
|
38001
|
+
var postScriptFunctions = /* @__PURE__ */ new WeakMap();
|
|
35001
38002
|
function evalShadingFunctionToComponents(doc, fnNode, inputs) {
|
|
35002
38003
|
const inArr = typeof inputs === "number" ? [inputs] : inputs;
|
|
35003
38004
|
const t = inArr[0] ?? 0;
|
|
@@ -35044,35 +38045,50 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
|
|
|
35044
38045
|
const decode = getNums("Decode", range);
|
|
35045
38046
|
const nOut = Math.max(1, Math.floor((decode.length || range.length || 6) / 2));
|
|
35046
38047
|
const mIn = Math.max(1, size.length);
|
|
35047
|
-
|
|
38048
|
+
const streamBytes = doc.decodeStream(resolved);
|
|
38049
|
+
let vertices = [{ index: 0, weight: 1 }];
|
|
35048
38050
|
let stride = 1;
|
|
35049
38051
|
for (let i = 0; i < mIn; i++) {
|
|
35050
38052
|
const d02 = dom[i * 2] ?? 0;
|
|
35051
38053
|
const d12 = dom[i * 2 + 1] ?? 1;
|
|
35052
|
-
const sMax = Math.max(
|
|
38054
|
+
const sMax = Math.max(0, (size[i] ?? 2) - 1);
|
|
35053
38055
|
const e0 = encode[i * 2] ?? 0;
|
|
35054
38056
|
const e1 = encode[i * 2 + 1] ?? sMax;
|
|
35055
38057
|
const x = Math.max(d02, Math.min(d12, inArr[i] ?? 0));
|
|
35056
|
-
const u =
|
|
35057
|
-
const
|
|
35058
|
-
|
|
38058
|
+
const u = d12 === d02 ? 0 : (x - d02) / (d12 - d02);
|
|
38059
|
+
const e = Math.max(0, Math.min(sMax, e0 + u * (e1 - e0)));
|
|
38060
|
+
const low = Math.floor(e), fraction = e - low;
|
|
38061
|
+
const next = [];
|
|
38062
|
+
for (const vertex of vertices) {
|
|
38063
|
+
const index = vertex.index + low * stride;
|
|
38064
|
+
if (index * nOut * bps < streamBytes.length * 8) next.push({ index, weight: vertex.weight * (1 - fraction) });
|
|
38065
|
+
if (fraction && (index + stride) * nOut * bps < streamBytes.length * 8) {
|
|
38066
|
+
next.push({ index: index + stride, weight: vertex.weight * fraction });
|
|
38067
|
+
}
|
|
38068
|
+
}
|
|
38069
|
+
vertices = next;
|
|
35059
38070
|
stride *= size[i] ?? 2;
|
|
35060
38071
|
}
|
|
35061
|
-
const
|
|
38072
|
+
const maxSample = 2 ** bps - 1;
|
|
38073
|
+
const readSample = (index) => {
|
|
38074
|
+
let bitOffset = index * bps, remaining = bps, value = 0;
|
|
38075
|
+
while (remaining > 0) {
|
|
38076
|
+
const bitInByte = bitOffset % 8;
|
|
38077
|
+
const take = Math.min(remaining, 8 - bitInByte);
|
|
38078
|
+
const byte = streamBytes[Math.floor(bitOffset / 8)] ?? 0;
|
|
38079
|
+
value = value * 2 ** take + (byte >> 8 - bitInByte - take & (1 << take) - 1);
|
|
38080
|
+
bitOffset += take;
|
|
38081
|
+
remaining -= take;
|
|
38082
|
+
}
|
|
38083
|
+
return value / maxSample;
|
|
38084
|
+
};
|
|
35062
38085
|
const out2 = [];
|
|
35063
|
-
const maxSample = bps === 16 ? 65535 : 255;
|
|
35064
38086
|
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;
|
|
38087
|
+
let value = 0;
|
|
38088
|
+
for (const vertex of vertices) value += readSample(vertex.index * nOut + j) * vertex.weight;
|
|
35073
38089
|
const dec0 = decode[j * 2] ?? 0;
|
|
35074
38090
|
const dec1 = decode[j * 2 + 1] ?? 1;
|
|
35075
|
-
out2.push(dec0 +
|
|
38091
|
+
out2.push(dec0 + value * (dec1 - dec0));
|
|
35076
38092
|
}
|
|
35077
38093
|
return clampRange(out2);
|
|
35078
38094
|
}
|
|
@@ -35082,34 +38098,40 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
|
|
|
35082
38098
|
const d12 = dom[i * 2 + 1] ?? 1;
|
|
35083
38099
|
return Math.max(d02, Math.min(d12, v));
|
|
35084
38100
|
});
|
|
35085
|
-
const
|
|
35086
|
-
|
|
35087
|
-
|
|
38101
|
+
const source = bytesToString3(doc.decodeStream(resolved));
|
|
38102
|
+
let cached = postScriptFunctions.get(resolved);
|
|
38103
|
+
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])) {
|
|
38104
|
+
cached = { source, domain: dom, range, evaluate: buildPostScriptJsFunction(source, dom, range) };
|
|
38105
|
+
postScriptFunctions.set(resolved, cached);
|
|
38106
|
+
}
|
|
38107
|
+
const output = [];
|
|
38108
|
+
cached.evaluate(clampedInputs, 0, output, 0);
|
|
38109
|
+
return output;
|
|
35088
38110
|
}
|
|
35089
38111
|
if (ft === 3) {
|
|
35090
38112
|
const fnsArr = doc.resolveArray(dictGet(fnDict, "Functions"));
|
|
35091
38113
|
const bounds = getNums("Bounds", []);
|
|
35092
38114
|
const encode = getNums("Encode", []);
|
|
35093
38115
|
if (fnsArr && fnsArr.items.length > 0) {
|
|
38116
|
+
const input = Math.max(dom[0] ?? 0, Math.min(dom[1] ?? 1, t));
|
|
35094
38117
|
let segIdx = 0;
|
|
35095
|
-
while (segIdx < bounds.length &&
|
|
38118
|
+
while (segIdx < bounds.length && input >= bounds[segIdx]) segIdx++;
|
|
35096
38119
|
segIdx = Math.min(fnsArr.items.length - 1, segIdx);
|
|
35097
38120
|
const b0 = segIdx === 0 ? dom[0] ?? 0 : bounds[segIdx - 1];
|
|
35098
38121
|
const b1 = segIdx < bounds.length ? bounds[segIdx] : dom[1] ?? 1;
|
|
35099
38122
|
const e0 = encode[segIdx * 2] ?? 0;
|
|
35100
38123
|
const e1 = encode[segIdx * 2 + 1] ?? 1;
|
|
35101
|
-
const localT =
|
|
35102
|
-
return evalShadingFunctionToComponents(doc, fnsArr.items[segIdx],
|
|
38124
|
+
const localT = b1 !== b0 ? e0 + (input - b0) / (b1 - b0) * (e1 - e0) : e0;
|
|
38125
|
+
return clampRange(evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], localT));
|
|
35103
38126
|
}
|
|
35104
38127
|
}
|
|
35105
|
-
const c0 = getNums("C0", [0
|
|
35106
|
-
const c1 = getNums("C1", [1
|
|
38128
|
+
const c0 = getNums("C0", [0]);
|
|
38129
|
+
const c1 = getNums("C1", [1]);
|
|
35107
38130
|
const nNode = doc.resolve(dictGet(fnDict, "N"));
|
|
35108
|
-
const expN = nNode?.kind === "number"
|
|
38131
|
+
const expN = nNode?.kind === "number" ? nNode.value : 1;
|
|
35109
38132
|
const d0 = dom[0] ?? 0;
|
|
35110
38133
|
const d1 = dom[1] ?? 1;
|
|
35111
|
-
const
|
|
35112
|
-
const w = Math.pow(Math.max(0, Math.min(1, normT)), expN);
|
|
38134
|
+
const w = Math.pow(Math.max(d0, Math.min(d1, t)), expN);
|
|
35113
38135
|
const len = Math.max(c0.length, c1.length);
|
|
35114
38136
|
const out = [];
|
|
35115
38137
|
for (let i = 0; i < len; i++) {
|
|
@@ -35125,30 +38147,14 @@ function shadingComponentsToRgb(csName, comps) {
|
|
|
35125
38147
|
return [v, v, v];
|
|
35126
38148
|
}
|
|
35127
38149
|
if (csName === "DeviceCMYK" || csName === "CMYK" || comps.length >= 4) {
|
|
35128
|
-
const
|
|
35129
|
-
return [
|
|
38150
|
+
const rgb2 = cmykColorSpace2.getRgb([comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0, comps[3] ?? 0], 0);
|
|
38151
|
+
return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
|
|
35130
38152
|
}
|
|
35131
38153
|
return [comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0];
|
|
35132
38154
|
}
|
|
35133
38155
|
function kClamp(v) {
|
|
35134
38156
|
return Math.max(0, Math.min(1, v));
|
|
35135
38157
|
}
|
|
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
38158
|
function getColorSpaceComponentCount(doc, csNode, activeResources, depth = 0) {
|
|
35153
38159
|
if (!csNode || depth > 4) return 3;
|
|
35154
38160
|
const resolved = doc ? doc.resolve(csNode) : csNode;
|
|
@@ -35205,63 +38211,10 @@ function convertColorSpaceComponentsToRgb(doc, csNode, csNameFallback, comps, ac
|
|
|
35205
38211
|
if (resolved.kind === "array" && resolved.items.length > 0 && doc) {
|
|
35206
38212
|
const familyNode = doc.resolve(resolved.items[0]);
|
|
35207
38213
|
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);
|
|
38214
|
+
if (family === "CalGray" || family === "CalRGB" || family === "Lab") {
|
|
38215
|
+
const colorSpace = createCalibratedColorSpace(doc, family, resolved.items[1]);
|
|
38216
|
+
const rgb2 = colorSpace.getRgb(comps, 0);
|
|
38217
|
+
return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
|
|
35265
38218
|
}
|
|
35266
38219
|
if (family === "ICCBased" && resolved.items[1]) {
|
|
35267
38220
|
const iccNode = doc.resolve(resolved.items[1]);
|
|
@@ -35342,143 +38295,28 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
|
|
|
35342
38295
|
const r = doc.resolve(it);
|
|
35343
38296
|
return r?.kind === "number" ? r.value : 0;
|
|
35344
38297
|
});
|
|
35345
|
-
const xmin = decodeNums[0], xmax = decodeNums[1], ymin = decodeNums[2], ymax = decodeNums[3];
|
|
35346
|
-
const numColorParams = Math.max(1, Math.floor((decodeNums.length - 4) / 2));
|
|
35347
38298
|
const fnNode = dictGet(shDict, "Function");
|
|
35348
38299
|
const csNode = doc.resolve(dictGet(shDict, "ColorSpace"));
|
|
35349
38300
|
const csName = csNode?.kind === "name" ? csNode.decoded : "DeviceRGB";
|
|
35350
|
-
|
|
35351
|
-
const
|
|
35352
|
-
|
|
35353
|
-
|
|
35354
|
-
|
|
35355
|
-
|
|
35356
|
-
|
|
35357
|
-
|
|
35358
|
-
|
|
35359
|
-
|
|
35360
|
-
|
|
35361
|
-
|
|
35362
|
-
|
|
35363
|
-
|
|
35364
|
-
|
|
35365
|
-
|
|
35366
|
-
|
|
35367
|
-
|
|
35368
|
-
|
|
35369
|
-
};
|
|
35370
|
-
const readColorRgb = () => {
|
|
35371
|
-
const params = [];
|
|
35372
|
-
for (let c = 0; c < numColorParams; c++) {
|
|
35373
|
-
const rc = readBits(bpcComp) / compMax;
|
|
35374
|
-
const cMin = decodeNums[4 + c * 2] ?? 0;
|
|
35375
|
-
const cMax = decodeNums[4 + c * 2 + 1] ?? 1;
|
|
35376
|
-
params.push(cMin + rc * (cMax - cMin));
|
|
35377
|
-
}
|
|
35378
|
-
const comps = fnNode ? evalShadingFunctionToComponents(doc, fnNode, params) : params;
|
|
35379
|
-
return convertColorSpaceComponentsToRgb(doc, csNode, csName, comps);
|
|
35380
|
-
};
|
|
35381
|
-
const triangles = [];
|
|
35382
|
-
if (shType === 4) {
|
|
35383
|
-
const minBitsPerVert = bpcFlag + 2 * bpcCoord + numColorParams * bpcComp;
|
|
35384
|
-
let triVerts;
|
|
35385
|
-
while (bitPos + minBitsPerVert <= totalBits) {
|
|
35386
|
-
const flag = readBits(bpcFlag) & 3;
|
|
35387
|
-
const [x, y] = readCoord();
|
|
35388
|
-
const rgb2 = readColorRgb();
|
|
35389
|
-
const vNew = { x, y, rgb: rgb2 };
|
|
35390
|
-
if (flag === 0 || !triVerts) {
|
|
35391
|
-
if (bitPos + 2 * minBitsPerVert > totalBits) break;
|
|
35392
|
-
readBits(bpcFlag);
|
|
35393
|
-
const [x1, y1] = readCoord();
|
|
35394
|
-
const rgb1 = readColorRgb();
|
|
35395
|
-
readBits(bpcFlag);
|
|
35396
|
-
const [x2, y2] = readCoord();
|
|
35397
|
-
const rgb22 = readColorRgb();
|
|
35398
|
-
triVerts = [vNew, { x: x1, y: y1, rgb: rgb1 }, { x: x2, y: y2, rgb: rgb22 }];
|
|
35399
|
-
triangles.push(triVerts);
|
|
35400
|
-
} else if (flag === 1) {
|
|
35401
|
-
triVerts = [triVerts[1], triVerts[2], vNew];
|
|
35402
|
-
triangles.push(triVerts);
|
|
35403
|
-
} else if (flag === 2) {
|
|
35404
|
-
triVerts = [triVerts[0], triVerts[2], vNew];
|
|
35405
|
-
triangles.push(triVerts);
|
|
35406
|
-
}
|
|
35407
|
-
}
|
|
35408
|
-
} else if (shType === 5) {
|
|
35409
|
-
const minBitsPerVert = 2 * bpcCoord + numColorParams * bpcComp;
|
|
35410
|
-
const verts = [];
|
|
35411
|
-
while (bitPos + minBitsPerVert <= totalBits) {
|
|
35412
|
-
const [x, y] = readCoord();
|
|
35413
|
-
const rgb2 = readColorRgb();
|
|
35414
|
-
verts.push({ x, y, rgb: rgb2 });
|
|
35415
|
-
}
|
|
35416
|
-
const numRows = Math.floor(verts.length / vPerRow);
|
|
35417
|
-
for (let r = 0; r + 1 < numRows; r++) {
|
|
35418
|
-
for (let c = 0; c + 1 < vPerRow; c++) {
|
|
35419
|
-
const v00 = verts[r * vPerRow + c];
|
|
35420
|
-
const v01 = verts[r * vPerRow + c + 1];
|
|
35421
|
-
const v11 = verts[(r + 1) * vPerRow + c + 1];
|
|
35422
|
-
const v10 = verts[(r + 1) * vPerRow + c];
|
|
35423
|
-
triangles.push([v00, v01, v11], [v00, v11, v10]);
|
|
35424
|
-
}
|
|
35425
|
-
}
|
|
35426
|
-
} else if (shType === 6 || shType === 7) {
|
|
35427
|
-
const numCtrl = shType === 6 ? 12 : 16;
|
|
35428
|
-
const minBitsPatch = bpcFlag + (numCtrl - 4) * 2 * bpcCoord + 2 * numColorParams * bpcComp;
|
|
35429
|
-
let prevPts;
|
|
35430
|
-
let prevColors;
|
|
35431
|
-
while (bitPos + minBitsPatch <= totalBits) {
|
|
35432
|
-
const flag = readBits(bpcFlag) & 3;
|
|
35433
|
-
let pts = [];
|
|
35434
|
-
let cols = [];
|
|
35435
|
-
if (flag === 0 || !prevPts || !prevColors) {
|
|
35436
|
-
for (let i = 0; i < numCtrl; i++) pts.push(readCoord());
|
|
35437
|
-
for (let i = 0; i < 4; i++) cols.push(readColorRgb());
|
|
35438
|
-
} else {
|
|
35439
|
-
const extraCtrl = numCtrl - 4;
|
|
35440
|
-
const readExtra = [];
|
|
35441
|
-
for (let i = 0; i < extraCtrl; i++) readExtra.push(readCoord());
|
|
35442
|
-
const c2 = readColorRgb();
|
|
35443
|
-
const c3 = readColorRgb();
|
|
35444
|
-
pts = [prevPts[3], prevPts[4], prevPts[5], prevPts[6], ...readExtra];
|
|
35445
|
-
cols = [prevColors[1], prevColors[2], c2, c3];
|
|
35446
|
-
}
|
|
35447
|
-
prevPts = pts;
|
|
35448
|
-
prevColors = cols;
|
|
35449
|
-
const p00 = pts[0];
|
|
35450
|
-
const p03 = pts[3];
|
|
35451
|
-
const p33 = pts[6];
|
|
35452
|
-
const p30 = pts[9];
|
|
35453
|
-
const c00 = cols[0], c03 = cols[1], c33 = cols[2], c30 = cols[3];
|
|
35454
|
-
const steps = 4;
|
|
35455
|
-
const grid = [];
|
|
35456
|
-
for (let iu = 0; iu <= steps; iu++) {
|
|
35457
|
-
const u = iu / steps;
|
|
35458
|
-
const row = [];
|
|
35459
|
-
for (let iv = 0; iv <= steps; iv++) {
|
|
35460
|
-
const v = iv / steps;
|
|
35461
|
-
const x = (1 - u) * (1 - v) * p00[0] + (1 - u) * v * p03[0] + u * v * p33[0] + u * (1 - v) * p30[0];
|
|
35462
|
-
const y = (1 - u) * (1 - v) * p00[1] + (1 - u) * v * p03[1] + u * v * p33[1] + u * (1 - v) * p30[1];
|
|
35463
|
-
const r = (1 - u) * (1 - v) * c00[0] + (1 - u) * v * c03[0] + u * v * c33[0] + u * (1 - v) * c30[0];
|
|
35464
|
-
const g = (1 - u) * (1 - v) * c00[1] + (1 - u) * v * c03[1] + u * v * c33[1] + u * (1 - v) * c30[1];
|
|
35465
|
-
const b = (1 - u) * (1 - v) * c00[2] + (1 - u) * v * c03[2] + u * v * c33[2] + u * (1 - v) * c30[2];
|
|
35466
|
-
row.push({ x, y, rgb: [r, g, b] });
|
|
35467
|
-
}
|
|
35468
|
-
grid.push(row);
|
|
35469
|
-
}
|
|
35470
|
-
for (let iu = 0; iu < steps; iu++) {
|
|
35471
|
-
for (let iv = 0; iv < steps; iv++) {
|
|
35472
|
-
const g00 = grid[iu][iv];
|
|
35473
|
-
const g01 = grid[iu][iv + 1];
|
|
35474
|
-
const g11 = grid[iu + 1][iv + 1];
|
|
35475
|
-
const g10 = grid[iu + 1][iv];
|
|
35476
|
-
triangles.push([g00, g01, g11], [g00, g11, g10]);
|
|
35477
|
-
}
|
|
35478
|
-
}
|
|
35479
|
-
}
|
|
35480
|
-
}
|
|
35481
|
-
if (triangles.length === 0) return void 0;
|
|
38301
|
+
const numComps = fnNode ? 1 : getColorSpaceComponentCount(doc, csNode);
|
|
38302
|
+
const mesh = new MeshShading(shType, new Stream(bytes), {
|
|
38303
|
+
bitsPerCoordinate: bpcCoord,
|
|
38304
|
+
bitsPerComponent: bpcComp,
|
|
38305
|
+
bitsPerFlag: bpcFlag,
|
|
38306
|
+
decode: decodeNums,
|
|
38307
|
+
numComps,
|
|
38308
|
+
colorFn: null,
|
|
38309
|
+
colorSpace: {
|
|
38310
|
+
numComps,
|
|
38311
|
+
getRgb(components) {
|
|
38312
|
+
const params = Array.from(components);
|
|
38313
|
+
const values = fnNode ? evalShadingFunctionToComponents(doc, fnNode, params) : params;
|
|
38314
|
+
return new Uint8Array(convertColorSpaceComponentsToRgb(doc, csNode, csName, values).map((value) => Math.round(Math.max(0, Math.min(1, value)) * 255)));
|
|
38315
|
+
}
|
|
38316
|
+
}
|
|
38317
|
+
}, vPerRow);
|
|
38318
|
+
const [, , positions, colors, vertexCount] = mesh.getIR();
|
|
38319
|
+
if (vertexCount === 0) return void 0;
|
|
35482
38320
|
const [bx0, by0, bx1, by1] = targetBox;
|
|
35483
38321
|
const boxW = Math.max(1, bx1 - bx0);
|
|
35484
38322
|
const boxH = Math.max(1, by1 - by0);
|
|
@@ -35490,10 +38328,10 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
|
|
|
35490
38328
|
const [px, py] = transformPoint(effectiveCtm, vx, vy);
|
|
35491
38329
|
return [(px - bx0) / boxW * imgW, (by1 - py) / boxH * imgH];
|
|
35492
38330
|
};
|
|
35493
|
-
for (
|
|
35494
|
-
const [x0, y0] = toImgCoords(
|
|
35495
|
-
const [x1, y1] = toImgCoords(
|
|
35496
|
-
const [x2, y2] = toImgCoords(
|
|
38331
|
+
for (let vertex = 0; vertex < vertexCount; vertex += 3) {
|
|
38332
|
+
const [x0, y0] = toImgCoords(positions[vertex * 2], positions[vertex * 2 + 1]);
|
|
38333
|
+
const [x1, y1] = toImgCoords(positions[vertex * 2 + 2], positions[vertex * 2 + 3]);
|
|
38334
|
+
const [x2, y2] = toImgCoords(positions[vertex * 2 + 4], positions[vertex * 2 + 5]);
|
|
35497
38335
|
const denom = (y1 - y2) * (x0 - x2) + (x2 - x1) * (y0 - y2);
|
|
35498
38336
|
if (Math.abs(denom) < 1e-6) continue;
|
|
35499
38337
|
const minX = Math.max(0, Math.floor(Math.min(x0, x1, x2)));
|
|
@@ -35508,13 +38346,12 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
|
|
|
35508
38346
|
const w1 = ((y2 - y0) * (px - x2) + (x0 - x2) * (py - y2)) / denom;
|
|
35509
38347
|
const w2 = 1 - w0 - w1;
|
|
35510
38348
|
if (w0 >= -1e-4 && w1 >= -1e-4 && w2 >= -1e-4) {
|
|
35511
|
-
const r = w0 * v0.rgb[0] + w1 * v1.rgb[0] + w2 * v2.rgb[0];
|
|
35512
|
-
const g = w0 * v0.rgb[1] + w1 * v1.rgb[1] + w2 * v2.rgb[1];
|
|
35513
|
-
const b = w0 * v0.rgb[2] + w1 * v1.rgb[2] + w2 * v2.rgb[2];
|
|
35514
38349
|
const pIdx = (iy * imgW + ix) * 4;
|
|
35515
|
-
|
|
35516
|
-
|
|
35517
|
-
|
|
38350
|
+
for (let channel = 0; channel < 3; channel++) {
|
|
38351
|
+
rgba[pIdx + channel] = Math.round(
|
|
38352
|
+
w0 * colors[vertex * 4 + channel] + w1 * colors[vertex * 4 + 4 + channel] + w2 * colors[vertex * 4 + 8 + channel]
|
|
38353
|
+
);
|
|
38354
|
+
}
|
|
35518
38355
|
rgba[pIdx + 3] = a8;
|
|
35519
38356
|
}
|
|
35520
38357
|
}
|
|
@@ -35601,6 +38438,8 @@ function renderShadingDictToImage(doc, shDict, shadingCtm, targetBox, fillAlpha,
|
|
|
35601
38438
|
const [a, b, c, d, e, f] = effectiveCtm;
|
|
35602
38439
|
const det = a * d - b * c;
|
|
35603
38440
|
if (Math.abs(det) <= 1e-8) return void 0;
|
|
38441
|
+
const [sa, sb, sc, sd, se, sf] = shadingCtm;
|
|
38442
|
+
const shadingDet = sa * sd - sb * sc;
|
|
35604
38443
|
const t0Dom = shDomain[0] ?? 0;
|
|
35605
38444
|
const t1Dom = shDomain[1] ?? 1;
|
|
35606
38445
|
for (let iy = 0; iy < imgH; iy++) {
|
|
@@ -35611,8 +38450,10 @@ function renderShadingDictToImage(doc, shDict, shadingCtm, targetBox, fillAlpha,
|
|
|
35611
38450
|
const dxPdf = xPdf - e;
|
|
35612
38451
|
const xs = (d * dxPdf - c * dyPdf) / det;
|
|
35613
38452
|
const ys = (-b * dxPdf + a * dyPdf) / det;
|
|
35614
|
-
if (shBBox
|
|
35615
|
-
|
|
38453
|
+
if (shBBox) {
|
|
38454
|
+
const bboxX = (sd * (xPdf - se) - sc * (yPdf - sf)) / shadingDet;
|
|
38455
|
+
const bboxY = (-sb * (xPdf - se) + sa * (yPdf - sf)) / shadingDet;
|
|
38456
|
+
if (bboxX < shBBox[0] || bboxX > shBBox[2] || bboxY < shBBox[1] || bboxY > shBBox[3]) continue;
|
|
35616
38457
|
}
|
|
35617
38458
|
let comps;
|
|
35618
38459
|
if (shType === 1) {
|
|
@@ -35912,7 +38753,8 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
35912
38753
|
const shDict = shNode?.kind === "dict" ? shNode : shNode?.kind === "stream" ? shNode.dict : void 0;
|
|
35913
38754
|
const shStream = shNode?.kind === "stream" ? shNode : void 0;
|
|
35914
38755
|
if (shDict) {
|
|
35915
|
-
const
|
|
38756
|
+
const [originX, originY] = params.origin ?? [0, 0];
|
|
38757
|
+
const targetBox = st.clipRect ?? [originX, originY, originX + params.width, originY + params.height];
|
|
35916
38758
|
const img = renderShadingDictToImage(
|
|
35917
38759
|
params.cosDoc,
|
|
35918
38760
|
shDict,
|
|
@@ -35951,12 +38793,10 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
35951
38793
|
} else if (operator === "RG" || operator === "SC" || operator === "SCN") {
|
|
35952
38794
|
st.strokeColor = resolveScColorOperands(operator === "RG" ? "DeviceRGB" : st.strokeColorSpaceName, ops, activeResources);
|
|
35953
38795
|
} else if (operator === "k") {
|
|
35954
|
-
|
|
35955
|
-
st.fillColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
|
|
38796
|
+
st.fillColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
|
|
35956
38797
|
st.fillPatternName = void 0;
|
|
35957
38798
|
} else if (operator === "K") {
|
|
35958
|
-
|
|
35959
|
-
st.strokeColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
|
|
38799
|
+
st.strokeColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
|
|
35960
38800
|
} else if (operator === "gs" && params.cosDoc && activeResources && ops[0]?.kind === "name") {
|
|
35961
38801
|
const extDict = params.cosDoc.resolveDict(dictGet(activeResources, "ExtGState"));
|
|
35962
38802
|
const gsDict = extDict ? params.cosDoc.resolveDict(dictGet(extDict, ops[0].decoded)) : void 0;
|
|
@@ -36165,7 +39005,7 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
36165
39005
|
stateStack.pop();
|
|
36166
39006
|
capturedOperations = parentOperations;
|
|
36167
39007
|
}
|
|
36168
|
-
if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
|
|
39008
|
+
if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, isolated, bboxClip: nextClipPaths?.[0], blendMode: st.blendMode, clipRect: st.clipRect } });
|
|
36169
39009
|
};
|
|
36170
39010
|
const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
|
|
36171
39011
|
for (const node of nodes) {
|
|
@@ -36749,6 +39589,7 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
36749
39589
|
pageIndex: params.pageIndex,
|
|
36750
39590
|
width: params.width,
|
|
36751
39591
|
height: params.height,
|
|
39592
|
+
...params.origin ? { origin: params.origin } : {},
|
|
36752
39593
|
rotation: params.rotation ?? 0,
|
|
36753
39594
|
glyphs,
|
|
36754
39595
|
paths,
|
|
@@ -38219,7 +41060,7 @@ var PdfPage = class {
|
|
|
38219
41060
|
return [n0.value, n1.value, n2.value, n3.value];
|
|
38220
41061
|
}
|
|
38221
41062
|
}
|
|
38222
|
-
return [0, 0, 612, 792];
|
|
41063
|
+
return key === "MediaBox" ? [0, 0, 612, 792] : this.resolveBox("MediaBox");
|
|
38223
41064
|
}
|
|
38224
41065
|
getMediaBox() {
|
|
38225
41066
|
return this.resolveBox("MediaBox");
|
|
@@ -38892,16 +41733,19 @@ var PdfPage = class {
|
|
|
38892
41733
|
});
|
|
38893
41734
|
}
|
|
38894
41735
|
}
|
|
38895
|
-
|
|
41736
|
+
const mediaBox = this.getMediaBox(), cropBox = this.getCropBox();
|
|
41737
|
+
const originX = Math.min(mediaBox[0], mediaBox[2]), originY = Math.min(mediaBox[1], mediaBox[3]);
|
|
41738
|
+
return { ...evaluateContentStreamToDisplayList({
|
|
38896
41739
|
pageIndex: this.index,
|
|
38897
41740
|
width,
|
|
38898
41741
|
height,
|
|
41742
|
+
origin: [originX, originY],
|
|
38899
41743
|
rotation: this.getRotation(),
|
|
38900
41744
|
nodes: baseNodes,
|
|
38901
41745
|
cosDoc: this.cosDoc,
|
|
38902
41746
|
resourcesDict: evalResourcesDict,
|
|
38903
41747
|
annotations: extractPageAnnotations(this.cosDoc, this.pageDict)
|
|
38904
|
-
});
|
|
41748
|
+
}), cropBox: [cropBox[0] - originX, cropBox[1] - originY, cropBox[2] - originX, cropBox[3] - originY] };
|
|
38905
41749
|
}
|
|
38906
41750
|
extractPage(options) {
|
|
38907
41751
|
const dl = this.evaluateDisplayList();
|
|
@@ -38919,10 +41763,10 @@ var PdfPage = class {
|
|
|
38919
41763
|
return extractTablesFromDisplayList(this.evaluateDisplayList());
|
|
38920
41764
|
}
|
|
38921
41765
|
renderToBitmap(options) {
|
|
38922
|
-
return renderDisplayListToBitmap(this.evaluateDisplayList(), options);
|
|
41766
|
+
return renderDisplayListToBitmap(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
|
|
38923
41767
|
}
|
|
38924
41768
|
renderToPng(options) {
|
|
38925
|
-
return renderDisplayListToPng(this.evaluateDisplayList(), options);
|
|
41769
|
+
return renderDisplayListToPng(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
|
|
38926
41770
|
}
|
|
38927
41771
|
};
|
|
38928
41772
|
function createStandardFontHandle(standardName) {
|
|
@@ -40368,7 +43212,7 @@ function prepareStroke(path, scale) {
|
|
|
40368
43212
|
}
|
|
40369
43213
|
return { matrix, width, dashArray, dashPhase };
|
|
40370
43214
|
}
|
|
40371
|
-
function strokeContours(path, pageHeight, scale) {
|
|
43215
|
+
function strokeContours(path, pageHeight, scale, originX = 0, originY = 0) {
|
|
40372
43216
|
const stroke = prepareStroke(path, scale);
|
|
40373
43217
|
if (!stroke) return [];
|
|
40374
43218
|
const inverse = inverseStrokeMatrix(stroke.matrix);
|
|
@@ -40380,8 +43224,8 @@ function strokeContours(path, pageHeight, scale) {
|
|
|
40380
43224
|
(inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
|
|
40381
43225
|
];
|
|
40382
43226
|
const toScreen = ([x, y]) => [
|
|
40383
|
-
(a * x / strokeScale + c * y / strokeScale + e) * scale,
|
|
40384
|
-
(pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
|
|
43227
|
+
(a * x / strokeScale + c * y / strokeScale + e - originX) * scale,
|
|
43228
|
+
(pageHeight + originY - b * x / strokeScale - d * y / strokeScale - f) * scale
|
|
40385
43229
|
];
|
|
40386
43230
|
const contours = strokeOutlines(
|
|
40387
43231
|
segmentsToScreenPaths(path.segments, pageHeight, scale, project),
|
|
@@ -40539,18 +43383,37 @@ function renderSoftMask(mask, displayList, scale) {
|
|
|
40539
43383
|
}
|
|
40540
43384
|
return bitmap;
|
|
40541
43385
|
}
|
|
40542
|
-
function
|
|
40543
|
-
|
|
43386
|
+
function getDisplayListCropBox(list) {
|
|
43387
|
+
const full = [0, 0, list.width, list.height];
|
|
43388
|
+
const box = list.cropBox;
|
|
43389
|
+
if (!box || !box.every(Number.isFinite)) return full;
|
|
43390
|
+
const x0 = Math.max(0, Math.min(box[0], box[2]));
|
|
43391
|
+
const y0 = Math.max(0, Math.min(box[1], box[3]));
|
|
43392
|
+
const x1 = Math.min(list.width, Math.max(box[0], box[2]));
|
|
43393
|
+
const y1 = Math.min(list.height, Math.max(box[1], box[3]));
|
|
43394
|
+
return x1 > x0 && y1 > y0 ? [x0, y0, x1, y1] : full;
|
|
43395
|
+
}
|
|
43396
|
+
function hasCompositingEffects(operations, includeSoftMasks = false) {
|
|
43397
|
+
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));
|
|
43398
|
+
}
|
|
43399
|
+
function needsGroupBackdrop(group) {
|
|
43400
|
+
return group.isolated === false && !!group.softMask && hasCompositingEffects(group.operations, true);
|
|
43401
|
+
}
|
|
43402
|
+
function containsBackdropGroup(operations) {
|
|
43403
|
+
return operations.some((operation) => operation.kind === "group" && (needsGroupBackdrop(operation.value) || containsBackdropGroup(operation.value.operations)));
|
|
40544
43404
|
}
|
|
40545
43405
|
function renderDisplayListToBitmap(displayList, options = {}) {
|
|
40546
43406
|
const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
|
|
40547
43407
|
const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
|
|
40548
43408
|
const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
|
|
40549
43409
|
const scale = scaleX;
|
|
43410
|
+
const [originX, originY] = displayList.origin ?? [0, 0];
|
|
43411
|
+
const pageTop = originY + displayList.height;
|
|
43412
|
+
const toScreen = (x, y) => [(x - originX) * scale, (pageTop - y) * scale];
|
|
40550
43413
|
const width = Math.max(1, Math.round(displayList.width * scale));
|
|
40551
43414
|
const height = Math.max(1, Math.round(displayList.height * scale));
|
|
40552
43415
|
const rgba = new Uint8Array(width * height * 4);
|
|
40553
|
-
const deferBackground = !options.transparent &&
|
|
43416
|
+
const deferBackground = !options.transparent && hasCompositingEffects(paintOperations(displayList));
|
|
40554
43417
|
const transparent = options.transparent || deferBackground;
|
|
40555
43418
|
const bg = options.background ?? { r: 1, g: 1, b: 1 };
|
|
40556
43419
|
const bgR = transparent ? 0 : Math.round(bg.r * 255);
|
|
@@ -40575,14 +43438,27 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40575
43438
|
let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
|
|
40576
43439
|
if (operation.kind === "group") {
|
|
40577
43440
|
const group = operation.value;
|
|
40578
|
-
|
|
43441
|
+
let operations = group.operations;
|
|
43442
|
+
if (needsGroupBackdrop(group)) {
|
|
43443
|
+
operations = [{ kind: "image", value: {
|
|
43444
|
+
name: "GroupBackdrop",
|
|
43445
|
+
width,
|
|
43446
|
+
height,
|
|
43447
|
+
decodedRgba: rgba.slice(),
|
|
43448
|
+
matrix: [width / scale, 0, 0, height / scale, originX, pageTop - height / scale],
|
|
43449
|
+
colorSpace: "DeviceRGB",
|
|
43450
|
+
bitsPerComponent: 8,
|
|
43451
|
+
...group.bboxClip ? { clipPaths: [group.bboxClip] } : {}
|
|
43452
|
+
} }, ...operations];
|
|
43453
|
+
}
|
|
43454
|
+
const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, useCropBox: false, transparent: true });
|
|
40579
43455
|
for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
|
|
40580
43456
|
operation = { kind: "image", value: {
|
|
40581
43457
|
name: "TransparencyGroup",
|
|
40582
43458
|
width: bitmap.width,
|
|
40583
43459
|
height: bitmap.height,
|
|
40584
43460
|
decodedRgba: bitmap.data,
|
|
40585
|
-
matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale,
|
|
43461
|
+
matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, originX, pageTop - bitmap.height / scale],
|
|
40586
43462
|
colorSpace: "DeviceRGB",
|
|
40587
43463
|
bitsPerComponent: 8,
|
|
40588
43464
|
blendMode: group.blendMode,
|
|
@@ -40596,7 +43472,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40596
43472
|
for (const clip of clips) {
|
|
40597
43473
|
const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
|
|
40598
43474
|
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);
|
|
43475
|
+
fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale, toScreen), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
|
|
40600
43476
|
for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
|
|
40601
43477
|
}
|
|
40602
43478
|
cachedClips = clips;
|
|
@@ -40643,15 +43519,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40643
43519
|
if (operation.kind === "path") {
|
|
40644
43520
|
const path = operation.value;
|
|
40645
43521
|
if (path.fillColor) {
|
|
40646
|
-
const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale), true);
|
|
40647
|
-
const clipScreen = path.clipRect ? [path.clipRect[0] * scale, (
|
|
43522
|
+
const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale, toScreen), true);
|
|
43523
|
+
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
43524
|
fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
|
|
40649
43525
|
}
|
|
40650
43526
|
if (path.strokeColor) {
|
|
40651
43527
|
const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
|
|
40652
43528
|
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, (
|
|
43529
|
+
const edges = pathsToEdges(strokeContours(path, displayList.height, scale, originX, originY).map((points) => ({ points, closed: true })));
|
|
43530
|
+
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
43531
|
fillEdgesScanline4x4(
|
|
40656
43532
|
rgba,
|
|
40657
43533
|
width,
|
|
@@ -40674,12 +43550,12 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40674
43550
|
if (Math.abs(det) <= 1e-8) continue;
|
|
40675
43551
|
const cornersPdfX = [e, a + e, a + c + e, c + e];
|
|
40676
43552
|
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((
|
|
43553
|
+
const cornersPx = cornersPdfX.map((cx) => (cx - originX) * scale);
|
|
43554
|
+
const cornersPy = cornersPdfY.map((cy) => (pageTop - cy) * scale);
|
|
43555
|
+
const clipMinPx = img.clipRect ? Math.floor((img.clipRect[0] - originX) * scale) : 0;
|
|
43556
|
+
const clipMaxPx = img.clipRect ? Math.ceil((img.clipRect[2] - originX) * scale) - 1 : width - 1;
|
|
43557
|
+
const clipMinPy = img.clipRect ? Math.floor((pageTop - img.clipRect[3]) * scale) : 0;
|
|
43558
|
+
const clipMaxPy = img.clipRect ? Math.ceil((pageTop - img.clipRect[1]) * scale) - 1 : height - 1;
|
|
40683
43559
|
const minPx = Math.max(0, clipMinPx, Math.floor(Math.min(...cornersPx)));
|
|
40684
43560
|
const maxPx = Math.min(width - 1, clipMaxPx, Math.ceil(Math.max(...cornersPx)) - 1);
|
|
40685
43561
|
const minPy = Math.max(0, clipMinPy, Math.floor(Math.min(...cornersPy)));
|
|
@@ -40696,11 +43572,11 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40696
43572
|
const smooth = Math.fround((s1 + s2 + Math.hypot(s1 - s2, 2 * cross)) / 2) <= 1;
|
|
40697
43573
|
const sample = new Float64Array(4);
|
|
40698
43574
|
for (let py = minPy; py <= maxPy; py++) {
|
|
40699
|
-
const yPdf =
|
|
43575
|
+
const yPdf = pageTop - (py + 0.5) / scale;
|
|
40700
43576
|
if (img.clipRect && (yPdf < img.clipRect[1] || yPdf > img.clipRect[3])) continue;
|
|
40701
43577
|
const dyPdf = yPdf - f;
|
|
40702
43578
|
for (let px = minPx; px <= maxPx; px++) {
|
|
40703
|
-
const xPdf = (px + 0.5) / scale;
|
|
43579
|
+
const xPdf = originX + (px + 0.5) / scale;
|
|
40704
43580
|
if (img.clipRect && (xPdf < img.clipRect[0] || xPdf > img.clipRect[2])) continue;
|
|
40705
43581
|
const dxPdf = xPdf - e;
|
|
40706
43582
|
const u = (d * dxPdf - c * dyPdf) / det;
|
|
@@ -40761,6 +43637,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40761
43637
|
}
|
|
40762
43638
|
result = { width: targetW, height: targetH, data: resampled };
|
|
40763
43639
|
}
|
|
43640
|
+
if (options.useCropBox) {
|
|
43641
|
+
const box = getDisplayListCropBox(displayList);
|
|
43642
|
+
result = cropRgbaBitmap(result, {
|
|
43643
|
+
x: box[0] * scaleX,
|
|
43644
|
+
y: (displayList.height - box[3]) * scaleY,
|
|
43645
|
+
width: (box[2] - box[0]) * scaleX,
|
|
43646
|
+
height: (box[3] - box[1]) * scaleY
|
|
43647
|
+
});
|
|
43648
|
+
}
|
|
40764
43649
|
result = rotateRgbaBitmapQuarterTurns(result, displayList.rotation ?? 0);
|
|
40765
43650
|
if (options.cropRect) {
|
|
40766
43651
|
result = cropRgbaBitmap(result, options.cropRect);
|
|
@@ -40830,18 +43715,44 @@ function svgPathData(segments, height, matrix) {
|
|
|
40830
43715
|
}
|
|
40831
43716
|
function renderDisplayListToSvg(displayList, options = {}) {
|
|
40832
43717
|
const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1);
|
|
43718
|
+
if (containsBackdropGroup(paintOperations(displayList))) {
|
|
43719
|
+
const bitmap = renderDisplayListToBitmap(displayList, { ...options, scale: baseScale });
|
|
43720
|
+
const embedded = svgImage({
|
|
43721
|
+
name: "PageComposite",
|
|
43722
|
+
width: bitmap.width,
|
|
43723
|
+
height: bitmap.height,
|
|
43724
|
+
decodedRgba: bitmap.data,
|
|
43725
|
+
matrix: [bitmap.width, 0, 0, bitmap.height, 0, 0],
|
|
43726
|
+
colorSpace: "DeviceRGB",
|
|
43727
|
+
bitsPerComponent: 8
|
|
43728
|
+
}, bitmap.height);
|
|
43729
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${bitmap.width}" height="${bitmap.height}" viewBox="0 0 ${bitmap.width} ${bitmap.height}">${embedded}</svg>
|
|
43730
|
+
`;
|
|
43731
|
+
}
|
|
40833
43732
|
const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
|
|
40834
43733
|
const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
|
|
40835
|
-
const
|
|
43734
|
+
const [originX, originY] = displayList.origin ?? [0, 0];
|
|
43735
|
+
const viewport = new PageViewport({ viewBox: [originX, originY, originX + displayList.width, originY + displayList.height], userUnit: 1, scale: 1, rotation: displayList.rotation ?? 0 });
|
|
40836
43736
|
const quarterTurn = displayList.rotation === 90 || displayList.rotation === 270;
|
|
40837
43737
|
const outputScaleX = quarterTurn ? scaleY : scaleX;
|
|
40838
43738
|
const outputScaleY = quarterTurn ? scaleX : scaleY;
|
|
40839
|
-
|
|
40840
|
-
|
|
40841
|
-
|
|
40842
|
-
|
|
40843
|
-
|
|
40844
|
-
|
|
43739
|
+
let bounds = [0, 0, viewport.width, viewport.height];
|
|
43740
|
+
if (options.useCropBox) {
|
|
43741
|
+
const box = getDisplayListCropBox(displayList);
|
|
43742
|
+
const [x0, y0, x1, y1] = [box[0] + originX, box[1] + originY, box[2] + originX, box[3] + originY];
|
|
43743
|
+
const [a, b, c, d, e, f] = viewport.transform;
|
|
43744
|
+
bounds = [a * x0 + c * y0 + e, b * x0 + d * y0 + f, a * x1 + c * y1 + e, b * x1 + d * y1 + f];
|
|
43745
|
+
}
|
|
43746
|
+
const viewX = Math.min(bounds[0], bounds[2]), viewY = Math.min(bounds[1], bounds[3]);
|
|
43747
|
+
const viewWidth = Math.abs(bounds[2] - bounds[0]), viewHeight = Math.abs(bounds[3] - bounds[1]);
|
|
43748
|
+
const fullW = Math.max(1, Math.round(viewWidth * outputScaleX));
|
|
43749
|
+
const fullH = Math.max(1, Math.round(viewHeight * outputScaleY));
|
|
43750
|
+
const cropX = options.cropRect ? options.cropRect.x / outputScaleX : 0;
|
|
43751
|
+
const vbX = viewX + cropX;
|
|
43752
|
+
const cropY = options.cropRect ? options.cropRect.y / outputScaleY : 0;
|
|
43753
|
+
const vbY = viewY + cropY;
|
|
43754
|
+
const vbW = options.cropRect && options.cropRect.width > 0 ? options.cropRect.width / outputScaleX : Math.max(1, viewWidth - cropX);
|
|
43755
|
+
const vbH = options.cropRect && options.cropRect.height > 0 ? options.cropRect.height / outputScaleY : Math.max(1, viewHeight - cropY);
|
|
40845
43756
|
const outW = options.cropRect && options.cropRect.width > 0 ? Math.round(options.cropRect.width) : Math.max(1, fullW - Math.round(options.cropRect?.x ?? 0));
|
|
40846
43757
|
const outH = options.cropRect && options.cropRect.height > 0 ? Math.round(options.cropRect.height) : Math.max(1, fullH - Math.round(options.cropRect?.y ?? 0));
|
|
40847
43758
|
const parts = [
|
|
@@ -40851,7 +43762,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
|
|
|
40851
43762
|
parts.push(` <rect x="${vbX}" y="${vbY}" width="${vbW}" height="${vbH}" fill="#ffffff"/>`);
|
|
40852
43763
|
}
|
|
40853
43764
|
parts.push('<g style="isolation:isolate">');
|
|
40854
|
-
if (displayList.rotation) {
|
|
43765
|
+
if (displayList.rotation || originX || originY) {
|
|
40855
43766
|
const [a, b, c, d, e, f] = viewport.transform;
|
|
40856
43767
|
parts.push(`<g transform="matrix(${a} ${b} ${-c} ${-d} ${e + c * displayList.height} ${f + d * displayList.height})">`);
|
|
40857
43768
|
}
|
|
@@ -40877,11 +43788,11 @@ function renderDisplayListToSvg(displayList, options = {}) {
|
|
|
40877
43788
|
width: bitmap.width,
|
|
40878
43789
|
height: bitmap.height,
|
|
40879
43790
|
decodedRgba: bitmap.data,
|
|
40880
|
-
matrix: [displayList.width, 0, 0, displayList.height,
|
|
43791
|
+
matrix: [displayList.width, 0, 0, displayList.height, originX, originY],
|
|
40881
43792
|
colorSpace: "DeviceGray",
|
|
40882
43793
|
bitsPerComponent: 8
|
|
40883
43794
|
};
|
|
40884
|
-
parts.push(`<defs><mask id="${id}" maskUnits="userSpaceOnUse" x="
|
|
43795
|
+
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
43796
|
}
|
|
40886
43797
|
parts.push(`<g mask="url(#${id})">`);
|
|
40887
43798
|
}
|
|
@@ -40893,7 +43804,7 @@ function renderDisplayListToSvg(displayList, options = {}) {
|
|
|
40893
43804
|
}
|
|
40894
43805
|
for (const image of imageClips) {
|
|
40895
43806
|
const id = `image-clip-${clipId++}`;
|
|
40896
|
-
parts.push(`<defs><mask id="${id}" maskUnits="userSpaceOnUse" x="
|
|
43807
|
+
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
43808
|
}
|
|
40898
43809
|
if (operation.kind === "group") {
|
|
40899
43810
|
parts.push(`<g opacity="${operation.value.alpha}" style="isolation:isolate">`);
|
|
@@ -40937,84 +43848,11 @@ function renderDisplayListToSvg(displayList, options = {}) {
|
|
|
40937
43848
|
}
|
|
40938
43849
|
};
|
|
40939
43850
|
appendOperations(paintOperations(displayList));
|
|
40940
|
-
if (displayList.rotation) parts.push("</g>");
|
|
43851
|
+
if (displayList.rotation || originX || originY) parts.push("</g>");
|
|
40941
43852
|
parts.push("</g>");
|
|
40942
43853
|
parts.push("</svg>\n");
|
|
40943
43854
|
return parts.join("\n");
|
|
40944
43855
|
}
|
|
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
43856
|
function discardUnreachableObjects(doc) {
|
|
41019
43857
|
const reachable = /* @__PURE__ */ new Set();
|
|
41020
43858
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -41925,29 +44763,9 @@ function runPdftoppmCliSync(argv, files, options = {}) {
|
|
|
41925
44763
|
if (oddOnly && p % 2 === 0) continue;
|
|
41926
44764
|
if (evenOnly && p % 2 === 1) continue;
|
|
41927
44765
|
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
|
-
}
|
|
44766
|
+
const displayList = page.evaluateDisplayList({ hideAnnotations });
|
|
44767
|
+
const box = useCropBox ? getDisplayListCropBox(displayList) : [0, 0, displayList.width, displayList.height];
|
|
44768
|
+
const rawSize = { width: box[2] - box[0], height: box[3] - box[1] };
|
|
41951
44769
|
const rot = page.getRotation();
|
|
41952
44770
|
const ptW = rot === 90 || rot === 270 ? rawSize.height : rawSize.width;
|
|
41953
44771
|
const ptH = rot === 90 || rot === 270 ? rawSize.width : rawSize.height;
|
|
@@ -41970,33 +44788,17 @@ function runPdftoppmCliSync(argv, files, options = {}) {
|
|
|
41970
44788
|
const cropRect = hasCrop ? { x: cropX, y: cropY, width: cropW, height: cropH } : void 0;
|
|
41971
44789
|
let renderedBytes;
|
|
41972
44790
|
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 }), {
|
|
44791
|
+
const svgText = renderDisplayListToSvg(displayList, {
|
|
41990
44792
|
dpiX: effDpiX,
|
|
41991
44793
|
dpiY: effDpiY,
|
|
41992
44794
|
useCropBox,
|
|
41993
|
-
cropRect
|
|
44795
|
+
cropRect,
|
|
41994
44796
|
hideAnnotations,
|
|
41995
44797
|
transparent
|
|
41996
44798
|
});
|
|
41997
44799
|
renderedBytes = new TextEncoder().encode(svgText);
|
|
41998
44800
|
} else {
|
|
41999
|
-
const bitmap =
|
|
44801
|
+
const bitmap = renderDisplayListToBitmap(displayList, {
|
|
42000
44802
|
dpiX: effDpiX,
|
|
42001
44803
|
dpiY: effDpiY,
|
|
42002
44804
|
useCropBox,
|