modern-canvas 0.4.34 → 0.4.36
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.cjs +573 -15
- package/dist/index.d.cts +51 -4
- package/dist/index.d.mts +51 -4
- package/dist/index.d.ts +51 -4
- package/dist/index.js +40 -40
- package/dist/index.mjs +571 -16
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1106,6 +1106,24 @@ class Color {
|
|
|
1106
1106
|
constructor(value = 0) {
|
|
1107
1107
|
this.value = value;
|
|
1108
1108
|
}
|
|
1109
|
+
toHex() {
|
|
1110
|
+
return this._colord.toHex();
|
|
1111
|
+
}
|
|
1112
|
+
toRgb() {
|
|
1113
|
+
return this._colord.toRgb();
|
|
1114
|
+
}
|
|
1115
|
+
toRgbString() {
|
|
1116
|
+
return this._colord.toRgbString();
|
|
1117
|
+
}
|
|
1118
|
+
toHsl() {
|
|
1119
|
+
return this._colord.toHsl();
|
|
1120
|
+
}
|
|
1121
|
+
toHslString() {
|
|
1122
|
+
return this._colord.toHslString();
|
|
1123
|
+
}
|
|
1124
|
+
toHsv() {
|
|
1125
|
+
return this._colord.toHsv();
|
|
1126
|
+
}
|
|
1109
1127
|
toArgb(alpha = this.a, applyToRGB = true) {
|
|
1110
1128
|
if (alpha === 1) {
|
|
1111
1129
|
return (255 << 24) + this.rgb;
|
|
@@ -1123,9 +1141,6 @@ class Color {
|
|
|
1123
1141
|
}
|
|
1124
1142
|
return (alpha * 255 << 24) + (r << 16) + (g << 8) + b;
|
|
1125
1143
|
}
|
|
1126
|
-
toHex() {
|
|
1127
|
-
return this._colord.toHex();
|
|
1128
|
-
}
|
|
1129
1144
|
toArray() {
|
|
1130
1145
|
return [this.r, this.g, this.b, this.a];
|
|
1131
1146
|
}
|
|
@@ -1722,6 +1737,468 @@ class ColorMatrix extends Matrix {
|
|
|
1722
1737
|
}
|
|
1723
1738
|
}
|
|
1724
1739
|
|
|
1740
|
+
var GradientParser = GradientParser || {};
|
|
1741
|
+
GradientParser.parse = /* @__PURE__ */ function() {
|
|
1742
|
+
const tokens = {
|
|
1743
|
+
linearGradient: /^(-(webkit|o|ms|moz)-)?(linear-gradient)/i,
|
|
1744
|
+
repeatingLinearGradient: /^(-(webkit|o|ms|moz)-)?(repeating-linear-gradient)/i,
|
|
1745
|
+
radialGradient: /^(-(webkit|o|ms|moz)-)?(radial-gradient)/i,
|
|
1746
|
+
repeatingRadialGradient: /^(-(webkit|o|ms|moz)-)?(repeating-radial-gradient)/i,
|
|
1747
|
+
sideOrCorner: /^to (left (top|bottom)|right (top|bottom)|top (left|right)|bottom (left|right)|left|right|top|bottom)/i,
|
|
1748
|
+
extentKeywords: /^(closest-side|closest-corner|farthest-side|farthest-corner|contain|cover)/,
|
|
1749
|
+
positionKeywords: /^(left|center|right|top|bottom)/i,
|
|
1750
|
+
pixelValue: /^(-?((\d*\.\d+)|(\d+\.?)))px/,
|
|
1751
|
+
percentageValue: /^(-?((\d*\.\d+)|(\d+\.?)))%/,
|
|
1752
|
+
emValue: /^(-?((\d*\.\d+)|(\d+\.?)))em/,
|
|
1753
|
+
angleValue: /^(-?((\d*\.\d+)|(\d+\.?)))deg/,
|
|
1754
|
+
radianValue: /^(-?((\d*\.\d+)|(\d+\.?)))rad/,
|
|
1755
|
+
startCall: /^\(/,
|
|
1756
|
+
endCall: /^\)/,
|
|
1757
|
+
comma: /^,/,
|
|
1758
|
+
hexColor: /^#([0-9a-f]+)/i,
|
|
1759
|
+
literalColor: /^([a-z]+)/i,
|
|
1760
|
+
rgbColor: /^rgb/i,
|
|
1761
|
+
rgbaColor: /^rgba/i,
|
|
1762
|
+
varColor: /^var/i,
|
|
1763
|
+
calcValue: /^calc/i,
|
|
1764
|
+
variableName: /^(--[a-z0-9-,\s#]+)/i,
|
|
1765
|
+
number: /^((\d*\.\d+)|(\d+\.?))/,
|
|
1766
|
+
hslColor: /^hsl/i,
|
|
1767
|
+
hslaColor: /^hsla/i
|
|
1768
|
+
};
|
|
1769
|
+
let input = "";
|
|
1770
|
+
function error(msg) {
|
|
1771
|
+
const err = new Error(`${input}: ${msg}`);
|
|
1772
|
+
err.source = input;
|
|
1773
|
+
throw err;
|
|
1774
|
+
}
|
|
1775
|
+
function getAST() {
|
|
1776
|
+
const ast = matchListDefinitions();
|
|
1777
|
+
if (input.length > 0) {
|
|
1778
|
+
error("Invalid input not EOF");
|
|
1779
|
+
}
|
|
1780
|
+
return ast;
|
|
1781
|
+
}
|
|
1782
|
+
function matchListDefinitions() {
|
|
1783
|
+
return matchListing(matchDefinition);
|
|
1784
|
+
}
|
|
1785
|
+
function matchDefinition() {
|
|
1786
|
+
return matchGradient(
|
|
1787
|
+
"linear-gradient",
|
|
1788
|
+
tokens.linearGradient,
|
|
1789
|
+
matchLinearOrientation
|
|
1790
|
+
) || matchGradient(
|
|
1791
|
+
"repeating-linear-gradient",
|
|
1792
|
+
tokens.repeatingLinearGradient,
|
|
1793
|
+
matchLinearOrientation
|
|
1794
|
+
) || matchGradient(
|
|
1795
|
+
"radial-gradient",
|
|
1796
|
+
tokens.radialGradient,
|
|
1797
|
+
matchListRadialOrientations
|
|
1798
|
+
) || matchGradient(
|
|
1799
|
+
"repeating-radial-gradient",
|
|
1800
|
+
tokens.repeatingRadialGradient,
|
|
1801
|
+
matchListRadialOrientations
|
|
1802
|
+
);
|
|
1803
|
+
}
|
|
1804
|
+
function matchGradient(gradientType, pattern, orientationMatcher) {
|
|
1805
|
+
return matchCall(pattern, (captures) => {
|
|
1806
|
+
const orientation = orientationMatcher();
|
|
1807
|
+
if (orientation) {
|
|
1808
|
+
if (!scan(tokens.comma)) {
|
|
1809
|
+
error("Missing comma before color stops");
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
return {
|
|
1813
|
+
type: gradientType,
|
|
1814
|
+
orientation,
|
|
1815
|
+
colorStops: matchListing(matchColorStop)
|
|
1816
|
+
};
|
|
1817
|
+
});
|
|
1818
|
+
}
|
|
1819
|
+
function matchCall(pattern, callback) {
|
|
1820
|
+
const captures = scan(pattern);
|
|
1821
|
+
if (captures) {
|
|
1822
|
+
if (!scan(tokens.startCall)) {
|
|
1823
|
+
error("Missing (");
|
|
1824
|
+
}
|
|
1825
|
+
const result = callback(captures);
|
|
1826
|
+
if (!scan(tokens.endCall)) {
|
|
1827
|
+
error("Missing )");
|
|
1828
|
+
}
|
|
1829
|
+
return result;
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
function matchLinearOrientation() {
|
|
1833
|
+
const sideOrCorner = matchSideOrCorner();
|
|
1834
|
+
if (sideOrCorner) {
|
|
1835
|
+
return sideOrCorner;
|
|
1836
|
+
}
|
|
1837
|
+
const legacyDirection = match("position-keyword", tokens.positionKeywords, 1);
|
|
1838
|
+
if (legacyDirection) {
|
|
1839
|
+
return {
|
|
1840
|
+
type: "directional",
|
|
1841
|
+
value: legacyDirection.value
|
|
1842
|
+
};
|
|
1843
|
+
}
|
|
1844
|
+
return matchAngle();
|
|
1845
|
+
}
|
|
1846
|
+
function matchSideOrCorner() {
|
|
1847
|
+
return match("directional", tokens.sideOrCorner, 1);
|
|
1848
|
+
}
|
|
1849
|
+
function matchAngle() {
|
|
1850
|
+
return match("angular", tokens.angleValue, 1) || match("angular", tokens.radianValue, 1);
|
|
1851
|
+
}
|
|
1852
|
+
function matchListRadialOrientations() {
|
|
1853
|
+
let radialOrientations;
|
|
1854
|
+
let radialOrientation = matchRadialOrientation();
|
|
1855
|
+
let lookaheadCache;
|
|
1856
|
+
if (radialOrientation) {
|
|
1857
|
+
radialOrientations = [];
|
|
1858
|
+
radialOrientations.push(radialOrientation);
|
|
1859
|
+
lookaheadCache = input;
|
|
1860
|
+
if (scan(tokens.comma)) {
|
|
1861
|
+
radialOrientation = matchRadialOrientation();
|
|
1862
|
+
if (radialOrientation) {
|
|
1863
|
+
radialOrientations.push(radialOrientation);
|
|
1864
|
+
} else {
|
|
1865
|
+
input = lookaheadCache;
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
return radialOrientations;
|
|
1870
|
+
}
|
|
1871
|
+
function matchRadialOrientation() {
|
|
1872
|
+
let radialType = matchCircle() || matchEllipse();
|
|
1873
|
+
if (radialType) {
|
|
1874
|
+
radialType.at = matchAtPosition();
|
|
1875
|
+
} else {
|
|
1876
|
+
const extent = matchExtentKeyword();
|
|
1877
|
+
if (extent) {
|
|
1878
|
+
radialType = extent;
|
|
1879
|
+
const positionAt = matchAtPosition();
|
|
1880
|
+
if (positionAt) {
|
|
1881
|
+
radialType.at = positionAt;
|
|
1882
|
+
}
|
|
1883
|
+
} else {
|
|
1884
|
+
const atPosition = matchAtPosition();
|
|
1885
|
+
if (atPosition) {
|
|
1886
|
+
radialType = {
|
|
1887
|
+
type: "default-radial",
|
|
1888
|
+
at: atPosition
|
|
1889
|
+
};
|
|
1890
|
+
} else {
|
|
1891
|
+
const defaultPosition = matchPositioning();
|
|
1892
|
+
if (defaultPosition) {
|
|
1893
|
+
radialType = {
|
|
1894
|
+
type: "default-radial",
|
|
1895
|
+
at: defaultPosition
|
|
1896
|
+
};
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
return radialType;
|
|
1902
|
+
}
|
|
1903
|
+
function matchCircle() {
|
|
1904
|
+
const circle = match("shape", /^(circle)/i, 0);
|
|
1905
|
+
if (circle) {
|
|
1906
|
+
circle.style = matchLength() || matchExtentKeyword();
|
|
1907
|
+
}
|
|
1908
|
+
return circle;
|
|
1909
|
+
}
|
|
1910
|
+
function matchEllipse() {
|
|
1911
|
+
const ellipse = match("shape", /^(ellipse)/i, 0);
|
|
1912
|
+
if (ellipse) {
|
|
1913
|
+
ellipse.style = matchPositioning() || matchDistance() || matchExtentKeyword();
|
|
1914
|
+
}
|
|
1915
|
+
return ellipse;
|
|
1916
|
+
}
|
|
1917
|
+
function matchExtentKeyword() {
|
|
1918
|
+
return match("extent-keyword", tokens.extentKeywords, 1);
|
|
1919
|
+
}
|
|
1920
|
+
function matchAtPosition() {
|
|
1921
|
+
if (match("position", /^at/, 0)) {
|
|
1922
|
+
const positioning = matchPositioning();
|
|
1923
|
+
if (!positioning) {
|
|
1924
|
+
error("Missing positioning value");
|
|
1925
|
+
}
|
|
1926
|
+
return positioning;
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
function matchPositioning() {
|
|
1930
|
+
const location = matchCoordinates();
|
|
1931
|
+
if (location.x || location.y) {
|
|
1932
|
+
return {
|
|
1933
|
+
type: "position",
|
|
1934
|
+
value: location
|
|
1935
|
+
};
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
function matchCoordinates() {
|
|
1939
|
+
return {
|
|
1940
|
+
x: matchDistance(),
|
|
1941
|
+
y: matchDistance()
|
|
1942
|
+
};
|
|
1943
|
+
}
|
|
1944
|
+
function matchListing(matcher) {
|
|
1945
|
+
let captures = matcher();
|
|
1946
|
+
const result = [];
|
|
1947
|
+
if (captures) {
|
|
1948
|
+
result.push(captures);
|
|
1949
|
+
while (scan(tokens.comma)) {
|
|
1950
|
+
captures = matcher();
|
|
1951
|
+
if (captures) {
|
|
1952
|
+
result.push(captures);
|
|
1953
|
+
} else {
|
|
1954
|
+
error("One extra comma");
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
return result;
|
|
1959
|
+
}
|
|
1960
|
+
function matchColorStop() {
|
|
1961
|
+
const color = matchColor();
|
|
1962
|
+
if (!color) {
|
|
1963
|
+
error("Expected color definition");
|
|
1964
|
+
}
|
|
1965
|
+
color.length = matchDistance();
|
|
1966
|
+
return color;
|
|
1967
|
+
}
|
|
1968
|
+
function matchColor() {
|
|
1969
|
+
return matchHexColor() || matchHSLAColor() || matchHSLColor() || matchRGBAColor() || matchRGBColor() || matchVarColor() || matchLiteralColor();
|
|
1970
|
+
}
|
|
1971
|
+
function matchLiteralColor() {
|
|
1972
|
+
return match("literal", tokens.literalColor, 0);
|
|
1973
|
+
}
|
|
1974
|
+
function matchHexColor() {
|
|
1975
|
+
return match("hex", tokens.hexColor, 1);
|
|
1976
|
+
}
|
|
1977
|
+
function matchRGBColor() {
|
|
1978
|
+
return matchCall(tokens.rgbColor, () => {
|
|
1979
|
+
return {
|
|
1980
|
+
type: "rgb",
|
|
1981
|
+
value: matchListing(matchNumber)
|
|
1982
|
+
};
|
|
1983
|
+
});
|
|
1984
|
+
}
|
|
1985
|
+
function matchRGBAColor() {
|
|
1986
|
+
return matchCall(tokens.rgbaColor, () => {
|
|
1987
|
+
return {
|
|
1988
|
+
type: "rgba",
|
|
1989
|
+
value: matchListing(matchNumber)
|
|
1990
|
+
};
|
|
1991
|
+
});
|
|
1992
|
+
}
|
|
1993
|
+
function matchVarColor() {
|
|
1994
|
+
return matchCall(tokens.varColor, () => {
|
|
1995
|
+
return {
|
|
1996
|
+
type: "var",
|
|
1997
|
+
value: matchVariableName()
|
|
1998
|
+
};
|
|
1999
|
+
});
|
|
2000
|
+
}
|
|
2001
|
+
function matchHSLColor() {
|
|
2002
|
+
return matchCall(tokens.hslColor, () => {
|
|
2003
|
+
const lookahead = scan(tokens.percentageValue);
|
|
2004
|
+
if (lookahead) {
|
|
2005
|
+
error("HSL hue value must be a number in degrees (0-360) or normalized (-360 to 360), not a percentage");
|
|
2006
|
+
}
|
|
2007
|
+
const hue = matchNumber();
|
|
2008
|
+
scan(tokens.comma);
|
|
2009
|
+
let captures = scan(tokens.percentageValue);
|
|
2010
|
+
const sat = captures ? captures[1] : null;
|
|
2011
|
+
scan(tokens.comma);
|
|
2012
|
+
captures = scan(tokens.percentageValue);
|
|
2013
|
+
const light = captures ? captures[1] : null;
|
|
2014
|
+
if (!sat || !light) {
|
|
2015
|
+
error("Expected percentage value for saturation and lightness in HSL");
|
|
2016
|
+
}
|
|
2017
|
+
return {
|
|
2018
|
+
type: "hsl",
|
|
2019
|
+
value: [hue, sat, light]
|
|
2020
|
+
};
|
|
2021
|
+
});
|
|
2022
|
+
}
|
|
2023
|
+
function matchHSLAColor() {
|
|
2024
|
+
return matchCall(tokens.hslaColor, () => {
|
|
2025
|
+
const hue = matchNumber();
|
|
2026
|
+
scan(tokens.comma);
|
|
2027
|
+
let captures = scan(tokens.percentageValue);
|
|
2028
|
+
const sat = captures ? captures[1] : null;
|
|
2029
|
+
scan(tokens.comma);
|
|
2030
|
+
captures = scan(tokens.percentageValue);
|
|
2031
|
+
const light = captures ? captures[1] : null;
|
|
2032
|
+
scan(tokens.comma);
|
|
2033
|
+
const alpha = matchNumber();
|
|
2034
|
+
if (!sat || !light) {
|
|
2035
|
+
error("Expected percentage value for saturation and lightness in HSLA");
|
|
2036
|
+
}
|
|
2037
|
+
return {
|
|
2038
|
+
type: "hsla",
|
|
2039
|
+
value: [hue, sat, light, alpha]
|
|
2040
|
+
};
|
|
2041
|
+
});
|
|
2042
|
+
}
|
|
2043
|
+
function matchVariableName() {
|
|
2044
|
+
return scan(tokens.variableName)[1];
|
|
2045
|
+
}
|
|
2046
|
+
function matchNumber() {
|
|
2047
|
+
return scan(tokens.number)[1];
|
|
2048
|
+
}
|
|
2049
|
+
function matchDistance() {
|
|
2050
|
+
return match("%", tokens.percentageValue, 1) || matchPositionKeyword() || matchCalc() || matchLength();
|
|
2051
|
+
}
|
|
2052
|
+
function matchPositionKeyword() {
|
|
2053
|
+
return match("position-keyword", tokens.positionKeywords, 1);
|
|
2054
|
+
}
|
|
2055
|
+
function matchCalc() {
|
|
2056
|
+
return matchCall(tokens.calcValue, () => {
|
|
2057
|
+
let openParenCount = 1;
|
|
2058
|
+
let i = 0;
|
|
2059
|
+
while (openParenCount > 0 && i < input.length) {
|
|
2060
|
+
const char = input.charAt(i);
|
|
2061
|
+
if (char === "(") {
|
|
2062
|
+
openParenCount++;
|
|
2063
|
+
} else if (char === ")") {
|
|
2064
|
+
openParenCount--;
|
|
2065
|
+
}
|
|
2066
|
+
i++;
|
|
2067
|
+
}
|
|
2068
|
+
if (openParenCount > 0) {
|
|
2069
|
+
error("Missing closing parenthesis in calc() expression");
|
|
2070
|
+
}
|
|
2071
|
+
const calcContent = input.substring(0, i - 1);
|
|
2072
|
+
consume(i - 1);
|
|
2073
|
+
return {
|
|
2074
|
+
type: "calc",
|
|
2075
|
+
value: calcContent
|
|
2076
|
+
};
|
|
2077
|
+
});
|
|
2078
|
+
}
|
|
2079
|
+
function matchLength() {
|
|
2080
|
+
return match("px", tokens.pixelValue, 1) || match("em", tokens.emValue, 1);
|
|
2081
|
+
}
|
|
2082
|
+
function match(type, pattern, captureIndex) {
|
|
2083
|
+
const captures = scan(pattern);
|
|
2084
|
+
if (captures) {
|
|
2085
|
+
return {
|
|
2086
|
+
type,
|
|
2087
|
+
value: captures[captureIndex]
|
|
2088
|
+
};
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
function scan(regexp) {
|
|
2092
|
+
let captures, blankCaptures;
|
|
2093
|
+
blankCaptures = /^\s+/.exec(input);
|
|
2094
|
+
if (blankCaptures) {
|
|
2095
|
+
consume(blankCaptures[0].length);
|
|
2096
|
+
}
|
|
2097
|
+
captures = regexp.exec(input);
|
|
2098
|
+
if (captures) {
|
|
2099
|
+
consume(captures[0].length);
|
|
2100
|
+
}
|
|
2101
|
+
return captures;
|
|
2102
|
+
}
|
|
2103
|
+
function consume(size) {
|
|
2104
|
+
input = input.substr(size);
|
|
2105
|
+
}
|
|
2106
|
+
return function(code) {
|
|
2107
|
+
input = code.toString().trim();
|
|
2108
|
+
if (input.endsWith(";")) {
|
|
2109
|
+
input = input.slice(0, -1);
|
|
2110
|
+
}
|
|
2111
|
+
return getAST();
|
|
2112
|
+
};
|
|
2113
|
+
}();
|
|
2114
|
+
const parseGradient = GradientParser.parse.bind(GradientParser);
|
|
2115
|
+
|
|
2116
|
+
class LinearGradient {
|
|
2117
|
+
constructor(x0, y0, x1, y1, stops) {
|
|
2118
|
+
this.x0 = x0;
|
|
2119
|
+
this.y0 = y0;
|
|
2120
|
+
this.x1 = x1;
|
|
2121
|
+
this.y1 = y1;
|
|
2122
|
+
this.stops = stops;
|
|
2123
|
+
}
|
|
2124
|
+
static from(css) {
|
|
2125
|
+
let angleDeg = 0;
|
|
2126
|
+
const stops = [];
|
|
2127
|
+
const ast = parseGradient(css)[0];
|
|
2128
|
+
if (ast.type === "linear-gradient") {
|
|
2129
|
+
switch (ast?.orientation?.type) {
|
|
2130
|
+
case "angular":
|
|
2131
|
+
angleDeg = Number(ast.orientation.value);
|
|
2132
|
+
break;
|
|
2133
|
+
}
|
|
2134
|
+
ast.colorStops.forEach((stop) => {
|
|
2135
|
+
let offset = 0;
|
|
2136
|
+
let color = "rgba(0, 0, 0, 0)";
|
|
2137
|
+
switch (stop.type) {
|
|
2138
|
+
case "rgb":
|
|
2139
|
+
color = `rgb(${stop.value[0]}, ${stop.value[1]}, ${stop.value[2]})`;
|
|
2140
|
+
break;
|
|
2141
|
+
case "rgba":
|
|
2142
|
+
color = `rgba(${stop.value[0]}, ${stop.value[1]}, ${stop.value[2]}, ${stop.value[3]})`;
|
|
2143
|
+
break;
|
|
2144
|
+
case "literal":
|
|
2145
|
+
color = stop.value;
|
|
2146
|
+
break;
|
|
2147
|
+
case "hex":
|
|
2148
|
+
color = stop.value;
|
|
2149
|
+
break;
|
|
2150
|
+
}
|
|
2151
|
+
switch (stop.length?.type) {
|
|
2152
|
+
case "%":
|
|
2153
|
+
offset = Number(stop.length.value) / 100;
|
|
2154
|
+
break;
|
|
2155
|
+
}
|
|
2156
|
+
stops.push({ offset, color });
|
|
2157
|
+
});
|
|
2158
|
+
}
|
|
2159
|
+
const angleRad = (angleDeg + 90) * Math.PI / 180;
|
|
2160
|
+
const width = 1;
|
|
2161
|
+
const height = 1;
|
|
2162
|
+
const halfWidth = width / 2;
|
|
2163
|
+
const halfHeight = height / 2;
|
|
2164
|
+
const length = Math.sqrt(width * width + height * height) / 2;
|
|
2165
|
+
const x0 = halfWidth + length * Math.cos(angleRad + Math.PI);
|
|
2166
|
+
const y0 = halfHeight + length * Math.sin(angleRad + Math.PI);
|
|
2167
|
+
const x1 = halfWidth + length * Math.cos(angleRad);
|
|
2168
|
+
const y1 = halfHeight + length * Math.sin(angleRad);
|
|
2169
|
+
return new LinearGradient(x0, y0, x1, y1, stops);
|
|
2170
|
+
}
|
|
2171
|
+
parse(width, height) {
|
|
2172
|
+
return this._parseByCanvas(width, height);
|
|
2173
|
+
}
|
|
2174
|
+
_parseByCanvas(width, height) {
|
|
2175
|
+
const canvas = document.createElement("canvas");
|
|
2176
|
+
canvas.width = width;
|
|
2177
|
+
canvas.height = height;
|
|
2178
|
+
const ctx = canvas.getContext("2d");
|
|
2179
|
+
if (!ctx) {
|
|
2180
|
+
throw new Error("Failed to parse linear gradient, get canvas context is null.");
|
|
2181
|
+
}
|
|
2182
|
+
const gradient = ctx.createLinearGradient(
|
|
2183
|
+
this.x0 * width,
|
|
2184
|
+
this.y0 * height,
|
|
2185
|
+
this.x1 * width,
|
|
2186
|
+
this.y1 * height
|
|
2187
|
+
);
|
|
2188
|
+
this.stops.forEach((stop) => {
|
|
2189
|
+
gradient.addColorStop(stop.offset, stop.color);
|
|
2190
|
+
});
|
|
2191
|
+
ctx.fillStyle = gradient;
|
|
2192
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
2193
|
+
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
2194
|
+
return {
|
|
2195
|
+
width: imageData.width,
|
|
2196
|
+
height: imageData.height,
|
|
2197
|
+
pixels: new Uint8Array(imageData.data.buffer)
|
|
2198
|
+
};
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2201
|
+
|
|
1725
2202
|
class Matrix2 extends Matrix {
|
|
1726
2203
|
constructor(array) {
|
|
1727
2204
|
super(2, 2, array);
|
|
@@ -1826,6 +2303,47 @@ class Projection2D extends Matrix3 {
|
|
|
1826
2303
|
}
|
|
1827
2304
|
}
|
|
1828
2305
|
|
|
2306
|
+
class RadialGradient {
|
|
2307
|
+
constructor(x0, y0, r0, x1, y1, r1, stops) {
|
|
2308
|
+
this.x0 = x0;
|
|
2309
|
+
this.y0 = y0;
|
|
2310
|
+
this.r0 = r0;
|
|
2311
|
+
this.x1 = x1;
|
|
2312
|
+
this.y1 = y1;
|
|
2313
|
+
this.r1 = r1;
|
|
2314
|
+
this.stops = stops;
|
|
2315
|
+
}
|
|
2316
|
+
parse(width, height) {
|
|
2317
|
+
return this._parseByCanvas(width, height);
|
|
2318
|
+
}
|
|
2319
|
+
_parseByCanvas(width, height) {
|
|
2320
|
+
const canvas = document.createElement("canvas");
|
|
2321
|
+
const ctx = canvas.getContext("2d");
|
|
2322
|
+
if (!ctx) {
|
|
2323
|
+
throw new Error("Failed to parse radial gradient, get canvas context is null.");
|
|
2324
|
+
}
|
|
2325
|
+
const gradient = ctx.createRadialGradient(
|
|
2326
|
+
this.x0 * width,
|
|
2327
|
+
this.y0 * height,
|
|
2328
|
+
this.r0,
|
|
2329
|
+
this.x1 * width,
|
|
2330
|
+
this.y1 * height,
|
|
2331
|
+
this.r1
|
|
2332
|
+
);
|
|
2333
|
+
this.stops.forEach((stop) => {
|
|
2334
|
+
gradient.addColorStop(stop.offset, stop.color);
|
|
2335
|
+
});
|
|
2336
|
+
ctx.fillStyle = gradient;
|
|
2337
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
2338
|
+
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
2339
|
+
return {
|
|
2340
|
+
width: imageData.width,
|
|
2341
|
+
height: imageData.height,
|
|
2342
|
+
pixels: new Uint8Array(imageData.data.buffer)
|
|
2343
|
+
};
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
|
|
1829
2347
|
class Vector2 extends Vector {
|
|
1830
2348
|
get x() {
|
|
1831
2349
|
return this._array[0];
|
|
@@ -5130,6 +5648,23 @@ class ColorTexture extends Texture2D {
|
|
|
5130
5648
|
}
|
|
5131
5649
|
}
|
|
5132
5650
|
|
|
5651
|
+
class GradientTexture extends Texture2D {
|
|
5652
|
+
// |(radial-gradient)
|
|
5653
|
+
static regExp = /(linear-gradient)/;
|
|
5654
|
+
static test(value) {
|
|
5655
|
+
return this.regExp.test(value);
|
|
5656
|
+
}
|
|
5657
|
+
constructor(value, width, height) {
|
|
5658
|
+
if (width === Infinity)
|
|
5659
|
+
width = 0;
|
|
5660
|
+
if (height === Infinity)
|
|
5661
|
+
height = 0;
|
|
5662
|
+
super(
|
|
5663
|
+
LinearGradient.from(value).parse(width, height)
|
|
5664
|
+
);
|
|
5665
|
+
}
|
|
5666
|
+
}
|
|
5667
|
+
|
|
5133
5668
|
function resolveOptions$1(options) {
|
|
5134
5669
|
return {
|
|
5135
5670
|
autoLoad: Boolean(options?.autoLoad ?? true),
|
|
@@ -5572,6 +6107,21 @@ let Node = class extends CoreObject {
|
|
|
5572
6107
|
}).append(nodes);
|
|
5573
6108
|
this.on("treeEnter", this._onTreeEnter).on("treeExit", this._onTreeExit).on("parented", this._onParented).on("unparented", this._onUnparented).on("ready", this._onReady).on("process", this._onProcess);
|
|
5574
6109
|
}
|
|
6110
|
+
setProperties(properties) {
|
|
6111
|
+
if (properties) {
|
|
6112
|
+
const {
|
|
6113
|
+
meta,
|
|
6114
|
+
...restProperties
|
|
6115
|
+
} = properties;
|
|
6116
|
+
if (meta) {
|
|
6117
|
+
for (const key in meta) {
|
|
6118
|
+
this.setMeta(key, meta[key]);
|
|
6119
|
+
}
|
|
6120
|
+
}
|
|
6121
|
+
super.setProperties(restProperties);
|
|
6122
|
+
}
|
|
6123
|
+
return this;
|
|
6124
|
+
}
|
|
5575
6125
|
/** Name */
|
|
5576
6126
|
getName() {
|
|
5577
6127
|
return this.name;
|
|
@@ -7066,20 +7616,27 @@ class CanvasContext extends Path2D {
|
|
|
7066
7616
|
miterLimit;
|
|
7067
7617
|
_defaultStyle = Texture2D.EMPTY;
|
|
7068
7618
|
_draws = [];
|
|
7619
|
+
_colorToTexture(color, width, height) {
|
|
7620
|
+
if (color instanceof Texture2D) {
|
|
7621
|
+
return color;
|
|
7622
|
+
} else if (typeof color === "string" && GradientTexture.test(color)) {
|
|
7623
|
+
return new GradientTexture(color, width, height);
|
|
7624
|
+
} else {
|
|
7625
|
+
return new ColorTexture(color);
|
|
7626
|
+
}
|
|
7627
|
+
}
|
|
7069
7628
|
stroke(options) {
|
|
7629
|
+
const path = new Path2D(this);
|
|
7070
7630
|
let texture = this._defaultStyle;
|
|
7071
7631
|
if (this.strokeStyle) {
|
|
7072
|
-
|
|
7073
|
-
|
|
7074
|
-
} else {
|
|
7075
|
-
texture = new ColorTexture(this.strokeStyle);
|
|
7076
|
-
}
|
|
7632
|
+
const { width, height } = path.getBoundingBox();
|
|
7633
|
+
texture = this._colorToTexture(this.strokeStyle, width, height);
|
|
7077
7634
|
}
|
|
7078
7635
|
if (this.curves.length) {
|
|
7079
7636
|
this._draws.push({
|
|
7080
7637
|
...options,
|
|
7081
7638
|
type: "stroke",
|
|
7082
|
-
path
|
|
7639
|
+
path,
|
|
7083
7640
|
texture,
|
|
7084
7641
|
textureTransform: this.textureTransform,
|
|
7085
7642
|
style: {
|
|
@@ -7100,18 +7657,16 @@ class CanvasContext extends Path2D {
|
|
|
7100
7657
|
this.rect(x, y, width, height).stroke();
|
|
7101
7658
|
}
|
|
7102
7659
|
fill(options) {
|
|
7660
|
+
const path = new Path2D(this);
|
|
7103
7661
|
let texture = this._defaultStyle;
|
|
7104
7662
|
if (this.fillStyle) {
|
|
7105
|
-
|
|
7106
|
-
|
|
7107
|
-
} else {
|
|
7108
|
-
texture = new ColorTexture(this.fillStyle);
|
|
7109
|
-
}
|
|
7663
|
+
const { width, height } = path.getBoundingBox();
|
|
7664
|
+
texture = this._colorToTexture(this.fillStyle, width, height);
|
|
7110
7665
|
}
|
|
7111
7666
|
this._draws.push({
|
|
7112
7667
|
...options,
|
|
7113
7668
|
type: "fill",
|
|
7114
|
-
path
|
|
7669
|
+
path,
|
|
7115
7670
|
texture,
|
|
7116
7671
|
textureTransform: this.textureTransform
|
|
7117
7672
|
});
|
|
@@ -14019,4 +14574,4 @@ async function render(options) {
|
|
|
14019
14574
|
});
|
|
14020
14575
|
}
|
|
14021
14576
|
|
|
14022
|
-
export { AnimatedTexture, Animation, Assets, Audio, AudioPipeline, AudioProcessor, AudioSpectrum, AudioWaveform, BaseElement2D, BaseElement2DBackground, BaseElement2DFill, BaseElement2DForeground, BaseElement2DGeometry, BaseElement2DOutline, BaseElement2DShadow, BaseElement2DStyle, BaseElement2DText, CanvasContext, CanvasItem, CanvasItemEditor, CanvasTexture, Color, ColorAdjustEffect, ColorFilterEffect, ColorMatrix, ColorOverlayEffect, ColorRemoveEffect, ColorReplaceEffect, ColorTexture, Control, CoreObject, DEG_TO_RAD, DEVICE_PIXEL_RATIO, DropShadowEffect, Effect, EffectMaterial, Element2D, Element2DStyle, EmbossEffect, Engine, EventEmitter, FlexElement2D, FlexElement2DStyle, FlexLayout, FontLoader, GIFLoader, GaussianBlurEffect, Geometry, GlitchEffect, GodrayEffect, Graphics2D, HTMLAudio, HTMLAudioContext, HTMLSound, IN_BROWSER, Image2D, ImageTexture, IndexBuffer, Input, InputEvent, JSONLoader, KawaseBlurEffect, KawaseTransition, LeftEraseTransition, Loader, Lottie2D, LottieLoader, MainLoop, MaskEffect, Material, Matrix, Matrix2, Matrix3, Matrix4, MouseInputEvent, Node, Node2D, OutlineEffect, PI, PI_2, PixelateEffect, PixelsTexture, PointerInputEvent, Projection2D, QuadGeometry, QuadUvGeometry, RAD_TO_DEG, Range, RawWeakMap, Rect2, RefCounted, Renderer, Resource, Ruler, SUPPORTS_AUDIO_CONTEXT, SUPPORTS_CLICK_EVENTS, SUPPORTS_CREATE_IMAGE_BITMAP, SUPPORTS_IMAGE_BITMAP, SUPPORTS_MOUSE_EVENTS, SUPPORTS_OFFLINE_AUDIO_CONTEXT, SUPPORTS_POINTER_EVENTS, SUPPORTS_RESIZE_OBSERVER, SUPPORTS_TOUCH_EVENTS, SUPPORTS_WEBGL2, SUPPORTS_WEBKIT_AUDIO_CONTEXT, SUPPORTS_WEBKIT_OFFLINE_AUDIO_CONTEXT, SUPPORTS_WEB_AUDIO, SUPPORTS_WHEEL_EVENTS, Scaler, SceneTree, ScrollBar, Text2D, TextLoader, Texture2D, TextureLoader, TextureRect2D, Ticker, TiltShiftTransition, Timeline, TimelineNode, Transform2D, TransformRect2D, Transition, TwistTransition, UvGeometry, UvMaterial, Vector, Vector2, Vector3, Vector4, VertexAttribute, VertexBuffer, Video2D, VideoLoader, VideoTexture, Viewport, ViewportTexture, WebAudio, WebAudioContext, WebGLBatch2DModule, WebGLBlendMode, WebGLBufferModule, WebGLFramebufferModule, WebGLMaskModule, WebGLModule, WebGLProgramModule, WebGLRenderer, WebGLScissorModule, WebGLState, WebGLStateModule, WebGLStencilModule, WebGLTextureModule, WebGLVertexArrayModule, WebGLViewportModule, WebSound, WheelInputEvent, XScrollBar, YScrollBar, ZoomBlurEffect, assets, clamp, clampFrag, createHTMLCanvas, createNode, crossOrigin, cubicBezier, curves, customNode, customNodes, defaultOptions, defineProperty, determineCrossOrigin, ease, easeIn, easeInOut, easeOut, frag$1 as frag, getDeclarations, getDefaultCssPropertyValue, isCanvasElement, isElementNode, isImageElement, isPow2, isVideoElement, isWebgl2, lerp, linear, log2, mapWebGLBlendModes, nextPow2, nextTick, parseCSSFilter, parseCSSTransform, parseCSSTransformOrigin, parseCssFunctions, parseCssProperty, property, protectedProperty, render, timingFunctions, uid };
|
|
14577
|
+
export { AnimatedTexture, Animation, Assets, Audio, AudioPipeline, AudioProcessor, AudioSpectrum, AudioWaveform, BaseElement2D, BaseElement2DBackground, BaseElement2DFill, BaseElement2DForeground, BaseElement2DGeometry, BaseElement2DOutline, BaseElement2DShadow, BaseElement2DStyle, BaseElement2DText, CanvasContext, CanvasItem, CanvasItemEditor, CanvasTexture, Color, ColorAdjustEffect, ColorFilterEffect, ColorMatrix, ColorOverlayEffect, ColorRemoveEffect, ColorReplaceEffect, ColorTexture, Control, CoreObject, DEG_TO_RAD, DEVICE_PIXEL_RATIO, DropShadowEffect, Effect, EffectMaterial, Element2D, Element2DStyle, EmbossEffect, Engine, EventEmitter, FlexElement2D, FlexElement2DStyle, FlexLayout, FontLoader, GIFLoader, GaussianBlurEffect, Geometry, GlitchEffect, GodrayEffect, GradientTexture, Graphics2D, HTMLAudio, HTMLAudioContext, HTMLSound, IN_BROWSER, Image2D, ImageTexture, IndexBuffer, Input, InputEvent, JSONLoader, KawaseBlurEffect, KawaseTransition, LeftEraseTransition, LinearGradient, Loader, Lottie2D, LottieLoader, MainLoop, MaskEffect, Material, Matrix, Matrix2, Matrix3, Matrix4, MouseInputEvent, Node, Node2D, OutlineEffect, PI, PI_2, PixelateEffect, PixelsTexture, PointerInputEvent, Projection2D, QuadGeometry, QuadUvGeometry, RAD_TO_DEG, RadialGradient, Range, RawWeakMap, Rect2, RefCounted, Renderer, Resource, Ruler, SUPPORTS_AUDIO_CONTEXT, SUPPORTS_CLICK_EVENTS, SUPPORTS_CREATE_IMAGE_BITMAP, SUPPORTS_IMAGE_BITMAP, SUPPORTS_MOUSE_EVENTS, SUPPORTS_OFFLINE_AUDIO_CONTEXT, SUPPORTS_POINTER_EVENTS, SUPPORTS_RESIZE_OBSERVER, SUPPORTS_TOUCH_EVENTS, SUPPORTS_WEBGL2, SUPPORTS_WEBKIT_AUDIO_CONTEXT, SUPPORTS_WEBKIT_OFFLINE_AUDIO_CONTEXT, SUPPORTS_WEB_AUDIO, SUPPORTS_WHEEL_EVENTS, Scaler, SceneTree, ScrollBar, Text2D, TextLoader, Texture2D, TextureLoader, TextureRect2D, Ticker, TiltShiftTransition, Timeline, TimelineNode, Transform2D, TransformRect2D, Transition, TwistTransition, UvGeometry, UvMaterial, Vector, Vector2, Vector3, Vector4, VertexAttribute, VertexBuffer, Video2D, VideoLoader, VideoTexture, Viewport, ViewportTexture, WebAudio, WebAudioContext, WebGLBatch2DModule, WebGLBlendMode, WebGLBufferModule, WebGLFramebufferModule, WebGLMaskModule, WebGLModule, WebGLProgramModule, WebGLRenderer, WebGLScissorModule, WebGLState, WebGLStateModule, WebGLStencilModule, WebGLTextureModule, WebGLVertexArrayModule, WebGLViewportModule, WebSound, WheelInputEvent, XScrollBar, YScrollBar, ZoomBlurEffect, assets, clamp, clampFrag, createHTMLCanvas, createNode, crossOrigin, cubicBezier, curves, customNode, customNodes, defaultOptions, defineProperty, determineCrossOrigin, ease, easeIn, easeInOut, easeOut, frag$1 as frag, getDeclarations, getDefaultCssPropertyValue, isCanvasElement, isElementNode, isImageElement, isPow2, isVideoElement, isWebgl2, lerp, linear, log2, mapWebGLBlendModes, nextPow2, nextTick, parseCSSFilter, parseCSSTransform, parseCSSTransformOrigin, parseCssFunctions, parseCssProperty, property, protectedProperty, render, timingFunctions, uid };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "modern-canvas",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.36",
|
|
5
5
|
"packageManager": "pnpm@9.15.1",
|
|
6
6
|
"description": "A JavaScript WebGL rendering engine.",
|
|
7
7
|
"author": "wxm",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"colord": "^2.9.3",
|
|
71
71
|
"earcut": "^3.0.1",
|
|
72
72
|
"modern-font": "^0.4.1",
|
|
73
|
-
"modern-idoc": "^0.5.
|
|
73
|
+
"modern-idoc": "^0.5.4",
|
|
74
74
|
"modern-path2d": "^1.2.19",
|
|
75
75
|
"modern-text": "^1.3.10",
|
|
76
76
|
"yoga-layout": "^3.2.1"
|