@effing/canvas 0.22.0 → 0.22.1
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/index.js +67 -42
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1041,6 +1041,7 @@ function drawBoxShadow(ctx, x, y, width, height, boxShadow, borderRadius) {
|
|
|
1041
1041
|
|
|
1042
1042
|
// src/jsx/draw/svg.ts
|
|
1043
1043
|
import { Path2D } from "@napi-rs/canvas";
|
|
1044
|
+
import parseCssColor from "parse-css-color";
|
|
1044
1045
|
function resolveCurrentColor(value, color) {
|
|
1045
1046
|
if (value?.toLowerCase() === "currentcolor") return color;
|
|
1046
1047
|
return value;
|
|
@@ -1098,10 +1099,10 @@ function parseFrac(value, fallback) {
|
|
|
1098
1099
|
}
|
|
1099
1100
|
function applyOpacity(color, opacity) {
|
|
1100
1101
|
if (opacity >= 1) return color;
|
|
1101
|
-
const
|
|
1102
|
-
if (
|
|
1103
|
-
|
|
1104
|
-
return
|
|
1102
|
+
const parsed = parseCssColor(color);
|
|
1103
|
+
if (!parsed) return color;
|
|
1104
|
+
const [r, g, b] = parsed.values;
|
|
1105
|
+
return `rgba(${r}, ${g}, ${b}, ${parsed.alpha * opacity})`;
|
|
1105
1106
|
}
|
|
1106
1107
|
function addGradientStops(gradient, def) {
|
|
1107
1108
|
for (const stop of normalizeChildren(def)) {
|
|
@@ -1438,7 +1439,14 @@ function drawSvgContainer(ctx, node, x, y, width, height) {
|
|
|
1438
1439
|
}
|
|
1439
1440
|
const color = node.style.color ?? "black";
|
|
1440
1441
|
const merged = mergeStyleIntoProps(node.props);
|
|
1441
|
-
const
|
|
1442
|
+
const inherited = {
|
|
1443
|
+
fill: resolveCurrentColor(merged.fill, color) ?? "black",
|
|
1444
|
+
stroke: resolveCurrentColor(merged.stroke, color),
|
|
1445
|
+
strokeWidth: merged.strokeWidth ?? merged["stroke-width"],
|
|
1446
|
+
strokeLinecap: merged.strokeLinecap ?? merged["stroke-linecap"],
|
|
1447
|
+
strokeLinejoin: merged.strokeLinejoin ?? merged["stroke-linejoin"],
|
|
1448
|
+
strokeOpacity: merged.strokeOpacity ?? merged["stroke-opacity"]
|
|
1449
|
+
};
|
|
1442
1450
|
const children = node.props.children;
|
|
1443
1451
|
if (children != null) {
|
|
1444
1452
|
const childArray = Array.isArray(children) ? children : [children];
|
|
@@ -1447,7 +1455,7 @@ function drawSvgContainer(ctx, node, x, y, width, height) {
|
|
|
1447
1455
|
);
|
|
1448
1456
|
const defs = collectDefs(svgChildren);
|
|
1449
1457
|
for (const child of svgChildren) {
|
|
1450
|
-
drawSvgChild(ctx, child,
|
|
1458
|
+
drawSvgChild(ctx, child, inherited, color, defs, vbW, vbH);
|
|
1451
1459
|
}
|
|
1452
1460
|
}
|
|
1453
1461
|
ctx.restore();
|
|
@@ -1604,7 +1612,7 @@ function applyFilter(filterDef, sourceGraphic, w, h) {
|
|
|
1604
1612
|
}
|
|
1605
1613
|
return lastResult;
|
|
1606
1614
|
}
|
|
1607
|
-
function drawSvgChild(ctx, child,
|
|
1615
|
+
function drawSvgChild(ctx, child, inherited, color, defs = EMPTY_DEFS, vbW = 0, vbH = 0) {
|
|
1608
1616
|
const { type } = child;
|
|
1609
1617
|
const props = mergeStyleIntoProps(child.props);
|
|
1610
1618
|
if (type === "defs" || type === "clipPath" || type === "mask" || type === "filter")
|
|
@@ -1632,28 +1640,28 @@ function drawSvgChild(ctx, child, inheritedFill, color, defs = EMPTY_DEFS, vbW =
|
|
|
1632
1640
|
})() : ctx;
|
|
1633
1641
|
switch (type) {
|
|
1634
1642
|
case "path":
|
|
1635
|
-
drawPath(targetCtx, props,
|
|
1643
|
+
drawPath(targetCtx, props, inherited, color, defs);
|
|
1636
1644
|
break;
|
|
1637
1645
|
case "circle":
|
|
1638
|
-
drawCircle(targetCtx, props,
|
|
1646
|
+
drawCircle(targetCtx, props, inherited, color, defs, vbW, vbH);
|
|
1639
1647
|
break;
|
|
1640
1648
|
case "rect":
|
|
1641
|
-
drawSvgRect(targetCtx, props,
|
|
1649
|
+
drawSvgRect(targetCtx, props, inherited, color, defs, vbW, vbH);
|
|
1642
1650
|
break;
|
|
1643
1651
|
case "line":
|
|
1644
|
-
drawLine(targetCtx, props, color, defs, vbW, vbH);
|
|
1652
|
+
drawLine(targetCtx, props, inherited, color, defs, vbW, vbH);
|
|
1645
1653
|
break;
|
|
1646
1654
|
case "ellipse":
|
|
1647
|
-
drawEllipse(targetCtx, props,
|
|
1655
|
+
drawEllipse(targetCtx, props, inherited, color, defs, vbW, vbH);
|
|
1648
1656
|
break;
|
|
1649
1657
|
case "polygon":
|
|
1650
|
-
drawPolygon(targetCtx, props,
|
|
1658
|
+
drawPolygon(targetCtx, props, inherited, color, defs);
|
|
1651
1659
|
break;
|
|
1652
1660
|
case "polyline":
|
|
1653
|
-
drawPolyline(targetCtx, props,
|
|
1661
|
+
drawPolyline(targetCtx, props, inherited, color, defs);
|
|
1654
1662
|
break;
|
|
1655
1663
|
case "g":
|
|
1656
|
-
drawGroup(targetCtx, child,
|
|
1664
|
+
drawGroup(targetCtx, child, inherited, color, defs, vbW, vbH);
|
|
1657
1665
|
break;
|
|
1658
1666
|
}
|
|
1659
1667
|
if (needsOffscreen && elemCanvas) {
|
|
@@ -1663,7 +1671,15 @@ function drawSvgChild(ctx, child, inheritedFill, color, defs = EMPTY_DEFS, vbW =
|
|
|
1663
1671
|
Math.ceil(vbH)
|
|
1664
1672
|
);
|
|
1665
1673
|
for (const shape of maskShapes) {
|
|
1666
|
-
drawSvgChild(
|
|
1674
|
+
drawSvgChild(
|
|
1675
|
+
maskCtx,
|
|
1676
|
+
shape,
|
|
1677
|
+
{ fill: "white" },
|
|
1678
|
+
"white",
|
|
1679
|
+
defs,
|
|
1680
|
+
vbW,
|
|
1681
|
+
vbH
|
|
1682
|
+
);
|
|
1667
1683
|
}
|
|
1668
1684
|
targetCtx.globalCompositeOperation = "destination-in";
|
|
1669
1685
|
targetCtx.drawImage(maskCanvas, 0, 0);
|
|
@@ -1687,14 +1703,14 @@ function drawSvgChild(ctx, child, inheritedFill, color, defs = EMPTY_DEFS, vbW =
|
|
|
1687
1703
|
if (clipPath) ctx.restore();
|
|
1688
1704
|
if (transform) ctx.restore();
|
|
1689
1705
|
}
|
|
1690
|
-
function drawPath(ctx, props,
|
|
1706
|
+
function drawPath(ctx, props, inherited, color, defs) {
|
|
1691
1707
|
const d = props.d;
|
|
1692
1708
|
if (!d) return;
|
|
1693
1709
|
const path = new Path2D(d);
|
|
1694
1710
|
const bbox = pathBBox(d);
|
|
1695
|
-
applyFillAndStroke(ctx, props, path,
|
|
1711
|
+
applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox);
|
|
1696
1712
|
}
|
|
1697
|
-
function drawCircle(ctx, props,
|
|
1713
|
+
function drawCircle(ctx, props, inherited, color, defs, vbW = 0, vbH = 0) {
|
|
1698
1714
|
const cx = svgLength(props.cx, vbW);
|
|
1699
1715
|
const cy = svgLength(props.cy, vbH);
|
|
1700
1716
|
const r = svgLength(props.r, Math.min(vbW, vbH));
|
|
@@ -1702,9 +1718,9 @@ function drawCircle(ctx, props, inheritedFill, color, defs, vbW = 0, vbH = 0) {
|
|
|
1702
1718
|
const path = new Path2D();
|
|
1703
1719
|
path.arc(cx, cy, r, 0, Math.PI * 2);
|
|
1704
1720
|
const bbox = { x: cx - r, y: cy - r, width: 2 * r, height: 2 * r };
|
|
1705
|
-
applyFillAndStroke(ctx, props, path,
|
|
1721
|
+
applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox);
|
|
1706
1722
|
}
|
|
1707
|
-
function drawSvgRect(ctx, props,
|
|
1723
|
+
function drawSvgRect(ctx, props, inherited, color, defs, vbW = 0, vbH = 0) {
|
|
1708
1724
|
const x = svgLength(props.x, vbW);
|
|
1709
1725
|
const y = svgLength(props.y, vbH);
|
|
1710
1726
|
const w = svgLength(props.width, vbW);
|
|
@@ -1723,9 +1739,9 @@ function drawSvgRect(ctx, props, inheritedFill, color, defs, vbW = 0, vbH = 0) {
|
|
|
1723
1739
|
path.rect(x, y, w, h);
|
|
1724
1740
|
}
|
|
1725
1741
|
const bbox = { x, y, width: w, height: h };
|
|
1726
|
-
applyFillAndStroke(ctx, props, path,
|
|
1742
|
+
applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox);
|
|
1727
1743
|
}
|
|
1728
|
-
function drawLine(ctx, props, color, defs, vbW = 0, vbH = 0) {
|
|
1744
|
+
function drawLine(ctx, props, inherited, color, defs, vbW = 0, vbH = 0) {
|
|
1729
1745
|
const x1 = svgLength(props.x1, vbW);
|
|
1730
1746
|
const y1 = svgLength(props.y1, vbH);
|
|
1731
1747
|
const x2 = svgLength(props.x2, vbW);
|
|
@@ -1739,9 +1755,9 @@ function drawLine(ctx, props, color, defs, vbW = 0, vbH = 0) {
|
|
|
1739
1755
|
width: Math.abs(x2 - x1),
|
|
1740
1756
|
height: Math.abs(y2 - y1)
|
|
1741
1757
|
};
|
|
1742
|
-
applyStroke(ctx, props, path, color, defs, bbox);
|
|
1758
|
+
applyStroke(ctx, props, path, inherited, color, defs, bbox);
|
|
1743
1759
|
}
|
|
1744
|
-
function drawEllipse(ctx, props,
|
|
1760
|
+
function drawEllipse(ctx, props, inherited, color, defs, vbW = 0, vbH = 0) {
|
|
1745
1761
|
const cx = svgLength(props.cx, vbW);
|
|
1746
1762
|
const cy = svgLength(props.cy, vbH);
|
|
1747
1763
|
const rx = svgLength(props.rx, vbW);
|
|
@@ -1755,9 +1771,9 @@ function drawEllipse(ctx, props, inheritedFill, color, defs, vbW = 0, vbH = 0) {
|
|
|
1755
1771
|
width: 2 * rx,
|
|
1756
1772
|
height: 2 * ry
|
|
1757
1773
|
};
|
|
1758
|
-
applyFillAndStroke(ctx, props, path,
|
|
1774
|
+
applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox);
|
|
1759
1775
|
}
|
|
1760
|
-
function drawPolygon(ctx, props,
|
|
1776
|
+
function drawPolygon(ctx, props, inherited, color, defs) {
|
|
1761
1777
|
const points = parsePoints(props.points);
|
|
1762
1778
|
if (points.length < 2) return;
|
|
1763
1779
|
const path = new Path2D();
|
|
@@ -1767,9 +1783,9 @@ function drawPolygon(ctx, props, inheritedFill, color, defs) {
|
|
|
1767
1783
|
}
|
|
1768
1784
|
path.closePath();
|
|
1769
1785
|
const bbox = pointsBBox(points);
|
|
1770
|
-
applyFillAndStroke(ctx, props, path,
|
|
1786
|
+
applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox);
|
|
1771
1787
|
}
|
|
1772
|
-
function drawPolyline(ctx, props,
|
|
1788
|
+
function drawPolyline(ctx, props, inherited, color, defs) {
|
|
1773
1789
|
const points = parsePoints(props.points);
|
|
1774
1790
|
if (points.length < 2) return;
|
|
1775
1791
|
const path = new Path2D();
|
|
@@ -1778,7 +1794,7 @@ function drawPolyline(ctx, props, inheritedFill, color, defs) {
|
|
|
1778
1794
|
path.lineTo(points[i][0], points[i][1]);
|
|
1779
1795
|
}
|
|
1780
1796
|
const bbox = pointsBBox(points);
|
|
1781
|
-
applyFillAndStroke(ctx, props, path,
|
|
1797
|
+
applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox);
|
|
1782
1798
|
}
|
|
1783
1799
|
function applySvgTransform(ctx, transform) {
|
|
1784
1800
|
const re = /\b(translate|scale|rotate|skewX|skewY|matrix)\s*\(([^)]*)\)/g;
|
|
@@ -1841,11 +1857,18 @@ function applySvgTransform(ctx, transform) {
|
|
|
1841
1857
|
}
|
|
1842
1858
|
}
|
|
1843
1859
|
}
|
|
1844
|
-
function drawGroup(ctx, node,
|
|
1860
|
+
function drawGroup(ctx, node, inherited, color, defs = EMPTY_DEFS, vbW = 0, vbH = 0) {
|
|
1845
1861
|
const children = normalizeChildren(node);
|
|
1846
1862
|
if (children.length === 0) return;
|
|
1847
1863
|
const merged = mergeStyleIntoProps(node.props);
|
|
1848
|
-
const
|
|
1864
|
+
const groupInherited = {
|
|
1865
|
+
fill: resolveCurrentColor(merged.fill, color) ?? inherited.fill,
|
|
1866
|
+
stroke: resolveCurrentColor(merged.stroke, color) ?? inherited.stroke,
|
|
1867
|
+
strokeWidth: merged.strokeWidth ?? merged["stroke-width"] ?? inherited.strokeWidth,
|
|
1868
|
+
strokeLinecap: merged.strokeLinecap ?? merged["stroke-linecap"] ?? inherited.strokeLinecap,
|
|
1869
|
+
strokeLinejoin: merged.strokeLinejoin ?? merged["stroke-linejoin"] ?? inherited.strokeLinejoin,
|
|
1870
|
+
strokeOpacity: merged.strokeOpacity ?? merged["stroke-opacity"] ?? inherited.strokeOpacity
|
|
1871
|
+
};
|
|
1849
1872
|
const transform = merged.transform;
|
|
1850
1873
|
if (transform) {
|
|
1851
1874
|
ctx.save();
|
|
@@ -1853,7 +1876,7 @@ function drawGroup(ctx, node, inheritedFill, color, defs = EMPTY_DEFS, vbW = 0,
|
|
|
1853
1876
|
}
|
|
1854
1877
|
for (const child of children) {
|
|
1855
1878
|
if (child != null && typeof child === "object") {
|
|
1856
|
-
drawSvgChild(ctx, child,
|
|
1879
|
+
drawSvgChild(ctx, child, groupInherited, color, defs, vbW, vbH);
|
|
1857
1880
|
}
|
|
1858
1881
|
}
|
|
1859
1882
|
if (transform) {
|
|
@@ -1869,8 +1892,8 @@ function parsePoints(value) {
|
|
|
1869
1892
|
}
|
|
1870
1893
|
return result;
|
|
1871
1894
|
}
|
|
1872
|
-
function applyFillAndStroke(ctx, props, path,
|
|
1873
|
-
const fill = resolveCurrentColor(props.fill, color) ??
|
|
1895
|
+
function applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox) {
|
|
1896
|
+
const fill = resolveCurrentColor(props.fill, color) ?? inherited.fill;
|
|
1874
1897
|
const fillRule = props.fillRule ?? props["fill-rule"];
|
|
1875
1898
|
const fillOpacity = Number(props.fillOpacity ?? props["fill-opacity"] ?? 1);
|
|
1876
1899
|
const fillRef = parseUrlRef(fill);
|
|
@@ -1902,17 +1925,19 @@ function applyFillAndStroke(ctx, props, path, inheritedFill, color, defs, bbox)
|
|
|
1902
1925
|
ctx.fillStyle = applyOpacity(fill, fillOpacity);
|
|
1903
1926
|
ctx.fill(path, fillRule ?? "nonzero");
|
|
1904
1927
|
}
|
|
1905
|
-
applyStroke(ctx, props, path, color, defs, bbox);
|
|
1928
|
+
applyStroke(ctx, props, path, inherited, color, defs, bbox);
|
|
1906
1929
|
}
|
|
1907
|
-
function applyStroke(ctx, props, path, color, defs, bbox) {
|
|
1908
|
-
const stroke = resolveCurrentColor(props.stroke, color);
|
|
1930
|
+
function applyStroke(ctx, props, path, inherited, color, defs, bbox) {
|
|
1931
|
+
const stroke = resolveCurrentColor(props.stroke, color) ?? inherited.stroke;
|
|
1909
1932
|
if (!stroke || stroke === "none") return;
|
|
1910
1933
|
const strokeOpacity = Number(
|
|
1911
|
-
props.strokeOpacity ?? props["stroke-opacity"] ?? 1
|
|
1934
|
+
props.strokeOpacity ?? props["stroke-opacity"] ?? inherited.strokeOpacity ?? 1
|
|
1935
|
+
);
|
|
1936
|
+
ctx.lineWidth = Number(
|
|
1937
|
+
props.strokeWidth ?? props["stroke-width"] ?? inherited.strokeWidth ?? 1
|
|
1912
1938
|
);
|
|
1913
|
-
ctx.
|
|
1914
|
-
ctx.
|
|
1915
|
-
ctx.lineJoin = props.strokeLinejoin ?? props["stroke-linejoin"] ?? "miter";
|
|
1939
|
+
ctx.lineCap = props.strokeLinecap ?? props["stroke-linecap"] ?? inherited.strokeLinecap ?? "butt";
|
|
1940
|
+
ctx.lineJoin = props.strokeLinejoin ?? props["stroke-linejoin"] ?? inherited.strokeLinejoin ?? "miter";
|
|
1916
1941
|
const strokeRef = parseUrlRef(stroke);
|
|
1917
1942
|
if (strokeRef) {
|
|
1918
1943
|
const gradientDef = defs.gradients.get(strokeRef);
|