emf-converter 4.0.0 → 4.2.0
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/README.md +8 -6
- package/dist/index.js +870 -166
- package/dist/index.mjs +870 -166
- package/package.json +6 -2
package/dist/index.js
CHANGED
|
@@ -24,9 +24,9 @@ function lerpArgbToRgba(argbA, argbB, t) {
|
|
|
24
24
|
return `rgba(${r},${g},${b},${a.toFixed(3)})`;
|
|
25
25
|
}
|
|
26
26
|
function invertCssColor(color) {
|
|
27
|
-
const
|
|
28
|
-
if (
|
|
29
|
-
const v = parseInt(
|
|
27
|
+
const hex5 = /^#([0-9a-f]{6})$/i.exec(color);
|
|
28
|
+
if (hex5) {
|
|
29
|
+
const v = parseInt(hex5[1], 16);
|
|
30
30
|
const inv2 = 16777215 ^ v;
|
|
31
31
|
return `#${inv2.toString(16).padStart(6, "0")}`;
|
|
32
32
|
}
|
|
@@ -386,8 +386,8 @@ function cssHexToRgb(color) {
|
|
|
386
386
|
if (!m) {
|
|
387
387
|
return 0;
|
|
388
388
|
}
|
|
389
|
-
const
|
|
390
|
-
return parseInt(
|
|
389
|
+
const hex5 = m[1].length === 3 ? m[1].replace(/./g, (c) => c + c) : m[1];
|
|
390
|
+
return parseInt(hex5, 16);
|
|
391
391
|
}
|
|
392
392
|
function decodeMonoBits(view, bmiOffset, bitsOffset) {
|
|
393
393
|
if (bmiOffset + 16 > view.byteLength) {
|
|
@@ -493,6 +493,23 @@ function totalGlyphAdvance(dx) {
|
|
|
493
493
|
}
|
|
494
494
|
return sum;
|
|
495
495
|
}
|
|
496
|
+
function applyTextJustification(advances, characters, extra, count) {
|
|
497
|
+
const result = advances.slice();
|
|
498
|
+
if (extra === 0 || count <= 0) {
|
|
499
|
+
return result;
|
|
500
|
+
}
|
|
501
|
+
let seen = 0;
|
|
502
|
+
for (let i = 0; i < result.length && i < characters.length; i++) {
|
|
503
|
+
if (characters[i] !== 32) {
|
|
504
|
+
continue;
|
|
505
|
+
}
|
|
506
|
+
const before = Math.round(seen * extra / count);
|
|
507
|
+
seen++;
|
|
508
|
+
const after = Math.round(seen * extra / count);
|
|
509
|
+
result[i] += after - before;
|
|
510
|
+
}
|
|
511
|
+
return result;
|
|
512
|
+
}
|
|
496
513
|
function alignmentStartOffset(totalWidth, align) {
|
|
497
514
|
if (align === "center") {
|
|
498
515
|
return -totalWidth / 2;
|
|
@@ -629,8 +646,11 @@ var EMR_PAINTRGN = 74;
|
|
|
629
646
|
var EMR_MASKBLT = 78;
|
|
630
647
|
var EMR_PLGBLT = 79;
|
|
631
648
|
var EMR_SETDIBITSTODEVICE = 80;
|
|
649
|
+
var EMR_EXTTEXTOUTA = 83;
|
|
632
650
|
var EMR_POLYPOLYLINE16 = 90;
|
|
633
651
|
var EMR_POLYDRAW16 = 92;
|
|
652
|
+
var EMR_POLYTEXTOUTA = 96;
|
|
653
|
+
var EMR_POLYTEXTOUTW = 97;
|
|
634
654
|
var EMR_CREATECOLORSPACE = 99;
|
|
635
655
|
var EMR_SETCOLORSPACE = 100;
|
|
636
656
|
var EMR_DELETECOLORSPACE = 101;
|
|
@@ -639,6 +659,7 @@ var EMR_GLSBOUNDEDRECORD = 103;
|
|
|
639
659
|
var EMR_PIXELFORMAT = 104;
|
|
640
660
|
var EMR_DRAWESCAPE = 105;
|
|
641
661
|
var EMR_EXTESCAPE = 106;
|
|
662
|
+
var EMR_SMALLTEXTOUT = 108;
|
|
642
663
|
var EMR_FORCEUFIMAPPING = 109;
|
|
643
664
|
var EMR_NAMEDESCAPE = 110;
|
|
644
665
|
var EMR_COLORCORRECTPALETTE = 111;
|
|
@@ -709,6 +730,7 @@ var EMFPLUS_SETRENDERINGORIGIN = 16413;
|
|
|
709
730
|
var EMFPLUS_SETTEXTCONTRAST = 16416;
|
|
710
731
|
var EMFPLUS_SETCOMPOSITINGMODE = 16419;
|
|
711
732
|
var EMFPLUS_STROKEFILLPATH = 16439;
|
|
733
|
+
var EMFPLUS_SERIALIZABLEOBJECT = 16440;
|
|
712
734
|
var EMFPLUS_SETTSGRAPHICS = 16441;
|
|
713
735
|
var EMFPLUS_SETTSCLIP = 16442;
|
|
714
736
|
var EMFPLUS_OBJECTTYPE_BRUSH = 1;
|
|
@@ -13102,7 +13124,7 @@ function parseEmfPlusPenObject(view, dataOff, recDataSize, textureCache, cacheKe
|
|
|
13102
13124
|
o += 4;
|
|
13103
13125
|
return v;
|
|
13104
13126
|
};
|
|
13105
|
-
const pen = { kind: "plus-pen", color: "rgba(0,0,0,1)", width: penWidth
|
|
13127
|
+
const pen = { kind: "plus-pen", color: "rgba(0,0,0,1)", width: penWidth, dashStyle: 0 };
|
|
13106
13128
|
if (penFlags & PEN_TRANSFORM) {
|
|
13107
13129
|
if (o + 24 <= end) {
|
|
13108
13130
|
pen.transform = [0, 4, 8, 12, 16, 20].map((k) => view.getFloat32(o + k, true));
|
|
@@ -13719,7 +13741,8 @@ function gmx(r, x) {
|
|
|
13719
13741
|
const wt = r.state.worldTransform;
|
|
13720
13742
|
const px = wt[0] * x + wt[4];
|
|
13721
13743
|
if (r.useMappingMode) {
|
|
13722
|
-
|
|
13744
|
+
const dx = (px - r.windowOrg.x) / (r.windowExt.cx || 1) * (r.viewportExt.cx || 1) + r.viewportOrg.x;
|
|
13745
|
+
return r.deviceToCanvas ? (dx - r.bounds.left) * r.sx : dx;
|
|
13723
13746
|
}
|
|
13724
13747
|
return (px - r.bounds.left) * r.sx;
|
|
13725
13748
|
}
|
|
@@ -13727,24 +13750,31 @@ function gmy(r, y) {
|
|
|
13727
13750
|
const wt = r.state.worldTransform;
|
|
13728
13751
|
const py = wt[3] * y + wt[5];
|
|
13729
13752
|
if (r.useMappingMode) {
|
|
13730
|
-
|
|
13753
|
+
const dy = (py - r.windowOrg.y) / (r.windowExt.cy || 1) * (r.viewportExt.cy || 1) + r.viewportOrg.y;
|
|
13754
|
+
return r.deviceToCanvas ? (dy - r.bounds.top) * r.sy : dy;
|
|
13731
13755
|
}
|
|
13732
13756
|
return (py - r.bounds.top) * r.sy;
|
|
13733
13757
|
}
|
|
13734
13758
|
function gmw(r, w) {
|
|
13735
13759
|
const pw = r.state.worldTransform[0] * w;
|
|
13736
13760
|
if (r.useMappingMode) {
|
|
13737
|
-
return pw / (r.windowExt.cx || 1) * (r.viewportExt.cx || 1);
|
|
13761
|
+
return pw / (r.windowExt.cx || 1) * (r.viewportExt.cx || 1) * (r.deviceToCanvas ? r.sx : 1);
|
|
13738
13762
|
}
|
|
13739
13763
|
return pw * r.sx;
|
|
13740
13764
|
}
|
|
13741
13765
|
function gmh(r, h) {
|
|
13742
13766
|
const ph = r.state.worldTransform[3] * h;
|
|
13743
13767
|
if (r.useMappingMode) {
|
|
13744
|
-
return ph / (r.windowExt.cy || 1) * (r.viewportExt.cy || 1);
|
|
13768
|
+
return ph / (r.windowExt.cy || 1) * (r.viewportExt.cy || 1) * (r.deviceToCanvas ? r.sy : 1);
|
|
13745
13769
|
}
|
|
13746
13770
|
return ph * r.sy;
|
|
13747
13771
|
}
|
|
13772
|
+
function gdiDevicePixelX(r) {
|
|
13773
|
+
return !r.useMappingMode || r.deviceToCanvas ? r.sx : 1;
|
|
13774
|
+
}
|
|
13775
|
+
function gdiDevicePixelY(r) {
|
|
13776
|
+
return !r.useMappingMode || r.deviceToCanvas ? r.sy : 1;
|
|
13777
|
+
}
|
|
13748
13778
|
function activateGdiMappingMode(r) {
|
|
13749
13779
|
r.useMappingMode = true;
|
|
13750
13780
|
}
|
|
@@ -13757,13 +13787,14 @@ function gdiDeviceMatrix(r) {
|
|
|
13757
13787
|
if (r.useMappingMode) {
|
|
13758
13788
|
const kx = (r.viewportExt.cx || 1) / (r.windowExt.cx || 1);
|
|
13759
13789
|
const ky = (r.viewportExt.cy || 1) / (r.windowExt.cy || 1);
|
|
13790
|
+
const [cx, cy, ox, oy] = r.deviceToCanvas ? [r.sx, r.sy, r.bounds.left, r.bounds.top] : [1, 1, 0, 0];
|
|
13760
13791
|
return [
|
|
13761
|
-
wt[0] * kx,
|
|
13762
|
-
wt[1] * ky,
|
|
13763
|
-
wt[2] * kx,
|
|
13764
|
-
wt[3] * ky,
|
|
13765
|
-
(wt[4] - r.windowOrg.x) * kx + r.viewportOrg.x,
|
|
13766
|
-
(wt[5] - r.windowOrg.y) * ky + r.viewportOrg.y
|
|
13792
|
+
wt[0] * kx * cx,
|
|
13793
|
+
wt[1] * ky * cy,
|
|
13794
|
+
wt[2] * kx * cx,
|
|
13795
|
+
wt[3] * ky * cy,
|
|
13796
|
+
((wt[4] - r.windowOrg.x) * kx + r.viewportOrg.x - ox) * cx,
|
|
13797
|
+
((wt[5] - r.windowOrg.y) * ky + r.viewportOrg.y - oy) * cy
|
|
13767
13798
|
];
|
|
13768
13799
|
}
|
|
13769
13800
|
const sx = r.sx || 1;
|
|
@@ -14938,19 +14969,7 @@ var SvgContext = class {
|
|
|
14938
14969
|
}
|
|
14939
14970
|
}
|
|
14940
14971
|
// ---- text ---------------------------------------------------------------
|
|
14941
|
-
measurer() {
|
|
14942
|
-
if (this.measureCtx === void 0) {
|
|
14943
|
-
const temp = createTempCanvas(1, 1);
|
|
14944
|
-
this.measureCtx = temp && !isSoftwareRaster(temp.canvas) ? temp.ctx : null;
|
|
14945
|
-
}
|
|
14946
|
-
return this.measureCtx;
|
|
14947
|
-
}
|
|
14948
14972
|
measureText(text) {
|
|
14949
|
-
const real = this.shadow ?? this.measurer();
|
|
14950
|
-
if (real) {
|
|
14951
|
-
real.font = this.state.font;
|
|
14952
|
-
return real.measureText(text);
|
|
14953
|
-
}
|
|
14954
14973
|
const size = parseFont(this.state.font).size;
|
|
14955
14974
|
return { width: estimateTextWidth(text, size) };
|
|
14956
14975
|
}
|
|
@@ -15650,8 +15669,8 @@ function paintWithRop2PerPixel(ctx, rop2, color, draw, pad = 2, fillRule) {
|
|
|
15650
15669
|
sc.restore();
|
|
15651
15670
|
}
|
|
15652
15671
|
const pointTest = fillRule !== void 0 && typeof sc.isPointInPath === "function";
|
|
15653
|
-
const
|
|
15654
|
-
const fixedP =
|
|
15672
|
+
const hex5 = /^#([0-9a-f]{6})$/i.exec(color.trim());
|
|
15673
|
+
const fixedP = hex5 ? parseInt(hex5[1], 16) : -1;
|
|
15655
15674
|
const paint = canvasGetImageData(sc, 0, 0, box.w, box.h);
|
|
15656
15675
|
const pd = paint.data;
|
|
15657
15676
|
const dd = index === 240 ? null : canvasGetImageData(ctx, box.x, box.y, box.w, box.h).data;
|
|
@@ -17950,7 +17969,7 @@ function writeTextureColor(inv2, width, height, rgba, wrap, halfPixel2, dx, dy,
|
|
|
17950
17969
|
const iv = Math.floor(cv + 1e-9);
|
|
17951
17970
|
const fu = Math.max(0, cu - iu);
|
|
17952
17971
|
const fv = Math.max(0, cv - iv);
|
|
17953
|
-
const
|
|
17972
|
+
const clamp2 = wrap === "clamp";
|
|
17954
17973
|
const mirrorX = wrap === "tile-flip-x" || wrap === "tile-flip-xy";
|
|
17955
17974
|
const mirrorY = wrap === "tile-flip-y" || wrap === "tile-flip-xy";
|
|
17956
17975
|
let r = 0;
|
|
@@ -17966,7 +17985,7 @@ function writeTextureColor(inv2, width, height, rgba, wrap, halfPixel2, dx, dy,
|
|
|
17966
17985
|
}
|
|
17967
17986
|
let x;
|
|
17968
17987
|
let y;
|
|
17969
|
-
if (
|
|
17988
|
+
if (clamp2) {
|
|
17970
17989
|
if (tu < 0 || tv < 0 || tu >= width || tv >= height) {
|
|
17971
17990
|
continue;
|
|
17972
17991
|
}
|
|
@@ -20348,8 +20367,8 @@ function paintParallelogram(rCtx, a, b, q, sw, sh, pixel) {
|
|
|
20348
20367
|
});
|
|
20349
20368
|
}
|
|
20350
20369
|
function alignMirroredDest(rCtx, req) {
|
|
20351
|
-
const pxX = rCtx
|
|
20352
|
-
const pxY = rCtx
|
|
20370
|
+
const pxX = gdiDevicePixelX(rCtx);
|
|
20371
|
+
const pxY = gdiDevicePixelY(rCtx);
|
|
20353
20372
|
return {
|
|
20354
20373
|
...req,
|
|
20355
20374
|
dx: req.dw < 0 ? req.dx + pxX : req.dx,
|
|
@@ -20584,10 +20603,10 @@ function axisMap(rCtx, xDest, yDest, cxDest, cyDest, sx, sy, sw, sh) {
|
|
|
20584
20603
|
const dw = gmw(rCtx, cxDest);
|
|
20585
20604
|
const dh = gmh(rCtx, cyDest);
|
|
20586
20605
|
if (dw < 0) {
|
|
20587
|
-
dx += rCtx
|
|
20606
|
+
dx += gdiDevicePixelX(rCtx);
|
|
20588
20607
|
}
|
|
20589
20608
|
if (dh < 0) {
|
|
20590
|
-
dy += rCtx
|
|
20609
|
+
dy += gdiDevicePixelY(rCtx);
|
|
20591
20610
|
}
|
|
20592
20611
|
const W = Math.round(Math.abs(dw));
|
|
20593
20612
|
const H = Math.round(Math.abs(dh));
|
|
@@ -20955,10 +20974,109 @@ function handleEmfGdiBlendBlitRecord(rCtx, recType, offset, dataOff, recSize) {
|
|
|
20955
20974
|
}
|
|
20956
20975
|
}
|
|
20957
20976
|
|
|
20977
|
+
// src/emf-ansi.ts
|
|
20978
|
+
var CP1252_HIGH2 = [
|
|
20979
|
+
8364,
|
|
20980
|
+
129,
|
|
20981
|
+
8218,
|
|
20982
|
+
402,
|
|
20983
|
+
8222,
|
|
20984
|
+
8230,
|
|
20985
|
+
8224,
|
|
20986
|
+
8225,
|
|
20987
|
+
710,
|
|
20988
|
+
8240,
|
|
20989
|
+
352,
|
|
20990
|
+
8249,
|
|
20991
|
+
338,
|
|
20992
|
+
141,
|
|
20993
|
+
381,
|
|
20994
|
+
143,
|
|
20995
|
+
144,
|
|
20996
|
+
8216,
|
|
20997
|
+
8217,
|
|
20998
|
+
8220,
|
|
20999
|
+
8221,
|
|
21000
|
+
8226,
|
|
21001
|
+
8211,
|
|
21002
|
+
8212,
|
|
21003
|
+
732,
|
|
21004
|
+
8482,
|
|
21005
|
+
353,
|
|
21006
|
+
8250,
|
|
21007
|
+
339,
|
|
21008
|
+
157,
|
|
21009
|
+
382,
|
|
21010
|
+
376
|
|
21011
|
+
];
|
|
21012
|
+
function ansiToCode(b, charSet) {
|
|
21013
|
+
return charSet === 2 ? b : b >= 128 && b <= 159 ? CP1252_HIGH2[b - 128] : b;
|
|
21014
|
+
}
|
|
21015
|
+
var CHARSET_ENCODING = {
|
|
21016
|
+
0: "windows-1252",
|
|
21017
|
+
1: "windows-1252",
|
|
21018
|
+
128: "shift_jis",
|
|
21019
|
+
129: "euc-kr",
|
|
21020
|
+
130: "johab",
|
|
21021
|
+
134: "gbk",
|
|
21022
|
+
136: "big5",
|
|
21023
|
+
161: "windows-1253",
|
|
21024
|
+
162: "windows-1254",
|
|
21025
|
+
163: "windows-1258",
|
|
21026
|
+
177: "windows-1255",
|
|
21027
|
+
178: "windows-1256",
|
|
21028
|
+
186: "windows-1257",
|
|
21029
|
+
204: "windows-1251",
|
|
21030
|
+
222: "windows-874",
|
|
21031
|
+
238: "windows-1250",
|
|
21032
|
+
255: "ibm437"
|
|
21033
|
+
};
|
|
21034
|
+
function decodeAnsiRecord(bytes, charSet) {
|
|
21035
|
+
if (charSet === 2) {
|
|
21036
|
+
return { codes: [...bytes], byteLengths: bytes.map(() => 1) };
|
|
21037
|
+
}
|
|
21038
|
+
const label = CHARSET_ENCODING[charSet] ?? "windows-1252";
|
|
21039
|
+
try {
|
|
21040
|
+
const decoder = new TextDecoder(label, { fatal: true });
|
|
21041
|
+
const replacementDecoder = new TextDecoder(label);
|
|
21042
|
+
const source = new Uint8Array(bytes);
|
|
21043
|
+
const codes = [];
|
|
21044
|
+
const byteLengths = [];
|
|
21045
|
+
let i = 0;
|
|
21046
|
+
while (i < bytes.length) {
|
|
21047
|
+
let decoded = null;
|
|
21048
|
+
let consumed = 1;
|
|
21049
|
+
for (let n = 1; n <= Math.min(4, bytes.length - i); n++) {
|
|
21050
|
+
try {
|
|
21051
|
+
const candidate = decoder.decode(source.subarray(i, i + n));
|
|
21052
|
+
if (candidate.length > 0) {
|
|
21053
|
+
decoded = candidate;
|
|
21054
|
+
consumed = n;
|
|
21055
|
+
break;
|
|
21056
|
+
}
|
|
21057
|
+
} catch {
|
|
21058
|
+
}
|
|
21059
|
+
}
|
|
21060
|
+
if (decoded === null) {
|
|
21061
|
+
decoded = replacementDecoder.decode(source.subarray(i, i + 1));
|
|
21062
|
+
}
|
|
21063
|
+
for (let j = 0; j < decoded.length; j++) {
|
|
21064
|
+
codes.push(decoded.charCodeAt(j));
|
|
21065
|
+
byteLengths.push(j === decoded.length - 1 ? consumed : 0);
|
|
21066
|
+
}
|
|
21067
|
+
i += consumed;
|
|
21068
|
+
}
|
|
21069
|
+
return { codes, byteLengths };
|
|
21070
|
+
} catch {
|
|
21071
|
+
return { codes: bytes.map((b) => ansiToCode(b, charSet)), byteLengths: bytes.map(() => 1) };
|
|
21072
|
+
}
|
|
21073
|
+
}
|
|
21074
|
+
|
|
20958
21075
|
// src/gdi-text-render.ts
|
|
20959
21076
|
var ETO_OPAQUE = 2;
|
|
20960
21077
|
var ETO_CLIPPED = 4;
|
|
20961
21078
|
var ETO_GLYPH_INDEX = 16;
|
|
21079
|
+
var ETO_IGNORELANGUAGE = 4096;
|
|
20962
21080
|
var ETO_PDY = 8192;
|
|
20963
21081
|
var GRAY_INV_GAMMA = 0.43;
|
|
20964
21082
|
var GRAY_BLACK_ON_WHITE = [255, 255, 240, 233, 225, 217, 208, 199, 189, 178, 167, 154, 140, 124, 104, 77, 0];
|
|
@@ -21039,15 +21157,24 @@ function fillDeviceQuad(ctx, pts, color, clip) {
|
|
|
21039
21157
|
ctx.fill();
|
|
21040
21158
|
ctx.restore();
|
|
21041
21159
|
}
|
|
21160
|
+
function isC1Control(code) {
|
|
21161
|
+
return code >= 128 && code <= 159;
|
|
21162
|
+
}
|
|
21163
|
+
function suppressC1Glyph(run, index) {
|
|
21164
|
+
return !run.glyphIndices && !(run.options & ETO_IGNORELANGUAGE) && isC1Control(run.codes[index]);
|
|
21165
|
+
}
|
|
21042
21166
|
function layoutGdiRun(font, run) {
|
|
21043
21167
|
const n = run.codes.length;
|
|
21044
21168
|
const glyphs = run.codes.map((c) => run.glyphIndices ? c : font.glyphIndex(c));
|
|
21045
|
-
|
|
21169
|
+
let adv = [];
|
|
21046
21170
|
for (let i = 0; i < n; i++) {
|
|
21047
21171
|
adv.push(
|
|
21048
|
-
run.dx && i < run.dx.length ? run.dx[i] : run.matrix ? font.rotatedAdvance(glyphs[i]) : font.advance(glyphs[i])
|
|
21172
|
+
suppressC1Glyph(run, i) && !run.dx ? 0 : run.dx && i < run.dx.length ? run.dx[i] : run.matrix ? font.rotatedAdvance(glyphs[i]) : font.advance(glyphs[i])
|
|
21049
21173
|
);
|
|
21050
21174
|
}
|
|
21175
|
+
if (!run.dx && run.textJustification && !run.glyphIndices) {
|
|
21176
|
+
adv = applyTextJustification(adv, run.codes, run.textJustification.extra, run.textJustification.count);
|
|
21177
|
+
}
|
|
21051
21178
|
const advY = [];
|
|
21052
21179
|
for (let i = 0; i < n; i++) {
|
|
21053
21180
|
advY.push(run.dy && i < run.dy.length ? run.dy[i] : 0);
|
|
@@ -21090,9 +21217,11 @@ function layoutGdiRun(font, run) {
|
|
|
21090
21217
|
const subX = font.gridFit ? 0 : Math.round((origin.x - ox) * 64);
|
|
21091
21218
|
const oy = Math.round(origin.y);
|
|
21092
21219
|
origins.push({ x: ox + subX / 64, y: oy, along, down });
|
|
21093
|
-
|
|
21094
|
-
|
|
21095
|
-
|
|
21220
|
+
if (!suppressC1Glyph(run, i)) {
|
|
21221
|
+
const g = font.glyph(glyphs[i], gm, subX);
|
|
21222
|
+
if (g.bitmap) {
|
|
21223
|
+
placed.push({ x: ox + g.bitmap.left, y: oy - g.bitmap.top, bitmap: g.bitmap });
|
|
21224
|
+
}
|
|
21096
21225
|
}
|
|
21097
21226
|
along += adv[i];
|
|
21098
21227
|
down += advY[i];
|
|
@@ -21177,21 +21306,25 @@ function paintGdiTextRun(ctx, font, run, fontFamilyMap) {
|
|
|
21177
21306
|
}
|
|
21178
21307
|
function emitSvgRun(ctx, font, run, glyphs, origins, fontFamilyMap) {
|
|
21179
21308
|
let text = "";
|
|
21309
|
+
const visibleOrigins = [];
|
|
21180
21310
|
for (let i = 0; i < origins.length; i++) {
|
|
21181
21311
|
const code = run.glyphIndices ? font.charForGlyph(glyphs[i]) : run.codes[i];
|
|
21312
|
+
if (!run.glyphIndices && !(run.options & ETO_IGNORELANGUAGE) && isC1Control(code)) continue;
|
|
21182
21313
|
text += String.fromCharCode(code);
|
|
21314
|
+
visibleOrigins.push(origins[i]);
|
|
21183
21315
|
}
|
|
21316
|
+
if (text.length === 0) return;
|
|
21184
21317
|
const m = run.matrix;
|
|
21185
21318
|
const ttf = font.ttf;
|
|
21186
21319
|
const bold = font.syntheticBold || ttf.weightClass >= 600;
|
|
21187
21320
|
const italic = font.syntheticItalic || (ttf.fsSelection & 1) !== 0 || (ttf.macStyle & 2) !== 0;
|
|
21188
|
-
const first =
|
|
21321
|
+
const first = visibleOrigins[0];
|
|
21189
21322
|
ctx.fillGlyphRun({
|
|
21190
21323
|
text,
|
|
21191
21324
|
// Upright runs: device positions. Rotated runs: offsets along/across
|
|
21192
21325
|
// the baseline from the first glyph, under the frame matrix.
|
|
21193
|
-
xs:
|
|
21194
|
-
ys:
|
|
21326
|
+
xs: visibleOrigins.map((o) => m ? o.along - first.along : o.x),
|
|
21327
|
+
ys: visibleOrigins.map((o) => m ? o.down - first.down : o.y),
|
|
21195
21328
|
matrix: m ? [m[0], m[1], m[2], m[3], first.x, first.y] : null,
|
|
21196
21329
|
scaleX: font.ppemX !== font.ppem ? font.ppemX / font.ppem : 1,
|
|
21197
21330
|
fontFamily: mapFontFamily(ttf.family, fontFamilyMap),
|
|
@@ -21362,6 +21495,7 @@ function drawGdiTextCall(ctx, fonts, state, call) {
|
|
|
21362
21495
|
y: ref.y,
|
|
21363
21496
|
dx: call.dx ? call.dx.map((v) => v * advanceScale) : null,
|
|
21364
21497
|
dy: call.dy ? call.dy.map((v) => -v * fontScale) : null,
|
|
21498
|
+
textJustification: call.textJustification ? { ...call.textJustification, extra: call.textJustification.extra * advanceScale } : void 0,
|
|
21365
21499
|
textAlign: state.textAlign,
|
|
21366
21500
|
textColor: state.textColor,
|
|
21367
21501
|
bkColor: state.bkColor,
|
|
@@ -21498,11 +21632,11 @@ function readDxArray(view, offset, dataOff, nChars, viewEnd) {
|
|
|
21498
21632
|
}
|
|
21499
21633
|
const dx = [];
|
|
21500
21634
|
for (let i = 0; i < nChars; i++) {
|
|
21501
|
-
dx.push(view.
|
|
21635
|
+
dx.push(view.getInt32(start + i * 4, true));
|
|
21502
21636
|
}
|
|
21503
21637
|
return dx;
|
|
21504
21638
|
}
|
|
21505
|
-
function drawWithFontEngine(rCtx, offset, dataOff, nChars, offString) {
|
|
21639
|
+
function drawWithFontEngine(rCtx, offset, dataOff, nChars, offString, viewEnd) {
|
|
21506
21640
|
const { ctx, view, state } = rCtx;
|
|
21507
21641
|
const fonts = rCtx.fonts;
|
|
21508
21642
|
if (!fonts) {
|
|
@@ -21514,7 +21648,7 @@ function drawWithFontEngine(rCtx, offset, dataOff, nChars, offString) {
|
|
|
21514
21648
|
codes.push(view.getUint16(offset + offString + i * 2, true));
|
|
21515
21649
|
}
|
|
21516
21650
|
const pdy = (options & ETO_PDY) !== 0;
|
|
21517
|
-
const raw = readDxArray(view, offset, dataOff, pdy ? nChars * 2 : nChars,
|
|
21651
|
+
const raw = readDxArray(view, offset, dataOff, pdy ? nChars * 2 : nChars, viewEnd);
|
|
21518
21652
|
let dx = raw;
|
|
21519
21653
|
let dy = null;
|
|
21520
21654
|
if (raw && pdy) {
|
|
@@ -21539,7 +21673,8 @@ function drawWithFontEngine(rCtx, offset, dataOff, nChars, offString) {
|
|
|
21539
21673
|
},
|
|
21540
21674
|
dx,
|
|
21541
21675
|
dy,
|
|
21542
|
-
matrix: gdiDeviceMatrix(rCtx)
|
|
21676
|
+
matrix: gdiDeviceMatrix(rCtx),
|
|
21677
|
+
textJustification: state.textJustification
|
|
21543
21678
|
});
|
|
21544
21679
|
if (!adv) {
|
|
21545
21680
|
return false;
|
|
@@ -21551,12 +21686,12 @@ function drawWithFontEngine(rCtx, offset, dataOff, nChars, offString) {
|
|
|
21551
21686
|
return true;
|
|
21552
21687
|
}
|
|
21553
21688
|
function horizontalAlign(textAlign) {
|
|
21689
|
+
if ((textAlign & 6) === 6) {
|
|
21690
|
+
return "center";
|
|
21691
|
+
}
|
|
21554
21692
|
if (textAlign & 2) {
|
|
21555
21693
|
return "right";
|
|
21556
21694
|
}
|
|
21557
|
-
if (textAlign & 6) {
|
|
21558
|
-
return "center";
|
|
21559
|
-
}
|
|
21560
21695
|
return "left";
|
|
21561
21696
|
}
|
|
21562
21697
|
function verticalBaseline(textAlign) {
|
|
@@ -21598,11 +21733,11 @@ function handleExtTextOutW(rCtx, offset, dataOff, recSize) {
|
|
|
21598
21733
|
const refY = view.getInt32(dataOff + 32, true);
|
|
21599
21734
|
const nChars = view.getUint32(dataOff + 36, true);
|
|
21600
21735
|
const offString = view.getUint32(dataOff + 40, true);
|
|
21601
|
-
const viewEnd = view.byteLength;
|
|
21602
|
-
if (nChars === 0 || offString === 0 ||
|
|
21736
|
+
const viewEnd = Math.min(view.byteLength, offset + recSize);
|
|
21737
|
+
if (nChars === 0 || offString === 0 || nChars > Math.floor((viewEnd - offset - offString) / 2)) {
|
|
21603
21738
|
return true;
|
|
21604
21739
|
}
|
|
21605
|
-
if (drawWithFontEngine(rCtx, offset, dataOff, nChars, offString)) {
|
|
21740
|
+
if (drawWithFontEngine(rCtx, offset, dataOff, nChars, offString, viewEnd)) {
|
|
21606
21741
|
return true;
|
|
21607
21742
|
}
|
|
21608
21743
|
const text = readUtf16LE(view, offset + offString, nChars);
|
|
@@ -21617,8 +21752,16 @@ function handleExtTextOutW(rCtx, offset, dataOff, recSize) {
|
|
|
21617
21752
|
const align = horizontalAlign(state.textAlign);
|
|
21618
21753
|
ctx.textBaseline = verticalBaseline(state.textAlign);
|
|
21619
21754
|
ctx.textAlign = align === "center" ? "center" : align === "right" ? "right" : "left";
|
|
21620
|
-
const
|
|
21621
|
-
const
|
|
21755
|
+
const pdy = (view.getUint32(dataOff + 44, true) & ETO_PDY) !== 0;
|
|
21756
|
+
const dxRaw = readDxArray(view, offset, dataOff, pdy ? nChars * 2 : nChars, viewEnd);
|
|
21757
|
+
const dxLogical = dxRaw && pdy ? dxRaw.filter((_, i) => i % 2 === 0) : dxRaw;
|
|
21758
|
+
let dxDevice = dxLogical ? dxLogical.map((v) => advanceScale !== null ? v * advanceScale : gmw(rCtx, v)) : null;
|
|
21759
|
+
if (!dxDevice && state.textJustification && !pdy) {
|
|
21760
|
+
const units = text.split("");
|
|
21761
|
+
const natural = units.map((ch) => ctx.measureText(ch).width);
|
|
21762
|
+
const scale = advanceScale ?? gmw(rCtx, 1);
|
|
21763
|
+
dxDevice = applyTextJustification(natural, units.map((ch) => ch.charCodeAt(0)), state.textJustification.extra * scale, state.textJustification.count);
|
|
21764
|
+
}
|
|
21622
21765
|
if (dxDevice) {
|
|
21623
21766
|
ctx.textAlign = "left";
|
|
21624
21767
|
}
|
|
@@ -21651,10 +21794,118 @@ function handleExtTextOutW(rCtx, offset, dataOff, recSize) {
|
|
|
21651
21794
|
}
|
|
21652
21795
|
return true;
|
|
21653
21796
|
}
|
|
21797
|
+
function drawTextCall(rCtx, x, y, codes, options, rect, dx) {
|
|
21798
|
+
const n = codes.length;
|
|
21799
|
+
const offString = 76;
|
|
21800
|
+
const offDx = offString + n * 2 + 3 & -4;
|
|
21801
|
+
const dxCount = dx ? dx.length : 0;
|
|
21802
|
+
const size = offDx + dxCount * 4;
|
|
21803
|
+
const view = new DataView(new ArrayBuffer(size));
|
|
21804
|
+
view.setUint32(44, n, true);
|
|
21805
|
+
view.setUint32(48, offString, true);
|
|
21806
|
+
view.setUint32(52, options, true);
|
|
21807
|
+
view.setInt32(36, x, true);
|
|
21808
|
+
view.setInt32(40, y, true);
|
|
21809
|
+
view.setInt32(56, rect[0], true);
|
|
21810
|
+
view.setInt32(60, rect[1], true);
|
|
21811
|
+
view.setInt32(64, rect[2], true);
|
|
21812
|
+
view.setInt32(68, rect[3], true);
|
|
21813
|
+
view.setUint32(72, dx ? offDx : 0, true);
|
|
21814
|
+
for (let i = 0; i < n; i++) view.setUint16(offString + i * 2, codes[i], true);
|
|
21815
|
+
if (dx) for (let i = 0; i < dxCount; i++) view.setInt32(offDx + i * 4, dx[i], true);
|
|
21816
|
+
const child = { ...rCtx, view };
|
|
21817
|
+
handleExtTextOutW(child, 0, 8, size);
|
|
21818
|
+
}
|
|
21819
|
+
function readAnsiRecord(view, start, count, charSet) {
|
|
21820
|
+
return decodeAnsiRecord(Array.from({ length: count }, (_, i) => view.getUint8(start + i)), charSet);
|
|
21821
|
+
}
|
|
21822
|
+
function collapseAnsiDx(dx, byteLengths, pdy) {
|
|
21823
|
+
if (!dx) return null;
|
|
21824
|
+
const result = [];
|
|
21825
|
+
let at = 0;
|
|
21826
|
+
for (const bytes of byteLengths) {
|
|
21827
|
+
let x = 0, y = 0;
|
|
21828
|
+
for (let i = 0; i < bytes; i++) {
|
|
21829
|
+
x += dx[at + i * (pdy ? 2 : 1)] ?? 0;
|
|
21830
|
+
if (pdy) y += dx[at + i * 2 + 1] ?? 0;
|
|
21831
|
+
}
|
|
21832
|
+
result.push(x);
|
|
21833
|
+
if (pdy) result.push(y);
|
|
21834
|
+
at += bytes * (pdy ? 2 : 1);
|
|
21835
|
+
}
|
|
21836
|
+
return result;
|
|
21837
|
+
}
|
|
21838
|
+
function handlePolyText(rCtx, offset, dataOff, recSize, wide) {
|
|
21839
|
+
const { view, state } = rCtx;
|
|
21840
|
+
const end = Math.min(view.byteLength, offset + recSize);
|
|
21841
|
+
if (recSize < 40) return true;
|
|
21842
|
+
const count = view.getUint32(dataOff + 28, true);
|
|
21843
|
+
const arrayStart = dataOff + 32;
|
|
21844
|
+
if (count > Math.floor((end - arrayStart) / 40)) return true;
|
|
21845
|
+
const charSet = state.fontDetails?.charSet ?? 1;
|
|
21846
|
+
for (let i = 0; i < count; i++) {
|
|
21847
|
+
const e = arrayStart + i * 40;
|
|
21848
|
+
const x = view.getInt32(e, true), y = view.getInt32(e + 4, true);
|
|
21849
|
+
const n = view.getUint32(e + 8, true), offString = view.getUint32(e + 12, true);
|
|
21850
|
+
const options = view.getUint32(e + 16, true);
|
|
21851
|
+
const rect = [view.getInt32(e + 20, true), view.getInt32(e + 24, true), view.getInt32(e + 28, true), view.getInt32(e + 32, true)];
|
|
21852
|
+
const offDx = view.getUint32(e + 36, true);
|
|
21853
|
+
const unit = wide ? 2 : 1;
|
|
21854
|
+
if (!offString || offString > end - offset || n > Math.floor((end - (offset + offString)) / unit)) continue;
|
|
21855
|
+
const ansi = wide ? null : readAnsiRecord(view, offset + offString, n, charSet);
|
|
21856
|
+
const codes = wide ? Array.from({ length: n }, (_, j) => view.getUint16(offset + offString + j * 2, true)) : ansi.codes;
|
|
21857
|
+
let dx = null;
|
|
21858
|
+
const pdy = (options & ETO_PDY) !== 0;
|
|
21859
|
+
const dxCount = n * (pdy ? 2 : 1);
|
|
21860
|
+
if (offDx && offDx <= end - offset && dxCount <= Math.floor((end - (offset + offDx)) / 4)) {
|
|
21861
|
+
dx = Array.from({ length: dxCount }, (_, j) => view.getInt32(offset + offDx + j * 4, true));
|
|
21862
|
+
if (!wide) dx = collapseAnsiDx(dx, ansi.byteLengths, pdy);
|
|
21863
|
+
}
|
|
21864
|
+
drawTextCall(rCtx, x, y, codes, options, rect, dx);
|
|
21865
|
+
}
|
|
21866
|
+
return true;
|
|
21867
|
+
}
|
|
21868
|
+
function handleSmallTextOut(rCtx, offset, dataOff, recSize) {
|
|
21869
|
+
const { view } = rCtx;
|
|
21870
|
+
const end = Math.min(view.byteLength, offset + recSize);
|
|
21871
|
+
if (recSize < 36) return true;
|
|
21872
|
+
const x = view.getInt32(dataOff, true), y = view.getInt32(dataOff + 4, true);
|
|
21873
|
+
const n = view.getUint32(dataOff + 8, true), options = view.getUint32(dataOff + 12, true);
|
|
21874
|
+
const small = (options & 512) !== 0, noRect = (options & 256) !== 0;
|
|
21875
|
+
const base = dataOff + 28 + (noRect ? 0 : 16);
|
|
21876
|
+
if (base > end || n > Math.floor((end - base) / (small ? 1 : 2))) return true;
|
|
21877
|
+
const rect = noRect ? [0, 0, 0, 0] : [view.getInt32(dataOff + 28, true), view.getInt32(dataOff + 32, true), view.getInt32(dataOff + 36, true), view.getInt32(dataOff + 40, true)];
|
|
21878
|
+
const codes = small ? Array.from({ length: n }, (_, i) => view.getUint8(base + i)) : Array.from({ length: n }, (_, i) => view.getUint16(base + i * 2, true));
|
|
21879
|
+
drawTextCall(rCtx, x, y, codes, options, rect, null);
|
|
21880
|
+
return true;
|
|
21881
|
+
}
|
|
21654
21882
|
function handleEmfGdiDrawTextRecord(rCtx, recType, offset, dataOff, recSize) {
|
|
21655
21883
|
if (recType === EMR_EXTTEXTOUTW) {
|
|
21656
21884
|
return handleExtTextOutW(rCtx, offset, dataOff, recSize);
|
|
21657
21885
|
}
|
|
21886
|
+
if (recType === EMR_EXTTEXTOUTA || recType === EMR_POLYTEXTOUTA || recType === EMR_POLYTEXTOUTW || recType === EMR_SMALLTEXTOUT) {
|
|
21887
|
+
if (recType === EMR_POLYTEXTOUTA || recType === EMR_POLYTEXTOUTW) return handlePolyText(rCtx, offset, dataOff, recSize, recType === EMR_POLYTEXTOUTW);
|
|
21888
|
+
if (recType === EMR_SMALLTEXTOUT) return handleSmallTextOut(rCtx, offset, dataOff, recSize);
|
|
21889
|
+
const { view, state } = rCtx;
|
|
21890
|
+
const end = Math.min(view.byteLength, offset + recSize);
|
|
21891
|
+
if (recSize < 76) return true;
|
|
21892
|
+
const x = view.getInt32(dataOff + 28, true), y = view.getInt32(dataOff + 32, true);
|
|
21893
|
+
const n = view.getUint32(dataOff + 36, true), strOff = view.getUint32(dataOff + 40, true), options = view.getUint32(dataOff + 44, true);
|
|
21894
|
+
if (!strOff || strOff > end - offset) return true;
|
|
21895
|
+
if (n > end - (offset + strOff)) return true;
|
|
21896
|
+
const ansi = readAnsiRecord(view, offset + strOff, n, state.fontDetails?.charSet ?? 1);
|
|
21897
|
+
const rect = [view.getInt32(dataOff + 48, true), view.getInt32(dataOff + 52, true), view.getInt32(dataOff + 56, true), view.getInt32(dataOff + 60, true)];
|
|
21898
|
+
const offDx = view.getUint32(dataOff + 64, true);
|
|
21899
|
+
let dx = null;
|
|
21900
|
+
const pdy = (options & ETO_PDY) !== 0;
|
|
21901
|
+
const dxCount = n * (pdy ? 2 : 1);
|
|
21902
|
+
if (offDx && offDx <= end - offset && dxCount <= Math.floor((end - (offset + offDx)) / 4)) {
|
|
21903
|
+
dx = Array.from({ length: dxCount }, (_, i) => view.getInt32(offset + offDx + i * 4, true));
|
|
21904
|
+
dx = collapseAnsiDx(dx, ansi.byteLengths, pdy);
|
|
21905
|
+
}
|
|
21906
|
+
drawTextCall(rCtx, x, y, ansi.codes, options, rect, dx);
|
|
21907
|
+
return true;
|
|
21908
|
+
}
|
|
21658
21909
|
return false;
|
|
21659
21910
|
}
|
|
21660
21911
|
|
|
@@ -23284,6 +23535,412 @@ function handleEmfGdiStateRecord(rCtx, recType, _offset, dataOff, recSize) {
|
|
|
23284
23535
|
}
|
|
23285
23536
|
}
|
|
23286
23537
|
|
|
23538
|
+
// src/emf-plus-image-effects.ts
|
|
23539
|
+
var EFFECT_GUIDS = {
|
|
23540
|
+
"633C80A4-1843-482B-9EF2-BE2834C5FDD4": "blur",
|
|
23541
|
+
"D3A1DBE1-8EC4-4C17-9F4C-EA97AD1C343D": "brightnessContrast",
|
|
23542
|
+
"537E597D-251E-48DA-9664-29CA496B70F8": "colorBalance",
|
|
23543
|
+
"DD6A0022-58E4-4A67-9D9B-D48EB881A53D": "colorCurve",
|
|
23544
|
+
"A7CE72A9-0F7F-40D7-B3CC-D0C02D5C3212": "colorLookupTable",
|
|
23545
|
+
"718F2615-7933-40E3-A511-5F68FE14DD74": "colorMatrix",
|
|
23546
|
+
"8B2DD6C3-EB07-4D87-A5F0-7108E26A9C5F": "hueSaturationLightness",
|
|
23547
|
+
"99C354EC-2A31-4F3A-8C34-17A803B33A25": "levels",
|
|
23548
|
+
"74D29D05-69A4-4266-9549-3CC52836B632": "redEyeCorrection",
|
|
23549
|
+
"63CBF3EE-C526-402C-8F71-62C540BF5142": "sharpen",
|
|
23550
|
+
"1077AF00-2848-4441-9489-44AD4C2D7A2C": "tint"
|
|
23551
|
+
};
|
|
23552
|
+
var DRAWIMAGE_EFFECT_FLAG = 8192;
|
|
23553
|
+
var CurveAdjustment = {
|
|
23554
|
+
Exposure: 0,
|
|
23555
|
+
Density: 1,
|
|
23556
|
+
Contrast: 2,
|
|
23557
|
+
Highlight: 3,
|
|
23558
|
+
Shadow: 4,
|
|
23559
|
+
Midtone: 5,
|
|
23560
|
+
WhiteSaturation: 6,
|
|
23561
|
+
BlackSaturation: 7
|
|
23562
|
+
};
|
|
23563
|
+
var CurveChannel = { All: 0, Red: 1, Green: 2, Blue: 3 };
|
|
23564
|
+
var hex4 = (v, digits) => v.toString(16).toUpperCase().padStart(digits, "0");
|
|
23565
|
+
function readGuid(view, off) {
|
|
23566
|
+
const tail = [];
|
|
23567
|
+
for (let i = 0; i < 8; i++) {
|
|
23568
|
+
tail.push(hex4(view.getUint8(off + 8 + i), 2));
|
|
23569
|
+
}
|
|
23570
|
+
return [
|
|
23571
|
+
hex4(view.getUint32(off, true), 8),
|
|
23572
|
+
hex4(view.getUint16(off + 4, true), 4),
|
|
23573
|
+
hex4(view.getUint16(off + 6, true), 4),
|
|
23574
|
+
tail.slice(0, 2).join(""),
|
|
23575
|
+
tail.slice(2).join("")
|
|
23576
|
+
].join("-");
|
|
23577
|
+
}
|
|
23578
|
+
var clamp = (v, lo, hi) => v < lo ? lo : v > hi ? hi : v;
|
|
23579
|
+
function parseSerializableObject(view, dataOff, dataSize) {
|
|
23580
|
+
if (dataSize < 20) {
|
|
23581
|
+
return null;
|
|
23582
|
+
}
|
|
23583
|
+
const kind = EFFECT_GUIDS[readGuid(view, dataOff)];
|
|
23584
|
+
const size = view.getUint32(dataOff + 16, true);
|
|
23585
|
+
if (!kind || 20 + size > dataSize) {
|
|
23586
|
+
return null;
|
|
23587
|
+
}
|
|
23588
|
+
const p = dataOff + 20;
|
|
23589
|
+
const i32 = (k, lo, hi) => clamp(view.getInt32(p + 4 * k, true), lo, hi);
|
|
23590
|
+
const f323 = (k, lo, hi) => {
|
|
23591
|
+
const v = view.getFloat32(p + 4 * k, true);
|
|
23592
|
+
return Number.isFinite(v) ? clamp(v, lo, hi) : 0;
|
|
23593
|
+
};
|
|
23594
|
+
const need = (n) => size >= n;
|
|
23595
|
+
switch (kind) {
|
|
23596
|
+
case "blur":
|
|
23597
|
+
return need(8) ? { kind, radius: f323(0, 0, 255), expandEdge: view.getUint32(p + 4, true) !== 0 } : null;
|
|
23598
|
+
case "brightnessContrast":
|
|
23599
|
+
return need(8) ? { kind, brightness: i32(0, -255, 255), contrast: i32(1, -100, 100) } : null;
|
|
23600
|
+
case "colorBalance":
|
|
23601
|
+
return need(12) ? { kind, cyanRed: i32(0, -100, 100), magentaGreen: i32(1, -100, 100), yellowBlue: i32(2, -100, 100) } : null;
|
|
23602
|
+
case "colorCurve":
|
|
23603
|
+
return need(12) ? {
|
|
23604
|
+
kind,
|
|
23605
|
+
adjustment: view.getInt32(p, true),
|
|
23606
|
+
channel: view.getInt32(p + 4, true),
|
|
23607
|
+
intensity: i32(2, -255, 255)
|
|
23608
|
+
} : null;
|
|
23609
|
+
case "colorLookupTable": {
|
|
23610
|
+
if (!need(1024)) {
|
|
23611
|
+
return null;
|
|
23612
|
+
}
|
|
23613
|
+
const lut = (k) => new Uint8Array(view.buffer.slice(view.byteOffset + p + 256 * k, view.byteOffset + p + 256 * (k + 1)));
|
|
23614
|
+
return { kind, b: lut(0), g: lut(1), r: lut(2), a: lut(3) };
|
|
23615
|
+
}
|
|
23616
|
+
case "colorMatrix": {
|
|
23617
|
+
if (!need(100)) {
|
|
23618
|
+
return null;
|
|
23619
|
+
}
|
|
23620
|
+
const matrix = [];
|
|
23621
|
+
for (let k = 0; k < 25; k++) {
|
|
23622
|
+
const v = view.getFloat32(p + 4 * k, true);
|
|
23623
|
+
matrix.push(Number.isFinite(v) ? v : 0);
|
|
23624
|
+
}
|
|
23625
|
+
return { kind, matrix };
|
|
23626
|
+
}
|
|
23627
|
+
case "hueSaturationLightness":
|
|
23628
|
+
return need(12) ? { kind, hue: i32(0, -180, 180), saturation: i32(1, -100, 100), lightness: i32(2, -100, 100) } : null;
|
|
23629
|
+
case "levels":
|
|
23630
|
+
return need(12) ? { kind, highlight: i32(0, 0, 100), midtone: i32(1, -100, 100), shadow: i32(2, 0, 100) } : null;
|
|
23631
|
+
case "redEyeCorrection": {
|
|
23632
|
+
if (!need(4)) {
|
|
23633
|
+
return null;
|
|
23634
|
+
}
|
|
23635
|
+
const count = view.getInt32(p, true);
|
|
23636
|
+
if (count < 0 || 4 + 16 * count > size) {
|
|
23637
|
+
return null;
|
|
23638
|
+
}
|
|
23639
|
+
const areas = [];
|
|
23640
|
+
for (let k = 0; k < count; k++) {
|
|
23641
|
+
const o = p + 4 + 16 * k;
|
|
23642
|
+
areas.push({
|
|
23643
|
+
left: view.getInt32(o, true),
|
|
23644
|
+
top: view.getInt32(o + 4, true),
|
|
23645
|
+
right: view.getInt32(o + 8, true),
|
|
23646
|
+
bottom: view.getInt32(o + 12, true)
|
|
23647
|
+
});
|
|
23648
|
+
}
|
|
23649
|
+
return { kind, areas };
|
|
23650
|
+
}
|
|
23651
|
+
case "sharpen":
|
|
23652
|
+
return need(8) ? { kind, radius: f323(0, 0, 255), amount: f323(1, 0, 100) } : null;
|
|
23653
|
+
case "tint":
|
|
23654
|
+
return need(8) ? { kind, hue: i32(0, -180, 180), amount: i32(1, -100, 100) } : null;
|
|
23655
|
+
}
|
|
23656
|
+
}
|
|
23657
|
+
function buildLut(f) {
|
|
23658
|
+
const lut = new Uint8Array(256);
|
|
23659
|
+
for (let v = 0; v < 256; v++) {
|
|
23660
|
+
lut[v] = clamp(Math.round(f(v)), 0, 255);
|
|
23661
|
+
}
|
|
23662
|
+
return lut;
|
|
23663
|
+
}
|
|
23664
|
+
function contrastCurve(c) {
|
|
23665
|
+
const gain = c >= 100 ? 1e6 : c >= 0 ? 100 / (100 - c) : (100 + c) / 100;
|
|
23666
|
+
return (v) => (v - 127.5) * gain + 127.5;
|
|
23667
|
+
}
|
|
23668
|
+
function balanceCurve(t) {
|
|
23669
|
+
const f = t / 100;
|
|
23670
|
+
return (v) => f >= 0 ? v + (255 - v) * f : v * (1 + f);
|
|
23671
|
+
}
|
|
23672
|
+
function midtoneCurve(t) {
|
|
23673
|
+
const gamma = 2 ** (-t / 100);
|
|
23674
|
+
return (v) => 255 * (v / 255) ** gamma;
|
|
23675
|
+
}
|
|
23676
|
+
function curveAdjustmentLut(adjustment, intensity) {
|
|
23677
|
+
const t = intensity;
|
|
23678
|
+
switch (adjustment) {
|
|
23679
|
+
case CurveAdjustment.Exposure:
|
|
23680
|
+
return buildLut((v) => v * (1 + t / 255));
|
|
23681
|
+
case CurveAdjustment.Density:
|
|
23682
|
+
return buildLut((v) => v * (1 - t / 255));
|
|
23683
|
+
case CurveAdjustment.Contrast:
|
|
23684
|
+
return buildLut(contrastCurve(clamp(t, -100, 100)));
|
|
23685
|
+
case CurveAdjustment.Highlight:
|
|
23686
|
+
case CurveAdjustment.Shadow: {
|
|
23687
|
+
const high = adjustment === CurveAdjustment.Highlight;
|
|
23688
|
+
const amp = clamp(t, -100, 100) * 0.32;
|
|
23689
|
+
return buildLut((v) => {
|
|
23690
|
+
const inside = high ? v > 128 : v < 128;
|
|
23691
|
+
if (!inside) {
|
|
23692
|
+
return v;
|
|
23693
|
+
}
|
|
23694
|
+
const u = high ? (v - 128) / 127 : v / 128;
|
|
23695
|
+
return v + amp * Math.sin(Math.PI * u);
|
|
23696
|
+
});
|
|
23697
|
+
}
|
|
23698
|
+
case CurveAdjustment.Midtone:
|
|
23699
|
+
return buildLut(midtoneCurve(clamp(t, -100, 100)));
|
|
23700
|
+
case CurveAdjustment.WhiteSaturation: {
|
|
23701
|
+
const w = Math.max(1, clamp(t, 0, 255));
|
|
23702
|
+
return buildLut((v) => v * 255 / w);
|
|
23703
|
+
}
|
|
23704
|
+
case CurveAdjustment.BlackSaturation: {
|
|
23705
|
+
const b = Math.min(254, clamp(t, 0, 255));
|
|
23706
|
+
return buildLut((v) => (v - b) * 255 / (255 - b));
|
|
23707
|
+
}
|
|
23708
|
+
default:
|
|
23709
|
+
return null;
|
|
23710
|
+
}
|
|
23711
|
+
}
|
|
23712
|
+
function levelsLut(highlight, midtone, shadow) {
|
|
23713
|
+
const black = shadow / 100 * 255;
|
|
23714
|
+
const white = Math.max(black + 1, highlight / 100 * 255);
|
|
23715
|
+
const gamma = midtoneCurve(midtone);
|
|
23716
|
+
return buildLut((v) => gamma(clamp((v - black) / (white - black), 0, 1) * 255));
|
|
23717
|
+
}
|
|
23718
|
+
function applyLuts(src, r, g, b, a = null) {
|
|
23719
|
+
const out = new Uint8ClampedArray(src);
|
|
23720
|
+
for (let i = 0; i < out.length; i += 4) {
|
|
23721
|
+
if (r) out[i] = r[src[i]];
|
|
23722
|
+
if (g) out[i + 1] = g[src[i + 1]];
|
|
23723
|
+
if (b) out[i + 2] = b[src[i + 2]];
|
|
23724
|
+
if (a) out[i + 3] = a[src[i + 3]];
|
|
23725
|
+
}
|
|
23726
|
+
return out;
|
|
23727
|
+
}
|
|
23728
|
+
function applyColorMatrix(src, m) {
|
|
23729
|
+
const out = new Uint8ClampedArray(src.length);
|
|
23730
|
+
for (let i = 0; i < src.length; i += 4) {
|
|
23731
|
+
const r = src[i] / 255;
|
|
23732
|
+
const g = src[i + 1] / 255;
|
|
23733
|
+
const b = src[i + 2] / 255;
|
|
23734
|
+
const a = src[i + 3] / 255;
|
|
23735
|
+
for (let j = 0; j < 4; j++) {
|
|
23736
|
+
const v = r * m[j] + g * m[5 + j] + b * m[10 + j] + a * m[15 + j] + m[20 + j];
|
|
23737
|
+
out[i + j] = Math.round(clamp(v, 0, 1) * 255);
|
|
23738
|
+
}
|
|
23739
|
+
}
|
|
23740
|
+
return out;
|
|
23741
|
+
}
|
|
23742
|
+
function rgbToHsl(r, g, b) {
|
|
23743
|
+
const max = Math.max(r, g, b);
|
|
23744
|
+
const min = Math.min(r, g, b);
|
|
23745
|
+
const l = (max + min) / 2;
|
|
23746
|
+
const d = max - min;
|
|
23747
|
+
if (d === 0) {
|
|
23748
|
+
return [0, 0, l];
|
|
23749
|
+
}
|
|
23750
|
+
const s = d / (1 - Math.abs(2 * l - 1));
|
|
23751
|
+
let h;
|
|
23752
|
+
if (max === r) {
|
|
23753
|
+
h = (g - b) / d % 6;
|
|
23754
|
+
} else if (max === g) {
|
|
23755
|
+
h = (b - r) / d + 2;
|
|
23756
|
+
} else {
|
|
23757
|
+
h = (r - g) / d + 4;
|
|
23758
|
+
}
|
|
23759
|
+
h *= 60;
|
|
23760
|
+
return [h < 0 ? h + 360 : h, s, l];
|
|
23761
|
+
}
|
|
23762
|
+
function hslToRgb(h, s, l) {
|
|
23763
|
+
const c = (1 - Math.abs(2 * l - 1)) * s;
|
|
23764
|
+
const hp = (h % 360 + 360) % 360 / 60;
|
|
23765
|
+
const x = c * (1 - Math.abs(hp % 2 - 1));
|
|
23766
|
+
const m = l - c / 2;
|
|
23767
|
+
const [r, g, b] = hp < 1 ? [c, x, 0] : hp < 2 ? [x, c, 0] : hp < 3 ? [0, c, x] : hp < 4 ? [0, x, c] : hp < 5 ? [x, 0, c] : [c, 0, x];
|
|
23768
|
+
return [r + m, g + m, b + m];
|
|
23769
|
+
}
|
|
23770
|
+
function applyHueSaturationLightness(src, hue, saturation, lightness) {
|
|
23771
|
+
const out = new Uint8ClampedArray(src);
|
|
23772
|
+
const push = (v, t) => t >= 0 ? v + (1 - v) * (t / 100) : v * (1 + t / 100);
|
|
23773
|
+
for (let i = 0; i < src.length; i += 4) {
|
|
23774
|
+
const [h, s, l] = rgbToHsl(src[i] / 255, src[i + 1] / 255, src[i + 2] / 255);
|
|
23775
|
+
const [r, g, b] = hslToRgb(h + hue, push(s, saturation), push(l, lightness));
|
|
23776
|
+
out[i] = Math.round(r * 255);
|
|
23777
|
+
out[i + 1] = Math.round(g * 255);
|
|
23778
|
+
out[i + 2] = Math.round(b * 255);
|
|
23779
|
+
}
|
|
23780
|
+
return out;
|
|
23781
|
+
}
|
|
23782
|
+
var LUMA = [0.299, 0.587, 0.114];
|
|
23783
|
+
function applyTint(src, hue, amount) {
|
|
23784
|
+
const tint = hslToRgb(hue, 1, 0.5);
|
|
23785
|
+
const y = tint[0] * LUMA[0] + tint[1] * LUMA[1] + tint[2] * LUMA[2];
|
|
23786
|
+
const k = amount / 100 * 255;
|
|
23787
|
+
const add = tint.map((c) => (c - y) * k);
|
|
23788
|
+
const out = new Uint8ClampedArray(src);
|
|
23789
|
+
for (let i = 0; i < src.length; i += 4) {
|
|
23790
|
+
out[i] = Math.round(src[i] + add[0]);
|
|
23791
|
+
out[i + 1] = Math.round(src[i + 1] + add[1]);
|
|
23792
|
+
out[i + 2] = Math.round(src[i + 2] + add[2]);
|
|
23793
|
+
}
|
|
23794
|
+
return out;
|
|
23795
|
+
}
|
|
23796
|
+
function applyRedEyeCorrection(src, width, height, areas) {
|
|
23797
|
+
const out = new Uint8ClampedArray(src);
|
|
23798
|
+
for (const a of areas) {
|
|
23799
|
+
const x0 = clamp(a.left, 0, width);
|
|
23800
|
+
const x1 = clamp(a.right, 0, width);
|
|
23801
|
+
const y0 = clamp(a.top, 0, height);
|
|
23802
|
+
const y1 = clamp(a.bottom, 0, height);
|
|
23803
|
+
for (let y = y0; y < y1; y++) {
|
|
23804
|
+
for (let x = x0; x < x1; x++) {
|
|
23805
|
+
const i = (y * width + x) * 4;
|
|
23806
|
+
const r = out[i];
|
|
23807
|
+
const g = out[i + 1];
|
|
23808
|
+
const b = out[i + 2];
|
|
23809
|
+
if (r > g && r > b) {
|
|
23810
|
+
out[i] = Math.round((g + b) / 2);
|
|
23811
|
+
}
|
|
23812
|
+
}
|
|
23813
|
+
}
|
|
23814
|
+
}
|
|
23815
|
+
return out;
|
|
23816
|
+
}
|
|
23817
|
+
function boxRadiiForSigma(sigma) {
|
|
23818
|
+
const target = sigma * sigma;
|
|
23819
|
+
let k = 0;
|
|
23820
|
+
while ((k + 1) * (k + 2) <= target) {
|
|
23821
|
+
k++;
|
|
23822
|
+
}
|
|
23823
|
+
const v = (n) => n * (n + 1) / 3;
|
|
23824
|
+
let best = 0;
|
|
23825
|
+
for (let m = 1; m <= 3; m++) {
|
|
23826
|
+
if (Math.abs((3 - m) * v(k) + m * v(k + 1) - target) < Math.abs((3 - best) * v(k) + best * v(k + 1) - target)) {
|
|
23827
|
+
best = m;
|
|
23828
|
+
}
|
|
23829
|
+
}
|
|
23830
|
+
return [0, 1, 2].map((i) => i < best ? k + 1 : k);
|
|
23831
|
+
}
|
|
23832
|
+
function boxPass(src, w, h, r, horizontal) {
|
|
23833
|
+
if (r <= 0) {
|
|
23834
|
+
return src;
|
|
23835
|
+
}
|
|
23836
|
+
const out = new Float64Array(src.length);
|
|
23837
|
+
const lines = horizontal ? h : w;
|
|
23838
|
+
const len = horizontal ? w : h;
|
|
23839
|
+
const step = horizontal ? 4 : w * 4;
|
|
23840
|
+
const norm = 1 / (2 * r + 1);
|
|
23841
|
+
for (let line = 0; line < lines; line++) {
|
|
23842
|
+
const base = horizontal ? line * w * 4 : line * 4;
|
|
23843
|
+
for (let c = 0; c < 4; c++) {
|
|
23844
|
+
const at = (p) => src[base + clamp(p, 0, len - 1) * step + c];
|
|
23845
|
+
let sum = 0;
|
|
23846
|
+
for (let p = -r; p <= r; p++) {
|
|
23847
|
+
sum += at(p);
|
|
23848
|
+
}
|
|
23849
|
+
for (let p = 0; p < len; p++) {
|
|
23850
|
+
out[base + p * step + c] = sum * norm;
|
|
23851
|
+
sum += at(p + r + 1) - at(p - r);
|
|
23852
|
+
}
|
|
23853
|
+
}
|
|
23854
|
+
}
|
|
23855
|
+
return out;
|
|
23856
|
+
}
|
|
23857
|
+
function blurFloat(src, w, h, radius) {
|
|
23858
|
+
let buf = new Float64Array(src.length);
|
|
23859
|
+
for (let i = 0; i < src.length; i += 4) {
|
|
23860
|
+
const a = src[i + 3] / 255;
|
|
23861
|
+
buf[i] = src[i] * a;
|
|
23862
|
+
buf[i + 1] = src[i + 1] * a;
|
|
23863
|
+
buf[i + 2] = src[i + 2] * a;
|
|
23864
|
+
buf[i + 3] = src[i + 3];
|
|
23865
|
+
}
|
|
23866
|
+
for (const r of boxRadiiForSigma(radius / 2)) {
|
|
23867
|
+
buf = boxPass(buf, w, h, r, true);
|
|
23868
|
+
buf = boxPass(buf, w, h, r, false);
|
|
23869
|
+
}
|
|
23870
|
+
for (let i = 0; i < buf.length; i += 4) {
|
|
23871
|
+
const a = buf[i + 3] / 255;
|
|
23872
|
+
for (let c = 0; c < 3; c++) {
|
|
23873
|
+
buf[i + c] = a > 0 ? buf[i + c] / a : 0;
|
|
23874
|
+
}
|
|
23875
|
+
}
|
|
23876
|
+
return buf;
|
|
23877
|
+
}
|
|
23878
|
+
function applyBlur(src, w, h, radius) {
|
|
23879
|
+
const blurred = blurFloat(src, w, h, radius);
|
|
23880
|
+
const out = new Uint8ClampedArray(src.length);
|
|
23881
|
+
for (let i = 0; i < src.length; i++) {
|
|
23882
|
+
out[i] = Math.round(blurred[i]);
|
|
23883
|
+
}
|
|
23884
|
+
return out;
|
|
23885
|
+
}
|
|
23886
|
+
function applySharpen(src, w, h, radius, amount) {
|
|
23887
|
+
const blurred = blurFloat(src, w, h, radius);
|
|
23888
|
+
const k = amount / 100;
|
|
23889
|
+
const out = new Uint8ClampedArray(src);
|
|
23890
|
+
for (let i = 0; i < src.length; i += 4) {
|
|
23891
|
+
for (let c = 0; c < 3; c++) {
|
|
23892
|
+
out[i + c] = Math.round(src[i + c] + k * (src[i + c] - blurred[i + c]));
|
|
23893
|
+
}
|
|
23894
|
+
}
|
|
23895
|
+
return out;
|
|
23896
|
+
}
|
|
23897
|
+
function applyImageEffect(rgba, width, height, effect) {
|
|
23898
|
+
if (width <= 0 || height <= 0 || rgba.length !== width * height * 4) {
|
|
23899
|
+
return null;
|
|
23900
|
+
}
|
|
23901
|
+
switch (effect.kind) {
|
|
23902
|
+
case "blur":
|
|
23903
|
+
return applyBlur(rgba, width, height, effect.radius);
|
|
23904
|
+
case "sharpen":
|
|
23905
|
+
return applySharpen(rgba, width, height, effect.radius, effect.amount);
|
|
23906
|
+
case "brightnessContrast": {
|
|
23907
|
+
const contrast = contrastCurve(effect.contrast);
|
|
23908
|
+
const lut = buildLut((v) => contrast(v) + effect.brightness);
|
|
23909
|
+
return applyLuts(rgba, lut, lut, lut);
|
|
23910
|
+
}
|
|
23911
|
+
case "colorBalance":
|
|
23912
|
+
return applyLuts(
|
|
23913
|
+
rgba,
|
|
23914
|
+
buildLut(balanceCurve(effect.cyanRed)),
|
|
23915
|
+
buildLut(balanceCurve(effect.magentaGreen)),
|
|
23916
|
+
buildLut(balanceCurve(effect.yellowBlue))
|
|
23917
|
+
);
|
|
23918
|
+
case "colorCurve": {
|
|
23919
|
+
const lut = curveAdjustmentLut(effect.adjustment, effect.intensity);
|
|
23920
|
+
const ch = effect.channel;
|
|
23921
|
+
if (!lut || ch < CurveChannel.All || ch > CurveChannel.Blue) {
|
|
23922
|
+
return null;
|
|
23923
|
+
}
|
|
23924
|
+
const pick = (c) => ch === CurveChannel.All || ch === c ? lut : null;
|
|
23925
|
+
return applyLuts(rgba, pick(CurveChannel.Red), pick(CurveChannel.Green), pick(CurveChannel.Blue));
|
|
23926
|
+
}
|
|
23927
|
+
case "colorLookupTable":
|
|
23928
|
+
return applyLuts(rgba, effect.r, effect.g, effect.b, effect.a);
|
|
23929
|
+
case "colorMatrix":
|
|
23930
|
+
return applyColorMatrix(rgba, effect.matrix);
|
|
23931
|
+
case "hueSaturationLightness":
|
|
23932
|
+
return applyHueSaturationLightness(rgba, effect.hue, effect.saturation, effect.lightness);
|
|
23933
|
+
case "levels": {
|
|
23934
|
+
const lut = levelsLut(effect.highlight, effect.midtone, effect.shadow);
|
|
23935
|
+
return applyLuts(rgba, lut, lut, lut);
|
|
23936
|
+
}
|
|
23937
|
+
case "redEyeCorrection":
|
|
23938
|
+
return applyRedEyeCorrection(rgba, width, height, effect.areas);
|
|
23939
|
+
case "tint":
|
|
23940
|
+
return applyTint(rgba, effect.hue, effect.amount);
|
|
23941
|
+
}
|
|
23942
|
+
}
|
|
23943
|
+
|
|
23287
23944
|
// src/emf-plus-draw-image.ts
|
|
23288
23945
|
function surfaceSize4(ctx) {
|
|
23289
23946
|
const canvas = ctx.canvas;
|
|
@@ -23346,8 +24003,8 @@ function svgImagePayload(img, bitmap) {
|
|
|
23346
24003
|
}
|
|
23347
24004
|
return decodeBmpFile(bytes.buffer);
|
|
23348
24005
|
}
|
|
23349
|
-
function paintBitmapSvg(svg, img, bitmap, draw) {
|
|
23350
|
-
const payload = svgImagePayload(img, bitmap);
|
|
24006
|
+
function paintBitmapSvg(svg, img, bitmap, draw, pixelsOnly = false) {
|
|
24007
|
+
const payload = pixelsOnly && bitmap ? { kind: "rgba", data: bitmap.rgba, width: bitmap.width, height: bitmap.height } : svgImagePayload(img, bitmap);
|
|
23351
24008
|
if (!payload) {
|
|
23352
24009
|
return false;
|
|
23353
24010
|
}
|
|
@@ -23419,14 +24076,32 @@ function drawNestedMetafile(rCtx, img, cached, source) {
|
|
|
23419
24076
|
rCtx.deferredImages.push(...deferred);
|
|
23420
24077
|
return true;
|
|
23421
24078
|
}
|
|
23422
|
-
function
|
|
24079
|
+
function effectedBitmap(img, bitmap, effect) {
|
|
24080
|
+
let src = bitmap;
|
|
24081
|
+
if (!src && img.data) {
|
|
24082
|
+
const bmp = decodeBmpFile(img.data.slice(0));
|
|
24083
|
+
if (bmp && bmp.kind === "rgba") {
|
|
24084
|
+
src = { rgba: bmp.data, width: bmp.width, height: bmp.height };
|
|
24085
|
+
}
|
|
24086
|
+
}
|
|
24087
|
+
if (!src) {
|
|
24088
|
+
return null;
|
|
24089
|
+
}
|
|
24090
|
+
const rgba = applyImageEffect(src.rgba, src.width, src.height, effect);
|
|
24091
|
+
return rgba ? { kind: "bitmap", width: src.width, height: src.height, rgba } : null;
|
|
24092
|
+
}
|
|
24093
|
+
function drawEmfPlusImageNow(rCtx, img, draw, source, effect = null) {
|
|
23423
24094
|
const cached = img.cacheKey !== void 0 ? rCtx.imageCache?.get(img.cacheKey) : void 0;
|
|
23424
24095
|
if (img.type === 2) {
|
|
23425
24096
|
return drawNestedMetafile(rCtx, img, cached, source);
|
|
23426
24097
|
}
|
|
23427
|
-
|
|
24098
|
+
let bitmap = cached && cached.kind === "bitmap" ? cached : null;
|
|
24099
|
+
const effected = effect ? effectedBitmap(img, bitmap, effect) : null;
|
|
24100
|
+
if (effected) {
|
|
24101
|
+
bitmap = effected;
|
|
24102
|
+
}
|
|
23428
24103
|
if (isSvgContext(rCtx.ctx)) {
|
|
23429
|
-
return paintBitmapSvg(rCtx.ctx, img, bitmap, draw);
|
|
24104
|
+
return paintBitmapSvg(rCtx.ctx, img, bitmap, draw, effected !== null);
|
|
23430
24105
|
}
|
|
23431
24106
|
return bitmap ? paintBitmapRaster(rCtx.ctx, bitmap, draw) : false;
|
|
23432
24107
|
}
|
|
@@ -23667,7 +24342,7 @@ function penDashArray(pen) {
|
|
|
23667
24342
|
return pattern.map((v) => v * w);
|
|
23668
24343
|
}
|
|
23669
24344
|
function applyPlusPenStyle(ctx, pen, widthScale = 1) {
|
|
23670
|
-
ctx.lineWidth = pen.width * widthScale;
|
|
24345
|
+
ctx.lineWidth = (pen.width || 1) * widthScale;
|
|
23671
24346
|
const dashes = penDashArray(pen);
|
|
23672
24347
|
ctx.lineCap = canvasLineCap(dashes.length > 0 ? pen.dashCap ?? 0 : pen.startCap ?? pen.endCap);
|
|
23673
24348
|
ctx.lineJoin = canvasLineJoin(pen.lineJoin);
|
|
@@ -23679,19 +24354,27 @@ function applyPlusPenStyle(ctx, pen, widthScale = 1) {
|
|
|
23679
24354
|
}
|
|
23680
24355
|
function strokePlusGeometry(rCtx, pen, buildPath, points, closedFigure = false) {
|
|
23681
24356
|
const { ctx } = rCtx;
|
|
24357
|
+
const resolved = resolvePenTransform(pen);
|
|
24358
|
+
pen = resolved.pen;
|
|
24359
|
+
const nib = resolved.nib;
|
|
23682
24360
|
const inset = !!pen && pen.alignment === 1 && closedFigure;
|
|
23683
24361
|
const widthScale = inset ? 2 : 1;
|
|
23684
24362
|
const stroke = (c) => {
|
|
23685
|
-
if (inset) {
|
|
24363
|
+
if (inset || nib) {
|
|
23686
24364
|
c.save();
|
|
24365
|
+
}
|
|
24366
|
+
if (inset) {
|
|
23687
24367
|
c.beginPath();
|
|
23688
24368
|
buildPath(c);
|
|
23689
24369
|
c.clip();
|
|
23690
24370
|
}
|
|
23691
24371
|
c.beginPath();
|
|
23692
24372
|
buildPath(c);
|
|
24373
|
+
if (nib) {
|
|
24374
|
+
c.transform(nib[0], nib[1], nib[2], nib[3], 0, 0);
|
|
24375
|
+
}
|
|
23693
24376
|
c.stroke();
|
|
23694
|
-
if (inset) {
|
|
24377
|
+
if (inset || nib) {
|
|
23695
24378
|
c.restore();
|
|
23696
24379
|
}
|
|
23697
24380
|
};
|
|
@@ -23706,8 +24389,8 @@ function strokePlusGeometry(rCtx, pen, buildPath, points, closedFigure = false)
|
|
|
23706
24389
|
if (sampler) {
|
|
23707
24390
|
const size = surfaceSize5(ctx);
|
|
23708
24391
|
const device = plusWorldMatrix(rCtx);
|
|
23709
|
-
const scale =
|
|
23710
|
-
if (mode !== "canvas" && size && strokeGdiplus(rCtx, pen, sampler, buildPath, device, size, mode, closedFigure)) {
|
|
24392
|
+
const scale = maxStretch(nib ? mulMatrix(device, nib) : device);
|
|
24393
|
+
if (mode !== "canvas" && size && strokeGdiplus(rCtx, pen, nib, sampler, buildPath, device, size, mode, closedFigure)) {
|
|
23711
24394
|
return;
|
|
23712
24395
|
}
|
|
23713
24396
|
const miter = Math.max(1, ctx.miterLimit || 10);
|
|
@@ -23725,6 +24408,9 @@ function strokePlusGeometry(rCtx, pen, buildPath, points, closedFigure = false)
|
|
|
23725
24408
|
stroke(c);
|
|
23726
24409
|
c.beginPath();
|
|
23727
24410
|
buildPath(c);
|
|
24411
|
+
if (nib) {
|
|
24412
|
+
c.transform(nib[0], nib[1], nib[2], nib[3], 0, 0);
|
|
24413
|
+
}
|
|
23728
24414
|
},
|
|
23729
24415
|
mode,
|
|
23730
24416
|
(c, x, y) => c.isPointInStroke(x, y) && (!inset || c.isPointInPath(x, y))
|
|
@@ -23732,55 +24418,105 @@ function strokePlusGeometry(rCtx, pen, buildPath, points, closedFigure = false)
|
|
|
23732
24418
|
return;
|
|
23733
24419
|
}
|
|
23734
24420
|
}
|
|
23735
|
-
|
|
24421
|
+
const paint = pen.brush ? brushPaint2(rCtx, pen.brush) : pen.color;
|
|
24422
|
+
if ((hasCustomCap(pen) || nib && typeof paint !== "string") && fillPenOutline(rCtx, pen, nib, paint, buildPath, closedFigure)) {
|
|
23736
24423
|
return;
|
|
23737
24424
|
}
|
|
23738
|
-
ctx.strokeStyle =
|
|
24425
|
+
ctx.strokeStyle = paint;
|
|
23739
24426
|
}
|
|
23740
24427
|
applyPlusWorldTransform(rCtx);
|
|
23741
24428
|
stroke(ctx);
|
|
23742
24429
|
}
|
|
23743
|
-
function
|
|
23744
|
-
if (
|
|
23745
|
-
return
|
|
24430
|
+
function resolvePenTransform(pen) {
|
|
24431
|
+
if (!pen?.transform) {
|
|
24432
|
+
return { pen, nib: null };
|
|
23746
24433
|
}
|
|
23747
|
-
const
|
|
23748
|
-
const
|
|
23749
|
-
const
|
|
23750
|
-
|
|
23751
|
-
|
|
24434
|
+
const [a, b, c, d] = pen.transform;
|
|
24435
|
+
const sx = Math.hypot(a, b);
|
|
24436
|
+
const sy = Math.hypot(c, d);
|
|
24437
|
+
const dot = a * c + b * d;
|
|
24438
|
+
const det = a * d - b * c;
|
|
24439
|
+
const plain = { ...pen, transform: null };
|
|
24440
|
+
if (pen.width === 0 || isIdentity2(pen.transform) || !Number.isFinite(sx + sy + dot + det) || Math.abs(det) < 1e-12) {
|
|
24441
|
+
return { pen: { ...plain, width: pen.width === 0 ? 1 : pen.width }, nib: null };
|
|
23752
24442
|
}
|
|
23753
|
-
|
|
23754
|
-
|
|
23755
|
-
figures = recordDeviceFigures(buildPath, device);
|
|
23756
|
-
} catch {
|
|
23757
|
-
return false;
|
|
24443
|
+
if (Math.abs(sx - sy) <= 1e-6 * sx && Math.abs(dot) <= 1e-6 * sx * sy) {
|
|
24444
|
+
return { pen: { ...plain, width: pen.width * sx }, nib: null };
|
|
23758
24445
|
}
|
|
23759
|
-
|
|
23760
|
-
|
|
24446
|
+
return { pen: plain, nib: [a, b, c, d, 0, 0] };
|
|
24447
|
+
}
|
|
24448
|
+
function maxStretch(m) {
|
|
24449
|
+
const s = m[0] * m[0] + m[1] * m[1] + m[2] * m[2] + m[3] * m[3];
|
|
24450
|
+
const det = m[0] * m[3] - m[1] * m[2];
|
|
24451
|
+
return Math.sqrt((s + Math.sqrt(Math.max(0, s * s - 4 * det * det))) / 2);
|
|
24452
|
+
}
|
|
24453
|
+
function penFrame(device, nib) {
|
|
24454
|
+
if (!nib) {
|
|
24455
|
+
return { record: device, unit: Math.hypot(device[0], device[1]), toDevice: IDENTITY5 };
|
|
23761
24456
|
}
|
|
23762
|
-
const
|
|
23763
|
-
const
|
|
23764
|
-
const
|
|
23765
|
-
|
|
24457
|
+
const full = mulMatrix(device, nib);
|
|
24458
|
+
const unit = maxStretch(full);
|
|
24459
|
+
const inv2 = invertAffine(nib);
|
|
24460
|
+
if (!inv2 || !(unit > 0) || !Number.isFinite(unit)) {
|
|
24461
|
+
return null;
|
|
24462
|
+
}
|
|
24463
|
+
return {
|
|
24464
|
+
record: [inv2[0] * unit, inv2[1] * unit, inv2[2] * unit, inv2[3] * unit, 0, 0],
|
|
24465
|
+
unit,
|
|
24466
|
+
toDevice: mulMatrix(full, [1 / unit, 0, 0, 1 / unit, 0, 0])
|
|
24467
|
+
};
|
|
24468
|
+
}
|
|
24469
|
+
function framePen(pen, unit) {
|
|
24470
|
+
const dash = penDashArray(pen).map((v) => v * unit);
|
|
24471
|
+
return {
|
|
24472
|
+
half: (pen.width || 1) * unit / 2,
|
|
23766
24473
|
join: pen.lineJoin ?? 0,
|
|
23767
24474
|
miterLimit: pen.miterLimit && pen.miterLimit >= 1 ? pen.miterLimit : 10,
|
|
23768
24475
|
startCap: pen.startCap ?? 0,
|
|
23769
24476
|
endCap: pen.endCap ?? 0,
|
|
23770
24477
|
dashCap: pen.dashCap ?? 0,
|
|
23771
24478
|
dash: dash.length > 0 ? dash : null,
|
|
23772
|
-
dashOffset: (pen.dashOffset ?? 0) * (pen.width || 1) *
|
|
24479
|
+
dashOffset: (pen.dashOffset ?? 0) * (pen.width || 1) * unit,
|
|
23773
24480
|
compound: pen.compound ?? null,
|
|
23774
24481
|
inset: pen.alignment === 1
|
|
23775
24482
|
};
|
|
24483
|
+
}
|
|
24484
|
+
function strokeGdiplus(rCtx, pen, nib, sampler, buildPath, device, size, mode, closedFigure) {
|
|
24485
|
+
if (!nib) {
|
|
24486
|
+
const sx = Math.hypot(device[0], device[1]);
|
|
24487
|
+
const sy = Math.hypot(device[2], device[3]);
|
|
24488
|
+
const dot = device[0] * device[2] + device[1] * device[3];
|
|
24489
|
+
if (!(sx > 0) || Math.abs(sx - sy) > 1e-6 * sx || Math.abs(dot) > 1e-6 * sx * sy) {
|
|
24490
|
+
return false;
|
|
24491
|
+
}
|
|
24492
|
+
}
|
|
24493
|
+
const frame2 = penFrame(device, nib);
|
|
24494
|
+
if (!frame2) {
|
|
24495
|
+
return false;
|
|
24496
|
+
}
|
|
24497
|
+
let figures;
|
|
24498
|
+
try {
|
|
24499
|
+
figures = recordDeviceFigures(buildPath, frame2.record);
|
|
24500
|
+
} catch {
|
|
24501
|
+
return false;
|
|
24502
|
+
}
|
|
24503
|
+
if (closedFigure) {
|
|
24504
|
+
figures = figures.map((f) => ({ ...f, closed: true }));
|
|
24505
|
+
}
|
|
24506
|
+
const width = (pen.width || 1) * frame2.unit;
|
|
24507
|
+
const devicePen = framePen(pen, frame2.unit);
|
|
23776
24508
|
const antialias = mode === "gdiplus-aa";
|
|
24509
|
+
const toFix = (poly) => {
|
|
24510
|
+
const m = frame2.toDevice;
|
|
24511
|
+
return poly.flatMap((p) => [toPlusFix(m[0] * p.x + m[2] * p.y + m[4]), toPlusFix(m[1] * p.x + m[3] * p.y + m[5])]);
|
|
24512
|
+
};
|
|
23777
24513
|
let fix;
|
|
23778
24514
|
if (hasCustomCap(pen)) {
|
|
23779
|
-
fix = customCapOutline(figures, width, devicePen, pen).map(
|
|
24515
|
+
fix = customCapOutline(figures, width, devicePen, pen).map(toFix);
|
|
23780
24516
|
} else if (width <= NOMINAL_PEN_MAX && !devicePen.dash && !(((pen.startCap ?? 0) | (pen.endCap ?? 0) | (pen.dashCap ?? 0)) & 240)) {
|
|
23781
24517
|
return strokeNominal(rCtx, pen, sampler, buildPath, device, size, antialias, closedFigure);
|
|
23782
24518
|
} else {
|
|
23783
|
-
fix = widenFigures(figures, devicePen).map(
|
|
24519
|
+
fix = widenFigures(figures, devicePen).map(toFix);
|
|
23784
24520
|
}
|
|
23785
24521
|
const box = figuresBox(fix, size);
|
|
23786
24522
|
if (!box) {
|
|
@@ -23843,54 +24579,36 @@ function customCapOutline(figures, width, devicePen, pen) {
|
|
|
23843
24579
|
outline.push(...geo.polygons);
|
|
23844
24580
|
return outline;
|
|
23845
24581
|
}
|
|
23846
|
-
function
|
|
24582
|
+
function fillPenOutline(rCtx, pen, nib, paint, buildPath, closedFigure) {
|
|
23847
24583
|
const device = plusWorldMatrix(rCtx);
|
|
23848
|
-
const
|
|
23849
|
-
const
|
|
23850
|
-
if (!
|
|
24584
|
+
const frame2 = penFrame(device, nib);
|
|
24585
|
+
const deviceInv = invertAffine(device);
|
|
24586
|
+
if (!frame2 || !deviceInv || !(frame2.unit > 0)) {
|
|
23851
24587
|
return false;
|
|
23852
24588
|
}
|
|
23853
24589
|
let figures;
|
|
23854
24590
|
try {
|
|
23855
|
-
figures = recordDeviceFigures(buildPath,
|
|
24591
|
+
figures = recordDeviceFigures(buildPath, frame2.record);
|
|
23856
24592
|
} catch {
|
|
23857
24593
|
return false;
|
|
23858
24594
|
}
|
|
23859
24595
|
if (closedFigure) {
|
|
23860
24596
|
figures = figures.map((f) => ({ ...f, closed: true }));
|
|
23861
24597
|
}
|
|
23862
|
-
const width = (pen.width || 1) *
|
|
23863
|
-
const
|
|
23864
|
-
const
|
|
23865
|
-
|
|
23866
|
-
join: pen.lineJoin ?? 0,
|
|
23867
|
-
miterLimit: pen.miterLimit && pen.miterLimit >= 1 ? pen.miterLimit : 10,
|
|
23868
|
-
startCap: pen.startCap ?? 0,
|
|
23869
|
-
endCap: pen.endCap ?? 0,
|
|
23870
|
-
dashCap: pen.dashCap ?? 0,
|
|
23871
|
-
dash: dash.length > 0 ? dash : null,
|
|
23872
|
-
dashOffset: (pen.dashOffset ?? 0) * (pen.width || 1) * sx,
|
|
23873
|
-
compound: pen.compound ?? null,
|
|
23874
|
-
inset: pen.alignment === 1
|
|
23875
|
-
};
|
|
23876
|
-
const inv2 = [
|
|
23877
|
-
device[3] / det,
|
|
23878
|
-
-device[1] / det,
|
|
23879
|
-
-device[2] / det,
|
|
23880
|
-
device[0] / det,
|
|
23881
|
-
(device[2] * device[5] - device[3] * device[4]) / det,
|
|
23882
|
-
(device[1] * device[4] - device[0] * device[5]) / det
|
|
23883
|
-
];
|
|
24598
|
+
const width = (pen.width || 1) * frame2.unit;
|
|
24599
|
+
const devicePen = framePen(pen, frame2.unit);
|
|
24600
|
+
const outline = hasCustomCap(pen) ? customCapOutline(figures, width, devicePen, pen) : widenFigures(figures, devicePen);
|
|
24601
|
+
const toWorld = mulMatrix(deviceInv, frame2.toDevice);
|
|
23884
24602
|
const { ctx } = rCtx;
|
|
23885
24603
|
ctx.save();
|
|
23886
24604
|
try {
|
|
23887
|
-
ctx.fillStyle =
|
|
24605
|
+
ctx.fillStyle = paint;
|
|
23888
24606
|
applyPlusWorldTransform(rCtx);
|
|
23889
24607
|
ctx.beginPath();
|
|
23890
|
-
for (const poly of
|
|
24608
|
+
for (const poly of outline) {
|
|
23891
24609
|
poly.forEach((p, i) => {
|
|
23892
|
-
const x =
|
|
23893
|
-
const y =
|
|
24610
|
+
const x = toWorld[0] * p.x + toWorld[2] * p.y + toWorld[4];
|
|
24611
|
+
const y = toWorld[1] * p.x + toWorld[3] * p.y + toWorld[5];
|
|
23894
24612
|
if (i === 0) {
|
|
23895
24613
|
ctx.moveTo(x, y);
|
|
23896
24614
|
} else {
|
|
@@ -23905,6 +24623,7 @@ function fillCustomCapStroke(rCtx, pen, buildPath, closedFigure) {
|
|
|
23905
24623
|
}
|
|
23906
24624
|
return true;
|
|
23907
24625
|
}
|
|
24626
|
+
var IDENTITY5 = [1, 0, 0, 1, 0, 0];
|
|
23908
24627
|
function isIdentity2(m) {
|
|
23909
24628
|
return m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 1 && m[4] === 0 && m[5] === 0;
|
|
23910
24629
|
}
|
|
@@ -23957,7 +24676,7 @@ function imageResampleSpec(rCtx, dataOff, isMetafile, toWorld) {
|
|
|
23957
24676
|
...imageAttributesWrap(rCtx, view.getUint32(dataOff, true))
|
|
23958
24677
|
};
|
|
23959
24678
|
}
|
|
23960
|
-
function drawOrDeferImage(rCtx, imgObj, dataOff, dx, dy, dw, dh, toWorld) {
|
|
24679
|
+
function drawOrDeferImage(rCtx, imgObj, dataOff, dx, dy, dw, dh, toWorld, effect = null) {
|
|
23961
24680
|
if (!imgObj.data) {
|
|
23962
24681
|
return;
|
|
23963
24682
|
}
|
|
@@ -23981,7 +24700,7 @@ function drawOrDeferImage(rCtx, imgObj, dataOff, dx, dy, dw, dh, toWorld) {
|
|
|
23981
24700
|
srcH: view.getFloat32(dataOff + 20, true),
|
|
23982
24701
|
toWorld
|
|
23983
24702
|
};
|
|
23984
|
-
if (drawEmfPlusImageNow(rCtx, imgObj, draw, source)) {
|
|
24703
|
+
if (drawEmfPlusImageNow(rCtx, imgObj, draw, source, effect)) {
|
|
23985
24704
|
return;
|
|
23986
24705
|
}
|
|
23987
24706
|
if (isSvgContext(rCtx.ctx)) {
|
|
@@ -24153,6 +24872,7 @@ function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, paint, ali
|
|
|
24153
24872
|
dx,
|
|
24154
24873
|
dy: null,
|
|
24155
24874
|
textAlign: 24,
|
|
24875
|
+
options: 0,
|
|
24156
24876
|
matrix: null});
|
|
24157
24877
|
if (!cov) {
|
|
24158
24878
|
return true;
|
|
@@ -24344,6 +25064,10 @@ function handleEmfPlusTextImageRecord(rCtx, recType, recFlags, dataOff, recDataS
|
|
|
24344
25064
|
const imgObj = objectTable.get(imgId);
|
|
24345
25065
|
const count = view.getUint32(dataOff + 24, true);
|
|
24346
25066
|
const ptOff = dataOff + 28;
|
|
25067
|
+
const effect = (recFlags & DRAWIMAGE_EFFECT_FLAG) !== 0 ? rCtx.ext?.pendingEffect ?? null : null;
|
|
25068
|
+
if (rCtx.ext) {
|
|
25069
|
+
rCtx.ext.pendingEffect = null;
|
|
25070
|
+
}
|
|
24347
25071
|
if (count >= 3 && imgObj && imgObj.kind === "plus-image" && imgObj.data) {
|
|
24348
25072
|
const pts = readPlusPoints(view, ptOff, dataOff + recDataSize, 3, recFlags);
|
|
24349
25073
|
if (!pts) {
|
|
@@ -24367,7 +25091,7 @@ function handleEmfPlusTextImageRecord(rCtx, recType, recFlags, dataOff, recDataS
|
|
|
24367
25091
|
const c = (p3x - p1x) / sh;
|
|
24368
25092
|
const d = (p3y - p1y) / sh;
|
|
24369
25093
|
return [a, b, c, d, p1x - a * sx - c * sy, p1y - b * sx - d * sy];
|
|
24370
|
-
});
|
|
25094
|
+
}, effect);
|
|
24371
25095
|
} else {
|
|
24372
25096
|
imgObj && imgObj.kind === "plus-image" && imgObj.data;
|
|
24373
25097
|
}
|
|
@@ -25197,12 +25921,14 @@ function replayEmfPlusRecords(view, offset, length, ctx, canvasW, canvasH, state
|
|
|
25197
25921
|
recordCount++;
|
|
25198
25922
|
emfPlusRecordTypes.set(recType, (emfPlusRecordTypes.get(recType) ?? 0) + 1);
|
|
25199
25923
|
const dataOff = offset + 12;
|
|
25924
|
+
s.gdiPassthrough = recType === EMFPLUS_GETDC;
|
|
25200
25925
|
if (rCtx.ext?.multiFormatSkip && recType !== EMFPLUS_ENDOFFILE) {
|
|
25201
25926
|
offset += recSize;
|
|
25202
25927
|
continue;
|
|
25203
25928
|
}
|
|
25204
25929
|
switch (recType) {
|
|
25205
25930
|
case EMFPLUS_HEADER: {
|
|
25931
|
+
s.dualMode = (recFlags & 1) !== 0;
|
|
25206
25932
|
if (recDataSize >= 16) {
|
|
25207
25933
|
view.getFloat32(dataOff + 8, true);
|
|
25208
25934
|
view.getFloat32(dataOff + 12, true);
|
|
@@ -25221,6 +25947,12 @@ function replayEmfPlusRecords(view, offset, length, ctx, canvasW, canvasH, state
|
|
|
25221
25947
|
case EMFPLUS_MULTIFORMATSECTION:
|
|
25222
25948
|
case EMFPLUS_MULTIFORMATEND:
|
|
25223
25949
|
break;
|
|
25950
|
+
// An image effect for the next DrawImagePoints with flag E
|
|
25951
|
+
// (`emf-plus-image-effects.ts`); an unknown or malformed effect
|
|
25952
|
+
// replaces any earlier one with none.
|
|
25953
|
+
case EMFPLUS_SERIALIZABLEOBJECT:
|
|
25954
|
+
(rCtx.ext ?? (rCtx.ext = {})).pendingEffect = parseSerializableObject(view, dataOff, recDataSize);
|
|
25955
|
+
break;
|
|
25224
25956
|
case EMFPLUS_CLEAR: {
|
|
25225
25957
|
if (recDataSize >= 4) {
|
|
25226
25958
|
const argb = view.getUint32(dataOff, true);
|
|
@@ -25367,11 +26099,16 @@ function replayEmfRecords(view, ctx, bounds, canvasW, canvasH, dpiScale = 1, rep
|
|
|
25367
26099
|
state: { ...defaultState(), fontFamilyMap: replayOptions.fontFamilyMap },
|
|
25368
26100
|
stateStack: [],
|
|
25369
26101
|
inPath: false,
|
|
25370
|
-
|
|
26102
|
+
// GDI's defaults: both origins at 0 and a 1:1 window/viewport ratio.
|
|
26103
|
+
// The window/viewport mapping yields device units, placed on the
|
|
26104
|
+
// canvas like every other device coordinate (bounds' top-left to the
|
|
26105
|
+
// canvas origin, scaled by sx/sy); see `deviceToCanvas`.
|
|
26106
|
+
windowOrg: { x: 0, y: 0 },
|
|
25371
26107
|
windowExt: { cx: logicalW, cy: logicalH },
|
|
25372
26108
|
viewportOrg: { x: 0, y: 0 },
|
|
25373
|
-
viewportExt: { cx:
|
|
26109
|
+
viewportExt: { cx: logicalW, cy: logicalH },
|
|
25374
26110
|
useMappingMode: false,
|
|
26111
|
+
deviceToCanvas: true,
|
|
25375
26112
|
clipSaveDepth: 0,
|
|
25376
26113
|
bounds,
|
|
25377
26114
|
canvasW,
|
|
@@ -25458,6 +26195,13 @@ function replayEmfRecords(view, ctx, bounds, canvasW, canvasH, dpiScale = 1, rep
|
|
|
25458
26195
|
offset += recSize;
|
|
25459
26196
|
continue;
|
|
25460
26197
|
}
|
|
26198
|
+
if (emfPlusState.dualMode && !emfPlusState.gdiPassthrough) {
|
|
26199
|
+
if (recType !== EMR_SAVEDC && recType !== EMR_RESTOREDC) {
|
|
26200
|
+
handleEmfGdiStateRecord(rCtx, recType, offset, dataOff, recSize);
|
|
26201
|
+
}
|
|
26202
|
+
offset += recSize;
|
|
26203
|
+
continue;
|
|
26204
|
+
}
|
|
25461
26205
|
const handled = handleEmfGdiStateRecord(rCtx, recType, offset, dataOff, recSize) || handleEmfGdiDrawRecord(rCtx, recType, offset, dataOff, recSize) || handleEmfGdiPolyPathRecord(rCtx, recType, offset, dataOff, recSize);
|
|
25462
26206
|
if (!handled) {
|
|
25463
26207
|
console.warn(`[emf-converter] Unhandled EMR record type: ${recType}`);
|
|
@@ -26867,46 +27611,6 @@ function penIsNull(p) {
|
|
|
26867
27611
|
}
|
|
26868
27612
|
|
|
26869
27613
|
// src/wmf-text.ts
|
|
26870
|
-
var CP1252_HIGH2 = [
|
|
26871
|
-
8364,
|
|
26872
|
-
129,
|
|
26873
|
-
8218,
|
|
26874
|
-
402,
|
|
26875
|
-
8222,
|
|
26876
|
-
8230,
|
|
26877
|
-
8224,
|
|
26878
|
-
8225,
|
|
26879
|
-
710,
|
|
26880
|
-
8240,
|
|
26881
|
-
352,
|
|
26882
|
-
8249,
|
|
26883
|
-
338,
|
|
26884
|
-
141,
|
|
26885
|
-
381,
|
|
26886
|
-
143,
|
|
26887
|
-
144,
|
|
26888
|
-
8216,
|
|
26889
|
-
8217,
|
|
26890
|
-
8220,
|
|
26891
|
-
8221,
|
|
26892
|
-
8226,
|
|
26893
|
-
8211,
|
|
26894
|
-
8212,
|
|
26895
|
-
732,
|
|
26896
|
-
8482,
|
|
26897
|
-
353,
|
|
26898
|
-
8250,
|
|
26899
|
-
339,
|
|
26900
|
-
157,
|
|
26901
|
-
382,
|
|
26902
|
-
376
|
|
26903
|
-
];
|
|
26904
|
-
function ansiToCode(b, charSet) {
|
|
26905
|
-
if (charSet === 2) {
|
|
26906
|
-
return b;
|
|
26907
|
-
}
|
|
26908
|
-
return b >= 128 && b <= 159 ? CP1252_HIGH2[b - 128] : b;
|
|
26909
|
-
}
|
|
26910
27614
|
function fontAdvances(p, codes) {
|
|
26911
27615
|
const fonts = p.rCtx.fonts;
|
|
26912
27616
|
if (!fonts) {
|