emf-converter 4.8.7 → 4.8.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.js +423 -295
- package/dist/browser.mjs +423 -295
- package/dist/index.js +423 -295
- package/dist/index.mjs +423 -295
- package/package.json +1 -1
package/dist/browser.js
CHANGED
|
@@ -27798,10 +27798,10 @@ function parseEmfHeader(view) {
|
|
|
27798
27798
|
};
|
|
27799
27799
|
}
|
|
27800
27800
|
function getRenderableEmfBounds(header) {
|
|
27801
|
-
const boundsW = header.bounds.right - header.bounds.left;
|
|
27802
|
-
const boundsH = header.bounds.bottom - header.bounds.top;
|
|
27801
|
+
const boundsW = header.bounds.right - header.bounds.left + 1;
|
|
27802
|
+
const boundsH = header.bounds.bottom - header.bounds.top + 1;
|
|
27803
27803
|
if (boundsW > 0 && boundsH > 0) {
|
|
27804
|
-
return header.bounds;
|
|
27804
|
+
return { ...header.bounds, right: header.bounds.right + 1, bottom: header.bounds.bottom + 1 };
|
|
27805
27805
|
}
|
|
27806
27806
|
if (header.frameW > 0 && header.frameH > 0) {
|
|
27807
27807
|
emfLog(
|
|
@@ -30833,6 +30833,13 @@ function insetFixBox(box, inset) {
|
|
|
30833
30833
|
}
|
|
30834
30834
|
return framed;
|
|
30835
30835
|
}
|
|
30836
|
+
function sameEllipseRay(l, t, r, b, sx, sy, ex, ey) {
|
|
30837
|
+
const ax = BigInt(2 * sx - l - r);
|
|
30838
|
+
const ay = BigInt(2 * sy - t - b);
|
|
30839
|
+
const bx = BigInt(2 * ex - l - r);
|
|
30840
|
+
const by = BigInt(2 * ey - t - b);
|
|
30841
|
+
return ax * by === ay * bx && ax * bx + ay * by > 0n;
|
|
30842
|
+
}
|
|
30836
30843
|
function handleSetPixelV(rCtx, dataOff, recSize) {
|
|
30837
30844
|
const { ctx, view } = rCtx;
|
|
30838
30845
|
if (recSize >= 20) {
|
|
@@ -31190,7 +31197,9 @@ function handleArcFamily(rCtx, recType, dataOff, recSize) {
|
|
|
31190
31197
|
const rx = Math.abs(r - l) / 2;
|
|
31191
31198
|
const ry = Math.abs(b - t) / 2;
|
|
31192
31199
|
const startAngle = Math.atan2((startY - cyA) / (ry || 1), (startX - cxA) / (rx || 1));
|
|
31193
|
-
const
|
|
31200
|
+
const clockwise = state.arcDirection === 2;
|
|
31201
|
+
const fullEllipse = recType !== EMR_PIE && rx > 0 && ry > 0 && sameEllipseRay(l, t, r, b, startX, startY, endX, endY);
|
|
31202
|
+
const endAngle = fullEllipse ? startAngle + (clockwise ? 2 : -2) * Math.PI : Math.atan2((endY - cyA) / (ry || 1), (endX - cxA) / (rx || 1));
|
|
31194
31203
|
const rotated = hasWorldRotation(rCtx);
|
|
31195
31204
|
const unframed = fixBox(rCtx, l, t, r, b);
|
|
31196
31205
|
const inset = insideFrameInset(rCtx, unframed);
|
|
@@ -31204,13 +31213,18 @@ function handleArcFamily(rCtx, recType, dataOff, recSize) {
|
|
|
31204
31213
|
};
|
|
31205
31214
|
const isArcTo = recType === EMR_ARCTO;
|
|
31206
31215
|
const needsFill = recType === EMR_PIE || recType === EMR_CHORD;
|
|
31207
|
-
const clockwise = state.arcDirection === 2;
|
|
31208
31216
|
const startPoint = rotated ? gmapPoint(rCtx, cxA + rx * Math.cos(startAngle), cyA + ry * Math.sin(startAngle)) : { x: params.cx + params.rx * Math.cos(startAngle), y: params.cy + params.ry * Math.sin(startAngle) };
|
|
31209
31217
|
const build = (c) => {
|
|
31210
31218
|
if (recType === EMR_PIE) {
|
|
31211
31219
|
c.moveTo(params.cx, params.cy);
|
|
31220
|
+
} else if (!isArcTo && inPath) {
|
|
31221
|
+
c.moveTo(startPoint.x, startPoint.y);
|
|
31212
31222
|
}
|
|
31213
31223
|
if (isArcTo) {
|
|
31224
|
+
if (!inPath) {
|
|
31225
|
+
const from = currentFix(rCtx);
|
|
31226
|
+
c.moveTo(from[0] / 16, from[1] / 16);
|
|
31227
|
+
}
|
|
31214
31228
|
c.lineTo(startPoint.x, startPoint.y);
|
|
31215
31229
|
}
|
|
31216
31230
|
c.ellipse(params.cx, params.cy, params.rx, params.ry, params.rotation, startAngle, endAngle, !clockwise);
|
|
@@ -31230,7 +31244,9 @@ function handleArcFamily(rCtx, recType, dataOff, recSize) {
|
|
|
31230
31244
|
const rasterArgs = (immediate = false) => ({
|
|
31231
31245
|
box: inset ? framed : immediate && needsFill ? curvedFixBox(rCtx, l, t, r, b) : unframed,
|
|
31232
31246
|
s: radialOnBox(fixPoint(rCtx, startX, startY)),
|
|
31233
|
-
|
|
31247
|
+
// Device FIX rounding can separate distinct radial points on the
|
|
31248
|
+
// same logical ray. Preserve their proven endpoint identity.
|
|
31249
|
+
e: fullEllipse ? radialOnBox(fixPoint(rCtx, startX, startY)) : radialOnBox(fixPoint(rCtx, endX, endY)),
|
|
31234
31250
|
from: currentFix(rCtx)
|
|
31235
31251
|
});
|
|
31236
31252
|
if (inPath) {
|
|
@@ -35695,15 +35711,243 @@ function handleEmfObjectRecord(rCtx, recType, dataOff, recSize) {
|
|
|
35695
35711
|
}
|
|
35696
35712
|
}
|
|
35697
35713
|
|
|
35714
|
+
// src/wmf-mapping.ts
|
|
35715
|
+
var MM_TEXT = 1;
|
|
35716
|
+
var MM_LOMETRIC = 2;
|
|
35717
|
+
var MM_HIMETRIC = 3;
|
|
35718
|
+
var MM_LOENGLISH = 4;
|
|
35719
|
+
var MM_HIENGLISH = 5;
|
|
35720
|
+
var MM_TWIPS = 6;
|
|
35721
|
+
var MM_ISOTROPIC = 7;
|
|
35722
|
+
var MM_ANISOTROPIC = 8;
|
|
35723
|
+
var DEVICE_DPI = 96;
|
|
35724
|
+
function cloneMapping(m) {
|
|
35725
|
+
return {
|
|
35726
|
+
...m.dpi ? { dpi: { ...m.dpi } } : {},
|
|
35727
|
+
mode: m.mode,
|
|
35728
|
+
winOrg: { ...m.winOrg },
|
|
35729
|
+
winExt: { ...m.winExt },
|
|
35730
|
+
vpOrg: { ...m.vpOrg },
|
|
35731
|
+
vpExt: { ...m.vpExt }
|
|
35732
|
+
};
|
|
35733
|
+
}
|
|
35734
|
+
var METRIC_UNITS_PER_INCH = {
|
|
35735
|
+
[MM_LOMETRIC]: 254,
|
|
35736
|
+
[MM_HIMETRIC]: 2540,
|
|
35737
|
+
[MM_LOENGLISH]: 100,
|
|
35738
|
+
[MM_HIENGLISH]: 1e3,
|
|
35739
|
+
[MM_TWIPS]: 1440
|
|
35740
|
+
};
|
|
35741
|
+
function fixIsotropic(m) {
|
|
35742
|
+
if (m.mode !== MM_ISOTROPIC || !m.winExt.cx || !m.winExt.cy) {
|
|
35743
|
+
return;
|
|
35744
|
+
}
|
|
35745
|
+
const xdim = Math.abs(m.vpExt.cx / m.winExt.cx) / (m.dpi?.x ?? DEVICE_DPI);
|
|
35746
|
+
const ydim = Math.abs(m.vpExt.cy / m.winExt.cy) / (m.dpi?.y ?? DEVICE_DPI);
|
|
35747
|
+
if (xdim > ydim) {
|
|
35748
|
+
const min = m.vpExt.cx >= 0 ? 1 : -1;
|
|
35749
|
+
m.vpExt.cx = Math.floor(m.vpExt.cx * ydim / xdim + 0.5) || min;
|
|
35750
|
+
} else if (ydim > xdim) {
|
|
35751
|
+
const min = m.vpExt.cy >= 0 ? 1 : -1;
|
|
35752
|
+
m.vpExt.cy = Math.floor(m.vpExt.cy * xdim / ydim + 0.5) || min;
|
|
35753
|
+
}
|
|
35754
|
+
}
|
|
35755
|
+
function setMapMode(m, mode) {
|
|
35756
|
+
if (mode < MM_TEXT || mode > MM_ANISOTROPIC) {
|
|
35757
|
+
return;
|
|
35758
|
+
}
|
|
35759
|
+
const units = METRIC_UNITS_PER_INCH[mode === MM_ISOTROPIC ? MM_LOMETRIC : mode];
|
|
35760
|
+
if (mode === MM_TEXT) {
|
|
35761
|
+
m.winExt = { cx: 1, cy: 1 };
|
|
35762
|
+
m.vpExt = { cx: 1, cy: 1 };
|
|
35763
|
+
} else if (units !== void 0 && (mode !== MM_ISOTROPIC || m.mode !== MM_ISOTROPIC)) {
|
|
35764
|
+
m.winExt = { cx: units, cy: units };
|
|
35765
|
+
m.vpExt = { cx: m.dpi?.x ?? DEVICE_DPI, cy: -(m.dpi?.y ?? DEVICE_DPI) };
|
|
35766
|
+
}
|
|
35767
|
+
m.mode = mode;
|
|
35768
|
+
}
|
|
35769
|
+
function extentsSettable(m) {
|
|
35770
|
+
return m.mode === MM_ISOTROPIC || m.mode === MM_ANISOTROPIC;
|
|
35771
|
+
}
|
|
35772
|
+
function setWindowExt(m, cx, cy) {
|
|
35773
|
+
if (!extentsSettable(m) || cx === 0 || cy === 0) {
|
|
35774
|
+
return;
|
|
35775
|
+
}
|
|
35776
|
+
m.winExt = { cx, cy };
|
|
35777
|
+
fixIsotropic(m);
|
|
35778
|
+
}
|
|
35779
|
+
function setViewportExt(m, cx, cy) {
|
|
35780
|
+
if (!extentsSettable(m) || cx === 0 || cy === 0) {
|
|
35781
|
+
return;
|
|
35782
|
+
}
|
|
35783
|
+
m.vpExt = { cx, cy };
|
|
35784
|
+
fixIsotropic(m);
|
|
35785
|
+
}
|
|
35786
|
+
function scaled(v, num, den) {
|
|
35787
|
+
return Math.trunc(v * num / den);
|
|
35788
|
+
}
|
|
35789
|
+
function scaleWindowExt(m, xNum, xDen, yNum, yDen) {
|
|
35790
|
+
if (!extentsSettable(m) || !xDen || !yDen) {
|
|
35791
|
+
return;
|
|
35792
|
+
}
|
|
35793
|
+
const cx = scaled(m.winExt.cx, xNum, xDen);
|
|
35794
|
+
const cy = scaled(m.winExt.cy, yNum, yDen);
|
|
35795
|
+
if (cx === 0 || cy === 0) {
|
|
35796
|
+
return;
|
|
35797
|
+
}
|
|
35798
|
+
m.winExt = { cx, cy };
|
|
35799
|
+
fixIsotropic(m);
|
|
35800
|
+
}
|
|
35801
|
+
function scaleViewportExt(m, xNum, xDen, yNum, yDen) {
|
|
35802
|
+
if (!extentsSettable(m) || !xDen || !yDen) {
|
|
35803
|
+
return;
|
|
35804
|
+
}
|
|
35805
|
+
const cx = scaled(m.vpExt.cx, xNum, xDen);
|
|
35806
|
+
const cy = scaled(m.vpExt.cy, yNum, yDen);
|
|
35807
|
+
if (cx === 0 || cy === 0) {
|
|
35808
|
+
return;
|
|
35809
|
+
}
|
|
35810
|
+
m.vpExt = { cx, cy };
|
|
35811
|
+
fixIsotropic(m);
|
|
35812
|
+
}
|
|
35813
|
+
function applyWmfMapping(rCtx, m, kx, ky, mirrorWidth = 0) {
|
|
35814
|
+
rCtx.wmfLayoutRtl = mirrorWidth > 0;
|
|
35815
|
+
rCtx.useMappingMode = true;
|
|
35816
|
+
rCtx.windowOrg = { x: m.winOrg.x, y: m.winOrg.y };
|
|
35817
|
+
rCtx.windowExt = { cx: m.winExt.cx || 1, cy: m.winExt.cy || 1 };
|
|
35818
|
+
rCtx.viewportOrg = { x: m.vpOrg.x * kx, y: m.vpOrg.y * ky };
|
|
35819
|
+
rCtx.viewportExt = { cx: (m.vpExt.cx || 1) * kx, cy: (m.vpExt.cy || 1) * ky };
|
|
35820
|
+
if (mirrorWidth > 0) {
|
|
35821
|
+
rCtx.viewportOrg.x = mirrorWidth * kx - rCtx.viewportOrg.x;
|
|
35822
|
+
rCtx.viewportExt.cx = -rCtx.viewportExt.cx;
|
|
35823
|
+
}
|
|
35824
|
+
}
|
|
35825
|
+
function scanMappingRecords(view, start) {
|
|
35826
|
+
const out = {
|
|
35827
|
+
mode: null,
|
|
35828
|
+
winExt: null,
|
|
35829
|
+
vpExt: null
|
|
35830
|
+
};
|
|
35831
|
+
let off = start;
|
|
35832
|
+
let guard = 0;
|
|
35833
|
+
while (off + 6 <= view.byteLength && guard++ < 1e6) {
|
|
35834
|
+
const size = view.getUint32(off, true) * 2;
|
|
35835
|
+
const type = view.getUint16(off + 4, true);
|
|
35836
|
+
if (size < 6 || off + size > view.byteLength || type === 0) {
|
|
35837
|
+
break;
|
|
35838
|
+
}
|
|
35839
|
+
const d = off + 6;
|
|
35840
|
+
if (type === 259 && size >= 8 && out.mode === null) {
|
|
35841
|
+
out.mode = view.getUint16(d, true);
|
|
35842
|
+
} else if (type === 524 && size >= 10 && !out.winExt) {
|
|
35843
|
+
out.winExt = { cy: view.getInt16(d, true), cx: view.getInt16(d + 2, true) };
|
|
35844
|
+
} else if (type === 526 && size >= 10 && !out.vpExt) {
|
|
35845
|
+
out.vpExt = { cy: view.getInt16(d, true), cx: view.getInt16(d + 2, true) };
|
|
35846
|
+
}
|
|
35847
|
+
off += size;
|
|
35848
|
+
}
|
|
35849
|
+
return out;
|
|
35850
|
+
}
|
|
35851
|
+
function wmfPlayback(view, header, referenceDpi) {
|
|
35852
|
+
const valid = (v) => typeof v === "number" && Number.isFinite(v) && v > 0 ? v : DEVICE_DPI;
|
|
35853
|
+
const dpi = { x: valid(typeof referenceDpi === "number" ? referenceDpi : referenceDpi?.x), y: valid(typeof referenceDpi === "number" ? referenceDpi : referenceDpi?.y) };
|
|
35854
|
+
const density = referenceDpi === void 0 ? {} : { dpi };
|
|
35855
|
+
const bw = header.boundsRight - header.boundsLeft;
|
|
35856
|
+
const bh = header.boundsBottom - header.boundsTop;
|
|
35857
|
+
if (header.placeable !== false) {
|
|
35858
|
+
const inch = header.unitsPerInch > 0 ? header.unitsPerInch : DEVICE_DPI;
|
|
35859
|
+
const width2 = Math.max(1, Math.round(Math.abs(bw) * dpi.x / inch));
|
|
35860
|
+
const height2 = Math.max(1, Math.round(Math.abs(bh) * dpi.y / inch));
|
|
35861
|
+
return {
|
|
35862
|
+
width: width2,
|
|
35863
|
+
height: height2,
|
|
35864
|
+
mapping: {
|
|
35865
|
+
...density,
|
|
35866
|
+
mode: MM_ANISOTROPIC,
|
|
35867
|
+
winOrg: { x: header.boundsLeft, y: header.boundsTop },
|
|
35868
|
+
winExt: { cx: bw || 1, cy: bh || 1 },
|
|
35869
|
+
vpOrg: { x: 0, y: 0 },
|
|
35870
|
+
vpExt: { cx: width2, cy: height2 }
|
|
35871
|
+
}
|
|
35872
|
+
};
|
|
35873
|
+
}
|
|
35874
|
+
const scan = scanMappingRecords(view, header.headerSize);
|
|
35875
|
+
const scalable = scan.mode === MM_ISOTROPIC || scan.mode === MM_ANISOTROPIC;
|
|
35876
|
+
const ext = scalable && scan.vpExt ? scan.vpExt : scan.winExt;
|
|
35877
|
+
const width = ext ? Math.abs(ext.cx) : Math.abs(bw);
|
|
35878
|
+
const height = ext ? Math.abs(ext.cy) : Math.abs(bh);
|
|
35879
|
+
const w = Math.max(1, width || 1);
|
|
35880
|
+
const h = Math.max(1, height || 1);
|
|
35881
|
+
return {
|
|
35882
|
+
width: w,
|
|
35883
|
+
height: h,
|
|
35884
|
+
mapping: {
|
|
35885
|
+
...density,
|
|
35886
|
+
mode: MM_ANISOTROPIC,
|
|
35887
|
+
winOrg: { x: 0, y: 0 },
|
|
35888
|
+
winExt: { cx: w, cy: h },
|
|
35889
|
+
vpOrg: { x: 0, y: 0 },
|
|
35890
|
+
vpExt: { cx: w, cy: h }
|
|
35891
|
+
}
|
|
35892
|
+
};
|
|
35893
|
+
}
|
|
35894
|
+
|
|
35698
35895
|
// src/emf-gdi-transform-handlers.ts
|
|
35896
|
+
function emfDeviceDpi(view) {
|
|
35897
|
+
if (view.byteLength < 88 || view.getUint32(0, true) !== 1) {
|
|
35898
|
+
return void 0;
|
|
35899
|
+
}
|
|
35900
|
+
const devW = view.getInt32(72, true);
|
|
35901
|
+
const devH = view.getInt32(76, true);
|
|
35902
|
+
const mmW = view.getInt32(80, true);
|
|
35903
|
+
const mmH = view.getInt32(84, true);
|
|
35904
|
+
if (devW <= 0 || devH <= 0 || mmW <= 0 || mmH <= 0) {
|
|
35905
|
+
return void 0;
|
|
35906
|
+
}
|
|
35907
|
+
return { x: devW * 25.4 / mmW, y: devH * 25.4 / mmH };
|
|
35908
|
+
}
|
|
35909
|
+
function emfMapping(r) {
|
|
35910
|
+
const dpi = emfDeviceDpi(r.view);
|
|
35911
|
+
return {
|
|
35912
|
+
...dpi ? { dpi } : {},
|
|
35913
|
+
mode: r.mapMode ?? MM_TEXT,
|
|
35914
|
+
winOrg: r.windowOrg,
|
|
35915
|
+
winExt: { ...r.windowExt },
|
|
35916
|
+
vpOrg: r.viewportOrg,
|
|
35917
|
+
vpExt: { ...r.viewportExt }
|
|
35918
|
+
};
|
|
35919
|
+
}
|
|
35920
|
+
function storeMapping(r, m) {
|
|
35921
|
+
r.mapMode = m.mode;
|
|
35922
|
+
r.windowExt = m.winExt;
|
|
35923
|
+
r.viewportExt = m.vpExt;
|
|
35924
|
+
}
|
|
35925
|
+
function setExtent(r, viewport, cx, cy) {
|
|
35926
|
+
const m = emfMapping(r);
|
|
35927
|
+
if (!extentsSettable(m) || cx === 0 || cy === 0) {
|
|
35928
|
+
return;
|
|
35929
|
+
}
|
|
35930
|
+
if (viewport) {
|
|
35931
|
+
m.vpExt = { cx, cy };
|
|
35932
|
+
} else {
|
|
35933
|
+
m.winExt = { cx, cy };
|
|
35934
|
+
}
|
|
35935
|
+
fixIsotropic(m);
|
|
35936
|
+
storeMapping(r, m);
|
|
35937
|
+
activateGdiMappingMode(r);
|
|
35938
|
+
}
|
|
35939
|
+
function scaleExtent(r, viewport, xNum, xDenom, yNum, yDenom) {
|
|
35940
|
+
const ext = viewport ? r.viewportExt : r.windowExt;
|
|
35941
|
+
const cx = xDenom !== 0 ? Math.round(ext.cx * xNum / xDenom) : ext.cx;
|
|
35942
|
+
const cy = yDenom !== 0 ? Math.round(ext.cy * yNum / yDenom) : ext.cy;
|
|
35943
|
+
setExtent(r, viewport, cx, cy);
|
|
35944
|
+
}
|
|
35699
35945
|
function handleCoordinateRecord(rCtx, recType, dataOff, recSize) {
|
|
35700
35946
|
const { view } = rCtx;
|
|
35701
35947
|
switch (recType) {
|
|
35702
35948
|
case EMR_SETWINDOWEXTEX: {
|
|
35703
35949
|
if (recSize >= 16) {
|
|
35704
|
-
rCtx.
|
|
35705
|
-
rCtx.windowExt.cy = view.getInt32(dataOff + 4, true);
|
|
35706
|
-
activateGdiMappingMode(rCtx);
|
|
35950
|
+
setExtent(rCtx, false, view.getInt32(dataOff, true), view.getInt32(dataOff + 4, true));
|
|
35707
35951
|
}
|
|
35708
35952
|
return true;
|
|
35709
35953
|
}
|
|
@@ -35717,9 +35961,7 @@ function handleCoordinateRecord(rCtx, recType, dataOff, recSize) {
|
|
|
35717
35961
|
}
|
|
35718
35962
|
case EMR_SETVIEWPORTEXTEX: {
|
|
35719
35963
|
if (recSize >= 16) {
|
|
35720
|
-
rCtx.
|
|
35721
|
-
rCtx.viewportExt.cy = view.getInt32(dataOff + 4, true);
|
|
35722
|
-
activateGdiMappingMode(rCtx);
|
|
35964
|
+
setExtent(rCtx, true, view.getInt32(dataOff, true), view.getInt32(dataOff + 4, true));
|
|
35723
35965
|
}
|
|
35724
35966
|
return true;
|
|
35725
35967
|
}
|
|
@@ -35734,41 +35976,26 @@ function handleCoordinateRecord(rCtx, recType, dataOff, recSize) {
|
|
|
35734
35976
|
case EMR_SETMAPMODE: {
|
|
35735
35977
|
if (recSize >= 12) {
|
|
35736
35978
|
const mode = view.getUint32(dataOff, true);
|
|
35737
|
-
if (mode
|
|
35979
|
+
if (mode >= MM_TEXT && mode <= MM_ANISOTROPIC) {
|
|
35980
|
+
const m = emfMapping(rCtx);
|
|
35981
|
+
setMapMode(m, mode);
|
|
35982
|
+
storeMapping(rCtx, m);
|
|
35738
35983
|
activateGdiMappingMode(rCtx);
|
|
35739
35984
|
}
|
|
35740
35985
|
}
|
|
35741
35986
|
return true;
|
|
35742
35987
|
}
|
|
35743
|
-
case EMR_SCALEVIEWPORTEXTEX:
|
|
35744
|
-
if (recSize >= 24) {
|
|
35745
|
-
const xNum = view.getInt32(dataOff, true);
|
|
35746
|
-
const xDenom = view.getInt32(dataOff + 4, true);
|
|
35747
|
-
const yNum = view.getInt32(dataOff + 8, true);
|
|
35748
|
-
const yDenom = view.getInt32(dataOff + 12, true);
|
|
35749
|
-
if (xDenom !== 0) {
|
|
35750
|
-
rCtx.viewportExt.cx = Math.round(rCtx.viewportExt.cx * xNum / xDenom);
|
|
35751
|
-
}
|
|
35752
|
-
if (yDenom !== 0) {
|
|
35753
|
-
rCtx.viewportExt.cy = Math.round(rCtx.viewportExt.cy * yNum / yDenom);
|
|
35754
|
-
}
|
|
35755
|
-
activateGdiMappingMode(rCtx);
|
|
35756
|
-
}
|
|
35757
|
-
return true;
|
|
35758
|
-
}
|
|
35988
|
+
case EMR_SCALEVIEWPORTEXTEX:
|
|
35759
35989
|
case EMR_SCALEWINDOWEXTEX: {
|
|
35760
35990
|
if (recSize >= 24) {
|
|
35761
|
-
|
|
35762
|
-
|
|
35763
|
-
|
|
35764
|
-
|
|
35765
|
-
|
|
35766
|
-
|
|
35767
|
-
|
|
35768
|
-
|
|
35769
|
-
rCtx.windowExt.cy = Math.round(rCtx.windowExt.cy * yNum / yDenom);
|
|
35770
|
-
}
|
|
35771
|
-
activateGdiMappingMode(rCtx);
|
|
35991
|
+
scaleExtent(
|
|
35992
|
+
rCtx,
|
|
35993
|
+
recType === EMR_SCALEVIEWPORTEXTEX,
|
|
35994
|
+
view.getInt32(dataOff, true),
|
|
35995
|
+
view.getInt32(dataOff + 4, true),
|
|
35996
|
+
view.getInt32(dataOff + 8, true),
|
|
35997
|
+
view.getInt32(dataOff + 12, true)
|
|
35998
|
+
);
|
|
35772
35999
|
}
|
|
35773
36000
|
return true;
|
|
35774
36001
|
}
|
|
@@ -35908,6 +36135,15 @@ function handleEmfGdiStateRecord(rCtx, recType, _offset, dataOff, recSize) {
|
|
|
35908
36135
|
}
|
|
35909
36136
|
rCtx.clipStack ?? (rCtx.clipStack = []);
|
|
35910
36137
|
rCtx.clipStack.push({ region: rCtx.clipRegion ?? null });
|
|
36138
|
+
rCtx.mappingStack ?? (rCtx.mappingStack = []);
|
|
36139
|
+
rCtx.mappingStack.push({
|
|
36140
|
+
mapMode: rCtx.mapMode,
|
|
36141
|
+
windowOrg: { ...rCtx.windowOrg },
|
|
36142
|
+
windowExt: { ...rCtx.windowExt },
|
|
36143
|
+
viewportOrg: { ...rCtx.viewportOrg },
|
|
36144
|
+
viewportExt: { ...rCtx.viewportExt },
|
|
36145
|
+
useMappingMode: rCtx.useMappingMode
|
|
36146
|
+
});
|
|
35911
36147
|
rCtx.stateStack.push(cloneState(state));
|
|
35912
36148
|
ctx.save();
|
|
35913
36149
|
if (rCtx.clipRegion) {
|
|
@@ -35917,23 +36153,31 @@ function handleEmfGdiStateRecord(rCtx, recType, _offset, dataOff, recSize) {
|
|
|
35917
36153
|
}
|
|
35918
36154
|
case EMR_RESTOREDC: {
|
|
35919
36155
|
if (recSize >= 12) {
|
|
35920
|
-
while (rCtx.clipSaveDepth > 0) {
|
|
35921
|
-
ctx.restore();
|
|
35922
|
-
rCtx.clipSaveDepth--;
|
|
35923
|
-
}
|
|
35924
36156
|
let rel = view.getInt32(dataOff, true);
|
|
35925
36157
|
if (rel < 0) {
|
|
35926
36158
|
rel = rCtx.stateStack.length + rel + 1;
|
|
35927
36159
|
}
|
|
35928
|
-
|
|
36160
|
+
if (rel < 1 || rel > rCtx.stateStack.length) {
|
|
36161
|
+
return true;
|
|
36162
|
+
}
|
|
36163
|
+
while (rCtx.clipSaveDepth > 0) {
|
|
36164
|
+
ctx.restore();
|
|
36165
|
+
rCtx.clipSaveDepth--;
|
|
36166
|
+
}
|
|
36167
|
+
while (rCtx.stateStack.length > rel) {
|
|
35929
36168
|
rCtx.stateStack.pop();
|
|
35930
36169
|
rCtx.clipStack?.pop();
|
|
36170
|
+
rCtx.mappingStack?.pop();
|
|
35931
36171
|
ctx.restore();
|
|
35932
36172
|
}
|
|
35933
36173
|
const restored = rCtx.stateStack.pop();
|
|
35934
36174
|
if (restored) {
|
|
35935
36175
|
const clipSnapshot = rCtx.clipStack?.pop();
|
|
36176
|
+
const mappingSnapshot = rCtx.mappingStack?.pop();
|
|
35936
36177
|
Object.assign(state, restored);
|
|
36178
|
+
if (mappingSnapshot) {
|
|
36179
|
+
Object.assign(rCtx, mappingSnapshot);
|
|
36180
|
+
}
|
|
35937
36181
|
ctx.restore();
|
|
35938
36182
|
rCtx.clipRegion = clipSnapshot?.region ?? null;
|
|
35939
36183
|
if (rCtx.clipRegion) {
|
|
@@ -36743,24 +36987,22 @@ function rgbaToHex(c) {
|
|
|
36743
36987
|
}
|
|
36744
36988
|
return /^#[0-9a-f]{6}$/i.test(c) ? c : null;
|
|
36745
36989
|
}
|
|
36746
|
-
function
|
|
36990
|
+
function realizePlusEngineFont(rCtx, font, paint, brushSampler2) {
|
|
36747
36991
|
const fonts = rCtx.fonts;
|
|
36748
36992
|
const color = typeof paint === "string" ? rgbaToHex(paint) : null;
|
|
36749
|
-
const
|
|
36750
|
-
const graySmooth =
|
|
36993
|
+
const hint = rCtx.textRenderingHint ?? 0;
|
|
36994
|
+
const graySmooth = hint === 3 || hint === 4 || hint === 5;
|
|
36751
36995
|
const solidViaCoverage = !!color && graySmooth && !isSvgContext(rCtx.ctx);
|
|
36752
36996
|
const sampler = isSvgContext(rCtx.ctx) ? null : solidViaCoverage ? solidSampler(cssColorToArgb(paint) ?? 4278190080) : color ? null : brushSampler2;
|
|
36753
36997
|
const unit = font.unit ?? 0;
|
|
36754
|
-
if (!fonts || !color && !sampler ||
|
|
36755
|
-
return
|
|
36998
|
+
if (!fonts || !color && !sampler || unit !== 0 && unit !== 2) {
|
|
36999
|
+
return null;
|
|
36756
37000
|
}
|
|
36757
37001
|
const m = plusWorldMatrix(rCtx);
|
|
36758
37002
|
if (m[1] !== 0 || m[2] !== 0 || m[0] <= 0 || m[3] <= 0) {
|
|
36759
|
-
return
|
|
37003
|
+
return null;
|
|
36760
37004
|
}
|
|
36761
37005
|
const emPx = font.emSize * m[3];
|
|
36762
|
-
const hint = rCtx.textRenderingHint ?? 0;
|
|
36763
|
-
const quality = HINT_QUALITY[hint] ?? NONANTIALIASED_QUALITY;
|
|
36764
37006
|
const spec = {
|
|
36765
37007
|
face: font.family,
|
|
36766
37008
|
height: -Math.round(emPx),
|
|
@@ -36769,7 +37011,7 @@ function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, paint, ali
|
|
|
36769
37011
|
italic: (font.flags & 2) !== 0,
|
|
36770
37012
|
charSet: 1,
|
|
36771
37013
|
pitchAndFamily: 0,
|
|
36772
|
-
quality,
|
|
37014
|
+
quality: HINT_QUALITY[hint] ?? NONANTIALIASED_QUALITY,
|
|
36773
37015
|
unhinted: hint === 2 || hint === 4,
|
|
36774
37016
|
// AntiAlias ignores the font's gasp table (measured: Arial 16 px is
|
|
36775
37017
|
// grayscale there, but single-bit under AntiAliasGridFit, as in GDI).
|
|
@@ -36777,31 +37019,32 @@ function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, paint, ali
|
|
|
36777
37019
|
};
|
|
36778
37020
|
const realized = fonts.realize(spec, rCtx.fontFamilyMap);
|
|
36779
37021
|
if (!realized) {
|
|
36780
|
-
return
|
|
36781
|
-
}
|
|
36782
|
-
const ttf = realized.ttf;
|
|
36783
|
-
const unhinted = spec.unhinted === true;
|
|
36784
|
-
const exactAscent = emPx * ttf.winAscent / ttf.unitsPerEm;
|
|
36785
|
-
const ascent = unhinted ? exactAscent : Math.ceil(exactAscent);
|
|
36786
|
-
const x = m[0] * layoutX + m[4] + emPx * (format?.leadingMargin ?? PLUS_LEADING_EM);
|
|
36787
|
-
const y = m[3] * layoutY + m[5] + ascent;
|
|
36788
|
-
const codes = [];
|
|
36789
|
-
for (let i = 0; i < text.length; i++) {
|
|
36790
|
-
codes.push(text.charCodeAt(i));
|
|
37022
|
+
return null;
|
|
36791
37023
|
}
|
|
36792
|
-
|
|
36793
|
-
|
|
36794
|
-
|
|
36795
|
-
|
|
36796
|
-
|
|
36797
|
-
|
|
36798
|
-
|
|
36799
|
-
|
|
36800
|
-
|
|
36801
|
-
|
|
36802
|
-
|
|
36803
|
-
|
|
36804
|
-
|
|
37024
|
+
return {
|
|
37025
|
+
realized,
|
|
37026
|
+
emPx,
|
|
37027
|
+
m,
|
|
37028
|
+
unhinted: spec.unhinted === true,
|
|
37029
|
+
color,
|
|
37030
|
+
sampler,
|
|
37031
|
+
solidViaCoverage,
|
|
37032
|
+
underline: (font.flags & 4) !== 0,
|
|
37033
|
+
strikeOut: (font.flags & 8) !== 0
|
|
37034
|
+
};
|
|
37035
|
+
}
|
|
37036
|
+
function paintPlusEngineRun(rCtx, ef, run) {
|
|
37037
|
+
const base = {
|
|
37038
|
+
...run,
|
|
37039
|
+
textAlign: 24,
|
|
37040
|
+
bkColor: "#ffffff",
|
|
37041
|
+
bkMode: 1,
|
|
37042
|
+
options: 0,
|
|
37043
|
+
rect: null,
|
|
37044
|
+
matrix: null
|
|
37045
|
+
};
|
|
37046
|
+
if ((!ef.color || ef.solidViaCoverage) && ef.sampler) {
|
|
37047
|
+
const cov = gdiTextCoverage(ef.realized, { ...base});
|
|
36805
37048
|
if (!cov) {
|
|
36806
37049
|
return true;
|
|
36807
37050
|
}
|
|
@@ -36811,7 +37054,7 @@ function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, paint, ali
|
|
|
36811
37054
|
}
|
|
36812
37055
|
return compositeBrushCoverage(
|
|
36813
37056
|
rCtx,
|
|
36814
|
-
sampler,
|
|
37057
|
+
ef.sampler,
|
|
36815
37058
|
{ x: cov.x, y: cov.y, w: cov.width, h: cov.height },
|
|
36816
37059
|
cov.data,
|
|
36817
37060
|
cov.channels,
|
|
@@ -36819,25 +37062,82 @@ function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, paint, ali
|
|
|
36819
37062
|
cov.channels === 3 ? gamma : 1
|
|
36820
37063
|
);
|
|
36821
37064
|
}
|
|
36822
|
-
paintGdiTextRun(
|
|
36823
|
-
|
|
36824
|
-
|
|
36825
|
-
|
|
36826
|
-
|
|
36827
|
-
|
|
36828
|
-
dy: null,
|
|
36829
|
-
textAlign: 24,
|
|
36830
|
-
textColor: color,
|
|
36831
|
-
bkColor: "#ffffff",
|
|
36832
|
-
bkMode: 1,
|
|
36833
|
-
options: 0,
|
|
36834
|
-
rect: null,
|
|
36835
|
-
matrix: null,
|
|
36836
|
-
underline: (font.flags & 4) !== 0,
|
|
36837
|
-
strikeOut: (font.flags & 8) !== 0
|
|
36838
|
-
}, rCtx.fontFamilyMap);
|
|
37065
|
+
paintGdiTextRun(
|
|
37066
|
+
rCtx.ctx,
|
|
37067
|
+
ef.realized,
|
|
37068
|
+
{ ...base, textColor: ef.color, underline: ef.underline, strikeOut: ef.strikeOut },
|
|
37069
|
+
rCtx.fontFamilyMap
|
|
37070
|
+
);
|
|
36839
37071
|
return true;
|
|
36840
37072
|
}
|
|
37073
|
+
function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, paint, alignment, format, brushSampler2 = null) {
|
|
37074
|
+
if (alignment !== 0) {
|
|
37075
|
+
return false;
|
|
37076
|
+
}
|
|
37077
|
+
const ef = realizePlusEngineFont(rCtx, font, paint, brushSampler2);
|
|
37078
|
+
if (!ef) {
|
|
37079
|
+
return false;
|
|
37080
|
+
}
|
|
37081
|
+
const { realized, emPx, m, unhinted } = ef;
|
|
37082
|
+
const ttf = realized.ttf;
|
|
37083
|
+
const exactAscent = emPx * ttf.winAscent / ttf.unitsPerEm;
|
|
37084
|
+
const ascent = unhinted ? exactAscent : Math.ceil(exactAscent);
|
|
37085
|
+
const x = m[0] * layoutX + m[4] + emPx * (format?.leadingMargin ?? PLUS_LEADING_EM);
|
|
37086
|
+
const y = m[3] * layoutY + m[5] + ascent;
|
|
37087
|
+
const codes = [];
|
|
37088
|
+
for (let i = 0; i < text.length; i++) {
|
|
37089
|
+
codes.push(text.charCodeAt(i));
|
|
37090
|
+
}
|
|
37091
|
+
const tracking = format?.tracking ?? PLUS_DEFAULT_TRACKING;
|
|
37092
|
+
const dx = unhinted ? codes.map((c) => realized.advance(realized.glyphIndex(c)) * tracking) : null;
|
|
37093
|
+
return paintPlusEngineRun(rCtx, ef, { codes, glyphIndices: false, x, y, dx, dy: null });
|
|
37094
|
+
}
|
|
37095
|
+
var DRIVER_STRING_CMAP_LOOKUP = 1;
|
|
37096
|
+
var DRIVER_STRING_VERTICAL = 2;
|
|
37097
|
+
var DRIVER_STRING_REALIZED_ADVANCE = 4;
|
|
37098
|
+
function drawPlusDriverString(rCtx, recFlags, brushVal, font, codes, positions, options2) {
|
|
37099
|
+
const cmap = (options2 & DRIVER_STRING_CMAP_LOOKUP) !== 0;
|
|
37100
|
+
const realizedAdvance = (options2 & DRIVER_STRING_REALIZED_ADVANCE) !== 0;
|
|
37101
|
+
if (!(options2 & DRIVER_STRING_VERTICAL)) {
|
|
37102
|
+
const paint = resolveBrushPaint(rCtx, recFlags, brushVal);
|
|
37103
|
+
const ef = realizePlusEngineFont(rCtx, font, paint, rCtx.fonts ? deviceBrushSampler(rCtx, recFlags, brushVal) : null);
|
|
37104
|
+
if (ef) {
|
|
37105
|
+
const { m } = ef;
|
|
37106
|
+
const dev = positions.map((p) => ({ x: m[0] * p.x + m[4], y: m[3] * p.y + m[5] }));
|
|
37107
|
+
const step = (axis) => dev.map((p, i) => i + 1 < dev.length ? dev[i + 1][axis] - p[axis] : 0);
|
|
37108
|
+
paintPlusEngineRun(rCtx, ef, {
|
|
37109
|
+
codes,
|
|
37110
|
+
glyphIndices: !cmap,
|
|
37111
|
+
x: dev[0].x,
|
|
37112
|
+
y: dev[0].y,
|
|
37113
|
+
dx: realizedAdvance ? null : step("x"),
|
|
37114
|
+
dy: realizedAdvance ? null : step("y")
|
|
37115
|
+
});
|
|
37116
|
+
return;
|
|
37117
|
+
}
|
|
37118
|
+
}
|
|
37119
|
+
if (!cmap) {
|
|
37120
|
+
return;
|
|
37121
|
+
}
|
|
37122
|
+
const { ctx } = rCtx;
|
|
37123
|
+
const bold = font.flags & 1 ? "bold " : "";
|
|
37124
|
+
const italic = font.flags & 2 ? "italic " : "";
|
|
37125
|
+
const family = mapFontFamily(font.family, rCtx.fontFamilyMap);
|
|
37126
|
+
const setFont = () => {
|
|
37127
|
+
ctx.font = `${italic}${bold}${font.emSize}px ${family}`;
|
|
37128
|
+
ctx.textBaseline = "alphabetic";
|
|
37129
|
+
ctx.textAlign = "left";
|
|
37130
|
+
};
|
|
37131
|
+
if (realizedAdvance) {
|
|
37132
|
+
setFont();
|
|
37133
|
+
fillPlusText(rCtx, recFlags, brushVal, String.fromCharCode(...codes), positions[0].x, positions[0].y, font.emSize);
|
|
37134
|
+
return;
|
|
37135
|
+
}
|
|
37136
|
+
for (let i = 0; i < codes.length; i++) {
|
|
37137
|
+
setFont();
|
|
37138
|
+
fillPlusText(rCtx, recFlags, brushVal, String.fromCharCode(codes[i]), positions[i].x, positions[i].y, font.emSize);
|
|
37139
|
+
}
|
|
37140
|
+
}
|
|
36841
37141
|
function handleEmfPlusTextImageRecord(rCtx, recType, recFlags, dataOff, recDataSize) {
|
|
36842
37142
|
const { ctx, view, objectTable } = rCtx;
|
|
36843
37143
|
switch (recType) {
|
|
@@ -36921,24 +37221,31 @@ function handleEmfPlusTextImageRecord(rCtx, recType, recFlags, dataOff, recDataS
|
|
|
36921
37221
|
case EMFPLUS_DRAWDRIVERSTRING: {
|
|
36922
37222
|
if (recDataSize >= 16) {
|
|
36923
37223
|
const brushVal = view.getUint32(dataOff, true);
|
|
37224
|
+
const options2 = view.getUint32(dataOff + 4, true);
|
|
37225
|
+
const matrixPresent = view.getUint32(dataOff + 8, true) !== 0;
|
|
36924
37226
|
const glyphCount = view.getUint32(dataOff + 12, true);
|
|
36925
|
-
const
|
|
36926
|
-
const font = objectTable.get(fontId);
|
|
37227
|
+
const font = objectTable.get(recFlags & 255);
|
|
36927
37228
|
const glyphsOff = dataOff + 16;
|
|
36928
37229
|
const posOff = glyphsOff + glyphCount * 2;
|
|
36929
|
-
const
|
|
36930
|
-
if (glyphCount > 0 && glyphCount < 1e5 &&
|
|
36931
|
-
const
|
|
36932
|
-
|
|
36933
|
-
|
|
36934
|
-
|
|
36935
|
-
|
|
36936
|
-
|
|
36937
|
-
|
|
36938
|
-
|
|
36939
|
-
const
|
|
36940
|
-
|
|
36941
|
-
|
|
37230
|
+
const matrixOff = posOff + glyphCount * 8;
|
|
37231
|
+
if (glyphCount > 0 && glyphCount < 1e5 && matrixOff + (matrixPresent ? 24 : 0) <= dataOff + recDataSize && font && font.kind === "plus-font") {
|
|
37232
|
+
const codes = [];
|
|
37233
|
+
const positions = [];
|
|
37234
|
+
for (let i = 0; i < glyphCount; i++) {
|
|
37235
|
+
codes.push(view.getUint16(glyphsOff + i * 2, true));
|
|
37236
|
+
positions.push({ x: view.getFloat32(posOff + i * 8, true), y: view.getFloat32(posOff + i * 8 + 4, true) });
|
|
37237
|
+
}
|
|
37238
|
+
const world = rCtx.worldTransform;
|
|
37239
|
+
if (matrixPresent) {
|
|
37240
|
+
const xf = [0, 4, 8, 12, 16, 20].map((k) => view.getFloat32(matrixOff + k, true));
|
|
37241
|
+
if (xf.every(Number.isFinite)) {
|
|
37242
|
+
rCtx.worldTransform = mulMatrix(world, xf);
|
|
37243
|
+
}
|
|
37244
|
+
}
|
|
37245
|
+
try {
|
|
37246
|
+
drawPlusDriverString(rCtx, recFlags, brushVal, font, codes, positions, options2);
|
|
37247
|
+
} finally {
|
|
37248
|
+
rCtx.worldTransform = world;
|
|
36942
37249
|
}
|
|
36943
37250
|
}
|
|
36944
37251
|
}
|
|
@@ -37717,7 +38024,7 @@ function parseEmfPlusRegionObject(view, off, maxLen) {
|
|
|
37717
38024
|
}
|
|
37718
38025
|
view.getUint32(off, true);
|
|
37719
38026
|
const regionNodeCount = view.getUint32(off + 4, true);
|
|
37720
|
-
if (regionNodeCount
|
|
38027
|
+
if (regionNodeCount > 1e5) {
|
|
37721
38028
|
return null;
|
|
37722
38029
|
}
|
|
37723
38030
|
const endOff = off + maxLen;
|
|
@@ -38032,9 +38339,11 @@ function replayEmfRecords(view, ctx, bounds, canvasW, canvasH, dpiScale = 1, rep
|
|
|
38032
38339
|
// canvas like every other device coordinate (bounds' top-left to the
|
|
38033
38340
|
// canvas origin, scaled by sx/sy); see `deviceToCanvas`.
|
|
38034
38341
|
windowOrg: { x: 0, y: 0 },
|
|
38035
|
-
windowExt: { cx:
|
|
38342
|
+
windowExt: { cx: 1, cy: 1 },
|
|
38036
38343
|
viewportOrg: { x: 0, y: 0 },
|
|
38037
|
-
viewportExt: { cx:
|
|
38344
|
+
viewportExt: { cx: 1, cy: 1 },
|
|
38345
|
+
mapMode: 1,
|
|
38346
|
+
// MM_TEXT: the default DC uses one-to-one page/device units.
|
|
38038
38347
|
useMappingMode: false,
|
|
38039
38348
|
deviceToCanvas: true,
|
|
38040
38349
|
clipSaveDepth: 0,
|
|
@@ -38231,187 +38540,6 @@ function extractEmbeddedEmf(view, start) {
|
|
|
38231
38540
|
return out.buffer;
|
|
38232
38541
|
}
|
|
38233
38542
|
|
|
38234
|
-
// src/wmf-mapping.ts
|
|
38235
|
-
var MM_TEXT = 1;
|
|
38236
|
-
var MM_LOMETRIC = 2;
|
|
38237
|
-
var MM_HIMETRIC = 3;
|
|
38238
|
-
var MM_LOENGLISH = 4;
|
|
38239
|
-
var MM_HIENGLISH = 5;
|
|
38240
|
-
var MM_TWIPS = 6;
|
|
38241
|
-
var MM_ISOTROPIC = 7;
|
|
38242
|
-
var MM_ANISOTROPIC = 8;
|
|
38243
|
-
var DEVICE_DPI = 96;
|
|
38244
|
-
function cloneMapping(m) {
|
|
38245
|
-
return {
|
|
38246
|
-
...m.dpi ? { dpi: { ...m.dpi } } : {},
|
|
38247
|
-
mode: m.mode,
|
|
38248
|
-
winOrg: { ...m.winOrg },
|
|
38249
|
-
winExt: { ...m.winExt },
|
|
38250
|
-
vpOrg: { ...m.vpOrg },
|
|
38251
|
-
vpExt: { ...m.vpExt }
|
|
38252
|
-
};
|
|
38253
|
-
}
|
|
38254
|
-
var METRIC_UNITS_PER_INCH = {
|
|
38255
|
-
[MM_LOMETRIC]: 254,
|
|
38256
|
-
[MM_HIMETRIC]: 2540,
|
|
38257
|
-
[MM_LOENGLISH]: 100,
|
|
38258
|
-
[MM_HIENGLISH]: 1e3,
|
|
38259
|
-
[MM_TWIPS]: 1440
|
|
38260
|
-
};
|
|
38261
|
-
function fixIsotropic(m) {
|
|
38262
|
-
if (m.mode !== MM_ISOTROPIC || !m.winExt.cx || !m.winExt.cy) {
|
|
38263
|
-
return;
|
|
38264
|
-
}
|
|
38265
|
-
const xdim = Math.abs(m.vpExt.cx / m.winExt.cx) / (m.dpi?.x ?? DEVICE_DPI);
|
|
38266
|
-
const ydim = Math.abs(m.vpExt.cy / m.winExt.cy) / (m.dpi?.y ?? DEVICE_DPI);
|
|
38267
|
-
if (xdim > ydim) {
|
|
38268
|
-
const min = m.vpExt.cx >= 0 ? 1 : -1;
|
|
38269
|
-
m.vpExt.cx = Math.floor(m.vpExt.cx * ydim / xdim + 0.5) || min;
|
|
38270
|
-
} else if (ydim > xdim) {
|
|
38271
|
-
const min = m.vpExt.cy >= 0 ? 1 : -1;
|
|
38272
|
-
m.vpExt.cy = Math.floor(m.vpExt.cy * xdim / ydim + 0.5) || min;
|
|
38273
|
-
}
|
|
38274
|
-
}
|
|
38275
|
-
function setMapMode(m, mode) {
|
|
38276
|
-
if (mode < MM_TEXT || mode > MM_ANISOTROPIC) {
|
|
38277
|
-
return;
|
|
38278
|
-
}
|
|
38279
|
-
const units = METRIC_UNITS_PER_INCH[mode === MM_ISOTROPIC ? MM_LOMETRIC : mode];
|
|
38280
|
-
if (mode === MM_TEXT) {
|
|
38281
|
-
m.winExt = { cx: 1, cy: 1 };
|
|
38282
|
-
m.vpExt = { cx: 1, cy: 1 };
|
|
38283
|
-
} else if (units !== void 0 && (mode !== MM_ISOTROPIC || m.mode !== MM_ISOTROPIC)) {
|
|
38284
|
-
m.winExt = { cx: units, cy: units };
|
|
38285
|
-
m.vpExt = { cx: m.dpi?.x ?? DEVICE_DPI, cy: -(m.dpi?.y ?? DEVICE_DPI) };
|
|
38286
|
-
}
|
|
38287
|
-
m.mode = mode;
|
|
38288
|
-
}
|
|
38289
|
-
function extentsSettable(m) {
|
|
38290
|
-
return m.mode === MM_ISOTROPIC || m.mode === MM_ANISOTROPIC;
|
|
38291
|
-
}
|
|
38292
|
-
function setWindowExt(m, cx, cy) {
|
|
38293
|
-
if (!extentsSettable(m) || cx === 0 || cy === 0) {
|
|
38294
|
-
return;
|
|
38295
|
-
}
|
|
38296
|
-
m.winExt = { cx, cy };
|
|
38297
|
-
fixIsotropic(m);
|
|
38298
|
-
}
|
|
38299
|
-
function setViewportExt(m, cx, cy) {
|
|
38300
|
-
if (!extentsSettable(m) || cx === 0 || cy === 0) {
|
|
38301
|
-
return;
|
|
38302
|
-
}
|
|
38303
|
-
m.vpExt = { cx, cy };
|
|
38304
|
-
fixIsotropic(m);
|
|
38305
|
-
}
|
|
38306
|
-
function scaled(v, num, den) {
|
|
38307
|
-
return Math.trunc(v * num / den);
|
|
38308
|
-
}
|
|
38309
|
-
function scaleWindowExt(m, xNum, xDen, yNum, yDen) {
|
|
38310
|
-
if (!extentsSettable(m) || !xDen || !yDen) {
|
|
38311
|
-
return;
|
|
38312
|
-
}
|
|
38313
|
-
const cx = scaled(m.winExt.cx, xNum, xDen);
|
|
38314
|
-
const cy = scaled(m.winExt.cy, yNum, yDen);
|
|
38315
|
-
if (cx === 0 || cy === 0) {
|
|
38316
|
-
return;
|
|
38317
|
-
}
|
|
38318
|
-
m.winExt = { cx, cy };
|
|
38319
|
-
fixIsotropic(m);
|
|
38320
|
-
}
|
|
38321
|
-
function scaleViewportExt(m, xNum, xDen, yNum, yDen) {
|
|
38322
|
-
if (!extentsSettable(m) || !xDen || !yDen) {
|
|
38323
|
-
return;
|
|
38324
|
-
}
|
|
38325
|
-
const cx = scaled(m.vpExt.cx, xNum, xDen);
|
|
38326
|
-
const cy = scaled(m.vpExt.cy, yNum, yDen);
|
|
38327
|
-
if (cx === 0 || cy === 0) {
|
|
38328
|
-
return;
|
|
38329
|
-
}
|
|
38330
|
-
m.vpExt = { cx, cy };
|
|
38331
|
-
fixIsotropic(m);
|
|
38332
|
-
}
|
|
38333
|
-
function applyWmfMapping(rCtx, m, kx, ky, mirrorWidth = 0) {
|
|
38334
|
-
rCtx.wmfLayoutRtl = mirrorWidth > 0;
|
|
38335
|
-
rCtx.useMappingMode = true;
|
|
38336
|
-
rCtx.windowOrg = { x: m.winOrg.x, y: m.winOrg.y };
|
|
38337
|
-
rCtx.windowExt = { cx: m.winExt.cx || 1, cy: m.winExt.cy || 1 };
|
|
38338
|
-
rCtx.viewportOrg = { x: m.vpOrg.x * kx, y: m.vpOrg.y * ky };
|
|
38339
|
-
rCtx.viewportExt = { cx: (m.vpExt.cx || 1) * kx, cy: (m.vpExt.cy || 1) * ky };
|
|
38340
|
-
if (mirrorWidth > 0) {
|
|
38341
|
-
rCtx.viewportOrg.x = mirrorWidth * kx - rCtx.viewportOrg.x;
|
|
38342
|
-
rCtx.viewportExt.cx = -rCtx.viewportExt.cx;
|
|
38343
|
-
}
|
|
38344
|
-
}
|
|
38345
|
-
function scanMappingRecords(view, start) {
|
|
38346
|
-
const out = {
|
|
38347
|
-
mode: null,
|
|
38348
|
-
winExt: null,
|
|
38349
|
-
vpExt: null
|
|
38350
|
-
};
|
|
38351
|
-
let off = start;
|
|
38352
|
-
let guard = 0;
|
|
38353
|
-
while (off + 6 <= view.byteLength && guard++ < 1e6) {
|
|
38354
|
-
const size = view.getUint32(off, true) * 2;
|
|
38355
|
-
const type = view.getUint16(off + 4, true);
|
|
38356
|
-
if (size < 6 || off + size > view.byteLength || type === 0) {
|
|
38357
|
-
break;
|
|
38358
|
-
}
|
|
38359
|
-
const d = off + 6;
|
|
38360
|
-
if (type === 259 && size >= 8 && out.mode === null) {
|
|
38361
|
-
out.mode = view.getUint16(d, true);
|
|
38362
|
-
} else if (type === 524 && size >= 10 && !out.winExt) {
|
|
38363
|
-
out.winExt = { cy: view.getInt16(d, true), cx: view.getInt16(d + 2, true) };
|
|
38364
|
-
} else if (type === 526 && size >= 10 && !out.vpExt) {
|
|
38365
|
-
out.vpExt = { cy: view.getInt16(d, true), cx: view.getInt16(d + 2, true) };
|
|
38366
|
-
}
|
|
38367
|
-
off += size;
|
|
38368
|
-
}
|
|
38369
|
-
return out;
|
|
38370
|
-
}
|
|
38371
|
-
function wmfPlayback(view, header, referenceDpi) {
|
|
38372
|
-
const valid = (v) => typeof v === "number" && Number.isFinite(v) && v > 0 ? v : DEVICE_DPI;
|
|
38373
|
-
const dpi = { x: valid(typeof referenceDpi === "number" ? referenceDpi : referenceDpi?.x), y: valid(typeof referenceDpi === "number" ? referenceDpi : referenceDpi?.y) };
|
|
38374
|
-
const density = referenceDpi === void 0 ? {} : { dpi };
|
|
38375
|
-
const bw = header.boundsRight - header.boundsLeft;
|
|
38376
|
-
const bh = header.boundsBottom - header.boundsTop;
|
|
38377
|
-
if (header.placeable !== false) {
|
|
38378
|
-
const inch = header.unitsPerInch > 0 ? header.unitsPerInch : DEVICE_DPI;
|
|
38379
|
-
const width2 = Math.max(1, Math.round(Math.abs(bw) * dpi.x / inch));
|
|
38380
|
-
const height2 = Math.max(1, Math.round(Math.abs(bh) * dpi.y / inch));
|
|
38381
|
-
return {
|
|
38382
|
-
width: width2,
|
|
38383
|
-
height: height2,
|
|
38384
|
-
mapping: {
|
|
38385
|
-
...density,
|
|
38386
|
-
mode: MM_ANISOTROPIC,
|
|
38387
|
-
winOrg: { x: header.boundsLeft, y: header.boundsTop },
|
|
38388
|
-
winExt: { cx: bw || 1, cy: bh || 1 },
|
|
38389
|
-
vpOrg: { x: 0, y: 0 },
|
|
38390
|
-
vpExt: { cx: width2, cy: height2 }
|
|
38391
|
-
}
|
|
38392
|
-
};
|
|
38393
|
-
}
|
|
38394
|
-
const scan = scanMappingRecords(view, header.headerSize);
|
|
38395
|
-
const scalable = scan.mode === MM_ISOTROPIC || scan.mode === MM_ANISOTROPIC;
|
|
38396
|
-
const ext = scalable && scan.vpExt ? scan.vpExt : scan.winExt;
|
|
38397
|
-
const width = ext ? Math.abs(ext.cx) : Math.abs(bw);
|
|
38398
|
-
const height = ext ? Math.abs(ext.cy) : Math.abs(bh);
|
|
38399
|
-
const w = Math.max(1, width || 1);
|
|
38400
|
-
const h = Math.max(1, height || 1);
|
|
38401
|
-
return {
|
|
38402
|
-
width: w,
|
|
38403
|
-
height: h,
|
|
38404
|
-
mapping: {
|
|
38405
|
-
...density,
|
|
38406
|
-
mode: MM_ANISOTROPIC,
|
|
38407
|
-
winOrg: { x: 0, y: 0 },
|
|
38408
|
-
winExt: { cx: w, cy: h },
|
|
38409
|
-
vpOrg: { x: 0, y: 0 },
|
|
38410
|
-
vpExt: { cx: w, cy: h }
|
|
38411
|
-
}
|
|
38412
|
-
};
|
|
38413
|
-
}
|
|
38414
|
-
|
|
38415
38543
|
// src/wmf-emf-bridge.ts
|
|
38416
38544
|
var EmfRecordWriter = class {
|
|
38417
38545
|
constructor(type, capacity = 64) {
|