@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
|
@@ -2595,6 +2595,295 @@ function utf8PasswordToBytes(password) {
|
|
|
2595
2595
|
}
|
|
2596
2596
|
return stringToBytes(password);
|
|
2597
2597
|
}
|
|
2598
|
+
function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
|
|
2599
|
+
const COMPONENTS = 3;
|
|
2600
|
+
alpha01 = alpha01 !== 1 ? 0 : alpha01;
|
|
2601
|
+
const xRatio = w1 / w2;
|
|
2602
|
+
const yRatio = h1 / h2;
|
|
2603
|
+
let newIndex = 0, oldIndex;
|
|
2604
|
+
const xScaled = new Uint16Array(w2);
|
|
2605
|
+
const w1Scanline = w1 * COMPONENTS;
|
|
2606
|
+
for (let i = 0; i < w2; i++) {
|
|
2607
|
+
xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
|
|
2608
|
+
}
|
|
2609
|
+
for (let i = 0; i < h2; i++) {
|
|
2610
|
+
const py = Math.floor(i * yRatio) * w1Scanline;
|
|
2611
|
+
for (let j = 0; j < w2; j++) {
|
|
2612
|
+
oldIndex = py + xScaled[j];
|
|
2613
|
+
dest[newIndex++] = src[oldIndex++];
|
|
2614
|
+
dest[newIndex++] = src[oldIndex++];
|
|
2615
|
+
dest[newIndex++] = src[oldIndex++];
|
|
2616
|
+
newIndex += alpha01;
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2620
|
+
function isDefaultDecodeHelper(decode, expectedLen) {
|
|
2621
|
+
if (!Array.isArray(decode)) {
|
|
2622
|
+
return true;
|
|
2623
|
+
}
|
|
2624
|
+
const decodeLen = decode.length;
|
|
2625
|
+
if (decodeLen < expectedLen) {
|
|
2626
|
+
warn2("Decode map length is too short.");
|
|
2627
|
+
return true;
|
|
2628
|
+
}
|
|
2629
|
+
if (decodeLen > expectedLen) {
|
|
2630
|
+
info("Truncating too long decode map.");
|
|
2631
|
+
decode.length = expectedLen;
|
|
2632
|
+
}
|
|
2633
|
+
return false;
|
|
2634
|
+
}
|
|
2635
|
+
function parsePostScriptFunction(source) {
|
|
2636
|
+
return new Parser(new Lexer(source)).parse();
|
|
2637
|
+
}
|
|
2638
|
+
function _nodesEqual(a, b) {
|
|
2639
|
+
if (a === b) {
|
|
2640
|
+
return true;
|
|
2641
|
+
}
|
|
2642
|
+
if (a.type !== b.type) {
|
|
2643
|
+
return false;
|
|
2644
|
+
}
|
|
2645
|
+
switch (a.type) {
|
|
2646
|
+
case PS_NODE.arg:
|
|
2647
|
+
return a.index === b.index;
|
|
2648
|
+
case PS_NODE.const:
|
|
2649
|
+
return a.value === b.value;
|
|
2650
|
+
case PS_NODE.unary:
|
|
2651
|
+
return a.op === b.op && _nodesEqual(a.operand, b.operand);
|
|
2652
|
+
case PS_NODE.binary:
|
|
2653
|
+
return a.op === b.op && _nodesEqual(a.first, b.first) && _nodesEqual(a.second, b.second);
|
|
2654
|
+
case PS_NODE.ternary:
|
|
2655
|
+
return _nodesEqual(a.cond, b.cond) && _nodesEqual(a.then, b.then) && _nodesEqual(a.otherwise, b.otherwise);
|
|
2656
|
+
default:
|
|
2657
|
+
return false;
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
function _evalBinaryConst(op, a, b) {
|
|
2661
|
+
switch (op) {
|
|
2662
|
+
case TOKEN.add:
|
|
2663
|
+
return a + b;
|
|
2664
|
+
case TOKEN.sub:
|
|
2665
|
+
return a - b;
|
|
2666
|
+
case TOKEN.mul:
|
|
2667
|
+
return a * b;
|
|
2668
|
+
case TOKEN.div:
|
|
2669
|
+
return b !== 0 ? a / b : 0;
|
|
2670
|
+
// div by zero → 0
|
|
2671
|
+
case TOKEN.idiv:
|
|
2672
|
+
return b !== 0 ? Math.trunc(a / b) : 0;
|
|
2673
|
+
// div by zero → 0
|
|
2674
|
+
case TOKEN.mod:
|
|
2675
|
+
return b !== 0 ? a - Math.trunc(a / b) * b : 0;
|
|
2676
|
+
// div by zero → 0
|
|
2677
|
+
case TOKEN.exp: {
|
|
2678
|
+
const r = a ** b;
|
|
2679
|
+
return Number.isFinite(r) ? r : void 0;
|
|
2680
|
+
}
|
|
2681
|
+
case TOKEN.atan: {
|
|
2682
|
+
let deg = Math.atan2(a, b) * (180 / Math.PI);
|
|
2683
|
+
if (deg < 0) {
|
|
2684
|
+
deg += 360;
|
|
2685
|
+
}
|
|
2686
|
+
return deg;
|
|
2687
|
+
}
|
|
2688
|
+
case TOKEN.eq:
|
|
2689
|
+
return a === b;
|
|
2690
|
+
case TOKEN.ne:
|
|
2691
|
+
return a !== b;
|
|
2692
|
+
case TOKEN.gt:
|
|
2693
|
+
return a > b;
|
|
2694
|
+
case TOKEN.ge:
|
|
2695
|
+
return a >= b;
|
|
2696
|
+
case TOKEN.lt:
|
|
2697
|
+
return a < b;
|
|
2698
|
+
case TOKEN.le:
|
|
2699
|
+
return a <= b;
|
|
2700
|
+
case TOKEN.and:
|
|
2701
|
+
return typeof a === "boolean" ? a && b : a & b | 0;
|
|
2702
|
+
case TOKEN.or:
|
|
2703
|
+
return typeof a === "boolean" ? a || b : a | b | 0;
|
|
2704
|
+
case TOKEN.xor:
|
|
2705
|
+
return typeof a === "boolean" ? a !== b : a ^ b | 0;
|
|
2706
|
+
case TOKEN.bitshift:
|
|
2707
|
+
return b >= 0 ? a << b | 0 : a >> -b | 0;
|
|
2708
|
+
case TOKEN.min:
|
|
2709
|
+
return Math.min(a, b);
|
|
2710
|
+
case TOKEN.max:
|
|
2711
|
+
return Math.max(a, b);
|
|
2712
|
+
default:
|
|
2713
|
+
return void 0;
|
|
2714
|
+
}
|
|
2715
|
+
}
|
|
2716
|
+
function _evalUnaryConst(op, v) {
|
|
2717
|
+
switch (op) {
|
|
2718
|
+
case TOKEN.abs:
|
|
2719
|
+
return Math.abs(v);
|
|
2720
|
+
case TOKEN.neg:
|
|
2721
|
+
return -v;
|
|
2722
|
+
case TOKEN.ceiling:
|
|
2723
|
+
return Math.ceil(v);
|
|
2724
|
+
case TOKEN.floor:
|
|
2725
|
+
return Math.floor(v);
|
|
2726
|
+
case TOKEN.round:
|
|
2727
|
+
return Math.round(v);
|
|
2728
|
+
case TOKEN.truncate:
|
|
2729
|
+
return Math.trunc(v);
|
|
2730
|
+
case TOKEN.sqrt: {
|
|
2731
|
+
const r = Math.sqrt(v);
|
|
2732
|
+
return Number.isFinite(r) ? r : void 0;
|
|
2733
|
+
}
|
|
2734
|
+
case TOKEN.sin:
|
|
2735
|
+
return Math.sin(v % 360 * Math.PI / 180);
|
|
2736
|
+
case TOKEN.cos:
|
|
2737
|
+
return Math.cos(v % 360 * Math.PI / 180);
|
|
2738
|
+
case TOKEN.ln: {
|
|
2739
|
+
const r = Math.log(v);
|
|
2740
|
+
return Number.isFinite(r) ? r : void 0;
|
|
2741
|
+
}
|
|
2742
|
+
case TOKEN.log: {
|
|
2743
|
+
const r = Math.log10(v);
|
|
2744
|
+
return Number.isFinite(r) ? r : void 0;
|
|
2745
|
+
}
|
|
2746
|
+
case TOKEN.cvi:
|
|
2747
|
+
return Math.trunc(v);
|
|
2748
|
+
case TOKEN.cvr:
|
|
2749
|
+
return v;
|
|
2750
|
+
case TOKEN.not:
|
|
2751
|
+
return typeof v === "boolean" ? !v : ~v;
|
|
2752
|
+
default:
|
|
2753
|
+
return void 0;
|
|
2754
|
+
}
|
|
2755
|
+
}
|
|
2756
|
+
function _unaryValueType(op, operandType) {
|
|
2757
|
+
return op === TOKEN.not ? operandType : PS_VALUE_TYPE.numeric;
|
|
2758
|
+
}
|
|
2759
|
+
function _binaryValueType(op, firstType, secondType) {
|
|
2760
|
+
switch (op) {
|
|
2761
|
+
// Comparison operators always produce a boolean.
|
|
2762
|
+
case TOKEN.eq:
|
|
2763
|
+
case TOKEN.ne:
|
|
2764
|
+
case TOKEN.gt:
|
|
2765
|
+
case TOKEN.ge:
|
|
2766
|
+
case TOKEN.lt:
|
|
2767
|
+
case TOKEN.le:
|
|
2768
|
+
return PS_VALUE_TYPE.boolean;
|
|
2769
|
+
// and / or / xor preserve the type when both operands are the same known
|
|
2770
|
+
// type (both boolean or both numeric); otherwise the type is unknown.
|
|
2771
|
+
case TOKEN.and:
|
|
2772
|
+
case TOKEN.or:
|
|
2773
|
+
case TOKEN.xor:
|
|
2774
|
+
return firstType === secondType && firstType !== PS_VALUE_TYPE.unknown ? firstType : PS_VALUE_TYPE.unknown;
|
|
2775
|
+
// All arithmetic / bitshift operators produce a numeric result.
|
|
2776
|
+
default:
|
|
2777
|
+
return PS_VALUE_TYPE.numeric;
|
|
2778
|
+
}
|
|
2779
|
+
}
|
|
2780
|
+
function buildPostScriptJsFunction(source, domain, range, forceInterpreter = false) {
|
|
2781
|
+
const program = parsePostScriptFunction(source);
|
|
2782
|
+
const ir = !forceInterpreter && new PsJsCompiler(domain, range).compile(program);
|
|
2783
|
+
if (ir) {
|
|
2784
|
+
return (src, srcOffset, dest, destOffset) => {
|
|
2785
|
+
PsJsCompiler.execute(ir, src, srcOffset, dest, destOffset);
|
|
2786
|
+
};
|
|
2787
|
+
}
|
|
2788
|
+
return PSStackBasedInterpreter.build(program, domain, range);
|
|
2789
|
+
}
|
|
2790
|
+
function meshUpdateBounds(self) {
|
|
2791
|
+
let minX = self.coords[0][0], minY = self.coords[0][1], maxX = minX, maxY = minY;
|
|
2792
|
+
for (let i = 1, ii = self.coords.length; i < ii; i++) {
|
|
2793
|
+
const x = self.coords[i][0], y = self.coords[i][1];
|
|
2794
|
+
minX = minX > x ? x : minX;
|
|
2795
|
+
minY = minY > y ? y : minY;
|
|
2796
|
+
maxX = maxX < x ? x : maxX;
|
|
2797
|
+
maxY = maxY < y ? y : maxY;
|
|
2798
|
+
}
|
|
2799
|
+
self.bounds = [minX, minY, maxX, maxY];
|
|
2800
|
+
}
|
|
2801
|
+
function meshPackData(self) {
|
|
2802
|
+
let i, j, ii;
|
|
2803
|
+
const coords = self.coords;
|
|
2804
|
+
const coordsPacked = new Float32Array(coords.length * 2);
|
|
2805
|
+
for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
|
|
2806
|
+
const xy = coords[i];
|
|
2807
|
+
coordsPacked[j++] = xy[0];
|
|
2808
|
+
coordsPacked[j++] = xy[1];
|
|
2809
|
+
}
|
|
2810
|
+
self.coords = coordsPacked;
|
|
2811
|
+
const colors = self.colors;
|
|
2812
|
+
const colorsPacked = new Uint8Array(colors.length * 4);
|
|
2813
|
+
for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
|
|
2814
|
+
const c = colors[i];
|
|
2815
|
+
colorsPacked[j++] = c[0];
|
|
2816
|
+
colorsPacked[j++] = c[1];
|
|
2817
|
+
colorsPacked[j++] = c[2];
|
|
2818
|
+
j++;
|
|
2819
|
+
}
|
|
2820
|
+
self.colors = colorsPacked;
|
|
2821
|
+
for (const figure of self.figures) {
|
|
2822
|
+
figure.coords = new Uint32Array(figure.coords);
|
|
2823
|
+
figure.colors = new Uint32Array(figure.colors);
|
|
2824
|
+
}
|
|
2825
|
+
}
|
|
2826
|
+
function buildMeshVertexData(coords, colors, figures) {
|
|
2827
|
+
let vertexCount = 0;
|
|
2828
|
+
for (const figure of figures) {
|
|
2829
|
+
if (figure.type === MeshFigureType.TRIANGLES) {
|
|
2830
|
+
vertexCount += figure.coords.length;
|
|
2831
|
+
} else if (figure.type === MeshFigureType.LATTICE) {
|
|
2832
|
+
const vpr = figure.verticesPerRow;
|
|
2833
|
+
vertexCount += (Math.floor(figure.coords.length / vpr) - 1) * (vpr - 1) * 6;
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2836
|
+
const posData = new Float32Array(vertexCount * 2);
|
|
2837
|
+
const colData = new Uint8Array(vertexCount * 4);
|
|
2838
|
+
let pOff = 0, cOff = 0;
|
|
2839
|
+
const addVertex = (pi, ci) => {
|
|
2840
|
+
posData[pOff++] = coords[pi * 2];
|
|
2841
|
+
posData[pOff++] = coords[pi * 2 + 1];
|
|
2842
|
+
colData[cOff++] = colors[ci * 4];
|
|
2843
|
+
colData[cOff++] = colors[ci * 4 + 1];
|
|
2844
|
+
colData[cOff++] = colors[ci * 4 + 2];
|
|
2845
|
+
cOff++;
|
|
2846
|
+
};
|
|
2847
|
+
for (const figure of figures) {
|
|
2848
|
+
const ps = figure.coords;
|
|
2849
|
+
const cs = figure.colors;
|
|
2850
|
+
if (figure.type === MeshFigureType.TRIANGLES) {
|
|
2851
|
+
for (let i = 0, ii = ps.length; i < ii; i++) {
|
|
2852
|
+
addVertex(ps[i], cs[i]);
|
|
2853
|
+
}
|
|
2854
|
+
} else if (figure.type === MeshFigureType.LATTICE) {
|
|
2855
|
+
const vpr = figure.verticesPerRow;
|
|
2856
|
+
const rows = Math.floor(ps.length / vpr) - 1;
|
|
2857
|
+
const cols = vpr - 1;
|
|
2858
|
+
for (let i = 0; i < rows; i++) {
|
|
2859
|
+
let q = i * vpr;
|
|
2860
|
+
for (let j = 0; j < cols; j++, q++) {
|
|
2861
|
+
addVertex(ps[q], cs[q]);
|
|
2862
|
+
addVertex(ps[q + 1], cs[q + 1]);
|
|
2863
|
+
addVertex(ps[q + vpr], cs[q + vpr]);
|
|
2864
|
+
addVertex(ps[q + vpr + 1], cs[q + vpr + 1]);
|
|
2865
|
+
addVertex(ps[q + 1], cs[q + 1]);
|
|
2866
|
+
addVertex(ps[q + vpr], cs[q + vpr]);
|
|
2867
|
+
}
|
|
2868
|
+
}
|
|
2869
|
+
}
|
|
2870
|
+
}
|
|
2871
|
+
return { posData, colData, vertexCount };
|
|
2872
|
+
}
|
|
2873
|
+
function getB(count) {
|
|
2874
|
+
if (bCache?.has(count)) return bCache.get(count);
|
|
2875
|
+
const values = Array.from({ length: count + 1 }, (_, i) => {
|
|
2876
|
+
const t = i / count, t_ = 1 - t;
|
|
2877
|
+
return new Float32Array([
|
|
2878
|
+
t_ ** 3,
|
|
2879
|
+
3 * t * t_ ** 2,
|
|
2880
|
+
3 * t ** 2 * t_,
|
|
2881
|
+
t ** 3
|
|
2882
|
+
]);
|
|
2883
|
+
});
|
|
2884
|
+
(bCache ??= /* @__PURE__ */ new Map()).set(count, values);
|
|
2885
|
+
return values;
|
|
2886
|
+
}
|
|
2598
2887
|
function encodeFlate(bytes) {
|
|
2599
2888
|
return deflate(bytes);
|
|
2600
2889
|
}
|
|
@@ -4682,11 +4971,16 @@ function parseDictionaryStream(dictNode, lexer, bytes) {
|
|
|
4682
4971
|
let streamEnd = streamStart;
|
|
4683
4972
|
if (resolvedLength !== void 0 && resolvedLength >= 0 && streamStart + resolvedLength <= bytes.length) {
|
|
4684
4973
|
const candidateEnd = streamStart + resolvedLength;
|
|
4685
|
-
const
|
|
4686
|
-
|
|
4687
|
-
|
|
4974
|
+
const tailLexer = new CosByteLexer(bytes, candidateEnd);
|
|
4975
|
+
let endToken;
|
|
4976
|
+
try {
|
|
4977
|
+
endToken = tailLexer.nextToken();
|
|
4978
|
+
} catch (error) {
|
|
4979
|
+
if (!(error instanceof PdfError) || error.code !== "E_PARSE") throw error;
|
|
4980
|
+
}
|
|
4981
|
+
if (endToken?.kind === "keyword" && endToken.value === "endstream") {
|
|
4688
4982
|
rawStreamBytes = bytes.subarray(streamStart, candidateEnd);
|
|
4689
|
-
streamEnd =
|
|
4983
|
+
streamEnd = tailLexer.offset;
|
|
4690
4984
|
}
|
|
4691
4985
|
}
|
|
4692
4986
|
if (!rawStreamBytes) {
|
|
@@ -9629,6 +9923,24 @@ function initializeTile(context, tileIndex) {
|
|
|
9629
9923
|
}
|
|
9630
9924
|
tile.codingStyleDefaultParameters = context.currentTile.COD;
|
|
9631
9925
|
}
|
|
9926
|
+
function createCalibratedColorSpace(doc, family, parameters) {
|
|
9927
|
+
const dict = doc.resolveDict(parameters);
|
|
9928
|
+
const array = (key) => {
|
|
9929
|
+
const value = dict ? doc.resolveArray(dictGet(dict, key)) : void 0;
|
|
9930
|
+
return value?.items.map((item) => {
|
|
9931
|
+
const number = doc.resolve(item);
|
|
9932
|
+
return number?.kind === "number" ? number.value : 0;
|
|
9933
|
+
});
|
|
9934
|
+
};
|
|
9935
|
+
const whitePoint = array("WhitePoint") ?? [0.95047, 1, 1.08883];
|
|
9936
|
+
const blackPoint = array("BlackPoint");
|
|
9937
|
+
if (family === "CalGray") {
|
|
9938
|
+
const gamma = dict ? doc.resolve(dictGet(dict, "Gamma")) : void 0;
|
|
9939
|
+
return new CalGrayCS(whitePoint, blackPoint, gamma?.kind === "number" ? gamma.value : void 0);
|
|
9940
|
+
}
|
|
9941
|
+
if (family === "CalRGB") return new CalRGBCS(whitePoint, blackPoint, array("Gamma"), array("Matrix"));
|
|
9942
|
+
return new LabCS(whitePoint, blackPoint, array("Range"));
|
|
9943
|
+
}
|
|
9632
9944
|
function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
9633
9945
|
if (!csNode) return { colorSpace: "rgb", colorSpaceLabel: "rgb", components: 3 };
|
|
9634
9946
|
const resolved = doc.resolve(csNode);
|
|
@@ -9669,7 +9981,7 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
|
9669
9981
|
palette = lookupNode.bytes;
|
|
9670
9982
|
}
|
|
9671
9983
|
let resolvedBaseComp = baseInfo.components;
|
|
9672
|
-
if (palette && (baseInfo.
|
|
9984
|
+
if (palette && (baseInfo.isSeparation || baseInfo.isDeviceN || baseInfo.calibrated !== void 0)) {
|
|
9673
9985
|
const numEntries = Math.max(1, Math.min(hival + 1, Math.floor(palette.length / Math.max(1, baseInfo.components))));
|
|
9674
9986
|
const rgbaPal = decodeSamplesToRgba(palette, numEntries, 1, 8, baseInfo);
|
|
9675
9987
|
const rgbPal = new Uint8Array(numEntries * 3);
|
|
@@ -9699,74 +10011,21 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
|
9699
10011
|
}
|
|
9700
10012
|
return { colorSpace: "rgb", colorSpaceLabel: "icc", components: 3 };
|
|
9701
10013
|
}
|
|
9702
|
-
if (kindName === "CalGray") {
|
|
9703
|
-
const
|
|
9704
|
-
const gammaNode = calDict ? doc.resolve(dictGet(calDict, "Gamma")) : void 0;
|
|
9705
|
-
const gamma = gammaNode?.kind === "number" && gammaNode.value > 0 ? gammaNode.value : 1;
|
|
9706
|
-
return { colorSpace: "gray", colorSpaceLabel: "cal-gray", components: 1, calGrayGamma: gamma };
|
|
9707
|
-
}
|
|
9708
|
-
if (kindName === "CalRGB") {
|
|
9709
|
-
const calDict = doc.resolveDict(resolved.items[1]);
|
|
9710
|
-
const gammaArr = calDict ? doc.resolveArray(dictGet(calDict, "Gamma")) : void 0;
|
|
9711
|
-
let calRgbGamma = [1, 1, 1];
|
|
9712
|
-
if (gammaArr && gammaArr.items.length >= 3) {
|
|
9713
|
-
const gNums = gammaArr.items.slice(0, 3).map((it) => {
|
|
9714
|
-
const r = doc.resolve(it);
|
|
9715
|
-
return r?.kind === "number" && r.value > 0 ? r.value : 1;
|
|
9716
|
-
});
|
|
9717
|
-
calRgbGamma = [gNums[0], gNums[1], gNums[2]];
|
|
9718
|
-
}
|
|
9719
|
-
const matArr = calDict ? doc.resolveArray(dictGet(calDict, "Matrix")) : void 0;
|
|
9720
|
-
let calRgbMatrix;
|
|
9721
|
-
if (matArr && matArr.items.length >= 9) {
|
|
9722
|
-
calRgbMatrix = matArr.items.slice(0, 9).map((it) => {
|
|
9723
|
-
const r = doc.resolve(it);
|
|
9724
|
-
return r?.kind === "number" ? r.value : 0;
|
|
9725
|
-
});
|
|
9726
|
-
}
|
|
10014
|
+
if (kindName === "CalGray" || kindName === "CalRGB" || kindName === "Lab") {
|
|
10015
|
+
const calibrated = createCalibratedColorSpace(doc, kindName, resolved.items[1]);
|
|
9727
10016
|
return {
|
|
9728
|
-
colorSpace: "rgb",
|
|
9729
|
-
colorSpaceLabel: "cal-rgb",
|
|
9730
|
-
components: 3,
|
|
9731
|
-
|
|
9732
|
-
calRgbMatrix
|
|
10017
|
+
colorSpace: kindName === "CalGray" ? "gray" : "rgb",
|
|
10018
|
+
colorSpaceLabel: kindName === "CalGray" ? "cal-gray" : kindName === "CalRGB" ? "cal-rgb" : "lab",
|
|
10019
|
+
components: kindName === "CalGray" ? 1 : 3,
|
|
10020
|
+
calibrated
|
|
9733
10021
|
};
|
|
9734
10022
|
}
|
|
9735
|
-
if (kindName === "Lab") {
|
|
9736
|
-
const labDict = doc.resolveDict(resolved.items[1]);
|
|
9737
|
-
const rangeArr = labDict ? doc.resolveArray(dictGet(labDict, "Range")) : void 0;
|
|
9738
|
-
let labRange = [-100, 100, -100, 100];
|
|
9739
|
-
if (rangeArr && rangeArr.items.length >= 4) {
|
|
9740
|
-
const nums = rangeArr.items.slice(0, 4).map((it) => {
|
|
9741
|
-
const r = doc.resolve(it);
|
|
9742
|
-
return r?.kind === "number" ? r.value : 0;
|
|
9743
|
-
});
|
|
9744
|
-
labRange = [nums[0], nums[1], nums[2], nums[3]];
|
|
9745
|
-
}
|
|
9746
|
-
return { colorSpace: "rgb", colorSpaceLabel: "lab", components: 3, isLab: true, labRange };
|
|
9747
|
-
}
|
|
9748
10023
|
if (kindName === "Separation" || kindName === "DeviceN") {
|
|
9749
10024
|
const isDevN = kindName === "DeviceN";
|
|
9750
10025
|
const namesArr = isDevN ? doc.resolveArray(resolved.items[1]) : void 0;
|
|
9751
10026
|
const devNComponents = isDevN && namesArr ? Math.max(1, namesArr.items.length) : 1;
|
|
9752
10027
|
const altInfo = resolveColorSpaceInfo(doc, resolved.items[2], resourcesDict);
|
|
9753
10028
|
const altSpace = altInfo.colorSpace === "cmyk" ? "cmyk" : altInfo.colorSpace === "gray" ? "gray" : "rgb";
|
|
9754
|
-
const fnResolved = doc.resolve(resolved.items[3]);
|
|
9755
|
-
const fnDict = fnResolved?.kind === "stream" ? fnResolved.dict : fnResolved?.kind === "dict" ? fnResolved : void 0;
|
|
9756
|
-
const ftNode = fnDict ? doc.resolve(dictGet(fnDict, "FunctionType")) : void 0;
|
|
9757
|
-
const tintFunctionType = ftNode?.kind === "number" ? ftNode.value : 2;
|
|
9758
|
-
const c0Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C0")) : void 0;
|
|
9759
|
-
const c1Arr = fnDict ? doc.resolveArray(dictGet(fnDict, "C1")) : void 0;
|
|
9760
|
-
const nNode = fnDict ? doc.resolve(dictGet(fnDict, "N")) : void 0;
|
|
9761
|
-
const c0 = c0Arr ? c0Arr.items.map((it) => {
|
|
9762
|
-
const r = doc.resolve(it);
|
|
9763
|
-
return r?.kind === "number" ? r.value : 0;
|
|
9764
|
-
}) : altSpace === "cmyk" ? [0, 0, 0, 0] : altSpace === "gray" ? [1] : [1, 1, 1];
|
|
9765
|
-
const c1 = c1Arr ? c1Arr.items.map((it) => {
|
|
9766
|
-
const r = doc.resolve(it);
|
|
9767
|
-
return r?.kind === "number" ? r.value : 0;
|
|
9768
|
-
}) : altSpace === "cmyk" ? [0, 0, 0, 1] : altSpace === "gray" ? [0] : [0, 0, 0];
|
|
9769
|
-
const sepN = nNode?.kind === "number" && nNode.value > 0 ? nNode.value : 1;
|
|
9770
10029
|
return {
|
|
9771
10030
|
colorSpace: altSpace,
|
|
9772
10031
|
colorSpaceLabel: isDevN ? "devn" : "sep",
|
|
@@ -9774,12 +10033,9 @@ function resolveColorSpaceInfo(doc, csNode, resourcesDict) {
|
|
|
9774
10033
|
isSeparation: !isDevN,
|
|
9775
10034
|
isDeviceN: isDevN,
|
|
9776
10035
|
separationAltSpace: altSpace,
|
|
9777
|
-
|
|
9778
|
-
separationC1: c1,
|
|
9779
|
-
separationN: sepN,
|
|
10036
|
+
alternateCalibrated: altInfo.calibrated,
|
|
9780
10037
|
tintFunctionDoc: doc,
|
|
9781
|
-
tintFunctionNode: resolved.items[3]
|
|
9782
|
-
tintFunctionType
|
|
10038
|
+
tintFunctionNode: resolved.items[3]
|
|
9783
10039
|
};
|
|
9784
10040
|
}
|
|
9785
10041
|
}
|
|
@@ -9929,141 +10185,55 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
9929
10185
|
const rgba = new Uint8Array(width * height * 4);
|
|
9930
10186
|
const pixelCount = width * height;
|
|
9931
10187
|
if (csInfo.isSeparation || csInfo.isDeviceN) {
|
|
9932
|
-
const c0 = csInfo.separationC0 ?? [1, 1, 1];
|
|
9933
|
-
const c1 = csInfo.separationC1 ?? [0, 0, 0];
|
|
9934
|
-
const expN = csInfo.separationN ?? 1;
|
|
9935
10188
|
const alt = csInfo.separationAltSpace ?? "rgb";
|
|
9936
10189
|
const numCh = Math.max(1, csInfo.components);
|
|
9937
10190
|
const step = bpc === 16 ? 2 : 1;
|
|
9938
|
-
const useGenericTintFn = csInfo.tintFunctionDoc !== void 0 && csInfo.tintFunctionNode !== void 0 && (csInfo.tintFunctionType === 0 || csInfo.tintFunctionType === 3 || csInfo.tintFunctionType === 4);
|
|
9939
10191
|
for (let p = 0; p < pixelCount; p++) {
|
|
9940
10192
|
const chVals = [];
|
|
9941
|
-
let wSum = 0;
|
|
9942
10193
|
for (let ch3 = 0; ch3 < numCh; ch3++) {
|
|
9943
10194
|
const sRaw = (rawSamples[(p * numCh + ch3) * step] ?? 0) / 255;
|
|
9944
|
-
|
|
9945
|
-
chVals.push(tRemapped);
|
|
9946
|
-
wSum += Math.pow(Math.max(0, Math.min(1, tRemapped)), expN);
|
|
9947
|
-
}
|
|
9948
|
-
if (useGenericTintFn) {
|
|
9949
|
-
const outComps = evalShadingFunctionToComponents(
|
|
9950
|
-
csInfo.tintFunctionDoc,
|
|
9951
|
-
csInfo.tintFunctionNode,
|
|
9952
|
-
chVals
|
|
9953
|
-
);
|
|
9954
|
-
if (alt === "cmyk") {
|
|
9955
|
-
const c = outComps[0] ?? 0;
|
|
9956
|
-
const m = outComps[1] ?? 0;
|
|
9957
|
-
const y = outComps[2] ?? 0;
|
|
9958
|
-
const k = outComps[3] ?? 0;
|
|
9959
|
-
rgba[p * 4] = Math.round(Math.max(0, Math.min(1, (1 - c) * (1 - k))) * 255);
|
|
9960
|
-
rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, (1 - m) * (1 - k))) * 255);
|
|
9961
|
-
rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, (1 - y) * (1 - k))) * 255);
|
|
9962
|
-
} else if (alt === "gray") {
|
|
9963
|
-
const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
|
|
9964
|
-
rgba[p * 4] = gByte;
|
|
9965
|
-
rgba[p * 4 + 1] = gByte;
|
|
9966
|
-
rgba[p * 4 + 2] = gByte;
|
|
9967
|
-
} else {
|
|
9968
|
-
rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
|
|
9969
|
-
rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
|
|
9970
|
-
rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
|
|
9971
|
-
}
|
|
9972
|
-
rgba[p * 4 + 3] = 255;
|
|
9973
|
-
continue;
|
|
10195
|
+
chVals.push(remapUnitSampleWithDecode(sRaw, ch3, decodePairs));
|
|
9974
10196
|
}
|
|
9975
|
-
const
|
|
9976
|
-
|
|
9977
|
-
|
|
9978
|
-
|
|
9979
|
-
|
|
9980
|
-
|
|
9981
|
-
rgba
|
|
9982
|
-
|
|
9983
|
-
rgba[
|
|
10197
|
+
const outComps = evalShadingFunctionToComponents(
|
|
10198
|
+
csInfo.tintFunctionDoc,
|
|
10199
|
+
csInfo.tintFunctionNode,
|
|
10200
|
+
chVals
|
|
10201
|
+
);
|
|
10202
|
+
if (csInfo.alternateCalibrated) {
|
|
10203
|
+
rgba.set(csInfo.alternateCalibrated.getRgb(outComps, 0), p * 4);
|
|
10204
|
+
} else if (alt === "cmyk") {
|
|
10205
|
+
rgba.set(cmykColorSpace.getRgb([outComps[0] ?? 0, outComps[1] ?? 0, outComps[2] ?? 0, outComps[3] ?? 0], 0), p * 4);
|
|
9984
10206
|
} else if (alt === "gray") {
|
|
9985
|
-
const
|
|
9986
|
-
const gByte = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
|
|
10207
|
+
const gByte = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
|
|
9987
10208
|
rgba[p * 4] = gByte;
|
|
9988
10209
|
rgba[p * 4 + 1] = gByte;
|
|
9989
10210
|
rgba[p * 4 + 2] = gByte;
|
|
9990
10211
|
} else {
|
|
9991
|
-
|
|
9992
|
-
|
|
9993
|
-
|
|
9994
|
-
rgba[p * 4] = Math.round(Math.max(0, Math.min(1, rVal)) * 255);
|
|
9995
|
-
rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, gVal)) * 255);
|
|
9996
|
-
rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, bVal)) * 255);
|
|
10212
|
+
rgba[p * 4] = Math.round(Math.max(0, Math.min(1, outComps[0] ?? 0)) * 255);
|
|
10213
|
+
rgba[p * 4 + 1] = Math.round(Math.max(0, Math.min(1, outComps[1] ?? 0)) * 255);
|
|
10214
|
+
rgba[p * 4 + 2] = Math.round(Math.max(0, Math.min(1, outComps[2] ?? 0)) * 255);
|
|
9997
10215
|
}
|
|
9998
10216
|
rgba[p * 4 + 3] = 255;
|
|
9999
10217
|
}
|
|
10000
|
-
} else if (csInfo.
|
|
10001
|
-
const
|
|
10002
|
-
const
|
|
10003
|
-
const toSrgb = (u) => {
|
|
10004
|
-
const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
|
|
10005
|
-
return Math.round(Math.max(0, Math.min(1, c)) * 255);
|
|
10006
|
-
};
|
|
10218
|
+
} else if (csInfo.calibrated?.name === "Lab") {
|
|
10219
|
+
const { amin, amax, bmin, bmax } = csInfo.calibrated;
|
|
10220
|
+
const step = bpc === 16 ? 2 : 1;
|
|
10007
10221
|
for (let p = 0; p < pixelCount; p++) {
|
|
10008
|
-
const
|
|
10009
|
-
const
|
|
10010
|
-
const
|
|
10011
|
-
|
|
10012
|
-
if (L <= 0.01) {
|
|
10013
|
-
rgba[p * 4] = 0;
|
|
10014
|
-
rgba[p * 4 + 1] = 0;
|
|
10015
|
-
rgba[p * 4 + 2] = 0;
|
|
10016
|
-
rgba[p * 4 + 3] = 255;
|
|
10017
|
-
continue;
|
|
10018
|
-
}
|
|
10019
|
-
const a = amin + s1 * (amax - amin);
|
|
10020
|
-
const b = bmin + s2 * (bmax - bmin);
|
|
10021
|
-
const fy = (L + 16) / 116;
|
|
10022
|
-
const fx = fy + a / 500;
|
|
10023
|
-
const fz = fy - b / 200;
|
|
10024
|
-
const X = 0.95047 * invF(fx);
|
|
10025
|
-
const Y = 1 * invF(fy);
|
|
10026
|
-
const Z = 1.08883 * invF(fz);
|
|
10027
|
-
const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
|
|
10028
|
-
const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
|
|
10029
|
-
const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
|
|
10030
|
-
rgba[p * 4] = toSrgb(linR);
|
|
10031
|
-
rgba[p * 4 + 1] = toSrgb(linG);
|
|
10032
|
-
rgba[p * 4 + 2] = toSrgb(linB);
|
|
10222
|
+
const L = (rawSamples[p * 3 * step] ?? 0) / 255 * 100;
|
|
10223
|
+
const a = amin + (rawSamples[(p * 3 + 1) * step] ?? 128) / 255 * (amax - amin);
|
|
10224
|
+
const b = bmin + (rawSamples[(p * 3 + 2) * step] ?? 128) / 255 * (bmax - bmin);
|
|
10225
|
+
rgba.set(csInfo.calibrated.getRgb([L, a, b], 0), p * 4);
|
|
10033
10226
|
rgba[p * 4 + 3] = 255;
|
|
10034
10227
|
}
|
|
10035
10228
|
} else if (csInfo.colorSpace === "rgb") {
|
|
10036
|
-
const hasCalRgb = Boolean(csInfo.calRgbGamma || csInfo.calRgbMatrix);
|
|
10037
|
-
const toSrgbByte = (u) => {
|
|
10038
|
-
const c = u <= 31308e-7 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055;
|
|
10039
|
-
return Math.round(Math.max(0, Math.min(1, c)) * 255);
|
|
10040
|
-
};
|
|
10041
10229
|
const writeRgbPixel = (p, rByte, gByte, bByte) => {
|
|
10042
|
-
|
|
10043
|
-
|
|
10044
|
-
|
|
10045
|
-
if (
|
|
10046
|
-
|
|
10047
|
-
|
|
10048
|
-
|
|
10049
|
-
const cg = Math.pow(bU, gb);
|
|
10050
|
-
if (csInfo.calRgbMatrix && csInfo.calRgbMatrix.length >= 9) {
|
|
10051
|
-
const m = csInfo.calRgbMatrix;
|
|
10052
|
-
const X = m[0] * ag + m[3] * bg + m[6] * cg;
|
|
10053
|
-
const Y = m[1] * ag + m[4] * bg + m[7] * cg;
|
|
10054
|
-
const Z = m[2] * ag + m[5] * bg + m[8] * cg;
|
|
10055
|
-
const linR = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
|
|
10056
|
-
const linG = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
|
|
10057
|
-
const linB = X * 0.0557 + Y * -0.204 + Z * 1.057;
|
|
10058
|
-
rgba[p * 4] = toSrgbByte(linR);
|
|
10059
|
-
rgba[p * 4 + 1] = toSrgbByte(linG);
|
|
10060
|
-
rgba[p * 4 + 2] = toSrgbByte(linB);
|
|
10061
|
-
rgba[p * 4 + 3] = 255;
|
|
10062
|
-
return;
|
|
10063
|
-
}
|
|
10064
|
-
rU = ag;
|
|
10065
|
-
gU = bg;
|
|
10066
|
-
bU = cg;
|
|
10230
|
+
const rU = remapUnitSampleWithDecode(rByte / 255, 0, decodePairs);
|
|
10231
|
+
const gU = remapUnitSampleWithDecode(gByte / 255, 1, decodePairs);
|
|
10232
|
+
const bU = remapUnitSampleWithDecode(bByte / 255, 2, decodePairs);
|
|
10233
|
+
if (csInfo.calibrated) {
|
|
10234
|
+
rgba.set(csInfo.calibrated.getRgb([rU, gU, bU], 0), p * 4);
|
|
10235
|
+
rgba[p * 4 + 3] = 255;
|
|
10236
|
+
return;
|
|
10067
10237
|
}
|
|
10068
10238
|
rgba[p * 4] = Math.round(rU * 255);
|
|
10069
10239
|
rgba[p * 4 + 1] = Math.round(gU * 255);
|
|
@@ -10083,10 +10253,11 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
10083
10253
|
}
|
|
10084
10254
|
} else if (csInfo.colorSpace === "gray") {
|
|
10085
10255
|
const writeGrayPixel = (p, gByte) => {
|
|
10086
|
-
|
|
10087
|
-
if (csInfo.
|
|
10088
|
-
|
|
10089
|
-
|
|
10256
|
+
const gU = remapUnitSampleWithDecode(gByte / 255, 0, decodePairs);
|
|
10257
|
+
if (csInfo.calibrated) {
|
|
10258
|
+
rgba.set(csInfo.calibrated.getRgb([gU], 0), p * 4);
|
|
10259
|
+
rgba[p * 4 + 3] = 255;
|
|
10260
|
+
return;
|
|
10090
10261
|
}
|
|
10091
10262
|
const outG = Math.round(Math.max(0, Math.min(1, gU)) * 255);
|
|
10092
10263
|
rgba[p * 4] = outG;
|
|
@@ -10142,9 +10313,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
10142
10313
|
const m = remapUnitSampleWithDecode((rawSamples[p * stride + chStep] ?? 0) / 255, 1, decodePairs);
|
|
10143
10314
|
const y = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 2] ?? 0) / 255, 2, decodePairs);
|
|
10144
10315
|
const k = remapUnitSampleWithDecode((rawSamples[p * stride + chStep * 3] ?? 0) / 255, 3, decodePairs);
|
|
10145
|
-
rgba
|
|
10146
|
-
rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
|
|
10147
|
-
rgba[p * 4 + 2] = Math.round((1 - y) * (1 - k) * 255);
|
|
10316
|
+
rgba.set(cmykColorSpace.getRgb([c, m, y, k], 0), p * 4);
|
|
10148
10317
|
rgba[p * 4 + 3] = 255;
|
|
10149
10318
|
}
|
|
10150
10319
|
} else if (csInfo.colorSpace === "index") {
|
|
@@ -10182,9 +10351,7 @@ function decodeSamplesToRgba(rawSamples, width, height, bpc, csInfo, alphaSample
|
|
|
10182
10351
|
const m = pal[idx * 4 + 1] / 255;
|
|
10183
10352
|
const yel = pal[idx * 4 + 2] / 255;
|
|
10184
10353
|
const k = pal[idx * 4 + 3] / 255;
|
|
10185
|
-
rgba
|
|
10186
|
-
rgba[p * 4 + 1] = Math.round((1 - m) * (1 - k) * 255);
|
|
10187
|
-
rgba[p * 4 + 2] = Math.round((1 - yel) * (1 - k) * 255);
|
|
10354
|
+
rgba.set(cmykColorSpace.getRgb([c, m, yel, k], 0), p * 4);
|
|
10188
10355
|
} else {
|
|
10189
10356
|
rgba[p * 4] = pal[idx * baseComp];
|
|
10190
10357
|
rgba[p * 4 + 1] = pal[idx * baseComp + 1];
|
|
@@ -10655,193 +10822,6 @@ function resolvePageFonts(doc, resourcesDict) {
|
|
|
10655
10822
|
}
|
|
10656
10823
|
return fonts;
|
|
10657
10824
|
}
|
|
10658
|
-
function evaluateType4PostScriptTokens(tokens, initialStack) {
|
|
10659
|
-
const stack = [...initialStack];
|
|
10660
|
-
const runRange = (start, end) => {
|
|
10661
|
-
let i = start;
|
|
10662
|
-
while (i < end) {
|
|
10663
|
-
const tok = tokens[i];
|
|
10664
|
-
if (tok === "{") {
|
|
10665
|
-
let depth = 1;
|
|
10666
|
-
let j = i + 1;
|
|
10667
|
-
while (j < end && depth > 0) {
|
|
10668
|
-
if (tokens[j] === "{") depth++;
|
|
10669
|
-
else if (tokens[j] === "}") depth--;
|
|
10670
|
-
j++;
|
|
10671
|
-
}
|
|
10672
|
-
const blockStart = i + 1;
|
|
10673
|
-
const blockEnd = j - 1;
|
|
10674
|
-
if (j < end && tokens[j] === "{") {
|
|
10675
|
-
let depth2 = 1;
|
|
10676
|
-
let k = j + 1;
|
|
10677
|
-
while (k < end && depth2 > 0) {
|
|
10678
|
-
if (tokens[k] === "{") depth2++;
|
|
10679
|
-
else if (tokens[k] === "}") depth2--;
|
|
10680
|
-
k++;
|
|
10681
|
-
}
|
|
10682
|
-
if (k < end && tokens[k] === "ifelse") {
|
|
10683
|
-
const cond = stack.pop() ?? 0;
|
|
10684
|
-
if (cond !== 0) runRange(blockStart, blockEnd);
|
|
10685
|
-
else runRange(j + 1, k - 1);
|
|
10686
|
-
i = k + 1;
|
|
10687
|
-
continue;
|
|
10688
|
-
}
|
|
10689
|
-
}
|
|
10690
|
-
if (j < end && tokens[j] === "if") {
|
|
10691
|
-
const cond = stack.pop() ?? 0;
|
|
10692
|
-
if (cond !== 0) runRange(blockStart, blockEnd);
|
|
10693
|
-
i = j + 1;
|
|
10694
|
-
continue;
|
|
10695
|
-
}
|
|
10696
|
-
runRange(blockStart, blockEnd);
|
|
10697
|
-
i = j;
|
|
10698
|
-
continue;
|
|
10699
|
-
}
|
|
10700
|
-
if (tok === "}") {
|
|
10701
|
-
i++;
|
|
10702
|
-
continue;
|
|
10703
|
-
}
|
|
10704
|
-
const numVal2 = Number(tok);
|
|
10705
|
-
if (tok.length > 0 && !Number.isNaN(numVal2)) {
|
|
10706
|
-
stack.push(numVal2);
|
|
10707
|
-
} else if (tok === "true") {
|
|
10708
|
-
stack.push(1);
|
|
10709
|
-
} else if (tok === "false") {
|
|
10710
|
-
stack.push(0);
|
|
10711
|
-
} else if (tok === "add") {
|
|
10712
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
10713
|
-
stack.push(a + b);
|
|
10714
|
-
} else if (tok === "sub") {
|
|
10715
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
10716
|
-
stack.push(a - b);
|
|
10717
|
-
} else if (tok === "mul") {
|
|
10718
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
10719
|
-
stack.push(a * b);
|
|
10720
|
-
} else if (tok === "div") {
|
|
10721
|
-
const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
|
|
10722
|
-
stack.push(Math.abs(b) > 1e-12 ? a / b : 0);
|
|
10723
|
-
} else if (tok === "idiv") {
|
|
10724
|
-
const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
|
|
10725
|
-
stack.push(Math.abs(b) > 1e-12 ? Math.trunc(a / b) : 0);
|
|
10726
|
-
} else if (tok === "mod") {
|
|
10727
|
-
const b = stack.pop() ?? 1, a = stack.pop() ?? 0;
|
|
10728
|
-
stack.push(Math.abs(b) > 1e-12 ? a % b : 0);
|
|
10729
|
-
} else if (tok === "neg") {
|
|
10730
|
-
stack.push(-(stack.pop() ?? 0));
|
|
10731
|
-
} else if (tok === "abs") {
|
|
10732
|
-
stack.push(Math.abs(stack.pop() ?? 0));
|
|
10733
|
-
} else if (tok === "ceiling") {
|
|
10734
|
-
stack.push(Math.ceil(stack.pop() ?? 0));
|
|
10735
|
-
} else if (tok === "floor") {
|
|
10736
|
-
stack.push(Math.floor(stack.pop() ?? 0));
|
|
10737
|
-
} else if (tok === "round") {
|
|
10738
|
-
stack.push(Math.round(stack.pop() ?? 0));
|
|
10739
|
-
} else if (tok === "truncate" || tok === "cvi") {
|
|
10740
|
-
stack.push(Math.trunc(stack.pop() ?? 0));
|
|
10741
|
-
} else if (tok === "sqrt") {
|
|
10742
|
-
stack.push(Math.sqrt(Math.max(0, stack.pop() ?? 0)));
|
|
10743
|
-
} else if (tok === "sin") {
|
|
10744
|
-
stack.push(Math.sin((stack.pop() ?? 0) * Math.PI / 180));
|
|
10745
|
-
} else if (tok === "cos") {
|
|
10746
|
-
stack.push(Math.cos((stack.pop() ?? 0) * Math.PI / 180));
|
|
10747
|
-
} else if (tok === "atan") {
|
|
10748
|
-
const dx = stack.pop() ?? 1, dy = stack.pop() ?? 0;
|
|
10749
|
-
let deg = Math.atan2(dy, dx) * 180 / Math.PI;
|
|
10750
|
-
if (deg < 0) deg += 360;
|
|
10751
|
-
stack.push(deg);
|
|
10752
|
-
} else if (tok === "exp") {
|
|
10753
|
-
const exp = stack.pop() ?? 1, base = stack.pop() ?? 0;
|
|
10754
|
-
stack.push(Math.pow(base, exp));
|
|
10755
|
-
} else if (tok === "ln") {
|
|
10756
|
-
stack.push(Math.log(Math.max(1e-12, stack.pop() ?? 1)));
|
|
10757
|
-
} else if (tok === "log") {
|
|
10758
|
-
stack.push(Math.log10(Math.max(1e-12, stack.pop() ?? 1)));
|
|
10759
|
-
} else if (tok === "dup") {
|
|
10760
|
-
if (stack.length > 0) stack.push(stack[stack.length - 1]);
|
|
10761
|
-
} else if (tok === "exch") {
|
|
10762
|
-
if (stack.length >= 2) {
|
|
10763
|
-
const b = stack.pop(), a = stack.pop();
|
|
10764
|
-
stack.push(b, a);
|
|
10765
|
-
}
|
|
10766
|
-
} else if (tok === "pop") {
|
|
10767
|
-
stack.pop();
|
|
10768
|
-
} else if (tok === "copy") {
|
|
10769
|
-
const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
|
|
10770
|
-
const slice = stack.slice(Math.max(0, stack.length - n));
|
|
10771
|
-
stack.push(...slice);
|
|
10772
|
-
} else if (tok === "index") {
|
|
10773
|
-
const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
|
|
10774
|
-
const idx = stack.length - 1 - n;
|
|
10775
|
-
if (idx >= 0 && idx < stack.length) stack.push(stack[idx]);
|
|
10776
|
-
} else if (tok === "roll") {
|
|
10777
|
-
const jShift = Math.trunc(stack.pop() ?? 0);
|
|
10778
|
-
const n = Math.max(0, Math.trunc(stack.pop() ?? 0));
|
|
10779
|
-
if (n > 0 && stack.length >= n) {
|
|
10780
|
-
const sub = stack.splice(stack.length - n, n);
|
|
10781
|
-
const modShift = (jShift % n + n) % n;
|
|
10782
|
-
const rolled = [...sub.slice(n - modShift), ...sub.slice(0, n - modShift)];
|
|
10783
|
-
stack.push(...rolled);
|
|
10784
|
-
}
|
|
10785
|
-
} else if (tok === "eq") {
|
|
10786
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
10787
|
-
stack.push(Math.abs(a - b) < 1e-9 ? 1 : 0);
|
|
10788
|
-
} else if (tok === "ne") {
|
|
10789
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
10790
|
-
stack.push(Math.abs(a - b) >= 1e-9 ? 1 : 0);
|
|
10791
|
-
} else if (tok === "gt") {
|
|
10792
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
10793
|
-
stack.push(a > b ? 1 : 0);
|
|
10794
|
-
} else if (tok === "ge") {
|
|
10795
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
10796
|
-
stack.push(a >= b ? 1 : 0);
|
|
10797
|
-
} else if (tok === "lt") {
|
|
10798
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
10799
|
-
stack.push(a < b ? 1 : 0);
|
|
10800
|
-
} else if (tok === "le") {
|
|
10801
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
10802
|
-
stack.push(a <= b ? 1 : 0);
|
|
10803
|
-
} else if (tok === "and") {
|
|
10804
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
10805
|
-
stack.push(a !== 0 && b !== 0 ? 1 : 0);
|
|
10806
|
-
} else if (tok === "or") {
|
|
10807
|
-
const b = stack.pop() ?? 0, a = stack.pop() ?? 0;
|
|
10808
|
-
stack.push(a !== 0 || b !== 0 ? 1 : 0);
|
|
10809
|
-
} else if (tok === "not") {
|
|
10810
|
-
const a = stack.pop() ?? 0;
|
|
10811
|
-
stack.push(a === 0 ? 1 : 0);
|
|
10812
|
-
}
|
|
10813
|
-
i++;
|
|
10814
|
-
}
|
|
10815
|
-
};
|
|
10816
|
-
runRange(0, tokens.length);
|
|
10817
|
-
return stack;
|
|
10818
|
-
}
|
|
10819
|
-
function tokenizePostScriptCode(bytes) {
|
|
10820
|
-
const tokens = [];
|
|
10821
|
-
let cur = "";
|
|
10822
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
10823
|
-
const ch3 = String.fromCharCode(bytes[i]);
|
|
10824
|
-
if (ch3 === "{" || ch3 === "}") {
|
|
10825
|
-
if (cur.length > 0) {
|
|
10826
|
-
tokens.push(cur);
|
|
10827
|
-
cur = "";
|
|
10828
|
-
}
|
|
10829
|
-
tokens.push(ch3);
|
|
10830
|
-
} else if (ch3 === " " || ch3 === " " || ch3 === "\n" || ch3 === "\r") {
|
|
10831
|
-
if (cur.length > 0) {
|
|
10832
|
-
tokens.push(cur);
|
|
10833
|
-
cur = "";
|
|
10834
|
-
}
|
|
10835
|
-
} else {
|
|
10836
|
-
cur += ch3;
|
|
10837
|
-
}
|
|
10838
|
-
}
|
|
10839
|
-
if (cur.length > 0) tokens.push(cur);
|
|
10840
|
-
if (tokens[0] === "{" && tokens[tokens.length - 1] === "}") {
|
|
10841
|
-
return tokens.slice(1, -1);
|
|
10842
|
-
}
|
|
10843
|
-
return tokens;
|
|
10844
|
-
}
|
|
10845
10825
|
function evalShadingFunctionToComponents(doc, fnNode, inputs) {
|
|
10846
10826
|
const inArr = typeof inputs === "number" ? [inputs] : inputs;
|
|
10847
10827
|
const t = inArr[0] ?? 0;
|
|
@@ -10888,35 +10868,50 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
|
|
|
10888
10868
|
const decode = getNums("Decode", range);
|
|
10889
10869
|
const nOut = Math.max(1, Math.floor((decode.length || range.length || 6) / 2));
|
|
10890
10870
|
const mIn = Math.max(1, size.length);
|
|
10891
|
-
|
|
10871
|
+
const streamBytes = doc.decodeStream(resolved);
|
|
10872
|
+
let vertices = [{ index: 0, weight: 1 }];
|
|
10892
10873
|
let stride = 1;
|
|
10893
10874
|
for (let i = 0; i < mIn; i++) {
|
|
10894
10875
|
const d02 = dom[i * 2] ?? 0;
|
|
10895
10876
|
const d12 = dom[i * 2 + 1] ?? 1;
|
|
10896
|
-
const sMax = Math.max(
|
|
10877
|
+
const sMax = Math.max(0, (size[i] ?? 2) - 1);
|
|
10897
10878
|
const e0 = encode[i * 2] ?? 0;
|
|
10898
10879
|
const e1 = encode[i * 2 + 1] ?? sMax;
|
|
10899
10880
|
const x = Math.max(d02, Math.min(d12, inArr[i] ?? 0));
|
|
10900
|
-
const u =
|
|
10901
|
-
const
|
|
10902
|
-
|
|
10881
|
+
const u = d12 === d02 ? 0 : (x - d02) / (d12 - d02);
|
|
10882
|
+
const e = Math.max(0, Math.min(sMax, e0 + u * (e1 - e0)));
|
|
10883
|
+
const low = Math.floor(e), fraction = e - low;
|
|
10884
|
+
const next = [];
|
|
10885
|
+
for (const vertex of vertices) {
|
|
10886
|
+
const index = vertex.index + low * stride;
|
|
10887
|
+
if (index * nOut * bps < streamBytes.length * 8) next.push({ index, weight: vertex.weight * (1 - fraction) });
|
|
10888
|
+
if (fraction && (index + stride) * nOut * bps < streamBytes.length * 8) {
|
|
10889
|
+
next.push({ index: index + stride, weight: vertex.weight * fraction });
|
|
10890
|
+
}
|
|
10891
|
+
}
|
|
10892
|
+
vertices = next;
|
|
10903
10893
|
stride *= size[i] ?? 2;
|
|
10904
10894
|
}
|
|
10905
|
-
const
|
|
10895
|
+
const maxSample = 2 ** bps - 1;
|
|
10896
|
+
const readSample = (index) => {
|
|
10897
|
+
let bitOffset = index * bps, remaining = bps, value = 0;
|
|
10898
|
+
while (remaining > 0) {
|
|
10899
|
+
const bitInByte = bitOffset % 8;
|
|
10900
|
+
const take = Math.min(remaining, 8 - bitInByte);
|
|
10901
|
+
const byte = streamBytes[Math.floor(bitOffset / 8)] ?? 0;
|
|
10902
|
+
value = value * 2 ** take + (byte >> 8 - bitInByte - take & (1 << take) - 1);
|
|
10903
|
+
bitOffset += take;
|
|
10904
|
+
remaining -= take;
|
|
10905
|
+
}
|
|
10906
|
+
return value / maxSample;
|
|
10907
|
+
};
|
|
10906
10908
|
const out2 = [];
|
|
10907
|
-
const maxSample = bps === 16 ? 65535 : 255;
|
|
10908
10909
|
for (let j = 0; j < nOut; j++) {
|
|
10909
|
-
|
|
10910
|
-
|
|
10911
|
-
if (bps === 16) {
|
|
10912
|
-
rawVal = (streamBytes[sampleIdx * 2] ?? 0) << 8 | (streamBytes[sampleIdx * 2 + 1] ?? 0);
|
|
10913
|
-
} else {
|
|
10914
|
-
rawVal = streamBytes[sampleIdx] ?? 0;
|
|
10915
|
-
}
|
|
10916
|
-
const frac = rawVal / maxSample;
|
|
10910
|
+
let value = 0;
|
|
10911
|
+
for (const vertex of vertices) value += readSample(vertex.index * nOut + j) * vertex.weight;
|
|
10917
10912
|
const dec0 = decode[j * 2] ?? 0;
|
|
10918
10913
|
const dec1 = decode[j * 2 + 1] ?? 1;
|
|
10919
|
-
out2.push(dec0 +
|
|
10914
|
+
out2.push(dec0 + value * (dec1 - dec0));
|
|
10920
10915
|
}
|
|
10921
10916
|
return clampRange(out2);
|
|
10922
10917
|
}
|
|
@@ -10926,34 +10921,40 @@ function evalShadingFunctionToComponents(doc, fnNode, inputs) {
|
|
|
10926
10921
|
const d12 = dom[i * 2 + 1] ?? 1;
|
|
10927
10922
|
return Math.max(d02, Math.min(d12, v));
|
|
10928
10923
|
});
|
|
10929
|
-
const
|
|
10930
|
-
|
|
10931
|
-
|
|
10924
|
+
const source = bytesToString3(doc.decodeStream(resolved));
|
|
10925
|
+
let cached = postScriptFunctions.get(resolved);
|
|
10926
|
+
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])) {
|
|
10927
|
+
cached = { source, domain: dom, range, evaluate: buildPostScriptJsFunction(source, dom, range) };
|
|
10928
|
+
postScriptFunctions.set(resolved, cached);
|
|
10929
|
+
}
|
|
10930
|
+
const output = [];
|
|
10931
|
+
cached.evaluate(clampedInputs, 0, output, 0);
|
|
10932
|
+
return output;
|
|
10932
10933
|
}
|
|
10933
10934
|
if (ft === 3) {
|
|
10934
10935
|
const fnsArr = doc.resolveArray(dictGet(fnDict, "Functions"));
|
|
10935
10936
|
const bounds = getNums("Bounds", []);
|
|
10936
10937
|
const encode = getNums("Encode", []);
|
|
10937
10938
|
if (fnsArr && fnsArr.items.length > 0) {
|
|
10939
|
+
const input = Math.max(dom[0] ?? 0, Math.min(dom[1] ?? 1, t));
|
|
10938
10940
|
let segIdx = 0;
|
|
10939
|
-
while (segIdx < bounds.length &&
|
|
10941
|
+
while (segIdx < bounds.length && input >= bounds[segIdx]) segIdx++;
|
|
10940
10942
|
segIdx = Math.min(fnsArr.items.length - 1, segIdx);
|
|
10941
10943
|
const b0 = segIdx === 0 ? dom[0] ?? 0 : bounds[segIdx - 1];
|
|
10942
10944
|
const b1 = segIdx < bounds.length ? bounds[segIdx] : dom[1] ?? 1;
|
|
10943
10945
|
const e0 = encode[segIdx * 2] ?? 0;
|
|
10944
10946
|
const e1 = encode[segIdx * 2 + 1] ?? 1;
|
|
10945
|
-
const localT =
|
|
10946
|
-
return evalShadingFunctionToComponents(doc, fnsArr.items[segIdx],
|
|
10947
|
+
const localT = b1 !== b0 ? e0 + (input - b0) / (b1 - b0) * (e1 - e0) : e0;
|
|
10948
|
+
return clampRange(evalShadingFunctionToComponents(doc, fnsArr.items[segIdx], localT));
|
|
10947
10949
|
}
|
|
10948
10950
|
}
|
|
10949
|
-
const c0 = getNums("C0", [0
|
|
10950
|
-
const c1 = getNums("C1", [1
|
|
10951
|
+
const c0 = getNums("C0", [0]);
|
|
10952
|
+
const c1 = getNums("C1", [1]);
|
|
10951
10953
|
const nNode = doc.resolve(dictGet(fnDict, "N"));
|
|
10952
|
-
const expN = nNode?.kind === "number"
|
|
10954
|
+
const expN = nNode?.kind === "number" ? nNode.value : 1;
|
|
10953
10955
|
const d0 = dom[0] ?? 0;
|
|
10954
10956
|
const d1 = dom[1] ?? 1;
|
|
10955
|
-
const
|
|
10956
|
-
const w = Math.pow(Math.max(0, Math.min(1, normT)), expN);
|
|
10957
|
+
const w = Math.pow(Math.max(d0, Math.min(d1, t)), expN);
|
|
10957
10958
|
const len = Math.max(c0.length, c1.length);
|
|
10958
10959
|
const out = [];
|
|
10959
10960
|
for (let i = 0; i < len; i++) {
|
|
@@ -10969,30 +10970,14 @@ function shadingComponentsToRgb(csName, comps) {
|
|
|
10969
10970
|
return [v, v, v];
|
|
10970
10971
|
}
|
|
10971
10972
|
if (csName === "DeviceCMYK" || csName === "CMYK" || comps.length >= 4) {
|
|
10972
|
-
const
|
|
10973
|
-
return [
|
|
10973
|
+
const rgb2 = cmykColorSpace2.getRgb([comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0, comps[3] ?? 0], 0);
|
|
10974
|
+
return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
|
|
10974
10975
|
}
|
|
10975
10976
|
return [comps[0] ?? 0, comps[1] ?? 0, comps[2] ?? 0];
|
|
10976
10977
|
}
|
|
10977
10978
|
function kClamp(v) {
|
|
10978
10979
|
return Math.max(0, Math.min(1, v));
|
|
10979
10980
|
}
|
|
10980
|
-
function xyzToSrgb(X, Y, Z, Xw = 0.95047, Yw = 1, Zw = 1.08883) {
|
|
10981
|
-
const scaleX = Xw > 1e-6 ? 0.95047 / Xw : 1;
|
|
10982
|
-
const scaleY = Yw > 1e-6 ? 1 / Yw : 1;
|
|
10983
|
-
const scaleZ = Zw > 1e-6 ? 1.08883 / Zw : 1;
|
|
10984
|
-
const x = X * scaleX;
|
|
10985
|
-
const y = Y * scaleY;
|
|
10986
|
-
const z = Z * scaleZ;
|
|
10987
|
-
const rl = 3.2404542 * x - 1.5371385 * y - 0.4985314 * z;
|
|
10988
|
-
const gl = -0.969266 * x + 1.8760108 * y + 0.041556 * z;
|
|
10989
|
-
const bl = 0.0556434 * x - 0.2040259 * y + 1.0572252 * z;
|
|
10990
|
-
const toGamma = (u) => {
|
|
10991
|
-
const c = Math.max(0, Math.min(1, u));
|
|
10992
|
-
return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
|
|
10993
|
-
};
|
|
10994
|
-
return [toGamma(rl), toGamma(gl), toGamma(bl)];
|
|
10995
|
-
}
|
|
10996
10981
|
function getColorSpaceComponentCount(doc, csNode, activeResources, depth = 0) {
|
|
10997
10982
|
if (!csNode || depth > 4) return 3;
|
|
10998
10983
|
const resolved = doc ? doc.resolve(csNode) : csNode;
|
|
@@ -11049,63 +11034,10 @@ function convertColorSpaceComponentsToRgb(doc, csNode, csNameFallback, comps, ac
|
|
|
11049
11034
|
if (resolved.kind === "array" && resolved.items.length > 0 && doc) {
|
|
11050
11035
|
const familyNode = doc.resolve(resolved.items[0]);
|
|
11051
11036
|
const family = familyNode?.kind === "name" ? familyNode.decoded : "";
|
|
11052
|
-
if (family === "CalGray") {
|
|
11053
|
-
const
|
|
11054
|
-
const
|
|
11055
|
-
|
|
11056
|
-
const a = Math.pow(kClamp(comps[0] ?? 0), gamma);
|
|
11057
|
-
return [a, a, a];
|
|
11058
|
-
}
|
|
11059
|
-
if (family === "CalRGB") {
|
|
11060
|
-
const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
|
|
11061
|
-
const gammaArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Gamma")) : void 0;
|
|
11062
|
-
const getArrNum = (arr, idx, fb) => {
|
|
11063
|
-
const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
|
|
11064
|
-
return r?.kind === "number" ? r.value : fb;
|
|
11065
|
-
};
|
|
11066
|
-
const gr = getArrNum(gammaArr, 0, 1);
|
|
11067
|
-
const gg = getArrNum(gammaArr, 1, 1);
|
|
11068
|
-
const gb = getArrNum(gammaArr, 2, 1);
|
|
11069
|
-
const ag = Math.pow(kClamp(comps[0] ?? 0), gr > 0 ? gr : 1);
|
|
11070
|
-
const bg = Math.pow(kClamp(comps[1] ?? 0), gg > 0 ? gg : 1);
|
|
11071
|
-
const cg = Math.pow(kClamp(comps[2] ?? 0), gb > 0 ? gb : 1);
|
|
11072
|
-
const matArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Matrix")) : void 0;
|
|
11073
|
-
if (matArr && matArr.items.length >= 9) {
|
|
11074
|
-
const m = (i) => getArrNum(matArr, i, 0);
|
|
11075
|
-
const X = m(0) * ag + m(3) * bg + m(6) * cg;
|
|
11076
|
-
const Y = m(1) * ag + m(4) * bg + m(7) * cg;
|
|
11077
|
-
const Z = m(2) * ag + m(5) * bg + m(8) * cg;
|
|
11078
|
-
const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
|
|
11079
|
-
const Xw = getArrNum(wpArr, 0, 0.95047);
|
|
11080
|
-
const Yw = getArrNum(wpArr, 1, 1);
|
|
11081
|
-
const Zw = getArrNum(wpArr, 2, 1.08883);
|
|
11082
|
-
return xyzToSrgb(X, Y, Z, Xw, Yw, Zw);
|
|
11083
|
-
}
|
|
11084
|
-
return [ag, bg, cg];
|
|
11085
|
-
}
|
|
11086
|
-
if (family === "Lab") {
|
|
11087
|
-
const paramDict = resolved.items[1] ? doc.resolveDict(resolved.items[1]) : void 0;
|
|
11088
|
-
const wpArr = paramDict ? doc.resolveArray(dictGet(paramDict, "WhitePoint")) : void 0;
|
|
11089
|
-
const rangeArr = paramDict ? doc.resolveArray(dictGet(paramDict, "Range")) : void 0;
|
|
11090
|
-
const getNum = (arr, idx, fb) => {
|
|
11091
|
-
const r = arr && arr.items[idx] ? doc.resolve(arr.items[idx]) : void 0;
|
|
11092
|
-
return r?.kind === "number" ? r.value : fb;
|
|
11093
|
-
};
|
|
11094
|
-
const Xw = getNum(wpArr, 0, 0.95047);
|
|
11095
|
-
const Yw = getNum(wpArr, 1, 1);
|
|
11096
|
-
const Zw = getNum(wpArr, 2, 1.08883);
|
|
11097
|
-
const amin = getNum(rangeArr, 0, -100);
|
|
11098
|
-
const amax = getNum(rangeArr, 1, 100);
|
|
11099
|
-
const bmin = getNum(rangeArr, 2, -100);
|
|
11100
|
-
const bmax = getNum(rangeArr, 3, 100);
|
|
11101
|
-
const Lstar = Math.max(0, Math.min(100, comps[0] ?? 0));
|
|
11102
|
-
const astar = Math.max(amin, Math.min(amax, comps[1] ?? 0));
|
|
11103
|
-
const bstar = Math.max(bmin, Math.min(bmax, comps[2] ?? 0));
|
|
11104
|
-
const M = (Lstar + 16) / 116;
|
|
11105
|
-
const L = M + astar / 500;
|
|
11106
|
-
const N = M - bstar / 200;
|
|
11107
|
-
const gFn = (x) => x >= 6 / 29 ? x * x * x : 108 / 841 * (x - 4 / 29);
|
|
11108
|
-
return xyzToSrgb(Xw * gFn(L), Yw * gFn(M), Zw * gFn(N), Xw, Yw, Zw);
|
|
11037
|
+
if (family === "CalGray" || family === "CalRGB" || family === "Lab") {
|
|
11038
|
+
const colorSpace = createCalibratedColorSpace(doc, family, resolved.items[1]);
|
|
11039
|
+
const rgb2 = colorSpace.getRgb(comps, 0);
|
|
11040
|
+
return [rgb2[0] / 255, rgb2[1] / 255, rgb2[2] / 255];
|
|
11109
11041
|
}
|
|
11110
11042
|
if (family === "ICCBased" && resolved.items[1]) {
|
|
11111
11043
|
const iccNode = doc.resolve(resolved.items[1]);
|
|
@@ -11186,143 +11118,28 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
|
|
|
11186
11118
|
const r = doc.resolve(it);
|
|
11187
11119
|
return r?.kind === "number" ? r.value : 0;
|
|
11188
11120
|
});
|
|
11189
|
-
const xmin = decodeNums[0], xmax = decodeNums[1], ymin = decodeNums[2], ymax = decodeNums[3];
|
|
11190
|
-
const numColorParams = Math.max(1, Math.floor((decodeNums.length - 4) / 2));
|
|
11191
11121
|
const fnNode = dictGet(shDict, "Function");
|
|
11192
11122
|
const csNode = doc.resolve(dictGet(shDict, "ColorSpace"));
|
|
11193
11123
|
const csName = csNode?.kind === "name" ? csNode.decoded : "DeviceRGB";
|
|
11194
|
-
|
|
11195
|
-
const
|
|
11196
|
-
|
|
11197
|
-
|
|
11198
|
-
|
|
11199
|
-
|
|
11200
|
-
|
|
11201
|
-
|
|
11202
|
-
|
|
11203
|
-
|
|
11204
|
-
|
|
11205
|
-
|
|
11206
|
-
|
|
11207
|
-
|
|
11208
|
-
|
|
11209
|
-
|
|
11210
|
-
|
|
11211
|
-
|
|
11212
|
-
|
|
11213
|
-
};
|
|
11214
|
-
const readColorRgb = () => {
|
|
11215
|
-
const params = [];
|
|
11216
|
-
for (let c = 0; c < numColorParams; c++) {
|
|
11217
|
-
const rc = readBits(bpcComp) / compMax;
|
|
11218
|
-
const cMin = decodeNums[4 + c * 2] ?? 0;
|
|
11219
|
-
const cMax = decodeNums[4 + c * 2 + 1] ?? 1;
|
|
11220
|
-
params.push(cMin + rc * (cMax - cMin));
|
|
11221
|
-
}
|
|
11222
|
-
const comps = fnNode ? evalShadingFunctionToComponents(doc, fnNode, params) : params;
|
|
11223
|
-
return convertColorSpaceComponentsToRgb(doc, csNode, csName, comps);
|
|
11224
|
-
};
|
|
11225
|
-
const triangles = [];
|
|
11226
|
-
if (shType === 4) {
|
|
11227
|
-
const minBitsPerVert = bpcFlag + 2 * bpcCoord + numColorParams * bpcComp;
|
|
11228
|
-
let triVerts;
|
|
11229
|
-
while (bitPos + minBitsPerVert <= totalBits) {
|
|
11230
|
-
const flag = readBits(bpcFlag) & 3;
|
|
11231
|
-
const [x, y] = readCoord();
|
|
11232
|
-
const rgb2 = readColorRgb();
|
|
11233
|
-
const vNew = { x, y, rgb: rgb2 };
|
|
11234
|
-
if (flag === 0 || !triVerts) {
|
|
11235
|
-
if (bitPos + 2 * minBitsPerVert > totalBits) break;
|
|
11236
|
-
readBits(bpcFlag);
|
|
11237
|
-
const [x1, y1] = readCoord();
|
|
11238
|
-
const rgb1 = readColorRgb();
|
|
11239
|
-
readBits(bpcFlag);
|
|
11240
|
-
const [x2, y2] = readCoord();
|
|
11241
|
-
const rgb22 = readColorRgb();
|
|
11242
|
-
triVerts = [vNew, { x: x1, y: y1, rgb: rgb1 }, { x: x2, y: y2, rgb: rgb22 }];
|
|
11243
|
-
triangles.push(triVerts);
|
|
11244
|
-
} else if (flag === 1) {
|
|
11245
|
-
triVerts = [triVerts[1], triVerts[2], vNew];
|
|
11246
|
-
triangles.push(triVerts);
|
|
11247
|
-
} else if (flag === 2) {
|
|
11248
|
-
triVerts = [triVerts[0], triVerts[2], vNew];
|
|
11249
|
-
triangles.push(triVerts);
|
|
11250
|
-
}
|
|
11251
|
-
}
|
|
11252
|
-
} else if (shType === 5) {
|
|
11253
|
-
const minBitsPerVert = 2 * bpcCoord + numColorParams * bpcComp;
|
|
11254
|
-
const verts = [];
|
|
11255
|
-
while (bitPos + minBitsPerVert <= totalBits) {
|
|
11256
|
-
const [x, y] = readCoord();
|
|
11257
|
-
const rgb2 = readColorRgb();
|
|
11258
|
-
verts.push({ x, y, rgb: rgb2 });
|
|
11259
|
-
}
|
|
11260
|
-
const numRows = Math.floor(verts.length / vPerRow);
|
|
11261
|
-
for (let r = 0; r + 1 < numRows; r++) {
|
|
11262
|
-
for (let c = 0; c + 1 < vPerRow; c++) {
|
|
11263
|
-
const v00 = verts[r * vPerRow + c];
|
|
11264
|
-
const v01 = verts[r * vPerRow + c + 1];
|
|
11265
|
-
const v11 = verts[(r + 1) * vPerRow + c + 1];
|
|
11266
|
-
const v10 = verts[(r + 1) * vPerRow + c];
|
|
11267
|
-
triangles.push([v00, v01, v11], [v00, v11, v10]);
|
|
11268
|
-
}
|
|
11269
|
-
}
|
|
11270
|
-
} else if (shType === 6 || shType === 7) {
|
|
11271
|
-
const numCtrl = shType === 6 ? 12 : 16;
|
|
11272
|
-
const minBitsPatch = bpcFlag + (numCtrl - 4) * 2 * bpcCoord + 2 * numColorParams * bpcComp;
|
|
11273
|
-
let prevPts;
|
|
11274
|
-
let prevColors;
|
|
11275
|
-
while (bitPos + minBitsPatch <= totalBits) {
|
|
11276
|
-
const flag = readBits(bpcFlag) & 3;
|
|
11277
|
-
let pts = [];
|
|
11278
|
-
let cols = [];
|
|
11279
|
-
if (flag === 0 || !prevPts || !prevColors) {
|
|
11280
|
-
for (let i = 0; i < numCtrl; i++) pts.push(readCoord());
|
|
11281
|
-
for (let i = 0; i < 4; i++) cols.push(readColorRgb());
|
|
11282
|
-
} else {
|
|
11283
|
-
const extraCtrl = numCtrl - 4;
|
|
11284
|
-
const readExtra = [];
|
|
11285
|
-
for (let i = 0; i < extraCtrl; i++) readExtra.push(readCoord());
|
|
11286
|
-
const c2 = readColorRgb();
|
|
11287
|
-
const c3 = readColorRgb();
|
|
11288
|
-
pts = [prevPts[3], prevPts[4], prevPts[5], prevPts[6], ...readExtra];
|
|
11289
|
-
cols = [prevColors[1], prevColors[2], c2, c3];
|
|
11290
|
-
}
|
|
11291
|
-
prevPts = pts;
|
|
11292
|
-
prevColors = cols;
|
|
11293
|
-
const p00 = pts[0];
|
|
11294
|
-
const p03 = pts[3];
|
|
11295
|
-
const p33 = pts[6];
|
|
11296
|
-
const p30 = pts[9];
|
|
11297
|
-
const c00 = cols[0], c03 = cols[1], c33 = cols[2], c30 = cols[3];
|
|
11298
|
-
const steps = 4;
|
|
11299
|
-
const grid = [];
|
|
11300
|
-
for (let iu = 0; iu <= steps; iu++) {
|
|
11301
|
-
const u = iu / steps;
|
|
11302
|
-
const row = [];
|
|
11303
|
-
for (let iv = 0; iv <= steps; iv++) {
|
|
11304
|
-
const v = iv / steps;
|
|
11305
|
-
const x = (1 - u) * (1 - v) * p00[0] + (1 - u) * v * p03[0] + u * v * p33[0] + u * (1 - v) * p30[0];
|
|
11306
|
-
const y = (1 - u) * (1 - v) * p00[1] + (1 - u) * v * p03[1] + u * v * p33[1] + u * (1 - v) * p30[1];
|
|
11307
|
-
const r = (1 - u) * (1 - v) * c00[0] + (1 - u) * v * c03[0] + u * v * c33[0] + u * (1 - v) * c30[0];
|
|
11308
|
-
const g = (1 - u) * (1 - v) * c00[1] + (1 - u) * v * c03[1] + u * v * c33[1] + u * (1 - v) * c30[1];
|
|
11309
|
-
const b = (1 - u) * (1 - v) * c00[2] + (1 - u) * v * c03[2] + u * v * c33[2] + u * (1 - v) * c30[2];
|
|
11310
|
-
row.push({ x, y, rgb: [r, g, b] });
|
|
11311
|
-
}
|
|
11312
|
-
grid.push(row);
|
|
11313
|
-
}
|
|
11314
|
-
for (let iu = 0; iu < steps; iu++) {
|
|
11315
|
-
for (let iv = 0; iv < steps; iv++) {
|
|
11316
|
-
const g00 = grid[iu][iv];
|
|
11317
|
-
const g01 = grid[iu][iv + 1];
|
|
11318
|
-
const g11 = grid[iu + 1][iv + 1];
|
|
11319
|
-
const g10 = grid[iu + 1][iv];
|
|
11320
|
-
triangles.push([g00, g01, g11], [g00, g11, g10]);
|
|
11321
|
-
}
|
|
11322
|
-
}
|
|
11323
|
-
}
|
|
11324
|
-
}
|
|
11325
|
-
if (triangles.length === 0) return void 0;
|
|
11124
|
+
const numComps = fnNode ? 1 : getColorSpaceComponentCount(doc, csNode);
|
|
11125
|
+
const mesh = new MeshShading(shType, new Stream(bytes), {
|
|
11126
|
+
bitsPerCoordinate: bpcCoord,
|
|
11127
|
+
bitsPerComponent: bpcComp,
|
|
11128
|
+
bitsPerFlag: bpcFlag,
|
|
11129
|
+
decode: decodeNums,
|
|
11130
|
+
numComps,
|
|
11131
|
+
colorFn: null,
|
|
11132
|
+
colorSpace: {
|
|
11133
|
+
numComps,
|
|
11134
|
+
getRgb(components) {
|
|
11135
|
+
const params = Array.from(components);
|
|
11136
|
+
const values = fnNode ? evalShadingFunctionToComponents(doc, fnNode, params) : params;
|
|
11137
|
+
return new Uint8Array(convertColorSpaceComponentsToRgb(doc, csNode, csName, values).map((value) => Math.round(Math.max(0, Math.min(1, value)) * 255)));
|
|
11138
|
+
}
|
|
11139
|
+
}
|
|
11140
|
+
}, vPerRow);
|
|
11141
|
+
const [, , positions, colors, vertexCount] = mesh.getIR();
|
|
11142
|
+
if (vertexCount === 0) return void 0;
|
|
11326
11143
|
const [bx0, by0, bx1, by1] = targetBox;
|
|
11327
11144
|
const boxW = Math.max(1, bx1 - bx0);
|
|
11328
11145
|
const boxH = Math.max(1, by1 - by0);
|
|
@@ -11334,10 +11151,10 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
|
|
|
11334
11151
|
const [px, py] = transformPoint(effectiveCtm, vx, vy);
|
|
11335
11152
|
return [(px - bx0) / boxW * imgW, (by1 - py) / boxH * imgH];
|
|
11336
11153
|
};
|
|
11337
|
-
for (
|
|
11338
|
-
const [x0, y0] = toImgCoords(
|
|
11339
|
-
const [x1, y1] = toImgCoords(
|
|
11340
|
-
const [x2, y2] = toImgCoords(
|
|
11154
|
+
for (let vertex = 0; vertex < vertexCount; vertex += 3) {
|
|
11155
|
+
const [x0, y0] = toImgCoords(positions[vertex * 2], positions[vertex * 2 + 1]);
|
|
11156
|
+
const [x1, y1] = toImgCoords(positions[vertex * 2 + 2], positions[vertex * 2 + 3]);
|
|
11157
|
+
const [x2, y2] = toImgCoords(positions[vertex * 2 + 4], positions[vertex * 2 + 5]);
|
|
11341
11158
|
const denom = (y1 - y2) * (x0 - x2) + (x2 - x1) * (y0 - y2);
|
|
11342
11159
|
if (Math.abs(denom) < 1e-6) continue;
|
|
11343
11160
|
const minX = Math.max(0, Math.floor(Math.min(x0, x1, x2)));
|
|
@@ -11352,13 +11169,12 @@ function renderMeshShadingToImage(doc, shDict, shStream, shType, effectiveCtm, t
|
|
|
11352
11169
|
const w1 = ((y2 - y0) * (px - x2) + (x0 - x2) * (py - y2)) / denom;
|
|
11353
11170
|
const w2 = 1 - w0 - w1;
|
|
11354
11171
|
if (w0 >= -1e-4 && w1 >= -1e-4 && w2 >= -1e-4) {
|
|
11355
|
-
const r = w0 * v0.rgb[0] + w1 * v1.rgb[0] + w2 * v2.rgb[0];
|
|
11356
|
-
const g = w0 * v0.rgb[1] + w1 * v1.rgb[1] + w2 * v2.rgb[1];
|
|
11357
|
-
const b = w0 * v0.rgb[2] + w1 * v1.rgb[2] + w2 * v2.rgb[2];
|
|
11358
11172
|
const pIdx = (iy * imgW + ix) * 4;
|
|
11359
|
-
|
|
11360
|
-
|
|
11361
|
-
|
|
11173
|
+
for (let channel = 0; channel < 3; channel++) {
|
|
11174
|
+
rgba[pIdx + channel] = Math.round(
|
|
11175
|
+
w0 * colors[vertex * 4 + channel] + w1 * colors[vertex * 4 + 4 + channel] + w2 * colors[vertex * 4 + 8 + channel]
|
|
11176
|
+
);
|
|
11177
|
+
}
|
|
11362
11178
|
rgba[pIdx + 3] = a8;
|
|
11363
11179
|
}
|
|
11364
11180
|
}
|
|
@@ -11445,6 +11261,8 @@ function renderShadingDictToImage(doc, shDict, shadingCtm, targetBox, fillAlpha,
|
|
|
11445
11261
|
const [a, b, c, d, e, f] = effectiveCtm;
|
|
11446
11262
|
const det = a * d - b * c;
|
|
11447
11263
|
if (Math.abs(det) <= 1e-8) return void 0;
|
|
11264
|
+
const [sa, sb, sc, sd, se, sf] = shadingCtm;
|
|
11265
|
+
const shadingDet = sa * sd - sb * sc;
|
|
11448
11266
|
const t0Dom = shDomain[0] ?? 0;
|
|
11449
11267
|
const t1Dom = shDomain[1] ?? 1;
|
|
11450
11268
|
for (let iy = 0; iy < imgH; iy++) {
|
|
@@ -11455,8 +11273,10 @@ function renderShadingDictToImage(doc, shDict, shadingCtm, targetBox, fillAlpha,
|
|
|
11455
11273
|
const dxPdf = xPdf - e;
|
|
11456
11274
|
const xs = (d * dxPdf - c * dyPdf) / det;
|
|
11457
11275
|
const ys = (-b * dxPdf + a * dyPdf) / det;
|
|
11458
|
-
if (shBBox
|
|
11459
|
-
|
|
11276
|
+
if (shBBox) {
|
|
11277
|
+
const bboxX = (sd * (xPdf - se) - sc * (yPdf - sf)) / shadingDet;
|
|
11278
|
+
const bboxY = (-sb * (xPdf - se) + sa * (yPdf - sf)) / shadingDet;
|
|
11279
|
+
if (bboxX < shBBox[0] || bboxX > shBBox[2] || bboxY < shBBox[1] || bboxY > shBBox[3]) continue;
|
|
11460
11280
|
}
|
|
11461
11281
|
let comps;
|
|
11462
11282
|
if (shType === 1) {
|
|
@@ -11756,7 +11576,8 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
11756
11576
|
const shDict = shNode?.kind === "dict" ? shNode : shNode?.kind === "stream" ? shNode.dict : void 0;
|
|
11757
11577
|
const shStream = shNode?.kind === "stream" ? shNode : void 0;
|
|
11758
11578
|
if (shDict) {
|
|
11759
|
-
const
|
|
11579
|
+
const [originX, originY] = params.origin ?? [0, 0];
|
|
11580
|
+
const targetBox = st.clipRect ?? [originX, originY, originX + params.width, originY + params.height];
|
|
11760
11581
|
const img = renderShadingDictToImage(
|
|
11761
11582
|
params.cosDoc,
|
|
11762
11583
|
shDict,
|
|
@@ -11795,12 +11616,10 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
11795
11616
|
} else if (operator === "RG" || operator === "SC" || operator === "SCN") {
|
|
11796
11617
|
st.strokeColor = resolveScColorOperands(operator === "RG" ? "DeviceRGB" : st.strokeColorSpaceName, ops, activeResources);
|
|
11797
11618
|
} else if (operator === "k") {
|
|
11798
|
-
|
|
11799
|
-
st.fillColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
|
|
11619
|
+
st.fillColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
|
|
11800
11620
|
st.fillPatternName = void 0;
|
|
11801
11621
|
} else if (operator === "K") {
|
|
11802
|
-
|
|
11803
|
-
st.strokeColor = { r: (1 - c) * (1 - k), g: (1 - m) * (1 - k), b: (1 - y) * (1 - k) };
|
|
11622
|
+
st.strokeColor = resolveScColorOperands("DeviceCMYK", ops, activeResources);
|
|
11804
11623
|
} else if (operator === "gs" && params.cosDoc && activeResources && ops[0]?.kind === "name") {
|
|
11805
11624
|
const extDict = params.cosDoc.resolveDict(dictGet(activeResources, "ExtGState"));
|
|
11806
11625
|
const gsDict = extDict ? params.cosDoc.resolveDict(dictGet(extDict, ops[0].decoded)) : void 0;
|
|
@@ -12009,7 +11828,7 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
12009
11828
|
stateStack.pop();
|
|
12010
11829
|
capturedOperations = parentOperations;
|
|
12011
11830
|
}
|
|
12012
|
-
if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, blendMode: st.blendMode, clipRect: st.clipRect } });
|
|
11831
|
+
if (compositeGroup) emit({ kind: "group", value: { operations: children, alpha: st.fillAlpha, isolated, bboxClip: nextClipPaths?.[0], blendMode: st.blendMode, clipRect: st.clipRect } });
|
|
12013
11832
|
};
|
|
12014
11833
|
const walkNodes = (nodes, mcid, actualText, activeResources = params.resourcesDict, activeFonts = fonts, depth = 0) => {
|
|
12015
11834
|
for (const node of nodes) {
|
|
@@ -12593,6 +12412,7 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
12593
12412
|
pageIndex: params.pageIndex,
|
|
12594
12413
|
width: params.width,
|
|
12595
12414
|
height: params.height,
|
|
12415
|
+
...params.origin ? { origin: params.origin } : {},
|
|
12596
12416
|
rotation: params.rotation ?? 0,
|
|
12597
12417
|
glyphs,
|
|
12598
12418
|
paths,
|
|
@@ -14718,7 +14538,7 @@ function prepareStroke(path, scale) {
|
|
|
14718
14538
|
}
|
|
14719
14539
|
return { matrix, width, dashArray, dashPhase };
|
|
14720
14540
|
}
|
|
14721
|
-
function strokeContours(path, pageHeight, scale) {
|
|
14541
|
+
function strokeContours(path, pageHeight, scale, originX = 0, originY = 0) {
|
|
14722
14542
|
const stroke = prepareStroke(path, scale);
|
|
14723
14543
|
if (!stroke) return [];
|
|
14724
14544
|
const inverse = inverseStrokeMatrix(stroke.matrix);
|
|
@@ -14730,8 +14550,8 @@ function strokeContours(path, pageHeight, scale) {
|
|
|
14730
14550
|
(inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
|
|
14731
14551
|
];
|
|
14732
14552
|
const toScreen = ([x, y]) => [
|
|
14733
|
-
(a * x / strokeScale + c * y / strokeScale + e) * scale,
|
|
14734
|
-
(pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
|
|
14553
|
+
(a * x / strokeScale + c * y / strokeScale + e - originX) * scale,
|
|
14554
|
+
(pageHeight + originY - b * x / strokeScale - d * y / strokeScale - f) * scale
|
|
14735
14555
|
];
|
|
14736
14556
|
const contours = strokeOutlines(
|
|
14737
14557
|
segmentsToScreenPaths(path.segments, pageHeight, scale, project),
|
|
@@ -14889,18 +14709,34 @@ function renderSoftMask(mask, displayList, scale) {
|
|
|
14889
14709
|
}
|
|
14890
14710
|
return bitmap;
|
|
14891
14711
|
}
|
|
14892
|
-
function
|
|
14893
|
-
|
|
14712
|
+
function getDisplayListCropBox(list) {
|
|
14713
|
+
const full = [0, 0, list.width, list.height];
|
|
14714
|
+
const box = list.cropBox;
|
|
14715
|
+
if (!box || !box.every(Number.isFinite)) return full;
|
|
14716
|
+
const x0 = Math.max(0, Math.min(box[0], box[2]));
|
|
14717
|
+
const y0 = Math.max(0, Math.min(box[1], box[3]));
|
|
14718
|
+
const x1 = Math.min(list.width, Math.max(box[0], box[2]));
|
|
14719
|
+
const y1 = Math.min(list.height, Math.max(box[1], box[3]));
|
|
14720
|
+
return x1 > x0 && y1 > y0 ? [x0, y0, x1, y1] : full;
|
|
14721
|
+
}
|
|
14722
|
+
function hasCompositingEffects(operations, includeSoftMasks = false) {
|
|
14723
|
+
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));
|
|
14724
|
+
}
|
|
14725
|
+
function needsGroupBackdrop(group) {
|
|
14726
|
+
return group.isolated === false && !!group.softMask && hasCompositingEffects(group.operations, true);
|
|
14894
14727
|
}
|
|
14895
14728
|
function renderDisplayListToBitmap(displayList, options = {}) {
|
|
14896
14729
|
const baseScale = options.scale ?? (options.dpi ? options.dpi / 72 : 1.5);
|
|
14897
14730
|
const scaleX = options.dpiX !== void 0 ? options.dpiX / 72 : baseScale;
|
|
14898
14731
|
const scaleY = options.dpiY !== void 0 ? options.dpiY / 72 : baseScale;
|
|
14899
14732
|
const scale = scaleX;
|
|
14733
|
+
const [originX, originY] = displayList.origin ?? [0, 0];
|
|
14734
|
+
const pageTop = originY + displayList.height;
|
|
14735
|
+
const toScreen = (x, y) => [(x - originX) * scale, (pageTop - y) * scale];
|
|
14900
14736
|
const width = Math.max(1, Math.round(displayList.width * scale));
|
|
14901
14737
|
const height = Math.max(1, Math.round(displayList.height * scale));
|
|
14902
14738
|
const rgba = new Uint8Array(width * height * 4);
|
|
14903
|
-
const deferBackground = !options.transparent &&
|
|
14739
|
+
const deferBackground = !options.transparent && hasCompositingEffects(paintOperations(displayList));
|
|
14904
14740
|
const transparent = options.transparent || deferBackground;
|
|
14905
14741
|
const bg = options.background ?? { r: 1, g: 1, b: 1 };
|
|
14906
14742
|
const bgR = transparent ? 0 : Math.round(bg.r * 255);
|
|
@@ -14925,14 +14761,27 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
14925
14761
|
let operation = original.kind === "glyph" ? { kind: "path", value: glyphPaint(original.value) } : original;
|
|
14926
14762
|
if (operation.kind === "group") {
|
|
14927
14763
|
const group = operation.value;
|
|
14928
|
-
|
|
14764
|
+
let operations = group.operations;
|
|
14765
|
+
if (needsGroupBackdrop(group)) {
|
|
14766
|
+
operations = [{ kind: "image", value: {
|
|
14767
|
+
name: "GroupBackdrop",
|
|
14768
|
+
width,
|
|
14769
|
+
height,
|
|
14770
|
+
decodedRgba: rgba.slice(),
|
|
14771
|
+
matrix: [width / scale, 0, 0, height / scale, originX, pageTop - height / scale],
|
|
14772
|
+
colorSpace: "DeviceRGB",
|
|
14773
|
+
bitsPerComponent: 8,
|
|
14774
|
+
...group.bboxClip ? { clipPaths: [group.bboxClip] } : {}
|
|
14775
|
+
} }, ...operations];
|
|
14776
|
+
}
|
|
14777
|
+
const bitmap = renderDisplayListToBitmap({ ...displayList, rotation: 0, operations }, { ...options, scale, dpiX: void 0, dpiY: void 0, cropRect: void 0, useCropBox: false, transparent: true });
|
|
14929
14778
|
for (let i = 3; i < bitmap.data.length; i += 4) bitmap.data[i] = Math.round(bitmap.data[i] * group.alpha);
|
|
14930
14779
|
operation = { kind: "image", value: {
|
|
14931
14780
|
name: "TransparencyGroup",
|
|
14932
14781
|
width: bitmap.width,
|
|
14933
14782
|
height: bitmap.height,
|
|
14934
14783
|
decodedRgba: bitmap.data,
|
|
14935
|
-
matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale,
|
|
14784
|
+
matrix: [bitmap.width / scale, 0, 0, bitmap.height / scale, originX, pageTop - bitmap.height / scale],
|
|
14936
14785
|
colorSpace: "DeviceRGB",
|
|
14937
14786
|
bitsPerComponent: 8,
|
|
14938
14787
|
blendMode: group.blendMode,
|
|
@@ -14946,7 +14795,7 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
14946
14795
|
for (const clip of clips) {
|
|
14947
14796
|
const { segments, fillRule } = "segments" in clip ? clip : { segments: clip, fillRule: "nonzero" };
|
|
14948
14797
|
const layer = new Uint8Array(width * height * 4);
|
|
14949
|
-
fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
|
|
14798
|
+
fillEdgesScanline4x4(layer, width, height, pathsToEdges(segmentsToScreenPaths(segments, displayList.height, scale, toScreen), true), { r: 1, g: 1, b: 1 }, 1, fillRule);
|
|
14950
14799
|
for (let i = 3; i < layer.length; i += 4) clipMask[i] = Math.round(clipMask[i] * layer[i] / 255);
|
|
14951
14800
|
}
|
|
14952
14801
|
cachedClips = clips;
|
|
@@ -14993,15 +14842,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
14993
14842
|
if (operation.kind === "path") {
|
|
14994
14843
|
const path = operation.value;
|
|
14995
14844
|
if (path.fillColor) {
|
|
14996
|
-
const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale), true);
|
|
14997
|
-
const clipScreen = path.clipRect ? [path.clipRect[0] * scale, (
|
|
14845
|
+
const edges = pathsToEdges(segmentsToScreenPaths(path.segments, displayList.height, scale, toScreen), true);
|
|
14846
|
+
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;
|
|
14998
14847
|
fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
|
|
14999
14848
|
}
|
|
15000
14849
|
if (path.strokeColor) {
|
|
15001
14850
|
const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
|
|
15002
14851
|
const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
|
|
15003
|
-
const edges = pathsToEdges(strokeContours(path, displayList.height, scale).map((points) => ({ points, closed: true })));
|
|
15004
|
-
const clipScreen = path.clipRect ? [path.clipRect[0] * scale, (
|
|
14852
|
+
const edges = pathsToEdges(strokeContours(path, displayList.height, scale, originX, originY).map((points) => ({ points, closed: true })));
|
|
14853
|
+
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;
|
|
15005
14854
|
fillEdgesScanline4x4(
|
|
15006
14855
|
rgba,
|
|
15007
14856
|
width,
|
|
@@ -15024,12 +14873,12 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
15024
14873
|
if (Math.abs(det) <= 1e-8) continue;
|
|
15025
14874
|
const cornersPdfX = [e, a + e, a + c + e, c + e];
|
|
15026
14875
|
const cornersPdfY = [f, b + f, b + d + f, d + f];
|
|
15027
|
-
const cornersPx = cornersPdfX.map((cx) => cx * scale);
|
|
15028
|
-
const cornersPy = cornersPdfY.map((cy) => (
|
|
15029
|
-
const clipMinPx = img.clipRect ? Math.floor(img.clipRect[0] * scale) : 0;
|
|
15030
|
-
const clipMaxPx = img.clipRect ? Math.ceil(img.clipRect[2] * scale) - 1 : width - 1;
|
|
15031
|
-
const clipMinPy = img.clipRect ? Math.floor((
|
|
15032
|
-
const clipMaxPy = img.clipRect ? Math.ceil((
|
|
14876
|
+
const cornersPx = cornersPdfX.map((cx) => (cx - originX) * scale);
|
|
14877
|
+
const cornersPy = cornersPdfY.map((cy) => (pageTop - cy) * scale);
|
|
14878
|
+
const clipMinPx = img.clipRect ? Math.floor((img.clipRect[0] - originX) * scale) : 0;
|
|
14879
|
+
const clipMaxPx = img.clipRect ? Math.ceil((img.clipRect[2] - originX) * scale) - 1 : width - 1;
|
|
14880
|
+
const clipMinPy = img.clipRect ? Math.floor((pageTop - img.clipRect[3]) * scale) : 0;
|
|
14881
|
+
const clipMaxPy = img.clipRect ? Math.ceil((pageTop - img.clipRect[1]) * scale) - 1 : height - 1;
|
|
15033
14882
|
const minPx = Math.max(0, clipMinPx, Math.floor(Math.min(...cornersPx)));
|
|
15034
14883
|
const maxPx = Math.min(width - 1, clipMaxPx, Math.ceil(Math.max(...cornersPx)) - 1);
|
|
15035
14884
|
const minPy = Math.max(0, clipMinPy, Math.floor(Math.min(...cornersPy)));
|
|
@@ -15046,11 +14895,11 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
15046
14895
|
const smooth = Math.fround((s1 + s2 + Math.hypot(s1 - s2, 2 * cross)) / 2) <= 1;
|
|
15047
14896
|
const sample = new Float64Array(4);
|
|
15048
14897
|
for (let py = minPy; py <= maxPy; py++) {
|
|
15049
|
-
const yPdf =
|
|
14898
|
+
const yPdf = pageTop - (py + 0.5) / scale;
|
|
15050
14899
|
if (img.clipRect && (yPdf < img.clipRect[1] || yPdf > img.clipRect[3])) continue;
|
|
15051
14900
|
const dyPdf = yPdf - f;
|
|
15052
14901
|
for (let px = minPx; px <= maxPx; px++) {
|
|
15053
|
-
const xPdf = (px + 0.5) / scale;
|
|
14902
|
+
const xPdf = originX + (px + 0.5) / scale;
|
|
15054
14903
|
if (img.clipRect && (xPdf < img.clipRect[0] || xPdf > img.clipRect[2])) continue;
|
|
15055
14904
|
const dxPdf = xPdf - e;
|
|
15056
14905
|
const u = (d * dxPdf - c * dyPdf) / det;
|
|
@@ -15111,6 +14960,15 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
15111
14960
|
}
|
|
15112
14961
|
result = { width: targetW, height: targetH, data: resampled };
|
|
15113
14962
|
}
|
|
14963
|
+
if (options.useCropBox) {
|
|
14964
|
+
const box = getDisplayListCropBox(displayList);
|
|
14965
|
+
result = cropRgbaBitmap(result, {
|
|
14966
|
+
x: box[0] * scaleX,
|
|
14967
|
+
y: (displayList.height - box[3]) * scaleY,
|
|
14968
|
+
width: (box[2] - box[0]) * scaleX,
|
|
14969
|
+
height: (box[3] - box[1]) * scaleY
|
|
14970
|
+
});
|
|
14971
|
+
}
|
|
15114
14972
|
result = rotateRgbaBitmapQuarterTurns(result, displayList.rotation ?? 0);
|
|
15115
14973
|
if (options.cropRect) {
|
|
15116
14974
|
result = cropRgbaBitmap(result, options.cropRect);
|
|
@@ -15470,6 +15328,7 @@ var FONT_IDENTITY_MATRIX;
|
|
|
15470
15328
|
var LINE_FACTOR;
|
|
15471
15329
|
var LINE_DESCENT_FACTOR;
|
|
15472
15330
|
var BASELINE_FACTOR;
|
|
15331
|
+
var MeshFigureType;
|
|
15473
15332
|
var VerbosityLevel;
|
|
15474
15333
|
var DrawOPS;
|
|
15475
15334
|
var PasswordResponses;
|
|
@@ -15571,6 +15430,41 @@ var fixedDistCodeTab;
|
|
|
15571
15430
|
var FlateStream;
|
|
15572
15431
|
var getMetrics;
|
|
15573
15432
|
var getFontBasicMetrics;
|
|
15433
|
+
var ColorSpace;
|
|
15434
|
+
var DeviceCmykCS;
|
|
15435
|
+
var CalGrayCS;
|
|
15436
|
+
var CalRGBCS;
|
|
15437
|
+
var LabCS;
|
|
15438
|
+
var TOKEN;
|
|
15439
|
+
var Token;
|
|
15440
|
+
var Lexer;
|
|
15441
|
+
var PS_VALUE_TYPE;
|
|
15442
|
+
var PS_NODE;
|
|
15443
|
+
var PsNode;
|
|
15444
|
+
var PsProgram;
|
|
15445
|
+
var PsBlock;
|
|
15446
|
+
var PsNumber;
|
|
15447
|
+
var PsOperator;
|
|
15448
|
+
var PsIf;
|
|
15449
|
+
var PsIfElse;
|
|
15450
|
+
var PsArgNode;
|
|
15451
|
+
var PsConstNode;
|
|
15452
|
+
var PsUnaryNode;
|
|
15453
|
+
var PsBinaryNode;
|
|
15454
|
+
var PsTernaryNode;
|
|
15455
|
+
var Parser;
|
|
15456
|
+
var MAX_STACK_SIZE;
|
|
15457
|
+
var PSStackToTree;
|
|
15458
|
+
var OP;
|
|
15459
|
+
var _DEG_TO_RAD;
|
|
15460
|
+
var _RAD_TO_DEG;
|
|
15461
|
+
var PsJsCompiler;
|
|
15462
|
+
var PSStackBasedInterpreter;
|
|
15463
|
+
var ShadingType;
|
|
15464
|
+
var BaseShading;
|
|
15465
|
+
var MeshStreamReader;
|
|
15466
|
+
var bCache;
|
|
15467
|
+
var MeshShading;
|
|
15574
15468
|
var PdfError;
|
|
15575
15469
|
var DEFAULT_MAX_DECODED_BYTES;
|
|
15576
15470
|
var BoundedFlateStream;
|
|
@@ -15689,6 +15583,9 @@ var __webpack_exports__JpxImage;
|
|
|
15689
15583
|
var __webpack_exports__VerbosityLevel;
|
|
15690
15584
|
var __webpack_exports__getVerbosityLevel;
|
|
15691
15585
|
var __webpack_exports__setVerbosityLevel;
|
|
15586
|
+
var cmykColorSpace;
|
|
15587
|
+
var cmykColorSpace2;
|
|
15588
|
+
var postScriptFunctions;
|
|
15692
15589
|
var ACROFORM_FONT_ALIAS_MAP;
|
|
15693
15590
|
var PdfPage;
|
|
15694
15591
|
var MAX_STROKE_VERTICES;
|
|
@@ -19057,6 +18954,11 @@ var init_dist = __esm({
|
|
|
19057
18954
|
LINE_FACTOR = 1.35;
|
|
19058
18955
|
LINE_DESCENT_FACTOR = 0.35;
|
|
19059
18956
|
BASELINE_FACTOR = LINE_DESCENT_FACTOR / LINE_FACTOR;
|
|
18957
|
+
MeshFigureType = {
|
|
18958
|
+
TRIANGLES: 1,
|
|
18959
|
+
LATTICE: 2,
|
|
18960
|
+
PATCH: 3
|
|
18961
|
+
};
|
|
19060
18962
|
VerbosityLevel = {
|
|
19061
18963
|
ERRORS: 0,
|
|
19062
18964
|
WARNINGS: 1,
|
|
@@ -36794,6 +36696,3019 @@ var init_dist = __esm({
|
|
|
36794
36696
|
xHeight: Math.NaN
|
|
36795
36697
|
};
|
|
36796
36698
|
});
|
|
36699
|
+
ColorSpace = class _ColorSpace {
|
|
36700
|
+
static #rgbBuf = new Uint8ClampedArray(3);
|
|
36701
|
+
constructor(name, numComps) {
|
|
36702
|
+
if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _ColorSpace) {
|
|
36703
|
+
unreachable2("Cannot initialize ColorSpace.");
|
|
36704
|
+
}
|
|
36705
|
+
this.name = name;
|
|
36706
|
+
this.numComps = numComps;
|
|
36707
|
+
}
|
|
36708
|
+
/**
|
|
36709
|
+
* Converts the color value to the RGB color. The color components are
|
|
36710
|
+
* located in the src array starting from the srcOffset. Returns the array
|
|
36711
|
+
* of the rgb components, each value ranging from [0,255].
|
|
36712
|
+
*/
|
|
36713
|
+
getRgb(src, srcOffset, output = new Uint8ClampedArray(3)) {
|
|
36714
|
+
this.getRgbItem(src, srcOffset, output, 0);
|
|
36715
|
+
return output;
|
|
36716
|
+
}
|
|
36717
|
+
getRgbHex(src, srcOffset) {
|
|
36718
|
+
const buffer = this.getRgb(src, srcOffset, _ColorSpace.#rgbBuf);
|
|
36719
|
+
return Util.makeHexColor(buffer[0], buffer[1], buffer[2]);
|
|
36720
|
+
}
|
|
36721
|
+
/**
|
|
36722
|
+
* Converts the color value to the RGB color, similar to the getRgb method.
|
|
36723
|
+
* The result placed into the dest array starting from the destOffset.
|
|
36724
|
+
*/
|
|
36725
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
36726
|
+
unreachable2("Should not call ColorSpace.getRgbItem");
|
|
36727
|
+
}
|
|
36728
|
+
/**
|
|
36729
|
+
* Converts the specified number of the color values to the RGB colors.
|
|
36730
|
+
* The colors are located in the src array starting from the srcOffset.
|
|
36731
|
+
* The result is placed into the dest array starting from the destOffset.
|
|
36732
|
+
* The src array items shall be in [0,2^bits) range, the dest array items
|
|
36733
|
+
* will be in [0,255] range. alpha01 indicates how many alpha components
|
|
36734
|
+
* there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
|
|
36735
|
+
* array).
|
|
36736
|
+
*/
|
|
36737
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
36738
|
+
unreachable2("Should not call ColorSpace.getRgbBuffer");
|
|
36739
|
+
}
|
|
36740
|
+
/**
|
|
36741
|
+
* Converts `count` unscaled colors to RGB, starting at `destOffset`.
|
|
36742
|
+
* Components use the native color-space ranges expected by `getRgbItem`,
|
|
36743
|
+
* and each output has a `3 + alpha01` byte stride.
|
|
36744
|
+
* Subclasses may override this to batch expensive conversions.
|
|
36745
|
+
*/
|
|
36746
|
+
getRgbItems(src, count, dest, destOffset, alpha01) {
|
|
36747
|
+
const { numComps } = this;
|
|
36748
|
+
for (let i = 0, srcOffset = 0; i < count; i++, srcOffset += numComps) {
|
|
36749
|
+
this.getRgbItem(src, srcOffset, dest, destOffset);
|
|
36750
|
+
destOffset += 3 + alpha01;
|
|
36751
|
+
}
|
|
36752
|
+
}
|
|
36753
|
+
/**
|
|
36754
|
+
* Returns true if source data will be equal the result/output data.
|
|
36755
|
+
*/
|
|
36756
|
+
isPassthrough(bits) {
|
|
36757
|
+
return false;
|
|
36758
|
+
}
|
|
36759
|
+
/**
|
|
36760
|
+
* Refer to the static `ColorSpace.isDefaultDecode` method below.
|
|
36761
|
+
*/
|
|
36762
|
+
isDefaultDecode(decode, bpc) {
|
|
36763
|
+
return _ColorSpace.isDefaultDecode(decode, this.numComps);
|
|
36764
|
+
}
|
|
36765
|
+
/**
|
|
36766
|
+
* Fills in the RGB colors in the destination buffer. alpha01 indicates
|
|
36767
|
+
* how many alpha components there are in the dest array; it will be either
|
|
36768
|
+
* 0 (RGB array) or 1 (RGBA array).
|
|
36769
|
+
*/
|
|
36770
|
+
fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {
|
|
36771
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
36772
|
+
assert2(
|
|
36773
|
+
dest instanceof Uint8ClampedArray,
|
|
36774
|
+
'ColorSpace.fillRgb: Unsupported "dest" type.'
|
|
36775
|
+
);
|
|
36776
|
+
}
|
|
36777
|
+
const count = originalWidth * originalHeight;
|
|
36778
|
+
let rgbBuf = null;
|
|
36779
|
+
const numComponentColors = 1 << bpc;
|
|
36780
|
+
const needsResizing = originalHeight !== height || originalWidth !== width;
|
|
36781
|
+
if (this.isPassthrough(bpc)) {
|
|
36782
|
+
rgbBuf = comps;
|
|
36783
|
+
} else if (this.numComps === 1 && count > numComponentColors && this.name !== "DeviceGray" && this.name !== "DeviceRGB") {
|
|
36784
|
+
const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);
|
|
36785
|
+
for (let i = 0; i < numComponentColors; i++) {
|
|
36786
|
+
allColors[i] = i;
|
|
36787
|
+
}
|
|
36788
|
+
const colorMap = new Uint8ClampedArray(numComponentColors * 3);
|
|
36789
|
+
this.getRgbBuffer(
|
|
36790
|
+
allColors,
|
|
36791
|
+
0,
|
|
36792
|
+
numComponentColors,
|
|
36793
|
+
colorMap,
|
|
36794
|
+
0,
|
|
36795
|
+
bpc,
|
|
36796
|
+
/* alpha01 = */
|
|
36797
|
+
0
|
|
36798
|
+
);
|
|
36799
|
+
if (!needsResizing) {
|
|
36800
|
+
let destPos = 0;
|
|
36801
|
+
for (let i = 0; i < count; ++i) {
|
|
36802
|
+
const key = comps[i] * 3;
|
|
36803
|
+
dest[destPos++] = colorMap[key];
|
|
36804
|
+
dest[destPos++] = colorMap[key + 1];
|
|
36805
|
+
dest[destPos++] = colorMap[key + 2];
|
|
36806
|
+
destPos += alpha01;
|
|
36807
|
+
}
|
|
36808
|
+
} else {
|
|
36809
|
+
rgbBuf = new Uint8Array(count * 3);
|
|
36810
|
+
let rgbPos = 0;
|
|
36811
|
+
for (let i = 0; i < count; ++i) {
|
|
36812
|
+
const key = comps[i] * 3;
|
|
36813
|
+
rgbBuf[rgbPos++] = colorMap[key];
|
|
36814
|
+
rgbBuf[rgbPos++] = colorMap[key + 1];
|
|
36815
|
+
rgbBuf[rgbPos++] = colorMap[key + 2];
|
|
36816
|
+
}
|
|
36817
|
+
}
|
|
36818
|
+
} else if (!needsResizing) {
|
|
36819
|
+
this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);
|
|
36820
|
+
} else {
|
|
36821
|
+
rgbBuf = new Uint8ClampedArray(count * 3);
|
|
36822
|
+
this.getRgbBuffer(
|
|
36823
|
+
comps,
|
|
36824
|
+
0,
|
|
36825
|
+
count,
|
|
36826
|
+
rgbBuf,
|
|
36827
|
+
0,
|
|
36828
|
+
bpc,
|
|
36829
|
+
/* alpha01 = */
|
|
36830
|
+
0
|
|
36831
|
+
);
|
|
36832
|
+
}
|
|
36833
|
+
if (rgbBuf) {
|
|
36834
|
+
if (needsResizing) {
|
|
36835
|
+
resizeRgbImage(
|
|
36836
|
+
rgbBuf,
|
|
36837
|
+
dest,
|
|
36838
|
+
originalWidth,
|
|
36839
|
+
originalHeight,
|
|
36840
|
+
width,
|
|
36841
|
+
height,
|
|
36842
|
+
alpha01
|
|
36843
|
+
);
|
|
36844
|
+
} else {
|
|
36845
|
+
let destPos = 0, rgbPos = 0;
|
|
36846
|
+
for (let i = 0, ii = width * actualHeight; i < ii; i++) {
|
|
36847
|
+
dest[destPos++] = rgbBuf[rgbPos++];
|
|
36848
|
+
dest[destPos++] = rgbBuf[rgbPos++];
|
|
36849
|
+
dest[destPos++] = rgbBuf[rgbPos++];
|
|
36850
|
+
destPos += alpha01;
|
|
36851
|
+
}
|
|
36852
|
+
}
|
|
36853
|
+
}
|
|
36854
|
+
}
|
|
36855
|
+
/**
|
|
36856
|
+
* True if the colorspace has components in the default range of [0, 1].
|
|
36857
|
+
* This should be true for all colorspaces except for lab color spaces
|
|
36858
|
+
* which are [0,100], [-128, 127], [-128, 127].
|
|
36859
|
+
*/
|
|
36860
|
+
get usesZeroToOneRange() {
|
|
36861
|
+
return shadow2(this, "usesZeroToOneRange", true);
|
|
36862
|
+
}
|
|
36863
|
+
/**
|
|
36864
|
+
* Checks if a decode map matches the default decode map for a color space.
|
|
36865
|
+
* This handles the general decode maps where there are two values per
|
|
36866
|
+
* component, e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
|
|
36867
|
+
* This does not handle Lab, Indexed, or Pattern decode maps since they are
|
|
36868
|
+
* slightly different.
|
|
36869
|
+
* @param {Array} decode - Decode map (usually from an image).
|
|
36870
|
+
* @param {number} numComps - Number of components the color space has.
|
|
36871
|
+
*/
|
|
36872
|
+
static isDefaultDecode(decode, numComps) {
|
|
36873
|
+
if (isDefaultDecodeHelper(decode, numComps * 2)) {
|
|
36874
|
+
return true;
|
|
36875
|
+
}
|
|
36876
|
+
for (let i = 0, ii = decode.length; i < ii; i += 2) {
|
|
36877
|
+
if (decode[i] !== 0 || decode[i + 1] !== 1) {
|
|
36878
|
+
return false;
|
|
36879
|
+
}
|
|
36880
|
+
}
|
|
36881
|
+
return true;
|
|
36882
|
+
}
|
|
36883
|
+
};
|
|
36884
|
+
DeviceCmykCS = class extends ColorSpace {
|
|
36885
|
+
constructor() {
|
|
36886
|
+
super("DeviceCMYK", 4);
|
|
36887
|
+
}
|
|
36888
|
+
// The coefficients below was found using numerical analysis: the method of
|
|
36889
|
+
// steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
|
|
36890
|
+
// where color_value is the tabular value from the table of sampled RGB colors
|
|
36891
|
+
// from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
|
|
36892
|
+
// CMYK color conversion using the estimation below:
|
|
36893
|
+
// f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
|
|
36894
|
+
#toRgb(src, srcOffset, srcScale, dest, destOffset) {
|
|
36895
|
+
const c = src[srcOffset] * srcScale;
|
|
36896
|
+
const m = src[srcOffset + 1] * srcScale;
|
|
36897
|
+
const y = src[srcOffset + 2] * srcScale;
|
|
36898
|
+
const k = src[srcOffset + 3] * srcScale;
|
|
36899
|
+
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);
|
|
36900
|
+
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);
|
|
36901
|
+
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);
|
|
36902
|
+
}
|
|
36903
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
36904
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
36905
|
+
assert2(
|
|
36906
|
+
dest instanceof Uint8ClampedArray,
|
|
36907
|
+
'DeviceCmykCS.getRgbItem: Unsupported "dest" type.'
|
|
36908
|
+
);
|
|
36909
|
+
}
|
|
36910
|
+
this.#toRgb(src, srcOffset, 1, dest, destOffset);
|
|
36911
|
+
}
|
|
36912
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
36913
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
36914
|
+
assert2(
|
|
36915
|
+
dest instanceof Uint8ClampedArray,
|
|
36916
|
+
'DeviceCmykCS.getRgbBuffer: Unsupported "dest" type.'
|
|
36917
|
+
);
|
|
36918
|
+
}
|
|
36919
|
+
const scale = 1 / ((1 << bits) - 1);
|
|
36920
|
+
for (let i = 0; i < count; i++) {
|
|
36921
|
+
this.#toRgb(src, srcOffset, scale, dest, destOffset);
|
|
36922
|
+
srcOffset += 4;
|
|
36923
|
+
destOffset += 3 + alpha01;
|
|
36924
|
+
}
|
|
36925
|
+
}
|
|
36926
|
+
};
|
|
36927
|
+
CalGrayCS = class extends ColorSpace {
|
|
36928
|
+
constructor(whitePoint, blackPoint, gamma) {
|
|
36929
|
+
super("CalGray", 1);
|
|
36930
|
+
if (!whitePoint) {
|
|
36931
|
+
throw new FormatError(
|
|
36932
|
+
"WhitePoint missing - required for color space CalGray"
|
|
36933
|
+
);
|
|
36934
|
+
}
|
|
36935
|
+
[this.XW, this.YW, this.ZW] = whitePoint;
|
|
36936
|
+
[this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
|
|
36937
|
+
this.G = gamma || 1;
|
|
36938
|
+
if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
|
|
36939
|
+
throw new FormatError(
|
|
36940
|
+
`Invalid WhitePoint components for ${this.name}, no fallback available`
|
|
36941
|
+
);
|
|
36942
|
+
}
|
|
36943
|
+
if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
|
|
36944
|
+
info(`Invalid BlackPoint for ${this.name}, falling back to default.`);
|
|
36945
|
+
this.XB = this.YB = this.ZB = 0;
|
|
36946
|
+
}
|
|
36947
|
+
if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
|
|
36948
|
+
warn2(
|
|
36949
|
+
`${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ZB: ${this.ZB}, only default values are supported.`
|
|
36950
|
+
);
|
|
36951
|
+
}
|
|
36952
|
+
if (this.G < 1) {
|
|
36953
|
+
info(
|
|
36954
|
+
`Invalid Gamma: ${this.G} for ${this.name}, falling back to default.`
|
|
36955
|
+
);
|
|
36956
|
+
this.G = 1;
|
|
36957
|
+
}
|
|
36958
|
+
}
|
|
36959
|
+
#toRgb(src, srcOffset, dest, destOffset, scale) {
|
|
36960
|
+
const A = src[srcOffset] * scale;
|
|
36961
|
+
const AG = A ** this.G;
|
|
36962
|
+
const L = this.YW * AG;
|
|
36963
|
+
const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0);
|
|
36964
|
+
dest[destOffset] = val;
|
|
36965
|
+
dest[destOffset + 1] = val;
|
|
36966
|
+
dest[destOffset + 2] = val;
|
|
36967
|
+
}
|
|
36968
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
36969
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
36970
|
+
assert2(
|
|
36971
|
+
dest instanceof Uint8ClampedArray,
|
|
36972
|
+
'CalGrayCS.getRgbItem: Unsupported "dest" type.'
|
|
36973
|
+
);
|
|
36974
|
+
}
|
|
36975
|
+
this.#toRgb(src, srcOffset, dest, destOffset, 1);
|
|
36976
|
+
}
|
|
36977
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
36978
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
36979
|
+
assert2(
|
|
36980
|
+
dest instanceof Uint8ClampedArray,
|
|
36981
|
+
'CalGrayCS.getRgbBuffer: Unsupported "dest" type.'
|
|
36982
|
+
);
|
|
36983
|
+
}
|
|
36984
|
+
const scale = 1 / ((1 << bits) - 1);
|
|
36985
|
+
for (let i = 0; i < count; ++i) {
|
|
36986
|
+
this.#toRgb(src, srcOffset, dest, destOffset, scale);
|
|
36987
|
+
srcOffset += 1;
|
|
36988
|
+
destOffset += 3 + alpha01;
|
|
36989
|
+
}
|
|
36990
|
+
}
|
|
36991
|
+
};
|
|
36992
|
+
CalRGBCS = class _CalRGBCS extends ColorSpace {
|
|
36993
|
+
// See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these
|
|
36994
|
+
// matrices.
|
|
36995
|
+
// prettier-ignore
|
|
36996
|
+
static #BRADFORD_SCALE_MATRIX = new Float32Array([
|
|
36997
|
+
0.8951,
|
|
36998
|
+
0.2664,
|
|
36999
|
+
-0.1614,
|
|
37000
|
+
-0.7502,
|
|
37001
|
+
1.7135,
|
|
37002
|
+
0.0367,
|
|
37003
|
+
0.0389,
|
|
37004
|
+
-0.0685,
|
|
37005
|
+
1.0296
|
|
37006
|
+
]);
|
|
37007
|
+
// prettier-ignore
|
|
37008
|
+
static #BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([
|
|
37009
|
+
0.9869929,
|
|
37010
|
+
-0.1470543,
|
|
37011
|
+
0.1599627,
|
|
37012
|
+
0.4323053,
|
|
37013
|
+
0.5183603,
|
|
37014
|
+
0.0492912,
|
|
37015
|
+
-85287e-7,
|
|
37016
|
+
0.0400428,
|
|
37017
|
+
0.9684867
|
|
37018
|
+
]);
|
|
37019
|
+
// See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html.
|
|
37020
|
+
// prettier-ignore
|
|
37021
|
+
static #SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([
|
|
37022
|
+
3.2404542,
|
|
37023
|
+
-1.5371385,
|
|
37024
|
+
-0.4985314,
|
|
37025
|
+
-0.969266,
|
|
37026
|
+
1.8760108,
|
|
37027
|
+
0.041556,
|
|
37028
|
+
0.0556434,
|
|
37029
|
+
-0.2040259,
|
|
37030
|
+
1.0572252
|
|
37031
|
+
]);
|
|
37032
|
+
static #FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);
|
|
37033
|
+
static #tempNormalizeMatrix = new Float32Array(3);
|
|
37034
|
+
static #tempConvertMatrix1 = new Float32Array(3);
|
|
37035
|
+
static #tempConvertMatrix2 = new Float32Array(3);
|
|
37036
|
+
static #DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8;
|
|
37037
|
+
constructor(whitePoint, blackPoint, gamma, matrix) {
|
|
37038
|
+
super("CalRGB", 3);
|
|
37039
|
+
if (!whitePoint) {
|
|
37040
|
+
throw new FormatError(
|
|
37041
|
+
"WhitePoint missing - required for color space CalRGB"
|
|
37042
|
+
);
|
|
37043
|
+
}
|
|
37044
|
+
const [XW, YW, ZW] = this.whitePoint = whitePoint;
|
|
37045
|
+
const [XB, YB, ZB] = this.blackPoint = blackPoint || new Float32Array(3);
|
|
37046
|
+
[this.GR, this.GG, this.GB] = gamma || new Float32Array([1, 1, 1]);
|
|
37047
|
+
[
|
|
37048
|
+
this.MXA,
|
|
37049
|
+
this.MYA,
|
|
37050
|
+
this.MZA,
|
|
37051
|
+
this.MXB,
|
|
37052
|
+
this.MYB,
|
|
37053
|
+
this.MZB,
|
|
37054
|
+
this.MXC,
|
|
37055
|
+
this.MYC,
|
|
37056
|
+
this.MZC
|
|
37057
|
+
] = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
|
|
37058
|
+
if (XW < 0 || ZW < 0 || YW !== 1) {
|
|
37059
|
+
throw new FormatError(
|
|
37060
|
+
`Invalid WhitePoint components for ${this.name}, no fallback available`
|
|
37061
|
+
);
|
|
37062
|
+
}
|
|
37063
|
+
if (XB < 0 || YB < 0 || ZB < 0) {
|
|
37064
|
+
info(
|
|
37065
|
+
`Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], falling back to default.`
|
|
37066
|
+
);
|
|
37067
|
+
this.blackPoint = new Float32Array(3);
|
|
37068
|
+
}
|
|
37069
|
+
if (this.GR < 0 || this.GG < 0 || this.GB < 0) {
|
|
37070
|
+
info(
|
|
37071
|
+
`Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ${this.name}, falling back to default.`
|
|
37072
|
+
);
|
|
37073
|
+
this.GR = this.GG = this.GB = 1;
|
|
37074
|
+
}
|
|
37075
|
+
}
|
|
37076
|
+
#matrixProduct(a, b, result) {
|
|
37077
|
+
result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
37078
|
+
result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
|
|
37079
|
+
result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
|
|
37080
|
+
}
|
|
37081
|
+
#toFlat(sourceWhitePoint, LMS, result) {
|
|
37082
|
+
result[0] = LMS[0] * 1 / sourceWhitePoint[0];
|
|
37083
|
+
result[1] = LMS[1] * 1 / sourceWhitePoint[1];
|
|
37084
|
+
result[2] = LMS[2] * 1 / sourceWhitePoint[2];
|
|
37085
|
+
}
|
|
37086
|
+
#toD65(sourceWhitePoint, LMS, result) {
|
|
37087
|
+
const D65X = 0.95047;
|
|
37088
|
+
const D65Y = 1;
|
|
37089
|
+
const D65Z = 1.08883;
|
|
37090
|
+
result[0] = LMS[0] * D65X / sourceWhitePoint[0];
|
|
37091
|
+
result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
|
|
37092
|
+
result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
|
|
37093
|
+
}
|
|
37094
|
+
#sRGBTransferFunction(color) {
|
|
37095
|
+
if (color <= 31308e-7) {
|
|
37096
|
+
return MathClamp(12.92 * color, 0, 1);
|
|
37097
|
+
}
|
|
37098
|
+
return color >= 0.99554525 ? 1 : MathClamp((1 + 0.055) * color ** (1 / 2.4) - 0.055, 0, 1);
|
|
37099
|
+
}
|
|
37100
|
+
#decodeL(L) {
|
|
37101
|
+
if (L < 0) {
|
|
37102
|
+
return -this.#decodeL(-L);
|
|
37103
|
+
}
|
|
37104
|
+
return L > 8 ? ((L + 16) / 116) ** 3 : L * _CalRGBCS.#DECODE_L_CONSTANT;
|
|
37105
|
+
}
|
|
37106
|
+
#compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
|
|
37107
|
+
if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {
|
|
37108
|
+
result[0] = XYZ_Flat[0];
|
|
37109
|
+
result[1] = XYZ_Flat[1];
|
|
37110
|
+
result[2] = XYZ_Flat[2];
|
|
37111
|
+
return;
|
|
37112
|
+
}
|
|
37113
|
+
const zeroDecodeL = this.#decodeL(0);
|
|
37114
|
+
const X_DST = zeroDecodeL;
|
|
37115
|
+
const X_SRC = this.#decodeL(sourceBlackPoint[0]);
|
|
37116
|
+
const Y_DST = zeroDecodeL;
|
|
37117
|
+
const Y_SRC = this.#decodeL(sourceBlackPoint[1]);
|
|
37118
|
+
const Z_DST = zeroDecodeL;
|
|
37119
|
+
const Z_SRC = this.#decodeL(sourceBlackPoint[2]);
|
|
37120
|
+
const X_Scale = (1 - X_DST) / (1 - X_SRC);
|
|
37121
|
+
const X_Offset = 1 - X_Scale;
|
|
37122
|
+
const Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
|
|
37123
|
+
const Y_Offset = 1 - Y_Scale;
|
|
37124
|
+
const Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
|
|
37125
|
+
const Z_Offset = 1 - Z_Scale;
|
|
37126
|
+
result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
|
|
37127
|
+
result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
|
|
37128
|
+
result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
|
|
37129
|
+
}
|
|
37130
|
+
#normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
|
|
37131
|
+
if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
|
|
37132
|
+
result[0] = XYZ_In[0];
|
|
37133
|
+
result[1] = XYZ_In[1];
|
|
37134
|
+
result[2] = XYZ_In[2];
|
|
37135
|
+
return;
|
|
37136
|
+
}
|
|
37137
|
+
const LMS = result;
|
|
37138
|
+
this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
|
|
37139
|
+
const LMS_Flat = _CalRGBCS.#tempNormalizeMatrix;
|
|
37140
|
+
this.#toFlat(sourceWhitePoint, LMS, LMS_Flat);
|
|
37141
|
+
this.#matrixProduct(
|
|
37142
|
+
_CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
|
|
37143
|
+
LMS_Flat,
|
|
37144
|
+
result
|
|
37145
|
+
);
|
|
37146
|
+
}
|
|
37147
|
+
#normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
|
|
37148
|
+
const LMS = result;
|
|
37149
|
+
this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
|
|
37150
|
+
const LMS_D65 = _CalRGBCS.#tempNormalizeMatrix;
|
|
37151
|
+
this.#toD65(sourceWhitePoint, LMS, LMS_D65);
|
|
37152
|
+
this.#matrixProduct(
|
|
37153
|
+
_CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX,
|
|
37154
|
+
LMS_D65,
|
|
37155
|
+
result
|
|
37156
|
+
);
|
|
37157
|
+
}
|
|
37158
|
+
#toRgb(src, srcOffset, dest, destOffset, scale) {
|
|
37159
|
+
const A = MathClamp(src[srcOffset] * scale, 0, 1);
|
|
37160
|
+
const B = MathClamp(src[srcOffset + 1] * scale, 0, 1);
|
|
37161
|
+
const C = MathClamp(src[srcOffset + 2] * scale, 0, 1);
|
|
37162
|
+
const AGR = A === 1 ? 1 : A ** this.GR;
|
|
37163
|
+
const BGG = B === 1 ? 1 : B ** this.GG;
|
|
37164
|
+
const CGB = C === 1 ? 1 : C ** this.GB;
|
|
37165
|
+
const X = this.MXA * AGR + this.MXB * BGG + this.MXC * CGB;
|
|
37166
|
+
const Y = this.MYA * AGR + this.MYB * BGG + this.MYC * CGB;
|
|
37167
|
+
const Z = this.MZA * AGR + this.MZB * BGG + this.MZC * CGB;
|
|
37168
|
+
const XYZ = _CalRGBCS.#tempConvertMatrix1;
|
|
37169
|
+
XYZ[0] = X;
|
|
37170
|
+
XYZ[1] = Y;
|
|
37171
|
+
XYZ[2] = Z;
|
|
37172
|
+
const XYZ_Flat = _CalRGBCS.#tempConvertMatrix2;
|
|
37173
|
+
this.#normalizeWhitePointToFlat(this.whitePoint, XYZ, XYZ_Flat);
|
|
37174
|
+
const XYZ_Black = _CalRGBCS.#tempConvertMatrix1;
|
|
37175
|
+
this.#compensateBlackPoint(this.blackPoint, XYZ_Flat, XYZ_Black);
|
|
37176
|
+
const XYZ_D65 = _CalRGBCS.#tempConvertMatrix2;
|
|
37177
|
+
this.#normalizeWhitePointToD65(
|
|
37178
|
+
_CalRGBCS.#FLAT_WHITEPOINT_MATRIX,
|
|
37179
|
+
XYZ_Black,
|
|
37180
|
+
XYZ_D65
|
|
37181
|
+
);
|
|
37182
|
+
const SRGB = _CalRGBCS.#tempConvertMatrix1;
|
|
37183
|
+
this.#matrixProduct(_CalRGBCS.#SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
|
|
37184
|
+
dest[destOffset] = this.#sRGBTransferFunction(SRGB[0]) * 255;
|
|
37185
|
+
dest[destOffset + 1] = this.#sRGBTransferFunction(SRGB[1]) * 255;
|
|
37186
|
+
dest[destOffset + 2] = this.#sRGBTransferFunction(SRGB[2]) * 255;
|
|
37187
|
+
}
|
|
37188
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
37189
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
37190
|
+
assert2(
|
|
37191
|
+
dest instanceof Uint8ClampedArray,
|
|
37192
|
+
'CalRGBCS.getRgbItem: Unsupported "dest" type.'
|
|
37193
|
+
);
|
|
37194
|
+
}
|
|
37195
|
+
this.#toRgb(src, srcOffset, dest, destOffset, 1);
|
|
37196
|
+
}
|
|
37197
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
37198
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
37199
|
+
assert2(
|
|
37200
|
+
dest instanceof Uint8ClampedArray,
|
|
37201
|
+
'CalRGBCS.getRgbBuffer: Unsupported "dest" type.'
|
|
37202
|
+
);
|
|
37203
|
+
}
|
|
37204
|
+
const scale = 1 / ((1 << bits) - 1);
|
|
37205
|
+
for (let i = 0; i < count; ++i) {
|
|
37206
|
+
this.#toRgb(src, srcOffset, dest, destOffset, scale);
|
|
37207
|
+
srcOffset += 3;
|
|
37208
|
+
destOffset += 3 + alpha01;
|
|
37209
|
+
}
|
|
37210
|
+
}
|
|
37211
|
+
};
|
|
37212
|
+
LabCS = class extends ColorSpace {
|
|
37213
|
+
constructor(whitePoint, blackPoint, range) {
|
|
37214
|
+
super("Lab", 3);
|
|
37215
|
+
if (!whitePoint) {
|
|
37216
|
+
throw new FormatError(
|
|
37217
|
+
"WhitePoint missing - required for color space Lab"
|
|
37218
|
+
);
|
|
37219
|
+
}
|
|
37220
|
+
[this.XW, this.YW, this.ZW] = whitePoint;
|
|
37221
|
+
[this.amin, this.amax, this.bmin, this.bmax] = range || [
|
|
37222
|
+
-100,
|
|
37223
|
+
100,
|
|
37224
|
+
-100,
|
|
37225
|
+
100
|
|
37226
|
+
];
|
|
37227
|
+
[this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];
|
|
37228
|
+
if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
|
|
37229
|
+
throw new FormatError(
|
|
37230
|
+
"Invalid WhitePoint components, no fallback available"
|
|
37231
|
+
);
|
|
37232
|
+
}
|
|
37233
|
+
if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
|
|
37234
|
+
info("Invalid BlackPoint, falling back to default");
|
|
37235
|
+
this.XB = this.YB = this.ZB = 0;
|
|
37236
|
+
}
|
|
37237
|
+
if (this.amin > this.amax || this.bmin > this.bmax) {
|
|
37238
|
+
info("Invalid Range, falling back to defaults");
|
|
37239
|
+
this.amin = -100;
|
|
37240
|
+
this.amax = 100;
|
|
37241
|
+
this.bmin = -100;
|
|
37242
|
+
this.bmax = 100;
|
|
37243
|
+
}
|
|
37244
|
+
}
|
|
37245
|
+
// Function g(x) from spec
|
|
37246
|
+
#fn_g(x) {
|
|
37247
|
+
return x >= 6 / 29 ? x ** 3 : 108 / 841 * (x - 4 / 29);
|
|
37248
|
+
}
|
|
37249
|
+
#decode(value, high1, low2, high2) {
|
|
37250
|
+
return low2 + value * (high2 - low2) / high1;
|
|
37251
|
+
}
|
|
37252
|
+
// If decoding is needed maxVal should be 2^bits per component - 1.
|
|
37253
|
+
#toRgb(src, srcOffset, maxVal, dest, destOffset) {
|
|
37254
|
+
let Ls = src[srcOffset];
|
|
37255
|
+
let as = src[srcOffset + 1];
|
|
37256
|
+
let bs = src[srcOffset + 2];
|
|
37257
|
+
if (maxVal !== false) {
|
|
37258
|
+
Ls = this.#decode(Ls, maxVal, 0, 100);
|
|
37259
|
+
as = this.#decode(as, maxVal, this.amin, this.amax);
|
|
37260
|
+
bs = this.#decode(bs, maxVal, this.bmin, this.bmax);
|
|
37261
|
+
}
|
|
37262
|
+
if (as > this.amax) {
|
|
37263
|
+
as = this.amax;
|
|
37264
|
+
} else if (as < this.amin) {
|
|
37265
|
+
as = this.amin;
|
|
37266
|
+
}
|
|
37267
|
+
if (bs > this.bmax) {
|
|
37268
|
+
bs = this.bmax;
|
|
37269
|
+
} else if (bs < this.bmin) {
|
|
37270
|
+
bs = this.bmin;
|
|
37271
|
+
}
|
|
37272
|
+
const M = (Ls + 16) / 116;
|
|
37273
|
+
const L = M + as / 500;
|
|
37274
|
+
const N = M - bs / 200;
|
|
37275
|
+
const X = this.XW * this.#fn_g(L);
|
|
37276
|
+
const Y = this.YW * this.#fn_g(M);
|
|
37277
|
+
const Z = this.ZW * this.#fn_g(N);
|
|
37278
|
+
let r, g, b;
|
|
37279
|
+
if (this.ZW < 1) {
|
|
37280
|
+
r = X * 3.1339 + Y * -1.617 + Z * -0.4906;
|
|
37281
|
+
g = X * -0.9785 + Y * 1.916 + Z * 0.0333;
|
|
37282
|
+
b = X * 0.072 + Y * -0.229 + Z * 1.4057;
|
|
37283
|
+
} else {
|
|
37284
|
+
r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
|
|
37285
|
+
g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
|
|
37286
|
+
b = X * 0.0557 + Y * -0.204 + Z * 1.057;
|
|
37287
|
+
}
|
|
37288
|
+
dest[destOffset] = Math.sqrt(r) * 255;
|
|
37289
|
+
dest[destOffset + 1] = Math.sqrt(g) * 255;
|
|
37290
|
+
dest[destOffset + 2] = Math.sqrt(b) * 255;
|
|
37291
|
+
}
|
|
37292
|
+
getRgbItem(src, srcOffset, dest, destOffset) {
|
|
37293
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
37294
|
+
assert2(
|
|
37295
|
+
dest instanceof Uint8ClampedArray,
|
|
37296
|
+
'LabCS.getRgbItem: Unsupported "dest" type.'
|
|
37297
|
+
);
|
|
37298
|
+
}
|
|
37299
|
+
this.#toRgb(src, srcOffset, false, dest, destOffset);
|
|
37300
|
+
}
|
|
37301
|
+
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
|
|
37302
|
+
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
37303
|
+
assert2(
|
|
37304
|
+
dest instanceof Uint8ClampedArray,
|
|
37305
|
+
'LabCS.getRgbBuffer: Unsupported "dest" type.'
|
|
37306
|
+
);
|
|
37307
|
+
}
|
|
37308
|
+
const maxVal = (1 << bits) - 1;
|
|
37309
|
+
for (let i = 0; i < count; i++) {
|
|
37310
|
+
this.#toRgb(src, srcOffset, maxVal, dest, destOffset);
|
|
37311
|
+
srcOffset += 3;
|
|
37312
|
+
destOffset += 3 + alpha01;
|
|
37313
|
+
}
|
|
37314
|
+
}
|
|
37315
|
+
isDefaultDecode(decode, bpc) {
|
|
37316
|
+
return true;
|
|
37317
|
+
}
|
|
37318
|
+
get usesZeroToOneRange() {
|
|
37319
|
+
return shadow2(this, "usesZeroToOneRange", false);
|
|
37320
|
+
}
|
|
37321
|
+
};
|
|
37322
|
+
TOKEN = {
|
|
37323
|
+
// Structural tokens — not keyword operators
|
|
37324
|
+
number: 0,
|
|
37325
|
+
lbrace: 1,
|
|
37326
|
+
rbrace: 2,
|
|
37327
|
+
// Boolean literals
|
|
37328
|
+
true: 3,
|
|
37329
|
+
false: 4,
|
|
37330
|
+
// Arithmetic binary operators
|
|
37331
|
+
add: 5,
|
|
37332
|
+
sub: 6,
|
|
37333
|
+
mul: 7,
|
|
37334
|
+
div: 8,
|
|
37335
|
+
idiv: 9,
|
|
37336
|
+
mod: 10,
|
|
37337
|
+
exp: 11,
|
|
37338
|
+
// Comparison binary operators
|
|
37339
|
+
eq: 12,
|
|
37340
|
+
ne: 13,
|
|
37341
|
+
gt: 14,
|
|
37342
|
+
ge: 15,
|
|
37343
|
+
lt: 16,
|
|
37344
|
+
le: 17,
|
|
37345
|
+
// Bitwise / boolean binary operators
|
|
37346
|
+
and: 18,
|
|
37347
|
+
or: 19,
|
|
37348
|
+
xor: 20,
|
|
37349
|
+
bitshift: 21,
|
|
37350
|
+
// Unary arithmetic operators
|
|
37351
|
+
abs: 22,
|
|
37352
|
+
neg: 23,
|
|
37353
|
+
ceiling: 24,
|
|
37354
|
+
floor: 25,
|
|
37355
|
+
round: 26,
|
|
37356
|
+
truncate: 27,
|
|
37357
|
+
// Unary boolean / bitwise operator
|
|
37358
|
+
not: 28,
|
|
37359
|
+
// Mathematical functions — unary
|
|
37360
|
+
sqrt: 29,
|
|
37361
|
+
sin: 30,
|
|
37362
|
+
cos: 31,
|
|
37363
|
+
ln: 32,
|
|
37364
|
+
log: 33,
|
|
37365
|
+
// Mathematical function — binary
|
|
37366
|
+
atan: 34,
|
|
37367
|
+
// Type conversion operators
|
|
37368
|
+
cvi: 35,
|
|
37369
|
+
cvr: 36,
|
|
37370
|
+
// Stack operators
|
|
37371
|
+
dup: 37,
|
|
37372
|
+
exch: 38,
|
|
37373
|
+
pop: 39,
|
|
37374
|
+
copy: 40,
|
|
37375
|
+
index: 41,
|
|
37376
|
+
roll: 42,
|
|
37377
|
+
// Control flow
|
|
37378
|
+
if: 43,
|
|
37379
|
+
ifelse: 44,
|
|
37380
|
+
// End of input
|
|
37381
|
+
eof: 45,
|
|
37382
|
+
// Synthetic: produced by the optimizer, never emitted by the lexer.
|
|
37383
|
+
min: 46,
|
|
37384
|
+
max: 47
|
|
37385
|
+
};
|
|
37386
|
+
Token = class {
|
|
37387
|
+
constructor(id, value = null) {
|
|
37388
|
+
this.id = id;
|
|
37389
|
+
this.value = value;
|
|
37390
|
+
}
|
|
37391
|
+
};
|
|
37392
|
+
Lexer = class _Lexer {
|
|
37393
|
+
// Singletons for every non-number token, built lazily on first construction.
|
|
37394
|
+
// Keyword operator tokens carry their name as `value`; structural tokens
|
|
37395
|
+
// (lbrace, rbrace, eof) carry null.
|
|
37396
|
+
static #singletons = null;
|
|
37397
|
+
static #operatorSingletons = null;
|
|
37398
|
+
static #initSingletons() {
|
|
37399
|
+
const singletons = /* @__PURE__ */ Object.create(null);
|
|
37400
|
+
const operatorSingletons = /* @__PURE__ */ Object.create(null);
|
|
37401
|
+
for (const [name, id] of Object.entries(TOKEN)) {
|
|
37402
|
+
if (name === "number") {
|
|
37403
|
+
continue;
|
|
37404
|
+
}
|
|
37405
|
+
const isOperator = id >= TOKEN.true && id <= TOKEN.ifelse;
|
|
37406
|
+
const token = new Token(id, isOperator ? name : null);
|
|
37407
|
+
singletons[name] = token;
|
|
37408
|
+
if (isOperator) {
|
|
37409
|
+
operatorSingletons[name] = token;
|
|
37410
|
+
}
|
|
37411
|
+
}
|
|
37412
|
+
this.#singletons = singletons;
|
|
37413
|
+
this.#operatorSingletons = operatorSingletons;
|
|
37414
|
+
}
|
|
37415
|
+
constructor(data) {
|
|
37416
|
+
if (!_Lexer.#singletons) {
|
|
37417
|
+
_Lexer.#initSingletons();
|
|
37418
|
+
}
|
|
37419
|
+
this.data = data;
|
|
37420
|
+
this.pos = 0;
|
|
37421
|
+
this.len = data.length;
|
|
37422
|
+
this._numberPattern = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/iy;
|
|
37423
|
+
this._identifierPattern = /[a-z]+/y;
|
|
37424
|
+
}
|
|
37425
|
+
// Skip a % comment, advancing past the next \n or \r (or to EOF).
|
|
37426
|
+
_skipComment() {
|
|
37427
|
+
const lf = this.data.indexOf("\n", this.pos);
|
|
37428
|
+
const cr = this.data.indexOf("\r", this.pos);
|
|
37429
|
+
const eol = Math.min(lf < 0 ? this.len : lf, cr < 0 ? this.len : cr);
|
|
37430
|
+
this.pos = Math.min(eol + 1, this.len);
|
|
37431
|
+
}
|
|
37432
|
+
_getNumber() {
|
|
37433
|
+
this._numberPattern.lastIndex = this.pos;
|
|
37434
|
+
const match = this._numberPattern.exec(this.data);
|
|
37435
|
+
if (!match) {
|
|
37436
|
+
return new Token(TOKEN.number, 0);
|
|
37437
|
+
}
|
|
37438
|
+
const number = parseFloat(match[0]);
|
|
37439
|
+
if (!Number.isFinite(number)) {
|
|
37440
|
+
return new Token(TOKEN.number, 0);
|
|
37441
|
+
}
|
|
37442
|
+
this.pos = this._numberPattern.lastIndex;
|
|
37443
|
+
return new Token(TOKEN.number, number);
|
|
37444
|
+
}
|
|
37445
|
+
_getOperator() {
|
|
37446
|
+
this._identifierPattern.lastIndex = this.pos;
|
|
37447
|
+
const match = this._identifierPattern.exec(this.data);
|
|
37448
|
+
if (!match) {
|
|
37449
|
+
return new Token(TOKEN.number, 0);
|
|
37450
|
+
}
|
|
37451
|
+
this.pos = this._identifierPattern.lastIndex;
|
|
37452
|
+
const op = match[0];
|
|
37453
|
+
const token = _Lexer.#operatorSingletons[op];
|
|
37454
|
+
return token ?? new Token(TOKEN.number, 0);
|
|
37455
|
+
}
|
|
37456
|
+
// Return the next token, or Lexer.#singletons.eof at end of input.
|
|
37457
|
+
next() {
|
|
37458
|
+
while (this.pos < this.len) {
|
|
37459
|
+
const ch3 = this.data.charCodeAt(this.pos++);
|
|
37460
|
+
switch (ch3) {
|
|
37461
|
+
// PostScript white-space characters (PDF32000 §7.2.2)
|
|
37462
|
+
case 0:
|
|
37463
|
+
case 9:
|
|
37464
|
+
case 10:
|
|
37465
|
+
case 12:
|
|
37466
|
+
case 13:
|
|
37467
|
+
case 32:
|
|
37468
|
+
break;
|
|
37469
|
+
case 37:
|
|
37470
|
+
this._skipComment();
|
|
37471
|
+
break;
|
|
37472
|
+
case 123:
|
|
37473
|
+
return _Lexer.#singletons.lbrace;
|
|
37474
|
+
case 125:
|
|
37475
|
+
return _Lexer.#singletons.rbrace;
|
|
37476
|
+
case 43:
|
|
37477
|
+
case 45:
|
|
37478
|
+
this.pos--;
|
|
37479
|
+
return this._getNumber();
|
|
37480
|
+
case 46:
|
|
37481
|
+
this.pos--;
|
|
37482
|
+
return this._getNumber();
|
|
37483
|
+
default:
|
|
37484
|
+
if (ch3 >= 48 && ch3 <= 57) {
|
|
37485
|
+
this.pos--;
|
|
37486
|
+
return this._getNumber();
|
|
37487
|
+
}
|
|
37488
|
+
if (ch3 >= 97 && ch3 <= 122) {
|
|
37489
|
+
this.pos--;
|
|
37490
|
+
return this._getOperator();
|
|
37491
|
+
}
|
|
37492
|
+
return new Token(TOKEN.number, 0);
|
|
37493
|
+
}
|
|
37494
|
+
}
|
|
37495
|
+
return _Lexer.#singletons.eof;
|
|
37496
|
+
}
|
|
37497
|
+
};
|
|
37498
|
+
PS_VALUE_TYPE = {
|
|
37499
|
+
numeric: 0,
|
|
37500
|
+
// known to be a number (f64 in Wasm)
|
|
37501
|
+
boolean: 1,
|
|
37502
|
+
// known to be a boolean (0.0 = false, 1.0 = true in f64)
|
|
37503
|
+
unknown: 2
|
|
37504
|
+
// indeterminate at compile time
|
|
37505
|
+
};
|
|
37506
|
+
PS_NODE = {
|
|
37507
|
+
// Parser AST node types (produced by Parser / parsePostScriptFunction)
|
|
37508
|
+
program: 0,
|
|
37509
|
+
block: 1,
|
|
37510
|
+
number: 2,
|
|
37511
|
+
operator: 3,
|
|
37512
|
+
if: 4,
|
|
37513
|
+
ifelse: 5,
|
|
37514
|
+
// Tree AST node types (produced by PSStackToTree)
|
|
37515
|
+
arg: 6,
|
|
37516
|
+
const: 7,
|
|
37517
|
+
unary: 8,
|
|
37518
|
+
binary: 9,
|
|
37519
|
+
ternary: 10
|
|
37520
|
+
};
|
|
37521
|
+
PsNode = class {
|
|
37522
|
+
constructor(type) {
|
|
37523
|
+
this.type = type;
|
|
37524
|
+
}
|
|
37525
|
+
};
|
|
37526
|
+
PsProgram = class extends PsNode {
|
|
37527
|
+
constructor(body) {
|
|
37528
|
+
super(PS_NODE.program);
|
|
37529
|
+
this.body = body;
|
|
37530
|
+
}
|
|
37531
|
+
};
|
|
37532
|
+
PsBlock = class extends PsNode {
|
|
37533
|
+
constructor(instructions) {
|
|
37534
|
+
super(PS_NODE.block);
|
|
37535
|
+
this.instructions = instructions;
|
|
37536
|
+
}
|
|
37537
|
+
};
|
|
37538
|
+
PsNumber = class extends PsNode {
|
|
37539
|
+
/** @param {number} value */
|
|
37540
|
+
constructor(value) {
|
|
37541
|
+
super(PS_NODE.number);
|
|
37542
|
+
this.value = value;
|
|
37543
|
+
}
|
|
37544
|
+
};
|
|
37545
|
+
PsOperator = class extends PsNode {
|
|
37546
|
+
/** @param {number} op — one of the TOKEN.* constants from lexer.js */
|
|
37547
|
+
constructor(op) {
|
|
37548
|
+
super(PS_NODE.operator);
|
|
37549
|
+
this.op = op;
|
|
37550
|
+
}
|
|
37551
|
+
};
|
|
37552
|
+
PsIf = class extends PsNode {
|
|
37553
|
+
/** @param {PsBlock} then */
|
|
37554
|
+
constructor(then) {
|
|
37555
|
+
super(PS_NODE.if);
|
|
37556
|
+
this.then = then;
|
|
37557
|
+
}
|
|
37558
|
+
};
|
|
37559
|
+
PsIfElse = class extends PsNode {
|
|
37560
|
+
/**
|
|
37561
|
+
* @param {PsBlock} then
|
|
37562
|
+
* @param {PsBlock} otherwise
|
|
37563
|
+
*/
|
|
37564
|
+
constructor(then, otherwise) {
|
|
37565
|
+
super(PS_NODE.ifelse);
|
|
37566
|
+
this.then = then;
|
|
37567
|
+
this.otherwise = otherwise;
|
|
37568
|
+
}
|
|
37569
|
+
};
|
|
37570
|
+
PsArgNode = class extends PsNode {
|
|
37571
|
+
/** @param {number} index */
|
|
37572
|
+
constructor(index) {
|
|
37573
|
+
super(PS_NODE.arg);
|
|
37574
|
+
this.index = index;
|
|
37575
|
+
this.valueType = PS_VALUE_TYPE.numeric;
|
|
37576
|
+
}
|
|
37577
|
+
};
|
|
37578
|
+
PsConstNode = class extends PsNode {
|
|
37579
|
+
/** @param {number|boolean} value */
|
|
37580
|
+
constructor(value) {
|
|
37581
|
+
super(PS_NODE.const);
|
|
37582
|
+
this.value = value;
|
|
37583
|
+
this.valueType = typeof value === "boolean" ? PS_VALUE_TYPE.boolean : PS_VALUE_TYPE.numeric;
|
|
37584
|
+
}
|
|
37585
|
+
};
|
|
37586
|
+
PsUnaryNode = class extends PsNode {
|
|
37587
|
+
/**
|
|
37588
|
+
* @param {number} op — TOKEN.* constant
|
|
37589
|
+
* @param {PsNode} operand
|
|
37590
|
+
* @param {number} [valueType]
|
|
37591
|
+
*/
|
|
37592
|
+
constructor(op, operand, valueType = PS_VALUE_TYPE.unknown) {
|
|
37593
|
+
super(PS_NODE.unary);
|
|
37594
|
+
this.op = op;
|
|
37595
|
+
this.operand = operand;
|
|
37596
|
+
this.valueType = valueType;
|
|
37597
|
+
}
|
|
37598
|
+
};
|
|
37599
|
+
PsBinaryNode = class extends PsNode {
|
|
37600
|
+
/**
|
|
37601
|
+
* @param {number} op — TOKEN.* constant
|
|
37602
|
+
* @param {PsNode} first — was on top of stack
|
|
37603
|
+
* @param {PsNode} second — was below top
|
|
37604
|
+
* @param {number} [valueType]
|
|
37605
|
+
*/
|
|
37606
|
+
constructor(op, first, second, valueType = PS_VALUE_TYPE.unknown) {
|
|
37607
|
+
super(PS_NODE.binary);
|
|
37608
|
+
this.op = op;
|
|
37609
|
+
this.first = first;
|
|
37610
|
+
this.second = second;
|
|
37611
|
+
this.valueType = valueType;
|
|
37612
|
+
}
|
|
37613
|
+
};
|
|
37614
|
+
PsTernaryNode = class extends PsNode {
|
|
37615
|
+
/**
|
|
37616
|
+
* @param {PsNode} cond
|
|
37617
|
+
* @param {PsNode} then
|
|
37618
|
+
* @param {PsNode} otherwise
|
|
37619
|
+
* @param {number} [valueType]
|
|
37620
|
+
*/
|
|
37621
|
+
constructor(cond, then, otherwise, valueType = PS_VALUE_TYPE.unknown) {
|
|
37622
|
+
super(PS_NODE.ternary);
|
|
37623
|
+
this.cond = cond;
|
|
37624
|
+
this.then = then;
|
|
37625
|
+
this.otherwise = otherwise;
|
|
37626
|
+
this.valueType = valueType;
|
|
37627
|
+
}
|
|
37628
|
+
};
|
|
37629
|
+
Parser = class _Parser {
|
|
37630
|
+
constructor(lexer) {
|
|
37631
|
+
this.lexer = lexer;
|
|
37632
|
+
this._token = null;
|
|
37633
|
+
}
|
|
37634
|
+
static _isRegularOperator(id) {
|
|
37635
|
+
return id >= TOKEN.true && id < TOKEN.if;
|
|
37636
|
+
}
|
|
37637
|
+
// Fetch the next token from the lexer.
|
|
37638
|
+
_advance() {
|
|
37639
|
+
this._token = this.lexer.next();
|
|
37640
|
+
}
|
|
37641
|
+
// Assert that the current token has the given id, consume it, and return it.
|
|
37642
|
+
_expect(id) {
|
|
37643
|
+
if (this._token.id !== id) {
|
|
37644
|
+
throw new FormatError(
|
|
37645
|
+
`PostScript function: expected token id ${id}, got ${this._token.id}.`
|
|
37646
|
+
);
|
|
37647
|
+
}
|
|
37648
|
+
const tok = this._token;
|
|
37649
|
+
this._advance();
|
|
37650
|
+
return tok;
|
|
37651
|
+
}
|
|
37652
|
+
/**
|
|
37653
|
+
* Parse the full Type 4 function body.
|
|
37654
|
+
*
|
|
37655
|
+
* Grammar (simplified):
|
|
37656
|
+
* program ::= '{' block '}'
|
|
37657
|
+
* block ::= instruction*
|
|
37658
|
+
* instruction ::= number
|
|
37659
|
+
* | operator (any PS_OPERATOR except if / ifelse)
|
|
37660
|
+
* | '{' block '}' 'if'
|
|
37661
|
+
* | '{' block '}' '{' block '}' 'ifelse'
|
|
37662
|
+
* @returns {PsProgram}
|
|
37663
|
+
*/
|
|
37664
|
+
parse() {
|
|
37665
|
+
this._advance();
|
|
37666
|
+
this._expect(TOKEN.lbrace);
|
|
37667
|
+
const block = this._parseBlock();
|
|
37668
|
+
this._expect(TOKEN.rbrace);
|
|
37669
|
+
if (this._token.id !== TOKEN.eof) {
|
|
37670
|
+
warn2("PostScript function: unexpected content after closing brace.");
|
|
37671
|
+
}
|
|
37672
|
+
return new PsProgram(block);
|
|
37673
|
+
}
|
|
37674
|
+
_parseBlock() {
|
|
37675
|
+
const instructions = [];
|
|
37676
|
+
while (true) {
|
|
37677
|
+
const tok = this._token;
|
|
37678
|
+
switch (tok.id) {
|
|
37679
|
+
case TOKEN.number:
|
|
37680
|
+
instructions.push(new PsNumber(tok.value));
|
|
37681
|
+
this._advance();
|
|
37682
|
+
break;
|
|
37683
|
+
case TOKEN.lbrace: {
|
|
37684
|
+
this._advance();
|
|
37685
|
+
const thenBlock = this._parseBlock();
|
|
37686
|
+
this._expect(TOKEN.rbrace);
|
|
37687
|
+
if (this._token.id === TOKEN.if) {
|
|
37688
|
+
this._advance();
|
|
37689
|
+
instructions.push(new PsIf(thenBlock));
|
|
37690
|
+
} else if (this._token.id === TOKEN.lbrace) {
|
|
37691
|
+
this._advance();
|
|
37692
|
+
const elseBlock = this._parseBlock();
|
|
37693
|
+
this._expect(TOKEN.rbrace);
|
|
37694
|
+
this._expect(TOKEN.ifelse);
|
|
37695
|
+
instructions.push(new PsIfElse(thenBlock, elseBlock));
|
|
37696
|
+
} else {
|
|
37697
|
+
throw new FormatError(
|
|
37698
|
+
"PostScript function: a procedure block must be followed by 'if' or '{\u2026} ifelse'."
|
|
37699
|
+
);
|
|
37700
|
+
}
|
|
37701
|
+
break;
|
|
37702
|
+
}
|
|
37703
|
+
case TOKEN.rbrace:
|
|
37704
|
+
case TOKEN.eof:
|
|
37705
|
+
return new PsBlock(instructions);
|
|
37706
|
+
case TOKEN.if:
|
|
37707
|
+
case TOKEN.ifelse:
|
|
37708
|
+
throw new FormatError(
|
|
37709
|
+
`PostScript function: unexpected '${tok.value}' operator.`
|
|
37710
|
+
);
|
|
37711
|
+
default:
|
|
37712
|
+
if (_Parser._isRegularOperator(tok.id)) {
|
|
37713
|
+
instructions.push(new PsOperator(tok.id));
|
|
37714
|
+
this._advance();
|
|
37715
|
+
break;
|
|
37716
|
+
}
|
|
37717
|
+
throw new FormatError(
|
|
37718
|
+
`PostScript function: unexpected token id ${tok.id}.`
|
|
37719
|
+
);
|
|
37720
|
+
}
|
|
37721
|
+
}
|
|
37722
|
+
}
|
|
37723
|
+
};
|
|
37724
|
+
MAX_STACK_SIZE = 100;
|
|
37725
|
+
PSStackToTree = class _PSStackToTree {
|
|
37726
|
+
static #binaryOps = null;
|
|
37727
|
+
static #unaryOps = null;
|
|
37728
|
+
static #idempotentUnary = null;
|
|
37729
|
+
static #negatedComparison = null;
|
|
37730
|
+
static #init() {
|
|
37731
|
+
this.#binaryOps = /* @__PURE__ */ new Set([
|
|
37732
|
+
TOKEN.add,
|
|
37733
|
+
TOKEN.sub,
|
|
37734
|
+
TOKEN.mul,
|
|
37735
|
+
TOKEN.div,
|
|
37736
|
+
TOKEN.idiv,
|
|
37737
|
+
TOKEN.mod,
|
|
37738
|
+
TOKEN.exp,
|
|
37739
|
+
TOKEN.atan,
|
|
37740
|
+
TOKEN.eq,
|
|
37741
|
+
TOKEN.ne,
|
|
37742
|
+
TOKEN.gt,
|
|
37743
|
+
TOKEN.ge,
|
|
37744
|
+
TOKEN.lt,
|
|
37745
|
+
TOKEN.le,
|
|
37746
|
+
TOKEN.and,
|
|
37747
|
+
TOKEN.or,
|
|
37748
|
+
TOKEN.xor,
|
|
37749
|
+
TOKEN.bitshift
|
|
37750
|
+
]);
|
|
37751
|
+
this.#unaryOps = /* @__PURE__ */ new Set([
|
|
37752
|
+
TOKEN.abs,
|
|
37753
|
+
TOKEN.neg,
|
|
37754
|
+
TOKEN.ceiling,
|
|
37755
|
+
TOKEN.floor,
|
|
37756
|
+
TOKEN.round,
|
|
37757
|
+
TOKEN.truncate,
|
|
37758
|
+
TOKEN.sqrt,
|
|
37759
|
+
TOKEN.sin,
|
|
37760
|
+
TOKEN.cos,
|
|
37761
|
+
TOKEN.ln,
|
|
37762
|
+
TOKEN.log,
|
|
37763
|
+
TOKEN.cvi,
|
|
37764
|
+
TOKEN.cvr,
|
|
37765
|
+
TOKEN.not
|
|
37766
|
+
]);
|
|
37767
|
+
this.#idempotentUnary = /* @__PURE__ */ new Set([
|
|
37768
|
+
TOKEN.abs,
|
|
37769
|
+
TOKEN.ceiling,
|
|
37770
|
+
TOKEN.cvi,
|
|
37771
|
+
TOKEN.cvr,
|
|
37772
|
+
TOKEN.floor,
|
|
37773
|
+
TOKEN.round,
|
|
37774
|
+
TOKEN.truncate
|
|
37775
|
+
]);
|
|
37776
|
+
this.#negatedComparison = /* @__PURE__ */ new Map([
|
|
37777
|
+
[TOKEN.eq, TOKEN.ne],
|
|
37778
|
+
[TOKEN.ne, TOKEN.eq],
|
|
37779
|
+
[TOKEN.lt, TOKEN.ge],
|
|
37780
|
+
[TOKEN.le, TOKEN.gt],
|
|
37781
|
+
[TOKEN.gt, TOKEN.le],
|
|
37782
|
+
[TOKEN.ge, TOKEN.lt]
|
|
37783
|
+
]);
|
|
37784
|
+
}
|
|
37785
|
+
/**
|
|
37786
|
+
* @param {PsProgram} program
|
|
37787
|
+
* @param {number} numInputs — number of domain values placed on the stack
|
|
37788
|
+
* before the program runs (i.e. the length of the domain array / 2).
|
|
37789
|
+
* @returns {Array<PsNode>} — one tree node per output value.
|
|
37790
|
+
*/
|
|
37791
|
+
evaluate(program, numInputs) {
|
|
37792
|
+
if (!_PSStackToTree.#binaryOps) {
|
|
37793
|
+
_PSStackToTree.#init();
|
|
37794
|
+
}
|
|
37795
|
+
this._failed = false;
|
|
37796
|
+
if (numInputs > MAX_STACK_SIZE) {
|
|
37797
|
+
return null;
|
|
37798
|
+
}
|
|
37799
|
+
const stack = [];
|
|
37800
|
+
for (let i = 0; i < numInputs; i++) {
|
|
37801
|
+
stack.push(new PsArgNode(i));
|
|
37802
|
+
}
|
|
37803
|
+
this._evalBlock(program.body, stack);
|
|
37804
|
+
if (this._failed) {
|
|
37805
|
+
return null;
|
|
37806
|
+
}
|
|
37807
|
+
_PSStackToTree.#markShared(stack);
|
|
37808
|
+
return stack;
|
|
37809
|
+
}
|
|
37810
|
+
// Set node.shared / sharedCount on non-atomic nodes referenced more than
|
|
37811
|
+
// once. arg/const are excluded — they are cheap to re-emit inline.
|
|
37812
|
+
static #markShared(outputs) {
|
|
37813
|
+
const refCount = /* @__PURE__ */ new Map();
|
|
37814
|
+
const visit = (node) => {
|
|
37815
|
+
if (!node || node.type === PS_NODE.arg || node.type === PS_NODE.const) {
|
|
37816
|
+
return;
|
|
37817
|
+
}
|
|
37818
|
+
const prev = refCount.get(node) ?? 0;
|
|
37819
|
+
refCount.set(node, prev + 1);
|
|
37820
|
+
if (prev > 0) {
|
|
37821
|
+
return;
|
|
37822
|
+
}
|
|
37823
|
+
switch (node.type) {
|
|
37824
|
+
case PS_NODE.unary:
|
|
37825
|
+
visit(node.operand);
|
|
37826
|
+
break;
|
|
37827
|
+
case PS_NODE.binary:
|
|
37828
|
+
visit(node.first);
|
|
37829
|
+
visit(node.second);
|
|
37830
|
+
break;
|
|
37831
|
+
case PS_NODE.ternary:
|
|
37832
|
+
visit(node.cond);
|
|
37833
|
+
visit(node.then);
|
|
37834
|
+
visit(node.otherwise);
|
|
37835
|
+
break;
|
|
37836
|
+
}
|
|
37837
|
+
};
|
|
37838
|
+
for (const output of outputs) {
|
|
37839
|
+
visit(output);
|
|
37840
|
+
}
|
|
37841
|
+
for (const [node, count] of refCount) {
|
|
37842
|
+
if (count > 1) {
|
|
37843
|
+
node.shared = true;
|
|
37844
|
+
node.sharedCount = count;
|
|
37845
|
+
}
|
|
37846
|
+
}
|
|
37847
|
+
}
|
|
37848
|
+
_evalBlock(block, stack) {
|
|
37849
|
+
this._evalBlockFrom(block.instructions, 0, stack);
|
|
37850
|
+
}
|
|
37851
|
+
/**
|
|
37852
|
+
* Core evaluation loop. Processes `instructions[startIdx…]` in order,
|
|
37853
|
+
* mutating `stack` as each instruction executes.
|
|
37854
|
+
*
|
|
37855
|
+
* When a `{ body } if` instruction grows the stack (the PostScript "early
|
|
37856
|
+
* exit / guard" idiom), the remaining instructions in the current array are
|
|
37857
|
+
* evaluated on **both** the true-branch stack and the false-branch stack,
|
|
37858
|
+
* then the two results are merged into PsTernaryNodes. This handles
|
|
37859
|
+
* patterns like:
|
|
37860
|
+
*
|
|
37861
|
+
* cond { pop R G B sentinel } if
|
|
37862
|
+
* … more guards …
|
|
37863
|
+
* sentinel 0 gt { defaultR defaultG defaultB } if
|
|
37864
|
+
*/
|
|
37865
|
+
_evalBlockFrom(instructions, startIdx, stack) {
|
|
37866
|
+
for (let idx = startIdx; idx < instructions.length; idx++) {
|
|
37867
|
+
if (this._failed) {
|
|
37868
|
+
break;
|
|
37869
|
+
}
|
|
37870
|
+
const instr = instructions[idx];
|
|
37871
|
+
switch (instr.type) {
|
|
37872
|
+
case PS_NODE.number:
|
|
37873
|
+
stack.push(new PsConstNode(instr.value));
|
|
37874
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
37875
|
+
this._failed = true;
|
|
37876
|
+
}
|
|
37877
|
+
break;
|
|
37878
|
+
case PS_NODE.operator:
|
|
37879
|
+
this._evalOp(instr.op, stack);
|
|
37880
|
+
break;
|
|
37881
|
+
case PS_NODE.if: {
|
|
37882
|
+
if (stack.length < 1) {
|
|
37883
|
+
this._failed = true;
|
|
37884
|
+
break;
|
|
37885
|
+
}
|
|
37886
|
+
const cond = stack.pop();
|
|
37887
|
+
const saved = stack.slice();
|
|
37888
|
+
this._evalBlock(instr.then, stack);
|
|
37889
|
+
if (this._failed) {
|
|
37890
|
+
break;
|
|
37891
|
+
}
|
|
37892
|
+
if (stack.length === saved.length) {
|
|
37893
|
+
for (let i = 0; i < stack.length; i++) {
|
|
37894
|
+
if (stack[i] !== saved[i]) {
|
|
37895
|
+
stack[i] = this._makeTernary(cond, stack[i], saved[i]);
|
|
37896
|
+
}
|
|
37897
|
+
}
|
|
37898
|
+
} else if (stack.length > saved.length) {
|
|
37899
|
+
if (cond.type === PS_NODE.const) {
|
|
37900
|
+
if (!cond.value) {
|
|
37901
|
+
stack.length = 0;
|
|
37902
|
+
stack.push(...saved);
|
|
37903
|
+
}
|
|
37904
|
+
break;
|
|
37905
|
+
}
|
|
37906
|
+
const trueStack = stack.slice();
|
|
37907
|
+
this._evalBlockFrom(instructions, idx + 1, trueStack);
|
|
37908
|
+
if (this._failed) {
|
|
37909
|
+
break;
|
|
37910
|
+
}
|
|
37911
|
+
const falseStack = saved;
|
|
37912
|
+
this._evalBlockFrom(instructions, idx + 1, falseStack);
|
|
37913
|
+
if (this._failed) {
|
|
37914
|
+
break;
|
|
37915
|
+
}
|
|
37916
|
+
if (trueStack.length !== falseStack.length) {
|
|
37917
|
+
const zero2 = new PsConstNode(0);
|
|
37918
|
+
while (trueStack.length < falseStack.length) {
|
|
37919
|
+
trueStack.push(zero2);
|
|
37920
|
+
}
|
|
37921
|
+
while (falseStack.length < trueStack.length) {
|
|
37922
|
+
falseStack.push(zero2);
|
|
37923
|
+
}
|
|
37924
|
+
}
|
|
37925
|
+
stack.length = 0;
|
|
37926
|
+
for (let i = 0; i < trueStack.length; i++) {
|
|
37927
|
+
stack.push(this._makeTernary(cond, trueStack[i], falseStack[i]));
|
|
37928
|
+
}
|
|
37929
|
+
return;
|
|
37930
|
+
} else {
|
|
37931
|
+
this._failed = true;
|
|
37932
|
+
}
|
|
37933
|
+
break;
|
|
37934
|
+
}
|
|
37935
|
+
case PS_NODE.ifelse: {
|
|
37936
|
+
if (stack.length < 1) {
|
|
37937
|
+
this._failed = true;
|
|
37938
|
+
break;
|
|
37939
|
+
}
|
|
37940
|
+
const cond = stack.pop();
|
|
37941
|
+
const snapshot = stack.slice();
|
|
37942
|
+
const thenStack = snapshot.slice();
|
|
37943
|
+
this._evalBlock(instr.then, thenStack);
|
|
37944
|
+
if (this._failed) {
|
|
37945
|
+
break;
|
|
37946
|
+
}
|
|
37947
|
+
const elseStack = snapshot.slice();
|
|
37948
|
+
this._evalBlock(instr.otherwise, elseStack);
|
|
37949
|
+
if (this._failed) {
|
|
37950
|
+
break;
|
|
37951
|
+
}
|
|
37952
|
+
if (thenStack.length !== elseStack.length) {
|
|
37953
|
+
const zero2 = new PsConstNode(0);
|
|
37954
|
+
while (thenStack.length < elseStack.length) {
|
|
37955
|
+
thenStack.push(zero2);
|
|
37956
|
+
}
|
|
37957
|
+
while (elseStack.length < thenStack.length) {
|
|
37958
|
+
elseStack.push(zero2);
|
|
37959
|
+
}
|
|
37960
|
+
}
|
|
37961
|
+
stack.length = 0;
|
|
37962
|
+
for (let i = 0; i < thenStack.length; i++) {
|
|
37963
|
+
stack.push(this._makeTernary(cond, thenStack[i], elseStack[i]));
|
|
37964
|
+
}
|
|
37965
|
+
break;
|
|
37966
|
+
}
|
|
37967
|
+
}
|
|
37968
|
+
}
|
|
37969
|
+
}
|
|
37970
|
+
_evalOp(op, stack) {
|
|
37971
|
+
if (_PSStackToTree.#binaryOps.has(op)) {
|
|
37972
|
+
if (stack.length < 2) {
|
|
37973
|
+
this._failed = true;
|
|
37974
|
+
return;
|
|
37975
|
+
}
|
|
37976
|
+
const first = stack.pop();
|
|
37977
|
+
const second = stack.pop();
|
|
37978
|
+
stack.push(this._makeBinary(op, first, second));
|
|
37979
|
+
return;
|
|
37980
|
+
}
|
|
37981
|
+
if (_PSStackToTree.#unaryOps.has(op)) {
|
|
37982
|
+
if (stack.length < 1) {
|
|
37983
|
+
this._failed = true;
|
|
37984
|
+
return;
|
|
37985
|
+
}
|
|
37986
|
+
stack.push(this._makeUnary(op, stack.pop()));
|
|
37987
|
+
return;
|
|
37988
|
+
}
|
|
37989
|
+
switch (op) {
|
|
37990
|
+
case TOKEN.true:
|
|
37991
|
+
stack.push(new PsConstNode(true));
|
|
37992
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
37993
|
+
this._failed = true;
|
|
37994
|
+
}
|
|
37995
|
+
break;
|
|
37996
|
+
case TOKEN.false:
|
|
37997
|
+
stack.push(new PsConstNode(false));
|
|
37998
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
37999
|
+
this._failed = true;
|
|
38000
|
+
}
|
|
38001
|
+
break;
|
|
38002
|
+
case TOKEN.dup:
|
|
38003
|
+
if (stack.length < 1) {
|
|
38004
|
+
this._failed = true;
|
|
38005
|
+
break;
|
|
38006
|
+
}
|
|
38007
|
+
stack.push(stack.at(-1));
|
|
38008
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
38009
|
+
this._failed = true;
|
|
38010
|
+
}
|
|
38011
|
+
break;
|
|
38012
|
+
case TOKEN.exch: {
|
|
38013
|
+
if (stack.length < 2) {
|
|
38014
|
+
this._failed = true;
|
|
38015
|
+
break;
|
|
38016
|
+
}
|
|
38017
|
+
const a = stack.pop();
|
|
38018
|
+
const b = stack.pop();
|
|
38019
|
+
stack.push(a, b);
|
|
38020
|
+
break;
|
|
38021
|
+
}
|
|
38022
|
+
case TOKEN.pop:
|
|
38023
|
+
if (stack.length < 1) {
|
|
38024
|
+
this._failed = true;
|
|
38025
|
+
break;
|
|
38026
|
+
}
|
|
38027
|
+
stack.pop();
|
|
38028
|
+
break;
|
|
38029
|
+
case TOKEN.copy: {
|
|
38030
|
+
if (stack.length < 1) {
|
|
38031
|
+
this._failed = true;
|
|
38032
|
+
break;
|
|
38033
|
+
}
|
|
38034
|
+
const nNode = stack.pop();
|
|
38035
|
+
if (nNode.type === PS_NODE.const) {
|
|
38036
|
+
const n = nNode.value | 0;
|
|
38037
|
+
if (n === 0) {
|
|
38038
|
+
} else if (n < 0 || n > stack.length) {
|
|
38039
|
+
this._failed = true;
|
|
38040
|
+
} else {
|
|
38041
|
+
stack.push(...stack.slice(-n));
|
|
38042
|
+
if (stack.length > MAX_STACK_SIZE) {
|
|
38043
|
+
this._failed = true;
|
|
38044
|
+
}
|
|
38045
|
+
}
|
|
38046
|
+
} else {
|
|
38047
|
+
this._failed = true;
|
|
38048
|
+
}
|
|
38049
|
+
break;
|
|
38050
|
+
}
|
|
38051
|
+
case TOKEN.index: {
|
|
38052
|
+
if (stack.length < 1) {
|
|
38053
|
+
this._failed = true;
|
|
38054
|
+
break;
|
|
38055
|
+
}
|
|
38056
|
+
const nNode = stack.pop();
|
|
38057
|
+
if (nNode.type === PS_NODE.const) {
|
|
38058
|
+
const n = nNode.value | 0;
|
|
38059
|
+
if (n < 0 || n >= stack.length) {
|
|
38060
|
+
this._failed = true;
|
|
38061
|
+
} else {
|
|
38062
|
+
stack.push(stack.at(-n - 1));
|
|
38063
|
+
}
|
|
38064
|
+
} else {
|
|
38065
|
+
this._failed = true;
|
|
38066
|
+
}
|
|
38067
|
+
break;
|
|
38068
|
+
}
|
|
38069
|
+
case TOKEN.roll: {
|
|
38070
|
+
if (stack.length < 2) {
|
|
38071
|
+
this._failed = true;
|
|
38072
|
+
break;
|
|
38073
|
+
}
|
|
38074
|
+
const jNode = stack.pop();
|
|
38075
|
+
const nNode = stack.pop();
|
|
38076
|
+
if (nNode.type === PS_NODE.const && jNode.type === PS_NODE.const) {
|
|
38077
|
+
const n = nNode.value | 0;
|
|
38078
|
+
if (n === 0) {
|
|
38079
|
+
} else if (n < 0 || n > stack.length) {
|
|
38080
|
+
this._failed = true;
|
|
38081
|
+
} else {
|
|
38082
|
+
const j = ((jNode.value | 0) % n + n) % n;
|
|
38083
|
+
if (j > 0) {
|
|
38084
|
+
const slice = stack.splice(-n, n);
|
|
38085
|
+
stack.push(...slice.slice(n - j), ...slice.slice(0, n - j));
|
|
38086
|
+
}
|
|
38087
|
+
}
|
|
38088
|
+
} else {
|
|
38089
|
+
this._failed = true;
|
|
38090
|
+
}
|
|
38091
|
+
break;
|
|
38092
|
+
}
|
|
38093
|
+
default:
|
|
38094
|
+
this._failed = true;
|
|
38095
|
+
break;
|
|
38096
|
+
}
|
|
38097
|
+
}
|
|
38098
|
+
/**
|
|
38099
|
+
* Create a binary tree node, applying optimizations eagerly:
|
|
38100
|
+
*
|
|
38101
|
+
* 1. Constant folding — both operands are PsConstNode → fold to PsConstNode.
|
|
38102
|
+
* 2. Reflexive simplifications — x−x→0, x xor x→0, x eq x→true, etc.
|
|
38103
|
+
* 3. Algebraic simplifications with one known operand — identity elements
|
|
38104
|
+
* (x+0→x, x*1→x, …), absorbing elements (x*0→0, x and false→false, …),
|
|
38105
|
+
* and strength reductions (x*-1→neg(x), x^0.5→sqrt(x), x^2→x*x, …).
|
|
38106
|
+
*
|
|
38107
|
+
* Recall: `first` was on top of the stack (right operand for non-commutative
|
|
38108
|
+
* ops), `second` was below (left operand). So `a b sub` → second=a, first=b
|
|
38109
|
+
* → a − b.
|
|
38110
|
+
*/
|
|
38111
|
+
_makeBinary(op, first, second) {
|
|
38112
|
+
if (first.type === PS_NODE.const && second.type === PS_NODE.const) {
|
|
38113
|
+
const v = _evalBinaryConst(op, second.value, first.value);
|
|
38114
|
+
if (v !== void 0) {
|
|
38115
|
+
return new PsConstNode(v);
|
|
38116
|
+
}
|
|
38117
|
+
}
|
|
38118
|
+
if (_nodesEqual(first, second)) {
|
|
38119
|
+
switch (op) {
|
|
38120
|
+
case TOKEN.sub:
|
|
38121
|
+
return new PsConstNode(0);
|
|
38122
|
+
// x − x → 0
|
|
38123
|
+
case TOKEN.xor:
|
|
38124
|
+
return new PsConstNode(
|
|
38125
|
+
/* eslint-disable unicorn/prefer-logical-operator-over-ternary */
|
|
38126
|
+
first.valueType === PS_VALUE_TYPE.boolean ? false : 0
|
|
38127
|
+
/* eslint-enable unicorn/prefer-logical-operator-over-ternary */
|
|
38128
|
+
);
|
|
38129
|
+
// TOKEN.mod, TOKEN.div, TOKEN.idiv are NOT simplified here:
|
|
38130
|
+
// x op x is undefined when x = 0, so we cannot fold without knowing
|
|
38131
|
+
// that x is non-zero.
|
|
38132
|
+
case TOKEN.and:
|
|
38133
|
+
case TOKEN.or:
|
|
38134
|
+
return first;
|
|
38135
|
+
// x and x → x; x or x → x
|
|
38136
|
+
case TOKEN.min:
|
|
38137
|
+
case TOKEN.max:
|
|
38138
|
+
return first;
|
|
38139
|
+
// min(x,x) → x; max(x,x) → x
|
|
38140
|
+
case TOKEN.eq:
|
|
38141
|
+
case TOKEN.ge:
|
|
38142
|
+
case TOKEN.le:
|
|
38143
|
+
return new PsConstNode(true);
|
|
38144
|
+
case TOKEN.ne:
|
|
38145
|
+
case TOKEN.gt:
|
|
38146
|
+
case TOKEN.lt:
|
|
38147
|
+
return new PsConstNode(false);
|
|
38148
|
+
}
|
|
38149
|
+
}
|
|
38150
|
+
if (first.type === PS_NODE.const) {
|
|
38151
|
+
const b = first.value;
|
|
38152
|
+
switch (op) {
|
|
38153
|
+
case TOKEN.add:
|
|
38154
|
+
if (b === 0) {
|
|
38155
|
+
return second;
|
|
38156
|
+
}
|
|
38157
|
+
break;
|
|
38158
|
+
case TOKEN.sub:
|
|
38159
|
+
if (b === 0) {
|
|
38160
|
+
return second;
|
|
38161
|
+
}
|
|
38162
|
+
break;
|
|
38163
|
+
case TOKEN.mul:
|
|
38164
|
+
if (b === 1) {
|
|
38165
|
+
return second;
|
|
38166
|
+
}
|
|
38167
|
+
if (b === 0) {
|
|
38168
|
+
return first;
|
|
38169
|
+
}
|
|
38170
|
+
if (b === -1) {
|
|
38171
|
+
return this._makeUnary(TOKEN.neg, second);
|
|
38172
|
+
}
|
|
38173
|
+
break;
|
|
38174
|
+
case TOKEN.div:
|
|
38175
|
+
if (b !== 0) {
|
|
38176
|
+
return this._makeBinary(TOKEN.mul, new PsConstNode(1 / b), second);
|
|
38177
|
+
}
|
|
38178
|
+
break;
|
|
38179
|
+
case TOKEN.idiv:
|
|
38180
|
+
if (b === 1) {
|
|
38181
|
+
return second;
|
|
38182
|
+
}
|
|
38183
|
+
break;
|
|
38184
|
+
case TOKEN.exp:
|
|
38185
|
+
if (b === 1) {
|
|
38186
|
+
return second;
|
|
38187
|
+
}
|
|
38188
|
+
if (b === -1) {
|
|
38189
|
+
return this._makeBinary(TOKEN.div, second, new PsConstNode(1));
|
|
38190
|
+
}
|
|
38191
|
+
if (b === 0.5) {
|
|
38192
|
+
return this._makeUnary(TOKEN.sqrt, second);
|
|
38193
|
+
}
|
|
38194
|
+
if (b === 0.25) {
|
|
38195
|
+
const sqrtOnce = this._makeUnary(TOKEN.sqrt, second);
|
|
38196
|
+
return this._makeUnary(TOKEN.sqrt, sqrtOnce);
|
|
38197
|
+
}
|
|
38198
|
+
if (b === 2) {
|
|
38199
|
+
return this._makeBinary(TOKEN.mul, second, second);
|
|
38200
|
+
}
|
|
38201
|
+
if (b === 3) {
|
|
38202
|
+
return this._makeBinary(
|
|
38203
|
+
TOKEN.mul,
|
|
38204
|
+
this._makeBinary(TOKEN.mul, second, second),
|
|
38205
|
+
second
|
|
38206
|
+
);
|
|
38207
|
+
}
|
|
38208
|
+
if (b === 4) {
|
|
38209
|
+
const square = this._makeBinary(TOKEN.mul, second, second);
|
|
38210
|
+
return this._makeBinary(TOKEN.mul, square, square);
|
|
38211
|
+
}
|
|
38212
|
+
if (b === 0) {
|
|
38213
|
+
return new PsConstNode(1);
|
|
38214
|
+
}
|
|
38215
|
+
break;
|
|
38216
|
+
case TOKEN.and:
|
|
38217
|
+
if (b === true) {
|
|
38218
|
+
return second;
|
|
38219
|
+
}
|
|
38220
|
+
if (b === false) {
|
|
38221
|
+
return first;
|
|
38222
|
+
}
|
|
38223
|
+
break;
|
|
38224
|
+
case TOKEN.or:
|
|
38225
|
+
if (b === false) {
|
|
38226
|
+
return second;
|
|
38227
|
+
}
|
|
38228
|
+
if (b === true) {
|
|
38229
|
+
return first;
|
|
38230
|
+
}
|
|
38231
|
+
break;
|
|
38232
|
+
case TOKEN.min:
|
|
38233
|
+
if (second.type === PS_NODE.binary && second.op === TOKEN.max && second.first.type === PS_NODE.const && second.first.value >= b) {
|
|
38234
|
+
return first;
|
|
38235
|
+
}
|
|
38236
|
+
break;
|
|
38237
|
+
case TOKEN.max:
|
|
38238
|
+
if (second.type === PS_NODE.binary && second.op === TOKEN.min && second.first.type === PS_NODE.const && second.first.value <= b) {
|
|
38239
|
+
return first;
|
|
38240
|
+
}
|
|
38241
|
+
break;
|
|
38242
|
+
}
|
|
38243
|
+
}
|
|
38244
|
+
if (second.type === PS_NODE.const) {
|
|
38245
|
+
const a = second.value;
|
|
38246
|
+
switch (op) {
|
|
38247
|
+
case TOKEN.add:
|
|
38248
|
+
if (a === 0) {
|
|
38249
|
+
return first;
|
|
38250
|
+
}
|
|
38251
|
+
break;
|
|
38252
|
+
case TOKEN.sub:
|
|
38253
|
+
if (a === 0) {
|
|
38254
|
+
return this._makeUnary(TOKEN.neg, first);
|
|
38255
|
+
}
|
|
38256
|
+
break;
|
|
38257
|
+
case TOKEN.mul:
|
|
38258
|
+
if (a === 1) {
|
|
38259
|
+
return first;
|
|
38260
|
+
}
|
|
38261
|
+
if (a === 0) {
|
|
38262
|
+
return second;
|
|
38263
|
+
}
|
|
38264
|
+
if (a === -1) {
|
|
38265
|
+
return this._makeUnary(TOKEN.neg, first);
|
|
38266
|
+
}
|
|
38267
|
+
break;
|
|
38268
|
+
case TOKEN.and:
|
|
38269
|
+
if (a === true) {
|
|
38270
|
+
return first;
|
|
38271
|
+
}
|
|
38272
|
+
if (a === false) {
|
|
38273
|
+
return second;
|
|
38274
|
+
}
|
|
38275
|
+
break;
|
|
38276
|
+
case TOKEN.or:
|
|
38277
|
+
if (a === false) {
|
|
38278
|
+
return first;
|
|
38279
|
+
}
|
|
38280
|
+
if (a === true) {
|
|
38281
|
+
return second;
|
|
38282
|
+
}
|
|
38283
|
+
break;
|
|
38284
|
+
}
|
|
38285
|
+
}
|
|
38286
|
+
return new PsBinaryNode(
|
|
38287
|
+
op,
|
|
38288
|
+
first,
|
|
38289
|
+
second,
|
|
38290
|
+
_binaryValueType(op, first.valueType, second.valueType)
|
|
38291
|
+
);
|
|
38292
|
+
}
|
|
38293
|
+
/**
|
|
38294
|
+
* Create a unary tree node, applying optimizations eagerly:
|
|
38295
|
+
*
|
|
38296
|
+
* 1. Constant folding.
|
|
38297
|
+
* 2. not(comparison) → negated comparison: not(a eq b) → a ne b, etc.
|
|
38298
|
+
* 3. neg(a − b) → b − a.
|
|
38299
|
+
* 4. Double-negation: neg(neg(x)) → x, not(not(x)) → x.
|
|
38300
|
+
* 5. abs(neg(x)) → abs(x).
|
|
38301
|
+
* 6. Idempotent: f(f(x)) → f(x) for abs, ceiling, floor, round, etc.
|
|
38302
|
+
*/
|
|
38303
|
+
_makeUnary(op, operand) {
|
|
38304
|
+
if (operand.type === PS_NODE.const) {
|
|
38305
|
+
const v = _evalUnaryConst(op, operand.value);
|
|
38306
|
+
if (v !== void 0) {
|
|
38307
|
+
return new PsConstNode(v);
|
|
38308
|
+
}
|
|
38309
|
+
}
|
|
38310
|
+
if (op === TOKEN.not && operand.type === PS_NODE.binary) {
|
|
38311
|
+
const negated = _PSStackToTree.#negatedComparison.get(operand.op);
|
|
38312
|
+
if (negated !== void 0) {
|
|
38313
|
+
return new PsBinaryNode(
|
|
38314
|
+
negated,
|
|
38315
|
+
operand.first,
|
|
38316
|
+
operand.second,
|
|
38317
|
+
PS_VALUE_TYPE.boolean
|
|
38318
|
+
);
|
|
38319
|
+
}
|
|
38320
|
+
}
|
|
38321
|
+
if (op === TOKEN.neg && operand.type === PS_NODE.binary && operand.op === TOKEN.sub) {
|
|
38322
|
+
return this._makeBinary(TOKEN.sub, operand.second, operand.first);
|
|
38323
|
+
}
|
|
38324
|
+
if (operand.type === PS_NODE.unary) {
|
|
38325
|
+
if (op === TOKEN.neg && operand.op === TOKEN.neg || op === TOKEN.not && operand.op === TOKEN.not) {
|
|
38326
|
+
return operand.operand;
|
|
38327
|
+
}
|
|
38328
|
+
if (op === TOKEN.abs && operand.op === TOKEN.neg) {
|
|
38329
|
+
return this._makeUnary(TOKEN.abs, operand.operand);
|
|
38330
|
+
}
|
|
38331
|
+
if (_PSStackToTree.#idempotentUnary.has(op) && op === operand.op) {
|
|
38332
|
+
return operand;
|
|
38333
|
+
}
|
|
38334
|
+
}
|
|
38335
|
+
return new PsUnaryNode(op, operand, _unaryValueType(op, operand.valueType));
|
|
38336
|
+
}
|
|
38337
|
+
/**
|
|
38338
|
+
* Create a ternary node, applying optimizations eagerly:
|
|
38339
|
+
*
|
|
38340
|
+
* 1. Constant condition — fold to the live branch.
|
|
38341
|
+
* 2. Identical branches — the condition is irrelevant, return either branch.
|
|
38342
|
+
* 3. Boolean branch constants — `cond ? true : false` → cond,
|
|
38343
|
+
* `cond ? false : true` → not(cond).
|
|
38344
|
+
* 4. Ternary → branchless min/max when the condition compares two numeric
|
|
38345
|
+
* expressions that are also the two branches.
|
|
38346
|
+
*/
|
|
38347
|
+
_makeTernary(cond, then, otherwise) {
|
|
38348
|
+
if (cond.type === PS_NODE.const) {
|
|
38349
|
+
return cond.value ? then : otherwise;
|
|
38350
|
+
}
|
|
38351
|
+
if (_nodesEqual(then, otherwise)) {
|
|
38352
|
+
return then;
|
|
38353
|
+
}
|
|
38354
|
+
if (then.type === PS_NODE.const && otherwise.type === PS_NODE.const) {
|
|
38355
|
+
if (then.value === true && otherwise.value === false) {
|
|
38356
|
+
return cond;
|
|
38357
|
+
}
|
|
38358
|
+
if (then.value === false && otherwise.value === true) {
|
|
38359
|
+
return this._makeUnary(TOKEN.not, cond);
|
|
38360
|
+
}
|
|
38361
|
+
}
|
|
38362
|
+
if (cond.type === PS_NODE.binary) {
|
|
38363
|
+
const { op: cop, first: cf, second: cs } = cond;
|
|
38364
|
+
if (cop === TOKEN.gt || cop === TOKEN.ge) {
|
|
38365
|
+
if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
|
|
38366
|
+
return this._makeBinary(TOKEN.min, cf, cs);
|
|
38367
|
+
}
|
|
38368
|
+
if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
|
|
38369
|
+
return this._makeBinary(TOKEN.max, cf, cs);
|
|
38370
|
+
}
|
|
38371
|
+
} else if (cop === TOKEN.lt || cop === TOKEN.le) {
|
|
38372
|
+
if (_nodesEqual(then, cf) && _nodesEqual(otherwise, cs)) {
|
|
38373
|
+
return this._makeBinary(TOKEN.max, cf, cs);
|
|
38374
|
+
}
|
|
38375
|
+
if (_nodesEqual(then, cs) && _nodesEqual(otherwise, cf)) {
|
|
38376
|
+
return this._makeBinary(TOKEN.min, cf, cs);
|
|
38377
|
+
}
|
|
38378
|
+
}
|
|
38379
|
+
}
|
|
38380
|
+
return new PsTernaryNode(
|
|
38381
|
+
cond,
|
|
38382
|
+
then,
|
|
38383
|
+
otherwise,
|
|
38384
|
+
then.valueType === otherwise.valueType ? then.valueType : PS_VALUE_TYPE.unknown
|
|
38385
|
+
);
|
|
38386
|
+
}
|
|
38387
|
+
};
|
|
38388
|
+
OP = {
|
|
38389
|
+
ARG: 0,
|
|
38390
|
+
// [ARG, idx]
|
|
38391
|
+
CONST: 1,
|
|
38392
|
+
// [CONST, val]
|
|
38393
|
+
STORE: 2,
|
|
38394
|
+
// [STORE, slot, min, max] clamp(pop()) → mem[slot]
|
|
38395
|
+
IF: 3,
|
|
38396
|
+
// [IF, target] jump when top-of-stack === 0
|
|
38397
|
+
JUMP: 4,
|
|
38398
|
+
// [JUMP, target] unconditional
|
|
38399
|
+
ABS: 5,
|
|
38400
|
+
NEG: 6,
|
|
38401
|
+
CEIL: 7,
|
|
38402
|
+
FLOOR: 8,
|
|
38403
|
+
ROUND: 9,
|
|
38404
|
+
// floor(x + 0.5)
|
|
38405
|
+
TRUNC: 10,
|
|
38406
|
+
NOT_B: 11,
|
|
38407
|
+
// boolean NOT
|
|
38408
|
+
NOT_N: 12,
|
|
38409
|
+
// bitwise NOT
|
|
38410
|
+
SQRT: 13,
|
|
38411
|
+
SIN: 14,
|
|
38412
|
+
// degrees in/out
|
|
38413
|
+
COS: 15,
|
|
38414
|
+
LN: 16,
|
|
38415
|
+
LOG10: 17,
|
|
38416
|
+
CVI: 18,
|
|
38417
|
+
SHIFT: 19,
|
|
38418
|
+
// [SHIFT, amount] +ve = left, −ve = right
|
|
38419
|
+
// Binary ops: second below, first on top; result = second OP first.
|
|
38420
|
+
ADD: 20,
|
|
38421
|
+
SUB: 21,
|
|
38422
|
+
MUL: 22,
|
|
38423
|
+
DIV: 23,
|
|
38424
|
+
// 0 when divisor is 0
|
|
38425
|
+
IDIV: 24,
|
|
38426
|
+
// 0 when divisor is 0
|
|
38427
|
+
MOD: 25,
|
|
38428
|
+
// 0 when divisor is 0
|
|
38429
|
+
POW: 26,
|
|
38430
|
+
EQ: 27,
|
|
38431
|
+
NE: 28,
|
|
38432
|
+
GT: 29,
|
|
38433
|
+
GE: 30,
|
|
38434
|
+
LT: 31,
|
|
38435
|
+
LE: 32,
|
|
38436
|
+
AND: 33,
|
|
38437
|
+
OR: 34,
|
|
38438
|
+
XOR: 35,
|
|
38439
|
+
ATAN: 36,
|
|
38440
|
+
// atan2(second, first) → degrees [0, 360)
|
|
38441
|
+
MIN: 37,
|
|
38442
|
+
MAX: 38,
|
|
38443
|
+
TEE_TMP: 39,
|
|
38444
|
+
// [TEE_TMP, slot] peek top of stack → tmp[slot], leave on stack
|
|
38445
|
+
LOAD_TMP: 40
|
|
38446
|
+
// [LOAD_TMP, slot] push tmp[slot]
|
|
38447
|
+
};
|
|
38448
|
+
_DEG_TO_RAD = Math.PI / 180;
|
|
38449
|
+
_RAD_TO_DEG = 180 / Math.PI;
|
|
38450
|
+
PsJsCompiler = class {
|
|
38451
|
+
// Safe because JS is single-threaded.
|
|
38452
|
+
static #stack = new Float64Array(64);
|
|
38453
|
+
static #tmp = new Float64Array(64);
|
|
38454
|
+
constructor(domain, range) {
|
|
38455
|
+
this.nIn = domain.length >> 1;
|
|
38456
|
+
this.nOut = range.length >> 1;
|
|
38457
|
+
this.range = range;
|
|
38458
|
+
this.ir = [];
|
|
38459
|
+
this._tmpMap = /* @__PURE__ */ new Map();
|
|
38460
|
+
this._nextTmp = 0;
|
|
38461
|
+
}
|
|
38462
|
+
_compileNode(node) {
|
|
38463
|
+
if (node.shared) {
|
|
38464
|
+
const cached = this._tmpMap.get(node);
|
|
38465
|
+
if (cached !== void 0) {
|
|
38466
|
+
this.ir.push(OP.LOAD_TMP, cached);
|
|
38467
|
+
return true;
|
|
38468
|
+
}
|
|
38469
|
+
if (!this._compileNodeImpl(node)) {
|
|
38470
|
+
return false;
|
|
38471
|
+
}
|
|
38472
|
+
const slot = this._nextTmp++;
|
|
38473
|
+
this._tmpMap.set(node, slot);
|
|
38474
|
+
this.ir.push(OP.TEE_TMP, slot);
|
|
38475
|
+
return true;
|
|
38476
|
+
}
|
|
38477
|
+
return this._compileNodeImpl(node);
|
|
38478
|
+
}
|
|
38479
|
+
_compileNodeImpl(node) {
|
|
38480
|
+
switch (node.type) {
|
|
38481
|
+
case PS_NODE.arg:
|
|
38482
|
+
this.ir.push(OP.ARG, node.index);
|
|
38483
|
+
return true;
|
|
38484
|
+
case PS_NODE.const: {
|
|
38485
|
+
const v = node.value;
|
|
38486
|
+
this.ir.push(OP.CONST, typeof v === "boolean" ? Number(v) : v);
|
|
38487
|
+
return true;
|
|
38488
|
+
}
|
|
38489
|
+
case PS_NODE.unary:
|
|
38490
|
+
return this._compileUnary(node);
|
|
38491
|
+
case PS_NODE.binary:
|
|
38492
|
+
return this._compileBinary(node);
|
|
38493
|
+
case PS_NODE.ternary:
|
|
38494
|
+
return this._compileTernary(node);
|
|
38495
|
+
default:
|
|
38496
|
+
return false;
|
|
38497
|
+
}
|
|
38498
|
+
}
|
|
38499
|
+
_compileUnary(node) {
|
|
38500
|
+
const { op, operand, valueType } = node;
|
|
38501
|
+
if (op === TOKEN.cvr) {
|
|
38502
|
+
return this._compileNode(operand);
|
|
38503
|
+
}
|
|
38504
|
+
if (!this._compileNode(operand)) {
|
|
38505
|
+
return false;
|
|
38506
|
+
}
|
|
38507
|
+
switch (op) {
|
|
38508
|
+
case TOKEN.abs:
|
|
38509
|
+
this.ir.push(OP.ABS);
|
|
38510
|
+
break;
|
|
38511
|
+
case TOKEN.neg:
|
|
38512
|
+
this.ir.push(OP.NEG);
|
|
38513
|
+
break;
|
|
38514
|
+
case TOKEN.ceiling:
|
|
38515
|
+
this.ir.push(OP.CEIL);
|
|
38516
|
+
break;
|
|
38517
|
+
case TOKEN.floor:
|
|
38518
|
+
this.ir.push(OP.FLOOR);
|
|
38519
|
+
break;
|
|
38520
|
+
case TOKEN.round:
|
|
38521
|
+
this.ir.push(OP.ROUND);
|
|
38522
|
+
break;
|
|
38523
|
+
case TOKEN.truncate:
|
|
38524
|
+
this.ir.push(OP.TRUNC);
|
|
38525
|
+
break;
|
|
38526
|
+
case TOKEN.sqrt:
|
|
38527
|
+
this.ir.push(OP.SQRT);
|
|
38528
|
+
break;
|
|
38529
|
+
case TOKEN.sin:
|
|
38530
|
+
this.ir.push(OP.SIN);
|
|
38531
|
+
break;
|
|
38532
|
+
case TOKEN.cos:
|
|
38533
|
+
this.ir.push(OP.COS);
|
|
38534
|
+
break;
|
|
38535
|
+
case TOKEN.ln:
|
|
38536
|
+
this.ir.push(OP.LN);
|
|
38537
|
+
break;
|
|
38538
|
+
case TOKEN.log:
|
|
38539
|
+
this.ir.push(OP.LOG10);
|
|
38540
|
+
break;
|
|
38541
|
+
case TOKEN.cvi:
|
|
38542
|
+
this.ir.push(OP.CVI);
|
|
38543
|
+
break;
|
|
38544
|
+
case TOKEN.not:
|
|
38545
|
+
if (valueType === PS_VALUE_TYPE.boolean) {
|
|
38546
|
+
this.ir.push(OP.NOT_B);
|
|
38547
|
+
} else if (valueType === PS_VALUE_TYPE.numeric) {
|
|
38548
|
+
this.ir.push(OP.NOT_N);
|
|
38549
|
+
} else {
|
|
38550
|
+
return false;
|
|
38551
|
+
}
|
|
38552
|
+
break;
|
|
38553
|
+
default:
|
|
38554
|
+
return false;
|
|
38555
|
+
}
|
|
38556
|
+
return true;
|
|
38557
|
+
}
|
|
38558
|
+
_compileBinary(node) {
|
|
38559
|
+
const { op, first, second } = node;
|
|
38560
|
+
if (op === TOKEN.bitshift) {
|
|
38561
|
+
if (first.type !== PS_NODE.const || !Number.isInteger(first.value) || !this._compileNode(second)) {
|
|
38562
|
+
return false;
|
|
38563
|
+
}
|
|
38564
|
+
this.ir.push(OP.SHIFT, first.value);
|
|
38565
|
+
return true;
|
|
38566
|
+
}
|
|
38567
|
+
if (!this._compileNode(second) || !this._compileNode(first)) {
|
|
38568
|
+
return false;
|
|
38569
|
+
}
|
|
38570
|
+
switch (op) {
|
|
38571
|
+
case TOKEN.add:
|
|
38572
|
+
this.ir.push(OP.ADD);
|
|
38573
|
+
break;
|
|
38574
|
+
case TOKEN.sub:
|
|
38575
|
+
this.ir.push(OP.SUB);
|
|
38576
|
+
break;
|
|
38577
|
+
case TOKEN.mul:
|
|
38578
|
+
this.ir.push(OP.MUL);
|
|
38579
|
+
break;
|
|
38580
|
+
case TOKEN.div:
|
|
38581
|
+
this.ir.push(OP.DIV);
|
|
38582
|
+
break;
|
|
38583
|
+
case TOKEN.idiv:
|
|
38584
|
+
this.ir.push(OP.IDIV);
|
|
38585
|
+
break;
|
|
38586
|
+
case TOKEN.mod:
|
|
38587
|
+
this.ir.push(OP.MOD);
|
|
38588
|
+
break;
|
|
38589
|
+
case TOKEN.exp:
|
|
38590
|
+
this.ir.push(OP.POW);
|
|
38591
|
+
break;
|
|
38592
|
+
case TOKEN.eq:
|
|
38593
|
+
this.ir.push(OP.EQ);
|
|
38594
|
+
break;
|
|
38595
|
+
case TOKEN.ne:
|
|
38596
|
+
this.ir.push(OP.NE);
|
|
38597
|
+
break;
|
|
38598
|
+
case TOKEN.gt:
|
|
38599
|
+
this.ir.push(OP.GT);
|
|
38600
|
+
break;
|
|
38601
|
+
case TOKEN.ge:
|
|
38602
|
+
this.ir.push(OP.GE);
|
|
38603
|
+
break;
|
|
38604
|
+
case TOKEN.lt:
|
|
38605
|
+
this.ir.push(OP.LT);
|
|
38606
|
+
break;
|
|
38607
|
+
case TOKEN.le:
|
|
38608
|
+
this.ir.push(OP.LE);
|
|
38609
|
+
break;
|
|
38610
|
+
case TOKEN.and:
|
|
38611
|
+
this.ir.push(OP.AND);
|
|
38612
|
+
break;
|
|
38613
|
+
case TOKEN.or:
|
|
38614
|
+
this.ir.push(OP.OR);
|
|
38615
|
+
break;
|
|
38616
|
+
case TOKEN.xor:
|
|
38617
|
+
this.ir.push(OP.XOR);
|
|
38618
|
+
break;
|
|
38619
|
+
case TOKEN.atan:
|
|
38620
|
+
this.ir.push(OP.ATAN);
|
|
38621
|
+
break;
|
|
38622
|
+
case TOKEN.min:
|
|
38623
|
+
this.ir.push(OP.MIN);
|
|
38624
|
+
break;
|
|
38625
|
+
case TOKEN.max:
|
|
38626
|
+
this.ir.push(OP.MAX);
|
|
38627
|
+
break;
|
|
38628
|
+
default:
|
|
38629
|
+
return false;
|
|
38630
|
+
}
|
|
38631
|
+
return true;
|
|
38632
|
+
}
|
|
38633
|
+
_compileTernary(node) {
|
|
38634
|
+
if (!this._compileNode(node.cond)) {
|
|
38635
|
+
return false;
|
|
38636
|
+
}
|
|
38637
|
+
this.ir.push(OP.IF, 0);
|
|
38638
|
+
const ifPatch = this.ir.length - 1;
|
|
38639
|
+
if (!this._compileNode(node.then)) {
|
|
38640
|
+
return false;
|
|
38641
|
+
}
|
|
38642
|
+
this.ir.push(OP.JUMP, 0);
|
|
38643
|
+
const jumpPatch = this.ir.length - 1;
|
|
38644
|
+
this.ir[ifPatch] = this.ir.length;
|
|
38645
|
+
if (!this._compileNode(node.otherwise)) {
|
|
38646
|
+
return false;
|
|
38647
|
+
}
|
|
38648
|
+
this.ir[jumpPatch] = this.ir.length;
|
|
38649
|
+
return true;
|
|
38650
|
+
}
|
|
38651
|
+
compile(program) {
|
|
38652
|
+
const outputs = new PSStackToTree().evaluate(program, this.nIn);
|
|
38653
|
+
if (!outputs || outputs.length < this.nOut) {
|
|
38654
|
+
return null;
|
|
38655
|
+
}
|
|
38656
|
+
for (let i = 0; i < this.nOut; i++) {
|
|
38657
|
+
if (!this._compileNode(outputs[i])) {
|
|
38658
|
+
return null;
|
|
38659
|
+
}
|
|
38660
|
+
const min = this.range[i * 2];
|
|
38661
|
+
const max = this.range[i * 2 + 1];
|
|
38662
|
+
this.ir.push(OP.STORE, i, min, max);
|
|
38663
|
+
}
|
|
38664
|
+
return new Float64Array(this.ir);
|
|
38665
|
+
}
|
|
38666
|
+
static execute(ir, src, srcOffset, dest, destOffset) {
|
|
38667
|
+
let ip = 0, sp = 0;
|
|
38668
|
+
const n = ir.length;
|
|
38669
|
+
const stack = this.#stack;
|
|
38670
|
+
const tmp = this.#tmp;
|
|
38671
|
+
while (ip < n) {
|
|
38672
|
+
switch (ir[ip++] | 0) {
|
|
38673
|
+
case OP.ARG:
|
|
38674
|
+
stack[sp++] = src[srcOffset + (ir[ip++] | 0)];
|
|
38675
|
+
break;
|
|
38676
|
+
case OP.CONST:
|
|
38677
|
+
stack[sp++] = ir[ip++];
|
|
38678
|
+
break;
|
|
38679
|
+
case OP.STORE: {
|
|
38680
|
+
const slot = ir[ip++] | 0;
|
|
38681
|
+
const min = ir[ip++];
|
|
38682
|
+
const max = ir[ip++];
|
|
38683
|
+
dest[destOffset + slot] = MathClamp(stack[--sp], min, max);
|
|
38684
|
+
break;
|
|
38685
|
+
}
|
|
38686
|
+
case OP.IF: {
|
|
38687
|
+
const tgt = ir[ip++];
|
|
38688
|
+
if (stack[--sp] === 0) {
|
|
38689
|
+
ip = tgt;
|
|
38690
|
+
}
|
|
38691
|
+
break;
|
|
38692
|
+
}
|
|
38693
|
+
case OP.JUMP:
|
|
38694
|
+
ip = ir[ip];
|
|
38695
|
+
break;
|
|
38696
|
+
case OP.ABS:
|
|
38697
|
+
stack[sp - 1] = Math.abs(stack[sp - 1]);
|
|
38698
|
+
break;
|
|
38699
|
+
case OP.NEG:
|
|
38700
|
+
stack[sp - 1] = -stack[sp - 1];
|
|
38701
|
+
break;
|
|
38702
|
+
case OP.CEIL:
|
|
38703
|
+
stack[sp - 1] = Math.ceil(stack[sp - 1]);
|
|
38704
|
+
break;
|
|
38705
|
+
case OP.FLOOR:
|
|
38706
|
+
stack[sp - 1] = Math.floor(stack[sp - 1]);
|
|
38707
|
+
break;
|
|
38708
|
+
case OP.ROUND:
|
|
38709
|
+
stack[sp - 1] = Math.floor(stack[sp - 1] + 0.5);
|
|
38710
|
+
break;
|
|
38711
|
+
case OP.TRUNC:
|
|
38712
|
+
stack[sp - 1] = Math.trunc(stack[sp - 1]);
|
|
38713
|
+
break;
|
|
38714
|
+
case OP.NOT_B:
|
|
38715
|
+
stack[sp - 1] = stack[sp - 1] !== 0 ? 0 : 1;
|
|
38716
|
+
break;
|
|
38717
|
+
case OP.NOT_N:
|
|
38718
|
+
stack[sp - 1] = ~(stack[sp - 1] | 0);
|
|
38719
|
+
break;
|
|
38720
|
+
case OP.SQRT:
|
|
38721
|
+
stack[sp - 1] = Math.sqrt(stack[sp - 1]);
|
|
38722
|
+
break;
|
|
38723
|
+
case OP.SIN:
|
|
38724
|
+
stack[sp - 1] = Math.sin(stack[sp - 1] % 360 * _DEG_TO_RAD);
|
|
38725
|
+
break;
|
|
38726
|
+
case OP.COS:
|
|
38727
|
+
stack[sp - 1] = Math.cos(stack[sp - 1] % 360 * _DEG_TO_RAD);
|
|
38728
|
+
break;
|
|
38729
|
+
case OP.LN:
|
|
38730
|
+
stack[sp - 1] = Math.log(stack[sp - 1]);
|
|
38731
|
+
break;
|
|
38732
|
+
case OP.LOG10:
|
|
38733
|
+
stack[sp - 1] = Math.log10(stack[sp - 1]);
|
|
38734
|
+
break;
|
|
38735
|
+
case OP.CVI:
|
|
38736
|
+
stack[sp - 1] = Math.trunc(stack[sp - 1]) | 0;
|
|
38737
|
+
break;
|
|
38738
|
+
case OP.SHIFT: {
|
|
38739
|
+
const amt = ir[ip++];
|
|
38740
|
+
const v = stack[sp - 1] | 0;
|
|
38741
|
+
if (amt > 0) {
|
|
38742
|
+
stack[sp - 1] = v << amt;
|
|
38743
|
+
} else if (amt < 0) {
|
|
38744
|
+
stack[sp - 1] = v >> -amt;
|
|
38745
|
+
} else {
|
|
38746
|
+
stack[sp - 1] = v;
|
|
38747
|
+
}
|
|
38748
|
+
break;
|
|
38749
|
+
}
|
|
38750
|
+
case OP.ADD: {
|
|
38751
|
+
const b = stack[--sp];
|
|
38752
|
+
stack[sp - 1] += b;
|
|
38753
|
+
break;
|
|
38754
|
+
}
|
|
38755
|
+
case OP.SUB: {
|
|
38756
|
+
const b = stack[--sp];
|
|
38757
|
+
stack[sp - 1] -= b;
|
|
38758
|
+
break;
|
|
38759
|
+
}
|
|
38760
|
+
case OP.MUL: {
|
|
38761
|
+
const b = stack[--sp];
|
|
38762
|
+
stack[sp - 1] *= b;
|
|
38763
|
+
break;
|
|
38764
|
+
}
|
|
38765
|
+
case OP.DIV: {
|
|
38766
|
+
const b = stack[--sp];
|
|
38767
|
+
stack[sp - 1] = b !== 0 ? stack[sp - 1] / b : 0;
|
|
38768
|
+
break;
|
|
38769
|
+
}
|
|
38770
|
+
case OP.IDIV: {
|
|
38771
|
+
const b = stack[--sp];
|
|
38772
|
+
stack[sp - 1] = b !== 0 ? Math.trunc(stack[sp - 1] / b) : 0;
|
|
38773
|
+
break;
|
|
38774
|
+
}
|
|
38775
|
+
case OP.MOD: {
|
|
38776
|
+
const b = stack[--sp];
|
|
38777
|
+
stack[sp - 1] = b !== 0 ? stack[sp - 1] % b : 0;
|
|
38778
|
+
break;
|
|
38779
|
+
}
|
|
38780
|
+
case OP.POW: {
|
|
38781
|
+
const b = stack[--sp];
|
|
38782
|
+
stack[sp - 1] **= b;
|
|
38783
|
+
break;
|
|
38784
|
+
}
|
|
38785
|
+
case OP.EQ: {
|
|
38786
|
+
const b = stack[--sp];
|
|
38787
|
+
stack[sp - 1] = stack[sp - 1] === b ? 1 : 0;
|
|
38788
|
+
break;
|
|
38789
|
+
}
|
|
38790
|
+
case OP.NE: {
|
|
38791
|
+
const b = stack[--sp];
|
|
38792
|
+
stack[sp - 1] = stack[sp - 1] !== b ? 1 : 0;
|
|
38793
|
+
break;
|
|
38794
|
+
}
|
|
38795
|
+
case OP.GT: {
|
|
38796
|
+
const b = stack[--sp];
|
|
38797
|
+
stack[sp - 1] = stack[sp - 1] > b ? 1 : 0;
|
|
38798
|
+
break;
|
|
38799
|
+
}
|
|
38800
|
+
case OP.GE: {
|
|
38801
|
+
const b = stack[--sp];
|
|
38802
|
+
stack[sp - 1] = stack[sp - 1] >= b ? 1 : 0;
|
|
38803
|
+
break;
|
|
38804
|
+
}
|
|
38805
|
+
case OP.LT: {
|
|
38806
|
+
const b = stack[--sp];
|
|
38807
|
+
stack[sp - 1] = stack[sp - 1] < b ? 1 : 0;
|
|
38808
|
+
break;
|
|
38809
|
+
}
|
|
38810
|
+
case OP.LE: {
|
|
38811
|
+
const b = stack[--sp];
|
|
38812
|
+
stack[sp - 1] = stack[sp - 1] <= b ? 1 : 0;
|
|
38813
|
+
break;
|
|
38814
|
+
}
|
|
38815
|
+
case OP.AND: {
|
|
38816
|
+
const b = stack[--sp] | 0;
|
|
38817
|
+
stack[sp - 1] = (stack[sp - 1] | 0) & b;
|
|
38818
|
+
break;
|
|
38819
|
+
}
|
|
38820
|
+
case OP.OR: {
|
|
38821
|
+
const b = stack[--sp] | 0;
|
|
38822
|
+
stack[sp - 1] = stack[sp - 1] | 0 | b;
|
|
38823
|
+
break;
|
|
38824
|
+
}
|
|
38825
|
+
case OP.XOR: {
|
|
38826
|
+
const b = stack[--sp] | 0;
|
|
38827
|
+
stack[sp - 1] = (stack[sp - 1] | 0) ^ b;
|
|
38828
|
+
break;
|
|
38829
|
+
}
|
|
38830
|
+
case OP.ATAN: {
|
|
38831
|
+
const b = stack[--sp];
|
|
38832
|
+
const deg = Math.atan2(stack[sp - 1], b) * _RAD_TO_DEG;
|
|
38833
|
+
stack[sp - 1] = deg < 0 ? deg + 360 : deg;
|
|
38834
|
+
break;
|
|
38835
|
+
}
|
|
38836
|
+
case OP.MIN: {
|
|
38837
|
+
const b = stack[--sp];
|
|
38838
|
+
stack[sp - 1] = Math.min(stack[sp - 1], b);
|
|
38839
|
+
break;
|
|
38840
|
+
}
|
|
38841
|
+
case OP.MAX: {
|
|
38842
|
+
const b = stack[--sp];
|
|
38843
|
+
stack[sp - 1] = Math.max(stack[sp - 1], b);
|
|
38844
|
+
break;
|
|
38845
|
+
}
|
|
38846
|
+
case OP.TEE_TMP:
|
|
38847
|
+
tmp[ir[ip++] | 0] = stack[sp - 1];
|
|
38848
|
+
break;
|
|
38849
|
+
case OP.LOAD_TMP:
|
|
38850
|
+
stack[sp++] = tmp[ir[ip++] | 0];
|
|
38851
|
+
break;
|
|
38852
|
+
}
|
|
38853
|
+
}
|
|
38854
|
+
}
|
|
38855
|
+
};
|
|
38856
|
+
PSStackBasedInterpreter = class {
|
|
38857
|
+
// Safe: JS is single-threaded.
|
|
38858
|
+
static #stack = new Float64Array(100);
|
|
38859
|
+
static #sp = 0;
|
|
38860
|
+
static #push(v) {
|
|
38861
|
+
if (this.#sp < this.#stack.length) {
|
|
38862
|
+
this.#stack[this.#sp++] = v;
|
|
38863
|
+
}
|
|
38864
|
+
}
|
|
38865
|
+
static #execOp(op) {
|
|
38866
|
+
const stack = this.#stack;
|
|
38867
|
+
switch (op) {
|
|
38868
|
+
case TOKEN.true:
|
|
38869
|
+
this.#push(1);
|
|
38870
|
+
break;
|
|
38871
|
+
case TOKEN.false:
|
|
38872
|
+
this.#push(0);
|
|
38873
|
+
break;
|
|
38874
|
+
case TOKEN.abs:
|
|
38875
|
+
stack[this.#sp - 1] = Math.abs(stack[this.#sp - 1]);
|
|
38876
|
+
break;
|
|
38877
|
+
case TOKEN.neg:
|
|
38878
|
+
stack[this.#sp - 1] = -stack[this.#sp - 1];
|
|
38879
|
+
break;
|
|
38880
|
+
case TOKEN.ceiling:
|
|
38881
|
+
stack[this.#sp - 1] = Math.ceil(stack[this.#sp - 1]);
|
|
38882
|
+
break;
|
|
38883
|
+
case TOKEN.floor:
|
|
38884
|
+
stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1]);
|
|
38885
|
+
break;
|
|
38886
|
+
case TOKEN.round:
|
|
38887
|
+
stack[this.#sp - 1] = Math.floor(stack[this.#sp - 1] + 0.5);
|
|
38888
|
+
break;
|
|
38889
|
+
case TOKEN.truncate:
|
|
38890
|
+
stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]);
|
|
38891
|
+
break;
|
|
38892
|
+
case TOKEN.sqrt:
|
|
38893
|
+
stack[this.#sp - 1] = Math.sqrt(stack[this.#sp - 1]);
|
|
38894
|
+
break;
|
|
38895
|
+
case TOKEN.sin:
|
|
38896
|
+
stack[this.#sp - 1] = Math.sin(
|
|
38897
|
+
stack[this.#sp - 1] % 360 * _DEG_TO_RAD
|
|
38898
|
+
);
|
|
38899
|
+
break;
|
|
38900
|
+
case TOKEN.cos:
|
|
38901
|
+
stack[this.#sp - 1] = Math.cos(
|
|
38902
|
+
stack[this.#sp - 1] % 360 * _DEG_TO_RAD
|
|
38903
|
+
);
|
|
38904
|
+
break;
|
|
38905
|
+
case TOKEN.ln:
|
|
38906
|
+
stack[this.#sp - 1] = Math.log(stack[this.#sp - 1]);
|
|
38907
|
+
break;
|
|
38908
|
+
case TOKEN.log:
|
|
38909
|
+
stack[this.#sp - 1] = Math.log10(stack[this.#sp - 1]);
|
|
38910
|
+
break;
|
|
38911
|
+
case TOKEN.cvi:
|
|
38912
|
+
stack[this.#sp - 1] = Math.trunc(stack[this.#sp - 1]) | 0;
|
|
38913
|
+
break;
|
|
38914
|
+
case TOKEN.cvr:
|
|
38915
|
+
break;
|
|
38916
|
+
// values are already f64
|
|
38917
|
+
case TOKEN.not: {
|
|
38918
|
+
const v = stack[this.#sp - 1];
|
|
38919
|
+
stack[this.#sp - 1] = v === 0 || v === 1 ? 1 - v : ~(v | 0);
|
|
38920
|
+
break;
|
|
38921
|
+
}
|
|
38922
|
+
case TOKEN.add: {
|
|
38923
|
+
const b = stack[--this.#sp];
|
|
38924
|
+
stack[this.#sp - 1] += b;
|
|
38925
|
+
break;
|
|
38926
|
+
}
|
|
38927
|
+
case TOKEN.sub: {
|
|
38928
|
+
const b = stack[--this.#sp];
|
|
38929
|
+
stack[this.#sp - 1] -= b;
|
|
38930
|
+
break;
|
|
38931
|
+
}
|
|
38932
|
+
case TOKEN.mul: {
|
|
38933
|
+
const b = stack[--this.#sp];
|
|
38934
|
+
stack[this.#sp - 1] *= b;
|
|
38935
|
+
break;
|
|
38936
|
+
}
|
|
38937
|
+
case TOKEN.div: {
|
|
38938
|
+
const b = stack[--this.#sp];
|
|
38939
|
+
stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] / b : 0;
|
|
38940
|
+
break;
|
|
38941
|
+
}
|
|
38942
|
+
case TOKEN.idiv: {
|
|
38943
|
+
const b = stack[--this.#sp];
|
|
38944
|
+
stack[this.#sp - 1] = b !== 0 ? Math.trunc(stack[this.#sp - 1] / b) : 0;
|
|
38945
|
+
break;
|
|
38946
|
+
}
|
|
38947
|
+
case TOKEN.mod: {
|
|
38948
|
+
const b = stack[--this.#sp];
|
|
38949
|
+
stack[this.#sp - 1] = b !== 0 ? stack[this.#sp - 1] % b : 0;
|
|
38950
|
+
break;
|
|
38951
|
+
}
|
|
38952
|
+
case TOKEN.exp: {
|
|
38953
|
+
const b = stack[--this.#sp];
|
|
38954
|
+
stack[this.#sp - 1] **= b;
|
|
38955
|
+
break;
|
|
38956
|
+
}
|
|
38957
|
+
case TOKEN.atan: {
|
|
38958
|
+
const dx = stack[--this.#sp];
|
|
38959
|
+
const deg = Math.atan2(stack[this.#sp - 1], dx) * _RAD_TO_DEG;
|
|
38960
|
+
stack[this.#sp - 1] = deg < 0 ? deg + 360 : deg;
|
|
38961
|
+
break;
|
|
38962
|
+
}
|
|
38963
|
+
case TOKEN.eq: {
|
|
38964
|
+
const b = stack[--this.#sp];
|
|
38965
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] === b ? 1 : 0;
|
|
38966
|
+
break;
|
|
38967
|
+
}
|
|
38968
|
+
case TOKEN.ne: {
|
|
38969
|
+
const b = stack[--this.#sp];
|
|
38970
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] !== b ? 1 : 0;
|
|
38971
|
+
break;
|
|
38972
|
+
}
|
|
38973
|
+
case TOKEN.gt: {
|
|
38974
|
+
const b = stack[--this.#sp];
|
|
38975
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] > b ? 1 : 0;
|
|
38976
|
+
break;
|
|
38977
|
+
}
|
|
38978
|
+
case TOKEN.ge: {
|
|
38979
|
+
const b = stack[--this.#sp];
|
|
38980
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] >= b ? 1 : 0;
|
|
38981
|
+
break;
|
|
38982
|
+
}
|
|
38983
|
+
case TOKEN.lt: {
|
|
38984
|
+
const b = stack[--this.#sp];
|
|
38985
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] < b ? 1 : 0;
|
|
38986
|
+
break;
|
|
38987
|
+
}
|
|
38988
|
+
case TOKEN.le: {
|
|
38989
|
+
const b = stack[--this.#sp];
|
|
38990
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] <= b ? 1 : 0;
|
|
38991
|
+
break;
|
|
38992
|
+
}
|
|
38993
|
+
case TOKEN.and: {
|
|
38994
|
+
const b = stack[--this.#sp] | 0;
|
|
38995
|
+
stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) & b;
|
|
38996
|
+
break;
|
|
38997
|
+
}
|
|
38998
|
+
case TOKEN.or: {
|
|
38999
|
+
const b = stack[--this.#sp] | 0;
|
|
39000
|
+
stack[this.#sp - 1] = stack[this.#sp - 1] | 0 | b;
|
|
39001
|
+
break;
|
|
39002
|
+
}
|
|
39003
|
+
case TOKEN.xor: {
|
|
39004
|
+
const b = stack[--this.#sp] | 0;
|
|
39005
|
+
stack[this.#sp - 1] = (stack[this.#sp - 1] | 0) ^ b;
|
|
39006
|
+
break;
|
|
39007
|
+
}
|
|
39008
|
+
case TOKEN.bitshift: {
|
|
39009
|
+
const amt = stack[--this.#sp] | 0;
|
|
39010
|
+
const v = stack[this.#sp - 1] | 0;
|
|
39011
|
+
stack[this.#sp - 1] = amt > 0 ? v << amt : v >> -amt;
|
|
39012
|
+
break;
|
|
39013
|
+
}
|
|
39014
|
+
case TOKEN.min: {
|
|
39015
|
+
const b = stack[--this.#sp];
|
|
39016
|
+
stack[this.#sp - 1] = Math.min(stack[this.#sp - 1], b);
|
|
39017
|
+
break;
|
|
39018
|
+
}
|
|
39019
|
+
case TOKEN.max: {
|
|
39020
|
+
const b = stack[--this.#sp];
|
|
39021
|
+
stack[this.#sp - 1] = Math.max(stack[this.#sp - 1], b);
|
|
39022
|
+
break;
|
|
39023
|
+
}
|
|
39024
|
+
case TOKEN.dup:
|
|
39025
|
+
this.#push(stack[this.#sp - 1]);
|
|
39026
|
+
break;
|
|
39027
|
+
case TOKEN.exch: {
|
|
39028
|
+
const a = stack[--this.#sp];
|
|
39029
|
+
const b = stack[--this.#sp];
|
|
39030
|
+
this.#push(a);
|
|
39031
|
+
this.#push(b);
|
|
39032
|
+
break;
|
|
39033
|
+
}
|
|
39034
|
+
case TOKEN.pop:
|
|
39035
|
+
this.#sp--;
|
|
39036
|
+
break;
|
|
39037
|
+
case TOKEN.copy: {
|
|
39038
|
+
const n = Math.trunc(stack[--this.#sp]);
|
|
39039
|
+
const base = this.#sp - n;
|
|
39040
|
+
for (let k = 0; k < n; k++) {
|
|
39041
|
+
this.#push(stack[base + k]);
|
|
39042
|
+
}
|
|
39043
|
+
break;
|
|
39044
|
+
}
|
|
39045
|
+
case TOKEN.index: {
|
|
39046
|
+
const i = Math.trunc(stack[--this.#sp]);
|
|
39047
|
+
this.#push(stack[this.#sp - 1 - i]);
|
|
39048
|
+
break;
|
|
39049
|
+
}
|
|
39050
|
+
case TOKEN.roll: {
|
|
39051
|
+
const j = Math.trunc(stack[--this.#sp]);
|
|
39052
|
+
const n = Math.trunc(stack[--this.#sp]);
|
|
39053
|
+
if (n > 1 && j !== 0) {
|
|
39054
|
+
const mod = (j % n + n) % n;
|
|
39055
|
+
if (mod !== 0) {
|
|
39056
|
+
const base = this.#sp - n;
|
|
39057
|
+
const sub = stack.slice(base, this.#sp);
|
|
39058
|
+
for (let k = 0; k < n; k++) {
|
|
39059
|
+
stack[base + k] = sub[(k - mod + n) % n];
|
|
39060
|
+
}
|
|
39061
|
+
}
|
|
39062
|
+
}
|
|
39063
|
+
break;
|
|
39064
|
+
}
|
|
39065
|
+
}
|
|
39066
|
+
}
|
|
39067
|
+
static #execBlock(instructions) {
|
|
39068
|
+
for (const instr of instructions) {
|
|
39069
|
+
switch (instr.type) {
|
|
39070
|
+
case PS_NODE.number:
|
|
39071
|
+
this.#push(instr.value);
|
|
39072
|
+
break;
|
|
39073
|
+
case PS_NODE.operator:
|
|
39074
|
+
this.#execOp(instr.op);
|
|
39075
|
+
break;
|
|
39076
|
+
case PS_NODE.if:
|
|
39077
|
+
if (this.#stack[--this.#sp] !== 0) {
|
|
39078
|
+
this.#execBlock(instr.then.instructions);
|
|
39079
|
+
}
|
|
39080
|
+
break;
|
|
39081
|
+
case PS_NODE.ifelse:
|
|
39082
|
+
if (this.#stack[--this.#sp] !== 0) {
|
|
39083
|
+
this.#execBlock(instr.then.instructions);
|
|
39084
|
+
} else {
|
|
39085
|
+
this.#execBlock(instr.otherwise.instructions);
|
|
39086
|
+
}
|
|
39087
|
+
break;
|
|
39088
|
+
}
|
|
39089
|
+
}
|
|
39090
|
+
}
|
|
39091
|
+
/**
|
|
39092
|
+
* @param {import("./ast.js").PsProgram} program
|
|
39093
|
+
* @param {number[]} domain – flat [min0,max0, …]
|
|
39094
|
+
* @param {number[]} range – flat [min0,max0, …]
|
|
39095
|
+
* @returns {Function} – `(src, srcOffset, dest, destOffset) => void`
|
|
39096
|
+
*/
|
|
39097
|
+
static build(program, domain, range) {
|
|
39098
|
+
const nIn = domain.length >> 1;
|
|
39099
|
+
const nOut = range.length >> 1;
|
|
39100
|
+
const { instructions } = program.body;
|
|
39101
|
+
return (src, srcOffset, dest, destOffset) => {
|
|
39102
|
+
this.#sp = 0;
|
|
39103
|
+
for (let i = 0; i < nIn; i++) {
|
|
39104
|
+
this.#push(src[srcOffset + i]);
|
|
39105
|
+
}
|
|
39106
|
+
this.#execBlock(instructions);
|
|
39107
|
+
const base = this.#sp - nOut;
|
|
39108
|
+
for (let i = 0; i < nOut; i++) {
|
|
39109
|
+
const v = base + i >= 0 ? this.#stack[base + i] : 0;
|
|
39110
|
+
dest[destOffset + i] = MathClamp(v, range[i * 2], range[i * 2 + 1]);
|
|
39111
|
+
}
|
|
39112
|
+
};
|
|
39113
|
+
}
|
|
39114
|
+
};
|
|
39115
|
+
ShadingType = {
|
|
39116
|
+
FUNCTION_BASED: 1,
|
|
39117
|
+
AXIAL: 2,
|
|
39118
|
+
RADIAL: 3,
|
|
39119
|
+
FREE_FORM_MESH: 4,
|
|
39120
|
+
LATTICE_FORM_MESH: 5,
|
|
39121
|
+
COONS_PATCH_MESH: 6,
|
|
39122
|
+
TENSOR_PATCH_MESH: 7
|
|
39123
|
+
};
|
|
39124
|
+
BaseShading = class _BaseShading {
|
|
39125
|
+
// A small number to offset the first/last color stops so we can insert ones
|
|
39126
|
+
// to support extend. Number.MIN_VALUE is too small and breaks the extend.
|
|
39127
|
+
static SMALL_NUMBER = 1e-6;
|
|
39128
|
+
constructor() {
|
|
39129
|
+
if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) && this.constructor === _BaseShading) {
|
|
39130
|
+
unreachable2("Cannot initialize BaseShading.");
|
|
39131
|
+
}
|
|
39132
|
+
}
|
|
39133
|
+
getIR() {
|
|
39134
|
+
unreachable2("Abstract method `getIR` called.");
|
|
39135
|
+
}
|
|
39136
|
+
};
|
|
39137
|
+
MeshStreamReader = class {
|
|
39138
|
+
constructor(stream, context) {
|
|
39139
|
+
this.stream = stream;
|
|
39140
|
+
this.context = context;
|
|
39141
|
+
this.buffer = 0;
|
|
39142
|
+
this.bufferLength = 0;
|
|
39143
|
+
const numComps = context.numComps;
|
|
39144
|
+
this.tmpCompsBuf = new Float32Array(numComps);
|
|
39145
|
+
const csNumComps = context.colorSpace.numComps;
|
|
39146
|
+
this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf;
|
|
39147
|
+
}
|
|
39148
|
+
get hasData() {
|
|
39149
|
+
if (this.stream.end) {
|
|
39150
|
+
return this.stream.pos < this.stream.end;
|
|
39151
|
+
}
|
|
39152
|
+
if (this.bufferLength > 0) {
|
|
39153
|
+
return true;
|
|
39154
|
+
}
|
|
39155
|
+
const nextByte = this.stream.getByte();
|
|
39156
|
+
if (nextByte < 0) {
|
|
39157
|
+
return false;
|
|
39158
|
+
}
|
|
39159
|
+
this.buffer = nextByte;
|
|
39160
|
+
this.bufferLength = 8;
|
|
39161
|
+
return true;
|
|
39162
|
+
}
|
|
39163
|
+
readBits(n) {
|
|
39164
|
+
const { stream } = this;
|
|
39165
|
+
let { buffer, bufferLength } = this;
|
|
39166
|
+
if (n === 32) {
|
|
39167
|
+
if (bufferLength === 0) {
|
|
39168
|
+
return stream.getInt32() >>> 0;
|
|
39169
|
+
}
|
|
39170
|
+
buffer = buffer << 24 | stream.getByte() << 16 | stream.getByte() << 8 | stream.getByte();
|
|
39171
|
+
const nextByte = stream.getByte();
|
|
39172
|
+
this.buffer = nextByte & (1 << bufferLength) - 1;
|
|
39173
|
+
return (buffer << 8 - bufferLength | (nextByte & 255) >> bufferLength) >>> 0;
|
|
39174
|
+
}
|
|
39175
|
+
if (n === 8 && bufferLength === 0) {
|
|
39176
|
+
return stream.getByte();
|
|
39177
|
+
}
|
|
39178
|
+
while (bufferLength < n) {
|
|
39179
|
+
buffer = buffer << 8 | stream.getByte();
|
|
39180
|
+
bufferLength += 8;
|
|
39181
|
+
}
|
|
39182
|
+
bufferLength -= n;
|
|
39183
|
+
this.bufferLength = bufferLength;
|
|
39184
|
+
this.buffer = buffer & (1 << bufferLength) - 1;
|
|
39185
|
+
return buffer >> bufferLength;
|
|
39186
|
+
}
|
|
39187
|
+
align() {
|
|
39188
|
+
this.buffer = 0;
|
|
39189
|
+
this.bufferLength = 0;
|
|
39190
|
+
}
|
|
39191
|
+
readFlag() {
|
|
39192
|
+
return this.readBits(this.context.bitsPerFlag);
|
|
39193
|
+
}
|
|
39194
|
+
readCoordinate() {
|
|
39195
|
+
const { bitsPerCoordinate, decode } = this.context;
|
|
39196
|
+
const xi = this.readBits(bitsPerCoordinate);
|
|
39197
|
+
const yi = this.readBits(bitsPerCoordinate);
|
|
39198
|
+
const scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 23283064365386963e-26;
|
|
39199
|
+
return [
|
|
39200
|
+
xi * scale * (decode[1] - decode[0]) + decode[0],
|
|
39201
|
+
yi * scale * (decode[3] - decode[2]) + decode[2]
|
|
39202
|
+
];
|
|
39203
|
+
}
|
|
39204
|
+
readComponents() {
|
|
39205
|
+
const { bitsPerComponent, colorFn, colorSpace, decode, numComps } = this.context;
|
|
39206
|
+
const scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 23283064365386963e-26;
|
|
39207
|
+
const components = this.tmpCompsBuf;
|
|
39208
|
+
for (let i = 0, j = 4; i < numComps; i++, j += 2) {
|
|
39209
|
+
const ci = this.readBits(bitsPerComponent);
|
|
39210
|
+
components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j];
|
|
39211
|
+
}
|
|
39212
|
+
const color = this.tmpCsCompsBuf;
|
|
39213
|
+
colorFn?.(components, 0, color, 0);
|
|
39214
|
+
return colorSpace.getRgb(color, 0);
|
|
39215
|
+
}
|
|
39216
|
+
};
|
|
39217
|
+
bCache = null;
|
|
39218
|
+
MeshShading = class _MeshShading extends BaseShading {
|
|
39219
|
+
static MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;
|
|
39220
|
+
static MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;
|
|
39221
|
+
// Count of triangles per entire mesh bounds.
|
|
39222
|
+
static TRIANGLE_DENSITY = 20;
|
|
39223
|
+
constructor(shadingType, stream, context, rowVertices) {
|
|
39224
|
+
super();
|
|
39225
|
+
this.shadingType = shadingType;
|
|
39226
|
+
this.bbox = this.background = null;
|
|
39227
|
+
this.coords = [];
|
|
39228
|
+
this.colors = [];
|
|
39229
|
+
this.figures = [];
|
|
39230
|
+
const reader = new MeshStreamReader(stream, context);
|
|
39231
|
+
let patchMesh = false;
|
|
39232
|
+
switch (this.shadingType) {
|
|
39233
|
+
case ShadingType.FREE_FORM_MESH:
|
|
39234
|
+
this._decodeType4Shading(reader);
|
|
39235
|
+
break;
|
|
39236
|
+
case ShadingType.LATTICE_FORM_MESH:
|
|
39237
|
+
const verticesPerRow = rowVertices | 0;
|
|
39238
|
+
if (verticesPerRow < 2) {
|
|
39239
|
+
throw new FormatError("Invalid VerticesPerRow");
|
|
39240
|
+
}
|
|
39241
|
+
this._decodeType5Shading(reader, verticesPerRow);
|
|
39242
|
+
break;
|
|
39243
|
+
case ShadingType.COONS_PATCH_MESH:
|
|
39244
|
+
this._decodeType6Shading(reader);
|
|
39245
|
+
patchMesh = true;
|
|
39246
|
+
break;
|
|
39247
|
+
case ShadingType.TENSOR_PATCH_MESH:
|
|
39248
|
+
this._decodeType7Shading(reader);
|
|
39249
|
+
patchMesh = true;
|
|
39250
|
+
break;
|
|
39251
|
+
default:
|
|
39252
|
+
unreachable2("Unsupported mesh type.");
|
|
39253
|
+
break;
|
|
39254
|
+
}
|
|
39255
|
+
if (patchMesh) {
|
|
39256
|
+
this._updateBounds();
|
|
39257
|
+
for (let i = 0, ii = this.figures.length; i < ii; i++) {
|
|
39258
|
+
this._buildFigureFromPatch(i);
|
|
39259
|
+
}
|
|
39260
|
+
}
|
|
39261
|
+
this._updateBounds();
|
|
39262
|
+
this._packData();
|
|
39263
|
+
}
|
|
39264
|
+
_decodeType4Shading(reader) {
|
|
39265
|
+
const coords = this.coords;
|
|
39266
|
+
const colors = this.colors;
|
|
39267
|
+
const operators = [];
|
|
39268
|
+
const ps = [];
|
|
39269
|
+
let verticesLeft = 0;
|
|
39270
|
+
while (reader.hasData) {
|
|
39271
|
+
const f = reader.readFlag();
|
|
39272
|
+
const coord = reader.readCoordinate();
|
|
39273
|
+
const color = reader.readComponents();
|
|
39274
|
+
if (verticesLeft === 0) {
|
|
39275
|
+
if (!(0 <= f && f <= 2)) {
|
|
39276
|
+
throw new FormatError("Unknown type4 flag");
|
|
39277
|
+
}
|
|
39278
|
+
switch (f) {
|
|
39279
|
+
case 0:
|
|
39280
|
+
verticesLeft = 3;
|
|
39281
|
+
break;
|
|
39282
|
+
case 1:
|
|
39283
|
+
ps.push(ps.at(-2), ps.at(-1));
|
|
39284
|
+
verticesLeft = 1;
|
|
39285
|
+
break;
|
|
39286
|
+
case 2:
|
|
39287
|
+
ps.push(ps.at(-3), ps.at(-1));
|
|
39288
|
+
verticesLeft = 1;
|
|
39289
|
+
break;
|
|
39290
|
+
}
|
|
39291
|
+
operators.push(f);
|
|
39292
|
+
}
|
|
39293
|
+
ps.push(coords.length);
|
|
39294
|
+
coords.push(coord);
|
|
39295
|
+
colors.push(color);
|
|
39296
|
+
verticesLeft--;
|
|
39297
|
+
reader.align();
|
|
39298
|
+
}
|
|
39299
|
+
this.figures.push({
|
|
39300
|
+
type: MeshFigureType.TRIANGLES,
|
|
39301
|
+
coords: new Int32Array(ps),
|
|
39302
|
+
colors: new Int32Array(ps)
|
|
39303
|
+
});
|
|
39304
|
+
}
|
|
39305
|
+
_decodeType5Shading(reader, verticesPerRow) {
|
|
39306
|
+
const coords = this.coords;
|
|
39307
|
+
const colors = this.colors;
|
|
39308
|
+
const ps = [];
|
|
39309
|
+
while (reader.hasData) {
|
|
39310
|
+
const coord = reader.readCoordinate();
|
|
39311
|
+
const color = reader.readComponents();
|
|
39312
|
+
ps.push(coords.length);
|
|
39313
|
+
coords.push(coord);
|
|
39314
|
+
colors.push(color);
|
|
39315
|
+
}
|
|
39316
|
+
this.figures.push({
|
|
39317
|
+
type: MeshFigureType.LATTICE,
|
|
39318
|
+
coords: new Int32Array(ps),
|
|
39319
|
+
colors: new Int32Array(ps),
|
|
39320
|
+
verticesPerRow
|
|
39321
|
+
});
|
|
39322
|
+
}
|
|
39323
|
+
_decodeType6Shading(reader) {
|
|
39324
|
+
const coords = this.coords;
|
|
39325
|
+
const colors = this.colors;
|
|
39326
|
+
const ps = new Int32Array(16);
|
|
39327
|
+
const cs = new Int32Array(4);
|
|
39328
|
+
while (reader.hasData) {
|
|
39329
|
+
const f = reader.readFlag();
|
|
39330
|
+
if (!(0 <= f && f <= 3)) {
|
|
39331
|
+
throw new FormatError("Unknown type6 flag");
|
|
39332
|
+
}
|
|
39333
|
+
const pi = coords.length;
|
|
39334
|
+
for (let i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) {
|
|
39335
|
+
coords.push(reader.readCoordinate());
|
|
39336
|
+
}
|
|
39337
|
+
const ci = colors.length;
|
|
39338
|
+
for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
|
|
39339
|
+
colors.push(reader.readComponents());
|
|
39340
|
+
}
|
|
39341
|
+
let tmp1, tmp2, tmp3, tmp4;
|
|
39342
|
+
switch (f) {
|
|
39343
|
+
// prettier-ignore
|
|
39344
|
+
case 0:
|
|
39345
|
+
ps[12] = pi + 3;
|
|
39346
|
+
ps[13] = pi + 4;
|
|
39347
|
+
ps[14] = pi + 5;
|
|
39348
|
+
ps[15] = pi + 6;
|
|
39349
|
+
ps[8] = pi + 2;
|
|
39350
|
+
ps[11] = pi + 7;
|
|
39351
|
+
ps[4] = pi + 1;
|
|
39352
|
+
ps[7] = pi + 8;
|
|
39353
|
+
ps[0] = pi;
|
|
39354
|
+
ps[1] = pi + 11;
|
|
39355
|
+
ps[2] = pi + 10;
|
|
39356
|
+
ps[3] = pi + 9;
|
|
39357
|
+
cs[2] = ci + 1;
|
|
39358
|
+
cs[3] = ci + 2;
|
|
39359
|
+
cs[0] = ci;
|
|
39360
|
+
cs[1] = ci + 3;
|
|
39361
|
+
break;
|
|
39362
|
+
// prettier-ignore
|
|
39363
|
+
case 1:
|
|
39364
|
+
tmp1 = ps[12];
|
|
39365
|
+
tmp2 = ps[13];
|
|
39366
|
+
tmp3 = ps[14];
|
|
39367
|
+
tmp4 = ps[15];
|
|
39368
|
+
ps[12] = tmp4;
|
|
39369
|
+
ps[13] = pi + 0;
|
|
39370
|
+
ps[14] = pi + 1;
|
|
39371
|
+
ps[15] = pi + 2;
|
|
39372
|
+
ps[8] = tmp3;
|
|
39373
|
+
ps[11] = pi + 3;
|
|
39374
|
+
ps[4] = tmp2;
|
|
39375
|
+
ps[7] = pi + 4;
|
|
39376
|
+
ps[0] = tmp1;
|
|
39377
|
+
ps[1] = pi + 7;
|
|
39378
|
+
ps[2] = pi + 6;
|
|
39379
|
+
ps[3] = pi + 5;
|
|
39380
|
+
tmp1 = cs[2];
|
|
39381
|
+
tmp2 = cs[3];
|
|
39382
|
+
cs[2] = tmp2;
|
|
39383
|
+
cs[3] = ci;
|
|
39384
|
+
cs[0] = tmp1;
|
|
39385
|
+
cs[1] = ci + 1;
|
|
39386
|
+
break;
|
|
39387
|
+
// prettier-ignore
|
|
39388
|
+
case 2:
|
|
39389
|
+
tmp1 = ps[15];
|
|
39390
|
+
tmp2 = ps[11];
|
|
39391
|
+
ps[12] = ps[3];
|
|
39392
|
+
ps[13] = pi + 0;
|
|
39393
|
+
ps[14] = pi + 1;
|
|
39394
|
+
ps[15] = pi + 2;
|
|
39395
|
+
ps[8] = ps[7];
|
|
39396
|
+
ps[11] = pi + 3;
|
|
39397
|
+
ps[4] = tmp2;
|
|
39398
|
+
ps[7] = pi + 4;
|
|
39399
|
+
ps[0] = tmp1;
|
|
39400
|
+
ps[1] = pi + 7;
|
|
39401
|
+
ps[2] = pi + 6;
|
|
39402
|
+
ps[3] = pi + 5;
|
|
39403
|
+
tmp1 = cs[3];
|
|
39404
|
+
cs[2] = cs[1];
|
|
39405
|
+
cs[3] = ci;
|
|
39406
|
+
cs[0] = tmp1;
|
|
39407
|
+
cs[1] = ci + 1;
|
|
39408
|
+
break;
|
|
39409
|
+
// prettier-ignore
|
|
39410
|
+
case 3:
|
|
39411
|
+
ps[12] = ps[0];
|
|
39412
|
+
ps[13] = pi + 0;
|
|
39413
|
+
ps[14] = pi + 1;
|
|
39414
|
+
ps[15] = pi + 2;
|
|
39415
|
+
ps[8] = ps[1];
|
|
39416
|
+
ps[11] = pi + 3;
|
|
39417
|
+
ps[4] = ps[2];
|
|
39418
|
+
ps[7] = pi + 4;
|
|
39419
|
+
ps[0] = ps[3];
|
|
39420
|
+
ps[1] = pi + 7;
|
|
39421
|
+
ps[2] = pi + 6;
|
|
39422
|
+
ps[3] = pi + 5;
|
|
39423
|
+
cs[2] = cs[0];
|
|
39424
|
+
cs[3] = ci;
|
|
39425
|
+
cs[0] = cs[1];
|
|
39426
|
+
cs[1] = ci + 1;
|
|
39427
|
+
break;
|
|
39428
|
+
}
|
|
39429
|
+
ps[5] = coords.length;
|
|
39430
|
+
coords.push([
|
|
39431
|
+
(-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,
|
|
39432
|
+
(-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
|
|
39433
|
+
]);
|
|
39434
|
+
ps[6] = coords.length;
|
|
39435
|
+
coords.push([
|
|
39436
|
+
(-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,
|
|
39437
|
+
(-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
|
|
39438
|
+
]);
|
|
39439
|
+
ps[9] = coords.length;
|
|
39440
|
+
coords.push([
|
|
39441
|
+
(-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,
|
|
39442
|
+
(-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
|
|
39443
|
+
]);
|
|
39444
|
+
ps[10] = coords.length;
|
|
39445
|
+
coords.push([
|
|
39446
|
+
(-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,
|
|
39447
|
+
(-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
|
|
39448
|
+
]);
|
|
39449
|
+
this.figures.push({
|
|
39450
|
+
type: MeshFigureType.PATCH,
|
|
39451
|
+
coords: new Int32Array(ps),
|
|
39452
|
+
// making copies of ps and cs
|
|
39453
|
+
colors: new Int32Array(cs)
|
|
39454
|
+
});
|
|
39455
|
+
}
|
|
39456
|
+
}
|
|
39457
|
+
_decodeType7Shading(reader) {
|
|
39458
|
+
const coords = this.coords;
|
|
39459
|
+
const colors = this.colors;
|
|
39460
|
+
const ps = new Int32Array(16);
|
|
39461
|
+
const cs = new Int32Array(4);
|
|
39462
|
+
while (reader.hasData) {
|
|
39463
|
+
const f = reader.readFlag();
|
|
39464
|
+
if (!(0 <= f && f <= 3)) {
|
|
39465
|
+
throw new FormatError("Unknown type7 flag");
|
|
39466
|
+
}
|
|
39467
|
+
const pi = coords.length;
|
|
39468
|
+
for (let i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) {
|
|
39469
|
+
coords.push(reader.readCoordinate());
|
|
39470
|
+
}
|
|
39471
|
+
const ci = colors.length;
|
|
39472
|
+
for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
|
|
39473
|
+
colors.push(reader.readComponents());
|
|
39474
|
+
}
|
|
39475
|
+
let tmp1, tmp2, tmp3, tmp4;
|
|
39476
|
+
switch (f) {
|
|
39477
|
+
// prettier-ignore
|
|
39478
|
+
case 0:
|
|
39479
|
+
ps[12] = pi + 3;
|
|
39480
|
+
ps[13] = pi + 4;
|
|
39481
|
+
ps[14] = pi + 5;
|
|
39482
|
+
ps[15] = pi + 6;
|
|
39483
|
+
ps[8] = pi + 2;
|
|
39484
|
+
ps[9] = pi + 13;
|
|
39485
|
+
ps[10] = pi + 14;
|
|
39486
|
+
ps[11] = pi + 7;
|
|
39487
|
+
ps[4] = pi + 1;
|
|
39488
|
+
ps[5] = pi + 12;
|
|
39489
|
+
ps[6] = pi + 15;
|
|
39490
|
+
ps[7] = pi + 8;
|
|
39491
|
+
ps[0] = pi;
|
|
39492
|
+
ps[1] = pi + 11;
|
|
39493
|
+
ps[2] = pi + 10;
|
|
39494
|
+
ps[3] = pi + 9;
|
|
39495
|
+
cs[2] = ci + 1;
|
|
39496
|
+
cs[3] = ci + 2;
|
|
39497
|
+
cs[0] = ci;
|
|
39498
|
+
cs[1] = ci + 3;
|
|
39499
|
+
break;
|
|
39500
|
+
// prettier-ignore
|
|
39501
|
+
case 1:
|
|
39502
|
+
tmp1 = ps[12];
|
|
39503
|
+
tmp2 = ps[13];
|
|
39504
|
+
tmp3 = ps[14];
|
|
39505
|
+
tmp4 = ps[15];
|
|
39506
|
+
ps[12] = tmp4;
|
|
39507
|
+
ps[13] = pi + 0;
|
|
39508
|
+
ps[14] = pi + 1;
|
|
39509
|
+
ps[15] = pi + 2;
|
|
39510
|
+
ps[8] = tmp3;
|
|
39511
|
+
ps[9] = pi + 9;
|
|
39512
|
+
ps[10] = pi + 10;
|
|
39513
|
+
ps[11] = pi + 3;
|
|
39514
|
+
ps[4] = tmp2;
|
|
39515
|
+
ps[5] = pi + 8;
|
|
39516
|
+
ps[6] = pi + 11;
|
|
39517
|
+
ps[7] = pi + 4;
|
|
39518
|
+
ps[0] = tmp1;
|
|
39519
|
+
ps[1] = pi + 7;
|
|
39520
|
+
ps[2] = pi + 6;
|
|
39521
|
+
ps[3] = pi + 5;
|
|
39522
|
+
tmp1 = cs[2];
|
|
39523
|
+
tmp2 = cs[3];
|
|
39524
|
+
cs[2] = tmp2;
|
|
39525
|
+
cs[3] = ci;
|
|
39526
|
+
cs[0] = tmp1;
|
|
39527
|
+
cs[1] = ci + 1;
|
|
39528
|
+
break;
|
|
39529
|
+
// prettier-ignore
|
|
39530
|
+
case 2:
|
|
39531
|
+
tmp1 = ps[15];
|
|
39532
|
+
tmp2 = ps[11];
|
|
39533
|
+
ps[12] = ps[3];
|
|
39534
|
+
ps[13] = pi + 0;
|
|
39535
|
+
ps[14] = pi + 1;
|
|
39536
|
+
ps[15] = pi + 2;
|
|
39537
|
+
ps[8] = ps[7];
|
|
39538
|
+
ps[9] = pi + 9;
|
|
39539
|
+
ps[10] = pi + 10;
|
|
39540
|
+
ps[11] = pi + 3;
|
|
39541
|
+
ps[4] = tmp2;
|
|
39542
|
+
ps[5] = pi + 8;
|
|
39543
|
+
ps[6] = pi + 11;
|
|
39544
|
+
ps[7] = pi + 4;
|
|
39545
|
+
ps[0] = tmp1;
|
|
39546
|
+
ps[1] = pi + 7;
|
|
39547
|
+
ps[2] = pi + 6;
|
|
39548
|
+
ps[3] = pi + 5;
|
|
39549
|
+
tmp1 = cs[3];
|
|
39550
|
+
cs[2] = cs[1];
|
|
39551
|
+
cs[3] = ci;
|
|
39552
|
+
cs[0] = tmp1;
|
|
39553
|
+
cs[1] = ci + 1;
|
|
39554
|
+
break;
|
|
39555
|
+
// prettier-ignore
|
|
39556
|
+
case 3:
|
|
39557
|
+
ps[12] = ps[0];
|
|
39558
|
+
ps[13] = pi + 0;
|
|
39559
|
+
ps[14] = pi + 1;
|
|
39560
|
+
ps[15] = pi + 2;
|
|
39561
|
+
ps[8] = ps[1];
|
|
39562
|
+
ps[9] = pi + 9;
|
|
39563
|
+
ps[10] = pi + 10;
|
|
39564
|
+
ps[11] = pi + 3;
|
|
39565
|
+
ps[4] = ps[2];
|
|
39566
|
+
ps[5] = pi + 8;
|
|
39567
|
+
ps[6] = pi + 11;
|
|
39568
|
+
ps[7] = pi + 4;
|
|
39569
|
+
ps[0] = ps[3];
|
|
39570
|
+
ps[1] = pi + 7;
|
|
39571
|
+
ps[2] = pi + 6;
|
|
39572
|
+
ps[3] = pi + 5;
|
|
39573
|
+
cs[2] = cs[0];
|
|
39574
|
+
cs[3] = ci;
|
|
39575
|
+
cs[0] = cs[1];
|
|
39576
|
+
cs[1] = ci + 1;
|
|
39577
|
+
break;
|
|
39578
|
+
}
|
|
39579
|
+
this.figures.push({
|
|
39580
|
+
type: MeshFigureType.PATCH,
|
|
39581
|
+
coords: new Int32Array(ps),
|
|
39582
|
+
// making copies of ps and cs
|
|
39583
|
+
colors: new Int32Array(cs)
|
|
39584
|
+
});
|
|
39585
|
+
}
|
|
39586
|
+
}
|
|
39587
|
+
_buildFigureFromPatch(index) {
|
|
39588
|
+
const figure = this.figures[index];
|
|
39589
|
+
assert2(
|
|
39590
|
+
figure.type === MeshFigureType.PATCH,
|
|
39591
|
+
"Unexpected patch mesh figure"
|
|
39592
|
+
);
|
|
39593
|
+
const coords = this.coords, colors = this.colors;
|
|
39594
|
+
const pi = figure.coords;
|
|
39595
|
+
const ci = figure.colors;
|
|
39596
|
+
const figureMinX = Math.min(
|
|
39597
|
+
coords[pi[0]][0],
|
|
39598
|
+
coords[pi[3]][0],
|
|
39599
|
+
coords[pi[12]][0],
|
|
39600
|
+
coords[pi[15]][0]
|
|
39601
|
+
);
|
|
39602
|
+
const figureMinY = Math.min(
|
|
39603
|
+
coords[pi[0]][1],
|
|
39604
|
+
coords[pi[3]][1],
|
|
39605
|
+
coords[pi[12]][1],
|
|
39606
|
+
coords[pi[15]][1]
|
|
39607
|
+
);
|
|
39608
|
+
const figureMaxX = Math.max(
|
|
39609
|
+
coords[pi[0]][0],
|
|
39610
|
+
coords[pi[3]][0],
|
|
39611
|
+
coords[pi[12]][0],
|
|
39612
|
+
coords[pi[15]][0]
|
|
39613
|
+
);
|
|
39614
|
+
const figureMaxY = Math.max(
|
|
39615
|
+
coords[pi[0]][1],
|
|
39616
|
+
coords[pi[3]][1],
|
|
39617
|
+
coords[pi[12]][1],
|
|
39618
|
+
coords[pi[15]][1]
|
|
39619
|
+
);
|
|
39620
|
+
let splitXBy = Math.ceil(
|
|
39621
|
+
(figureMaxX - figureMinX) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[2] - this.bounds[0])
|
|
39622
|
+
);
|
|
39623
|
+
splitXBy = MathClamp(
|
|
39624
|
+
splitXBy,
|
|
39625
|
+
_MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
|
|
39626
|
+
_MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT
|
|
39627
|
+
);
|
|
39628
|
+
let splitYBy = Math.ceil(
|
|
39629
|
+
(figureMaxY - figureMinY) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[3] - this.bounds[1])
|
|
39630
|
+
);
|
|
39631
|
+
splitYBy = MathClamp(
|
|
39632
|
+
splitYBy,
|
|
39633
|
+
_MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
|
|
39634
|
+
_MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT
|
|
39635
|
+
);
|
|
39636
|
+
const verticesPerRow = splitXBy + 1;
|
|
39637
|
+
const figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
|
|
39638
|
+
const figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
|
|
39639
|
+
let k = 0;
|
|
39640
|
+
const cl = new Uint8Array(3), cr = new Uint8Array(3);
|
|
39641
|
+
const c0 = colors[ci[0]], c1 = colors[ci[1]], c2 = colors[ci[2]], c3 = colors[ci[3]];
|
|
39642
|
+
const bRow = getB(splitYBy), bCol = getB(splitXBy);
|
|
39643
|
+
for (let row = 0; row <= splitYBy; row++) {
|
|
39644
|
+
cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0;
|
|
39645
|
+
cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0;
|
|
39646
|
+
cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0;
|
|
39647
|
+
cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0;
|
|
39648
|
+
cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0;
|
|
39649
|
+
cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0;
|
|
39650
|
+
for (let col = 0; col <= splitXBy; col++, k++) {
|
|
39651
|
+
if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) {
|
|
39652
|
+
continue;
|
|
39653
|
+
}
|
|
39654
|
+
let x = 0, y = 0;
|
|
39655
|
+
let q = 0;
|
|
39656
|
+
for (let i = 0; i <= 3; i++) {
|
|
39657
|
+
for (let j = 0; j <= 3; j++, q++) {
|
|
39658
|
+
const m = bRow[row][i] * bCol[col][j];
|
|
39659
|
+
x += coords[pi[q]][0] * m;
|
|
39660
|
+
y += coords[pi[q]][1] * m;
|
|
39661
|
+
}
|
|
39662
|
+
}
|
|
39663
|
+
figureCoords[k] = coords.length;
|
|
39664
|
+
coords.push([x, y]);
|
|
39665
|
+
figureColors[k] = colors.length;
|
|
39666
|
+
const newColor = new Uint8Array(3);
|
|
39667
|
+
newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0;
|
|
39668
|
+
newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0;
|
|
39669
|
+
newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0;
|
|
39670
|
+
colors.push(newColor);
|
|
39671
|
+
}
|
|
39672
|
+
}
|
|
39673
|
+
figureCoords[0] = pi[0];
|
|
39674
|
+
figureColors[0] = ci[0];
|
|
39675
|
+
figureCoords[splitXBy] = pi[3];
|
|
39676
|
+
figureColors[splitXBy] = ci[1];
|
|
39677
|
+
figureCoords[verticesPerRow * splitYBy] = pi[12];
|
|
39678
|
+
figureColors[verticesPerRow * splitYBy] = ci[2];
|
|
39679
|
+
figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15];
|
|
39680
|
+
figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
|
|
39681
|
+
this.figures[index] = {
|
|
39682
|
+
type: MeshFigureType.LATTICE,
|
|
39683
|
+
coords: figureCoords,
|
|
39684
|
+
colors: figureColors,
|
|
39685
|
+
verticesPerRow
|
|
39686
|
+
};
|
|
39687
|
+
}
|
|
39688
|
+
_updateBounds() {
|
|
39689
|
+
meshUpdateBounds(this);
|
|
39690
|
+
}
|
|
39691
|
+
_packData() {
|
|
39692
|
+
meshPackData(this);
|
|
39693
|
+
}
|
|
39694
|
+
getIR() {
|
|
39695
|
+
const { posData, colData, vertexCount } = buildMeshVertexData(
|
|
39696
|
+
this.coords,
|
|
39697
|
+
this.colors,
|
|
39698
|
+
this.figures
|
|
39699
|
+
);
|
|
39700
|
+
return [
|
|
39701
|
+
"Mesh",
|
|
39702
|
+
this.shadingType,
|
|
39703
|
+
posData,
|
|
39704
|
+
colData,
|
|
39705
|
+
vertexCount,
|
|
39706
|
+
this.bounds,
|
|
39707
|
+
this.bbox,
|
|
39708
|
+
this.background
|
|
39709
|
+
];
|
|
39710
|
+
}
|
|
39711
|
+
};
|
|
36797
39712
|
PdfError = class extends Error {
|
|
36798
39713
|
constructor(code, message) {
|
|
36799
39714
|
super(message);
|
|
@@ -40840,6 +43755,9 @@ var init_dist = __esm({
|
|
|
40840
43755
|
__webpack_exports__VerbosityLevel = __webpack_exports__.VerbosityLevel;
|
|
40841
43756
|
__webpack_exports__getVerbosityLevel = __webpack_exports__.getVerbosityLevel;
|
|
40842
43757
|
__webpack_exports__setVerbosityLevel = __webpack_exports__.setVerbosityLevel;
|
|
43758
|
+
cmykColorSpace = new DeviceCmykCS();
|
|
43759
|
+
cmykColorSpace2 = new DeviceCmykCS();
|
|
43760
|
+
postScriptFunctions = /* @__PURE__ */ new WeakMap();
|
|
40843
43761
|
ACROFORM_FONT_ALIAS_MAP = {
|
|
40844
43762
|
Helv: "Helvetica",
|
|
40845
43763
|
HeBo: "Helvetica-Bold",
|
|
@@ -40919,7 +43837,7 @@ var init_dist = __esm({
|
|
|
40919
43837
|
return [n0.value, n1.value, n2.value, n3.value];
|
|
40920
43838
|
}
|
|
40921
43839
|
}
|
|
40922
|
-
return [0, 0, 612, 792];
|
|
43840
|
+
return key === "MediaBox" ? [0, 0, 612, 792] : this.resolveBox("MediaBox");
|
|
40923
43841
|
}
|
|
40924
43842
|
getMediaBox() {
|
|
40925
43843
|
return this.resolveBox("MediaBox");
|
|
@@ -41592,16 +44510,19 @@ var init_dist = __esm({
|
|
|
41592
44510
|
});
|
|
41593
44511
|
}
|
|
41594
44512
|
}
|
|
41595
|
-
|
|
44513
|
+
const mediaBox = this.getMediaBox(), cropBox = this.getCropBox();
|
|
44514
|
+
const originX = Math.min(mediaBox[0], mediaBox[2]), originY = Math.min(mediaBox[1], mediaBox[3]);
|
|
44515
|
+
return { ...evaluateContentStreamToDisplayList({
|
|
41596
44516
|
pageIndex: this.index,
|
|
41597
44517
|
width,
|
|
41598
44518
|
height,
|
|
44519
|
+
origin: [originX, originY],
|
|
41599
44520
|
rotation: this.getRotation(),
|
|
41600
44521
|
nodes: baseNodes,
|
|
41601
44522
|
cosDoc: this.cosDoc,
|
|
41602
44523
|
resourcesDict: evalResourcesDict,
|
|
41603
44524
|
annotations: extractPageAnnotations(this.cosDoc, this.pageDict)
|
|
41604
|
-
});
|
|
44525
|
+
}), cropBox: [cropBox[0] - originX, cropBox[1] - originY, cropBox[2] - originX, cropBox[3] - originY] };
|
|
41605
44526
|
}
|
|
41606
44527
|
extractPage(options) {
|
|
41607
44528
|
const dl = this.evaluateDisplayList();
|
|
@@ -41619,10 +44540,10 @@ var init_dist = __esm({
|
|
|
41619
44540
|
return extractTablesFromDisplayList(this.evaluateDisplayList());
|
|
41620
44541
|
}
|
|
41621
44542
|
renderToBitmap(options) {
|
|
41622
|
-
return renderDisplayListToBitmap(this.evaluateDisplayList(), options);
|
|
44543
|
+
return renderDisplayListToBitmap(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
|
|
41623
44544
|
}
|
|
41624
44545
|
renderToPng(options) {
|
|
41625
|
-
return renderDisplayListToPng(this.evaluateDisplayList(), options);
|
|
44546
|
+
return renderDisplayListToPng(this.evaluateDisplayList({ hideAnnotations: options?.hideAnnotations }), options);
|
|
41626
44547
|
}
|
|
41627
44548
|
};
|
|
41628
44549
|
MAX_STROKE_VERTICES = 1e6;
|