emf-converter 4.3.1 → 4.3.3
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 +3 -3
- package/dist/index.js +448 -144
- package/dist/index.mjs +448 -144
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1735,7 +1735,21 @@ var KAPPA = 0.5522847498307936;
|
|
|
1735
1735
|
function axisBox(l, t, r, b) {
|
|
1736
1736
|
return { ax: l, ay: t, exx: r - l, exy: 0, eyx: 0, eyy: b - t };
|
|
1737
1737
|
}
|
|
1738
|
-
function ellipseBeziersBox(box) {
|
|
1738
|
+
function ellipseBeziersBox(box, clockwise = false) {
|
|
1739
|
+
if (!clockwise) {
|
|
1740
|
+
return ellipsePoints(box, false);
|
|
1741
|
+
}
|
|
1742
|
+
const e = clockwiseEllipseBeziersBox(box);
|
|
1743
|
+
const out = [];
|
|
1744
|
+
for (let i = e.length - 2; i >= 0; i -= 2) {
|
|
1745
|
+
out.push(e[i], e[i + 1]);
|
|
1746
|
+
}
|
|
1747
|
+
return out;
|
|
1748
|
+
}
|
|
1749
|
+
function clockwiseEllipseBeziersBox(box) {
|
|
1750
|
+
return ellipsePoints(box, true);
|
|
1751
|
+
}
|
|
1752
|
+
function ellipsePoints(box, cwControls) {
|
|
1739
1753
|
const half = (v, up) => up ? Math.ceil(v / 2) : Math.floor(v / 2);
|
|
1740
1754
|
const hMidLo = (v) => half(v, false);
|
|
1741
1755
|
const hMidHi = (v) => half(v, true);
|
|
@@ -1745,6 +1759,11 @@ function ellipseBeziersBox(box) {
|
|
|
1745
1759
|
const vMidHi = (v) => half(v, true);
|
|
1746
1760
|
const vCtl = (v) => Math.floor(v / 2) - Math.floor(KAPPA * Math.floor(v / 2));
|
|
1747
1761
|
const vCtlR = (v) => v - vCtl(v);
|
|
1762
|
+
const vDist = (v) => Math.ceil(KAPPA * Math.floor(v / 2));
|
|
1763
|
+
const rightUpper = cwControls ? (v) => vMidHi(v) - vDist(v) : vCtl;
|
|
1764
|
+
const leftUpper = cwControls ? (v) => vMidLo(v) - vDist(v) : vCtl;
|
|
1765
|
+
const leftLower = cwControls ? (v) => vMidLo(v) + vDist(v) : vCtlR;
|
|
1766
|
+
const rightLower = cwControls ? (v) => vMidHi(v) + vDist(v) : vCtlR;
|
|
1748
1767
|
const zero = () => 0;
|
|
1749
1768
|
const full = (v) => v;
|
|
1750
1769
|
const { ax, ay, exx, exy, eyx, eyy } = box;
|
|
@@ -1753,17 +1772,17 @@ function ellipseBeziersBox(box) {
|
|
|
1753
1772
|
out.push(ax + gx(exx) + gy(eyx), ay + gx(exy) + gy(eyy));
|
|
1754
1773
|
};
|
|
1755
1774
|
P(full, vMidHi);
|
|
1756
|
-
P(full,
|
|
1775
|
+
P(full, rightUpper);
|
|
1757
1776
|
P(hCtl, zero);
|
|
1758
1777
|
P(hMidLo, zero);
|
|
1759
1778
|
P(hCtl2, zero);
|
|
1760
|
-
P(zero,
|
|
1779
|
+
P(zero, leftUpper);
|
|
1761
1780
|
P(zero, vMidLo);
|
|
1762
|
-
P(zero,
|
|
1781
|
+
P(zero, leftLower);
|
|
1763
1782
|
P(hCtl2, full);
|
|
1764
1783
|
P(hMidHi, full);
|
|
1765
1784
|
P(hCtl, full);
|
|
1766
|
-
P(full,
|
|
1785
|
+
P(full, rightLower);
|
|
1767
1786
|
P(full, vMidHi);
|
|
1768
1787
|
return out;
|
|
1769
1788
|
}
|
|
@@ -1780,8 +1799,12 @@ function flattenBezierPath(pts) {
|
|
|
1780
1799
|
function roundRectCorners(l, t, r, b, cw, ch) {
|
|
1781
1800
|
const w = r - l;
|
|
1782
1801
|
const h = b - t;
|
|
1783
|
-
|
|
1784
|
-
|
|
1802
|
+
let ew = Math.min(Math.abs(cw), w);
|
|
1803
|
+
let eh = Math.min(Math.abs(ch), h);
|
|
1804
|
+
if (ew === 0 || eh === 0) {
|
|
1805
|
+
ew = 0;
|
|
1806
|
+
eh = 0;
|
|
1807
|
+
}
|
|
1785
1808
|
const hy = Math.floor(h / 2) - Math.floor((h - eh) / 2);
|
|
1786
1809
|
const topX = Math.floor(r - ew / 2);
|
|
1787
1810
|
const hx = r - topX;
|
|
@@ -1890,12 +1913,7 @@ function angleArcFix(box, startDeg, sweepDeg) {
|
|
|
1890
1913
|
const cx = l + w / 2;
|
|
1891
1914
|
const cy = t + h / 2;
|
|
1892
1915
|
const E = ellipseBeziers(l, t, l + w, t + h);
|
|
1893
|
-
const Ecw =
|
|
1894
|
-
const d = Math.ceil(KAPPA * Math.floor(h / 2));
|
|
1895
|
-
Ecw[3] = Ecw[1] - d;
|
|
1896
|
-
Ecw[11] = Ecw[13] - d;
|
|
1897
|
-
Ecw[15] = Ecw[13] + d;
|
|
1898
|
-
Ecw[23] = Ecw[1] + d;
|
|
1916
|
+
const Ecw = clockwiseEllipseBeziersBox(axisBox(l, t, l + w, t + h));
|
|
1899
1917
|
const start = startDeg * Math.PI / 180;
|
|
1900
1918
|
const out = [Math.round(cx + w / 2 * tableCos(start)), Math.round(cy - h / 2 * tableSin(start))];
|
|
1901
1919
|
for (const p of angleArcPieces(startDeg, sweepDeg)) {
|
|
@@ -1937,15 +1955,7 @@ function arcBeziers(l, t, r, b, xs, ys, xe, ye, clockwise) {
|
|
|
1937
1955
|
}
|
|
1938
1956
|
const px = (a2) => cx + rx * tableCos(a2);
|
|
1939
1957
|
const py = (a2) => cy - ry * tableSin(a2);
|
|
1940
|
-
const E = ellipseBeziers(l, t, r, b);
|
|
1941
|
-
if (clockwise) {
|
|
1942
|
-
const fh = Math.floor((b - t) / 2);
|
|
1943
|
-
const d = Math.ceil(KAPPA * fh);
|
|
1944
|
-
E[3] = E[1] - d;
|
|
1945
|
-
E[11] = E[13] - d;
|
|
1946
|
-
E[15] = E[13] + d;
|
|
1947
|
-
E[23] = E[1] + d;
|
|
1948
|
-
}
|
|
1958
|
+
const E = clockwise ? clockwiseEllipseBeziersBox(axisBox(l, t, r, b)) : ellipseBeziers(l, t, r, b);
|
|
1949
1959
|
const out = [Math.round(px(a0)), Math.round(py(a0))];
|
|
1950
1960
|
let a = a0;
|
|
1951
1961
|
for (let guard = 0; guard < 8 && (s > 0 ? a < a1 - 1e-12 : a > a1 + 1e-12); guard++) {
|
|
@@ -1978,12 +1988,45 @@ function arcBeziers(l, t, r, b, xs, ys, xe, ye, clockwise) {
|
|
|
1978
1988
|
var GdiRasterPath = class {
|
|
1979
1989
|
constructor() {
|
|
1980
1990
|
this.figures = [];
|
|
1991
|
+
/**
|
|
1992
|
+
* The path as `GetPath` reports it, before flattening: FIX points
|
|
1993
|
+
* (`[x0, y0, ...]`) and their `PT_*` types (`PT_MOVETO` 6, `PT_LINETO`
|
|
1994
|
+
* 2, `PT_BEZIERTO` 4, `PT_CLOSEFIGURE` 1 or-ed onto a figure's last
|
|
1995
|
+
* point). Used to check the geometry against Windows' own paths.
|
|
1996
|
+
*/
|
|
1997
|
+
this.getPath = { pts: [], types: [] };
|
|
1981
1998
|
this.current = null;
|
|
1982
1999
|
}
|
|
1983
2000
|
/** Starts a new figure at (`x`, `y`). */
|
|
1984
2001
|
moveTo(x, y) {
|
|
1985
2002
|
this.current = { pts: [x, y], closed: false };
|
|
1986
2003
|
this.figures.push(this.current);
|
|
2004
|
+
this.log(x, y, 6);
|
|
2005
|
+
}
|
|
2006
|
+
/**
|
|
2007
|
+
* Starts a new figure at the current position (`x`, `y`) unless the open
|
|
2008
|
+
* figure already ends there. GDI opens a new figure for a drawing call
|
|
2009
|
+
* that continues from the current position (`LineTo`, `PolylineTo`,
|
|
2010
|
+
* `ArcTo`, ...) when the path is empty, its last figure is closed, or
|
|
2011
|
+
* the current position has moved away from the path's last point (a
|
|
2012
|
+
* `MoveTo`, or a call such as `Polyline`, `Arc` or `PolyPolygon` that
|
|
2013
|
+
* adds to the path without moving the current position; Windows'
|
|
2014
|
+
* `GetPath`, Wine `gdi32/tests/path.c`, `test_all_functions`).
|
|
2015
|
+
*/
|
|
2016
|
+
continueAt(x, y) {
|
|
2017
|
+
const f = this.current;
|
|
2018
|
+
if (f && f.pts[f.pts.length - 2] === x && f.pts[f.pts.length - 1] === y) {
|
|
2019
|
+
return;
|
|
2020
|
+
}
|
|
2021
|
+
this.moveTo(x, y);
|
|
2022
|
+
}
|
|
2023
|
+
/** True when a figure is open (not closed and not ended by an appended path). */
|
|
2024
|
+
hasOpenFigure() {
|
|
2025
|
+
return this.current !== null;
|
|
2026
|
+
}
|
|
2027
|
+
log(x, y, type) {
|
|
2028
|
+
this.getPath.pts.push(x, y);
|
|
2029
|
+
this.getPath.types.push(type);
|
|
1987
2030
|
}
|
|
1988
2031
|
/** Adds a line to (`x`, `y`), starting a figure there when none is open. */
|
|
1989
2032
|
lineTo(x, y) {
|
|
@@ -1992,6 +2035,7 @@ var GdiRasterPath = class {
|
|
|
1992
2035
|
this.moveTo(last ? last[0] : x, last ? last[1] : y);
|
|
1993
2036
|
}
|
|
1994
2037
|
this.current.pts.push(x, y);
|
|
2038
|
+
this.log(x, y, 2);
|
|
1995
2039
|
}
|
|
1996
2040
|
/** Adds a cubic Bezier from the current point. */
|
|
1997
2041
|
bezierTo(c1x, c1y, c2x, c2y, x, y) {
|
|
@@ -2001,6 +2045,9 @@ var GdiRasterPath = class {
|
|
|
2001
2045
|
}
|
|
2002
2046
|
const p = this.current.pts;
|
|
2003
2047
|
this.flattenInto(p[p.length - 2], p[p.length - 1], c1x, c1y, c2x, c2y, x, y);
|
|
2048
|
+
this.log(c1x, c1y, 4);
|
|
2049
|
+
this.log(c2x, c2y, 4);
|
|
2050
|
+
this.log(x, y, 4);
|
|
2004
2051
|
}
|
|
2005
2052
|
/** Flattens one Bezier onto the open figure, recording its end tangents. */
|
|
2006
2053
|
flattenInto(x0, y0, c1x, c1y, c2x, c2y, x3, y3) {
|
|
@@ -2035,6 +2082,9 @@ var GdiRasterPath = class {
|
|
|
2035
2082
|
}
|
|
2036
2083
|
for (let i = 2; i + 5 < pts.length; i += 6) {
|
|
2037
2084
|
this.flattenInto(pts[i - 2], pts[i - 1], pts[i], pts[i + 1], pts[i + 2], pts[i + 3], pts[i + 4], pts[i + 5]);
|
|
2085
|
+
for (let k = i; k < i + 6; k += 2) {
|
|
2086
|
+
this.log(pts[k], pts[k + 1], 4);
|
|
2087
|
+
}
|
|
2038
2088
|
}
|
|
2039
2089
|
}
|
|
2040
2090
|
/** Closes the open figure (the next drawing call starts a new one). */
|
|
@@ -2042,6 +2092,8 @@ var GdiRasterPath = class {
|
|
|
2042
2092
|
if (this.current) {
|
|
2043
2093
|
this.current.closed = true;
|
|
2044
2094
|
this.current = null;
|
|
2095
|
+
const t = this.getPath.types;
|
|
2096
|
+
t[t.length - 1] |= 1;
|
|
2045
2097
|
}
|
|
2046
2098
|
}
|
|
2047
2099
|
/** Appends every figure of `other`. */
|
|
@@ -2049,6 +2101,9 @@ var GdiRasterPath = class {
|
|
|
2049
2101
|
for (const f of other.figures) {
|
|
2050
2102
|
this.figures.push({ pts: f.pts.slice(), closed: f.closed, tangents: f.tangents && new Map(f.tangents) });
|
|
2051
2103
|
}
|
|
2104
|
+
for (let i = 0; i < other.getPath.types.length; i++) {
|
|
2105
|
+
this.log(other.getPath.pts[2 * i], other.getPath.pts[2 * i + 1], other.getPath.types[i]);
|
|
2106
|
+
}
|
|
2052
2107
|
this.current = null;
|
|
2053
2108
|
}
|
|
2054
2109
|
lastPoint() {
|
|
@@ -12645,7 +12700,10 @@ function dashFigure(pts, closed, pen) {
|
|
|
12645
12700
|
for (let i = 0; i + 1 < path.length; i++) {
|
|
12646
12701
|
const a = path[i];
|
|
12647
12702
|
const b = path[i + 1];
|
|
12648
|
-
|
|
12703
|
+
const m = pen.dashMetric;
|
|
12704
|
+
const vx = b.x - a.x;
|
|
12705
|
+
const vy = b.y - a.y;
|
|
12706
|
+
let segLen = m ? Math.hypot(m[0] * vx + m[2] * vy, m[1] * vx + m[3] * vy) : Math.hypot(vx, vy);
|
|
12649
12707
|
let t0 = 0;
|
|
12650
12708
|
while (segLen - t0 > remaining + 1e-9) {
|
|
12651
12709
|
t0 += remaining;
|
|
@@ -12673,6 +12731,26 @@ function dashFigure(pts, closed, pen) {
|
|
|
12673
12731
|
}
|
|
12674
12732
|
return out.filter((d) => d.pts.length > 1);
|
|
12675
12733
|
}
|
|
12734
|
+
var ARROW_ANCHOR = 20;
|
|
12735
|
+
function arrowAnchor(pp, atEnd, half) {
|
|
12736
|
+
const w = 2 * half;
|
|
12737
|
+
const tip = atEnd ? pp[pp.length - 1] : pp[0];
|
|
12738
|
+
const next = atEnd ? pp[pp.length - 2] : pp[1];
|
|
12739
|
+
const len = Math.hypot(next.x - tip.x, next.y - tip.y);
|
|
12740
|
+
const ux = (next.x - tip.x) / len;
|
|
12741
|
+
const uy = (next.y - tip.y) / len;
|
|
12742
|
+
const depth = 2 * w;
|
|
12743
|
+
const across = 2 * w / Math.sqrt(3);
|
|
12744
|
+
const base = { x: tip.x + ux * depth, y: tip.y + uy * depth };
|
|
12745
|
+
if (len > depth) {
|
|
12746
|
+
if (atEnd) {
|
|
12747
|
+
pp[pp.length - 1] = base;
|
|
12748
|
+
} else {
|
|
12749
|
+
pp[0] = base;
|
|
12750
|
+
}
|
|
12751
|
+
}
|
|
12752
|
+
return [tip, { x: base.x - uy * across, y: base.y + ux * across }, { x: base.x + uy * across, y: base.y - ux * across }];
|
|
12753
|
+
}
|
|
12676
12754
|
var MIN_DASH = 1 / 256;
|
|
12677
12755
|
function signedArea(pts) {
|
|
12678
12756
|
let a = 0;
|
|
@@ -12723,6 +12801,19 @@ function widenFigures(figures, pen) {
|
|
|
12723
12801
|
if (pp.length < 2) {
|
|
12724
12802
|
continue;
|
|
12725
12803
|
}
|
|
12804
|
+
const arrows = [];
|
|
12805
|
+
let startCapOverride = null;
|
|
12806
|
+
let endCapOverride = null;
|
|
12807
|
+
if (!pieceClosed && !(pen.dash && closed)) {
|
|
12808
|
+
if (piece.first && pen.startCap === ARROW_ANCHOR) {
|
|
12809
|
+
arrows.push(arrowAnchor(pp, false, h));
|
|
12810
|
+
startCapOverride = 0;
|
|
12811
|
+
}
|
|
12812
|
+
if (piece.last && pen.endCap === ARROW_ANCHOR) {
|
|
12813
|
+
arrows.push(arrowAnchor(pp, true, h));
|
|
12814
|
+
endCapOverride = 0;
|
|
12815
|
+
}
|
|
12816
|
+
}
|
|
12726
12817
|
for (const [o1, o2] of bands) {
|
|
12727
12818
|
if (pieceClosed) {
|
|
12728
12819
|
polys.push(sidePoints(pp, true, o2, pen));
|
|
@@ -12733,11 +12824,16 @@ function widenFigures(figures, pen) {
|
|
|
12733
12824
|
const right = sidePoints(pp, false, o1, pen).reverse();
|
|
12734
12825
|
const fEnd = frame(pp[pp.length - 2], pp[pp.length - 1]);
|
|
12735
12826
|
const f0 = frame(pp[1], pp[0]);
|
|
12736
|
-
const endCap = piece.last && !(pen.dash && closed) ? pen.endCap : pen.dashCap;
|
|
12737
|
-
const startCap = piece.first && !(pen.dash && closed) ? pen.startCap : pen.dashCap;
|
|
12827
|
+
const endCap = endCapOverride ?? (piece.last && !(pen.dash && closed) ? pen.endCap : pen.dashCap);
|
|
12828
|
+
const startCap = startCapOverride ?? (piece.first && !(pen.dash && closed) ? pen.startCap : pen.dashCap);
|
|
12738
12829
|
const capEnd = capPoints(pp[pp.length - 1], fEnd, o1, o2, endCap, h);
|
|
12739
12830
|
const capStart = capPoints(pp[0], f0, -o2, -o1, startCap, h);
|
|
12740
|
-
|
|
12831
|
+
const poly = [...left.slice(0, -1), ...capEnd, ...right.slice(1, -1), ...capStart];
|
|
12832
|
+
polys.push(poly);
|
|
12833
|
+
const sign = Math.sign(signedArea(poly));
|
|
12834
|
+
for (const arrow of arrows) {
|
|
12835
|
+
polys.push(Math.sign(signedArea(arrow)) === sign ? arrow : arrow.slice().reverse());
|
|
12836
|
+
}
|
|
12741
12837
|
}
|
|
12742
12838
|
}
|
|
12743
12839
|
}
|
|
@@ -16651,8 +16747,11 @@ function boxCorners(box) {
|
|
|
16651
16747
|
const { ax, ay, exx, exy, eyx, eyy } = box;
|
|
16652
16748
|
return [ax + exx, ay + exy, ax, ay, ax + eyx, ay + eyy, ax + exx + eyx, ay + exy + eyy];
|
|
16653
16749
|
}
|
|
16654
|
-
function
|
|
16655
|
-
|
|
16750
|
+
function flipBox(box) {
|
|
16751
|
+
return { ax: box.ax + box.eyx, ay: box.ay + box.eyy, exx: box.exx, exy: box.exy, eyx: -box.eyx, eyy: -box.eyy };
|
|
16752
|
+
}
|
|
16753
|
+
function rectRasterPath(box, clockwise = false) {
|
|
16754
|
+
const c = boxCorners(clockwise ? flipBox(box) : box);
|
|
16656
16755
|
const path = new GdiRasterPath();
|
|
16657
16756
|
path.moveTo(c[0], c[1]);
|
|
16658
16757
|
path.lineTo(c[2], c[3]);
|
|
@@ -16661,9 +16760,9 @@ function rectRasterPath(box) {
|
|
|
16661
16760
|
path.closeFigure();
|
|
16662
16761
|
return path;
|
|
16663
16762
|
}
|
|
16664
|
-
function ellipseRasterPath(box) {
|
|
16763
|
+
function ellipseRasterPath(box, clockwise = false) {
|
|
16665
16764
|
const path = new GdiRasterPath();
|
|
16666
|
-
path.addBeziers(ellipseBeziersBox(box), true);
|
|
16765
|
+
path.addBeziers(ellipseBeziersBox(box, clockwise), true);
|
|
16667
16766
|
path.closeFigure();
|
|
16668
16767
|
return path;
|
|
16669
16768
|
}
|
|
@@ -16689,13 +16788,16 @@ function boxFrame(box) {
|
|
|
16689
16788
|
const h = Math.round(Math.hypot(box.eyx, box.eyy));
|
|
16690
16789
|
return { l: 0, t: 0, r: w, b: h };
|
|
16691
16790
|
}
|
|
16692
|
-
function roundRectRasterPath(box, cw, ch) {
|
|
16791
|
+
function roundRectRasterPath(box, cw, ch, clockwise = false, rectangle = false) {
|
|
16792
|
+
if (rectangle) {
|
|
16793
|
+
return rectRasterPath(box, clockwise);
|
|
16794
|
+
}
|
|
16693
16795
|
const f = boxFrame(box);
|
|
16694
16796
|
const q = roundRectCorners(f.l, f.t, f.r, f.b, cw, ch);
|
|
16695
16797
|
const map = frameMapper(box, f.l, f.t, f.r - f.l, f.b - f.t);
|
|
16696
16798
|
const pts = [];
|
|
16697
16799
|
for (let i = 0; i < q.length; i += 2) {
|
|
16698
|
-
pts.push(...map(q[i], q[i + 1]));
|
|
16800
|
+
pts.push(...map(q[i], clockwise ? f.t + f.b - q[i + 1] : q[i + 1]));
|
|
16699
16801
|
}
|
|
16700
16802
|
const path = new GdiRasterPath();
|
|
16701
16803
|
for (let c = 0; c < 4; c++) {
|
|
@@ -16738,7 +16840,7 @@ function arcRasterPath(box, s, e, clockwise, kind, from, path = new GdiRasterPat
|
|
|
16738
16840
|
pts.push(...map(bz[i], bz[i + 1]));
|
|
16739
16841
|
}
|
|
16740
16842
|
if (kind === "arcto" && from) {
|
|
16741
|
-
path.
|
|
16843
|
+
path.continueAt(from[0], from[1]);
|
|
16742
16844
|
path.addBeziers(pts, false);
|
|
16743
16845
|
} else {
|
|
16744
16846
|
path.addBeziers(pts, true);
|
|
@@ -19458,6 +19560,15 @@ function rasterPathOf(rCtx) {
|
|
|
19458
19560
|
rCtx.rasterPath ?? (rCtx.rasterPath = new GdiRasterPath());
|
|
19459
19561
|
return rCtx.rasterPath;
|
|
19460
19562
|
}
|
|
19563
|
+
function continueFigure(rCtx) {
|
|
19564
|
+
const path = rasterPathOf(rCtx);
|
|
19565
|
+
const [x, y] = currentFix(rCtx);
|
|
19566
|
+
const before = path.figures.length;
|
|
19567
|
+
path.continueAt(x, y);
|
|
19568
|
+
if (path.figures.length !== before) {
|
|
19569
|
+
gdiPathRecorder(rCtx).moveTo(x / 16, y / 16);
|
|
19570
|
+
}
|
|
19571
|
+
}
|
|
19461
19572
|
function lineStyleOf(rCtx) {
|
|
19462
19573
|
rCtx.lineStyle ?? (rCtx.lineStyle = { pos: 0 });
|
|
19463
19574
|
return rCtx.lineStyle;
|
|
@@ -19473,6 +19584,9 @@ function currentFix(rCtx) {
|
|
|
19473
19584
|
}
|
|
19474
19585
|
return fixPoint(rCtx, state.curX, state.curY);
|
|
19475
19586
|
}
|
|
19587
|
+
function uprightFixBox(rCtx, l, t, r, b) {
|
|
19588
|
+
return fixBox(rCtx, Math.min(l, r), Math.min(t, b), Math.max(l, r), Math.max(t, b));
|
|
19589
|
+
}
|
|
19476
19590
|
function fixExtent(rCtx, v, axis) {
|
|
19477
19591
|
const m = gdiDeviceMatrix(rCtx);
|
|
19478
19592
|
const k = axis === 0 ? Math.hypot(m[0], m[1]) : Math.hypot(m[2], m[3]);
|
|
@@ -19515,6 +19629,7 @@ function handleLineTo(rCtx, dataOff, recSize) {
|
|
|
19515
19629
|
const to = rotated ? gmapPoint(rCtx, lx, ly) : { x: gmx(rCtx, lx), y: gmy(rCtx, ly) };
|
|
19516
19630
|
const fixTo = fixPoint(rCtx, lx, ly);
|
|
19517
19631
|
if (inPath) {
|
|
19632
|
+
continueFigure(rCtx);
|
|
19518
19633
|
gdiPathRecorder(rCtx).lineTo(to.x, to.y);
|
|
19519
19634
|
rasterPathOf(rCtx).lineTo(fixTo[0], fixTo[1]);
|
|
19520
19635
|
} else {
|
|
@@ -19549,7 +19664,8 @@ function handleRectangle(rCtx, dataOff, recSize) {
|
|
|
19549
19664
|
const t = view.getInt32(dataOff + 4, true);
|
|
19550
19665
|
const r = view.getInt32(dataOff + 8, true);
|
|
19551
19666
|
const b = view.getInt32(dataOff + 12, true);
|
|
19552
|
-
const box =
|
|
19667
|
+
const box = uprightFixBox(rCtx, l, t, r, b);
|
|
19668
|
+
const clockwise = rCtx.state.arcDirection === 2;
|
|
19553
19669
|
if (!inPath) {
|
|
19554
19670
|
resetLineStyle(rCtx);
|
|
19555
19671
|
}
|
|
@@ -19568,14 +19684,14 @@ function handleRectangle(rCtx, dataOff, recSize) {
|
|
|
19568
19684
|
};
|
|
19569
19685
|
if (inPath) {
|
|
19570
19686
|
appendRect(gdiPathRecorder(rCtx));
|
|
19571
|
-
rasterPathOf(rCtx).append(rectRasterPath(box));
|
|
19687
|
+
rasterPathOf(rCtx).append(rectRasterPath(box, clockwise));
|
|
19572
19688
|
} else {
|
|
19573
19689
|
paintGdiShape(rCtx, {
|
|
19574
19690
|
build: (c) => {
|
|
19575
19691
|
c.beginPath();
|
|
19576
19692
|
appendRect(c);
|
|
19577
19693
|
},
|
|
19578
|
-
raster: () => rectRasterPath(box),
|
|
19694
|
+
raster: () => rectRasterPath(box, clockwise),
|
|
19579
19695
|
rectangle: true,
|
|
19580
19696
|
fill: true,
|
|
19581
19697
|
stroke: true,
|
|
@@ -19590,14 +19706,14 @@ function handleRectangle(rCtx, dataOff, recSize) {
|
|
|
19590
19706
|
const h = gmh(rCtx, b - t);
|
|
19591
19707
|
if (inPath) {
|
|
19592
19708
|
gdiPathRecorder(rCtx).rect(x, y, w, h);
|
|
19593
|
-
rasterPathOf(rCtx).append(rectRasterPath(box));
|
|
19709
|
+
rasterPathOf(rCtx).append(rectRasterPath(box, clockwise));
|
|
19594
19710
|
} else if (needsPathBasedRectangle(rCtx)) {
|
|
19595
19711
|
paintGdiShape(rCtx, {
|
|
19596
19712
|
build: (c) => {
|
|
19597
19713
|
c.beginPath();
|
|
19598
19714
|
c.rect(x, y, w, h);
|
|
19599
19715
|
},
|
|
19600
|
-
raster: () => rectRasterPath(box),
|
|
19716
|
+
raster: () => rectRasterPath(box, clockwise),
|
|
19601
19717
|
rectangle: true,
|
|
19602
19718
|
fill: true,
|
|
19603
19719
|
stroke: true,
|
|
@@ -19710,7 +19826,8 @@ function handleRoundRect(rCtx, dataOff, recSize) {
|
|
|
19710
19826
|
gmh(rCtx, cornerH) / 2,
|
|
19711
19827
|
null
|
|
19712
19828
|
);
|
|
19713
|
-
const
|
|
19829
|
+
const clockwise = rCtx.state.arcDirection === 2;
|
|
19830
|
+
const raster = (box = uprightFixBox(rCtx, l, t, r, b)) => roundRectRasterPath(box, fixExtent(rCtx, cornerW, 0), fixExtent(rCtx, cornerH, 1), clockwise, cornerW === 0 || cornerH === 0);
|
|
19714
19831
|
if (inPath) {
|
|
19715
19832
|
drawRoundRect(gdiPathRecorder(rCtx));
|
|
19716
19833
|
rasterPathOf(rCtx).append(raster());
|
|
@@ -19721,7 +19838,7 @@ function handleRoundRect(rCtx, dataOff, recSize) {
|
|
|
19721
19838
|
c.beginPath();
|
|
19722
19839
|
drawRoundRect(c);
|
|
19723
19840
|
},
|
|
19724
|
-
raster: () => raster(curvedFixBox(rCtx, l, t, r, b)),
|
|
19841
|
+
raster: () => raster(curvedFixBox(rCtx, l, t, r, b, true)),
|
|
19725
19842
|
roundPen: true,
|
|
19726
19843
|
fill: true,
|
|
19727
19844
|
stroke: true
|
|
@@ -19730,8 +19847,8 @@ function handleRoundRect(rCtx, dataOff, recSize) {
|
|
|
19730
19847
|
}
|
|
19731
19848
|
return true;
|
|
19732
19849
|
}
|
|
19733
|
-
function curvedFixBox(rCtx, l, t, r, b) {
|
|
19734
|
-
const box = fixBox(rCtx, l, t, r, b);
|
|
19850
|
+
function curvedFixBox(rCtx, l, t, r, b, upright = false) {
|
|
19851
|
+
const box = upright ? uprightFixBox(rCtx, l, t, r, b) : fixBox(rCtx, l, t, r, b);
|
|
19735
19852
|
if (rCtx.state.penStyle !== 5) {
|
|
19736
19853
|
return box;
|
|
19737
19854
|
}
|
|
@@ -19757,6 +19874,7 @@ function handleEllipse(rCtx, dataOff, recSize) {
|
|
|
19757
19874
|
const t = view.getInt32(dataOff + 4, true);
|
|
19758
19875
|
const r = view.getInt32(dataOff + 8, true);
|
|
19759
19876
|
const b = view.getInt32(dataOff + 12, true);
|
|
19877
|
+
const clockwise = rCtx.state.arcDirection === 2;
|
|
19760
19878
|
const params = hasWorldRotation(rCtx) ? gdiEllipseParams(rCtx, (l + r) / 2, (t + b) / 2, Math.abs(r - l) / 2, Math.abs(b - t) / 2) : {
|
|
19761
19879
|
cx: gmx(rCtx, (l + r) / 2),
|
|
19762
19880
|
cy: gmy(rCtx, (t + b) / 2),
|
|
@@ -19766,7 +19884,7 @@ function handleEllipse(rCtx, dataOff, recSize) {
|
|
|
19766
19884
|
};
|
|
19767
19885
|
if (inPath) {
|
|
19768
19886
|
gdiPathRecorder(rCtx).ellipse(params.cx, params.cy, params.rx, params.ry, params.rotation, 0, Math.PI * 2);
|
|
19769
|
-
rasterPathOf(rCtx).append(ellipseRasterPath(
|
|
19887
|
+
rasterPathOf(rCtx).append(ellipseRasterPath(uprightFixBox(rCtx, l, t, r, b), clockwise));
|
|
19770
19888
|
} else {
|
|
19771
19889
|
resetLineStyle(rCtx);
|
|
19772
19890
|
paintGdiShape(rCtx, {
|
|
@@ -19774,7 +19892,7 @@ function handleEllipse(rCtx, dataOff, recSize) {
|
|
|
19774
19892
|
c.beginPath();
|
|
19775
19893
|
c.ellipse(params.cx, params.cy, params.rx, params.ry, params.rotation, 0, Math.PI * 2);
|
|
19776
19894
|
},
|
|
19777
|
-
raster: () => ellipseRasterPath(curvedFixBox(rCtx, l, t, r, b)),
|
|
19895
|
+
raster: () => ellipseRasterPath(curvedFixBox(rCtx, l, t, r, b, true), clockwise),
|
|
19778
19896
|
roundPen: true,
|
|
19779
19897
|
fill: true,
|
|
19780
19898
|
stroke: true
|
|
@@ -19832,6 +19950,9 @@ function handleArcFamily(rCtx, recType, dataOff, recSize) {
|
|
|
19832
19950
|
from: currentFix(rCtx)
|
|
19833
19951
|
});
|
|
19834
19952
|
if (inPath) {
|
|
19953
|
+
if (isArcTo) {
|
|
19954
|
+
continueFigure(rCtx);
|
|
19955
|
+
}
|
|
19835
19956
|
build(gdiPathRecorder(rCtx));
|
|
19836
19957
|
const a = rasterArgs();
|
|
19837
19958
|
arcRasterPath(a.box, a.s, a.e, clockwise, kind, a.from, rasterPathOf(rCtx));
|
|
@@ -19908,9 +20029,7 @@ function handleAngleArc(rCtx, dataOff, recSize) {
|
|
|
19908
20029
|
}
|
|
19909
20030
|
const e = [fixPts[fixPts.length - 2], fixPts[fixPts.length - 1]];
|
|
19910
20031
|
const buildRaster = (path, from) => {
|
|
19911
|
-
|
|
19912
|
-
path.moveTo(from[0], from[1]);
|
|
19913
|
-
}
|
|
20032
|
+
path.continueAt(from[0], from[1]);
|
|
19914
20033
|
path.addBeziers(fixPts, false);
|
|
19915
20034
|
};
|
|
19916
20035
|
const params = gdiEllipseParams(rCtx, cx, cy, radius, radius);
|
|
@@ -19924,9 +20043,9 @@ function handleAngleArc(rCtx, dataOff, recSize) {
|
|
|
19924
20043
|
c.ellipse(params.cx, params.cy, params.rx, params.ry, params.rotation, -a0, clockwise ? -a0 + span : -a0 - span, !clockwise);
|
|
19925
20044
|
};
|
|
19926
20045
|
if (inPath) {
|
|
19927
|
-
|
|
19928
|
-
buildCanvas(
|
|
19929
|
-
buildRaster(rasterPathOf(rCtx),
|
|
20046
|
+
continueFigure(rCtx);
|
|
20047
|
+
buildCanvas(gdiPathRecorder(rCtx));
|
|
20048
|
+
buildRaster(rasterPathOf(rCtx), currentFix(rCtx));
|
|
19930
20049
|
} else {
|
|
19931
20050
|
resetLineStyle(rCtx);
|
|
19932
20051
|
const from = currentFix(rCtx);
|
|
@@ -20005,50 +20124,111 @@ function readColorAdjustment(view, off) {
|
|
|
20005
20124
|
function isIdentityColorAdjustment(ca) {
|
|
20006
20125
|
return !ca || ca.flags === 0 && ca.redGamma === 1e4 && ca.greenGamma === 1e4 && ca.blueGamma === 1e4 && ca.referenceBlack === 0 && ca.referenceWhite === 1e4 && ca.contrast === 0 && ca.brightness === 0 && ca.colorfulness === 0 && ca.redGreenTint === 0;
|
|
20007
20126
|
}
|
|
20008
|
-
|
|
20009
|
-
|
|
20127
|
+
var CONTRAST_GAIN = 1.88;
|
|
20128
|
+
var BRIGHTNESS_GAIN = 78.5;
|
|
20129
|
+
var COLORFULNESS_GAIN = 1.335;
|
|
20130
|
+
var TINT_RADIANS = -1.135;
|
|
20131
|
+
var RGB_TO_XYZ = [
|
|
20132
|
+
[0.4124, 0.3576, 0.1805],
|
|
20133
|
+
[0.2126, 0.7152, 0.0722],
|
|
20134
|
+
[0.0193, 0.1192, 0.9505]
|
|
20135
|
+
];
|
|
20136
|
+
var XYZ_TO_RGB = invert3(RGB_TO_XYZ);
|
|
20137
|
+
var WHITE = RGB_TO_XYZ.map((row) => row[0] + row[1] + row[2]);
|
|
20138
|
+
var WHITE_D = WHITE[0] + 15 * WHITE[1] + 3 * WHITE[2];
|
|
20139
|
+
var WHITE_U = 4 * WHITE[0] / WHITE_D;
|
|
20140
|
+
var WHITE_V = 9 * WHITE[1] / WHITE_D;
|
|
20141
|
+
function invert3(m) {
|
|
20142
|
+
const [[a, b, c], [d, e, f], [g, h, i]] = m;
|
|
20143
|
+
const A = e * i - f * h;
|
|
20144
|
+
const B = f * g - d * i;
|
|
20145
|
+
const C = d * h - e * g;
|
|
20146
|
+
const det = a * A + b * B + c * C;
|
|
20147
|
+
return [
|
|
20148
|
+
[A / det, (c * h - b * i) / det, (b * f - c * e) / det],
|
|
20149
|
+
[B / det, (a * i - c * g) / det, (c * d - a * f) / det],
|
|
20150
|
+
[C / det, (b * g - a * h) / det, (a * e - b * d) / det]
|
|
20151
|
+
];
|
|
20152
|
+
}
|
|
20153
|
+
function lightness(t) {
|
|
20154
|
+
return t > 8856e-6 ? 116 * Math.cbrt(t) - 16 : 903.3 * t;
|
|
20155
|
+
}
|
|
20156
|
+
function fromLightness(l) {
|
|
20157
|
+
return l > 8 ? ((l + 16) / 116) ** 3 : l / 903.3;
|
|
20010
20158
|
}
|
|
20011
20159
|
var clamp012 = (v) => v < 0 ? 0 : v > 1 ? 1 : v;
|
|
20012
20160
|
function colorAdjustmentMapper(ca) {
|
|
20013
20161
|
const black = ca.referenceBlack / 1e4;
|
|
20014
20162
|
const span = Math.max(1e-6, ca.referenceWhite / 1e4 - black);
|
|
20015
20163
|
const gammas = [ca.redGamma / 1e4, ca.greenGamma / 1e4, ca.blueGamma / 1e4];
|
|
20016
|
-
const
|
|
20164
|
+
const negative = (ca.flags & CA_NEGATIVE) !== 0;
|
|
20165
|
+
const linear = gammas.map((gamma) => {
|
|
20017
20166
|
const table = new Float64Array(256);
|
|
20018
20167
|
for (let i = 0; i < 256; i++) {
|
|
20019
|
-
|
|
20020
|
-
|
|
20021
|
-
table[i] = ca.flags & CA_NEGATIVE ? 1 - v : v;
|
|
20168
|
+
const v = negative ? 1 - i / 255 : i / 255;
|
|
20169
|
+
table[i] = clamp012((v - black) / span) ** gamma;
|
|
20022
20170
|
}
|
|
20023
20171
|
return table;
|
|
20024
20172
|
});
|
|
20025
|
-
const chroma =
|
|
20026
|
-
const
|
|
20027
|
-
const
|
|
20028
|
-
const
|
|
20173
|
+
const chroma = ca.colorfulness < 0 ? 1 + ca.colorfulness / 100 : 1 + COLORFULNESS_GAIN * ca.colorfulness / 100;
|
|
20174
|
+
const angle = TINT_RADIANS * ca.redGreenTint / 100;
|
|
20175
|
+
const cos = Math.cos(angle) * chroma;
|
|
20176
|
+
const sin = Math.sin(angle) * chroma;
|
|
20177
|
+
const slope = Math.exp(CONTRAST_GAIN * ca.contrast / 100);
|
|
20178
|
+
const offset = 50 - 50 * slope + BRIGHTNESS_GAIN * ca.brightness / 100;
|
|
20029
20179
|
const log = (ca.flags & CA_LOG_FILTER) !== 0;
|
|
20030
|
-
const
|
|
20031
|
-
|
|
20180
|
+
const colour = ca.colorfulness !== 0 || ca.redGreenTint !== 0;
|
|
20181
|
+
const out = (v, c) => {
|
|
20182
|
+
v = clamp012(fromLightness(slope * lightness(clamp012(v)) + offset)) ** (1 / gammas[c]);
|
|
20032
20183
|
if (log) {
|
|
20033
20184
|
v = Math.log10(1 + 9 * v);
|
|
20034
20185
|
}
|
|
20035
20186
|
return Math.round(v * 255);
|
|
20036
20187
|
};
|
|
20037
20188
|
return (rgb2) => {
|
|
20038
|
-
|
|
20039
|
-
|
|
20040
|
-
|
|
20041
|
-
|
|
20042
|
-
|
|
20043
|
-
|
|
20044
|
-
|
|
20045
|
-
|
|
20046
|
-
|
|
20047
|
-
|
|
20048
|
-
|
|
20049
|
-
|
|
20189
|
+
let r = linear[0][rgb2 >> 16 & 255];
|
|
20190
|
+
let g = linear[1][rgb2 >> 8 & 255];
|
|
20191
|
+
let b = linear[2][rgb2 & 255];
|
|
20192
|
+
if (colour) {
|
|
20193
|
+
const x = RGB_TO_XYZ[0][0] * r + RGB_TO_XYZ[0][1] * g + RGB_TO_XYZ[0][2] * b;
|
|
20194
|
+
const y = RGB_TO_XYZ[1][0] * r + RGB_TO_XYZ[1][1] * g + RGB_TO_XYZ[1][2] * b;
|
|
20195
|
+
const z = RGB_TO_XYZ[2][0] * r + RGB_TO_XYZ[2][1] * g + RGB_TO_XYZ[2][2] * b;
|
|
20196
|
+
const d = x + 15 * y + 3 * z;
|
|
20197
|
+
if (d > 1e-12 && y > 1e-12) {
|
|
20198
|
+
const du = 4 * x / d - WHITE_U;
|
|
20199
|
+
const dv = 9 * y / d - WHITE_V;
|
|
20200
|
+
const u = WHITE_U + du * cos - dv * sin;
|
|
20201
|
+
const v = Math.max(1e-6, WHITE_V + du * sin + dv * cos);
|
|
20202
|
+
const x2 = y * 9 * u / (4 * v);
|
|
20203
|
+
const z2 = y * (12 - 3 * u - 20 * v) / (4 * v);
|
|
20204
|
+
r = XYZ_TO_RGB[0][0] * x2 + XYZ_TO_RGB[0][1] * y + XYZ_TO_RGB[0][2] * z2;
|
|
20205
|
+
g = XYZ_TO_RGB[1][0] * x2 + XYZ_TO_RGB[1][1] * y + XYZ_TO_RGB[1][2] * z2;
|
|
20206
|
+
b = XYZ_TO_RGB[2][0] * x2 + XYZ_TO_RGB[2][1] * y + XYZ_TO_RGB[2][2] * z2;
|
|
20207
|
+
}
|
|
20208
|
+
}
|
|
20209
|
+
return out(r, 0) << 16 | out(g, 1) << 8 | out(b, 2);
|
|
20050
20210
|
};
|
|
20051
20211
|
}
|
|
20212
|
+
function colorAdjustRgb(rgbs, ca) {
|
|
20213
|
+
if (!ca || isIdentityColorAdjustment(ca)) {
|
|
20214
|
+
return;
|
|
20215
|
+
}
|
|
20216
|
+
const map = colorAdjustmentMapper(ca);
|
|
20217
|
+
const cache = /* @__PURE__ */ new Map();
|
|
20218
|
+
for (let i = 0; i + 2 < rgbs.length; i += 3) {
|
|
20219
|
+
const rgb2 = rgbs[i] << 16 | rgbs[i + 1] << 8 | rgbs[i + 2];
|
|
20220
|
+
let v = cache.get(rgb2);
|
|
20221
|
+
if (v === void 0) {
|
|
20222
|
+
v = map(rgb2);
|
|
20223
|
+
if (cache.size < 65536) {
|
|
20224
|
+
cache.set(rgb2, v);
|
|
20225
|
+
}
|
|
20226
|
+
}
|
|
20227
|
+
rgbs[i] = v >> 16 & 255;
|
|
20228
|
+
rgbs[i + 1] = v >> 8 & 255;
|
|
20229
|
+
rgbs[i + 2] = v & 255;
|
|
20230
|
+
}
|
|
20231
|
+
}
|
|
20052
20232
|
function applyColorAdjustment(pixels, ca) {
|
|
20053
20233
|
if (!ca || isIdentityColorAdjustment(ca)) {
|
|
20054
20234
|
return;
|
|
@@ -20143,64 +20323,160 @@ function stretchGdi(src, sx, sy, sw, sh, dw, dh, mode) {
|
|
|
20143
20323
|
}
|
|
20144
20324
|
return { width: W, height: H, data };
|
|
20145
20325
|
}
|
|
20146
|
-
|
|
20147
|
-
|
|
20326
|
+
var FIX = 65536;
|
|
20327
|
+
function halftoneNearest(i, srcLen, dstLen) {
|
|
20328
|
+
const num = (2 * i + 1) * srcLen;
|
|
20329
|
+
const den = 2 * dstLen;
|
|
20330
|
+
let k = Math.floor(num / den);
|
|
20331
|
+
if (k * den === num) {
|
|
20332
|
+
k--;
|
|
20333
|
+
}
|
|
20334
|
+
return Math.max(0, Math.min(srcLen - 1, k));
|
|
20335
|
+
}
|
|
20336
|
+
function halftoneAxis(start, srcLen, dstLen, reverse) {
|
|
20337
|
+
const taps = [];
|
|
20148
20338
|
if (dstLen <= 0 || srcLen <= 0) {
|
|
20149
|
-
return
|
|
20339
|
+
return taps;
|
|
20150
20340
|
}
|
|
20151
|
-
const at = (k) => reverse ?
|
|
20341
|
+
const at = (k) => reverse ? start + srcLen - 1 - k : start + k;
|
|
20342
|
+
if (dstLen >= srcLen) {
|
|
20343
|
+
for (let i = 0; i < dstLen; i++) {
|
|
20344
|
+
taps.push([[at(halftoneNearest(i, srcLen, dstLen)), 1]]);
|
|
20345
|
+
}
|
|
20346
|
+
return taps;
|
|
20347
|
+
}
|
|
20348
|
+
const step = Math.ceil(srcLen * FIX / dstLen);
|
|
20152
20349
|
for (let i = 0; i < dstLen; i++) {
|
|
20153
|
-
const a = i *
|
|
20154
|
-
const b = (i + 1) *
|
|
20155
|
-
const
|
|
20156
|
-
for (let k = Math.floor(a /
|
|
20157
|
-
const overlap = Math.min(b, (k + 1) *
|
|
20350
|
+
const a = i * step;
|
|
20351
|
+
const b = (i + 1) * step;
|
|
20352
|
+
const run = [];
|
|
20353
|
+
for (let k = Math.floor(a / FIX); k * FIX < b && k < srcLen; k++) {
|
|
20354
|
+
const overlap = Math.min(b, (k + 1) * FIX) - Math.max(a, k * FIX);
|
|
20158
20355
|
if (overlap > 0) {
|
|
20159
|
-
|
|
20356
|
+
run.push([at(k), overlap]);
|
|
20357
|
+
}
|
|
20358
|
+
}
|
|
20359
|
+
taps.push(run);
|
|
20360
|
+
}
|
|
20361
|
+
return taps;
|
|
20362
|
+
}
|
|
20363
|
+
var SPECKLE_OVERSHOOT = 4;
|
|
20364
|
+
function halftoneDespeckle(px, w, h) {
|
|
20365
|
+
const src = px.slice();
|
|
20366
|
+
const at = (x, y, c) => src[(y * w + x) * 3 + c];
|
|
20367
|
+
const over = (v) => v < -SPECKLE_OVERSHOOT * 4 || v > (255 + SPECKLE_OVERSHOOT) * 4;
|
|
20368
|
+
for (let y = 0; y < h; y++) {
|
|
20369
|
+
const up = y > 0 ? y - 1 : Math.min(h - 1, y + 1);
|
|
20370
|
+
const down = y < h - 1 ? y + 1 : Math.max(0, y - 1);
|
|
20371
|
+
for (let x = 0; x < w; x++) {
|
|
20372
|
+
const left = x > 0 ? x - 1 : Math.min(w - 1, x + 1);
|
|
20373
|
+
const right = x < w - 1 ? x + 1 : Math.max(0, x - 1);
|
|
20374
|
+
let hClip = 0;
|
|
20375
|
+
let vClip = 0;
|
|
20376
|
+
for (let c = 0; c < 3; c++) {
|
|
20377
|
+
const v = at(x, y, c);
|
|
20378
|
+
if (over(6 * v - at(left, y, c) - at(right, y, c))) {
|
|
20379
|
+
hClip++;
|
|
20380
|
+
}
|
|
20381
|
+
if (over(6 * v - at(x, up, c) - at(x, down, c))) {
|
|
20382
|
+
vClip++;
|
|
20383
|
+
}
|
|
20384
|
+
}
|
|
20385
|
+
if (hClip < 2 || vClip < 2) {
|
|
20386
|
+
continue;
|
|
20387
|
+
}
|
|
20388
|
+
for (let c = 0; c < 3; c++) {
|
|
20389
|
+
px[(y * w + x) * 3 + c] = at(left, y, c) + 2 * at(x, y, c) + at(right, y, c) + 2 >> 2;
|
|
20160
20390
|
}
|
|
20161
20391
|
}
|
|
20162
|
-
out.push(taps);
|
|
20163
20392
|
}
|
|
20164
|
-
return out;
|
|
20165
20393
|
}
|
|
20166
|
-
function
|
|
20394
|
+
function halftoneSharpen(px, w, h) {
|
|
20395
|
+
const src = px.slice();
|
|
20396
|
+
const at = (x, y, c) => src[(Math.max(0, Math.min(h - 1, y)) * w + Math.max(0, Math.min(w - 1, x))) * 3 + c];
|
|
20397
|
+
for (let y = 0; y < h; y++) {
|
|
20398
|
+
for (let x = 0; x < w; x++) {
|
|
20399
|
+
for (let c = 0; c < 3; c++) {
|
|
20400
|
+
const v = at(x, y, c);
|
|
20401
|
+
const sum = at(x - 1, y, c) + at(x + 1, y, c) + at(x, y - 1, c) + at(x, y + 1, c);
|
|
20402
|
+
const out = v + Math.floor((4 * v - sum) / 8);
|
|
20403
|
+
px[(y * w + x) * 3 + c] = out < 0 ? 0 : out > 255 ? 255 : out;
|
|
20404
|
+
}
|
|
20405
|
+
}
|
|
20406
|
+
}
|
|
20407
|
+
}
|
|
20408
|
+
function stretchHalftone(src, sx, sy, sw, sh, dw, dh, adjust) {
|
|
20167
20409
|
const W = Math.max(0, Math.round(Math.abs(dw)));
|
|
20168
20410
|
const H = Math.max(0, Math.round(Math.abs(dh)));
|
|
20411
|
+
const SW = Math.round(Math.abs(sw));
|
|
20412
|
+
const SH = Math.round(Math.abs(sh));
|
|
20413
|
+
const x0 = Math.round(Math.min(sx, sx + sw));
|
|
20414
|
+
const y0 = Math.round(Math.min(sy, sy + sh));
|
|
20169
20415
|
const flipX = dw < 0 !== sw < 0;
|
|
20170
20416
|
const flipY = dh < 0 !== sh < 0;
|
|
20171
|
-
const cols = axisBoxWeights(Math.round(Math.min(sx, sx + sw)), Math.round(Math.abs(sw)), W, flipX);
|
|
20172
|
-
const rows = axisBoxWeights(Math.round(Math.min(sy, sy + sh)), Math.round(Math.abs(sh)), H, flipY);
|
|
20173
20417
|
const data = new Uint8ClampedArray(W * H * 4);
|
|
20174
|
-
|
|
20418
|
+
if (W === 0 || H === 0 || SW === 0 || SH === 0) {
|
|
20419
|
+
return { width: W, height: H, data };
|
|
20420
|
+
}
|
|
20421
|
+
const rect = new Int32Array(SW * SH * 3);
|
|
20422
|
+
for (let y = 0; y < SH; y++) {
|
|
20423
|
+
const yy = y0 + y;
|
|
20424
|
+
for (let x = 0; x < SW; x++) {
|
|
20425
|
+
const xx = x0 + x;
|
|
20426
|
+
if (yy < 0 || yy >= src.height || xx < 0 || xx >= src.width) {
|
|
20427
|
+
continue;
|
|
20428
|
+
}
|
|
20429
|
+
const i = (yy * src.width + xx) * 4;
|
|
20430
|
+
const o = (y * SW + x) * 3;
|
|
20431
|
+
rect[o] = src.data[i];
|
|
20432
|
+
rect[o + 1] = src.data[i + 1];
|
|
20433
|
+
rect[o + 2] = src.data[i + 2];
|
|
20434
|
+
}
|
|
20435
|
+
}
|
|
20436
|
+
const enlarging = W >= SW && H >= SH && (W > SW || H > SH);
|
|
20437
|
+
const reducing = W < SW && H < SH;
|
|
20438
|
+
if (enlarging) {
|
|
20439
|
+
halftoneDespeckle(rect, SW, SH);
|
|
20440
|
+
}
|
|
20441
|
+
if (adjust) {
|
|
20442
|
+
adjust(rect);
|
|
20443
|
+
}
|
|
20444
|
+
const cols = halftoneAxis(0, SW, W, flipX);
|
|
20445
|
+
const rows = halftoneAxis(0, SH, H, flipY);
|
|
20446
|
+
const out = new Int32Array(W * H * 3);
|
|
20175
20447
|
for (let y = 0; y < H; y++) {
|
|
20176
|
-
const ys = rows[y]
|
|
20448
|
+
const ys = rows[y];
|
|
20177
20449
|
for (let x = 0; x < W; x++) {
|
|
20178
|
-
const xs = cols[x]
|
|
20450
|
+
const xs = cols[x];
|
|
20179
20451
|
let r = 0;
|
|
20180
20452
|
let g = 0;
|
|
20181
20453
|
let b = 0;
|
|
20454
|
+
let total = 0;
|
|
20182
20455
|
for (const [yy, wy] of ys) {
|
|
20183
|
-
if (yy < 0 || yy >= src.height) {
|
|
20184
|
-
continue;
|
|
20185
|
-
}
|
|
20186
20456
|
for (const [xx, wx] of xs) {
|
|
20187
|
-
if (xx < 0 || xx >= src.width) {
|
|
20188
|
-
continue;
|
|
20189
|
-
}
|
|
20190
20457
|
const w = wx * wy;
|
|
20191
|
-
|
|
20192
|
-
|
|
20193
|
-
|
|
20194
|
-
|
|
20458
|
+
total += w;
|
|
20459
|
+
const i = (yy * SW + xx) * 3;
|
|
20460
|
+
r += rect[i] * w;
|
|
20461
|
+
g += rect[i + 1] * w;
|
|
20462
|
+
b += rect[i + 2] * w;
|
|
20195
20463
|
}
|
|
20196
20464
|
}
|
|
20197
|
-
const o = (y * W + x) *
|
|
20198
|
-
|
|
20199
|
-
|
|
20200
|
-
|
|
20201
|
-
data[o + 3] = 255;
|
|
20465
|
+
const o = (y * W + x) * 3;
|
|
20466
|
+
out[o] = Math.floor((2 * r + total) / (2 * total));
|
|
20467
|
+
out[o + 1] = Math.floor((2 * g + total) / (2 * total));
|
|
20468
|
+
out[o + 2] = Math.floor((2 * b + total) / (2 * total));
|
|
20202
20469
|
}
|
|
20203
20470
|
}
|
|
20471
|
+
if (reducing) {
|
|
20472
|
+
halftoneSharpen(out, W, H);
|
|
20473
|
+
}
|
|
20474
|
+
for (let i = 0, o = 0; i < W * H; i++, o += 3) {
|
|
20475
|
+
data[i * 4] = out[o];
|
|
20476
|
+
data[i * 4 + 1] = out[o + 1];
|
|
20477
|
+
data[i * 4 + 2] = out[o + 2];
|
|
20478
|
+
data[i * 4 + 3] = 255;
|
|
20479
|
+
}
|
|
20204
20480
|
return { width: W, height: H, data };
|
|
20205
20481
|
}
|
|
20206
20482
|
|
|
@@ -20226,7 +20502,7 @@ function patternOperand(rCtx, brush) {
|
|
|
20226
20502
|
function drawSourceMapped(target, decoded, req, offsetX, offsetY, mode) {
|
|
20227
20503
|
const dLeft = Math.min(req.dx, req.dx + req.dw) - offsetX;
|
|
20228
20504
|
const dTop = Math.min(req.dy, req.dy + req.dh) - offsetY;
|
|
20229
|
-
const px = mode === HALFTONE ? stretchHalftone(decoded.pixels, req.sx, req.sy, req.sw, req.sh, req.dw, req.dh) : stretchGdi(decoded.pixels, req.sx, req.sy, req.sw, req.sh, req.dw, req.dh, mode);
|
|
20505
|
+
const px = mode === HALFTONE ? stretchHalftone(decoded.pixels, req.sx, req.sy, req.sw, req.sh, req.dw, req.dh, decoded.adjust) : stretchGdi(decoded.pixels, req.sx, req.sy, req.sw, req.sh, req.dw, req.dh, mode);
|
|
20230
20506
|
if (px.width === 0 || px.height === 0) {
|
|
20231
20507
|
return;
|
|
20232
20508
|
}
|
|
@@ -20254,15 +20530,14 @@ function decodeSource(rCtx, req) {
|
|
|
20254
20530
|
if (!image) {
|
|
20255
20531
|
return null;
|
|
20256
20532
|
}
|
|
20257
|
-
|
|
20258
|
-
|
|
20259
|
-
}
|
|
20533
|
+
const ca = rCtx.state.colorAdjustment;
|
|
20534
|
+
const adjust = req.stretch && rCtx.state.stretchBltMode === HALFTONE && ca ? (rgb2) => colorAdjustRgb(rgb2, ca) : void 0;
|
|
20260
20535
|
let { sy } = req;
|
|
20261
20536
|
if (req.dibOrigin === "bottom-left" && rCtx.view.getInt32(req.source.bmi + 8, true) > 0) {
|
|
20262
20537
|
sy = image.height - sy - req.sh;
|
|
20263
20538
|
}
|
|
20264
20539
|
return {
|
|
20265
|
-
decoded: { pixels: image },
|
|
20540
|
+
decoded: { pixels: image, adjust },
|
|
20266
20541
|
req: { ...req, sy }
|
|
20267
20542
|
};
|
|
20268
20543
|
}
|
|
@@ -20418,6 +20693,9 @@ function executeRotatedBlit(rCtx, logDx, logDy, logDw, logDh, rop, source, sx, s
|
|
|
20418
20693
|
return;
|
|
20419
20694
|
}
|
|
20420
20695
|
src = decoded.decoded.pixels;
|
|
20696
|
+
if (decoded.decoded.adjust) {
|
|
20697
|
+
applyColorAdjustment(src, rCtx.state.colorAdjustment);
|
|
20698
|
+
}
|
|
20421
20699
|
srcX = decoded.req.sx;
|
|
20422
20700
|
srcY = decoded.req.sy;
|
|
20423
20701
|
}
|
|
@@ -22773,9 +23051,12 @@ function handlePoly(rCtx, recType, count, readPt, kinds) {
|
|
|
22773
23051
|
}
|
|
22774
23052
|
};
|
|
22775
23053
|
if (inPath) {
|
|
23054
|
+
if (isTo) {
|
|
23055
|
+
continueFigure(rCtx);
|
|
23056
|
+
}
|
|
22776
23057
|
build(gdiPathRecorder(rCtx));
|
|
22777
23058
|
rCtx.rasterPath ?? (rCtx.rasterPath = new GdiRasterPath());
|
|
22778
|
-
buildRaster(rCtx.rasterPath,
|
|
23059
|
+
buildRaster(rCtx.rasterPath, null);
|
|
22779
23060
|
} else {
|
|
22780
23061
|
const from = isTo ? currentFix(rCtx) : null;
|
|
22781
23062
|
const start = isTo ? gmapPoint(rCtx, state.curX, state.curY) : null;
|
|
@@ -22798,10 +23079,11 @@ function handlePoly(rCtx, recType, count, readPt, kinds) {
|
|
|
22798
23079
|
fillRule: state.polyFillMode === 2 ? "nonzero" : "evenodd"
|
|
22799
23080
|
});
|
|
22800
23081
|
}
|
|
22801
|
-
if (count > 0) {
|
|
23082
|
+
if (isTo && count > 0) {
|
|
22802
23083
|
const [x, y] = readPt(count - 1);
|
|
22803
23084
|
state.curX = x;
|
|
22804
23085
|
state.curY = y;
|
|
23086
|
+
rCtx.curFix = void 0;
|
|
22805
23087
|
}
|
|
22806
23088
|
}
|
|
22807
23089
|
function handlePoly32(rCtx, recType, offset, dataOff, recSize) {
|
|
@@ -22906,9 +23188,11 @@ function handlePolyDraw(rCtx, offset, dataOff, recSize, pointSize) {
|
|
|
22906
23188
|
};
|
|
22907
23189
|
const startsWithMove = (typeAt(0) & ~PT_CLOSEFIGURE) === PT_MOVETO;
|
|
22908
23190
|
if (inPath) {
|
|
23191
|
+
if (!startsWithMove) {
|
|
23192
|
+
continueFigure(rCtx);
|
|
23193
|
+
}
|
|
22909
23194
|
rCtx.rasterPath ?? (rCtx.rasterPath = new GdiRasterPath());
|
|
22910
|
-
|
|
22911
|
-
walk2(gdiPathRecorder(rCtx), rCtx.rasterPath, !startsWithMove && fresh ? currentFix(rCtx) : null, null);
|
|
23195
|
+
walk2(gdiPathRecorder(rCtx), rCtx.rasterPath, null, null);
|
|
22912
23196
|
} else {
|
|
22913
23197
|
const from = startsWithMove ? null : currentFix(rCtx);
|
|
22914
23198
|
const fromPx = startsWithMove ? null : gmapPoint(rCtx, state.curX, state.curY);
|
|
@@ -23879,12 +24163,12 @@ function hslToRgb(h, s, l) {
|
|
|
23879
24163
|
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];
|
|
23880
24164
|
return [r + m, g + m, b + m];
|
|
23881
24165
|
}
|
|
23882
|
-
function applyHueSaturationLightness(src, hue, saturation,
|
|
24166
|
+
function applyHueSaturationLightness(src, hue, saturation, lightness2) {
|
|
23883
24167
|
const out = new Uint8ClampedArray(src);
|
|
23884
24168
|
const push = (v, t) => t >= 0 ? v + (1 - v) * (t / 100) : v * (1 + t / 100);
|
|
23885
24169
|
for (let i = 0; i < src.length; i += 4) {
|
|
23886
24170
|
const [h, s, l] = rgbToHsl(src[i] / 255, src[i + 1] / 255, src[i + 2] / 255);
|
|
23887
|
-
const [r, g, b] = hslToRgb(h + hue, push(s, saturation), push(l,
|
|
24171
|
+
const [r, g, b] = hslToRgb(h + hue, push(s, saturation), push(l, lightness2));
|
|
23888
24172
|
out[i] = Math.round(r * 255);
|
|
23889
24173
|
out[i + 1] = Math.round(g * 255);
|
|
23890
24174
|
out[i + 2] = Math.round(b * 255);
|
|
@@ -24575,6 +24859,7 @@ function strokePlusGeometry(rCtx, pen, buildPath, points, closedFigure = false)
|
|
|
24575
24859
|
}
|
|
24576
24860
|
};
|
|
24577
24861
|
if (pen) {
|
|
24862
|
+
const nibDashed = !!nib && penDashArray(pen).length > 0;
|
|
24578
24863
|
applyPlusPenStyle(ctx, pen, widthScale);
|
|
24579
24864
|
const mode = plusRasterMode(rCtx);
|
|
24580
24865
|
let sampler = pen.brush && !isSvgContext(ctx) ? brushSampler(rCtx, pen.brush) : null;
|
|
@@ -24589,7 +24874,7 @@ function strokePlusGeometry(rCtx, pen, buildPath, points, closedFigure = false)
|
|
|
24589
24874
|
if (mode !== "canvas" && size && strokeGdiplus(rCtx, pen, nib, sampler, buildPath, device, size, mode, closedFigure)) {
|
|
24590
24875
|
return;
|
|
24591
24876
|
}
|
|
24592
|
-
const outline = hasCustomCap(pen) ? penOutlineWorld(rCtx, pen, nib, buildPath, closedFigure) : null;
|
|
24877
|
+
const outline = hasCustomCap(pen) || nibDashed ? penOutlineWorld(rCtx, pen, nib, buildPath, closedFigure) : null;
|
|
24593
24878
|
let box = null;
|
|
24594
24879
|
if (size && outline) {
|
|
24595
24880
|
box = deviceBounds(outline.flat(), device, size, 2);
|
|
@@ -24619,7 +24904,7 @@ function strokePlusGeometry(rCtx, pen, buildPath, points, closedFigure = false)
|
|
|
24619
24904
|
}
|
|
24620
24905
|
}
|
|
24621
24906
|
const paint = pen.brush ? brushPaint2(rCtx, pen.brush) : pen.color;
|
|
24622
|
-
if ((hasCustomCap(pen) || nib && typeof paint !== "string") && fillPenOutline(rCtx, pen, nib, paint, buildPath, closedFigure)) {
|
|
24907
|
+
if ((hasCustomCap(pen) || nibDashed || nib && typeof paint !== "string") && fillPenOutline(rCtx, pen, nib, paint, buildPath, closedFigure)) {
|
|
24623
24908
|
return;
|
|
24624
24909
|
}
|
|
24625
24910
|
ctx.strokeStyle = paint;
|
|
@@ -24641,7 +24926,9 @@ function resolvePenTransform(pen) {
|
|
|
24641
24926
|
return { pen: { ...plain, width: pen.width === 0 ? 1 : pen.width }, nib: null };
|
|
24642
24927
|
}
|
|
24643
24928
|
if (Math.abs(sx - sy) <= 1e-6 * sx && Math.abs(dot) <= 1e-6 * sx * sy) {
|
|
24644
|
-
|
|
24929
|
+
const pattern = pen.dashStyle === 5 ? pen.dashPattern : DASH_PATTERNS[pen.dashStyle];
|
|
24930
|
+
const dashed = pattern && pattern.length > 0 ? { dashStyle: 5, dashPattern: pattern.map((v) => v / sx), dashOffset: (pen.dashOffset ?? 0) / sx } : {};
|
|
24931
|
+
return { pen: { ...plain, ...dashed, width: pen.width * sx }, nib: null };
|
|
24645
24932
|
}
|
|
24646
24933
|
return { pen: plain, nib: [a, b, c, d, 0, 0] };
|
|
24647
24934
|
}
|
|
@@ -24666,7 +24953,7 @@ function penFrame(device, nib) {
|
|
|
24666
24953
|
toDevice: mulMatrix(full, [1 / unit, 0, 0, 1 / unit, 0, 0])
|
|
24667
24954
|
};
|
|
24668
24955
|
}
|
|
24669
|
-
function framePen(pen, unit) {
|
|
24956
|
+
function framePen(pen, unit, nib = null) {
|
|
24670
24957
|
const dash = penDashArray(pen).map((v) => v * unit);
|
|
24671
24958
|
return {
|
|
24672
24959
|
half: (pen.width || 1) * unit / 2,
|
|
@@ -24677,6 +24964,7 @@ function framePen(pen, unit) {
|
|
|
24677
24964
|
dashCap: pen.dashCap ?? 0,
|
|
24678
24965
|
dash: dash.length > 0 ? dash : null,
|
|
24679
24966
|
dashOffset: (pen.dashOffset ?? 0) * (pen.width || 1) * unit,
|
|
24967
|
+
dashMetric: nib ? [nib[0], nib[1], nib[2], nib[3]] : void 0,
|
|
24680
24968
|
compound: pen.compound ?? null,
|
|
24681
24969
|
inset: pen.alignment === 1
|
|
24682
24970
|
};
|
|
@@ -24704,7 +24992,7 @@ function strokeGdiplus(rCtx, pen, nib, sampler, buildPath, device, size, mode, c
|
|
|
24704
24992
|
figures = figures.map((f) => ({ ...f, closed: true }));
|
|
24705
24993
|
}
|
|
24706
24994
|
const width = (pen.width || 1) * frame2.unit;
|
|
24707
|
-
const devicePen = framePen(pen, frame2.unit);
|
|
24995
|
+
const devicePen = framePen(pen, frame2.unit, nib);
|
|
24708
24996
|
const antialias = mode === "gdiplus-aa";
|
|
24709
24997
|
const toFix = (poly) => {
|
|
24710
24998
|
const m = frame2.toDevice;
|
|
@@ -24796,7 +25084,7 @@ function penOutlineWorld(rCtx, pen, nib, buildPath, closedFigure) {
|
|
|
24796
25084
|
figures = figures.map((f) => ({ ...f, closed: true }));
|
|
24797
25085
|
}
|
|
24798
25086
|
const width = (pen.width || 1) * frame2.unit;
|
|
24799
|
-
const devicePen = framePen(pen, frame2.unit);
|
|
25087
|
+
const devicePen = framePen(pen, frame2.unit, nib);
|
|
24800
25088
|
const outline = hasCustomCap(pen) ? customCapOutline(figures, width, devicePen, pen) : widenFigures(figures, devicePen);
|
|
24801
25089
|
const m = mulMatrix(deviceInv, frame2.toDevice);
|
|
24802
25090
|
return outline.map((poly) => poly.map((p) => ({ x: m[0] * p.x + m[2] * p.y + m[4], y: m[1] * p.x + m[3] * p.y + m[5] })));
|
|
@@ -27364,7 +27652,8 @@ function wmfSetDibToDev(p, d, end) {
|
|
|
27364
27652
|
const hv = new DataView(bmi.buffer);
|
|
27365
27653
|
const fullH = hv.getInt32(8, true);
|
|
27366
27654
|
hv.setInt32(8, fullH < 0 ? -scanCount : scanCount, true);
|
|
27367
|
-
const [
|
|
27655
|
+
const [mx, oy] = deviceDest(p, dx, dy, 0, 0);
|
|
27656
|
+
const ox = p.layout & 1 ? mx - w : mx;
|
|
27368
27657
|
playStretchDibits(p, 13369376, ox, oy + (sy + h - hi), w, hi - lo, sx, lo - startScan, w, hi - lo, { bmi, bits: dib.bits }, true);
|
|
27369
27658
|
}
|
|
27370
27659
|
|
|
@@ -27711,25 +28000,30 @@ function wmfRectangle(p, l, t, r, b) {
|
|
|
27711
28000
|
c.beginPath();
|
|
27712
28001
|
c.rect(cr.x, cr.y, cr.w, cr.h);
|
|
27713
28002
|
},
|
|
27714
|
-
raster: () => rectRasterPath(fixBoxOf(box)),
|
|
28003
|
+
raster: () => rectRasterPath(fixBoxOf(box), clockwiseOf(p)),
|
|
27715
28004
|
rectangle: true,
|
|
27716
28005
|
fill: true,
|
|
27717
28006
|
stroke: true,
|
|
27718
28007
|
axisRect: { interior: rectInterior(p, box) }
|
|
27719
28008
|
});
|
|
27720
28009
|
}
|
|
28010
|
+
function compatCorner(p, w, h) {
|
|
28011
|
+
const m = gdiDeviceMatrix(p.rCtx);
|
|
28012
|
+
const cw = Math.round(Math.abs(w * m[0]) * 16);
|
|
28013
|
+
const ch = Math.round(Math.abs(h * m[3]) * 16);
|
|
28014
|
+
const ux = 16 * p.kx;
|
|
28015
|
+
const uy = 16 * p.ky;
|
|
28016
|
+
if (!penIsNull(p) && !penIsCosmetic(p.rCtx)) {
|
|
28017
|
+
return [Math.round(Math.floor(cw / (2 * ux)) * 2 * ux), Math.round(Math.floor(ch / (2 * uy)) * 2 * uy)];
|
|
28018
|
+
}
|
|
28019
|
+
return [Math.round(Math.floor(Math.round(cw / ux) / 2) * 2 * ux), Math.round(Math.floor(Math.round(ch / uy) / 2) * 2 * uy)];
|
|
28020
|
+
}
|
|
27721
28021
|
function wmfRoundRect(p, l, t, r, b, w, h) {
|
|
27722
28022
|
const box = compatBox(p, l, t, r, b, { curved: true });
|
|
27723
28023
|
if (box.x1 < box.x0 || box.y1 < box.y0) {
|
|
27724
28024
|
return;
|
|
27725
28025
|
}
|
|
27726
|
-
const
|
|
27727
|
-
let cw = Math.round(Math.abs(w * m[0]) * 16);
|
|
27728
|
-
let ch = Math.round(Math.abs(h * m[3]) * 16);
|
|
27729
|
-
if (!penIsNull(p) && !penIsCosmetic(p.rCtx)) {
|
|
27730
|
-
cw = Math.floor(cw / 32) * 32;
|
|
27731
|
-
ch = Math.floor(ch / 32) * 32;
|
|
27732
|
-
}
|
|
28026
|
+
const [cw, ch] = compatCorner(p, w, h);
|
|
27733
28027
|
const cr = canvasRect(box);
|
|
27734
28028
|
paintGdiShape(p.rCtx, {
|
|
27735
28029
|
build: (c) => {
|
|
@@ -27754,7 +28048,7 @@ function wmfRoundRect(p, l, t, r, b, w, h) {
|
|
|
27754
28048
|
c.ellipse(cr.x + ex, cr.y + ey, ex, ey, 0, 2 * q, 3 * q);
|
|
27755
28049
|
c.closePath();
|
|
27756
28050
|
},
|
|
27757
|
-
raster: () => roundRectRasterPath(fixBoxOf(box), cw, ch),
|
|
28051
|
+
raster: () => roundRectRasterPath(fixBoxOf(box), cw, ch, clockwiseOf(p), w === 0 || h === 0),
|
|
27758
28052
|
roundPen: true,
|
|
27759
28053
|
fill: true,
|
|
27760
28054
|
stroke: true
|
|
@@ -27771,24 +28065,31 @@ function wmfEllipse(p, l, t, r, b) {
|
|
|
27771
28065
|
c.beginPath();
|
|
27772
28066
|
c.ellipse(cr.x + cr.w / 2, cr.y + cr.h / 2, cr.w / 2, cr.h / 2, 0, 0, Math.PI * 2);
|
|
27773
28067
|
},
|
|
27774
|
-
raster: () => ellipseRasterPath(fixBoxOf(box)),
|
|
28068
|
+
raster: () => ellipseRasterPath(fixBoxOf(box), clockwiseOf(p)),
|
|
27775
28069
|
roundPen: true,
|
|
27776
28070
|
fill: true,
|
|
27777
28071
|
stroke: true
|
|
27778
28072
|
});
|
|
27779
28073
|
}
|
|
27780
|
-
function
|
|
27781
|
-
const box = compatBox(p, l, t, r, b, { curved: kind
|
|
28074
|
+
function compatArc(p, kind, l, t, r, b, xs, ys, xe, ye) {
|
|
28075
|
+
const box = compatBox(p, l, t, r, b, { curved: kind === "chord" || kind === "pie" });
|
|
27782
28076
|
if (box.x1 < box.x0 || box.y1 < box.y0) {
|
|
27783
|
-
return;
|
|
28077
|
+
return null;
|
|
27784
28078
|
}
|
|
27785
28079
|
const raw = compatBox(p, l, t, r, b, { exclusive: false });
|
|
27786
|
-
const
|
|
27787
|
-
const
|
|
27788
|
-
|
|
27789
|
-
|
|
27790
|
-
|
|
27791
|
-
|
|
28080
|
+
const onBox = (v, r0, r1, b0, b1) => (b0 + b1) / 2 + (r1 !== r0 ? (v - (r0 + r1) / 2) * (b1 - b0) / (r1 - r0) : v - (r0 + r1) / 2);
|
|
28081
|
+
const radial = (x, y) => {
|
|
28082
|
+
const [fx, fy] = fixPoint(p.rCtx, x, y);
|
|
28083
|
+
return [onBox(fx, raw.x0, raw.x1, box.x0, box.x1), onBox(fy, raw.y0, raw.y1, box.y0, box.y1)];
|
|
28084
|
+
};
|
|
28085
|
+
return { box, s: radial(xs, ys), e: radial(xe, ye) };
|
|
28086
|
+
}
|
|
28087
|
+
function wmfArcFamily(p, kind, l, t, r, b, xs, ys, xe, ye) {
|
|
28088
|
+
const geom = compatArc(p, kind, l, t, r, b, xs, ys, xe, ye);
|
|
28089
|
+
if (!geom) {
|
|
28090
|
+
return;
|
|
28091
|
+
}
|
|
28092
|
+
const { box, s, e } = geom;
|
|
27792
28093
|
const clockwise = p.rCtx.state.arcDirection === 2;
|
|
27793
28094
|
const cr = canvasRect(box);
|
|
27794
28095
|
const cx = cr.x + cr.w / 2;
|
|
@@ -27814,6 +28115,9 @@ function wmfArcFamily(p, kind, l, t, r, b, xs, ys, xe, ye) {
|
|
|
27814
28115
|
stroke: true
|
|
27815
28116
|
});
|
|
27816
28117
|
}
|
|
28118
|
+
function clockwiseOf(p) {
|
|
28119
|
+
return p.rCtx.state.arcDirection === 2;
|
|
28120
|
+
}
|
|
27817
28121
|
function penIsNull(p) {
|
|
27818
28122
|
return (p.rCtx.state.penStyle & 15) === PS_NULL3;
|
|
27819
28123
|
}
|