@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,
|
|
@@ -22512,6 +22517,3308 @@ var getFontBasicMetrics = getLookupTableFactory(function(t) {
|
|
|
22512
22517
|
xHeight: Math.NaN
|
|
22513
22518
|
};
|
|
22514
22519
|
});
|
|
22520
|
+
function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
|
|
22521
|
+
const COMPONENTS = 3;
|
|
22522
|
+
alpha01 = alpha01 !== 1 ? 0 : alpha01;
|
|
22523
|
+
const xRatio = w1 / w2;
|
|
22524
|
+
const yRatio = h1 / h2;
|
|
22525
|
+
let newIndex = 0, oldIndex;
|
|
22526
|
+
const xScaled = new Uint16Array(w2);
|
|
22527
|
+
const w1Scanline = w1 * COMPONENTS;
|
|
22528
|
+
for (let i = 0; i < w2; i++) {
|
|
22529
|
+
xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
|
|
22530
|
+
}
|
|
22531
|
+
for (let i = 0; i < h2; i++) {
|
|
22532
|
+
const py = Math.floor(i * yRatio) * w1Scanline;
|
|
22533
|
+
for (let j = 0; j < w2; j++) {
|
|
22534
|
+
oldIndex = py + xScaled[j];
|
|
22535
|
+
dest[newIndex++] = src[oldIndex++];
|
|
22536
|
+
dest[newIndex++] = src[oldIndex++];
|
|
22537
|
+
dest[newIndex++] = src[oldIndex++];
|
|
22538
|
+
newIndex += alpha01;
|
|
22539
|
+
}
|
|
22540
|
+
}
|
|
22541
|
+
}
|
|
22542
|
+
function isDefaultDecodeHelper(decode, expectedLen) {
|
|
22543
|
+
if (!Array.isArray(decode)) {
|
|
22544
|
+
return true;
|
|
22545
|
+
}
|
|
22546
|
+
const decodeLen = decode.length;
|
|
22547
|
+
if (decodeLen < expectedLen) {
|
|
22548
|
+
warn2("Decode map length is too short.");
|
|
22549
|
+
return true;
|
|
22550
|
+
}
|
|
22551
|
+
if (decodeLen > expectedLen) {
|
|
22552
|
+
info("Truncating too long decode map.");
|
|
22553
|
+
decode.length = expectedLen;
|
|
22554
|
+
}
|
|
22555
|
+
return false;
|
|
22556
|
+
}
|
|
22557
|
+
var ColorSpace = class _ColorSpace {
|
|
22558
|
+
static #rgbBuf = new Uint8ClampedArray(3);
|
|
22559
|
+
constructor(name, numComps) {
|
|
22560
|
+
if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _ColorSpace) {
|
|
22561
|
+
unreachable2("Cannot initialize ColorSpace.");
|
|
22562
|
+
}
|
|
22563
|
+
this.name = name;
|
|
22564
|
+
this.numComps = numComps;
|
|
22565
|
+
}
|
|
22566
|
+
/**
|
|
22567
|
+
* Converts the color value to the RGB color. The color components are
|
|
22568
|
+
* located in the src array starting from the srcOffset. Returns the array
|
|
22569
|
+
* of the rgb components, each value ranging from [0,255].
|
|
22570
|
+
*/
|
|
22571
|
+
getRgb(src, srcOffset, output = new Uint8ClampedArray(3)) {
|
|
22572
|
+
this.getRgbItem(src, srcOffset, output, 0);
|
|
22573
|
+
return output;
|
|
22574
|
+
}
|
|
22575
|
+
getRgbHex(src, srcOffset) {
|
|
22576
|
+
const buffer = this.getRgb(src, srcOffset, _ColorSpace.#rgbBuf);
|
|
22577
|
+
return Util.makeHexColor(buffer[0], buffer[1], buffer[2]);
|
|
22578
|
+
}
|
|
22579
|
+
/**
|
|
22580
|
+
* Converts the color value to the RGB color, similar to the getRgb method.
|
|
22581
|
+
* The result placed into the dest array starting from the destOffset.
|
|
22582
|
+
*/
|
|
22583
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
22584
|
+
unreachable2("Should not call ColorSpace.getRgbItem");
|
|
22585
|
+
}
|
|
22586
|
+
/**
|
|
22587
|
+
* Converts the specified number of the color values to the RGB colors.
|
|
22588
|
+
* The colors are located in the src array starting from the srcOffset.
|
|
22589
|
+
* The result is placed into the dest array starting from the destOffset.
|
|
22590
|
+
* The src array items shall be in [0,2^bits) range, the dest array items
|
|
22591
|
+
* will be in [0,255] range. alpha01 indicates how many alpha components
|
|
22592
|
+
* there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
|
|
22593
|
+
* array).
|
|
22594
|
+
*/
|
|
22595
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
22596
|
+
unreachable2("Should not call ColorSpace.getRgbBuffer");
|
|
22597
|
+
}
|
|
22598
|
+
/**
|
|
22599
|
+
* Converts `count` unscaled colors to RGB, starting at `destOffset`.
|
|
22600
|
+
* Components use the native color-space ranges expected by `getRgbItem`,
|
|
22601
|
+
* and each output has a `3 + alpha01` byte stride.
|
|
22602
|
+
* Subclasses may override this to batch expensive conversions.
|
|
22603
|
+
*/
|
|
22604
|
+
getRgbItems(src, count, dest, destOffset, alpha01) {
|
|
22605
|
+
const { numComps } = this;
|
|
22606
|
+
for (let i = 0, srcOffset = 0; i < count; i++, srcOffset += numComps) {
|
|
22607
|
+
this.getRgbItem(src, srcOffset, dest, destOffset);
|
|
22608
|
+
destOffset += 3 + alpha01;
|
|
22609
|
+
}
|
|
22610
|
+
}
|
|
22611
|
+
/**
|
|
22612
|
+
* Returns true if source data will be equal the result/output data.
|
|
22613
|
+
*/
|
|
22614
|
+
isPassthrough(bits) {
|
|
22615
|
+
return false;
|
|
22616
|
+
}
|
|
22617
|
+
/**
|
|
22618
|
+
* Refer to the static `ColorSpace.isDefaultDecode` method below.
|
|
22619
|
+
*/
|
|
22620
|
+
isDefaultDecode(decode, bpc) {
|
|
22621
|
+
return _ColorSpace.isDefaultDecode(decode, this.numComps);
|
|
22622
|
+
}
|
|
22623
|
+
/**
|
|
22624
|
+
* Fills in the RGB colors in the destination buffer. alpha01 indicates
|
|
22625
|
+
* how many alpha components there are in the dest array; it will be either
|
|
22626
|
+
* 0 (RGB array) or 1 (RGBA array).
|
|
22627
|
+
*/
|
|
22628
|
+
fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {
|
|
22629
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
22630
|
+
assert2(
|
|
22631
|
+
dest instanceof Uint8ClampedArray,
|
|
22632
|
+
'ColorSpace.fillRgb: Unsupported "dest" type.'
|
|
22633
|
+
);
|
|
22634
|
+
}
|
|
22635
|
+
const count = originalWidth * originalHeight;
|
|
22636
|
+
let rgbBuf = null;
|
|
22637
|
+
const numComponentColors = 1 << bpc;
|
|
22638
|
+
const needsResizing = originalHeight !== height || originalWidth !== width;
|
|
22639
|
+
if (this.isPassthrough(bpc)) {
|
|
22640
|
+
rgbBuf = comps;
|
|
22641
|
+
} else if (this.numComps === 1 && count > numComponentColors && this.name !== "DeviceGray" && this.name !== "DeviceRGB") {
|
|
22642
|
+
const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);
|
|
22643
|
+
for (let i = 0; i < numComponentColors; i++) {
|
|
22644
|
+
allColors[i] = i;
|
|
22645
|
+
}
|
|
22646
|
+
const colorMap = new Uint8ClampedArray(numComponentColors * 3);
|
|
22647
|
+
this.getRgbBuffer(
|
|
22648
|
+
allColors,
|
|
22649
|
+
0,
|
|
22650
|
+
numComponentColors,
|
|
22651
|
+
colorMap,
|
|
22652
|
+
0,
|
|
22653
|
+
bpc,
|
|
22654
|
+
/* alpha01 = */
|
|
22655
|
+
0
|
|
22656
|
+
);
|
|
22657
|
+
if (!needsResizing) {
|
|
22658
|
+
let destPos = 0;
|
|
22659
|
+
for (let i = 0; i < count; ++i) {
|
|
22660
|
+
const key = comps[i] * 3;
|
|
22661
|
+
dest[destPos++] = colorMap[key];
|
|
22662
|
+
dest[destPos++] = colorMap[key + 1];
|
|
22663
|
+
dest[destPos++] = colorMap[key + 2];
|
|
22664
|
+
destPos += alpha01;
|
|
22665
|
+
}
|
|
22666
|
+
} else {
|
|
22667
|
+
rgbBuf = new Uint8Array(count * 3);
|
|
22668
|
+
let rgbPos = 0;
|
|
22669
|
+
for (let i = 0; i < count; ++i) {
|
|
22670
|
+
const key = comps[i] * 3;
|
|
22671
|
+
rgbBuf[rgbPos++] = colorMap[key];
|
|
22672
|
+
rgbBuf[rgbPos++] = colorMap[key + 1];
|
|
22673
|
+
rgbBuf[rgbPos++] = colorMap[key + 2];
|
|
22674
|
+
}
|
|
22675
|
+
}
|
|
22676
|
+
} else if (!needsResizing) {
|
|
22677
|
+
this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);
|
|
22678
|
+
} else {
|
|
22679
|
+
rgbBuf = new Uint8ClampedArray(count * 3);
|
|
22680
|
+
this.getRgbBuffer(
|
|
22681
|
+
comps,
|
|
22682
|
+
0,
|
|
22683
|
+
count,
|
|
22684
|
+
rgbBuf,
|
|
22685
|
+
0,
|
|
22686
|
+
bpc,
|
|
22687
|
+
/* alpha01 = */
|
|
22688
|
+
0
|
|
22689
|
+
);
|
|
22690
|
+
}
|
|
22691
|
+
if (rgbBuf) {
|
|
22692
|
+
if (needsResizing) {
|
|
22693
|
+
resizeRgbImage(
|
|
22694
|
+
rgbBuf,
|
|
22695
|
+
dest,
|
|
22696
|
+
originalWidth,
|
|
22697
|
+
originalHeight,
|
|
22698
|
+
width,
|
|
22699
|
+
height,
|
|
22700
|
+
alpha01
|
|
22701
|
+
);
|
|
22702
|
+
} else {
|
|
22703
|
+
let destPos = 0, rgbPos = 0;
|
|
22704
|
+
for (let i = 0, ii = width * actualHeight; i < ii; i++) {
|
|
22705
|
+
dest[destPos++] = rgbBuf[rgbPos++];
|
|
22706
|
+
dest[destPos++] = rgbBuf[rgbPos++];
|
|
22707
|
+
dest[destPos++] = rgbBuf[rgbPos++];
|
|
22708
|
+
destPos += alpha01;
|
|
22709
|
+
}
|
|
22710
|
+
}
|
|
22711
|
+
}
|
|
22712
|
+
}
|
|
22713
|
+
/**
|
|
22714
|
+
* True if the colorspace has components in the default range of [0, 1].
|
|
22715
|
+
* This should be true for all colorspaces except for lab color spaces
|
|
22716
|
+
* which are [0,100], [-128, 127], [-128, 127].
|
|
22717
|
+
*/
|
|
22718
|
+
get usesZeroToOneRange() {
|
|
22719
|
+
return shadow2(this, "usesZeroToOneRange", true);
|
|
22720
|
+
}
|
|
22721
|
+
/**
|
|
22722
|
+
* Checks if a decode map matches the default decode map for a color space.
|
|
22723
|
+
* This handles the general decode maps where there are two values per
|
|
22724
|
+
* component, e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
|
|
22725
|
+
* This does not handle Lab, Indexed, or Pattern decode maps since they are
|
|
22726
|
+
* slightly different.
|
|
22727
|
+
* @param {Array} decode - Decode map (usually from an image).
|
|
22728
|
+
* @param {number} numComps - Number of components the color space has.
|
|
22729
|
+
*/
|
|
22730
|
+
static isDefaultDecode(decode, numComps) {
|
|
22731
|
+
if (isDefaultDecodeHelper(decode, numComps * 2)) {
|
|
22732
|
+
return true;
|
|
22733
|
+
}
|
|
22734
|
+
for (let i = 0, ii = decode.length; i < ii; i += 2) {
|
|
22735
|
+
if (decode[i] !== 0 || decode[i + 1] !== 1) {
|
|
22736
|
+
return false;
|
|
22737
|
+
}
|
|
22738
|
+
}
|
|
22739
|
+
return true;
|
|
22740
|
+
}
|
|
22741
|
+
};
|
|
22742
|
+
var DeviceCmykCS = class extends ColorSpace {
|
|
22743
|
+
constructor() {
|
|
22744
|
+
super("DeviceCMYK", 4);
|
|
22745
|
+
}
|
|
22746
|
+
// The coefficients below was found using numerical analysis: the method of
|
|
22747
|
+
// steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
|
|
22748
|
+
// where color_value is the tabular value from the table of sampled RGB colors
|
|
22749
|
+
// from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
|
|
22750
|
+
// CMYK color conversion using the estimation below:
|
|
22751
|
+
// f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
|
|
22752
|
+
#toRgb(src, srcOffset, srcScale, dest, destOffset) {
|
|
22753
|
+
const c = src[srcOffset] * srcScale;
|
|
22754
|
+
const m = src[srcOffset + 1] * srcScale;
|
|
22755
|
+
const y = src[srcOffset + 2] * srcScale;
|
|
22756
|
+
const k = src[srcOffset + 3] * srcScale;
|
|
22757
|
+
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);
|
|
22758
|
+
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);
|
|
22759
|
+
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);
|
|
22760
|
+
}
|
|
22761
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
22762
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
22763
|
+
assert2(
|
|
22764
|
+
dest instanceof Uint8ClampedArray,
|
|
22765
|
+
'DeviceCmykCS.getRgbItem: Unsupported "dest" type.'
|
|
22766
|
+
);
|
|
22767
|
+
}
|
|
22768
|
+
this.#toRgb(src, srcOffset, 1, dest, destOffset);
|
|
22769
|
+
}
|
|
22770
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
22771
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
22772
|
+
assert2(
|
|
22773
|
+
dest instanceof Uint8ClampedArray,
|
|
22774
|
+
'DeviceCmykCS.getRgbBuffer: Unsupported "dest" type.'
|
|
22775
|
+
);
|
|
22776
|
+
}
|
|
22777
|
+
const scale = 1 / ((1 << bits) - 1);
|
|
22778
|
+
for (let i = 0; i < count; i++) {
|
|
22779
|
+
this.#toRgb(src, srcOffset, scale, dest, destOffset);
|
|
22780
|
+
srcOffset += 4;
|
|
22781
|
+
destOffset += 3 + alpha01;
|
|
22782
|
+
}
|
|
22783
|
+
}
|
|
22784
|
+
};
|
|
22785
|
+
var CalGrayCS = class extends ColorSpace {
|
|
22786
|
+
constructor(whitePoint, blackPoint, gamma) {
|
|
22787
|
+
super("CalGray", 1);
|
|
22788
|
+
if (!whitePoint) {
|
|
22789
|
+
throw new FormatError(
|
|
22790
|
+
"WhitePoint missing - required for color space CalGray"
|
|
22791
|
+
);
|
|
22792
|
+
}
|
|
22793
|
+
[this.XW, this.YW, this.ZW] = whitePoint;
|
|
22794
|
+
[this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
|
|
22795
|
+
this.G = gamma || 1;
|
|
22796
|
+
if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
|
|
22797
|
+
throw new FormatError(
|
|
22798
|
+
`Invalid WhitePoint components for ${this.name}, no fallback available`
|
|
22799
|
+
);
|
|
22800
|
+
}
|
|
22801
|
+
if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
|
|
22802
|
+
info(`Invalid BlackPoint for ${this.name}, falling back to default.`);
|
|
22803
|
+
this.XB = this.YB = this.ZB = 0;
|
|
22804
|
+
}
|
|
22805
|
+
if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
|
|
22806
|
+
warn2(
|
|
22807
|
+
`${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ZB: ${this.ZB}, only default values are supported.`
|
|
22808
|
+
);
|
|
22809
|
+
}
|
|
22810
|
+
if (this.G < 1) {
|
|
22811
|
+
info(
|
|
22812
|
+
`Invalid Gamma: ${this.G} for ${this.name}, falling back to default.`
|
|
22813
|
+
);
|
|
22814
|
+
this.G = 1;
|
|
22815
|
+
}
|
|
22816
|
+
}
|
|
22817
|
+
#toRgb(src, srcOffset, dest, destOffset, scale) {
|
|
22818
|
+
const A = src[srcOffset] * scale;
|
|
22819
|
+
const AG = A ** this.G;
|
|
22820
|
+
const L = this.YW * AG;
|
|
22821
|
+
const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0);
|
|
22822
|
+
dest[destOffset] = val;
|
|
22823
|
+
dest[destOffset + 1] = val;
|
|
22824
|
+
dest[destOffset + 2] = val;
|
|
22825
|
+
}
|
|
22826
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
22827
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
22828
|
+
assert2(
|
|
22829
|
+
dest instanceof Uint8ClampedArray,
|
|
22830
|
+
'CalGrayCS.getRgbItem: Unsupported "dest" type.'
|
|
22831
|
+
);
|
|
22832
|
+
}
|
|
22833
|
+
this.#toRgb(src, srcOffset, dest, destOffset, 1);
|
|
22834
|
+
}
|
|
22835
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
22836
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
22837
|
+
assert2(
|
|
22838
|
+
dest instanceof Uint8ClampedArray,
|
|
22839
|
+
'CalGrayCS.getRgbBuffer: Unsupported "dest" type.'
|
|
22840
|
+
);
|
|
22841
|
+
}
|
|
22842
|
+
const scale = 1 / ((1 << bits) - 1);
|
|
22843
|
+
for (let i = 0; i < count; ++i) {
|
|
22844
|
+
this.#toRgb(src, srcOffset, dest, destOffset, scale);
|
|
22845
|
+
srcOffset += 1;
|
|
22846
|
+
destOffset += 3 + alpha01;
|
|
22847
|
+
}
|
|
22848
|
+
}
|
|
22849
|
+
};
|
|
22850
|
+
var CalRGBCS = class _CalRGBCS extends ColorSpace {
|
|
22851
|
+
// See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these
|
|
22852
|
+
// matrices.
|
|
22853
|
+
// prettier-ignore
|
|
22854
|
+
static #BRADFORD_SCALE_MATRIX = new Float32Array([
|
|
22855
|
+
0.8951,
|
|
22856
|
+
0.2664,
|
|
22857
|
+
-0.1614,
|
|
22858
|
+
-0.7502,
|
|
22859
|
+
1.7135,
|
|
22860
|
+
0.0367,
|
|
22861
|
+
0.0389,
|
|
22862
|
+
-0.0685,
|
|
22863
|
+
1.0296
|
|
22864
|
+
]);
|
|
22865
|
+
// prettier-ignore
|
|
22866
|
+
static #BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([
|
|
22867
|
+
0.9869929,
|
|
22868
|
+
-0.1470543,
|
|
22869
|
+
0.1599627,
|
|
22870
|
+
0.4323053,
|
|
22871
|
+
0.5183603,
|
|
22872
|
+
0.0492912,
|
|
22873
|
+
-85287e-7,
|
|
22874
|
+
0.0400428,
|
|
22875
|
+
0.9684867
|
|
22876
|
+
]);
|
|
22877
|
+
// See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html.
|
|
22878
|
+
// prettier-ignore
|
|
22879
|
+
static #SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([
|
|
22880
|
+
3.2404542,
|
|
22881
|
+
-1.5371385,
|
|
22882
|
+
-0.4985314,
|
|
22883
|
+
-0.969266,
|
|
22884
|
+
1.8760108,
|
|
22885
|
+
0.041556,
|
|
22886
|
+
0.0556434,
|
|
22887
|
+
-0.2040259,
|
|
22888
|
+
1.0572252
|
|
22889
|
+
]);
|
|
22890
|
+
static #FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);
|
|
22891
|
+
static #tempNormalizeMatrix = new Float32Array(3);
|
|
22892
|
+
static #tempConvertMatrix1 = new Float32Array(3);
|
|
22893
|
+
static #tempConvertMatrix2 = new Float32Array(3);
|
|
22894
|
+
static #DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8;
|
|
22895
|
+
constructor(whitePoint, blackPoint, gamma, matrix) {
|
|
22896
|
+
super("CalRGB", 3);
|
|
22897
|
+
if (!whitePoint) {
|
|
22898
|
+
throw new FormatError(
|
|
22899
|
+
"WhitePoint missing - required for color space CalRGB"
|
|
22900
|
+
);
|
|
22901
|
+
}
|
|
22902
|
+
const [XW, YW, ZW] = this.whitePoint = whitePoint;
|
|
22903
|
+
const [XB, YB, ZB] = this.blackPoint = blackPoint || new Float32Array(3);
|
|
22904
|
+
[this.GR, this.GG, this.GB] = gamma || new Float32Array([1, 1, 1]);
|
|
22905
|
+
[
|
|
22906
|
+
this.MXA,
|
|
22907
|
+
this.MYA,
|
|
22908
|
+
this.MZA,
|
|
22909
|
+
this.MXB,
|
|
22910
|
+
this.MYB,
|
|
22911
|
+
this.MZB,
|
|
22912
|
+
this.MXC,
|
|
22913
|
+
this.MYC,
|
|
22914
|
+
this.MZC
|
|
22915
|
+
] = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
|
|
22916
|
+
if (XW < 0 || ZW < 0 || YW !== 1) {
|
|
22917
|
+
throw new FormatError(
|
|
22918
|
+
`Invalid WhitePoint components for ${this.name}, no fallback available`
|
|
22919
|
+
);
|
|
22920
|
+
}
|
|
22921
|
+
if (XB < 0 || YB < 0 || ZB < 0) {
|
|
22922
|
+
info(
|
|
22923
|
+
`Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], falling back to default.`
|
|
22924
|
+
);
|
|
22925
|
+
this.blackPoint = new Float32Array(3);
|
|
22926
|
+
}
|
|
22927
|
+
if (this.GR < 0 || this.GG < 0 || this.GB < 0) {
|
|
22928
|
+
info(
|
|
22929
|
+
`Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ${this.name}, falling back to default.`
|
|
22930
|
+
);
|
|
22931
|
+
this.GR = this.GG = this.GB = 1;
|
|
22932
|
+
}
|
|
22933
|
+
}
|
|
22934
|
+
#matrixProduct(a, b, result) {
|
|
22935
|
+
result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
22936
|
+
result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
|
|
22937
|
+
result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
|
|
22938
|
+
}
|
|
22939
|
+
#toFlat(sourceWhitePoint, LMS, result) {
|
|
22940
|
+
result[0] = LMS[0] * 1 / sourceWhitePoint[0];
|
|
22941
|
+
result[1] = LMS[1] * 1 / sourceWhitePoint[1];
|
|
22942
|
+
result[2] = LMS[2] * 1 / sourceWhitePoint[2];
|
|
22943
|
+
}
|
|
22944
|
+
#toD65(sourceWhitePoint, LMS, result) {
|
|
22945
|
+
const D65X = 0.95047;
|
|
22946
|
+
const D65Y = 1;
|
|
22947
|
+
const D65Z = 1.08883;
|
|
22948
|
+
result[0] = LMS[0] * D65X / sourceWhitePoint[0];
|
|
22949
|
+
result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
|
|
22950
|
+
result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
|
|
22951
|
+
}
|
|
22952
|
+
#sRGBTransferFunction(color) {
|
|
22953
|
+
if (color <= 31308e-7) {
|
|
22954
|
+
return MathClamp(12.92 * color, 0, 1);
|
|
22955
|
+
}
|
|
22956
|
+
return color >= 0.99554525 ? 1 : MathClamp((1 + 0.055) * color ** (1 / 2.4) - 0.055, 0, 1);
|
|
22957
|
+
}
|
|
22958
|
+
#decodeL(L) {
|
|
22959
|
+
if (L < 0) {
|
|
22960
|
+
return -this.#decodeL(-L);
|
|
22961
|
+
}
|
|
22962
|
+
return L > 8 ? ((L + 16) / 116) ** 3 : L * _CalRGBCS.#DECODE_L_CONSTANT;
|
|
22963
|
+
}
|
|
22964
|
+
#compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
|
|
22965
|
+
if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {
|
|
22966
|
+
result[0] = XYZ_Flat[0];
|
|
22967
|
+
result[1] = XYZ_Flat[1];
|
|
22968
|
+
result[2] = XYZ_Flat[2];
|
|
22969
|
+
return;
|
|
22970
|
+
}
|
|
22971
|
+
const zeroDecodeL = this.#decodeL(0);
|
|
22972
|
+
const X_DST = zeroDecodeL;
|
|
22973
|
+
const X_SRC = this.#decodeL(sourceBlackPoint[0]);
|
|
22974
|
+
const Y_DST = zeroDecodeL;
|
|
22975
|
+
const Y_SRC = this.#decodeL(sourceBlackPoint[1]);
|
|
22976
|
+
const Z_DST = zeroDecodeL;
|
|
22977
|
+
const Z_SRC = this.#decodeL(sourceBlackPoint[2]);
|
|
22978
|
+
const X_Scale = (1 - X_DST) / (1 - X_SRC);
|
|
22979
|
+
const X_Offset = 1 - X_Scale;
|
|
22980
|
+
const Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
|
|
22981
|
+
const Y_Offset = 1 - Y_Scale;
|
|
22982
|
+
const Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
|
|
22983
|
+
const Z_Offset = 1 - Z_Scale;
|
|
22984
|
+
result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
|
|
22985
|
+
result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
|
|
22986
|
+
result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
|
|
22987
|
+
}
|
|
22988
|
+
#normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
|
|
22989
|
+
if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
|
|
22990
|
+
result[0] = XYZ_In[0];
|
|
22991
|
+
result[1] = XYZ_In[1];
|
|
22992
|
+
result[2] = XYZ_In[2];
|
|
22993
|
+
return;
|
|
22994
|
+
}
|
|
22995
|
+
const LMS = result;
|
|
22996
|
+
this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
|
|
22997
|
+
const LMS_Flat = _CalRGBCS.#tempNormalizeMatrix;
|
|
22998
|
+
this.#toFlat(sourceWhitePoint, LMS, LMS_Flat);
|
|
22999
|
+
this.#matrixProduct(
|
|
23000
|
+
_CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
|
|
23001
|
+
LMS_Flat,
|
|
23002
|
+
result
|
|
23003
|
+
);
|
|
23004
|
+
}
|
|
23005
|
+
#normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
|
|
23006
|
+
const LMS = result;
|
|
23007
|
+
this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
|
|
23008
|
+
const LMS_D65 = _CalRGBCS.#tempNormalizeMatrix;
|
|
23009
|
+
this.#toD65(sourceWhitePoint, LMS, LMS_D65);
|
|
23010
|
+
this.#matrixProduct(
|
|
23011
|
+
_CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
|
|
23012
|
+
LMS_D65,
|
|
23013
|
+
result
|
|
23014
|
+
);
|
|
23015
|
+
}
|
|
23016
|
+
#toRgb(src, srcOffset, dest, destOffset, scale) {
|
|
23017
|
+
const A = MathClamp(src[srcOffset] * scale, 0, 1);
|
|
23018
|
+
const B = MathClamp(src[srcOffset + 1] * scale, 0, 1);
|
|
23019
|
+
const C = MathClamp(src[srcOffset + 2] * scale, 0, 1);
|
|
23020
|
+
const AGR = A === 1 ? 1 : A ** this.GR;
|
|
23021
|
+
const BGG = B === 1 ? 1 : B ** this.GG;
|
|
23022
|
+
const CGB = C === 1 ? 1 : C ** this.GB;
|
|
23023
|
+
const X = this.MXA * AGR + this.MXB * BGG + this.MXC * CGB;
|
|
23024
|
+
const Y = this.MYA * AGR + this.MYB * BGG + this.MYC * CGB;
|
|
23025
|
+
const Z = this.MZA * AGR + this.MZB * BGG + this.MZC * CGB;
|
|
23026
|
+
const XYZ = _CalRGBCS.#tempConvertMatrix1;
|
|
23027
|
+
XYZ[0] = X;
|
|
23028
|
+
XYZ[1] = Y;
|
|
23029
|
+
XYZ[2] = Z;
|
|
23030
|
+
const XYZ_Flat = _CalRGBCS.#tempConvertMatrix2;
|
|
23031
|
+
this.#normalizeWhitePointToFlat(this.whitePoint, XYZ, XYZ_Flat);
|
|
23032
|
+
const XYZ_Black = _CalRGBCS.#tempConvertMatrix1;
|
|
23033
|
+
this.#compensateBlackPoint(this.blackPoint, XYZ_Flat, XYZ_Black);
|
|
23034
|
+
const XYZ_D65 = _CalRGBCS.#tempConvertMatrix2;
|
|
23035
|
+
this.#normalizeWhitePointToD65(
|
|
23036
|
+
_CalRGBCS.#FLAT_WHITEPOINT_MATRIX,
|
|
23037
|
+
XYZ_Black,
|
|
23038
|
+
XYZ_D65
|
|
23039
|
+
);
|
|
23040
|
+
const SRGB = _CalRGBCS.#tempConvertMatrix1;
|
|
23041
|
+
this.#matrixProduct(_CalRGBCS.#SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
|
|
23042
|
+
dest[destOffset] = this.#sRGBTransferFunction(SRGB[0]) * 255;
|
|
23043
|
+
dest[destOffset + 1] = this.#sRGBTransferFunction(SRGB[1]) * 255;
|
|
23044
|
+
dest[destOffset + 2] = this.#sRGBTransferFunction(SRGB[2]) * 255;
|
|
23045
|
+
}
|
|
23046
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
23047
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
23048
|
+
assert2(
|
|
23049
|
+
dest instanceof Uint8ClampedArray,
|
|
23050
|
+
'CalRGBCS.getRgbItem: Unsupported "dest" type.'
|
|
23051
|
+
);
|
|
23052
|
+
}
|
|
23053
|
+
this.#toRgb(src, srcOffset, dest, destOffset, 1);
|
|
23054
|
+
}
|
|
23055
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
23056
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
23057
|
+
assert2(
|
|
23058
|
+
dest instanceof Uint8ClampedArray,
|
|
23059
|
+
'CalRGBCS.getRgbBuffer: Unsupported "dest" type.'
|
|
23060
|
+
);
|
|
23061
|
+
}
|
|
23062
|
+
const scale = 1 / ((1 << bits) - 1);
|
|
23063
|
+
for (let i = 0; i < count; ++i) {
|
|
23064
|
+
this.#toRgb(src, srcOffset, dest, destOffset, scale);
|
|
23065
|
+
srcOffset += 3;
|
|
23066
|
+
destOffset += 3 + alpha01;
|
|
23067
|
+
}
|
|
23068
|
+
}
|
|
23069
|
+
};
|
|
23070
|
+
var LabCS = class extends ColorSpace {
|
|
23071
|
+
constructor(whitePoint, blackPoint, range) {
|
|
23072
|
+
super("Lab", 3);
|
|
23073
|
+
if (!whitePoint) {
|
|
23074
|
+
throw new FormatError(
|
|
23075
|
+
"WhitePoint missing - required for color space Lab"
|
|
23076
|
+
);
|
|
23077
|
+
}
|
|
23078
|
+
[this.XW, this.YW, this.ZW] = whitePoint;
|
|
23079
|
+
[this.amin, this.amax, this.bmin, this.bmax] = range || [
|
|
23080
|
+
-100,
|
|
23081
|
+
100,
|
|
23082
|
+
-100,
|
|
23083
|
+
100
|
|
23084
|
+
];
|
|
23085
|
+
[this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
|
|
23086
|
+
if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
|
|
23087
|
+
throw new FormatError(
|
|
23088
|
+
"Invalid WhitePoint components, no fallback available"
|
|
23089
|
+
);
|
|
23090
|
+
}
|
|
23091
|
+
if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
|
|
23092
|
+
info("Invalid BlackPoint, falling back to default");
|
|
23093
|
+
this.XB = this.YB = this.ZB = 0;
|
|
23094
|
+
}
|
|
23095
|
+
if (this.amin > this.amax || this.bmin > this.bmax) {
|
|
23096
|
+
info("Invalid Range, falling back to defaults");
|
|
23097
|
+
this.amin = -100;
|
|
23098
|
+
this.amax = 100;
|
|
23099
|
+
this.bmin = -100;
|
|
23100
|
+
this.bmax = 100;
|
|
23101
|
+
}
|
|
23102
|
+
}
|
|
23103
|
+
// Function g(x) from spec
|
|
23104
|
+
#fn_g(x) {
|
|
23105
|
+
return x >= 6 / 29 ? x ** 3 : 108 / 841 * (x - 4 / 29);
|
|
23106
|
+
}
|
|
23107
|
+
#decode(value, high1, low2, high2) {
|
|
23108
|
+
return low2 + value * (high2 - low2) / high1;
|
|
23109
|
+
}
|
|
23110
|
+
// If decoding is needed maxVal should be 2^bits per component - 1.
|
|
23111
|
+
#toRgb(src, srcOffset, maxVal, dest, destOffset) {
|
|
23112
|
+
let Ls = src[srcOffset];
|
|
23113
|
+
let as = src[srcOffset + 1];
|
|
23114
|
+
let bs = src[srcOffset + 2];
|
|
23115
|
+
if (maxVal !== false) {
|
|
23116
|
+
Ls = this.#decode(Ls, maxVal, 0, 100);
|
|
23117
|
+
as = this.#decode(as, maxVal, this.amin, this.amax);
|
|
23118
|
+
bs = this.#decode(bs, maxVal, this.bmin, this.bmax);
|
|
23119
|
+
}
|
|
23120
|
+
if (as > this.amax) {
|
|
23121
|
+
as = this.amax;
|
|
23122
|
+
} else if (as < this.amin) {
|
|
23123
|
+
as = this.amin;
|
|
23124
|
+
}
|
|
23125
|
+
if (bs > this.bmax) {
|
|
23126
|
+
bs = this.bmax;
|
|
23127
|
+
} else if (bs < this.bmin) {
|
|
23128
|
+
bs = this.bmin;
|
|
23129
|
+
}
|
|
23130
|
+
const M = (Ls + 16) / 116;
|
|
23131
|
+
const L = M + as / 500;
|
|
23132
|
+
const N = M - bs / 200;
|
|
23133
|
+
const X = this.XW * this.#fn_g(L);
|
|
23134
|
+
const Y = this.YW * this.#fn_g(M);
|
|
23135
|
+
const Z = this.ZW * this.#fn_g(N);
|
|
23136
|
+
let r, g, b;
|
|
23137
|
+
if (this.ZW < 1) {
|
|
23138
|
+
r = X * 3.1339 + Y * -1.617 + Z * -0.4906;
|
|
23139
|
+
g = X * -0.9785 + Y * 1.916 + Z * 0.0333;
|
|
23140
|
+
b = X * 0.072 + Y * -0.229 + Z * 1.4057;
|
|
23141
|
+
} else {
|
|
23142
|
+
r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
|
|
23143
|
+
g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
|
|
23144
|
+
b = X * 0.0557 + Y * -0.204 + Z * 1.057;
|
|
23145
|
+
}
|
|
23146
|
+
dest[destOffset] = Math.sqrt(r) * 255;
|
|
23147
|
+
dest[destOffset + 1] = Math.sqrt(g) * 255;
|
|
23148
|
+
dest[destOffset + 2] = Math.sqrt(b) * 255;
|
|
23149
|
+
}
|
|
23150
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
23151
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
23152
|
+
assert2(
|
|
23153
|
+
dest instanceof Uint8ClampedArray,
|
|
23154
|
+
'LabCS.getRgbItem: Unsupported "dest" type.'
|
|
23155
|
+
);
|
|
23156
|
+
}
|
|
23157
|
+
this.#toRgb(src, srcOffset, false, dest, destOffset);
|
|
23158
|
+
}
|
|
23159
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
23160
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
23161
|
+
assert2(
|
|
23162
|
+
dest instanceof Uint8ClampedArray,
|
|
23163
|
+
'LabCS.getRgbBuffer: Unsupported "dest" type.'
|
|
23164
|
+
);
|
|
23165
|
+
}
|
|
23166
|
+
const maxVal = (1 << bits) - 1;
|
|
23167
|
+
for (let i = 0; i < count; i++) {
|
|
23168
|
+
this.#toRgb(src, srcOffset, maxVal, dest, destOffset);
|
|
23169
|
+
srcOffset += 3;
|
|
23170
|
+
destOffset += 3 + alpha01;
|
|
23171
|
+
}
|
|
23172
|
+
}
|
|
23173
|
+
isDefaultDecode(decode, bpc) {
|
|
23174
|
+
return true;
|
|
23175
|
+
}
|
|
23176
|
+
get usesZeroToOneRange() {
|
|
23177
|
+
return shadow2(this, "usesZeroToOneRange", false);
|
|
23178
|
+
}
|
|
23179
|
+
};
|
|
23180
|
+
var TOKEN = {
|
|
23181
|
+
// Structural tokens — not keyword operators
|
|
23182
|
+
number: 0,
|
|
23183
|
+
lbrace: 1,
|
|
23184
|
+
rbrace: 2,
|
|
23185
|
+
// Boolean literals
|
|
23186
|
+
true: 3,
|
|
23187
|
+
false: 4,
|
|
23188
|
+
// Arithmetic binary operators
|
|
23189
|
+
add: 5,
|
|
23190
|
+
sub: 6,
|
|
23191
|
+
mul: 7,
|
|
23192
|
+
div: 8,
|
|
23193
|
+
idiv: 9,
|
|
23194
|
+
mod: 10,
|
|
23195
|
+
exp: 11,
|
|
23196
|
+
// Comparison binary operators
|
|
23197
|
+
eq: 12,
|
|
23198
|
+
ne: 13,
|
|
23199
|
+
gt: 14,
|
|
23200
|
+
ge: 15,
|
|
23201
|
+
lt: 16,
|
|
23202
|
+
le: 17,
|
|
23203
|
+
// Bitwise / boolean binary operators
|
|
23204
|
+
and: 18,
|
|
23205
|
+
or: 19,
|
|
23206
|
+
xor: 20,
|
|
23207
|
+
bitshift: 21,
|
|
23208
|
+
// Unary arithmetic operators
|
|
23209
|
+
abs: 22,
|
|
23210
|
+
neg: 23,
|
|
23211
|
+
ceiling: 24,
|
|
23212
|
+
floor: 25,
|
|
23213
|
+
round: 26,
|
|
23214
|
+
truncate: 27,
|
|
23215
|
+
// Unary boolean / bitwise operator
|
|
23216
|
+
not: 28,
|
|
23217
|
+
// Mathematical functions — unary
|
|
23218
|
+
sqrt: 29,
|
|
23219
|
+
sin: 30,
|
|
23220
|
+
cos: 31,
|
|
23221
|
+
ln: 32,
|
|
23222
|
+
log: 33,
|
|
23223
|
+
// Mathematical function — binary
|
|
23224
|
+
atan: 34,
|
|
23225
|
+
// Type conversion operators
|
|
23226
|
+
cvi: 35,
|
|
23227
|
+
cvr: 36,
|
|
23228
|
+
// Stack operators
|
|
23229
|
+
dup: 37,
|
|
23230
|
+
exch: 38,
|
|
23231
|
+
pop: 39,
|
|
23232
|
+
copy: 40,
|
|
23233
|
+
index: 41,
|
|
23234
|
+
roll: 42,
|
|
23235
|
+
// Control flow
|
|
23236
|
+
if: 43,
|
|
23237
|
+
ifelse: 44,
|
|
23238
|
+
// End of input
|
|
23239
|
+
eof: 45,
|
|
23240
|
+
// Synthetic: produced by the optimizer, never emitted by the lexer.
|
|
23241
|
+
min: 46,
|
|
23242
|
+
max: 47
|
|
23243
|
+
};
|
|
23244
|
+
var Token = class {
|
|
23245
|
+
constructor(id, value = null) {
|
|
23246
|
+
this.id = id;
|
|
23247
|
+
this.value = value;
|
|
23248
|
+
}
|
|
23249
|
+
};
|
|
23250
|
+
var Lexer = class _Lexer {
|
|
23251
|
+
// Singletons for every non-number token, built lazily on first construction.
|
|
23252
|
+
// Keyword operator tokens carry their name as `value`; structural tokens
|
|
23253
|
+
// (lbrace, rbrace, eof) carry null.
|
|
23254
|
+
static #singletons = null;
|
|
23255
|
+
static #operatorSingletons = null;
|
|
23256
|
+
static #initSingletons() {
|
|
23257
|
+
const singletons = /* @__PURE__ */ Object.create(null);
|
|
23258
|
+
const operatorSingletons = /* @__PURE__ */ Object.create(null);
|
|
23259
|
+
for (const [name, id] of Object.entries(TOKEN)) {
|
|
23260
|
+
if (name === "number") {
|
|
23261
|
+
continue;
|
|
23262
|
+
}
|
|
23263
|
+
const isOperator = id >= TOKEN.true && id <= TOKEN.ifelse;
|
|
23264
|
+
const token = new Token(id, isOperator ? name : null);
|
|
23265
|
+
singletons[name] = token;
|
|
23266
|
+
if (isOperator) {
|
|
23267
|
+
operatorSingletons[name] = token;
|
|
23268
|
+
}
|
|
23269
|
+
}
|
|
23270
|
+
this.#singletons = singletons;
|
|
23271
|
+
this.#operatorSingletons = operatorSingletons;
|
|
23272
|
+
}
|
|
23273
|
+
constructor(data) {
|
|
23274
|
+
if (!_Lexer.#singletons) {
|
|
23275
|
+
_Lexer.#initSingletons();
|
|
23276
|
+
}
|
|
23277
|
+
this.data = data;
|
|
23278
|
+
this.pos = 0;
|
|
23279
|
+
this.len = data.length;
|
|
23280
|
+
this._numberPattern = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/iy;
|
|
23281
|
+
this._identifierPattern = /[a-z]+/y;
|
|
23282
|
+
}
|
|
23283
|
+
// Skip a % comment, advancing past the next \n or \r (or to EOF).
|
|
23284
|
+
_skipComment() {
|
|
23285
|
+
const lf = this.data.indexOf("\n", this.pos);
|
|
23286
|
+
const cr = this.data.indexOf("\r", this.pos);
|
|
23287
|
+
const eol = Math.min(lf < 0 ? this.len : lf, cr < 0 ? this.len : cr);
|
|
23288
|
+
this.pos = Math.min(eol + 1, this.len);
|
|
23289
|
+
}
|
|
23290
|
+
_getNumber() {
|
|
23291
|
+
this._numberPattern.lastIndex = this.pos;
|
|
23292
|
+
const match = this._numberPattern.exec(this.data);
|
|
23293
|
+
if (!match) {
|
|
23294
|
+
return new Token(TOKEN.number, 0);
|
|
23295
|
+
}
|
|
23296
|
+
const number = parseFloat(match[0]);
|
|
23297
|
+
if (!Number.isFinite(number)) {
|
|
23298
|
+
return new Token(TOKEN.number, 0);
|
|
23299
|
+
}
|
|
23300
|
+
this.pos = this._numberPattern.lastIndex;
|
|
23301
|
+
return new Token(TOKEN.number, number);
|
|
23302
|
+
}
|
|
23303
|
+
_getOperator() {
|
|
23304
|
+
this._identifierPattern.lastIndex = this.pos;
|
|
23305
|
+
const match = this._identifierPattern.exec(this.data);
|
|
23306
|
+
if (!match) {
|
|
23307
|
+
return new Token(TOKEN.number, 0);
|
|
23308
|
+
}
|
|
23309
|
+
this.pos = this._identifierPattern.lastIndex;
|
|
23310
|
+
const op = match[0];
|
|
23311
|
+
const token = _Lexer.#operatorSingletons[op];
|
|
23312
|
+
return token ?? new Token(TOKEN.number, 0);
|
|
23313
|
+
}
|
|
23314
|
+
// Return the next token, or Lexer.#singletons.eof at end of input.
|
|
23315
|
+
next() {
|
|
23316
|
+
while (this.pos < this.len) {
|
|
23317
|
+
const ch3 = this.data.charCodeAt(this.pos++);
|
|
23318
|
+
switch (ch3) {
|
|
23319
|
+
// PostScript white-space characters (PDF32000 §7.2.2)
|
|
23320
|
+
case 0:
|
|
23321
|
+
case 9:
|
|
23322
|
+
case 10:
|
|
23323
|
+
case 12:
|
|
23324
|
+
case 13:
|
|
23325
|
+
case 32:
|
|
23326
|
+
break;
|
|
23327
|
+
case 37:
|
|
23328
|
+
this._skipComment();
|
|
23329
|
+
break;
|
|
23330
|
+
case 123:
|
|
23331
|
+
return _Lexer.#singletons.lbrace;
|
|
23332
|
+
case 125:
|
|
23333
|
+
return _Lexer.#singletons.rbrace;
|
|
23334
|
+
case 43:
|
|
23335
|
+
case 45:
|
|
23336
|
+
this.pos--;
|
|
23337
|
+
return this._getNumber();
|
|
23338
|
+
case 46:
|
|
23339
|
+
this.pos--;
|
|
23340
|
+
return this._getNumber();
|
|
23341
|
+
default:
|
|
23342
|
+
if (ch3 >= 48 && ch3 <= 57) {
|
|
23343
|
+
this.pos--;
|
|
23344
|
+
return this._getNumber();
|
|
23345
|
+
}
|
|
23346
|
+
if (ch3 >= 97 && ch3 <= 122) {
|
|
23347
|
+
this.pos--;
|
|
23348
|
+
return this._getOperator();
|
|
23349
|
+
}
|
|
23350
|
+
return new Token(TOKEN.number, 0);
|
|
23351
|
+
}
|
|
23352
|
+
}
|
|
23353
|
+
return _Lexer.#singletons.eof;
|
|
23354
|
+
}
|
|
23355
|
+
};
|
|
23356
|
+
var PS_VALUE_TYPE = {
|
|
23357
|
+
numeric: 0,
|
|
23358
|
+
// known to be a number (f64 in Wasm)
|
|
23359
|
+
boolean: 1,
|
|
23360
|
+
// known to be a boolean (0.0 = false, 1.0 = true in f64)
|
|
23361
|
+
unknown: 2
|
|
23362
|
+
// indeterminate at compile time
|
|
23363
|
+
};
|
|
23364
|
+
var PS_NODE = {
|
|
23365
|
+
// Parser AST node types (produced by Parser / parsePostScriptFunction)
|
|
23366
|
+
program: 0,
|
|
23367
|
+
block: 1,
|
|
23368
|
+
number: 2,
|
|
23369
|
+
operator: 3,
|
|
23370
|
+
if: 4,
|
|
23371
|
+
ifelse: 5,
|
|
23372
|
+
// Tree AST node types (produced by PSStackToTree)
|
|
23373
|
+
arg: 6,
|
|
23374
|
+
const: 7,
|
|
23375
|
+
unary: 8,
|
|
23376
|
+
binary: 9,
|
|
23377
|
+
ternary: 10
|
|
23378
|
+
};
|
|
23379
|
+
var PsNode = class {
|
|
23380
|
+
constructor(type) {
|
|
23381
|
+
this.type = type;
|
|
23382
|
+
}
|
|
23383
|
+
};
|
|
23384
|
+
var PsProgram = class extends PsNode {
|
|
23385
|
+
constructor(body) {
|
|
23386
|
+
super(PS_NODE.program);
|
|
23387
|
+
this.body = body;
|
|
23388
|
+
}
|
|
23389
|
+
};
|
|
23390
|
+
var PsBlock = class extends PsNode {
|
|
23391
|
+
constructor(instructions) {
|
|
23392
|
+
super(PS_NODE.block);
|
|
23393
|
+
this.instructions = instructions;
|
|
23394
|
+
}
|
|
23395
|
+
};
|
|
23396
|
+
var PsNumber = class extends PsNode {
|
|
23397
|
+
/** @param {number} value */
|
|
23398
|
+
constructor(value) {
|
|
23399
|
+
super(PS_NODE.number);
|
|
23400
|
+
this.value = value;
|
|
23401
|
+
}
|
|
23402
|
+
};
|
|
23403
|
+
var PsOperator = class extends PsNode {
|
|
23404
|
+
/** @param {number} op — one of the TOKEN.* constants from lexer.js */
|
|
23405
|
+
constructor(op) {
|
|
23406
|
+
super(PS_NODE.operator);
|
|
23407
|
+
this.op = op;
|
|
23408
|
+
}
|
|
23409
|
+
};
|
|
23410
|
+
var PsIf = class extends PsNode {
|
|
23411
|
+
/** @param {PsBlock} then */
|
|
23412
|
+
constructor(then) {
|
|
23413
|
+
super(PS_NODE.if);
|
|
23414
|
+
this.then = then;
|
|
23415
|
+
}
|
|
23416
|
+
};
|
|
23417
|
+
var PsIfElse = class extends PsNode {
|
|
23418
|
+
/**
|
|
23419
|
+
* @param {PsBlock} then
|
|
23420
|
+
* @param {PsBlock} otherwise
|
|
23421
|
+
*/
|
|
23422
|
+
constructor(then, otherwise) {
|
|
23423
|
+
super(PS_NODE.ifelse);
|
|
23424
|
+
this.then = then;
|
|
23425
|
+
this.otherwise = otherwise;
|
|
23426
|
+
}
|
|
23427
|
+
};
|
|
23428
|
+
var PsArgNode = class extends PsNode {
|
|
23429
|
+
/** @param {number} index */
|
|
23430
|
+
constructor(index) {
|
|
23431
|
+
super(PS_NODE.arg);
|
|
23432
|
+
this.index = index;
|
|
23433
|
+
this.valueType = PS_VALUE_TYPE.numeric;
|
|
23434
|
+
}
|
|
23435
|
+
};
|
|
23436
|
+
var PsConstNode = class extends PsNode {
|
|
23437
|
+
/** @param {number|boolean} value */
|
|
23438
|
+
constructor(value) {
|
|
23439
|
+
super(PS_NODE.const);
|
|
23440
|
+
this.value = value;
|
|
23441
|
+
this.valueType = typeof value === "boolean" ? PS_VALUE_TYPE.boolean : PS_VALUE_TYPE.numeric;
|
|
23442
|
+
}
|
|
23443
|
+
};
|
|
23444
|
+
var PsUnaryNode = class extends PsNode {
|
|
23445
|
+
/**
|
|
23446
|
+
* @param {number} op — TOKEN.* constant
|
|
23447
|
+
* @param {PsNode} operand
|
|
23448
|
+
* @param {number} [valueType]
|
|
23449
|
+
*/
|
|
23450
|
+
constructor(op, operand, valueType = PS_VALUE_TYPE.unknown) {
|
|
23451
|
+
super(PS_NODE.unary);
|
|
23452
|
+
this.op = op;
|
|
23453
|
+
this.operand = operand;
|
|
23454
|
+
this.valueType = valueType;
|
|
23455
|
+
}
|
|
23456
|
+
};
|
|
23457
|
+
var PsBinaryNode = class extends PsNode {
|
|
23458
|
+
/**
|
|
23459
|
+
* @param {number} op — TOKEN.* constant
|
|
23460
|
+
* @param {PsNode} first — was on top of stack
|
|
23461
|
+
* @param {PsNode} second — was below top
|
|
23462
|
+
* @param {number} [valueType]
|
|
23463
|
+
*/
|
|
23464
|
+
constructor(op, first, second, valueType = PS_VALUE_TYPE.unknown) {
|
|
23465
|
+
super(PS_NODE.binary);
|
|
23466
|
+
this.op = op;
|
|
23467
|
+
this.first = first;
|
|
23468
|
+
this.second = second;
|
|
23469
|
+
this.valueType = valueType;
|
|
23470
|
+
}
|
|
23471
|
+
};
|
|
23472
|
+
var PsTernaryNode = class extends PsNode {
|
|
23473
|
+
/**
|
|
23474
|
+
* @param {PsNode} cond
|
|
23475
|
+
* @param {PsNode} then
|
|
23476
|
+
* @param {PsNode} otherwise
|
|
23477
|
+
* @param {number} [valueType]
|
|
23478
|
+
*/
|
|
23479
|
+
constructor(cond, then, otherwise, valueType = PS_VALUE_TYPE.unknown) {
|
|
23480
|
+
super(PS_NODE.ternary);
|
|
23481
|
+
this.cond = cond;
|
|
23482
|
+
this.then = then;
|
|
23483
|
+
this.otherwise = otherwise;
|
|
23484
|
+
this.valueType = valueType;
|
|
23485
|
+
}
|
|
23486
|
+
};
|
|
23487
|
+
var Parser = class _Parser {
|
|
23488
|
+
constructor(lexer) {
|
|
23489
|
+
this.lexer = lexer;
|
|
23490
|
+
this._token = null;
|
|
23491
|
+
}
|
|
23492
|
+
static _isRegularOperator(id) {
|
|
23493
|
+
return id >= TOKEN.true && id < TOKEN.if;
|
|
23494
|
+
}
|
|
23495
|
+
// Fetch the next token from the lexer.
|
|
23496
|
+
_advance() {
|
|
23497
|
+
this._token = this.lexer.next();
|
|
23498
|
+
}
|
|
23499
|
+
// Assert that the current token has the given id, consume it, and return it.
|
|
23500
|
+
_expect(id) {
|
|
23501
|
+
if (this._token.id !== id) {
|
|
23502
|
+
throw new FormatError(
|
|
23503
|
+
`PostScript function: expected token id ${id}, got ${this._token.id}.`
|
|
23504
|
+
);
|
|
23505
|
+
}
|
|
23506
|
+
const tok = this._token;
|
|
23507
|
+
this._advance();
|
|
23508
|
+
return tok;
|
|
23509
|
+
}
|
|
23510
|
+
/**
|
|
23511
|
+
* Parse the full Type 4 function body.
|
|
23512
|
+
*
|
|
23513
|
+
* Grammar (simplified):
|
|
23514
|
+
* program ::= '{' block '}'
|
|
23515
|
+
* block ::= instruction*
|
|
23516
|
+
* instruction ::= number
|
|
23517
|
+
* | operator (any PS_OPERATOR except if / ifelse)
|
|
23518
|
+
* | '{' block '}' 'if'
|
|
23519
|
+
* | '{' block '}' '{' block '}' 'ifelse'
|
|
23520
|
+
* @returns {PsProgram}
|
|
23521
|
+
*/
|
|
23522
|
+
parse() {
|
|
23523
|
+
this._advance();
|
|
23524
|
+
this._expect(TOKEN.lbrace);
|
|
23525
|
+
const block = this._parseBlock();
|
|
23526
|
+
this._expect(TOKEN.rbrace);
|
|
23527
|
+
if (this._token.id !== TOKEN.eof) {
|
|
23528
|
+
warn2("PostScript function: unexpected content after closing brace.");
|
|
23529
|
+
}
|
|
23530
|
+
return new PsProgram(block);
|
|
23531
|
+
}
|
|
23532
|
+
_parseBlock() {
|
|
23533
|
+
const instructions = [];
|
|
23534
|
+
while (true) {
|
|
23535
|
+
const tok = this._token;
|
|
23536
|
+
switch (tok.id) {
|
|
23537
|
+
case TOKEN.number:
|
|
23538
|
+
instructions.push(new PsNumber(tok.value));
|
|
23539
|
+
this._advance();
|
|
23540
|
+
break;
|
|
23541
|
+
case TOKEN.lbrace: {
|
|
23542
|
+
this._advance();
|
|
23543
|
+
const thenBlock = this._parseBlock();
|
|
23544
|
+
this._expect(TOKEN.rbrace);
|
|
23545
|
+
if (this._token.id === TOKEN.if) {
|
|
23546
|
+
this._advance();
|
|
23547
|
+
instructions.push(new PsIf(thenBlock));
|
|
23548
|
+
} else if (this._token.id === TOKEN.lbrace) {
|
|
23549
|
+
this._advance();
|
|
23550
|
+
const elseBlock = this._parseBlock();
|
|
23551
|
+
this._expect(TOKEN.rbrace);
|
|
23552
|
+
this._expect(TOKEN.ifelse);
|
|
23553
|
+
instructions.push(new PsIfElse(thenBlock, elseBlock));
|
|
23554
|
+
} else {
|
|
23555
|
+
throw new FormatError(
|
|
23556
|
+
"PostScript function: a procedure block must be followed by 'if' or '{\u2026} ifelse'."
|
|
23557
|
+
);
|
|
23558
|
+
}
|
|
23559
|
+
break;
|
|
23560
|
+
}
|
|
23561
|
+
case TOKEN.rbrace:
|
|
23562
|
+
case TOKEN.eof:
|
|
23563
|
+
return new PsBlock(instructions);
|
|
23564
|
+
case TOKEN.if:
|
|
23565
|
+
case TOKEN.ifelse:
|
|
23566
|
+
throw new FormatError(
|
|
23567
|
+
`PostScript function: unexpected '${tok.value}' operator.`
|
|
23568
|
+
);
|
|
23569
|
+
default:
|
|
23570
|
+
if (_Parser._isRegularOperator(tok.id)) {
|
|
23571
|
+
instructions.push(new PsOperator(tok.id));
|
|
23572
|
+
this._advance();
|
|
23573
|
+
break;
|
|
23574
|
+
}
|
|
23575
|
+
throw new FormatError(
|
|
23576
|
+
`PostScript function: unexpected token id ${tok.id}.`
|
|
23577
|
+
);
|
|
23578
|
+
}
|
|
23579
|
+
}
|
|
23580
|
+
}
|
|
23581
|
+
};
|
|
23582
|
+
function parsePostScriptFunction(source) {
|
|
23583
|
+
return new Parser(new Lexer(source)).parse();
|
|
23584
|
+
}
|
|
23585
|
+
function _nodesEqual(a, b) {
|
|
23586
|
+
if (a === b) {
|
|
23587
|
+
return true;
|
|
23588
|
+
}
|
|
23589
|
+
if (a.type !== b.type) {
|
|
23590
|
+
return false;
|
|
23591
|
+
}
|
|
23592
|
+
switch (a.type) {
|
|
23593
|
+
case PS_NODE.arg:
|
|
23594
|
+
return a.index === b.index;
|
|
23595
|
+
case PS_NODE.const:
|
|
23596
|
+
return a.value === b.value;
|
|
23597
|
+
case PS_NODE.unary:
|
|
23598
|
+
return a.op === b.op && _nodesEqual(a.operand, b.operand);
|
|
23599
|
+
case PS_NODE.binary:
|
|
23600
|
+
return a.op === b.op && _nodesEqual(a.first, b.first) && _nodesEqual(a.second, b.second);
|
|
23601
|
+
case PS_NODE.ternary:
|
|
23602
|
+
return _nodesEqual(a.cond, b.cond) && _nodesEqual(a.then, b.then) && _nodesEqual(a.otherwise, b.otherwise);
|
|
23603
|
+
default:
|
|
23604
|
+
return false;
|
|
23605
|
+
}
|
|
23606
|
+
}
|
|
23607
|
+
function _evalBinaryConst(op, a, b) {
|
|
23608
|
+
switch (op) {
|
|
23609
|
+
case TOKEN.add:
|
|
23610
|
+
return a + b;
|
|
23611
|
+
case TOKEN.sub:
|
|
23612
|
+
return a - b;
|
|
23613
|
+
case TOKEN.mul:
|
|
23614
|
+
return a * b;
|
|
23615
|
+
case TOKEN.div:
|
|
23616
|
+
return b !== 0 ? a / b : 0;
|
|
23617
|
+
// div by zero → 0
|
|
23618
|
+
case TOKEN.idiv:
|
|
23619
|
+
return b !== 0 ? Math.trunc(a / b) : 0;
|
|
23620
|
+
// div by zero → 0
|
|
23621
|
+
case TOKEN.mod:
|
|
23622
|
+
return b !== 0 ? a - Math.trunc(a / b) * b : 0;
|
|
23623
|
+
// div by zero → 0
|
|
23624
|
+
case TOKEN.exp: {
|
|
23625
|
+
const r = a ** b;
|
|
23626
|
+
return Number.isFinite(r) ? r : void 0;
|
|
23627
|
+
}
|
|
23628
|
+
case TOKEN.atan: {
|
|
23629
|
+
let deg = Math.atan2(a, b) * (180 / Math.PI);
|
|
23630
|
+
if (deg < 0) {
|
|
23631
|
+
deg += 360;
|
|
23632
|
+
}
|
|
23633
|
+
return deg;
|
|
23634
|
+
}
|
|
23635
|
+
case TOKEN.eq:
|
|
23636
|
+
return a === b;
|
|
23637
|
+
case TOKEN.ne:
|
|
23638
|
+
return a !== b;
|
|
23639
|
+
case TOKEN.gt:
|
|
23640
|
+
return a > b;
|
|
23641
|
+
case TOKEN.ge:
|
|
23642
|
+
return a >= b;
|
|
23643
|
+
case TOKEN.lt:
|
|
23644
|
+
return a < b;
|
|
23645
|
+
case TOKEN.le:
|
|
23646
|
+
return a <= b;
|
|
23647
|
+
case TOKEN.and:
|
|
23648
|
+
return typeof a === "boolean" ? a && b : a & b | 0;
|
|
23649
|
+
case TOKEN.or:
|
|
23650
|
+
return typeof a === "boolean" ? a || b : a | b | 0;
|
|
23651
|
+
case TOKEN.xor:
|
|
23652
|
+
return typeof a === "boolean" ? a !== b : a ^ b | 0;
|
|
23653
|
+
case TOKEN.bitshift:
|
|
23654
|
+
return b >= 0 ? a << b | 0 : a >> -b | 0;
|
|
23655
|
+
case TOKEN.min:
|
|
23656
|
+
return Math.min(a, b);
|
|
23657
|
+
case TOKEN.max:
|
|
23658
|
+
return Math.max(a, b);
|
|
23659
|
+
default:
|
|
23660
|
+
return void 0;
|
|
23661
|
+
}
|
|
23662
|
+
}
|
|
23663
|
+
function _evalUnaryConst(op, v) {
|
|
23664
|
+
switch (op) {
|
|
23665
|
+
case TOKEN.abs:
|
|
23666
|
+
return Math.abs(v);
|
|
23667
|
+
case TOKEN.neg:
|
|
23668
|
+
return -v;
|
|
23669
|
+
case TOKEN.ceiling:
|
|
23670
|
+
return Math.ceil(v);
|
|
23671
|
+
case TOKEN.floor:
|
|
23672
|
+
return Math.floor(v);
|
|
23673
|
+
case TOKEN.round:
|
|
23674
|
+
return Math.round(v);
|
|
23675
|
+
case TOKEN.truncate:
|
|
23676
|
+
return Math.trunc(v);
|
|
23677
|
+
case TOKEN.sqrt: {
|
|
23678
|
+
const r = Math.sqrt(v);
|
|
23679
|
+
return Number.isFinite(r) ? r : void 0;
|
|
23680
|
+
}
|
|
23681
|
+
case TOKEN.sin:
|
|
23682
|
+
return Math.sin(v % 360 * Math.PI / 180);
|
|
23683
|
+
case TOKEN.cos:
|
|
23684
|
+
return Math.cos(v % 360 * Math.PI / 180);
|
|
23685
|
+
case TOKEN.ln: {
|
|
23686
|
+
const r = Math.log(v);
|
|
23687
|
+
return Number.isFinite(r) ? r : void 0;
|
|
23688
|
+
}
|
|
23689
|
+
case TOKEN.log: {
|
|
23690
|
+
const r = Math.log10(v);
|
|
23691
|
+
return Number.isFinite(r) ? r : void 0;
|
|
23692
|
+
}
|
|
23693
|
+
case TOKEN.cvi:
|
|
23694
|
+
return Math.trunc(v);
|
|
23695
|
+
case TOKEN.cvr:
|
|
23696
|
+
return v;
|
|
23697
|
+
case TOKEN.not:
|
|
23698
|
+
return typeof v === "boolean" ? !v : ~v;
|
|
23699
|
+
default:
|
|
23700
|
+
return void 0;
|
|
23701
|
+
}
|
|
23702
|
+
}
|
|
23703
|
+
var MAX_STACK_SIZE = 100;
|
|
23704
|
+
function _unaryValueType(op, operandType) {
|
|
23705
|
+
return op === TOKEN.not ? operandType : PS_VALUE_TYPE.numeric;
|
|
23706
|
+
}
|
|
23707
|
+
function _binaryValueType(op, firstType, secondType) {
|
|
23708
|
+
switch (op) {
|
|
23709
|
+
// Comparison operators always produce a boolean.
|
|
23710
|
+
case TOKEN.eq:
|
|
23711
|
+
case TOKEN.ne:
|
|
23712
|
+
case TOKEN.gt:
|
|
23713
|
+
case TOKEN.ge:
|
|
23714
|
+
case TOKEN.lt:
|
|
23715
|
+
case TOKEN.le:
|
|
23716
|
+
return PS_VALUE_TYPE.boolean;
|
|
23717
|
+
// and / or / xor preserve the type when both operands are the same known
|
|
23718
|
+
// type (both boolean or both numeric); otherwise the type is unknown.
|
|
23719
|
+
case TOKEN.and:
|
|
23720
|
+
case TOKEN.or:
|
|
23721
|
+
case TOKEN.xor:
|
|
23722
|
+
return firstType === secondType && firstType !== PS_VALUE_TYPE.unknown ? firstType : PS_VALUE_TYPE.unknown;
|
|
23723
|
+
// All arithmetic / bitshift operators produce a numeric result.
|
|
23724
|
+
default:
|
|
23725
|
+
return PS_VALUE_TYPE.numeric;
|
|
23726
|
+
}
|
|
23727
|
+
}
|
|
23728
|
+
var PSStackToTree = class _PSStackToTree {
|
|
23729
|
+
static #binaryOps = null;
|
|
23730
|
+
static #unaryOps = null;
|
|
23731
|
+
static #idempotentUnary = null;
|
|
23732
|
+
static #negatedComparison = null;
|
|
23733
|
+
static #init() {
|
|
23734
|
+
this.#binaryOps = /* @__PURE__ */ new Set([
|
|
23735
|
+
TOKEN.add,
|
|
23736
|
+
TOKEN.sub,
|
|
23737
|
+
TOKEN.mul,
|
|
23738
|
+
TOKEN.div,
|
|
23739
|
+
TOKEN.idiv,
|
|
23740
|
+
TOKEN.mod,
|
|
23741
|
+
TOKEN.exp,
|
|
23742
|
+
TOKEN.atan,
|
|
23743
|
+
TOKEN.eq,
|
|
23744
|
+
TOKEN.ne,
|
|
23745
|
+
TOKEN.gt,
|
|
23746
|
+
TOKEN.ge,
|
|
23747
|
+
TOKEN.lt,
|
|
23748
|
+
TOKEN.le,
|
|
23749
|
+
TOKEN.and,
|
|
23750
|
+
TOKEN.or,
|
|
23751
|
+
TOKEN.xor,
|
|
23752
|
+
TOKEN.bitshift
|
|
23753
|
+
]);
|
|
23754
|
+
this.#unaryOps = /* @__PURE__ */ new Set([
|
|
23755
|
+
TOKEN.abs,
|
|
23756
|
+
TOKEN.neg,
|
|
23757
|
+
TOKEN.ceiling,
|
|
23758
|
+
TOKEN.floor,
|
|
23759
|
+
TOKEN.round,
|
|
23760
|
+
TOKEN.truncate,
|
|
23761
|
+
TOKEN.sqrt,
|
|
23762
|
+
TOKEN.sin,
|
|
23763
|
+
TOKEN.cos,
|
|
23764
|
+
TOKEN.ln,
|
|
23765
|
+
TOKEN.log,
|
|
23766
|
+
TOKEN.cvi,
|
|
23767
|
+
TOKEN.cvr,
|
|
23768
|
+
TOKEN.not
|
|
23769
|
+
]);
|
|
23770
|
+
this.#idempotentUnary = /* @__PURE__ */ new Set([
|
|
23771
|
+
TOKEN.abs,
|
|
23772
|
+
TOKEN.ceiling,
|
|
23773
|
+
TOKEN.cvi,
|
|
23774
|
+
TOKEN.cvr,
|
|
23775
|
+
TOKEN.floor,
|
|
23776
|
+
TOKEN.round,
|
|
23777
|
+
TOKEN.truncate
|
|
23778
|
+
]);
|
|
23779
|
+
this.#negatedComparison = /* @__PURE__ */ new Map([
|
|
23780
|
+
[TOKEN.eq, TOKEN.ne],
|
|
23781
|
+
[TOKEN.ne, TOKEN.eq],
|
|
23782
|
+
[TOKEN.lt, TOKEN.ge],
|
|
23783
|
+
[TOKEN.le, TOKEN.gt],
|
|
23784
|
+
[TOKEN.gt, TOKEN.le],
|
|
23785
|
+
[TOKEN.ge, TOKEN.lt]
|
|
23786
|
+
]);
|
|
23787
|
+
}
|
|
23788
|
+
/**
|
|
23789
|
+
* @param {PsProgram} program
|
|
23790
|
+
* @param {number} numInputs — number of domain values placed on the stack
|
|
23791
|
+
* before the program runs (i.e. the length of the domain array / 2).
|
|
23792
|
+
* @returns {Array<PsNode>} — one tree node per output value.
|
|
23793
|
+
*/
|
|
23794
|
+
evaluate(program, numInputs) {
|
|
23795
|
+
if (!_PSStackToTree.#binaryOps) {
|
|
23796
|
+
_PSStackToTree.#init();
|
|
23797
|
+
}
|
|
23798
|
+
this._failed = false;
|
|
23799
|
+
if (numInputs > MAX_STACK_SIZE) {
|
|
23800
|
+
return null;
|
|
23801
|
+
}
|
|
23802
|
+
const stack = [];
|
|
23803
|
+
for (let i = 0; i < numInputs; i++) {
|
|
23804
|
+
stack.push(new PsArgNode(i));
|
|
23805
|
+
}
|
|
23806
|
+
this._evalBlock(program.body, stack);
|
|
23807
|
+
if (this._failed) {
|
|
23808
|
+
return null;
|
|
23809
|
+
}
|
|
23810
|
+
_PSStackToTree.#markShared(stack);
|
|
23811
|
+
return stack;
|
|
23812
|
+
}
|
|
23813
|
+
// Set node.shared / sharedCount on non-atomic nodes referenced more than
|
|
23814
|
+
// once. arg/const are excluded — they are cheap to re-emit inline.
|
|
23815
|
+
static #markShared(outputs) {
|
|
23816
|
+
const refCount = /* @__PURE__ */ new Map();
|
|
23817
|
+
const visit = (node) => {
|
|
23818
|
+
if (!node || node.type === PS_NODE.arg || node.type === PS_NODE.const) {
|
|
23819
|
+
return;
|
|
23820
|
+
}
|
|
23821
|
+
const prev = refCount.get(node) ?? 0;
|
|
23822
|
+
refCount.set(node, prev + 1);
|
|
23823
|
+
if (prev > 0) {
|
|
23824
|
+
return;
|
|
23825
|
+
}
|
|
23826
|
+
switch (node.type) {
|
|
23827
|
+
case PS_NODE.unary:
|
|
23828
|
+
visit(node.operand);
|
|
23829
|
+
break;
|
|
23830
|
+
case PS_NODE.binary:
|
|
23831
|
+
visit(node.first);
|
|
23832
|
+
visit(node.second);
|
|
23833
|
+
break;
|
|
23834
|
+
case PS_NODE.ternary:
|
|
23835
|
+
visit(node.cond);
|
|
23836
|
+
visit(node.then);
|
|
23837
|
+
visit(node.otherwise);
|
|
23838
|
+
break;
|
|
23839
|
+
}
|
|
23840
|
+
};
|
|
23841
|
+
for (const output of outputs) {
|
|
23842
|
+
visit(output);
|
|
23843
|
+
}
|
|
23844
|
+
for (const [node, count] of refCount) {
|
|
23845
|
+
if (count > 1) {
|
|
23846
|
+
node.shared = true;
|
|
23847
|
+
node.sharedCount = count;
|
|
23848
|
+
}
|
|
23849
|
+
}
|
|
23850
|
+
}
|
|
23851
|
+
_evalBlock(block, stack) {
|
|
23852
|
+
this._evalBlockFrom(block.instructions, 0, stack);
|
|
23853
|
+
}
|
|
23854
|
+
/**
|
|
23855
|
+
* Core evaluation loop. Processes `instructions[startIdx…]` in order,
|
|
23856
|
+
* mutating `stack` as each instruction executes.
|
|
23857
|
+
*
|
|
23858
|
+
* When a `{ body } if` instruction grows the stack (the PostScript "early
|
|
23859
|
+
* exit / guard" idiom), the remaining instructions in the current array are
|
|
23860
|
+
* evaluated on **both** the true-branch stack and the false-branch stack,
|
|
23861
|
+
* then the two results are merged into PsTernaryNodes. This handles
|
|
23862
|
+
* patterns like:
|
|
23863
|
+
*
|
|
23864
|
+
* cond { pop R G B sentinel } if
|
|
23865
|
+
* … more guards …
|
|
23866
|
+
* sentinel 0 gt { defaultR defaultG defaultB } if
|
|
23867
|
+
*/
|
|
23868
|
+
_evalBlockFrom(instructions, startIdx, stack) {
|
|
23869
|
+
for (let idx = startIdx; idx < instructions.length; idx++) {
|
|
23870
|
+
if (this._failed) {
|
|
23871
|
+
break;
|
|
23872
|
+
}
|
|
23873
|
+
const instr = instructions[idx];
|
|
23874
|
+
switch (instr.type) {
|
|
23875
|
+
case PS_NODE.number:
|
|
23876
|
+
stack.push(new PsConstNode(instr.value));
|
|
23877
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
23878
|
+
this._failed = true;
|
|
23879
|
+
}
|
|
23880
|
+
break;
|
|
23881
|
+
case PS_NODE.operator:
|
|
23882
|
+
this._evalOp(instr.op, stack);
|
|
23883
|
+
break;
|
|
23884
|
+
case PS_NODE.if: {
|
|
23885
|
+
if (stack.length < 1) {
|
|
23886
|
+
this._failed = true;
|
|
23887
|
+
break;
|
|
23888
|
+
}
|
|
23889
|
+
const cond = stack.pop();
|
|
23890
|
+
const saved = stack.slice();
|
|
23891
|
+
this._evalBlock(instr.then, stack);
|
|
23892
|
+
if (this._failed) {
|
|
23893
|
+
break;
|
|
23894
|
+
}
|
|
23895
|
+
if (stack.length === saved.length) {
|
|
23896
|
+
for (let i = 0; i < stack.length; i++) {
|
|
23897
|
+
if (stack[i] !== saved[i]) {
|
|
23898
|
+
stack[i] = this._makeTernary(cond, stack[i], saved[i]);
|
|
23899
|
+
}
|
|
23900
|
+
}
|
|
23901
|
+
} else if (stack.length > saved.length) {
|
|
23902
|
+
if (cond.type === PS_NODE.const) {
|
|
23903
|
+
if (!cond.value) {
|
|
23904
|
+
stack.length = 0;
|
|
23905
|
+
stack.push(...saved);
|
|
23906
|
+
}
|
|
23907
|
+
break;
|
|
23908
|
+
}
|
|
23909
|
+
const trueStack = stack.slice();
|
|
23910
|
+
this._evalBlockFrom(instructions, idx + 1, trueStack);
|
|
23911
|
+
if (this._failed) {
|
|
23912
|
+
break;
|
|
23913
|
+
}
|
|
23914
|
+
const falseStack = saved;
|
|
23915
|
+
this._evalBlockFrom(instructions, idx + 1, falseStack);
|
|
23916
|
+
if (this._failed) {
|
|
23917
|
+
break;
|
|
23918
|
+
}
|
|
23919
|
+
if (trueStack.length !== falseStack.length) {
|
|
23920
|
+
const zero2 = new PsConstNode(0);
|
|
23921
|
+
while (trueStack.length < falseStack.length) {
|
|
23922
|
+
trueStack.push(zero2);
|
|
23923
|
+
}
|
|
23924
|
+
while (falseStack.length < trueStack.length) {
|
|
23925
|
+
falseStack.push(zero2);
|
|
23926
|
+
}
|
|
23927
|
+
}
|
|
23928
|
+
stack.length = 0;
|
|
23929
|
+
for (let i = 0; i < trueStack.length; i++) {
|
|
23930
|
+
stack.push(this._makeTernary(cond, trueStack[i], falseStack[i]));
|
|
23931
|
+
}
|
|
23932
|
+
return;
|
|
23933
|
+
} else {
|
|
23934
|
+
this._failed = true;
|
|
23935
|
+
}
|
|
23936
|
+
break;
|
|
23937
|
+
}
|
|
23938
|
+
case PS_NODE.ifelse: {
|
|
23939
|
+
if (stack.length < 1) {
|
|
23940
|
+
this._failed = true;
|
|
23941
|
+
break;
|
|
23942
|
+
}
|
|
23943
|
+
const cond = stack.pop();
|
|
23944
|
+
const snapshot = stack.slice();
|
|
23945
|
+
const thenStack = snapshot.slice();
|
|
23946
|
+
this._evalBlock(instr.then, thenStack);
|
|
23947
|
+
if (this._failed) {
|
|
23948
|
+
break;
|
|
23949
|
+
}
|
|
23950
|
+
const elseStack = snapshot.slice();
|
|
23951
|
+
this._evalBlock(instr.otherwise, elseStack);
|
|
23952
|
+
if (this._failed) {
|
|
23953
|
+
break;
|
|
23954
|
+
}
|
|
23955
|
+
if (thenStack.length !== elseStack.length) {
|
|
23956
|
+
const zero2 = new PsConstNode(0);
|
|
23957
|
+
while (thenStack.length < elseStack.length) {
|
|
23958
|
+
thenStack.push(zero2);
|
|
23959
|
+
}
|
|
23960
|
+
while (elseStack.length < thenStack.length) {
|
|
23961
|
+
elseStack.push(zero2);
|
|
23962
|
+
}
|
|
23963
|
+
}
|
|
23964
|
+
stack.length = 0;
|
|
23965
|
+
for (let i = 0; i < thenStack.length; i++) {
|
|
23966
|
+
stack.push(this._makeTernary(cond, thenStack[i], elseStack[i]));
|
|
23967
|
+
}
|
|
23968
|
+
break;
|
|
23969
|
+
}
|
|
23970
|
+
}
|
|
23971
|
+
}
|
|
23972
|
+
}
|
|
23973
|
+
_evalOp(op, stack) {
|
|
23974
|
+
if (_PSStackToTree.#binaryOps.has(op)) {
|
|
23975
|
+
if (stack.length < 2) {
|
|
23976
|
+
this._failed = true;
|
|
23977
|
+
return;
|
|
23978
|
+
}
|
|
23979
|
+
const first = stack.pop();
|
|
23980
|
+
const second = stack.pop();
|
|
23981
|
+
stack.push(this._makeBinary(op, first, second));
|
|
23982
|
+
return;
|
|
23983
|
+
}
|
|
23984
|
+
if (_PSStackToTree.#unaryOps.has(op)) {
|
|
23985
|
+
if (stack.length < 1) {
|
|
23986
|
+
this._failed = true;
|
|
23987
|
+
return;
|
|
23988
|
+
}
|
|
23989
|
+
stack.push(this._makeUnary(op, stack.pop()));
|
|
23990
|
+
return;
|
|
23991
|
+
}
|
|
23992
|
+
switch (op) {
|
|
23993
|
+
case TOKEN.true:
|
|
23994
|
+
stack.push(new PsConstNode(true));
|
|
23995
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
23996
|
+
this._failed = true;
|
|
23997
|
+
}
|
|
23998
|
+
break;
|
|
23999
|
+
case TOKEN.false:
|
|
24000
|
+
stack.push(new PsConstNode(false));
|
|
24001
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
24002
|
+
this._failed = true;
|
|
24003
|
+
}
|
|
24004
|
+
break;
|
|
24005
|
+
case TOKEN.dup:
|
|
24006
|
+
if (stack.length < 1) {
|
|
24007
|
+
this._failed = true;
|
|
24008
|
+
break;
|
|
24009
|
+
}
|
|
24010
|
+
stack.push(stack.at(-1));
|
|
24011
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
24012
|
+
this._failed = true;
|
|
24013
|
+
}
|
|
24014
|
+
break;
|
|
24015
|
+
case TOKEN.exch: {
|
|
24016
|
+
if (stack.length < 2) {
|
|
24017
|
+
this._failed = true;
|
|
24018
|
+
break;
|
|
24019
|
+
}
|
|
24020
|
+
const a = stack.pop();
|
|
24021
|
+
const b = stack.pop();
|
|
24022
|
+
stack.push(a, b);
|
|
24023
|
+
break;
|
|
24024
|
+
}
|
|
24025
|
+
case TOKEN.pop:
|
|
24026
|
+
if (stack.length < 1) {
|
|
24027
|
+
this._failed = true;
|
|
24028
|
+
break;
|
|
24029
|
+
}
|
|
24030
|
+
stack.pop();
|
|
24031
|
+
break;
|
|
24032
|
+
case TOKEN.copy: {
|
|
24033
|
+
if (stack.length < 1) {
|
|
24034
|
+
this._failed = true;
|
|
24035
|
+
break;
|
|
24036
|
+
}
|
|
24037
|
+
const nNode = stack.pop();
|
|
24038
|
+
if (nNode.type === PS_NODE.const) {
|
|
24039
|
+
const n = nNode.value | 0;
|
|
24040
|
+
if (n === 0) {
|
|
24041
|
+
} else if (n < 0 || n > stack.length) {
|
|
24042
|
+
this._failed = true;
|
|
24043
|
+
} else {
|
|
24044
|
+
stack.push(...stack.slice(-n));
|
|
24045
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
24046
|
+
this._failed = true;
|
|
24047
|
+
}
|
|
24048
|
+
}
|
|
24049
|
+
} else {
|
|
24050
|
+
this._failed = true;
|
|
24051
|
+
}
|
|
24052
|
+
break;
|
|
24053
|
+
}
|
|
24054
|
+
case TOKEN.index: {
|
|
24055
|
+
if (stack.length < 1) {
|
|
24056
|
+
this._failed = true;
|
|
24057
|
+
break;
|
|
24058
|
+
}
|
|
24059
|
+
const nNode = stack.pop();
|
|
24060
|
+
if (nNode.type === PS_NODE.const) {
|
|
24061
|
+
const n = nNode.value | 0;
|
|
24062
|
+
if (n < 0 || n >= stack.length) {
|
|
24063
|
+
this._failed = true;
|
|
24064
|
+
} else {
|
|
24065
|
+
stack.push(stack.at(-n - 1));
|
|
24066
|
+
}
|
|
24067
|
+
} else {
|
|
24068
|
+
this._failed = true;
|
|
24069
|
+
}
|
|
24070
|
+
break;
|
|
24071
|
+
}
|
|
24072
|
+
case TOKEN.roll: {
|
|
24073
|
+
if (stack.length < 2) {
|
|
24074
|
+
this._failed = true;
|
|
24075
|
+
break;
|
|
24076
|
+
}
|
|
24077
|
+
const jNode = stack.pop();
|
|
24078
|
+
const nNode = stack.pop();
|
|
24079
|
+
if (nNode.type === PS_NODE.const && jNode.type === PS_NODE.const) {
|
|
24080
|
+
const n = nNode.value | 0;
|
|
24081
|
+
if (n === 0) {
|
|
24082
|
+
} else if (n < 0 || n > stack.length) {
|
|
24083
|
+
this._failed = true;
|
|
24084
|
+
} else {
|
|
24085
|
+
const j = ((jNode.value | 0) % n + n) % n;
|
|
24086
|
+
if (j > 0) {
|
|
24087
|
+
const slice = stack.splice(-n, n);
|
|
24088
|
+
stack.push(...slice.slice(n - j), ...slice.slice(0, n - j));
|
|
24089
|
+
}
|
|
24090
|
+
}
|
|
24091
|
+
} else {
|
|
24092
|
+
this._failed = true;
|
|
24093
|
+
}
|
|
24094
|
+
break;
|
|
24095
|
+
}
|
|
24096
|
+
default:
|
|
24097
|
+
this._failed = true;
|
|
24098
|
+
break;
|
|
24099
|
+
}
|
|
24100
|
+
}
|
|
24101
|
+
/**
|
|
24102
|
+
* Create a binary tree node, applying optimizations eagerly:
|
|
24103
|
+
*
|
|
24104
|
+
* 1. Constant folding — both operands are PsConstNode → fold to PsConstNode.
|
|
24105
|
+
* 2. Reflexive simplifications — x−x→0, x xor x→0, x eq x→true, etc.
|
|
24106
|
+
* 3. Algebraic simplifications with one known operand — identity elements
|
|
24107
|
+
* (x+0→x, x*1→x, …), absorbing elements (x*0→0, x and false→false, …),
|
|
24108
|
+
* and strength reductions (x*-1→neg(x), x^0.5→sqrt(x), x^2→x*x, …).
|
|
24109
|
+
*
|
|
24110
|
+
* Recall: `first` was on top of the stack (right operand for non-commutative
|
|
24111
|
+
* ops), `second` was below (left operand). So `a b sub` → second=a, first=b
|
|
24112
|
+
* → a − b.
|
|
24113
|
+
*/
|
|
24114
|
+
_makeBinary(op, first, second) {
|
|
24115
|
+
if (first.type === PS_NODE.const && second.type === PS_NODE.const) {
|
|
24116
|
+
const v = _evalBinaryConst(op, second.value, first.value);
|
|
24117
|
+
if (v !== void 0) {
|
|
24118
|
+
return new PsConstNode(v);
|
|
24119
|
+
}
|
|
24120
|
+
}
|
|
24121
|
+
if (_nodesEqual(first, second)) {
|
|
24122
|
+
switch (op) {
|
|
24123
|
+
case TOKEN.sub:
|
|
24124
|
+
return new PsConstNode(0);
|
|
24125
|
+
// x − x → 0
|
|
24126
|
+
case TOKEN.xor:
|
|
24127
|
+
return new PsConstNode(
|
|
24128
|
+
/* eslint-disable unicorn/prefer-logical-operator-over-ternary */
|
|
24129
|
+
first.valueType === PS_VALUE_TYPE.boolean ? false : 0
|
|
24130
|
+
/* eslint-enable unicorn/prefer-logical-operator-over-ternary */
|
|
24131
|
+
);
|
|
24132
|
+
// TOKEN.mod, TOKEN.div, TOKEN.idiv are NOT simplified here:
|
|
24133
|
+
// x op x is undefined when x = 0, so we cannot fold without knowing
|
|
24134
|
+
// that x is non-zero.
|
|
24135
|
+
case TOKEN.and:
|
|
24136
|
+
case TOKEN.or:
|
|
24137
|
+
return first;
|
|
24138
|
+
// x and x → x; x or x → x
|
|
24139
|
+
case TOKEN.min:
|
|
24140
|
+
case TOKEN.max:
|
|
24141
|
+
return first;
|
|
24142
|
+
// min(x,x) → x; max(x,x) → x
|
|
24143
|
+
case TOKEN.eq:
|
|
24144
|
+
case TOKEN.ge:
|
|
24145
|
+
case TOKEN.le:
|
|
24146
|
+
return new PsConstNode(true);
|
|
24147
|
+
case TOKEN.ne:
|
|
24148
|
+
case TOKEN.gt:
|
|
24149
|
+
case TOKEN.lt:
|
|
24150
|
+
return new PsConstNode(false);
|
|
24151
|
+
}
|
|
24152
|
+
}
|
|
24153
|
+
if (first.type === PS_NODE.const) {
|
|
24154
|
+
const b = first.value;
|
|
24155
|
+
switch (op) {
|
|
24156
|
+
case TOKEN.add:
|
|
24157
|
+
if (b === 0) {
|
|
24158
|
+
return second;
|
|
24159
|
+
}
|
|
24160
|
+
break;
|
|
24161
|
+
case TOKEN.sub:
|
|
24162
|
+
if (b === 0) {
|
|
24163
|
+
return second;
|
|
24164
|
+
}
|
|
24165
|
+
break;
|
|
24166
|
+
case TOKEN.mul:
|
|
24167
|
+
if (b === 1) {
|
|
24168
|
+
return second;
|
|
24169
|
+
}
|
|
24170
|
+
if (b === 0) {
|
|
24171
|
+
return first;
|
|
24172
|
+
}
|
|
24173
|
+
if (b === -1) {
|
|
24174
|
+
return this._makeUnary(TOKEN.neg, second);
|
|
24175
|
+
}
|
|
24176
|
+
break;
|
|
24177
|
+
case TOKEN.div:
|
|
24178
|
+
if (b !== 0) {
|
|
24179
|
+
return this._makeBinary(TOKEN.mul, new PsConstNode(1 / b), second);
|
|
24180
|
+
}
|
|
24181
|
+
break;
|
|
24182
|
+
case TOKEN.idiv:
|
|
24183
|
+
if (b === 1) {
|
|
24184
|
+
return second;
|
|
24185
|
+
}
|
|
24186
|
+
break;
|
|
24187
|
+
case TOKEN.exp:
|
|
24188
|
+
if (b === 1) {
|
|
24189
|
+
return second;
|
|
24190
|
+
}
|
|
24191
|
+
if (b === -1) {
|
|
24192
|
+
return this._makeBinary(TOKEN.div, second, new PsConstNode(1));
|
|
24193
|
+
}
|
|
24194
|
+
if (b === 0.5) {
|
|
24195
|
+
return this._makeUnary(TOKEN.sqrt, second);
|
|
24196
|
+
}
|
|
24197
|
+
if (b === 0.25) {
|
|
24198
|
+
const sqrtOnce = this._makeUnary(TOKEN.sqrt, second);
|
|
24199
|
+
return this._makeUnary(TOKEN.sqrt, sqrtOnce);
|
|
24200
|
+
}
|
|
24201
|
+
if (b === 2) {
|
|
24202
|
+
return this._makeBinary(TOKEN.mul, second, second);
|
|
24203
|
+
}
|
|
24204
|
+
if (b === 3) {
|
|
24205
|
+
return this._makeBinary(
|
|
24206
|
+
TOKEN.mul,
|
|
24207
|
+
this._makeBinary(TOKEN.mul, second, second),
|
|
24208
|
+
second
|
|
24209
|
+
);
|
|
24210
|
+
}
|
|
24211
|
+
if (b === 4) {
|
|
24212
|
+
const square = this._makeBinary(TOKEN.mul, second, second);
|
|
24213
|
+
return this._makeBinary(TOKEN.mul, square, square);
|
|
24214
|
+
}
|
|
24215
|
+
if (b === 0) {
|
|
24216
|
+
return new PsConstNode(1);
|
|
24217
|
+
}
|
|
24218
|
+
break;
|
|
24219
|
+
case TOKEN.and:
|
|
24220
|
+
if (b === true) {
|
|
24221
|
+
return second;
|
|
24222
|
+
}
|
|
24223
|
+
if (b === false) {
|
|
24224
|
+
return first;
|
|
24225
|
+
}
|
|
24226
|
+
break;
|
|
24227
|
+
case TOKEN.or:
|
|
24228
|
+
if (b === false) {
|
|
24229
|
+
return second;
|
|
24230
|
+
}
|
|
24231
|
+
if (b === true) {
|
|
24232
|
+
return first;
|
|
24233
|
+
}
|
|
24234
|
+
break;
|
|
24235
|
+
case TOKEN.min:
|
|
24236
|
+
if (second.type === PS_NODE.binary && second.op === TOKEN.max && second.first.type === PS_NODE.const && second.first.value >= b) {
|
|
24237
|
+
return first;
|
|
24238
|
+
}
|
|
24239
|
+
break;
|
|
24240
|
+
case TOKEN.max:
|
|
24241
|
+
if (second.type === PS_NODE.binary && second.op === TOKEN.min && second.first.type === PS_NODE.const && second.first.value <= b) {
|
|
24242
|
+
return first;
|
|
24243
|
+
}
|
|
24244
|
+
break;
|
|
24245
|
+
}
|
|
24246
|
+
}
|
|
24247
|
+
if (second.type === PS_NODE.const) {
|
|
24248
|
+
const a = second.value;
|
|
24249
|
+
switch (op) {
|
|
24250
|
+
case TOKEN.add:
|
|
24251
|
+
if (a === 0) {
|
|
24252
|
+
return first;
|
|
24253
|
+
}
|
|
24254
|
+
break;
|
|
24255
|
+
case TOKEN.sub:
|
|
24256
|
+
if (a === 0) {
|
|
24257
|
+
return this._makeUnary(TOKEN.neg, first);
|
|
24258
|
+
}
|
|
24259
|
+
break;
|
|
24260
|
+
case TOKEN.mul:
|
|
24261
|
+
if (a === 1) {
|
|
24262
|
+
return first;
|
|
24263
|
+
}
|
|
24264
|
+
if (a === 0) {
|
|
24265
|
+
return second;
|
|
24266
|
+
}
|
|
24267
|
+
if (a === -1) {
|
|
24268
|
+
return this._makeUnary(TOKEN.neg, first);
|
|
24269
|
+
}
|
|
24270
|
+
break;
|
|
24271
|
+
case TOKEN.and:
|
|
24272
|
+
if (a === true) {
|
|
24273
|
+
return first;
|
|
24274
|
+
}
|
|
24275
|
+
if (a === false) {
|
|
24276
|
+
return second;
|
|
24277
|
+
}
|
|
24278
|
+
break;
|
|
24279
|
+
case TOKEN.or:
|
|
24280
|
+
if (a === false) {
|
|
24281
|
+
return first;
|
|
24282
|
+
}
|
|
24283
|
+
if (a === true) {
|
|
24284
|
+
return second;
|
|
24285
|
+
}
|
|
24286
|
+
break;
|
|
24287
|
+
}
|
|
24288
|
+
}
|
|
24289
|
+
return new PsBinaryNode(
|
|
24290
|
+
op,
|
|
24291
|
+
first,
|
|
24292
|
+
second,
|
|
24293
|
+
_binaryValueType(op, first.valueType, second.valueType)
|
|
24294
|
+
);
|
|
24295
|
+
}
|
|
24296
|
+
/**
|
|
24297
|
+
* Create a unary tree node, applying optimizations eagerly:
|
|
24298
|
+
*
|
|
24299
|
+
* 1. Constant folding.
|
|
24300
|
+
* 2. not(comparison) → negated comparison: not(a eq b) → a ne b, etc.
|
|
24301
|
+
* 3. neg(a − b) → b − a.
|
|
24302
|
+
* 4. Double-negation: neg(neg(x)) → x, not(not(x)) → x.
|
|
24303
|
+
* 5. abs(neg(x)) → abs(x).
|
|
24304
|
+
* 6. Idempotent: f(f(x)) → f(x) for abs, ceiling, floor, round, etc.
|
|
24305
|
+
*/
|
|
24306
|
+
_makeUnary(op, operand) {
|
|
24307
|
+
if (operand.type === PS_NODE.const) {
|
|
24308
|
+
const v = _evalUnaryConst(op, operand.value);
|
|
24309
|
+
if (v !== void 0) {
|
|
24310
|
+
return new PsConstNode(v);
|
|
24311
|
+
}
|
|
24312
|
+
}
|
|
24313
|
+
if (op === TOKEN.not && operand.type === PS_NODE.binary) {
|
|
24314
|
+
const negated = _PSStackToTree.#negatedComparison.get(operand.op);
|
|
24315
|
+
if (negated !== void 0) {
|
|
24316
|
+
return new PsBinaryNode(
|
|
24317
|
+
negated,
|
|
24318
|
+
operand.first,
|
|
24319
|
+
operand.second,
|
|
24320
|
+
PS_VALUE_TYPE.boolean
|
|
24321
|
+
);
|
|
24322
|
+
}
|
|
24323
|
+
}
|
|
24324
|
+
if (op === TOKEN.neg && operand.type === PS_NODE.binary && operand.op === TOKEN.sub) {
|
|
24325
|
+
return this._makeBinary(TOKEN.sub, operand.second, operand.first);
|
|
24326
|
+
}
|
|
24327
|
+
if (operand.type === PS_NODE.unary) {
|
|
24328
|
+
if (op === TOKEN.neg && operand.op === TOKEN.neg || op === TOKEN.not && operand.op === TOKEN.not) {
|
|
24329
|
+
return operand.operand;
|
|
24330
|
+
}
|
|
24331
|
+
if (op === TOKEN.abs && operand.op === TOKEN.neg) {
|
|
24332
|
+
return this._makeUnary(TOKEN.abs, operand.operand);
|
|
24333
|
+
}
|
|
24334
|
+
if (_PSStackToTree.#idempotentUnary.has(op) && op === operand.op) {
|
|
24335
|
+
return operand;
|
|
24336
|
+
}
|
|
24337
|
+
}
|
|
24338
|
+
return new PsUnaryNode(op, operand, _unaryValueType(op, operand.valueType));
|
|
24339
|
+
}
|
|
24340
|
+
/**
|
|
24341
|
+
* Create a ternary node, applying optimizations eagerly:
|
|
24342
|
+
*
|
|
24343
|
+
* 1. Constant condition — fold to the live branch.
|
|
24344
|
+
* 2. Identical branches — the condition is irrelevant, return either branch.
|
|
24345
|
+
* 3. Boolean branch constants — `cond ? true : false` → cond,
|
|
24346
|
+
* `cond ? false : true` → not(cond).
|
|
24347
|
+
* 4. Ternary → branchless min/max when the condition compares two numeric
|
|
24348
|
+
* expressions that are also the two branches.
|
|
24349
|
+
*/
|
|
24350
|
+
_makeTernary(cond, then, otherwise) {
|
|
24351
|
+
if (cond.type === PS_NODE.const) {
|
|
24352
|
+
return cond.value ? then : otherwise;
|
|
24353
|
+
}
|
|
24354
|
+
if (_nodesEqual(then, otherwise)) {
|
|
24355
|
+
return then;
|
|
24356
|
+
}
|
|
24357
|
+
if (then.type === PS_NODE.const && otherwise.type === PS_NODE.const) {
|
|
24358
|
+
if (then.value === true && otherwise.value === false) {
|
|
24359
|
+
return cond;
|
|
24360
|
+
}
|
|
24361
|
+
if (then.value === false && otherwise.value === true) {
|
|
24362
|
+
return this._makeUnary(TOKEN.not, cond);
|
|
24363
|
+
}
|
|
24364
|
+
}
|
|
24365
|
+
if (cond.type === PS_NODE.binary) {
|
|
24366
|
+
const { op: cop, first: cf, second: cs } = cond;
|
|
24367
|
+
if (cop === TOKEN.gt || cop === TOKEN.ge) {
|
|
24368
|
+
if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
|
|
24369
|
+
return this._makeBinary(TOKEN.min, cf, cs);
|
|
24370
|
+
}
|
|
24371
|
+
if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
|
|
24372
|
+
return this._makeBinary(TOKEN.max, cf, cs);
|
|
24373
|
+
}
|
|
24374
|
+
} else if (cop === TOKEN.lt || cop === TOKEN.le) {
|
|
24375
|
+
if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
|
|
24376
|
+
return this._makeBinary(TOKEN.max, cf, cs);
|
|
24377
|
+
}
|
|
24378
|
+
if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
|
|
24379
|
+
return this._makeBinary(TOKEN.min, cf, cs);
|
|
24380
|
+
}
|
|
24381
|
+
}
|
|
24382
|
+
}
|
|
24383
|
+
return new PsTernaryNode(
|
|
24384
|
+
cond,
|
|
24385
|
+
then,
|
|
24386
|
+
otherwise,
|
|
24387
|
+
then.valueType === otherwise.valueType ? then.valueType : PS_VALUE_TYPE.unknown
|
|
24388
|
+
);
|
|
24389
|
+
}
|
|
24390
|
+
};
|
|
24391
|
+
var OP = {
|
|
24392
|
+
ARG: 0,
|
|
24393
|
+
// [ARG, idx]
|
|
24394
|
+
CONST: 1,
|
|
24395
|
+
// [CONST, val]
|
|
24396
|
+
STORE: 2,
|
|
24397
|
+
// [STORE, slot, min, max] clamp(pop()) → mem[slot]
|
|
24398
|
+
IF: 3,
|
|
24399
|
+
// [IF, target] jump when top-of-stack === 0
|
|
24400
|
+
JUMP: 4,
|
|
24401
|
+
// [JUMP, target] unconditional
|
|
24402
|
+
ABS: 5,
|
|
24403
|
+
NEG: 6,
|
|
24404
|
+
CEIL: 7,
|
|
24405
|
+
FLOOR: 8,
|
|
24406
|
+
ROUND: 9,
|
|
24407
|
+
// floor(x + 0.5)
|
|
24408
|
+
TRUNC: 10,
|
|
24409
|
+
NOT_B: 11,
|
|
24410
|
+
// boolean NOT
|
|
24411
|
+
NOT_N: 12,
|
|
24412
|
+
// bitwise NOT
|
|
24413
|
+
SQRT: 13,
|
|
24414
|
+
SIN: 14,
|
|
24415
|
+
// degrees in/out
|
|
24416
|
+
COS: 15,
|
|
24417
|
+
LN: 16,
|
|
24418
|
+
LOG10: 17,
|
|
24419
|
+
CVI: 18,
|
|
24420
|
+
SHIFT: 19,
|
|
24421
|
+
// [SHIFT, amount] +ve = left, −ve = right
|
|
24422
|
+
// Binary ops: second below, first on top; result = second OP first.
|
|
24423
|
+
ADD: 20,
|
|
24424
|
+
SUB: 21,
|
|
24425
|
+
MUL: 22,
|
|
24426
|
+
DIV: 23,
|
|
24427
|
+
// 0 when divisor is 0
|
|
24428
|
+
IDIV: 24,
|
|
24429
|
+
// 0 when divisor is 0
|
|
24430
|
+
MOD: 25,
|
|
24431
|
+
// 0 when divisor is 0
|
|
24432
|
+
POW: 26,
|
|
24433
|
+
EQ: 27,
|
|
24434
|
+
NE: 28,
|
|
24435
|
+
GT: 29,
|
|
24436
|
+
GE: 30,
|
|
24437
|
+
LT: 31,
|
|
24438
|
+
LE: 32,
|
|
24439
|
+
AND: 33,
|
|
24440
|
+
OR: 34,
|
|
24441
|
+
XOR: 35,
|
|
24442
|
+
ATAN: 36,
|
|
24443
|
+
// atan2(second, first) → degrees [0, 360)
|
|
24444
|
+
MIN: 37,
|
|
24445
|
+
MAX: 38,
|
|
24446
|
+
TEE_TMP: 39,
|
|
24447
|
+
// [TEE_TMP, slot] peek top of stack → tmp[slot], leave on stack
|
|
24448
|
+
LOAD_TMP: 40
|
|
24449
|
+
// [LOAD_TMP, slot] push tmp[slot]
|
|
24450
|
+
};
|
|
24451
|
+
var _DEG_TO_RAD = Math.PI / 180;
|
|
24452
|
+
var _RAD_TO_DEG = 180 / Math.PI;
|
|
24453
|
+
var PsJsCompiler = class {
|
|
24454
|
+
// Safe because JS is single-threaded.
|
|
24455
|
+
static #stack = new Float64Array(64);
|
|
24456
|
+
static #tmp = new Float64Array(64);
|
|
24457
|
+
constructor(domain, range) {
|
|
24458
|
+
this.nIn = domain.length >> 1;
|
|
24459
|
+
this.nOut = range.length >> 1;
|
|
24460
|
+
this.range = range;
|
|
24461
|
+
this.ir = [];
|
|
24462
|
+
this._tmpMap = /* @__PURE__ */ new Map();
|
|
24463
|
+
this._nextTmp = 0;
|
|
24464
|
+
}
|
|
24465
|
+
_compileNode(node) {
|
|
24466
|
+
if (node.shared) {
|
|
24467
|
+
const cached = this._tmpMap.get(node);
|
|
24468
|
+
if (cached !== void 0) {
|
|
24469
|
+
this.ir.push(OP.LOAD_TMP, cached);
|
|
24470
|
+
return true;
|
|
24471
|
+
}
|
|
24472
|
+
if (!this._compileNodeImpl(node)) {
|
|
24473
|
+
return false;
|
|
24474
|
+
}
|
|
24475
|
+
const slot = this._nextTmp++;
|
|
24476
|
+
this._tmpMap.set(node, slot);
|
|
24477
|
+
this.ir.push(OP.TEE_TMP, slot);
|
|
24478
|
+
return true;
|
|
24479
|
+
}
|
|
24480
|
+
return this._compileNodeImpl(node);
|
|
24481
|
+
}
|
|
24482
|
+
_compileNodeImpl(node) {
|
|
24483
|
+
switch (node.type) {
|
|
24484
|
+
case PS_NODE.arg:
|
|
24485
|
+
this.ir.push(OP.ARG, node.index);
|
|
24486
|
+
return true;
|
|
24487
|
+
case PS_NODE.const: {
|
|
24488
|
+
const v = node.value;
|
|
24489
|
+
this.ir.push(OP.CONST, typeof v === "boolean" ? Number(v) : v);
|
|
24490
|
+
return true;
|
|
24491
|
+
}
|
|
24492
|
+
case PS_NODE.unary:
|
|
24493
|
+
return this._compileUnary(node);
|
|
24494
|
+
case PS_NODE.binary:
|
|
24495
|
+
return this._compileBinary(node);
|
|
24496
|
+
case PS_NODE.ternary:
|
|
24497
|
+
return this._compileTernary(node);
|
|
24498
|
+
default:
|
|
24499
|
+
return false;
|
|
24500
|
+
}
|
|
24501
|
+
}
|
|
24502
|
+
_compileUnary(node) {
|
|
24503
|
+
const { op, operand, valueType } = node;
|
|
24504
|
+
if (op === TOKEN.cvr) {
|
|
24505
|
+
return this._compileNode(operand);
|
|
24506
|
+
}
|
|
24507
|
+
if (!this._compileNode(operand)) {
|
|
24508
|
+
return false;
|
|
24509
|
+
}
|
|
24510
|
+
switch (op) {
|
|
24511
|
+
case TOKEN.abs:
|
|
24512
|
+
this.ir.push(OP.ABS);
|
|
24513
|
+
break;
|
|
24514
|
+
case TOKEN.neg:
|
|
24515
|
+
this.ir.push(OP.NEG);
|
|
24516
|
+
break;
|
|
24517
|
+
case TOKEN.ceiling:
|
|
24518
|
+
this.ir.push(OP.CEIL);
|
|
24519
|
+
break;
|
|
24520
|
+
case TOKEN.floor:
|
|
24521
|
+
this.ir.push(OP.FLOOR);
|
|
24522
|
+
break;
|
|
24523
|
+
case TOKEN.round:
|
|
24524
|
+
this.ir.push(OP.ROUND);
|
|
24525
|
+
break;
|
|
24526
|
+
case TOKEN.truncate:
|
|
24527
|
+
this.ir.push(OP.TRUNC);
|
|
24528
|
+
break;
|
|
24529
|
+
case TOKEN.sqrt:
|
|
24530
|
+
this.ir.push(OP.SQRT);
|
|
24531
|
+
break;
|
|
24532
|
+
case TOKEN.sin:
|
|
24533
|
+
this.ir.push(OP.SIN);
|
|
24534
|
+
break;
|
|
24535
|
+
case TOKEN.cos:
|
|
24536
|
+
this.ir.push(OP.COS);
|
|
24537
|
+
break;
|
|
24538
|
+
case TOKEN.ln:
|
|
24539
|
+
this.ir.push(OP.LN);
|
|
24540
|
+
break;
|
|
24541
|
+
case TOKEN.log:
|
|
24542
|
+
this.ir.push(OP.LOG10);
|
|
24543
|
+
break;
|
|
24544
|
+
case TOKEN.cvi:
|
|
24545
|
+
this.ir.push(OP.CVI);
|
|
24546
|
+
break;
|
|
24547
|
+
case TOKEN.not:
|
|
24548
|
+
if (valueType === PS_VALUE_TYPE.boolean) {
|
|
24549
|
+
this.ir.push(OP.NOT_B);
|
|
24550
|
+
} else if (valueType === PS_VALUE_TYPE.numeric) {
|
|
24551
|
+
this.ir.push(OP.NOT_N);
|
|
24552
|
+
} else {
|
|
24553
|
+
return false;
|
|
24554
|
+
}
|
|
24555
|
+
break;
|
|
24556
|
+
default:
|
|
24557
|
+
return false;
|
|
24558
|
+
}
|
|
24559
|
+
return true;
|
|
24560
|
+
}
|
|
24561
|
+
_compileBinary(node) {
|
|
24562
|
+
const { op, first, second } = node;
|
|
24563
|
+
if (op === TOKEN.bitshift) {
|
|
24564
|
+
if (first.type !== PS_NODE.const || !Number.isInteger(first.value) || !this._compileNode(second)) {
|
|
24565
|
+
return false;
|
|
24566
|
+
}
|
|
24567
|
+
this.ir.push(OP.SHIFT, first.value);
|
|
24568
|
+
return true;
|
|
24569
|
+
}
|
|
24570
|
+
if (!this._compileNode(second) || !this._compileNode(first)) {
|
|
24571
|
+
return false;
|
|
24572
|
+
}
|
|
24573
|
+
switch (op) {
|
|
24574
|
+
case TOKEN.add:
|
|
24575
|
+
this.ir.push(OP.ADD);
|
|
24576
|
+
break;
|
|
24577
|
+
case TOKEN.sub:
|
|
24578
|
+
this.ir.push(OP.SUB);
|
|
24579
|
+
break;
|
|
24580
|
+
case TOKEN.mul:
|
|
24581
|
+
this.ir.push(OP.MUL);
|
|
24582
|
+
break;
|
|
24583
|
+
case TOKEN.div:
|
|
24584
|
+
this.ir.push(OP.DIV);
|
|
24585
|
+
break;
|
|
24586
|
+
case TOKEN.idiv:
|
|
24587
|
+
this.ir.push(OP.IDIV);
|
|
24588
|
+
break;
|
|
24589
|
+
case TOKEN.mod:
|
|
24590
|
+
this.ir.push(OP.MOD);
|
|
24591
|
+
break;
|
|
24592
|
+
case TOKEN.exp:
|
|
24593
|
+
this.ir.push(OP.POW);
|
|
24594
|
+
break;
|
|
24595
|
+
case TOKEN.eq:
|
|
24596
|
+
this.ir.push(OP.EQ);
|
|
24597
|
+
break;
|
|
24598
|
+
case TOKEN.ne:
|
|
24599
|
+
this.ir.push(OP.NE);
|
|
24600
|
+
break;
|
|
24601
|
+
case TOKEN.gt:
|
|
24602
|
+
this.ir.push(OP.GT);
|
|
24603
|
+
break;
|
|
24604
|
+
case TOKEN.ge:
|
|
24605
|
+
this.ir.push(OP.GE);
|
|
24606
|
+
break;
|
|
24607
|
+
case TOKEN.lt:
|
|
24608
|
+
this.ir.push(OP.LT);
|
|
24609
|
+
break;
|
|
24610
|
+
case TOKEN.le:
|
|
24611
|
+
this.ir.push(OP.LE);
|
|
24612
|
+
break;
|
|
24613
|
+
case TOKEN.and:
|
|
24614
|
+
this.ir.push(OP.AND);
|
|
24615
|
+
break;
|
|
24616
|
+
case TOKEN.or:
|
|
24617
|
+
this.ir.push(OP.OR);
|
|
24618
|
+
break;
|
|
24619
|
+
case TOKEN.xor:
|
|
24620
|
+
this.ir.push(OP.XOR);
|
|
24621
|
+
break;
|
|
24622
|
+
case TOKEN.atan:
|
|
24623
|
+
this.ir.push(OP.ATAN);
|
|
24624
|
+
break;
|
|
24625
|
+
case TOKEN.min:
|
|
24626
|
+
this.ir.push(OP.MIN);
|
|
24627
|
+
break;
|
|
24628
|
+
case TOKEN.max:
|
|
24629
|
+
this.ir.push(OP.MAX);
|
|
24630
|
+
break;
|
|
24631
|
+
default:
|
|
24632
|
+
return false;
|
|
24633
|
+
}
|
|
24634
|
+
return true;
|
|
24635
|
+
}
|
|
24636
|
+
_compileTernary(node) {
|
|
24637
|
+
if (!this._compileNode(node.cond)) {
|
|
24638
|
+
return false;
|
|
24639
|
+
}
|
|
24640
|
+
this.ir.push(OP.IF, 0);
|
|
24641
|
+
const ifPatch = this.ir.length - 1;
|
|
24642
|
+
if (!this._compileNode(node.then)) {
|
|
24643
|
+
return false;
|
|
24644
|
+
}
|
|
24645
|
+
this.ir.push(OP.JUMP, 0);
|
|
24646
|
+
const jumpPatch = this.ir.length - 1;
|
|
24647
|
+
this.ir[ifPatch] = this.ir.length;
|
|
24648
|
+
if (!this._compileNode(node.otherwise)) {
|
|
24649
|
+
return false;
|
|
24650
|
+
}
|
|
24651
|
+
this.ir[jumpPatch] = this.ir.length;
|
|
24652
|
+
return true;
|
|
24653
|
+
}
|
|
24654
|
+
compile(program) {
|
|
24655
|
+
const outputs = new PSStackToTree().evaluate(program, this.nIn);
|
|
24656
|
+
if (!outputs || outputs.length < this.nOut) {
|
|
24657
|
+
return null;
|
|
24658
|
+
}
|
|
24659
|
+
for (let i = 0; i < this.nOut; i++) {
|
|
24660
|
+
if (!this._compileNode(outputs[i])) {
|
|
24661
|
+
return null;
|
|
24662
|
+
}
|
|
24663
|
+
const min = this.range[i * 2];
|
|
24664
|
+
const max = this.range[i * 2 + 1];
|
|
24665
|
+
this.ir.push(OP.STORE, i, min, max);
|
|
24666
|
+
}
|
|
24667
|
+
return new Float64Array(this.ir);
|
|
24668
|
+
}
|
|
24669
|
+
static execute(ir, src, srcOffset, dest, destOffset) {
|
|
24670
|
+
let ip = 0, sp = 0;
|
|
24671
|
+
const n = ir.length;
|
|
24672
|
+
const stack = this.#stack;
|
|
24673
|
+
const tmp = this.#tmp;
|
|
24674
|
+
while (ip < n) {
|
|
24675
|
+
switch (ir[ip++] | 0) {
|
|
24676
|
+
case OP.ARG:
|
|
24677
|
+
stack[sp++] = src[srcOffset + (ir[ip++] | 0)];
|
|
24678
|
+
break;
|
|
24679
|
+
case OP.CONST:
|
|
24680
|
+
stack[sp++] = ir[ip++];
|
|
24681
|
+
break;
|
|
24682
|
+
case OP.STORE: {
|
|
24683
|
+
const slot = ir[ip++] | 0;
|
|
24684
|
+
const min = ir[ip++];
|
|
24685
|
+
const max = ir[ip++];
|
|
24686
|
+
dest[destOffset + slot] = MathClamp(stack[--sp], min, max);
|
|
24687
|
+
break;
|
|
24688
|
+
}
|
|
24689
|
+
case OP.IF: {
|
|
24690
|
+
const tgt = ir[ip++];
|
|
24691
|
+
if (stack[--sp] === 0) {
|
|
24692
|
+
ip = tgt;
|
|
24693
|
+
}
|
|
24694
|
+
break;
|
|
24695
|
+
}
|
|
24696
|
+
case OP.JUMP:
|
|
24697
|
+
ip = ir[ip];
|
|
24698
|
+
break;
|
|
24699
|
+
case OP.ABS:
|
|
24700
|
+
stack[sp - 1] = Math.abs(stack[sp - 1]);
|
|
24701
|
+
break;
|
|
24702
|
+
case OP.NEG:
|
|
24703
|
+
stack[sp - 1] = -stack[sp - 1];
|
|
24704
|
+
break;
|
|
24705
|
+
case OP.CEIL:
|
|
24706
|
+
stack[sp - 1] = Math.ceil(stack[sp - 1]);
|
|
24707
|
+
break;
|
|
24708
|
+
case OP.FLOOR:
|
|
24709
|
+
stack[sp - 1] = Math.floor(stack[sp - 1]);
|
|
24710
|
+
break;
|
|
24711
|
+
case OP.ROUND:
|
|
24712
|
+
stack[sp - 1] = Math.floor(stack[sp - 1] + 0.5);
|
|
24713
|
+
break;
|
|
24714
|
+
case OP.TRUNC:
|
|
24715
|
+
stack[sp - 1] = Math.trunc(stack[sp - 1]);
|
|
24716
|
+
break;
|
|
24717
|
+
case OP.NOT_B:
|
|
24718
|
+
stack[sp - 1] = stack[sp - 1] !== 0 ? 0 : 1;
|
|
24719
|
+
break;
|
|
24720
|
+
case OP.NOT_N:
|
|
24721
|
+
stack[sp - 1] = ~(stack[sp - 1] | 0);
|
|
24722
|
+
break;
|
|
24723
|
+
case OP.SQRT:
|
|
24724
|
+
stack[sp - 1] = Math.sqrt(stack[sp - 1]);
|
|
24725
|
+
break;
|
|
24726
|
+
case OP.SIN:
|
|
24727
|
+
stack[sp - 1] = Math.sin(stack[sp - 1] % 360 * _DEG_TO_RAD);
|
|
24728
|
+
break;
|
|
24729
|
+
case OP.COS:
|
|
24730
|
+
stack[sp - 1] = Math.cos(stack[sp - 1] % 360 * _DEG_TO_RAD);
|
|
24731
|
+
break;
|
|
24732
|
+
case OP.LN:
|
|
24733
|
+
stack[sp - 1] = Math.log(stack[sp - 1]);
|
|
24734
|
+
break;
|
|
24735
|
+
case OP.LOG10:
|
|
24736
|
+
stack[sp - 1] = Math.log10(stack[sp - 1]);
|
|
24737
|
+
break;
|
|
24738
|
+
case OP.CVI:
|
|
24739
|
+
stack[sp - 1] = Math.trunc(stack[sp - 1]) | 0;
|
|
24740
|
+
break;
|
|
24741
|
+
case OP.SHIFT: {
|
|
24742
|
+
const amt = ir[ip++];
|
|
24743
|
+
const v = stack[sp - 1] | 0;
|
|
24744
|
+
if (amt > 0) {
|
|
24745
|
+
stack[sp - 1] = v << amt;
|
|
24746
|
+
} else if (amt < 0) {
|
|
24747
|
+
stack[sp - 1] = v >> -amt;
|
|
24748
|
+
} else {
|
|
24749
|
+
stack[sp - 1] = v;
|
|
24750
|
+
}
|
|
24751
|
+
break;
|
|
24752
|
+
}
|
|
24753
|
+
case OP.ADD: {
|
|
24754
|
+
const b = stack[--sp];
|
|
24755
|
+
stack[sp - 1] += b;
|
|
24756
|
+
break;
|
|
24757
|
+
}
|
|
24758
|
+
case OP.SUB: {
|
|
24759
|
+
const b = stack[--sp];
|
|
24760
|
+
stack[sp - 1] -= b;
|
|
24761
|
+
break;
|
|
24762
|
+
}
|
|
24763
|
+
case OP.MUL: {
|
|
24764
|
+
const b = stack[--sp];
|
|
24765
|
+
stack[sp - 1] *= b;
|
|
24766
|
+
break;
|
|
24767
|
+
}
|
|
24768
|
+
case OP.DIV: {
|
|
24769
|
+
const b = stack[--sp];
|
|
24770
|
+
stack[sp - 1] = b !== 0 ? stack[sp - 1] / b : 0;
|
|
24771
|
+
break;
|
|
24772
|
+
}
|
|
24773
|
+
case OP.IDIV: {
|
|
24774
|
+
const b = stack[--sp];
|
|
24775
|
+
stack[sp - 1] = b !== 0 ? Math.trunc(stack[sp - 1] / b) : 0;
|
|
24776
|
+
break;
|
|
24777
|
+
}
|
|
24778
|
+
case OP.MOD: {
|
|
24779
|
+
const b = stack[--sp];
|
|
24780
|
+
stack[sp - 1] = b !== 0 ? stack[sp - 1] % b : 0;
|
|
24781
|
+
break;
|
|
24782
|
+
}
|
|
24783
|
+
case OP.POW: {
|
|
24784
|
+
const b = stack[--sp];
|
|
24785
|
+
stack[sp - 1] **= b;
|
|
24786
|
+
break;
|
|
24787
|
+
}
|
|
24788
|
+
case OP.EQ: {
|
|
24789
|
+
const b = stack[--sp];
|
|
24790
|
+
stack[sp - 1] = stack[sp - 1] === b ? 1 : 0;
|
|
24791
|
+
break;
|
|
24792
|
+
}
|
|
24793
|
+
case OP.NE: {
|
|
24794
|
+
const b = stack[--sp];
|
|
24795
|
+
stack[sp - 1] = stack[sp - 1] !== b ? 1 : 0;
|
|
24796
|
+
break;
|
|
24797
|
+
}
|
|
24798
|
+
case OP.GT: {
|
|
24799
|
+
const b = stack[--sp];
|
|
24800
|
+
stack[sp - 1] = stack[sp - 1] > b ? 1 : 0;
|
|
24801
|
+
break;
|
|
24802
|
+
}
|
|
24803
|
+
case OP.GE: {
|
|
24804
|
+
const b = stack[--sp];
|
|
24805
|
+
stack[sp - 1] = stack[sp - 1] >= b ? 1 : 0;
|
|
24806
|
+
break;
|
|
24807
|
+
}
|
|
24808
|
+
case OP.LT: {
|
|
24809
|
+
const b = stack[--sp];
|
|
24810
|
+
stack[sp - 1] = stack[sp - 1] < b ? 1 : 0;
|
|
24811
|
+
break;
|
|
24812
|
+
}
|
|
24813
|
+
case OP.LE: {
|
|
24814
|
+
const b = stack[--sp];
|
|
24815
|
+
stack[sp - 1] = stack[sp - 1] <= b ? 1 : 0;
|
|
24816
|
+
break;
|
|
24817
|
+
}
|
|
24818
|
+
case OP.AND: {
|
|
24819
|
+
const b = stack[--sp] | 0;
|
|
24820
|
+
stack[sp - 1] = (stack[sp - 1] | 0) & b;
|
|
24821
|
+
break;
|
|
24822
|
+
}
|
|
24823
|
+
case OP.OR: {
|
|
24824
|
+
const b = stack[--sp] | 0;
|
|
24825
|
+
stack[sp - 1] = stack[sp - 1] | 0 | b;
|
|
24826
|
+
break;
|
|
24827
|
+
}
|
|
24828
|
+
case OP.XOR: {
|
|
24829
|
+
const b = stack[--sp] | 0;
|
|
24830
|
+
stack[sp - 1] = (stack[sp - 1] | 0) ^ b;
|
|
24831
|
+
break;
|
|
24832
|
+
}
|
|
24833
|
+
case OP.ATAN: {
|
|
24834
|
+
const b = stack[--sp];
|
|
24835
|
+
const deg = Math.atan2(stack[sp - 1], b) * _RAD_TO_DEG;
|
|
24836
|
+
stack[sp - 1] = deg < 0 ? deg + 360 : deg;
|
|
24837
|
+
break;
|
|
24838
|
+
}
|
|
24839
|
+
case OP.MIN: {
|
|
24840
|
+
const b = stack[--sp];
|
|
24841
|
+
stack[sp - 1] = Math.min(stack[sp - 1], b);
|
|
24842
|
+
break;
|
|
24843
|
+
}
|
|
24844
|
+
case OP.MAX: {
|
|
24845
|
+
const b = stack[--sp];
|
|
24846
|
+
stack[sp - 1] = Math.max(stack[sp - 1], b);
|
|
24847
|
+
break;
|
|
24848
|
+
}
|
|
24849
|
+
case OP.TEE_TMP:
|
|
24850
|
+
tmp[ir[ip++] | 0] = stack[sp - 1];
|
|
24851
|
+
break;
|
|
24852
|
+
case OP.LOAD_TMP:
|
|
24853
|
+
stack[sp++] = tmp[ir[ip++] | 0];
|
|
24854
|
+
break;
|
|
24855
|
+
}
|
|
24856
|
+
}
|
|
24857
|
+
}
|
|
24858
|
+
};
|
|
24859
|
+
var PSStackBasedInterpreter = class {
|
|
24860
|
+
// Safe: JS is single-threaded.
|
|
24861
|
+
static #stack = new Float64Array(100);
|
|
24862
|
+
static #sp = 0;
|
|
24863
|
+
static #push(v) {
|
|
24864
|
+
if (this.#sp < this.#stack.length) {
|
|
24865
|
+
this.#stack[this.#sp++] = v;
|
|
24866
|
+
}
|
|
24867
|
+
}
|
|
24868
|
+
static #execOp(op) {
|
|
24869
|
+
const stack = this.#stack;
|
|
24870
|
+
switch (op) {
|
|
24871
|
+
case TOKEN.true:
|
|
24872
|
+
this.#push(1);
|
|
24873
|
+
break;
|
|
24874
|
+
case TOKEN.false:
|
|
24875
|
+
this.#push(0);
|
|
24876
|
+
break;
|
|
24877
|
+
case TOKEN.abs:
|
|
24878
|
+
stack[this.#sp - 1] = Math.abs(stack[this.#sp - 1]);
|
|
24879
|
+
break;
|
|
24880
|
+
case TOKEN.neg:
|
|
24881
|
+
stack[this.#sp - 1] = -stack[this.#sp - 1];
|
|
24882
|
+
break;
|
|
24883
|
+
case TOKEN.ceiling:
|
|
24884
|
+
stack[this.#sp - 1] = Math.ceil(stack[this.#sp - 1]);
|
|
24885
|
+
break;
|
|
24886
|
+
case TOKEN.floor:
|
|
24887
|
+
stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1]);
|
|
24888
|
+
break;
|
|
24889
|
+
case TOKEN.round:
|
|
24890
|
+
stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1] + 0.5);
|
|
24891
|
+
break;
|
|
24892
|
+
case TOKEN.truncate:
|
|
24893
|
+
stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]);
|
|
24894
|
+
break;
|
|
24895
|
+
case TOKEN.sqrt:
|
|
24896
|
+
stack[this.#sp - 1] = Math.sqrt(stack[this.#sp - 1]);
|
|
24897
|
+
break;
|
|
24898
|
+
case TOKEN.sin:
|
|
24899
|
+
stack[this.#sp - 1] = Math.sin(
|
|
24900
|
+
stack[this.#sp - 1] % 360 * _DEG_TO_RAD
|
|
24901
|
+
);
|
|
24902
|
+
break;
|
|
24903
|
+
case TOKEN.cos:
|
|
24904
|
+
stack[this.#sp - 1] = Math.cos(
|
|
24905
|
+
stack[this.#sp - 1] % 360 * _DEG_TO_RAD
|
|
24906
|
+
);
|
|
24907
|
+
break;
|
|
24908
|
+
case TOKEN.ln:
|
|
24909
|
+
stack[this.#sp - 1] = Math.log(stack[this.#sp - 1]);
|
|
24910
|
+
break;
|
|
24911
|
+
case TOKEN.log:
|
|
24912
|
+
stack[this.#sp - 1] = Math.log10(stack[this.#sp - 1]);
|
|
24913
|
+
break;
|
|
24914
|
+
case TOKEN.cvi:
|
|
24915
|
+
stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]) | 0;
|
|
24916
|
+
break;
|
|
24917
|
+
case TOKEN.cvr:
|
|
24918
|
+
break;
|
|
24919
|
+
// values are already f64
|
|
24920
|
+
case TOKEN.not: {
|
|
24921
|
+
const v = stack[this.#sp - 1];
|
|
24922
|
+
stack[this.#sp - 1] = v === 0 || v === 1 ? 1 - v : ~(v | 0);
|
|
24923
|
+
break;
|
|
24924
|
+
}
|
|
24925
|
+
case TOKEN.add: {
|
|
24926
|
+
const b = stack[--this.#sp];
|
|
24927
|
+
stack[this.#sp - 1] += b;
|
|
24928
|
+
break;
|
|
24929
|
+
}
|
|
24930
|
+
case TOKEN.sub: {
|
|
24931
|
+
const b = stack[--this.#sp];
|
|
24932
|
+
stack[this.#sp - 1] -= b;
|
|
24933
|
+
break;
|
|
24934
|
+
}
|
|
24935
|
+
case TOKEN.mul: {
|
|
24936
|
+
const b = stack[--this.#sp];
|
|
24937
|
+
stack[this.#sp - 1] *= b;
|
|
24938
|
+
break;
|
|
24939
|
+
}
|
|
24940
|
+
case TOKEN.div: {
|
|
24941
|
+
const b = stack[--this.#sp];
|
|
24942
|
+
stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] / b : 0;
|
|
24943
|
+
break;
|
|
24944
|
+
}
|
|
24945
|
+
case TOKEN.idiv: {
|
|
24946
|
+
const b = stack[--this.#sp];
|
|
24947
|
+
stack[this.#sp - 1] = b !== 0 ? Math.trunc(stack[this.#sp - 1] / b) : 0;
|
|
24948
|
+
break;
|
|
24949
|
+
}
|
|
24950
|
+
case TOKEN.mod: {
|
|
24951
|
+
const b = stack[--this.#sp];
|
|
24952
|
+
stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] % b : 0;
|
|
24953
|
+
break;
|
|
24954
|
+
}
|
|
24955
|
+
case TOKEN.exp: {
|
|
24956
|
+
const b = stack[--this.#sp];
|
|
24957
|
+
stack[this.#sp - 1] **= b;
|
|
24958
|
+
break;
|
|
24959
|
+
}
|
|
24960
|
+
case TOKEN.atan: {
|
|
24961
|
+
const dx = stack[--this.#sp];
|
|
24962
|
+
const deg = Math.atan2(stack[this.#sp - 1], dx) * _RAD_TO_DEG;
|
|
24963
|
+
stack[this.#sp - 1] = deg < 0 ? deg + 360 : deg;
|
|
24964
|
+
break;
|
|
24965
|
+
}
|
|
24966
|
+
case TOKEN.eq: {
|
|
24967
|
+
const b = stack[--this.#sp];
|
|
24968
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] === b ? 1 : 0;
|
|
24969
|
+
break;
|
|
24970
|
+
}
|
|
24971
|
+
case TOKEN.ne: {
|
|
24972
|
+
const b = stack[--this.#sp];
|
|
24973
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] !== b ? 1 : 0;
|
|
24974
|
+
break;
|
|
24975
|
+
}
|
|
24976
|
+
case TOKEN.gt: {
|
|
24977
|
+
const b = stack[--this.#sp];
|
|
24978
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] > b ? 1 : 0;
|
|
24979
|
+
break;
|
|
24980
|
+
}
|
|
24981
|
+
case TOKEN.ge: {
|
|
24982
|
+
const b = stack[--this.#sp];
|
|
24983
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] >= b ? 1 : 0;
|
|
24984
|
+
break;
|
|
24985
|
+
}
|
|
24986
|
+
case TOKEN.lt: {
|
|
24987
|
+
const b = stack[--this.#sp];
|
|
24988
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] < b ? 1 : 0;
|
|
24989
|
+
break;
|
|
24990
|
+
}
|
|
24991
|
+
case TOKEN.le: {
|
|
24992
|
+
const b = stack[--this.#sp];
|
|
24993
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] <= b ? 1 : 0;
|
|
24994
|
+
break;
|
|
24995
|
+
}
|
|
24996
|
+
case TOKEN.and: {
|
|
24997
|
+
const b = stack[--this.#sp] | 0;
|
|
24998
|
+
stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) & b;
|
|
24999
|
+
break;
|
|
25000
|
+
}
|
|
25001
|
+
case TOKEN.or: {
|
|
25002
|
+
const b = stack[--this.#sp] | 0;
|
|
25003
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] | 0 | b;
|
|
25004
|
+
break;
|
|
25005
|
+
}
|
|
25006
|
+
case TOKEN.xor: {
|
|
25007
|
+
const b = stack[--this.#sp] | 0;
|
|
25008
|
+
stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) ^ b;
|
|
25009
|
+
break;
|
|
25010
|
+
}
|
|
25011
|
+
case TOKEN.bitshift: {
|
|
25012
|
+
const amt = stack[--this.#sp] | 0;
|
|
25013
|
+
const v = stack[this.#sp - 1] | 0;
|
|
25014
|
+
stack[this.#sp - 1] = amt > 0 ? v << amt : v >> -amt;
|
|
25015
|
+
break;
|
|
25016
|
+
}
|
|
25017
|
+
case TOKEN.min: {
|
|
25018
|
+
const b = stack[--this.#sp];
|
|
25019
|
+
stack[this.#sp - 1] = Math.min(stack[this.#sp - 1], b);
|
|
25020
|
+
break;
|
|
25021
|
+
}
|
|
25022
|
+
case TOKEN.max: {
|
|
25023
|
+
const b = stack[--this.#sp];
|
|
25024
|
+
stack[this.#sp - 1] = Math.max(stack[this.#sp - 1], b);
|
|
25025
|
+
break;
|
|
25026
|
+
}
|
|
25027
|
+
case TOKEN.dup:
|
|
25028
|
+
this.#push(stack[this.#sp - 1]);
|
|
25029
|
+
break;
|
|
25030
|
+
case TOKEN.exch: {
|
|
25031
|
+
const a = stack[--this.#sp];
|
|
25032
|
+
const b = stack[--this.#sp];
|
|
25033
|
+
this.#push(a);
|
|
25034
|
+
this.#push(b);
|
|
25035
|
+
break;
|
|
25036
|
+
}
|
|
25037
|
+
case TOKEN.pop:
|
|
25038
|
+
this.#sp--;
|
|
25039
|
+
break;
|
|
25040
|
+
case TOKEN.copy: {
|
|
25041
|
+
const n = Math.trunc(stack[--this.#sp]);
|
|
25042
|
+
const base = this.#sp - n;
|
|
25043
|
+
for (let k = 0; k < n; k++) {
|
|
25044
|
+
this.#push(stack[base + k]);
|
|
25045
|
+
}
|
|
25046
|
+
break;
|
|
25047
|
+
}
|
|
25048
|
+
case TOKEN.index: {
|
|
25049
|
+
const i = Math.trunc(stack[--this.#sp]);
|
|
25050
|
+
this.#push(stack[this.#sp - 1 - i]);
|
|
25051
|
+
break;
|
|
25052
|
+
}
|
|
25053
|
+
case TOKEN.roll: {
|
|
25054
|
+
const j = Math.trunc(stack[--this.#sp]);
|
|
25055
|
+
const n = Math.trunc(stack[--this.#sp]);
|
|
25056
|
+
if (n > 1 && j !== 0) {
|
|
25057
|
+
const mod = (j % n + n) % n;
|
|
25058
|
+
if (mod !== 0) {
|
|
25059
|
+
const base = this.#sp - n;
|
|
25060
|
+
const sub = stack.slice(base, this.#sp);
|
|
25061
|
+
for (let k = 0; k < n; k++) {
|
|
25062
|
+
stack[base + k] = sub[(k - mod + n) % n];
|
|
25063
|
+
}
|
|
25064
|
+
}
|
|
25065
|
+
}
|
|
25066
|
+
break;
|
|
25067
|
+
}
|
|
25068
|
+
}
|
|
25069
|
+
}
|
|
25070
|
+
static #execBlock(instructions) {
|
|
25071
|
+
for (const instr of instructions) {
|
|
25072
|
+
switch (instr.type) {
|
|
25073
|
+
case PS_NODE.number:
|
|
25074
|
+
this.#push(instr.value);
|
|
25075
|
+
break;
|
|
25076
|
+
case PS_NODE.operator:
|
|
25077
|
+
this.#execOp(instr.op);
|
|
25078
|
+
break;
|
|
25079
|
+
case PS_NODE.if:
|
|
25080
|
+
if (this.#stack[--this.#sp] !== 0) {
|
|
25081
|
+
this.#execBlock(instr.then.instructions);
|
|
25082
|
+
}
|
|
25083
|
+
break;
|
|
25084
|
+
case PS_NODE.ifelse:
|
|
25085
|
+
if (this.#stack[--this.#sp] !== 0) {
|
|
25086
|
+
this.#execBlock(instr.then.instructions);
|
|
25087
|
+
} else {
|
|
25088
|
+
this.#execBlock(instr.otherwise.instructions);
|
|
25089
|
+
}
|
|
25090
|
+
break;
|
|
25091
|
+
}
|
|
25092
|
+
}
|
|
25093
|
+
}
|
|
25094
|
+
/**
|
|
25095
|
+
* @param {import("./ast.js").PsProgram} program
|
|
25096
|
+
* @param {number[]} domain – flat [min0,max0, …]
|
|
25097
|
+
* @param {number[]} range – flat [min0,max0, …]
|
|
25098
|
+
* @returns {Function} – `(src, srcOffset, dest, destOffset) => void`
|
|
25099
|
+
*/
|
|
25100
|
+
static build(program, domain, range) {
|
|
25101
|
+
const nIn = domain.length >> 1;
|
|
25102
|
+
const nOut = range.length >> 1;
|
|
25103
|
+
const { instructions } = program.body;
|
|
25104
|
+
return (src, srcOffset, dest, destOffset) => {
|
|
25105
|
+
this.#sp = 0;
|
|
25106
|
+
for (let i = 0; i < nIn; i++) {
|
|
25107
|
+
this.#push(src[srcOffset + i]);
|
|
25108
|
+
}
|
|
25109
|
+
this.#execBlock(instructions);
|
|
25110
|
+
const base = this.#sp - nOut;
|
|
25111
|
+
for (let i = 0; i < nOut; i++) {
|
|
25112
|
+
const v = base + i >= 0 ? this.#stack[base + i] : 0;
|
|
25113
|
+
dest[destOffset + i] = MathClamp(v, range[i * 2], range[i * 2 + 1]);
|
|
25114
|
+
}
|
|
25115
|
+
};
|
|
25116
|
+
}
|
|
25117
|
+
};
|
|
25118
|
+
function buildPostScriptJsFunction(source, domain, range, forceInterpreter = false) {
|
|
25119
|
+
const program = parsePostScriptFunction(source);
|
|
25120
|
+
const ir = !forceInterpreter && new PsJsCompiler(domain, range).compile(program);
|
|
25121
|
+
if (ir) {
|
|
25122
|
+
return (src, srcOffset, dest, destOffset) => {
|
|
25123
|
+
PsJsCompiler.execute(ir, src, srcOffset, dest, destOffset);
|
|
25124
|
+
};
|
|
25125
|
+
}
|
|
25126
|
+
return PSStackBasedInterpreter.build(program, domain, range);
|
|
25127
|
+
}
|
|
25128
|
+
var ShadingType = {
|
|
25129
|
+
FUNCTION_BASED: 1,
|
|
25130
|
+
AXIAL: 2,
|
|
25131
|
+
RADIAL: 3,
|
|
25132
|
+
FREE_FORM_MESH: 4,
|
|
25133
|
+
LATTICE_FORM_MESH: 5,
|
|
25134
|
+
COONS_PATCH_MESH: 6,
|
|
25135
|
+
TENSOR_PATCH_MESH: 7
|
|
25136
|
+
};
|
|
25137
|
+
var BaseShading = class _BaseShading {
|
|
25138
|
+
// A small number to offset the first/last color stops so we can insert ones
|
|
25139
|
+
// to support extend. Number.MIN_VALUE is too small and breaks the extend.
|
|
25140
|
+
static SMALL_NUMBER = 1e-6;
|
|
25141
|
+
constructor() {
|
|
25142
|
+
if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _BaseShading) {
|
|
25143
|
+
unreachable2("Cannot initialize BaseShading.");
|
|
25144
|
+
}
|
|
25145
|
+
}
|
|
25146
|
+
getIR() {
|
|
25147
|
+
unreachable2("Abstract method `getIR` called.");
|
|
25148
|
+
}
|
|
25149
|
+
};
|
|
25150
|
+
function meshUpdateBounds(self) {
|
|
25151
|
+
let minX = self.coords[0][0], minY = self.coords[0][1], maxX = minX, maxY = minY;
|
|
25152
|
+
for (let i = 1, ii = self.coords.length; i < ii; i++) {
|
|
25153
|
+
const x = self.coords[i][0], y = self.coords[i][1];
|
|
25154
|
+
minX = minX > x ? x : minX;
|
|
25155
|
+
minY = minY > y ? y : minY;
|
|
25156
|
+
maxX = maxX < x ? x : maxX;
|
|
25157
|
+
maxY = maxY < y ? y : maxY;
|
|
25158
|
+
}
|
|
25159
|
+
self.bounds = [minX, minY, maxX, maxY];
|
|
25160
|
+
}
|
|
25161
|
+
function meshPackData(self) {
|
|
25162
|
+
let i, j, ii;
|
|
25163
|
+
const coords = self.coords;
|
|
25164
|
+
const coordsPacked = new Float32Array(coords.length * 2);
|
|
25165
|
+
for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
|
|
25166
|
+
const xy = coords[i];
|
|
25167
|
+
coordsPacked[j++] = xy[0];
|
|
25168
|
+
coordsPacked[j++] = xy[1];
|
|
25169
|
+
}
|
|
25170
|
+
self.coords = coordsPacked;
|
|
25171
|
+
const colors = self.colors;
|
|
25172
|
+
const colorsPacked = new Uint8Array(colors.length * 4);
|
|
25173
|
+
for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
|
|
25174
|
+
const c = colors[i];
|
|
25175
|
+
colorsPacked[j++] = c[0];
|
|
25176
|
+
colorsPacked[j++] = c[1];
|
|
25177
|
+
colorsPacked[j++] = c[2];
|
|
25178
|
+
j++;
|
|
25179
|
+
}
|
|
25180
|
+
self.colors = colorsPacked;
|
|
25181
|
+
for (const figure of self.figures) {
|
|
25182
|
+
figure.coords = new Uint32Array(figure.coords);
|
|
25183
|
+
figure.colors = new Uint32Array(figure.colors);
|
|
25184
|
+
}
|
|
25185
|
+
}
|
|
25186
|
+
function buildMeshVertexData(coords, colors, figures) {
|
|
25187
|
+
let vertexCount = 0;
|
|
25188
|
+
for (const figure of figures) {
|
|
25189
|
+
if (figure.type === MeshFigureType.TRIANGLES) {
|
|
25190
|
+
vertexCount += figure.coords.length;
|
|
25191
|
+
} else if (figure.type === MeshFigureType.LATTICE) {
|
|
25192
|
+
const vpr = figure.verticesPerRow;
|
|
25193
|
+
vertexCount += (Math.floor(figure.coords.length / vpr) - 1) * (vpr - 1) * 6;
|
|
25194
|
+
}
|
|
25195
|
+
}
|
|
25196
|
+
const posData = new Float32Array(vertexCount * 2);
|
|
25197
|
+
const colData = new Uint8Array(vertexCount * 4);
|
|
25198
|
+
let pOff = 0, cOff = 0;
|
|
25199
|
+
const addVertex = (pi, ci) => {
|
|
25200
|
+
posData[pOff++] = coords[pi * 2];
|
|
25201
|
+
posData[pOff++] = coords[pi * 2 + 1];
|
|
25202
|
+
colData[cOff++] = colors[ci * 4];
|
|
25203
|
+
colData[cOff++] = colors[ci * 4 + 1];
|
|
25204
|
+
colData[cOff++] = colors[ci * 4 + 2];
|
|
25205
|
+
cOff++;
|
|
25206
|
+
};
|
|
25207
|
+
for (const figure of figures) {
|
|
25208
|
+
const ps = figure.coords;
|
|
25209
|
+
const cs = figure.colors;
|
|
25210
|
+
if (figure.type === MeshFigureType.TRIANGLES) {
|
|
25211
|
+
for (let i = 0, ii = ps.length; i < ii; i++) {
|
|
25212
|
+
addVertex(ps[i], cs[i]);
|
|
25213
|
+
}
|
|
25214
|
+
} else if (figure.type === MeshFigureType.LATTICE) {
|
|
25215
|
+
const vpr = figure.verticesPerRow;
|
|
25216
|
+
const rows = Math.floor(ps.length / vpr) - 1;
|
|
25217
|
+
const cols = vpr - 1;
|
|
25218
|
+
for (let i = 0; i < rows; i++) {
|
|
25219
|
+
let q = i * vpr;
|
|
25220
|
+
for (let j = 0; j < cols; j++, q++) {
|
|
25221
|
+
addVertex(ps[q], cs[q]);
|
|
25222
|
+
addVertex(ps[q + 1], cs[q + 1]);
|
|
25223
|
+
addVertex(ps[q + vpr], cs[q + vpr]);
|
|
25224
|
+
addVertex(ps[q + vpr + 1], cs[q + vpr + 1]);
|
|
25225
|
+
addVertex(ps[q + 1], cs[q + 1]);
|
|
25226
|
+
addVertex(ps[q + vpr], cs[q + vpr]);
|
|
25227
|
+
}
|
|
25228
|
+
}
|
|
25229
|
+
}
|
|
25230
|
+
}
|
|
25231
|
+
return { posData, colData, vertexCount };
|
|
25232
|
+
}
|
|
25233
|
+
var MeshStreamReader = class {
|
|
25234
|
+
constructor(stream, context) {
|
|
25235
|
+
this.stream = stream;
|
|
25236
|
+
this.context = context;
|
|
25237
|
+
this.buffer = 0;
|
|
25238
|
+
this.bufferLength = 0;
|
|
25239
|
+
const numComps = context.numComps;
|
|
25240
|
+
this.tmpCompsBuf = new Float32Array(numComps);
|
|
25241
|
+
const csNumComps = context.colorSpace.numComps;
|
|
25242
|
+
this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf;
|
|
25243
|
+
}
|
|
25244
|
+
get hasData() {
|
|
25245
|
+
if (this.stream.end) {
|
|
25246
|
+
return this.stream.pos < this.stream.end;
|
|
25247
|
+
}
|
|
25248
|
+
if (this.bufferLength > 0) {
|
|
25249
|
+
return true;
|
|
25250
|
+
}
|
|
25251
|
+
const nextByte = this.stream.getByte();
|
|
25252
|
+
if (nextByte < 0) {
|
|
25253
|
+
return false;
|
|
25254
|
+
}
|
|
25255
|
+
this.buffer = nextByte;
|
|
25256
|
+
this.bufferLength = 8;
|
|
25257
|
+
return true;
|
|
25258
|
+
}
|
|
25259
|
+
readBits(n) {
|
|
25260
|
+
const { stream } = this;
|
|
25261
|
+
let { buffer, bufferLength } = this;
|
|
25262
|
+
if (n === 32) {
|
|
25263
|
+
if (bufferLength === 0) {
|
|
25264
|
+
return stream.getInt32() >>> 0;
|
|
25265
|
+
}
|
|
25266
|
+
buffer = buffer << 24 | stream.getByte() << 16 | stream.getByte() << 8 | stream.getByte();
|
|
25267
|
+
const nextByte = stream.getByte();
|
|
25268
|
+
this.buffer = nextByte & (1 << bufferLength) - 1;
|
|
25269
|
+
return (buffer << 8 - bufferLength | (nextByte & 255) >> bufferLength) >>> 0;
|
|
25270
|
+
}
|
|
25271
|
+
if (n === 8 && bufferLength === 0) {
|
|
25272
|
+
return stream.getByte();
|
|
25273
|
+
}
|
|
25274
|
+
while (bufferLength < n) {
|
|
25275
|
+
buffer = buffer << 8 | stream.getByte();
|
|
25276
|
+
bufferLength += 8;
|
|
25277
|
+
}
|
|
25278
|
+
bufferLength -= n;
|
|
25279
|
+
this.bufferLength = bufferLength;
|
|
25280
|
+
this.buffer = buffer & (1 << bufferLength) - 1;
|
|
25281
|
+
return buffer >> bufferLength;
|
|
25282
|
+
}
|
|
25283
|
+
align() {
|
|
25284
|
+
this.buffer = 0;
|
|
25285
|
+
this.bufferLength = 0;
|
|
25286
|
+
}
|
|
25287
|
+
readFlag() {
|
|
25288
|
+
return this.readBits(this.context.bitsPerFlag);
|
|
25289
|
+
}
|
|
25290
|
+
readCoordinate() {
|
|
25291
|
+
const { bitsPerCoordinate, decode } = this.context;
|
|
25292
|
+
const xi = this.readBits(bitsPerCoordinate);
|
|
25293
|
+
const yi = this.readBits(bitsPerCoordinate);
|
|
25294
|
+
const scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 23283064365386963e-26;
|
|
25295
|
+
return [
|
|
25296
|
+
xi * scale * (decode[1] - decode[0]) + decode[0],
|
|
25297
|
+
yi * scale * (decode[3] - decode[2]) + decode[2]
|
|
25298
|
+
];
|
|
25299
|
+
}
|
|
25300
|
+
readComponents() {
|
|
25301
|
+
const { bitsPerComponent, colorFn, colorSpace, decode, numComps } = this.context;
|
|
25302
|
+
const scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 23283064365386963e-26;
|
|
25303
|
+
const components = this.tmpCompsBuf;
|
|
25304
|
+
for (let i = 0, j = 4; i < numComps; i++, j += 2) {
|
|
25305
|
+
const ci = this.readBits(bitsPerComponent);
|
|
25306
|
+
components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j];
|
|
25307
|
+
}
|
|
25308
|
+
const color = this.tmpCsCompsBuf;
|
|
25309
|
+
colorFn?.(components, 0, color, 0);
|
|
25310
|
+
return colorSpace.getRgb(color, 0);
|
|
25311
|
+
}
|
|
25312
|
+
};
|
|
25313
|
+
var bCache = null;
|
|
25314
|
+
function getB(count) {
|
|
25315
|
+
if (bCache?.has(count)) return bCache.get(count);
|
|
25316
|
+
const values = Array.from({ length: count + 1 }, (_, i) => {
|
|
25317
|
+
const t = i / count, t_ = 1 - t;
|
|
25318
|
+
return new Float32Array([
|
|
25319
|
+
t_ ** 3,
|
|
25320
|
+
3 * t * t_ ** 2,
|
|
25321
|
+
3 * t ** 2 * t_,
|
|
25322
|
+
t ** 3
|
|
25323
|
+
]);
|
|
25324
|
+
});
|
|
25325
|
+
(bCache ??= /* @__PURE__ */ new Map()).set(count, values);
|
|
25326
|
+
return values;
|
|
25327
|
+
}
|
|
25328
|
+
var MeshShading = class _MeshShading extends BaseShading {
|
|
25329
|
+
static MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;
|
|
25330
|
+
static MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;
|
|
25331
|
+
// Count of triangles per entire mesh bounds.
|
|
25332
|
+
static TRIANGLE_DENSITY = 20;
|
|
25333
|
+
constructor(shadingType, stream, context, rowVertices) {
|
|
25334
|
+
super();
|
|
25335
|
+
this.shadingType = shadingType;
|
|
25336
|
+
this.bbox = this.background = null;
|
|
25337
|
+
this.coords = [];
|
|
25338
|
+
this.colors = [];
|
|
25339
|
+
this.figures = [];
|
|
25340
|
+
const reader = new MeshStreamReader(stream, context);
|
|
25341
|
+
let patchMesh = false;
|
|
25342
|
+
switch (this.shadingType) {
|
|
25343
|
+
case ShadingType.FREE_FORM_MESH:
|
|
25344
|
+
this._decodeType4Shading(reader);
|
|
25345
|
+
break;
|
|
25346
|
+
case ShadingType.LATTICE_FORM_MESH:
|
|
25347
|
+
const verticesPerRow = rowVertices | 0;
|
|
25348
|
+
if (verticesPerRow < 2) {
|
|
25349
|
+
throw new FormatError("Invalid VerticesPerRow");
|
|
25350
|
+
}
|
|
25351
|
+
this._decodeType5Shading(reader, verticesPerRow);
|
|
25352
|
+
break;
|
|
25353
|
+
case ShadingType.COONS_PATCH_MESH:
|
|
25354
|
+
this._decodeType6Shading(reader);
|
|
25355
|
+
patchMesh = true;
|
|
25356
|
+
break;
|
|
25357
|
+
case ShadingType.TENSOR_PATCH_MESH:
|
|
25358
|
+
this._decodeType7Shading(reader);
|
|
25359
|
+
patchMesh = true;
|
|
25360
|
+
break;
|
|
25361
|
+
default:
|
|
25362
|
+
unreachable2("Unsupported mesh type.");
|
|
25363
|
+
break;
|
|
25364
|
+
}
|
|
25365
|
+
if (patchMesh) {
|
|
25366
|
+
this._updateBounds();
|
|
25367
|
+
for (let i = 0, ii = this.figures.length; i < ii; i++) {
|
|
25368
|
+
this._buildFigureFromPatch(i);
|
|
25369
|
+
}
|
|
25370
|
+
}
|
|
25371
|
+
this._updateBounds();
|
|
25372
|
+
this._packData();
|
|
25373
|
+
}
|
|
25374
|
+
_decodeType4Shading(reader) {
|
|
25375
|
+
const coords = this.coords;
|
|
25376
|
+
const colors = this.colors;
|
|
25377
|
+
const operators = [];
|
|
25378
|
+
const ps = [];
|
|
25379
|
+
let verticesLeft = 0;
|
|
25380
|
+
while (reader.hasData) {
|
|
25381
|
+
const f = reader.readFlag();
|
|
25382
|
+
const coord = reader.readCoordinate();
|
|
25383
|
+
const color = reader.readComponents();
|
|
25384
|
+
if (verticesLeft === 0) {
|
|
25385
|
+
if (!(0 <= f && f <= 2)) {
|
|
25386
|
+
throw new FormatError("Unknown type4 flag");
|
|
25387
|
+
}
|
|
25388
|
+
switch (f) {
|
|
25389
|
+
case 0:
|
|
25390
|
+
verticesLeft = 3;
|
|
25391
|
+
break;
|
|
25392
|
+
case 1:
|
|
25393
|
+
ps.push(ps.at(-2), ps.at(-1));
|
|
25394
|
+
verticesLeft = 1;
|
|
25395
|
+
break;
|
|
25396
|
+
case 2:
|
|
25397
|
+
ps.push(ps.at(-3), ps.at(-1));
|
|
25398
|
+
verticesLeft = 1;
|
|
25399
|
+
break;
|
|
25400
|
+
}
|
|
25401
|
+
operators.push(f);
|
|
25402
|
+
}
|
|
25403
|
+
ps.push(coords.length);
|
|
25404
|
+
coords.push(coord);
|
|
25405
|
+
colors.push(color);
|
|
25406
|
+
verticesLeft--;
|
|
25407
|
+
reader.align();
|
|
25408
|
+
}
|
|
25409
|
+
this.figures.push({
|
|
25410
|
+
type: MeshFigureType.TRIANGLES,
|
|
25411
|
+
coords: new Int32Array(ps),
|
|
25412
|
+
colors: new Int32Array(ps)
|
|
25413
|
+
});
|
|
25414
|
+
}
|
|
25415
|
+
_decodeType5Shading(reader, verticesPerRow) {
|
|
25416
|
+
const coords = this.coords;
|
|
25417
|
+
const colors = this.colors;
|
|
25418
|
+
const ps = [];
|
|
25419
|
+
while (reader.hasData) {
|
|
25420
|
+
const coord = reader.readCoordinate();
|
|
25421
|
+
const color = reader.readComponents();
|
|
25422
|
+
ps.push(coords.length);
|
|
25423
|
+
coords.push(coord);
|
|
25424
|
+
colors.push(color);
|
|
25425
|
+
}
|
|
25426
|
+
this.figures.push({
|
|
25427
|
+
type: MeshFigureType.LATTICE,
|
|
25428
|
+
coords: new Int32Array(ps),
|
|
25429
|
+
colors: new Int32Array(ps),
|
|
25430
|
+
verticesPerRow
|
|
25431
|
+
});
|
|
25432
|
+
}
|
|
25433
|
+
_decodeType6Shading(reader) {
|
|
25434
|
+
const coords = this.coords;
|
|
25435
|
+
const colors = this.colors;
|
|
25436
|
+
const ps = new Int32Array(16);
|
|
25437
|
+
const cs = new Int32Array(4);
|
|
25438
|
+
while (reader.hasData) {
|
|
25439
|
+
const f = reader.readFlag();
|
|
25440
|
+
if (!(0 <= f && f <= 3)) {
|
|
25441
|
+
throw new FormatError("Unknown type6 flag");
|
|
25442
|
+
}
|
|
25443
|
+
const pi = coords.length;
|
|
25444
|
+
for (let i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) {
|
|
25445
|
+
coords.push(reader.readCoordinate());
|
|
25446
|
+
}
|
|
25447
|
+
const ci = colors.length;
|
|
25448
|
+
for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
|
|
25449
|
+
colors.push(reader.readComponents());
|
|
25450
|
+
}
|
|
25451
|
+
let tmp1, tmp2, tmp3, tmp4;
|
|
25452
|
+
switch (f) {
|
|
25453
|
+
// prettier-ignore
|
|
25454
|
+
case 0:
|
|
25455
|
+
ps[12] = pi + 3;
|
|
25456
|
+
ps[13] = pi + 4;
|
|
25457
|
+
ps[14] = pi + 5;
|
|
25458
|
+
ps[15] = pi + 6;
|
|
25459
|
+
ps[8] = pi + 2;
|
|
25460
|
+
ps[11] = pi + 7;
|
|
25461
|
+
ps[4] = pi + 1;
|
|
25462
|
+
ps[7] = pi + 8;
|
|
25463
|
+
ps[0] = pi;
|
|
25464
|
+
ps[1] = pi + 11;
|
|
25465
|
+
ps[2] = pi + 10;
|
|
25466
|
+
ps[3] = pi + 9;
|
|
25467
|
+
cs[2] = ci + 1;
|
|
25468
|
+
cs[3] = ci + 2;
|
|
25469
|
+
cs[0] = ci;
|
|
25470
|
+
cs[1] = ci + 3;
|
|
25471
|
+
break;
|
|
25472
|
+
// prettier-ignore
|
|
25473
|
+
case 1:
|
|
25474
|
+
tmp1 = ps[12];
|
|
25475
|
+
tmp2 = ps[13];
|
|
25476
|
+
tmp3 = ps[14];
|
|
25477
|
+
tmp4 = ps[15];
|
|
25478
|
+
ps[12] = tmp4;
|
|
25479
|
+
ps[13] = pi + 0;
|
|
25480
|
+
ps[14] = pi + 1;
|
|
25481
|
+
ps[15] = pi + 2;
|
|
25482
|
+
ps[8] = tmp3;
|
|
25483
|
+
ps[11] = pi + 3;
|
|
25484
|
+
ps[4] = tmp2;
|
|
25485
|
+
ps[7] = pi + 4;
|
|
25486
|
+
ps[0] = tmp1;
|
|
25487
|
+
ps[1] = pi + 7;
|
|
25488
|
+
ps[2] = pi + 6;
|
|
25489
|
+
ps[3] = pi + 5;
|
|
25490
|
+
tmp1 = cs[2];
|
|
25491
|
+
tmp2 = cs[3];
|
|
25492
|
+
cs[2] = tmp2;
|
|
25493
|
+
cs[3] = ci;
|
|
25494
|
+
cs[0] = tmp1;
|
|
25495
|
+
cs[1] = ci + 1;
|
|
25496
|
+
break;
|
|
25497
|
+
// prettier-ignore
|
|
25498
|
+
case 2:
|
|
25499
|
+
tmp1 = ps[15];
|
|
25500
|
+
tmp2 = ps[11];
|
|
25501
|
+
ps[12] = ps[3];
|
|
25502
|
+
ps[13] = pi + 0;
|
|
25503
|
+
ps[14] = pi + 1;
|
|
25504
|
+
ps[15] = pi + 2;
|
|
25505
|
+
ps[8] = ps[7];
|
|
25506
|
+
ps[11] = pi + 3;
|
|
25507
|
+
ps[4] = tmp2;
|
|
25508
|
+
ps[7] = pi + 4;
|
|
25509
|
+
ps[0] = tmp1;
|
|
25510
|
+
ps[1] = pi + 7;
|
|
25511
|
+
ps[2] = pi + 6;
|
|
25512
|
+
ps[3] = pi + 5;
|
|
25513
|
+
tmp1 = cs[3];
|
|
25514
|
+
cs[2] = cs[1];
|
|
25515
|
+
cs[3] = ci;
|
|
25516
|
+
cs[0] = tmp1;
|
|
25517
|
+
cs[1] = ci + 1;
|
|
25518
|
+
break;
|
|
25519
|
+
// prettier-ignore
|
|
25520
|
+
case 3:
|
|
25521
|
+
ps[12] = ps[0];
|
|
25522
|
+
ps[13] = pi + 0;
|
|
25523
|
+
ps[14] = pi + 1;
|
|
25524
|
+
ps[15] = pi + 2;
|
|
25525
|
+
ps[8] = ps[1];
|
|
25526
|
+
ps[11] = pi + 3;
|
|
25527
|
+
ps[4] = ps[2];
|
|
25528
|
+
ps[7] = pi + 4;
|
|
25529
|
+
ps[0] = ps[3];
|
|
25530
|
+
ps[1] = pi + 7;
|
|
25531
|
+
ps[2] = pi + 6;
|
|
25532
|
+
ps[3] = pi + 5;
|
|
25533
|
+
cs[2] = cs[0];
|
|
25534
|
+
cs[3] = ci;
|
|
25535
|
+
cs[0] = cs[1];
|
|
25536
|
+
cs[1] = ci + 1;
|
|
25537
|
+
break;
|
|
25538
|
+
}
|
|
25539
|
+
ps[5] = coords.length;
|
|
25540
|
+
coords.push([
|
|
25541
|
+
(-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,
|
|
25542
|
+
(-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
|
|
25543
|
+
]);
|
|
25544
|
+
ps[6] = coords.length;
|
|
25545
|
+
coords.push([
|
|
25546
|
+
(-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,
|
|
25547
|
+
(-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
|
|
25548
|
+
]);
|
|
25549
|
+
ps[9] = coords.length;
|
|
25550
|
+
coords.push([
|
|
25551
|
+
(-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,
|
|
25552
|
+
(-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
|
|
25553
|
+
]);
|
|
25554
|
+
ps[10] = coords.length;
|
|
25555
|
+
coords.push([
|
|
25556
|
+
(-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,
|
|
25557
|
+
(-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
|
|
25558
|
+
]);
|
|
25559
|
+
this.figures.push({
|
|
25560
|
+
type: MeshFigureType.PATCH,
|
|
25561
|
+
coords: new Int32Array(ps),
|
|
25562
|
+
// making copies of ps and cs
|
|
25563
|
+
colors: new Int32Array(cs)
|
|
25564
|
+
});
|
|
25565
|
+
}
|
|
25566
|
+
}
|
|
25567
|
+
_decodeType7Shading(reader) {
|
|
25568
|
+
const coords = this.coords;
|
|
25569
|
+
const colors = this.colors;
|
|
25570
|
+
const ps = new Int32Array(16);
|
|
25571
|
+
const cs = new Int32Array(4);
|
|
25572
|
+
while (reader.hasData) {
|
|
25573
|
+
const f = reader.readFlag();
|
|
25574
|
+
if (!(0 <= f && f <= 3)) {
|
|
25575
|
+
throw new FormatError("Unknown type7 flag");
|
|
25576
|
+
}
|
|
25577
|
+
const pi = coords.length;
|
|
25578
|
+
for (let i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) {
|
|
25579
|
+
coords.push(reader.readCoordinate());
|
|
25580
|
+
}
|
|
25581
|
+
const ci = colors.length;
|
|
25582
|
+
for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
|
|
25583
|
+
colors.push(reader.readComponents());
|
|
25584
|
+
}
|
|
25585
|
+
let tmp1, tmp2, tmp3, tmp4;
|
|
25586
|
+
switch (f) {
|
|
25587
|
+
// prettier-ignore
|
|
25588
|
+
case 0:
|
|
25589
|
+
ps[12] = pi + 3;
|
|
25590
|
+
ps[13] = pi + 4;
|
|
25591
|
+
ps[14] = pi + 5;
|
|
25592
|
+
ps[15] = pi + 6;
|
|
25593
|
+
ps[8] = pi + 2;
|
|
25594
|
+
ps[9] = pi + 13;
|
|
25595
|
+
ps[10] = pi + 14;
|
|
25596
|
+
ps[11] = pi + 7;
|
|
25597
|
+
ps[4] = pi + 1;
|
|
25598
|
+
ps[5] = pi + 12;
|
|
25599
|
+
ps[6] = pi + 15;
|
|
25600
|
+
ps[7] = pi + 8;
|
|
25601
|
+
ps[0] = pi;
|
|
25602
|
+
ps[1] = pi + 11;
|
|
25603
|
+
ps[2] = pi + 10;
|
|
25604
|
+
ps[3] = pi + 9;
|
|
25605
|
+
cs[2] = ci + 1;
|
|
25606
|
+
cs[3] = ci + 2;
|
|
25607
|
+
cs[0] = ci;
|
|
25608
|
+
cs[1] = ci + 3;
|
|
25609
|
+
break;
|
|
25610
|
+
// prettier-ignore
|
|
25611
|
+
case 1:
|
|
25612
|
+
tmp1 = ps[12];
|
|
25613
|
+
tmp2 = ps[13];
|
|
25614
|
+
tmp3 = ps[14];
|
|
25615
|
+
tmp4 = ps[15];
|
|
25616
|
+
ps[12] = tmp4;
|
|
25617
|
+
ps[13] = pi + 0;
|
|
25618
|
+
ps[14] = pi + 1;
|
|
25619
|
+
ps[15] = pi + 2;
|
|
25620
|
+
ps[8] = tmp3;
|
|
25621
|
+
ps[9] = pi + 9;
|
|
25622
|
+
ps[10] = pi + 10;
|
|
25623
|
+
ps[11] = pi + 3;
|
|
25624
|
+
ps[4] = tmp2;
|
|
25625
|
+
ps[5] = pi + 8;
|
|
25626
|
+
ps[6] = pi + 11;
|
|
25627
|
+
ps[7] = pi + 4;
|
|
25628
|
+
ps[0] = tmp1;
|
|
25629
|
+
ps[1] = pi + 7;
|
|
25630
|
+
ps[2] = pi + 6;
|
|
25631
|
+
ps[3] = pi + 5;
|
|
25632
|
+
tmp1 = cs[2];
|
|
25633
|
+
tmp2 = cs[3];
|
|
25634
|
+
cs[2] = tmp2;
|
|
25635
|
+
cs[3] = ci;
|
|
25636
|
+
cs[0] = tmp1;
|
|
25637
|
+
cs[1] = ci + 1;
|
|
25638
|
+
break;
|
|
25639
|
+
// prettier-ignore
|
|
25640
|
+
case 2:
|
|
25641
|
+
tmp1 = ps[15];
|
|
25642
|
+
tmp2 = ps[11];
|
|
25643
|
+
ps[12] = ps[3];
|
|
25644
|
+
ps[13] = pi + 0;
|
|
25645
|
+
ps[14] = pi + 1;
|
|
25646
|
+
ps[15] = pi + 2;
|
|
25647
|
+
ps[8] = ps[7];
|
|
25648
|
+
ps[9] = pi + 9;
|
|
25649
|
+
ps[10] = pi + 10;
|
|
25650
|
+
ps[11] = pi + 3;
|
|
25651
|
+
ps[4] = tmp2;
|
|
25652
|
+
ps[5] = pi + 8;
|
|
25653
|
+
ps[6] = pi + 11;
|
|
25654
|
+
ps[7] = pi + 4;
|
|
25655
|
+
ps[0] = tmp1;
|
|
25656
|
+
ps[1] = pi + 7;
|
|
25657
|
+
ps[2] = pi + 6;
|
|
25658
|
+
ps[3] = pi + 5;
|
|
25659
|
+
tmp1 = cs[3];
|
|
25660
|
+
cs[2] = cs[1];
|
|
25661
|
+
cs[3] = ci;
|
|
25662
|
+
cs[0] = tmp1;
|
|
25663
|
+
cs[1] = ci + 1;
|
|
25664
|
+
break;
|
|
25665
|
+
// prettier-ignore
|
|
25666
|
+
case 3:
|
|
25667
|
+
ps[12] = ps[0];
|
|
25668
|
+
ps[13] = pi + 0;
|
|
25669
|
+
ps[14] = pi + 1;
|
|
25670
|
+
ps[15] = pi + 2;
|
|
25671
|
+
ps[8] = ps[1];
|
|
25672
|
+
ps[9] = pi + 9;
|
|
25673
|
+
ps[10] = pi + 10;
|
|
25674
|
+
ps[11] = pi + 3;
|
|
25675
|
+
ps[4] = ps[2];
|
|
25676
|
+
ps[5] = pi + 8;
|
|
25677
|
+
ps[6] = pi + 11;
|
|
25678
|
+
ps[7] = pi + 4;
|
|
25679
|
+
ps[0] = ps[3];
|
|
25680
|
+
ps[1] = pi + 7;
|
|
25681
|
+
ps[2] = pi + 6;
|
|
25682
|
+
ps[3] = pi + 5;
|
|
25683
|
+
cs[2] = cs[0];
|
|
25684
|
+
cs[3] = ci;
|
|
25685
|
+
cs[0] = cs[1];
|
|
25686
|
+
cs[1] = ci + 1;
|
|
25687
|
+
break;
|
|
25688
|
+
}
|
|
25689
|
+
this.figures.push({
|
|
25690
|
+
type: MeshFigureType.PATCH,
|
|
25691
|
+
coords: new Int32Array(ps),
|
|
25692
|
+
// making copies of ps and cs
|
|
25693
|
+
colors: new Int32Array(cs)
|
|
25694
|
+
});
|
|
25695
|
+
}
|
|
25696
|
+
}
|
|
25697
|
+
_buildFigureFromPatch(index) {
|
|
25698
|
+
const figure = this.figures[index];
|
|
25699
|
+
assert2(
|
|
25700
|
+
figure.type === MeshFigureType.PATCH,
|
|
25701
|
+
"Unexpected patch mesh figure"
|
|
25702
|
+
);
|
|
25703
|
+
const coords = this.coords, colors = this.colors;
|
|
25704
|
+
const pi = figure.coords;
|
|
25705
|
+
const ci = figure.colors;
|
|
25706
|
+
const figureMinX = Math.min(
|
|
25707
|
+
coords[pi[0]][0],
|
|
25708
|
+
coords[pi[3]][0],
|
|
25709
|
+
coords[pi[12]][0],
|
|
25710
|
+
coords[pi[15]][0]
|
|
25711
|
+
);
|
|
25712
|
+
const figureMinY = Math.min(
|
|
25713
|
+
coords[pi[0]][1],
|
|
25714
|
+
coords[pi[3]][1],
|
|
25715
|
+
coords[pi[12]][1],
|
|
25716
|
+
coords[pi[15]][1]
|
|
25717
|
+
);
|
|
25718
|
+
const figureMaxX = Math.max(
|
|
25719
|
+
coords[pi[0]][0],
|
|
25720
|
+
coords[pi[3]][0],
|
|
25721
|
+
coords[pi[12]][0],
|
|
25722
|
+
coords[pi[15]][0]
|
|
25723
|
+
);
|
|
25724
|
+
const figureMaxY = Math.max(
|
|
25725
|
+
coords[pi[0]][1],
|
|
25726
|
+
coords[pi[3]][1],
|
|
25727
|
+
coords[pi[12]][1],
|
|
25728
|
+
coords[pi[15]][1]
|
|
25729
|
+
);
|
|
25730
|
+
let splitXBy = Math.ceil(
|
|
25731
|
+
(figureMaxX - figureMinX) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[2] - this.bounds[0])
|
|
25732
|
+
);
|
|
25733
|
+
splitXBy = MathClamp(
|
|
25734
|
+
splitXBy,
|
|
25735
|
+
_MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
|
|
25736
|
+
_MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT
|
|
25737
|
+
);
|
|
25738
|
+
let splitYBy = Math.ceil(
|
|
25739
|
+
(figureMaxY - figureMinY) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[3] - this.bounds[1])
|
|
25740
|
+
);
|
|
25741
|
+
splitYBy = MathClamp(
|
|
25742
|
+
splitYBy,
|
|
25743
|
+
_MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
|
|
25744
|
+
_MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT
|
|
25745
|
+
);
|
|
25746
|
+
const verticesPerRow = splitXBy + 1;
|
|
25747
|
+
const figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
|
|
25748
|
+
const figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
|
|
25749
|
+
let k = 0;
|
|
25750
|
+
const cl = new Uint8Array(3), cr = new Uint8Array(3);
|
|
25751
|
+
const c0 = colors[ci[0]], c1 = colors[ci[1]], c2 = colors[ci[2]], c3 = colors[ci[3]];
|
|
25752
|
+
const bRow = getB(splitYBy), bCol = getB(splitXBy);
|
|
25753
|
+
for (let row = 0; row <= splitYBy; row++) {
|
|
25754
|
+
cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0;
|
|
25755
|
+
cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0;
|
|
25756
|
+
cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0;
|
|
25757
|
+
cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0;
|
|
25758
|
+
cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0;
|
|
25759
|
+
cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0;
|
|
25760
|
+
for (let col = 0; col <= splitXBy; col++, k++) {
|
|
25761
|
+
if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) {
|
|
25762
|
+
continue;
|
|
25763
|
+
}
|
|
25764
|
+
let x = 0, y = 0;
|
|
25765
|
+
let q = 0;
|
|
25766
|
+
for (let i = 0; i <= 3; i++) {
|
|
25767
|
+
for (let j = 0; j <= 3; j++, q++) {
|
|
25768
|
+
const m = bRow[row][i] * bCol[col][j];
|
|
25769
|
+
x += coords[pi[q]][0] * m;
|
|
25770
|
+
y += coords[pi[q]][1] * m;
|
|
25771
|
+
}
|
|
25772
|
+
}
|
|
25773
|
+
figureCoords[k] = coords.length;
|
|
25774
|
+
coords.push([x, y]);
|
|
25775
|
+
figureColors[k] = colors.length;
|
|
25776
|
+
const newColor = new Uint8Array(3);
|
|
25777
|
+
newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0;
|
|
25778
|
+
newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0;
|
|
25779
|
+
newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0;
|
|
25780
|
+
colors.push(newColor);
|
|
25781
|
+
}
|
|
25782
|
+
}
|
|
25783
|
+
figureCoords[0] = pi[0];
|
|
25784
|
+
figureColors[0] = ci[0];
|
|
25785
|
+
figureCoords[splitXBy] = pi[3];
|
|
25786
|
+
figureColors[splitXBy] = ci[1];
|
|
25787
|
+
figureCoords[verticesPerRow * splitYBy] = pi[12];
|
|
25788
|
+
figureColors[verticesPerRow * splitYBy] = ci[2];
|
|
25789
|
+
figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15];
|
|
25790
|
+
figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
|
|
25791
|
+
this.figures[index] = {
|
|
25792
|
+
type: MeshFigureType.LATTICE,
|
|
25793
|
+
coords: figureCoords,
|
|
25794
|
+
colors: figureColors,
|
|
25795
|
+
verticesPerRow
|
|
25796
|
+
};
|
|
25797
|
+
}
|
|
25798
|
+
_updateBounds() {
|
|
25799
|
+
meshUpdateBounds(this);
|
|
25800
|
+
}
|
|
25801
|
+
_packData() {
|
|
25802
|
+
meshPackData(this);
|
|
25803
|
+
}
|
|
25804
|
+
getIR() {
|
|
25805
|
+
const { posData, colData, vertexCount } = buildMeshVertexData(
|
|
25806
|
+
this.coords,
|
|
25807
|
+
this.colors,
|
|
25808
|
+
this.figures
|
|
25809
|
+
);
|
|
25810
|
+
return [
|
|
25811
|
+
"Mesh",
|
|
25812
|
+
this.shadingType,
|
|
25813
|
+
posData,
|
|
25814
|
+
colData,
|
|
25815
|
+
vertexCount,
|
|
25816
|
+
this.bounds,
|
|
25817
|
+
this.bbox,
|
|
25818
|
+
this.background
|
|
25819
|
+
];
|
|
25820
|
+
}
|
|
25821
|
+
};
|
|
22515
25822
|
var PdfError = class extends Error {
|
|
22516
25823
|
constructor(code, message) {
|
|
22517
25824
|
super(message);
|
|
@@ -25417,11 +28724,16 @@ function parseDictionaryStream(dictNode, lexer, bytes) {
|
|
|
25417
28724
|
let streamEnd = streamStart;
|
|
25418
28725
|
if (resolvedLength !== void 0 && resolvedLength >= 0 && streamStart + resolvedLength <= bytes.length) {
|
|
25419
28726
|
const candidateEnd = streamStart + resolvedLength;
|
|
25420
|
-
const
|
|
25421
|
-
|
|
25422
|
-
|
|
28727
|
+
const tailLexer = new CosByteLexer(bytes, candidateEnd);
|
|
28728
|
+
let endToken;
|
|
28729
|
+
try {
|
|
28730
|
+
endToken = tailLexer.nextToken();
|
|
28731
|
+
} catch (error) {
|
|
28732
|
+
if (!(error instanceof PdfError) || error.code !== "E_PARSE") throw error;
|
|
28733
|
+
}
|
|
28734
|
+
if (endToken?.kind === "keyword" && endToken.value === "endstream") {
|
|
25423
28735
|
rawStreamBytes = bytes.subarray(streamStart, candidateEnd);
|
|
25424
|
-
streamEnd =
|
|
28736
|
+
streamEnd = tailLexer.offset;
|
|
25425
28737
|
}
|
|
25426
28738
|
}
|
|
25427
28739
|
if (!rawStreamBytes) {
|
|
@@ -33591,6 +36903,25 @@ var __webpack_exports__JpxImage = __webpack_exports__.JpxImage;
|
|
|
33591
36903
|
var __webpack_exports__VerbosityLevel = __webpack_exports__.VerbosityLevel;
|
|
33592
36904
|
var __webpack_exports__getVerbosityLevel = __webpack_exports__.getVerbosityLevel;
|
|
33593
36905
|
var __webpack_exports__setVerbosityLevel = __webpack_exports__.setVerbosityLevel;
|
|
36906
|
+
function createCalibratedColorSpace(doc, family, parameters) {
|
|
36907
|
+
const dict = doc.resolveDict(parameters);
|
|
36908
|
+
const array = (key) => {
|
|
36909
|
+
const value = dict ? doc.resolveArray(dictGet(dict, key)) : void 0;
|
|
36910
|
+
return value?.items.map((item) => {
|
|
36911
|
+
const number = doc.resolve(item);
|
|
36912
|
+
return number?.kind === "number" ? number.value : 0;
|
|
36913
|
+
});
|
|
36914
|
+
};
|
|
36915
|
+
const whitePoint = array("WhitePoint") ?? [0.95047, 1, 1.08883];
|
|
36916
|
+
const blackPoint = array("BlackPoint");
|
|
36917
|
+
if (family === "CalGray") {
|
|
36918
|
+
const gamma = dict ? doc.resolve(dictGet(dict, "Gamma")) : void 0;
|
|
36919
|
+
return new CalGrayCS(whitePoint, blackPoint, gamma?.kind === "number" ? gamma.value : void 0);
|
|
36920
|
+
}
|
|
36921
|
+
if (family === "CalRGB") return new CalRGBCS(whitePoint, blackPoint, array("Gamma"), array("Matrix"));
|
|
36922
|
+
return new LabCS(whitePoint, blackPoint, array("Range"));
|
|
36923
|
+
}
|
|
36924
|
+
var cmykColorSpace = new DeviceCmykCS();
|
|
33594
36925
|
function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
33595
36926
|
if (!csNode) return { colorSpace: "rgb", colorSpaceLabel: "rgb", components: 3 };
|
|
33596
36927
|
const resolved = doc.resolve(csNode);
|
|
@@ -33631,7 +36962,7 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
|
33631
36962
|
palette = lookupNode.bytes;
|
|
33632
36963
|
}
|
|
33633
36964
|
let resolvedBaseComp = baseInfo.components;
|
|
33634
|
-
if (palette && (baseInfo.
|
|
36965
|
+
if (palette && (baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calibrated !== void 0)) {
|
|
33635
36966
|
const numEntries = Math.max(1, Math.min(hival + 1, Math.floor(palette.length / Math.max(1, baseInfo.components))));
|
|
33636
36967
|
const rgbaPal = decodeSamplesToRgba(palette, numEntries, 1, 8, baseInfo);
|
|
33637
36968
|
const rgbPal = new Uint8Array(numEntries * 3);
|
|
@@ -33661,74 +36992,21 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
|
33661
36992
|
}
|
|
33662
36993
|
return { colorSpace: "rgb", colorSpaceLabel: "icc", components: 3 };
|
|
33663
36994
|
}
|
|
33664
|
-
if (kindName === "CalGray") {
|
|
33665
|
-
const
|
|
33666
|
-
const gammaNode = calDict ? doc.resolve(dictGet(calDict, "Gamma")) : void 0;
|
|
33667
|
-
const gamma = gammaNode?.kind === "number" && gammaNode.value > 0 ? gammaNode.value : 1;
|
|
33668
|
-
return { colorSpace: "gray", colorSpaceLabel: "cal-gray", components: 1, calGrayGamma: gamma };
|
|
33669
|
-
}
|
|
33670
|
-
if (kindName === "CalRGB") {
|
|
33671
|
-
const calDict = doc.resolveDict(resolved.items[1]);
|
|
33672
|
-
const gammaArr = calDict ? doc.resolveArray(dictGet(calDict, "Gamma")) : void 0;
|
|
33673
|
-
let calRgbGamma = [1, 1, 1];
|
|
33674
|
-
if (gammaArr && gammaArr.items.length >= 3) {
|
|
33675
|
-
const gNums = gammaArr.items.slice(0, 3).map((it) => {
|
|
33676
|
-
const r = doc.resolve(it);
|
|
33677
|
-
return r?.kind === "number" && r.value > 0 ? r.value : 1;
|
|
33678
|
-
});
|
|
33679
|
-
calRgbGamma = [gNums[0], gNums[1], gNums[2]];
|
|
33680
|
-
}
|
|
33681
|
-
const matArr = calDict ? doc.resolveArray(dictGet(calDict, "Matrix")) : void 0;
|
|
33682
|
-
let calRgbMatrix;
|
|
33683
|
-
if (matArr && matArr.items.length >= 9) {
|
|
33684
|
-
calRgbMatrix = matArr.items.slice(0, 9).map((it) => {
|
|
33685
|
-
const r = doc.resolve(it);
|
|
33686
|
-
return r?.kind === "number" ? r.value : 0;
|
|
33687
|
-
});
|
|
33688
|
-
}
|
|
36995
|
+
if (kindName === "CalGray" || kindName === "CalRGB" || kindName === "Lab") {
|
|
36996
|
+
const calibrated = createCalibratedColorSpace(doc, kindName, resolved.items[1]);
|
|
33689
36997
|
return {
|
|
33690
|
-
colorSpace: "rgb",
|
|
33691
|
-
colorSpaceLabel: "cal-rgb",
|
|
33692
|
-
components: 3,
|
|
33693
|
-
|
|
33694
|
-
calRgbMatrix
|
|
36998
|
+
colorSpace: kindName === "CalGray" ? "gray" : "rgb",
|
|
36999
|
+
colorSpaceLabel: kindName === "CalGray" ? "cal-gray" : kindName === "CalRGB" ? "cal-rgb" : "lab",
|
|
37000
|
+
components: kindName === "CalGray" ? 1 : 3,
|
|
37001
|
+
calibrated
|
|
33695
37002
|
};
|
|
33696
37003
|
}
|
|
33697
|
-
if (kindName === "Lab") {
|
|
33698
|
-
const labDict = doc.resolveDict(resolved.items[1]);
|
|
33699
|
-
const rangeArr = labDict ? doc.resolveArray(dictGet(labDict, "Range")) : void 0;
|
|
33700
|
-
let labRange = [-100, 100, -100, 100];
|
|
33701
|
-
if (rangeArr && rangeArr.items.length >= 4) {
|
|
33702
|
-
const nums = rangeArr.items.slice(0, 4).map((it) => {
|
|
33703
|
-
const r = doc.resolve(it);
|
|
33704
|
-
return r?.kind === "number" ? r.value : 0;
|
|
33705
|
-
});
|
|
33706
|
-
labRange = [nums[0], nums[1], nums[2], nums[3]];
|
|
33707
|
-
}
|
|
33708
|
-
return { colorSpace: "rgb", colorSpaceLabel: "lab", components: 3, isLab: true, labRange };
|
|
33709
|
-
}
|
|
33710
37004
|
if (kindName === "Separation" || kindName === "DeviceN") {
|
|
33711
37005
|
const isDevN = kindName === "DeviceN";
|
|
33712
37006
|
const namesArr = isDevN ? doc.resolveArray(resolved.items[1]) : void 0;
|
|
33713
37007
|
const devNComponents = isDevN && namesArr ? Math.max(1, namesArr.items.length) : 1;
|
|
33714
37008
|
const altInfo = resolveColorSpaceInfo(doc, resolved.items[2], resourcesDict);
|
|
33715
37009
|
const altSpace = altInfo.colorSpace === "cmyk" ? "cmyk" : altInfo.colorSpace === "gray" ? "gray" : "rgb";
|
|
33716
|
-
const fnResolved = doc.resolve(resolved.items[3]);
|
|
33717
|
-
const fnDict = fnResolved?.kind === "stream" ? fnResolved.dict : fnResolved?.kind === "dict" ? fnResolved : void 0;
|
|
33718
|
-
const ftNode = fnDict ? doc.resolve(dictGet(fnDict, "FunctionType")) : void 0;
|
|
33719
|
-
const tintFunctionType = ftNode?.kind === "number" ? ftNode.value : 2;
|
|
33720
|
-
const c0Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C0")) : void 0;
|
|
33721
|
-
const c1Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C1")) : void 0;
|
|
33722
|
-
const nNode = fnDict ? doc.resolve(dictGet(fnDict, "N")) : void 0;
|
|
33723
|
-
const c0 = c0Arr ? c0Arr.items.map((it) => {
|
|
33724
|
-
const r = doc.resolve(it);
|
|
33725
|
-
return r?.kind === "number" ? r.value : 0;
|
|
33726
|
-
}) : altSpace === "cmyk" ? [0, 0, 0, 0] : altSpace === "gray" ? [1] : [1, 1, 1];
|
|
33727
|
-
const c1 = c1Arr ? c1Arr.items.map((it) => {
|
|
33728
|
-
const r = doc.resolve(it);
|
|
33729
|
-
return r?.kind === "number" ? r.value : 0;
|
|
33730
|
-
}) : altSpace === "cmyk" ? [0, 0, 0, 1] : altSpace === "gray" ? [0] : [0, 0, 0];
|
|
33731
|
-
const sepN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
|
|
33732
37010
|
return {
|
|
33733
37011
|
colorSpace: altSpace,
|
|
33734
37012
|
colorSpaceLabel: isDevN ? "devn" : "sep",
|
|
@@ -33736,12 +37014,9 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
|
33736
37014
|
isSeparation: !isDevN,
|
|
33737
37015
|
isDeviceN: isDevN,
|
|
33738
37016
|
separationAltSpace: altSpace,
|
|
33739
|
-
|
|
33740
|
-
separationC1: c1,
|
|
33741
|
-
separationN: sepN,
|
|
37017
|
+
alternateCalibrated: altInfo.calibrated,
|
|
33742
37018
|
tintFunctionDoc: doc,
|
|
33743
|
-
tintFunctionNode: resolved.items[3]
|
|
33744
|
-
tintFunctionType
|
|
37019
|
+
tintFunctionNode: resolved.items[3]
|
|
33745
37020
|
};
|
|
33746
37021
|
}
|
|
33747
37022
|
}
|
|
@@ -33891,141 +37166,55 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
33891
37166
|
const rgba = new Uint8Array(width * height * 4);
|
|
33892
37167
|
const pixelCount = width * height;
|
|
33893
37168
|
if (csInfo.isSeparation || csInfo.isDeviceN) {
|
|
33894
|
-
const c0 = csInfo.separationC0 ?? [1, 1, 1];
|
|
33895
|
-
const c1 = csInfo.separationC1 ?? [0, 0, 0];
|
|
33896
|
-
const expN = csInfo.separationN ?? 1;
|
|
33897
37169
|
const alt = csInfo.separationAltSpace ?? "rgb";
|
|
33898
37170
|
const numCh = Math.max(1, csInfo.components);
|
|
33899
37171
|
const step = bpc === 16 ? 2 : 1;
|
|
33900
|
-
const useGenericTintFn = csInfo.tintFunctionDoc !== void 0 && csInfo.tintFunctionNode !== void 0 && (csInfo.tintFunctionType === 0 || csInfo.tintFunctionType === 3 || csInfo.tintFunctionType === 4);
|
|
33901
37172
|
for (let p = 0; p < pixelCount; p++) {
|
|
33902
37173
|
const chVals = [];
|
|
33903
|
-
let wSum = 0;
|
|
33904
37174
|
for (let ch3 = 0; ch3 < numCh; ch3++) {
|
|
33905
37175
|
const sRaw = (rawSamples[(p * numCh + ch3) * step] ?? 0) / 255;
|
|
33906
|
-
|
|
33907
|
-
chVals.push(tRemapped);
|
|
33908
|
-
wSum += Math.pow(Math.max(0, Math.min(1, tRemapped)), expN);
|
|
33909
|
-
}
|
|
33910
|
-
if (useGenericTintFn) {
|
|
33911
|
-
const outComps = evalShadingFunctionToComponents(
|
|
33912
|
-
csInfo.tintFunctionDoc,
|
|
33913
|
-
csInfo.tintFunctionNode,
|
|
33914
|
-
chVals
|
|
33915
|
-
);
|
|
33916
|
-
if (alt === "cmyk") {
|
|
33917
|
-
const c = outComps[0] ?? 0;
|
|
33918
|
-
const m = outComps[1] ?? 0;
|
|
33919
|
-
const y = outComps[2] ?? 0;
|
|
33920
|
-
const k = outComps[3] ?? 0;
|
|
33921
|
-
rgba[p * 4] = Math.round(Math.max(0, Math.min(1, (1 - c) * (1 - k))) * 255);
|
|
33922
|
-
rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, (1 - m) * (1 - k))) * 255);
|
|
33923
|
-
rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, (1 - y) * (1 - k))) * 255);
|
|
33924
|
-
} else if (alt === "gray") {
|
|
33925
|
-
const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
|
|
33926
|
-
rgba[p * 4] = gByte;
|
|
33927
|
-
rgba[p * 4 + 1] = gByte;
|
|
33928
|
-
rgba[p * 4 + 2] = gByte;
|
|
33929
|
-
} else {
|
|
33930
|
-
rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
|
|
33931
|
-
rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
|
|
33932
|
-
rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
|
|
33933
|
-
}
|
|
33934
|
-
rgba[p * 4 + 3] = 255;
|
|
33935
|
-
continue;
|
|
37176
|
+
chVals.push(remapUnitSampleWithDecode(sRaw, ch3, decodePairs));
|
|
33936
37177
|
}
|
|
33937
|
-
const
|
|
33938
|
-
|
|
33939
|
-
|
|
33940
|
-
|
|
33941
|
-
|
|
33942
|
-
|
|
33943
|
-
rgba
|
|
33944
|
-
|
|
33945
|
-
rgba[
|
|
37178
|
+
const outComps = evalShadingFunctionToComponents(
|
|
37179
|
+
csInfo.tintFunctionDoc,
|
|
37180
|
+
csInfo.tintFunctionNode,
|
|
37181
|
+
chVals
|
|
37182
|
+
);
|
|
37183
|
+
if (csInfo.alternateCalibrated) {
|
|
37184
|
+
rgba.set(csInfo.alternateCalibrated.getRgb(outComps, 0), p * 4);
|
|
37185
|
+
} else if (alt === "cmyk") {
|
|
37186
|
+
rgba.set(cmykColorSpace.getRgb([outComps[0] ?? 0, outComps[1] ?? 0, outComps[2] ?? 0, outComps[3] ?? 0], 0), p * 4);
|
|
33946
37187
|
} else if (alt === "gray") {
|
|
33947
|
-
const
|
|
33948
|
-
const gByte = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
|
|
37188
|
+
const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
|
|
33949
37189
|
rgba[p * 4] = gByte;
|
|
33950
37190
|
rgba[p * 4 + 1] = gByte;
|
|
33951
37191
|
rgba[p * 4 + 2] = gByte;
|
|
33952
37192
|
} else {
|
|
33953
|
-
|
|
33954
|
-
|
|
33955
|
-
|
|
33956
|
-
rgba[p * 4] = Math.round(Math.max(0, Math.min(1, rVal)) * 255);
|
|
33957
|
-
rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
|
|
33958
|
-
rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, bVal)) * 255);
|
|
37193
|
+
rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
|
|
37194
|
+
rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
|
|
37195
|
+
rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
|
|
33959
37196
|
}
|
|
33960
37197
|
rgba[p * 4 + 3] = 255;
|
|
33961
37198
|
}
|
|
33962
|
-
} else if (csInfo.
|
|
33963
|
-
const
|
|
33964
|
-
const
|
|
33965
|
-
const toSrgb = (u) => {
|
|
33966
|
-
const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
|
|
33967
|
-
return Math.round(Math.max(0, Math.min(1, c)) * 255);
|
|
33968
|
-
};
|
|
37199
|
+
} else if (csInfo.calibrated?.name === "Lab") {
|
|
37200
|
+
const { amin, amax, bmin, bmax } = csInfo.calibrated;
|
|
37201
|
+
const step = bpc === 16 ? 2 : 1;
|
|
33969
37202
|
for (let p = 0; p < pixelCount; p++) {
|
|
33970
|
-
const
|
|
33971
|
-
const
|
|
33972
|
-
const
|
|
33973
|
-
|
|
33974
|
-
if (L <= 0.01) {
|
|
33975
|
-
rgba[p * 4] = 0;
|
|
33976
|
-
rgba[p * 4 + 1] = 0;
|
|
33977
|
-
rgba[p * 4 + 2] = 0;
|
|
33978
|
-
rgba[p * 4 + 3] = 255;
|
|
33979
|
-
continue;
|
|
33980
|
-
}
|
|
33981
|
-
const a = amin + s1 * (amax - amin);
|
|
33982
|
-
const b = bmin + s2 * (bmax - bmin);
|
|
33983
|
-
const fy = (L + 16) / 116;
|
|
33984
|
-
const fx = fy + a / 500;
|
|
33985
|
-
const fz = fy - b / 200;
|
|
33986
|
-
const X = 0.95047 * invF(fx);
|
|
33987
|
-
const Y = 1 * invF(fy);
|
|
33988
|
-
const Z = 1.08883 * invF(fz);
|
|
33989
|
-
const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
|
|
33990
|
-
const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
|
|
33991
|
-
const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
|
|
33992
|
-
rgba[p * 4] = toSrgb(linR);
|
|
33993
|
-
rgba[p * 4 + 1] = toSrgb(linG);
|
|
33994
|
-
rgba[p * 4 + 2] = toSrgb(linB);
|
|
37203
|
+
const L = (rawSamples[p * 3 * step] ?? 0) / 255 * 100;
|
|
37204
|
+
const a = amin + (rawSamples[(p * 3 + 1) * step] ?? 128) / 255 * (amax - amin);
|
|
37205
|
+
const b = bmin + (rawSamples[(p * 3 + 2) * step] ?? 128) / 255 * (bmax - bmin);
|
|
37206
|
+
rgba.set(csInfo.calibrated.getRgb([L, a, b], 0), p * 4);
|
|
33995
37207
|
rgba[p * 4 + 3] = 255;
|
|
33996
37208
|
}
|
|
33997
37209
|
} else if (csInfo.colorSpace === "rgb") {
|
|
33998
|
-
const hasCalRgb = Boolean(csInfo.calRgbGamma || csInfo.calRgbMatrix);
|
|
33999
|
-
const toSrgbByte = (u) => {
|
|
34000
|
-
const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
|
|
34001
|
-
return Math.round(Math.max(0, Math.min(1, c)) * 255);
|
|
34002
|
-
};
|
|
34003
37210
|
const writeRgbPixel = (p, rByte, gByte, bByte) => {
|
|
34004
|
-
|
|
34005
|
-
|
|
34006
|
-
|
|
34007
|
-
if (
|
|
34008
|
-
|
|
34009
|
-
|
|
34010
|
-
|
|
34011
|
-
const cg = Math.pow(bU, gb);
|
|
34012
|
-
if (csInfo.calRgbMatrix && csInfo.calRgbMatrix.length >= 9) {
|
|
34013
|
-
const m = csInfo.calRgbMatrix;
|
|
34014
|
-
const X = m[0] * ag + m[3] * bg + m[6] * cg;
|
|
34015
|
-
const Y = m[1] * ag + m[4] * bg + m[7] * cg;
|
|
34016
|
-
const Z = m[2] * ag + m[5] * bg + m[8] * cg;
|
|
34017
|
-
const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
|
|
34018
|
-
const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
|
|
34019
|
-
const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
|
|
34020
|
-
rgba[p * 4] = toSrgbByte(linR);
|
|
34021
|
-
rgba[p * 4 + 1] = toSrgbByte(linG);
|
|
34022
|
-
rgba[p * 4 + 2] = toSrgbByte(linB);
|
|
34023
|
-
rgba[p * 4 + 3] = 255;
|
|
34024
|
-
return;
|
|
34025
|
-
}
|
|
34026
|
-
rU = ag;
|
|
34027
|
-
gU = bg;
|
|
34028
|
-
bU = cg;
|
|
37211
|
+
const rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
|
|
37212
|
+
const gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
|
|
37213
|
+
const bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
|
|
37214
|
+
if (csInfo.calibrated) {
|
|
37215
|
+
rgba.set(csInfo.calibrated.getRgb([rU, gU, bU], 0), p * 4);
|
|
37216
|
+
rgba[p * 4 + 3] = 255;
|
|
37217
|
+
return;
|
|
34029
37218
|
}
|
|
34030
37219
|
rgba[p * 4] = Math.round(rU * 255);
|
|
34031
37220
|
rgba[p * 4 + 1] = Math.round(gU * 255);
|
|
@@ -34045,10 +37234,11 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
34045
37234
|
}
|
|
34046
37235
|
} else if (csInfo.colorSpace === "gray") {
|
|
34047
37236
|
const writeGrayPixel = (p, gByte) => {
|
|
34048
|
-
|
|
34049
|
-
if (csInfo.
|
|
34050
|
-
|
|
34051
|
-
|
|
37237
|
+
const gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
|
|
37238
|
+
if (csInfo.calibrated) {
|
|
37239
|
+
rgba.set(csInfo.calibrated.getRgb([gU], 0), p * 4);
|
|
37240
|
+
rgba[p * 4 + 3] = 255;
|
|
37241
|
+
return;
|
|
34052
37242
|
}
|
|
34053
37243
|
const outG = Math.round(Math.max(0, Math.min(1, gU)) * 255);
|
|
34054
37244
|
rgba[p * 4] = outG;
|
|
@@ -34104,9 +37294,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
34104
37294
|
const m = remapUnitSampleWithDecode((rawSamples[p * stride + chStep] ?? 0) / 255, 1, decodePairs);
|
|
34105
37295
|
const y = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 2] ?? 0) / 255, 2, decodePairs);
|
|
34106
37296
|
const k = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 3] ?? 0) / 255, 3, decodePairs);
|
|
34107
|
-
rgba
|
|
34108
|
-
rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
|
|
34109
|
-
rgba[p * 4 + 2] = Math.round((1 - y) * (1 - k) * 255);
|
|
37297
|
+
rgba.set(cmykColorSpace.getRgb([c, m, y, k], 0), p * 4);
|
|
34110
37298
|
rgba[p * 4 + 3] = 255;
|
|
34111
37299
|
}
|
|
34112
37300
|
} else if (csInfo.colorSpace === "index") {
|
|
@@ -34144,9 +37332,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
34144
37332
|
const m = pal[idx * 4 + 1] / 255;
|
|
34145
37333
|
const yel = pal[idx * 4 + 2] / 255;
|
|
34146
37334
|
const k = pal[idx * 4 + 3] / 255;
|
|
34147
|
-
rgba
|
|
34148
|
-
rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
|
|
34149
|
-
rgba[p * 4 + 2] = Math.round((1 - yel) * (1 - k) * 255);
|
|
37335
|
+
rgba.set(cmykColorSpace.getRgb([c, m, yel, k], 0), p * 4);
|
|
34150
37336
|
} else {
|
|
34151
37337
|
rgba[p * 4] = pal[idx * baseComp];
|
|
34152
37338
|
rgba[p * 4 + 1] = pal[idx * baseComp + 1];
|
|
@@ -34401,6 +37587,7 @@ function decodeInlineImageNodeToRgba(doc, dict, rawData, activeRes, fillColor) {
|
|
|
34401
37587
|
});
|
|
34402
37588
|
return decodeXObjectImageToRgba(context, { kind: "stream", dict, rawBytes: rawData }, activeRes, fillColor);
|
|
34403
37589
|
}
|
|
37590
|
+
var cmykColorSpace2 = new DeviceCmykCS();
|
|
34404
37591
|
function multiplyMatrices(m1, m2) {
|
|
34405
37592
|
return [
|
|
34406
37593
|
m1[0] * m2[0] + m1[1] * m2[2],
|
|
@@ -34617,193 +37804,7 @@ function resolvePageFonts(doc, resourcesDict) {
|
|
|
34617
37804
|
}
|
|
34618
37805
|
return fonts;
|
|
34619
37806
|
}
|
|
34620
|
-
|
|
34621
|
-
const stack = [...initialStack];
|
|
34622
|
-
const runRange = (start, end) => {
|
|
34623
|
-
let i = start;
|
|
34624
|
-
while (i < end) {
|
|
34625
|
-
const tok = tokens[i];
|
|
34626
|
-
if (tok === "{") {
|
|
34627
|
-
let depth = 1;
|
|
34628
|
-
let j = i + 1;
|
|
34629
|
-
while (j < end && depth > 0) {
|
|
34630
|
-
if (tokens[j] === "{") depth++;
|
|
34631
|
-
else if (tokens[j] === "}") depth--;
|
|
34632
|
-
j++;
|
|
34633
|
-
}
|
|
34634
|
-
const blockStart = i + 1;
|
|
34635
|
-
const blockEnd = j - 1;
|
|
34636
|
-
if (j < end && tokens[j] === "{") {
|
|
34637
|
-
let depth2 = 1;
|
|
34638
|
-
let k = j + 1;
|
|
34639
|
-
while (k < end && depth2 > 0) {
|
|
34640
|
-
if (tokens[k] === "{") depth2++;
|
|
34641
|
-
else if (tokens[k] === "}") depth2--;
|
|
34642
|
-
k++;
|
|
34643
|
-
}
|
|
34644
|
-
if (k < end && tokens[k] === "ifelse") {
|
|
34645
|
-
const cond = stack.pop() ?? 0;
|
|
34646
|
-
if (cond !== 0) runRange(blockStart, blockEnd);
|
|
34647
|
-
else runRange(j + 1, k - 1);
|
|
34648
|
-
i = k + 1;
|
|
34649
|
-
continue;
|
|
34650
|
-
}
|
|
34651
|
-
}
|
|
34652
|
-
if (j < end && tokens[j] === "if") {
|
|
34653
|
-
const cond = stack.pop() ?? 0;
|
|
34654
|
-
if (cond !== 0) runRange(blockStart, blockEnd);
|
|
34655
|
-
i = j + 1;
|
|
34656
|
-
continue;
|
|
34657
|
-
}
|
|
34658
|
-
runRange(blockStart, blockEnd);
|
|
34659
|
-
i = j;
|
|
34660
|
-
continue;
|
|
34661
|
-
}
|
|
34662
|
-
if (tok === "}") {
|
|
34663
|
-
i++;
|
|
34664
|
-
continue;
|
|
34665
|
-
}
|
|
34666
|
-
const numVal2 = Number(tok);
|
|
34667
|
-
if (tok.length > 0 && !Number.isNaN(numVal2)) {
|
|
34668
|
-
stack.push(numVal2);
|
|
34669
|
-
} else if (tok === "true") {
|
|
34670
|
-
stack.push(1);
|
|
34671
|
-
} else if (tok === "false") {
|
|
34672
|
-
stack.push(0);
|
|
34673
|
-
} else if (tok === "add") {
|
|
34674
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34675
|
-
stack.push(a + b);
|
|
34676
|
-
} else if (tok === "sub") {
|
|
34677
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34678
|
-
stack.push(a - b);
|
|
34679
|
-
} else if (tok === "mul") {
|
|
34680
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34681
|
-
stack.push(a * b);
|
|
34682
|
-
} else if (tok === "div") {
|
|
34683
|
-
const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
|
|
34684
|
-
stack.push(Math.abs(b) > 1e-12 ? a / b : 0);
|
|
34685
|
-
} else if (tok === "idiv") {
|
|
34686
|
-
const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
|
|
34687
|
-
stack.push(Math.abs(b) > 1e-12 ? Math.trunc(a / b) : 0);
|
|
34688
|
-
} else if (tok === "mod") {
|
|
34689
|
-
const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
|
|
34690
|
-
stack.push(Math.abs(b) > 1e-12 ? a % b : 0);
|
|
34691
|
-
} else if (tok === "neg") {
|
|
34692
|
-
stack.push(-(stack.pop() ?? 0));
|
|
34693
|
-
} else if (tok === "abs") {
|
|
34694
|
-
stack.push(Math.abs(stack.pop() ?? 0));
|
|
34695
|
-
} else if (tok === "ceiling") {
|
|
34696
|
-
stack.push(Math.ceil(stack.pop() ?? 0));
|
|
34697
|
-
} else if (tok === "floor") {
|
|
34698
|
-
stack.push(Math.floor(stack.pop() ?? 0));
|
|
34699
|
-
} else if (tok === "round") {
|
|
34700
|
-
stack.push(Math.round(stack.pop() ?? 0));
|
|
34701
|
-
} else if (tok === "truncate" || tok === "cvi") {
|
|
34702
|
-
stack.push(Math.trunc(stack.pop() ?? 0));
|
|
34703
|
-
} else if (tok === "sqrt") {
|
|
34704
|
-
stack.push(Math.sqrt(Math.max(0, stack.pop() ?? 0)));
|
|
34705
|
-
} else if (tok === "sin") {
|
|
34706
|
-
stack.push(Math.sin((stack.pop() ?? 0) * Math.PI / 180));
|
|
34707
|
-
} else if (tok === "cos") {
|
|
34708
|
-
stack.push(Math.cos((stack.pop() ?? 0) * Math.PI / 180));
|
|
34709
|
-
} else if (tok === "atan") {
|
|
34710
|
-
const dx = stack.pop() ?? 1, dy = stack.pop() ?? 0;
|
|
34711
|
-
let deg = Math.atan2(dy, dx) * 180 / Math.PI;
|
|
34712
|
-
if (deg < 0) deg += 360;
|
|
34713
|
-
stack.push(deg);
|
|
34714
|
-
} else if (tok === "exp") {
|
|
34715
|
-
const exp = stack.pop() ?? 1, base = stack.pop() ?? 0;
|
|
34716
|
-
stack.push(Math.pow(base, exp));
|
|
34717
|
-
} else if (tok === "ln") {
|
|
34718
|
-
stack.push(Math.log(Math.max(1e-12, stack.pop() ?? 1)));
|
|
34719
|
-
} else if (tok === "log") {
|
|
34720
|
-
stack.push(Math.log10(Math.max(1e-12, stack.pop() ?? 1)));
|
|
34721
|
-
} else if (tok === "dup") {
|
|
34722
|
-
if (stack.length > 0) stack.push(stack[stack.length - 1]);
|
|
34723
|
-
} else if (tok === "exch") {
|
|
34724
|
-
if (stack.length >= 2) {
|
|
34725
|
-
const b = stack.pop(), a = stack.pop();
|
|
34726
|
-
stack.push(b, a);
|
|
34727
|
-
}
|
|
34728
|
-
} else if (tok === "pop") {
|
|
34729
|
-
stack.pop();
|
|
34730
|
-
} else if (tok === "copy") {
|
|
34731
|
-
const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
|
|
34732
|
-
const slice = stack.slice(Math.max(0, stack.length - n));
|
|
34733
|
-
stack.push(...slice);
|
|
34734
|
-
} else if (tok === "index") {
|
|
34735
|
-
const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
|
|
34736
|
-
const idx = stack.length - 1 - n;
|
|
34737
|
-
if (idx >= 0 && idx < stack.length) stack.push(stack[idx]);
|
|
34738
|
-
} else if (tok === "roll") {
|
|
34739
|
-
const jShift = Math.trunc(stack.pop() ?? 0);
|
|
34740
|
-
const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
|
|
34741
|
-
if (n > 0 && stack.length >= n) {
|
|
34742
|
-
const sub = stack.splice(stack.length - n, n);
|
|
34743
|
-
const modShift = (jShift % n + n) % n;
|
|
34744
|
-
const rolled = [...sub.slice(n - modShift), ...sub.slice(0, n - modShift)];
|
|
34745
|
-
stack.push(...rolled);
|
|
34746
|
-
}
|
|
34747
|
-
} else if (tok === "eq") {
|
|
34748
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34749
|
-
stack.push(Math.abs(a - b) < 1e-9 ? 1 : 0);
|
|
34750
|
-
} else if (tok === "ne") {
|
|
34751
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34752
|
-
stack.push(Math.abs(a - b) >= 1e-9 ? 1 : 0);
|
|
34753
|
-
} else if (tok === "gt") {
|
|
34754
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34755
|
-
stack.push(a > b ? 1 : 0);
|
|
34756
|
-
} else if (tok === "ge") {
|
|
34757
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34758
|
-
stack.push(a >= b ? 1 : 0);
|
|
34759
|
-
} else if (tok === "lt") {
|
|
34760
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34761
|
-
stack.push(a < b ? 1 : 0);
|
|
34762
|
-
} else if (tok === "le") {
|
|
34763
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34764
|
-
stack.push(a <= b ? 1 : 0);
|
|
34765
|
-
} else if (tok === "and") {
|
|
34766
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34767
|
-
stack.push(a !== 0 && b !== 0 ? 1 : 0);
|
|
34768
|
-
} else if (tok === "or") {
|
|
34769
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
34770
|
-
stack.push(a !== 0 || b !== 0 ? 1 : 0);
|
|
34771
|
-
} else if (tok === "not") {
|
|
34772
|
-
const a = stack.pop() ?? 0;
|
|
34773
|
-
stack.push(a === 0 ? 1 : 0);
|
|
34774
|
-
}
|
|
34775
|
-
i++;
|
|
34776
|
-
}
|
|
34777
|
-
};
|
|
34778
|
-
runRange(0, tokens.length);
|
|
34779
|
-
return stack;
|
|
34780
|
-
}
|
|
34781
|
-
function tokenizePostScriptCode(bytes) {
|
|
34782
|
-
const tokens = [];
|
|
34783
|
-
let cur = "";
|
|
34784
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
34785
|
-
const ch3 = String.fromCharCode(bytes[i]);
|
|
34786
|
-
if (ch3 === "{" || ch3 === "}") {
|
|
34787
|
-
if (cur.length > 0) {
|
|
34788
|
-
tokens.push(cur);
|
|
34789
|
-
cur = "";
|
|
34790
|
-
}
|
|
34791
|
-
tokens.push(ch3);
|
|
34792
|
-
} else if (ch3 === " " || ch3 === " " || ch3 === "\n" || ch3 === "\r") {
|
|
34793
|
-
if (cur.length > 0) {
|
|
34794
|
-
tokens.push(cur);
|
|
34795
|
-
cur = "";
|
|
34796
|
-
}
|
|
34797
|
-
} else {
|
|
34798
|
-
cur += ch3;
|
|
34799
|
-
}
|
|
34800
|
-
}
|
|
34801
|
-
if (cur.length > 0) tokens.push(cur);
|
|
34802
|
-
if (tokens[0] === "{" && tokens[tokens.length - 1] === "}") {
|
|
34803
|
-
return tokens.slice(1, -1);
|
|
34804
|
-
}
|
|
34805
|
-
return tokens;
|
|
34806
|
-
}
|
|
37807
|
+
var postScriptFunctions = /* @__PURE__ */ new WeakMap();
|
|
34807
37808
|
function evalShadingFunctionToComponents(doc, fnNode, inputs) {
|
|
34808
37809
|
const inArr = typeof inputs === "number" ? [inputs] : inputs;
|
|
34809
37810
|
const t = inArr[0] ?? 0;
|
|
@@ -34850,35 +37851,50 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
|
|
|
34850
37851
|
const decode = getNums("Decode", range);
|
|
34851
37852
|
const nOut = Math.max(1, Math.floor((decode.length || range.length || 6) / 2));
|
|
34852
37853
|
const mIn = Math.max(1, size.length);
|
|
34853
|
-
|
|
37854
|
+
const streamBytes = doc.decodeStream(resolved);
|
|
37855
|
+
let vertices = [{ index: 0, weight: 1 }];
|
|
34854
37856
|
let stride = 1;
|
|
34855
37857
|
for (let i = 0; i < mIn; i++) {
|
|
34856
37858
|
const d02 = dom[i * 2] ?? 0;
|
|
34857
37859
|
const d12 = dom[i * 2 + 1] ?? 1;
|
|
34858
|
-
const sMax = Math.max(
|
|
37860
|
+
const sMax = Math.max(0, (size[i] ?? 2) - 1);
|
|
34859
37861
|
const e0 = encode[i * 2] ?? 0;
|
|
34860
37862
|
const e1 = encode[i * 2 + 1] ?? sMax;
|
|
34861
37863
|
const x = Math.max(d02, Math.min(d12, inArr[i] ?? 0));
|
|
34862
|
-
const u =
|
|
34863
|
-
const
|
|
34864
|
-
|
|
37864
|
+
const u = d12 === d02 ? 0 : (x - d02) / (d12 - d02);
|
|
37865
|
+
const e = Math.max(0, Math.min(sMax, e0 + u * (e1 - e0)));
|
|
37866
|
+
const low = Math.floor(e), fraction = e - low;
|
|
37867
|
+
const next = [];
|
|
37868
|
+
for (const vertex of vertices) {
|
|
37869
|
+
const index = vertex.index + low * stride;
|
|
37870
|
+
if (index * nOut * bps < streamBytes.length * 8) next.push({ index, weight: vertex.weight * (1 - fraction) });
|
|
37871
|
+
if (fraction && (index + stride) * nOut * bps < streamBytes.length * 8) {
|
|
37872
|
+
next.push({ index: index + stride, weight: vertex.weight * fraction });
|
|
37873
|
+
}
|
|
37874
|
+
}
|
|
37875
|
+
vertices = next;
|
|
34865
37876
|
stride *= size[i] ?? 2;
|
|
34866
37877
|
}
|
|
34867
|
-
const
|
|
37878
|
+
const maxSample = 2 ** bps - 1;
|
|
37879
|
+
const readSample = (index) => {
|
|
37880
|
+
let bitOffset = index * bps, remaining = bps, value = 0;
|
|
37881
|
+
while (remaining > 0) {
|
|
37882
|
+
const bitInByte = bitOffset % 8;
|
|
37883
|
+
const take = Math.min(remaining, 8 - bitInByte);
|
|
37884
|
+
const byte = streamBytes[Math.floor(bitOffset / 8)] ?? 0;
|
|
37885
|
+
value = value * 2 ** take + (byte >> 8 - bitInByte - take & (1 << take) - 1);
|
|
37886
|
+
bitOffset += take;
|
|
37887
|
+
remaining -= take;
|
|
37888
|
+
}
|
|
37889
|
+
return value / maxSample;
|
|
37890
|
+
};
|
|
34868
37891
|
const out2 = [];
|
|
34869
|
-
const maxSample = bps === 16 ? 65535 : 255;
|
|
34870
37892
|
for (let j = 0; j < nOut; j++) {
|
|
34871
|
-
|
|
34872
|
-
|
|
34873
|
-
if (bps === 16) {
|
|
34874
|
-
rawVal = (streamBytes[sampleIdx * 2] ?? 0) << 8 | (streamBytes[sampleIdx * 2 + 1] ?? 0);
|
|
34875
|
-
} else {
|
|
34876
|
-
rawVal = streamBytes[sampleIdx] ?? 0;
|
|
34877
|
-
}
|
|
34878
|
-
const frac = rawVal / maxSample;
|
|
37893
|
+
let value = 0;
|
|
37894
|
+
for (const vertex of vertices) value += readSample(vertex.index * nOut + j) * vertex.weight;
|
|
34879
37895
|
const dec0 = decode[j * 2] ?? 0;
|
|
34880
37896
|
const dec1 = decode[j * 2 + 1] ?? 1;
|
|
34881
|
-
out2.push(dec0 +
|
|
37897
|
+
out2.push(dec0 + value * (dec1 - dec0));
|
|
34882
37898
|
}
|
|
34883
37899
|
return clampRange(out2);
|
|
34884
37900
|
}
|
|
@@ -34888,34 +37904,40 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
|
|
|
34888
37904
|
const d12 = dom[i * 2 + 1] ?? 1;
|
|
34889
37905
|
return Math.max(d02, Math.min(d12, v));
|
|
34890
37906
|
});
|
|
34891
|
-
const
|
|
34892
|
-
|
|
34893
|
-
|
|
37907
|
+
const source = bytesToString3(doc.decodeStream(resolved));
|
|
37908
|
+
let cached = postScriptFunctions.get(resolved);
|
|
37909
|
+
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])) {
|
|
37910
|
+
cached = { source, domain: dom, range, evaluate: buildPostScriptJsFunction(source, dom, range) };
|
|
37911
|
+
postScriptFunctions.set(resolved, cached);
|
|
37912
|
+
}
|
|
37913
|
+
const output = [];
|
|
37914
|
+
cached.evaluate(clampedInputs, 0, output, 0);
|
|
37915
|
+
return output;
|
|
34894
37916
|
}
|
|
34895
37917
|
if (ft === 3) {
|
|
34896
37918
|
const fnsArr = doc.resolveArray(dictGet(fnDict, "Functions"));
|
|
34897
37919
|
const bounds = getNums("Bounds", []);
|
|
34898
37920
|
const encode = getNums("Encode", []);
|
|
34899
37921
|
if (fnsArr && fnsArr.items.length > 0) {
|
|
37922
|
+
const input = Math.max(dom[0] ?? 0, Math.min(dom[1] ?? 1, t));
|
|
34900
37923
|
let segIdx = 0;
|
|
34901
|
-
while (segIdx < bounds.length &&
|
|
37924
|
+
while (segIdx < bounds.length && input >= bounds[segIdx]) segIdx++;
|
|
34902
37925
|
segIdx = Math.min(fnsArr.items.length - 1, segIdx);
|
|
34903
37926
|
const b0 = segIdx === 0 ? dom[0] ?? 0 : bounds[segIdx - 1];
|
|
34904
37927
|
const b1 = segIdx < bounds.length ? bounds[segIdx] : dom[1] ?? 1;
|
|
34905
37928
|
const e0 = encode[segIdx * 2] ?? 0;
|
|
34906
37929
|
const e1 = encode[segIdx * 2 + 1] ?? 1;
|
|
34907
|
-
const localT =
|
|
34908
|
-
return evalShadingFunctionToComponents(doc, fnsArr.items[segIdx],
|
|
37930
|
+
const localT = b1 !== b0 ? e0 + (input - b0) / (b1 - b0) * (e1 - e0) : e0;
|
|
37931
|
+
return clampRange(evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], localT));
|
|
34909
37932
|
}
|
|
34910
37933
|
}
|
|
34911
|
-
const c0 = getNums("C0", [0
|
|
34912
|
-
const c1 = getNums("C1", [1
|
|
37934
|
+
const c0 = getNums("C0", [0]);
|
|
37935
|
+
const c1 = getNums("C1", [1]);
|
|
34913
37936
|
const nNode = doc.resolve(dictGet(fnDict, "N"));
|
|
34914
|
-
const expN = nNode?.kind === "number"
|
|
37937
|
+
const expN = nNode?.kind === "number" ? nNode.value : 1;
|
|
34915
37938
|
const d0 = dom[0] ?? 0;
|
|
34916
37939
|
const d1 = dom[1] ?? 1;
|
|
34917
|
-
const
|
|
34918
|
-
const w = Math.pow(Math.max(0, Math.min(1, normT)), expN);
|
|
37940
|
+
const w = Math.pow(Math.max(d0, Math.min(d1, t)), expN);
|
|
34919
37941
|
const len = Math.max(c0.length, c1.length);
|
|
34920
37942
|
const out = [];
|
|
34921
37943
|
for (let i = 0; i < len; i++) {
|
|
@@ -34931,30 +37953,14 @@ function shadingComponentsToRgb(csName, comps) {
|
|
|
34931
37953
|
return [v, v, v];
|
|
34932
37954
|
}
|
|
34933
37955
|
if (csName === "DeviceCMYK" || csName === "CMYK" || comps.length >= 4) {
|
|
34934
|
-
const
|
|
34935
|
-
return [
|
|
37956
|
+
const rgb2 = cmykColorSpace2.getRgb([comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0, comps[3] ?? 0], 0);
|
|
37957
|
+
return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
|
|
34936
37958
|
}
|
|
34937
37959
|
return [comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0];
|
|
34938
37960
|
}
|
|
34939
37961
|
function kClamp(v) {
|
|
34940
37962
|
return Math.max(0, Math.min(1, v));
|
|
34941
37963
|
}
|
|
34942
|
-
function xyzToSrgb(X, Y, Z, Xw = 0.95047, Yw = 1, Zw = 1.08883) {
|
|
34943
|
-
const scaleX = Xw > 1e-6 ? 0.95047 / Xw : 1;
|
|
34944
|
-
const scaleY = Yw > 1e-6 ? 1 / Yw : 1;
|
|
34945
|
-
const scaleZ = Zw > 1e-6 ? 1.08883 / Zw : 1;
|
|
34946
|
-
const x = X * scaleX;
|
|
34947
|
-
const y = Y * scaleY;
|
|
34948
|
-
const z = Z * scaleZ;
|
|
34949
|
-
const rl = 3.2404542 * x - 1.5371385 * y - 0.4985314 * z;
|
|
34950
|
-
const gl = -0.969266 * x + 1.8760108 * y + 0.041556 * z;
|
|
34951
|
-
const bl = 0.0556434 * x - 0.2040259 * y + 1.0572252 * z;
|
|
34952
|
-
const toGamma = (u) => {
|
|
34953
|
-
const c = Math.max(0, Math.min(1, u));
|
|
34954
|
-
return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
|
|
34955
|
-
};
|
|
34956
|
-
return [toGamma(rl), toGamma(gl), toGamma(bl)];
|
|
34957
|
-
}
|
|
34958
37964
|
function getColorSpaceComponentCount(doc, csNode, activeResources, depth = 0) {
|
|
34959
37965
|
if (!csNode || depth > 4) return 3;
|
|
34960
37966
|
const resolved = doc ? doc.resolve(csNode) : csNode;
|
|
@@ -35011,63 +38017,10 @@ function convertColorSpaceComponentsToRgb(doc, csNode, csNameFallback, comps, ac
|
|
|
35011
38017
|
if (resolved.kind === "array" && resolved.items.length > 0 && doc) {
|
|
35012
38018
|
const familyNode = doc.resolve(resolved.items[0]);
|
|
35013
38019
|
const family = familyNode?.kind === "name" ? familyNode.decoded : "";
|
|
35014
|
-
if (family === "CalGray") {
|
|
35015
|
-
const
|
|
35016
|
-
const
|
|
35017
|
-
|
|
35018
|
-
const a = Math.pow(kClamp(comps[0] ?? 0), gamma);
|
|
35019
|
-
return [a, a, a];
|
|
35020
|
-
}
|
|
35021
|
-
if (family === "CalRGB") {
|
|
35022
|
-
const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
|
|
35023
|
-
const gammaArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Gamma")) : void 0;
|
|
35024
|
-
const getArrNum = (arr, idx, fb) => {
|
|
35025
|
-
const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
|
|
35026
|
-
return r?.kind === "number" ? r.value : fb;
|
|
35027
|
-
};
|
|
35028
|
-
const gr = getArrNum(gammaArr, 0, 1);
|
|
35029
|
-
const gg = getArrNum(gammaArr, 1, 1);
|
|
35030
|
-
const gb = getArrNum(gammaArr, 2, 1);
|
|
35031
|
-
const ag = Math.pow(kClamp(comps[0] ?? 0), gr > 0 ? gr : 1);
|
|
35032
|
-
const bg = Math.pow(kClamp(comps[1] ?? 0), gg > 0 ? gg : 1);
|
|
35033
|
-
const cg = Math.pow(kClamp(comps[2] ?? 0), gb > 0 ? gb : 1);
|
|
35034
|
-
const matArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Matrix")) : void 0;
|
|
35035
|
-
if (matArr && matArr.items.length >= 9) {
|
|
35036
|
-
const m = (i) => getArrNum(matArr, i, 0);
|
|
35037
|
-
const X = m(0) * ag + m(3) * bg + m(6) * cg;
|
|
35038
|
-
const Y = m(1) * ag + m(4) * bg + m(7) * cg;
|
|
35039
|
-
const Z = m(2) * ag + m(5) * bg + m(8) * cg;
|
|
35040
|
-
const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
|
|
35041
|
-
const Xw = getArrNum(wpArr, 0, 0.95047);
|
|
35042
|
-
const Yw = getArrNum(wpArr, 1, 1);
|
|
35043
|
-
const Zw = getArrNum(wpArr, 2, 1.08883);
|
|
35044
|
-
return xyzToSrgb(X, Y, Z, Xw, Yw, Zw);
|
|
35045
|
-
}
|
|
35046
|
-
return [ag, bg, cg];
|
|
35047
|
-
}
|
|
35048
|
-
if (family === "Lab") {
|
|
35049
|
-
const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
|
|
35050
|
-
const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
|
|
35051
|
-
const rangeArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Range")) : void 0;
|
|
35052
|
-
const getNum = (arr, idx, fb) => {
|
|
35053
|
-
const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
|
|
35054
|
-
return r?.kind === "number" ? r.value : fb;
|
|
35055
|
-
};
|
|
35056
|
-
const Xw = getNum(wpArr, 0, 0.95047);
|
|
35057
|
-
const Yw = getNum(wpArr, 1, 1);
|
|
35058
|
-
const Zw = getNum(wpArr, 2, 1.08883);
|
|
35059
|
-
const amin = getNum(rangeArr, 0, -100);
|
|
35060
|
-
const amax = getNum(rangeArr, 1, 100);
|
|
35061
|
-
const bmin = getNum(rangeArr, 2, -100);
|
|
35062
|
-
const bmax = getNum(rangeArr, 3, 100);
|
|
35063
|
-
const Lstar = Math.max(0, Math.min(100, comps[0] ?? 0));
|
|
35064
|
-
const astar = Math.max(amin, Math.min(amax, comps[1] ?? 0));
|
|
35065
|
-
const bstar = Math.max(bmin, Math.min(bmax, comps[2] ?? 0));
|
|
35066
|
-
const M = (Lstar + 16) / 116;
|
|
35067
|
-
const L = M + astar / 500;
|
|
35068
|
-
const N = M - bstar / 200;
|
|
35069
|
-
const gFn = (x) => x >= 6 / 29 ? x * x * x : 108 / 841 * (x - 4 / 29);
|
|
35070
|
-
return xyzToSrgb(Xw * gFn(L), Yw * gFn(M), Zw * gFn(N), Xw, Yw, Zw);
|
|
38020
|
+
if (family === "CalGray" || family === "CalRGB" || family === "Lab") {
|
|
38021
|
+
const colorSpace = createCalibratedColorSpace(doc, family, resolved.items[1]);
|
|
38022
|
+
const rgb2 = colorSpace.getRgb(comps, 0);
|
|
38023
|
+
return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
|
|
35071
38024
|
}
|
|
35072
38025
|
if (family === "ICCBased" && resolved.items[1]) {
|
|
35073
38026
|
const iccNode = doc.resolve(resolved.items[1]);
|
|
@@ -35148,143 +38101,28 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
|
|
|
35148
38101
|
const r = doc.resolve(it);
|
|
35149
38102
|
return r?.kind === "number" ? r.value : 0;
|
|
35150
38103
|
});
|
|
35151
|
-
const xmin = decodeNums[0], xmax = decodeNums[1], ymin = decodeNums[2], ymax = decodeNums[3];
|
|
35152
|
-
const numColorParams = Math.max(1, Math.floor((decodeNums.length - 4) / 2));
|
|
35153
38104
|
const fnNode = dictGet(shDict, "Function");
|
|
35154
38105
|
const csNode = doc.resolve(dictGet(shDict, "ColorSpace"));
|
|
35155
38106
|
const csName = csNode?.kind === "name" ? csNode.decoded : "DeviceRGB";
|
|
35156
|
-
|
|
35157
|
-
const
|
|
35158
|
-
|
|
35159
|
-
|
|
35160
|
-
|
|
35161
|
-
|
|
35162
|
-
|
|
35163
|
-
|
|
35164
|
-
|
|
35165
|
-
|
|
35166
|
-
|
|
35167
|
-
|
|
35168
|
-
|
|
35169
|
-
|
|
35170
|
-
|
|
35171
|
-
|
|
35172
|
-
|
|
35173
|
-
|
|
35174
|
-
|
|
35175
|
-
};
|
|
35176
|
-
const readColorRgb = () => {
|
|
35177
|
-
const params = [];
|
|
35178
|
-
for (let c = 0; c < numColorParams; c++) {
|
|
35179
|
-
const rc = readBits(bpcComp) / compMax;
|
|
35180
|
-
const cMin = decodeNums[4 + c * 2] ?? 0;
|
|
35181
|
-
const cMax = decodeNums[4 + c * 2 + 1] ?? 1;
|
|
35182
|
-
params.push(cMin + rc * (cMax - cMin));
|
|
35183
|
-
}
|
|
35184
|
-
const comps = fnNode ? evalShadingFunctionToComponents(doc, fnNode, params) : params;
|
|
35185
|
-
return convertColorSpaceComponentsToRgb(doc, csNode, csName, comps);
|
|
35186
|
-
};
|
|
35187
|
-
const triangles = [];
|
|
35188
|
-
if (shType === 4) {
|
|
35189
|
-
const minBitsPerVert = bpcFlag + 2 * bpcCoord + numColorParams * bpcComp;
|
|
35190
|
-
let triVerts;
|
|
35191
|
-
while (bitPos + minBitsPerVert <= totalBits) {
|
|
35192
|
-
const flag = readBits(bpcFlag) & 3;
|
|
35193
|
-
const [x, y] = readCoord();
|
|
35194
|
-
const rgb2 = readColorRgb();
|
|
35195
|
-
const vNew = { x, y, rgb: rgb2 };
|
|
35196
|
-
if (flag === 0 || !triVerts) {
|
|
35197
|
-
if (bitPos + 2 * minBitsPerVert > totalBits) break;
|
|
35198
|
-
readBits(bpcFlag);
|
|
35199
|
-
const [x1, y1] = readCoord();
|
|
35200
|
-
const rgb1 = readColorRgb();
|
|
35201
|
-
readBits(bpcFlag);
|
|
35202
|
-
const [x2, y2] = readCoord();
|
|
35203
|
-
const rgb22 = readColorRgb();
|
|
35204
|
-
triVerts = [vNew, { x: x1, y: y1, rgb: rgb1 }, { x: x2, y: y2, rgb: rgb22 }];
|
|
35205
|
-
triangles.push(triVerts);
|
|
35206
|
-
} else if (flag === 1) {
|
|
35207
|
-
triVerts = [triVerts[1], triVerts[2], vNew];
|
|
35208
|
-
triangles.push(triVerts);
|
|
35209
|
-
} else if (flag === 2) {
|
|
35210
|
-
triVerts = [triVerts[0], triVerts[2], vNew];
|
|
35211
|
-
triangles.push(triVerts);
|
|
35212
|
-
}
|
|
35213
|
-
}
|
|
35214
|
-
} else if (shType === 5) {
|
|
35215
|
-
const minBitsPerVert = 2 * bpcCoord + numColorParams * bpcComp;
|
|
35216
|
-
const verts = [];
|
|
35217
|
-
while (bitPos + minBitsPerVert <= totalBits) {
|
|
35218
|
-
const [x, y] = readCoord();
|
|
35219
|
-
const rgb2 = readColorRgb();
|
|
35220
|
-
verts.push({ x, y, rgb: rgb2 });
|
|
35221
|
-
}
|
|
35222
|
-
const numRows = Math.floor(verts.length / vPerRow);
|
|
35223
|
-
for (let r = 0; r + 1 < numRows; r++) {
|
|
35224
|
-
for (let c = 0; c + 1 < vPerRow; c++) {
|
|
35225
|
-
const v00 = verts[r * vPerRow + c];
|
|
35226
|
-
const v01 = verts[r * vPerRow + c + 1];
|
|
35227
|
-
const v11 = verts[(r + 1) * vPerRow + c + 1];
|
|
35228
|
-
const v10 = verts[(r + 1) * vPerRow + c];
|
|
35229
|
-
triangles.push([v00, v01, v11], [v00, v11, v10]);
|
|
35230
|
-
}
|
|
35231
|
-
}
|
|
35232
|
-
} else if (shType === 6 || shType === 7) {
|
|
35233
|
-
const numCtrl = shType === 6 ? 12 : 16;
|
|
35234
|
-
const minBitsPatch = bpcFlag + (numCtrl - 4) * 2 * bpcCoord + 2 * numColorParams * bpcComp;
|
|
35235
|
-
let prevPts;
|
|
35236
|
-
let prevColors;
|
|
35237
|
-
while (bitPos + minBitsPatch <= totalBits) {
|
|
35238
|
-
const flag = readBits(bpcFlag) & 3;
|
|
35239
|
-
let pts = [];
|
|
35240
|
-
let cols = [];
|
|
35241
|
-
if (flag === 0 || !prevPts || !prevColors) {
|
|
35242
|
-
for (let i = 0; i < numCtrl; i++) pts.push(readCoord());
|
|
35243
|
-
for (let i = 0; i < 4; i++) cols.push(readColorRgb());
|
|
35244
|
-
} else {
|
|
35245
|
-
const extraCtrl = numCtrl - 4;
|
|
35246
|
-
const readExtra = [];
|
|
35247
|
-
for (let i = 0; i < extraCtrl; i++) readExtra.push(readCoord());
|
|
35248
|
-
const c2 = readColorRgb();
|
|
35249
|
-
const c3 = readColorRgb();
|
|
35250
|
-
pts = [prevPts[3], prevPts[4], prevPts[5], prevPts[6], ...readExtra];
|
|
35251
|
-
cols = [prevColors[1], prevColors[2], c2, c3];
|
|
35252
|
-
}
|
|
35253
|
-
prevPts = pts;
|
|
35254
|
-
prevColors = cols;
|
|
35255
|
-
const p00 = pts[0];
|
|
35256
|
-
const p03 = pts[3];
|
|
35257
|
-
const p33 = pts[6];
|
|
35258
|
-
const p30 = pts[9];
|
|
35259
|
-
const c00 = cols[0], c03 = cols[1], c33 = cols[2], c30 = cols[3];
|
|
35260
|
-
const steps = 4;
|
|
35261
|
-
const grid = [];
|
|
35262
|
-
for (let iu = 0; iu <= steps; iu++) {
|
|
35263
|
-
const u = iu / steps;
|
|
35264
|
-
const row = [];
|
|
35265
|
-
for (let iv = 0; iv <= steps; iv++) {
|
|
35266
|
-
const v = iv / steps;
|
|
35267
|
-
const x = (1 - u) * (1 - v) * p00[0] + (1 - u) * v * p03[0] + u * v * p33[0] + u * (1 - v) * p30[0];
|
|
35268
|
-
const y = (1 - u) * (1 - v) * p00[1] + (1 - u) * v * p03[1] + u * v * p33[1] + u * (1 - v) * p30[1];
|
|
35269
|
-
const r = (1 - u) * (1 - v) * c00[0] + (1 - u) * v * c03[0] + u * v * c33[0] + u * (1 - v) * c30[0];
|
|
35270
|
-
const g = (1 - u) * (1 - v) * c00[1] + (1 - u) * v * c03[1] + u * v * c33[1] + u * (1 - v) * c30[1];
|
|
35271
|
-
const b = (1 - u) * (1 - v) * c00[2] + (1 - u) * v * c03[2] + u * v * c33[2] + u * (1 - v) * c30[2];
|
|
35272
|
-
row.push({ x, y, rgb: [r, g, b] });
|
|
35273
|
-
}
|
|
35274
|
-
grid.push(row);
|
|
35275
|
-
}
|
|
35276
|
-
for (let iu = 0; iu < steps; iu++) {
|
|
35277
|
-
for (let iv = 0; iv < steps; iv++) {
|
|
35278
|
-
const g00 = grid[iu][iv];
|
|
35279
|
-
const g01 = grid[iu][iv + 1];
|
|
35280
|
-
const g11 = grid[iu + 1][iv + 1];
|
|
35281
|
-
const g10 = grid[iu + 1][iv];
|
|
35282
|
-
triangles.push([g00, g01, g11], [g00, g11, g10]);
|
|
35283
|
-
}
|
|
35284
|
-
}
|
|
35285
|
-
}
|
|
35286
|
-
}
|
|
35287
|
-
if (triangles.length === 0) return void 0;
|
|
38107
|
+
const numComps = fnNode ? 1 : getColorSpaceComponentCount(doc, csNode);
|
|
38108
|
+
const mesh = new MeshShading(shType, new Stream(bytes), {
|
|
38109
|
+
bitsPerCoordinate: bpcCoord,
|
|
38110
|
+
bitsPerComponent: bpcComp,
|
|
38111
|
+
bitsPerFlag: bpcFlag,
|
|
38112
|
+
decode: decodeNums,
|
|
38113
|
+
numComps,
|
|
38114
|
+
colorFn: null,
|
|
38115
|
+
colorSpace: {
|
|
38116
|
+
numComps,
|
|
38117
|
+
getRgb(components) {
|
|
38118
|
+
const params = Array.from(components);
|
|
38119
|
+
const values = fnNode ? evalShadingFunctionToComponents(doc, fnNode, params) : params;
|
|
38120
|
+
return new Uint8Array(convertColorSpaceComponentsToRgb(doc, csNode, csName, values).map((value) => Math.round(Math.max(0, Math.min(1, value)) * 255)));
|
|
38121
|
+
}
|
|
38122
|
+
}
|
|
38123
|
+
}, vPerRow);
|
|
38124
|
+
const [, , positions, colors, vertexCount] = mesh.getIR();
|
|
38125
|
+
if (vertexCount === 0) return void 0;
|
|
35288
38126
|
const [bx0, by0, bx1, by1] = targetBox;
|
|
35289
38127
|
const boxW = Math.max(1, bx1 - bx0);
|
|
35290
38128
|
const boxH = Math.max(1, by1 - by0);
|
|
@@ -35296,10 +38134,10 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
|
|
|
35296
38134
|
const [px, py] = transformPoint(effectiveCtm, vx, vy);
|
|
35297
38135
|
return [(px - bx0) / boxW * imgW, (by1 - py) / boxH * imgH];
|
|
35298
38136
|
};
|
|
35299
|
-
for (
|
|
35300
|
-
const [x0, y0] = toImgCoords(
|
|
35301
|
-
const [x1, y1] = toImgCoords(
|
|
35302
|
-
const [x2, y2] = toImgCoords(
|
|
38137
|
+
for (let vertex = 0; vertex < vertexCount; vertex += 3) {
|
|
38138
|
+
const [x0, y0] = toImgCoords(positions[vertex * 2], positions[vertex * 2 + 1]);
|
|
38139
|
+
const [x1, y1] = toImgCoords(positions[vertex * 2 + 2], positions[vertex * 2 + 3]);
|
|
38140
|
+
const [x2, y2] = toImgCoords(positions[vertex * 2 + 4], positions[vertex * 2 + 5]);
|
|
35303
38141
|
const denom = (y1 - y2) * (x0 - x2) + (x2 - x1) * (y0 - y2);
|
|
35304
38142
|
if (Math.abs(denom) < 1e-6) continue;
|
|
35305
38143
|
const minX = Math.max(0, Math.floor(Math.min(x0, x1, x2)));
|
|
@@ -35314,13 +38152,12 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
|
|
|
35314
38152
|
const w1 = ((y2 - y0) * (px - x2) + (x0 - x2) * (py - y2)) / denom;
|
|
35315
38153
|
const w2 = 1 - w0 - w1;
|
|
35316
38154
|
if (w0 >= -1e-4 && w1 >= -1e-4 && w2 >= -1e-4) {
|
|
35317
|
-
const r = w0 * v0.rgb[0] + w1 * v1.rgb[0] + w2 * v2.rgb[0];
|
|
35318
|
-
const g = w0 * v0.rgb[1] + w1 * v1.rgb[1] + w2 * v2.rgb[1];
|
|
35319
|
-
const b = w0 * v0.rgb[2] + w1 * v1.rgb[2] + w2 * v2.rgb[2];
|
|
35320
38155
|
const pIdx = (iy * imgW + ix) * 4;
|
|
35321
|
-
|
|
35322
|
-
|
|
35323
|
-
|
|
38156
|
+
for (let channel = 0; channel < 3; channel++) {
|
|
38157
|
+
rgba[pIdx + channel] = Math.round(
|
|
38158
|
+
w0 * colors[vertex * 4 + channel] + w1 * colors[vertex * 4 + 4 + channel] + w2 * colors[vertex * 4 + 8 + channel]
|
|
38159
|
+
);
|
|
38160
|
+
}
|
|
35324
38161
|
rgba[pIdx + 3] = a8;
|
|
35325
38162
|
}
|
|
35326
38163
|
}
|
|
@@ -35407,6 +38244,8 @@ function renderShadingDictToImage(doc, shDict, shadingCtm, targetBox, fillAlpha,
|
|
|
35407
38244
|
const [a, b, c, d, e, f] = effectiveCtm;
|
|
35408
38245
|
const det = a * d - b * c;
|
|
35409
38246
|
if (Math.abs(det) <= 1e-8) return void 0;
|
|
38247
|
+
const [sa, sb, sc, sd, se, sf] = shadingCtm;
|
|
38248
|
+
const shadingDet = sa * sd - sb * sc;
|
|
35410
38249
|
const t0Dom = shDomain[0] ?? 0;
|
|
35411
38250
|
const t1Dom = shDomain[1] ?? 1;
|
|
35412
38251
|
for (let iy = 0; iy < imgH; iy++) {
|
|
@@ -35417,8 +38256,10 @@ function renderShadingDictToImage(doc, shDict, shadingCtm, targetBox, fillAlpha,
|
|
|
35417
38256
|
const dxPdf = xPdf - e;
|
|
35418
38257
|
const xs = (d * dxPdf - c * dyPdf) / det;
|
|
35419
38258
|
const ys = (-b * dxPdf + a * dyPdf) / det;
|
|
35420
|
-
if (shBBox
|
|
35421
|
-
|
|
38259
|
+
if (shBBox) {
|
|
38260
|
+
const bboxX = (sd * (xPdf - se) - sc * (yPdf - sf)) / shadingDet;
|
|
38261
|
+
const bboxY = (-sb * (xPdf - se) + sa * (yPdf - sf)) / shadingDet;
|
|
38262
|
+
if (bboxX < shBBox[0] || bboxX > shBBox[2] || bboxY < shBBox[1] || bboxY > shBBox[3]) continue;
|
|
35422
38263
|
}
|
|
35423
38264
|
let comps;
|
|
35424
38265
|
if (shType === 1) {
|
|
@@ -35718,7 +38559,8 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
35718
38559
|
const shDict = shNode?.kind === "dict" ? shNode : shNode?.kind === "stream" ? shNode.dict : void 0;
|
|
35719
38560
|
const shStream = shNode?.kind === "stream" ? shNode : void 0;
|
|
35720
38561
|
if (shDict) {
|
|
35721
|
-
const
|
|
38562
|
+
const [originX, originY] = params.origin ?? [0, 0];
|
|
38563
|
+
const targetBox = st.clipRect ?? [originX, originY, originX + params.width, originY + params.height];
|
|
35722
38564
|
const img = renderShadingDictToImage(
|
|
35723
38565
|
params.cosDoc,
|
|
35724
38566
|
shDict,
|
|
@@ -35757,12 +38599,10 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
35757
38599
|
} else if (operator === "RG" || operator === "SC" || operator === "SCN") {
|
|
35758
38600
|
st.strokeColor = resolveScColorOperands(operator === "RG" ? "DeviceRGB" : st.strokeColorSpaceName, ops, activeResources);
|
|
35759
38601
|
} else if (operator === "k") {
|
|
35760
|
-
|
|
35761
|
-
st.fillColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
|
|
38602
|
+
st.fillColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
|
|
35762
38603
|
st.fillPatternName = void 0;
|
|
35763
38604
|
} else if (operator === "K") {
|
|
35764
|
-
|
|
35765
|
-
st.strokeColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
|
|
38605
|
+
st.strokeColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
|
|
35766
38606
|
} else if (operator === "gs" && params.cosDoc && activeResources && ops[0]?.kind === "name") {
|
|
35767
38607
|
const extDict = params.cosDoc.resolveDict(dictGet(activeResources, "ExtGState"));
|
|
35768
38608
|
const gsDict = extDict ? params.cosDoc.resolveDict(dictGet(extDict, ops[0].decoded)) : void 0;
|
|
@@ -35971,7 +38811,7 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
35971
38811
|
stateStack.pop();
|
|
35972
38812
|
capturedOperations = parentOperations;
|
|
35973
38813
|
}
|
|
35974
|
-
if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
|
|
38814
|
+
if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, isolated, bboxClip: nextClipPaths?.[0], blendMode: st.blendMode, clipRect: st.clipRect } });
|
|
35975
38815
|
};
|
|
35976
38816
|
const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
|
|
35977
38817
|
for (const node of nodes) {
|
|
@@ -36555,6 +39395,7 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
36555
39395
|
pageIndex: params.pageIndex,
|
|
36556
39396
|
width: params.width,
|
|
36557
39397
|
height: params.height,
|
|
39398
|
+
...params.origin ? { origin: params.origin } : {},
|
|
36558
39399
|
rotation: params.rotation ?? 0,
|
|
36559
39400
|
glyphs,
|
|
36560
39401
|
paths,
|
|
@@ -38589,7 +41430,7 @@ var PdfPage = class {
|
|
|
38589
41430
|
return [n0.value, n1.value, n2.value, n3.value];
|
|
38590
41431
|
}
|
|
38591
41432
|
}
|
|
38592
|
-
return [0, 0, 612, 792];
|
|
41433
|
+
return key === "MediaBox" ? [0, 0, 612, 792] : this.resolveBox("MediaBox");
|
|
38593
41434
|
}
|
|
38594
41435
|
getMediaBox() {
|
|
38595
41436
|
return this.resolveBox("MediaBox");
|
|
@@ -39262,16 +42103,19 @@ var PdfPage = class {
|
|
|
39262
42103
|
});
|
|
39263
42104
|
}
|
|
39264
42105
|
}
|
|
39265
|
-
|
|
42106
|
+
const mediaBox = this.getMediaBox(), cropBox = this.getCropBox();
|
|
42107
|
+
const originX = Math.min(mediaBox[0], mediaBox[2]), originY = Math.min(mediaBox[1], mediaBox[3]);
|
|
42108
|
+
return { ...evaluateContentStreamToDisplayList({
|
|
39266
42109
|
pageIndex: this.index,
|
|
39267
42110
|
width,
|
|
39268
42111
|
height,
|
|
42112
|
+
origin: [originX, originY],
|
|
39269
42113
|
rotation: this.getRotation(),
|
|
39270
42114
|
nodes: baseNodes,
|
|
39271
42115
|
cosDoc: this.cosDoc,
|
|
39272
42116
|
resourcesDict: evalResourcesDict,
|
|
39273
42117
|
annotations: extractPageAnnotations(this.cosDoc, this.pageDict)
|
|
39274
|
-
});
|
|
42118
|
+
}), cropBox: [cropBox[0] - originX, cropBox[1] - originY, cropBox[2] - originX, cropBox[3] - originY] };
|
|
39275
42119
|
}
|
|
39276
42120
|
extractPage(options) {
|
|
39277
42121
|
const dl = this.evaluateDisplayList();
|
|
@@ -39289,10 +42133,10 @@ var PdfPage = class {
|
|
|
39289
42133
|
return extractTablesFromDisplayList(this.evaluateDisplayList());
|
|
39290
42134
|
}
|
|
39291
42135
|
renderToBitmap(options) {
|
|
39292
|
-
return renderDisplayListToBitmap(this.evaluateDisplayList(), options);
|
|
42136
|
+
return renderDisplayListToBitmap(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
|
|
39293
42137
|
}
|
|
39294
42138
|
renderToPng(options) {
|
|
39295
|
-
return renderDisplayListToPng(this.evaluateDisplayList(), options);
|
|
42139
|
+
return renderDisplayListToPng(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
|
|
39296
42140
|
}
|
|
39297
42141
|
};
|
|
39298
42142
|
function createStandardFontHandle(standardName) {
|
|
@@ -40342,7 +43186,7 @@ function prepareStroke(path, scale) {
|
|
|
40342
43186
|
}
|
|
40343
43187
|
return { matrix, width, dashArray, dashPhase };
|
|
40344
43188
|
}
|
|
40345
|
-
function strokeContours(path, pageHeight, scale) {
|
|
43189
|
+
function strokeContours(path, pageHeight, scale, originX = 0, originY = 0) {
|
|
40346
43190
|
const stroke = prepareStroke(path, scale);
|
|
40347
43191
|
if (!stroke) return [];
|
|
40348
43192
|
const inverse = inverseStrokeMatrix(stroke.matrix);
|
|
@@ -40354,8 +43198,8 @@ function strokeContours(path, pageHeight, scale) {
|
|
|
40354
43198
|
(inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
|
|
40355
43199
|
];
|
|
40356
43200
|
const toScreen = ([x, y]) => [
|
|
40357
|
-
(a * x / strokeScale + c * y / strokeScale + e) * scale,
|
|
40358
|
-
(pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
|
|
43201
|
+
(a * x / strokeScale + c * y / strokeScale + e - originX) * scale,
|
|
43202
|
+
(pageHeight + originY - b * x / strokeScale - d * y / strokeScale - f) * scale
|
|
40359
43203
|
];
|
|
40360
43204
|
const contours = strokeOutlines(
|
|
40361
43205
|
segmentsToScreenPaths(path.segments, pageHeight, scale, project),
|
|
@@ -40513,18 +43357,34 @@ function renderSoftMask(mask, displayList, scale) {
|
|
|
40513
43357
|
}
|
|
40514
43358
|
return bitmap;
|
|
40515
43359
|
}
|
|
40516
|
-
function
|
|
40517
|
-
|
|
43360
|
+
function getDisplayListCropBox(list) {
|
|
43361
|
+
const full = [0, 0, list.width, list.height];
|
|
43362
|
+
const box = list.cropBox;
|
|
43363
|
+
if (!box || !box.every(Number.isFinite)) return full;
|
|
43364
|
+
const x0 = Math.max(0, Math.min(box[0], box[2]));
|
|
43365
|
+
const y0 = Math.max(0, Math.min(box[1], box[3]));
|
|
43366
|
+
const x1 = Math.min(list.width, Math.max(box[0], box[2]));
|
|
43367
|
+
const y1 = Math.min(list.height, Math.max(box[1], box[3]));
|
|
43368
|
+
return x1 > x0 && y1 > y0 ? [x0, y0, x1, y1] : full;
|
|
43369
|
+
}
|
|
43370
|
+
function hasCompositingEffects(operations, includeSoftMasks = false) {
|
|
43371
|
+
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));
|
|
43372
|
+
}
|
|
43373
|
+
function needsGroupBackdrop(group) {
|
|
43374
|
+
return group.isolated === false && !!group.softMask && hasCompositingEffects(group.operations, true);
|
|
40518
43375
|
}
|
|
40519
43376
|
function renderDisplayListToBitmap(displayList, options = {}) {
|
|
40520
43377
|
const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
|
|
40521
43378
|
const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
|
|
40522
43379
|
const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
|
|
40523
43380
|
const scale = scaleX;
|
|
43381
|
+
const [originX, originY] = displayList.origin ?? [0, 0];
|
|
43382
|
+
const pageTop = originY + displayList.height;
|
|
43383
|
+
const toScreen = (x, y) => [(x - originX) * scale, (pageTop - y) * scale];
|
|
40524
43384
|
const width = Math.max(1, Math.round(displayList.width * scale));
|
|
40525
43385
|
const height = Math.max(1, Math.round(displayList.height * scale));
|
|
40526
43386
|
const rgba = new Uint8Array(width * height * 4);
|
|
40527
|
-
const deferBackground = !options.transparent &&
|
|
43387
|
+
const deferBackground = !options.transparent && hasCompositingEffects(paintOperations(displayList));
|
|
40528
43388
|
const transparent = options.transparent || deferBackground;
|
|
40529
43389
|
const bg = options.background ?? { r: 1, g: 1, b: 1 };
|
|
40530
43390
|
const bgR = transparent ? 0 : Math.round(bg.r * 255);
|
|
@@ -40549,14 +43409,27 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40549
43409
|
let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
|
|
40550
43410
|
if (operation.kind === "group") {
|
|
40551
43411
|
const group = operation.value;
|
|
40552
|
-
|
|
43412
|
+
let operations = group.operations;
|
|
43413
|
+
if (needsGroupBackdrop(group)) {
|
|
43414
|
+
operations = [{ kind: "image", value: {
|
|
43415
|
+
name: "GroupBackdrop",
|
|
43416
|
+
width,
|
|
43417
|
+
height,
|
|
43418
|
+
decodedRgba: rgba.slice(),
|
|
43419
|
+
matrix: [width / scale, 0, 0, height / scale, originX, pageTop - height / scale],
|
|
43420
|
+
colorSpace: "DeviceRGB",
|
|
43421
|
+
bitsPerComponent: 8,
|
|
43422
|
+
...group.bboxClip ? { clipPaths: [group.bboxClip] } : {}
|
|
43423
|
+
} }, ...operations];
|
|
43424
|
+
}
|
|
43425
|
+
const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, useCropBox: false, transparent: true });
|
|
40553
43426
|
for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
|
|
40554
43427
|
operation = { kind: "image", value: {
|
|
40555
43428
|
name: "TransparencyGroup",
|
|
40556
43429
|
width: bitmap.width,
|
|
40557
43430
|
height: bitmap.height,
|
|
40558
43431
|
decodedRgba: bitmap.data,
|
|
40559
|
-
matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale,
|
|
43432
|
+
matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, originX, pageTop - bitmap.height / scale],
|
|
40560
43433
|
colorSpace: "DeviceRGB",
|
|
40561
43434
|
bitsPerComponent: 8,
|
|
40562
43435
|
blendMode: group.blendMode,
|
|
@@ -40570,7 +43443,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40570
43443
|
for (const clip of clips) {
|
|
40571
43444
|
const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
|
|
40572
43445
|
const layer = new Uint8Array(width * height * 4);
|
|
40573
|
-
fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
|
|
43446
|
+
fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale, toScreen), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
|
|
40574
43447
|
for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
|
|
40575
43448
|
}
|
|
40576
43449
|
cachedClips = clips;
|
|
@@ -40617,15 +43490,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40617
43490
|
if (operation.kind === "path") {
|
|
40618
43491
|
const path = operation.value;
|
|
40619
43492
|
if (path.fillColor) {
|
|
40620
|
-
const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale), true);
|
|
40621
|
-
const clipScreen = path.clipRect ? [path.clipRect[0] * scale, (
|
|
43493
|
+
const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale, toScreen), true);
|
|
43494
|
+
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;
|
|
40622
43495
|
fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
|
|
40623
43496
|
}
|
|
40624
43497
|
if (path.strokeColor) {
|
|
40625
43498
|
const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
|
|
40626
43499
|
const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
|
|
40627
|
-
const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
|
|
40628
|
-
const clipScreen = path.clipRect ? [path.clipRect[0] * scale, (
|
|
43500
|
+
const edges = pathsToEdges(strokeContours(path, displayList.height, scale, originX, originY).map((points) => ({ points, closed: true })));
|
|
43501
|
+
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;
|
|
40629
43502
|
fillEdgesScanline4x4(
|
|
40630
43503
|
rgba,
|
|
40631
43504
|
width,
|
|
@@ -40648,12 +43521,12 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40648
43521
|
if (Math.abs(det) <= 1e-8) continue;
|
|
40649
43522
|
const cornersPdfX = [e, a + e, a + c + e, c + e];
|
|
40650
43523
|
const cornersPdfY = [f, b + f, b + d + f, d + f];
|
|
40651
|
-
const cornersPx = cornersPdfX.map((cx) => cx * scale);
|
|
40652
|
-
const cornersPy = cornersPdfY.map((cy) => (
|
|
40653
|
-
const clipMinPx = img.clipRect ? Math.floor(img.clipRect[0] * scale) : 0;
|
|
40654
|
-
const clipMaxPx = img.clipRect ? Math.ceil(img.clipRect[2] * scale) - 1 : width - 1;
|
|
40655
|
-
const clipMinPy = img.clipRect ? Math.floor((
|
|
40656
|
-
const clipMaxPy = img.clipRect ? Math.ceil((
|
|
43524
|
+
const cornersPx = cornersPdfX.map((cx) => (cx - originX) * scale);
|
|
43525
|
+
const cornersPy = cornersPdfY.map((cy) => (pageTop - cy) * scale);
|
|
43526
|
+
const clipMinPx = img.clipRect ? Math.floor((img.clipRect[0] - originX) * scale) : 0;
|
|
43527
|
+
const clipMaxPx = img.clipRect ? Math.ceil((img.clipRect[2] - originX) * scale) - 1 : width - 1;
|
|
43528
|
+
const clipMinPy = img.clipRect ? Math.floor((pageTop - img.clipRect[3]) * scale) : 0;
|
|
43529
|
+
const clipMaxPy = img.clipRect ? Math.ceil((pageTop - img.clipRect[1]) * scale) - 1 : height - 1;
|
|
40657
43530
|
const minPx = Math.max(0, clipMinPx, Math.floor(Math.min(...cornersPx)));
|
|
40658
43531
|
const maxPx = Math.min(width - 1, clipMaxPx, Math.ceil(Math.max(...cornersPx)) - 1);
|
|
40659
43532
|
const minPy = Math.max(0, clipMinPy, Math.floor(Math.min(...cornersPy)));
|
|
@@ -40670,11 +43543,11 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40670
43543
|
const smooth = Math.fround((s1 + s2 + Math.hypot(s1 - s2, 2 * cross)) / 2) <= 1;
|
|
40671
43544
|
const sample = new Float64Array(4);
|
|
40672
43545
|
for (let py = minPy; py <= maxPy; py++) {
|
|
40673
|
-
const yPdf =
|
|
43546
|
+
const yPdf = pageTop - (py + 0.5) / scale;
|
|
40674
43547
|
if (img.clipRect && (yPdf < img.clipRect[1] || yPdf > img.clipRect[3])) continue;
|
|
40675
43548
|
const dyPdf = yPdf - f;
|
|
40676
43549
|
for (let px = minPx; px <= maxPx; px++) {
|
|
40677
|
-
const xPdf = (px + 0.5) / scale;
|
|
43550
|
+
const xPdf = originX + (px + 0.5) / scale;
|
|
40678
43551
|
if (img.clipRect && (xPdf < img.clipRect[0] || xPdf > img.clipRect[2])) continue;
|
|
40679
43552
|
const dxPdf = xPdf - e;
|
|
40680
43553
|
const u = (d * dxPdf - c * dyPdf) / det;
|
|
@@ -40735,6 +43608,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40735
43608
|
}
|
|
40736
43609
|
result = { width: targetW, height: targetH, data: resampled };
|
|
40737
43610
|
}
|
|
43611
|
+
if (options.useCropBox) {
|
|
43612
|
+
const box = getDisplayListCropBox(displayList);
|
|
43613
|
+
result = cropRgbaBitmap(result, {
|
|
43614
|
+
x: box[0] * scaleX,
|
|
43615
|
+
y: (displayList.height - box[3]) * scaleY,
|
|
43616
|
+
width: (box[2] - box[0]) * scaleX,
|
|
43617
|
+
height: (box[3] - box[1]) * scaleY
|
|
43618
|
+
});
|
|
43619
|
+
}
|
|
40738
43620
|
result = rotateRgbaBitmapQuarterTurns(result, displayList.rotation ?? 0);
|
|
40739
43621
|
if (options.cropRect) {
|
|
40740
43622
|
result = cropRgbaBitmap(result, options.cropRect);
|