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