modern-path2d 1.1.0 → 1.2.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.cjs CHANGED
@@ -1595,6 +1595,12 @@ class Curve {
1595
1595
  getControlPointRefs() {
1596
1596
  return [];
1597
1597
  }
1598
+ applyTransform(transform) {
1599
+ this.getControlPointRefs().forEach((p) => {
1600
+ p.applyMatrix3(transform);
1601
+ });
1602
+ return this;
1603
+ }
1598
1604
  getUnevenPointArray(count = 5, output = []) {
1599
1605
  const p = new Vector2();
1600
1606
  for (let i = 0, len = Math.max(1, count) - 1; i <= len; i++) {
@@ -1736,10 +1742,6 @@ class Curve {
1736
1742
  }
1737
1743
  return mid;
1738
1744
  }
1739
- matrix(matrix) {
1740
- this.getControlPointRefs().forEach((point) => point.applyMatrix3(matrix));
1741
- return this;
1742
- }
1743
1745
  getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
1744
1746
  const potins = this.getPoints();
1745
1747
  for (let i = 0, len = potins.length; i < len; i++) {
@@ -1813,18 +1815,53 @@ const tempTransform0$1 = new Matrix3();
1813
1815
  const tempTransform1$1 = new Matrix3();
1814
1816
  const tempTransform2$1 = new Matrix3();
1815
1817
  const tempV2 = new Vector2();
1816
- class EllipseCurve extends Curve {
1817
- constructor(cx = 0, cy = 0, rx = 1, ry = 1, rotation = 0, startAngle = 0, endAngle = Math.PI * 2, clockwise = false) {
1818
+ class RoundCurve extends Curve {
1819
+ constructor(_center, _radius, _diff, rotate = 0, startAngle = 0, endAngle = Math.PI * 2, clockwise = false) {
1818
1820
  super();
1819
- this.rotation = rotation;
1821
+ this._center = _center;
1822
+ this._radius = _radius;
1823
+ this._diff = _diff;
1824
+ this.rotate = rotate;
1820
1825
  this.startAngle = startAngle;
1821
1826
  this.endAngle = endAngle;
1822
1827
  this.clockwise = clockwise;
1823
- this.center = new Vector2(cx, cy);
1824
- this.radius = new Vector2(rx, ry);
1825
1828
  }
1826
- center;
1827
- radius;
1829
+ get cx() {
1830
+ return this._center.x;
1831
+ }
1832
+ set cx(val) {
1833
+ this._center.x = val;
1834
+ }
1835
+ get cy() {
1836
+ return this._center.y;
1837
+ }
1838
+ set cy(val) {
1839
+ this._center.y = val;
1840
+ }
1841
+ get rx() {
1842
+ return this._radius.x;
1843
+ }
1844
+ set rx(val) {
1845
+ this._radius.x = val;
1846
+ }
1847
+ get ry() {
1848
+ return this._radius.y;
1849
+ }
1850
+ set ry(val) {
1851
+ this._radius.y = val;
1852
+ }
1853
+ get dx() {
1854
+ return this._diff.x;
1855
+ }
1856
+ set dx(val) {
1857
+ this._diff.x = val;
1858
+ }
1859
+ get dy() {
1860
+ return this._diff.y;
1861
+ }
1862
+ set dy(val) {
1863
+ this._diff.y = val;
1864
+ }
1828
1865
  isClockwise() {
1829
1866
  return this.clockwise;
1830
1867
  }
@@ -1849,40 +1886,38 @@ class EllipseCurve extends Curve {
1849
1886
  }
1850
1887
  }
1851
1888
  const angle = this.startAngle + t * deltaAngle;
1852
- let _x = this.center.x + this.radius.x * Math.cos(angle);
1853
- let _y = this.center.y + this.radius.y * Math.sin(angle);
1854
- if (this.rotation !== 0) {
1855
- const cos = Math.cos(this.rotation);
1856
- const sin = Math.sin(this.rotation);
1857
- const tx = _x - this.center.x;
1858
- const ty = _y - this.center.y;
1859
- _x = tx * cos - ty * sin + this.center.x;
1860
- _y = tx * sin + ty * cos + this.center.y;
1889
+ let _x = this.cx + this.rx * Math.cos(angle);
1890
+ let _y = this.cy + this.ry * Math.sin(angle);
1891
+ if (this.rotate !== 0) {
1892
+ const cos = Math.cos(this.rotate);
1893
+ const sin = Math.sin(this.rotate);
1894
+ const tx = _x - this.cx;
1895
+ const ty = _y - this.cy;
1896
+ _x = tx * cos - ty * sin + this.cx;
1897
+ _y = tx * sin + ty * cos + this.cy;
1861
1898
  }
1862
1899
  return output.set(_x, _y);
1863
1900
  }
1864
1901
  toCommands() {
1865
- const { center, radius, startAngle, endAngle, clockwise, rotation } = this;
1866
- const { x: cx, y: cy } = center;
1867
- const { x: rx, y: ry } = radius;
1868
- const startX = cx + rx * Math.cos(startAngle) * Math.cos(rotation) - ry * Math.sin(startAngle) * Math.sin(rotation);
1869
- const startY = cy + rx * Math.cos(startAngle) * Math.sin(rotation) + ry * Math.sin(startAngle) * Math.cos(rotation);
1902
+ const { cx, cy, rx, ry, startAngle, endAngle, clockwise, rotate } = this;
1903
+ const startX = cx + rx * Math.cos(startAngle) * Math.cos(rotate) - ry * Math.sin(startAngle) * Math.sin(rotate);
1904
+ const startY = cy + rx * Math.cos(startAngle) * Math.sin(rotate) + ry * Math.sin(startAngle) * Math.cos(rotate);
1870
1905
  const angleDiff = Math.abs(startAngle - endAngle);
1871
1906
  const largeArcFlag = angleDiff > Math.PI ? 1 : 0;
1872
1907
  const sweepFlag = clockwise ? 1 : 0;
1873
- const angle = rotation * 180 / Math.PI;
1908
+ const angle = rotate * 180 / Math.PI;
1874
1909
  if (angleDiff >= 2 * Math.PI) {
1875
1910
  const midAngle = startAngle + Math.PI;
1876
- const midX = cx + rx * Math.cos(midAngle) * Math.cos(rotation) - ry * Math.sin(midAngle) * Math.sin(rotation);
1877
- const midY = cy + rx * Math.cos(midAngle) * Math.sin(rotation) + ry * Math.sin(midAngle) * Math.cos(rotation);
1911
+ const midX = cx + rx * Math.cos(midAngle) * Math.cos(rotate) - ry * Math.sin(midAngle) * Math.sin(rotate);
1912
+ const midY = cy + rx * Math.cos(midAngle) * Math.sin(rotate) + ry * Math.sin(midAngle) * Math.cos(rotate);
1878
1913
  return [
1879
1914
  { type: "M", x: startX, y: startY },
1880
1915
  { type: "A", rx, ry, angle, largeArcFlag: 0, sweepFlag, x: midX, y: midY },
1881
1916
  { type: "A", rx, ry, angle, largeArcFlag: 0, sweepFlag, x: startX, y: startY }
1882
1917
  ];
1883
1918
  } else {
1884
- const endX = cx + rx * Math.cos(endAngle) * Math.cos(rotation) - ry * Math.sin(endAngle) * Math.sin(rotation);
1885
- const endY = cy + rx * Math.cos(endAngle) * Math.sin(rotation) + ry * Math.sin(endAngle) * Math.cos(rotation);
1919
+ const endX = cx + rx * Math.cos(endAngle) * Math.cos(rotate) - ry * Math.sin(endAngle) * Math.sin(rotate);
1920
+ const endY = cy + rx * Math.cos(endAngle) * Math.sin(rotate) + ry * Math.sin(endAngle) * Math.cos(rotate);
1886
1921
  return [
1887
1922
  { type: "M", x: startX, y: startY },
1888
1923
  { type: "A", rx, ry, angle, largeArcFlag, sweepFlag, x: endX, y: endY }
@@ -1890,24 +1925,24 @@ class EllipseCurve extends Curve {
1890
1925
  }
1891
1926
  }
1892
1927
  drawTo(ctx) {
1893
- const { center, radius, rotation, startAngle, endAngle, clockwise } = this;
1928
+ const { cx, cy, rx, ry, rotate, startAngle, endAngle, clockwise } = this;
1894
1929
  ctx.ellipse(
1895
- center.x,
1896
- center.y,
1897
- radius.x,
1898
- radius.y,
1899
- rotation,
1930
+ cx,
1931
+ cy,
1932
+ rx,
1933
+ ry,
1934
+ rotate,
1900
1935
  startAngle,
1901
1936
  endAngle,
1902
1937
  !clockwise
1903
1938
  );
1904
1939
  return this;
1905
1940
  }
1906
- matrix(matrix) {
1907
- tempV2.set(this.center.x, this.center.y);
1941
+ applyTransform(matrix) {
1942
+ tempV2.set(this.cx, this.cy);
1908
1943
  tempV2.applyMatrix3(matrix);
1909
- this.center.x = tempV2.x;
1910
- this.center.y = tempV2.y;
1944
+ this.cx = tempV2.x;
1945
+ this.cy = tempV2.y;
1911
1946
  if (isTransformSkewed(matrix)) {
1912
1947
  transfEllipseGeneric(this, matrix);
1913
1948
  } else {
@@ -1916,71 +1951,80 @@ class EllipseCurve extends Curve {
1916
1951
  return this;
1917
1952
  }
1918
1953
  getControlPointRefs() {
1919
- return [this.center];
1954
+ return [this._center];
1920
1955
  }
1921
1956
  getAdaptivePointArray(output = []) {
1922
- const i = output.length - 1;
1923
- const x = this.center.x;
1924
- const y = this.center.y;
1925
- const rx = this.radius.x;
1926
- const ry = this.radius.y;
1927
- const dx = 0;
1928
- const dy = 0;
1957
+ const { cx, cy, rx, ry, dx, dy } = this;
1929
1958
  if (!(rx >= 0 && ry >= 0 && dx >= 0 && dy >= 0)) {
1930
1959
  return output;
1931
1960
  }
1932
1961
  const n = Math.ceil(2.3 * Math.sqrt(rx + ry));
1933
- const m = n * 8 + (0) + (0);
1962
+ const m = n * 8 + (dx ? 4 : 0) + (dy ? 4 : 0);
1934
1963
  if (m === 0) {
1935
1964
  return output;
1936
1965
  }
1966
+ const array = [];
1937
1967
  if (n === 0) {
1938
- output[i] = output[i + 6] = x + dx;
1939
- output[i + 1] = output[i + 3] = y + dy;
1940
- output[i + 2] = output[i + 4] = x - dx;
1941
- output[i + 5] = output[i + 7] = y - dy;
1942
- return output;
1968
+ array[0] = array[6] = cx + dx;
1969
+ array[1] = array[3] = cy + dy;
1970
+ array[2] = array[4] = cx - dx;
1971
+ array[5] = array[7] = cy - dy;
1972
+ } else {
1973
+ let j1 = 0;
1974
+ let j2 = n * 4 + (dx ? 2 : 0) + 2;
1975
+ let j3 = j2;
1976
+ let j4 = m;
1977
+ let x0 = dx + rx;
1978
+ let y0 = dy;
1979
+ let x1 = cx + x0;
1980
+ let x2 = cx - x0;
1981
+ let y1 = cy + y0;
1982
+ array[j1++] = x1;
1983
+ array[j1++] = y1;
1984
+ array[--j2] = y1;
1985
+ array[--j2] = x2;
1986
+ if (dy) {
1987
+ const y22 = cy - y0;
1988
+ array[j3++] = x2;
1989
+ array[j3++] = y22;
1990
+ array[--j4] = y22;
1991
+ array[--j4] = x1;
1992
+ }
1993
+ for (let i = 1; i < n; i++) {
1994
+ const a = Math.PI / 2 * (i / n);
1995
+ const x02 = dx + Math.cos(a) * rx;
1996
+ const y02 = dy + Math.sin(a) * ry;
1997
+ const x12 = cx + x02;
1998
+ const x22 = cx - x02;
1999
+ const y12 = cy + y02;
2000
+ const y22 = cy - y02;
2001
+ array[j1++] = x12;
2002
+ array[j1++] = y12;
2003
+ array[--j2] = y12;
2004
+ array[--j2] = x22;
2005
+ array[j3++] = x22;
2006
+ array[j3++] = y22;
2007
+ array[--j4] = y22;
2008
+ array[--j4] = x12;
2009
+ }
2010
+ x0 = dx;
2011
+ y0 = dy + ry;
2012
+ x1 = cx + x0;
2013
+ x2 = cx - x0;
2014
+ y1 = cy + y0;
2015
+ const y2 = cy - y0;
2016
+ array[j1++] = x1;
2017
+ array[j1++] = y1;
2018
+ array[--j4] = y2;
2019
+ array[--j4] = x1;
2020
+ if (dx) {
2021
+ array[j1++] = x2;
2022
+ array[j1++] = y1;
2023
+ array[--j4] = y2;
2024
+ array[--j4] = x2;
2025
+ }
1943
2026
  }
1944
- let j1 = i;
1945
- let j2 = n * 4 + (0) + 2 + i;
1946
- let j3 = j2;
1947
- let j4 = m + i;
1948
- let x0 = dx + rx;
1949
- let y0 = dy;
1950
- let x1 = x + x0;
1951
- let x2 = x - x0;
1952
- let y1 = y + y0;
1953
- output[j1++] = x1;
1954
- output[j1++] = y1;
1955
- output[--j2] = y1;
1956
- output[--j2] = x2;
1957
- for (let i2 = 1; i2 < n; i2++) {
1958
- const a = Math.PI / 2 * (i2 / n);
1959
- const x02 = dx + Math.cos(a) * rx;
1960
- const y02 = dy + Math.sin(a) * ry;
1961
- const x12 = x + x02;
1962
- const x22 = x - x02;
1963
- const y12 = y + y02;
1964
- const y22 = y - y02;
1965
- output[j1++] = x12;
1966
- output[j1++] = y12;
1967
- output[--j2] = y12;
1968
- output[--j2] = x22;
1969
- output[j3++] = x22;
1970
- output[j3++] = y22;
1971
- output[--j4] = y22;
1972
- output[--j4] = x12;
1973
- }
1974
- x0 = dx;
1975
- y0 = dy + ry;
1976
- x1 = x + x0;
1977
- x2 = x - x0;
1978
- y1 = y + y0;
1979
- const y2 = y - y0;
1980
- output[j1++] = x1;
1981
- output[j1++] = y1;
1982
- output[--j4] = y2;
1983
- output[--j4] = x1;
2027
+ Array.prototype.push.apply(output, array);
1984
2028
  return output;
1985
2029
  }
1986
2030
  fillTriangulate(options = {}) {
@@ -2026,11 +2070,9 @@ class EllipseCurve extends Curve {
2026
2070
  };
2027
2071
  }
2028
2072
  getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
2029
- const { center, radius, rotation: theta } = this;
2030
- const { x: rx, y: ry } = radius;
2031
- const { x: cx, y: cy } = center;
2032
- const cosTheta = Math.cos(theta);
2033
- const sinTheta = Math.sin(theta);
2073
+ const { cx, cy, rx, ry, rotate } = this;
2074
+ const cosTheta = Math.cos(rotate);
2075
+ const sinTheta = Math.sin(rotate);
2034
2076
  const halfWidth = Math.sqrt(
2035
2077
  rx * rx * cosTheta * cosTheta + ry * ry * sinTheta * sinTheta
2036
2078
  );
@@ -2045,22 +2087,22 @@ class EllipseCurve extends Curve {
2045
2087
  }
2046
2088
  copy(source) {
2047
2089
  super.copy(source);
2048
- this.center.x = source.center.x;
2049
- this.center.y = source.center.y;
2050
- this.radius.x = source.radius.x;
2051
- this.radius.y = source.radius.y;
2090
+ this.cx = source.cx;
2091
+ this.cy = source.cy;
2092
+ this.rx = source.rx;
2093
+ this.ry = source.ry;
2052
2094
  this.startAngle = source.startAngle;
2053
2095
  this.endAngle = source.endAngle;
2054
2096
  this.clockwise = source.clockwise;
2055
- this.rotation = source.rotation;
2097
+ this.rotate = source.rotate;
2056
2098
  return this;
2057
2099
  }
2058
2100
  }
2059
2101
  function transfEllipseGeneric(curve, m) {
2060
- const a = curve.radius.x;
2061
- const b = curve.radius.y;
2062
- const cosTheta = Math.cos(curve.rotation);
2063
- const sinTheta = Math.sin(curve.rotation);
2102
+ const a = curve.rx;
2103
+ const b = curve.ry;
2104
+ const cosTheta = Math.cos(curve.rotate);
2105
+ const sinTheta = Math.sin(curve.rotate);
2064
2106
  const v1 = new Vector2(a * cosTheta, a * sinTheta);
2065
2107
  const v2 = new Vector2(-b * sinTheta, b * cosTheta);
2066
2108
  const f1 = v1.applyMatrix3(m);
@@ -2083,9 +2125,9 @@ function transfEllipseGeneric(curve, m) {
2083
2125
  const ed = eigenDecomposition(mQe[0], mQe[1], mQe[4]);
2084
2126
  const rt1sqrt = Math.sqrt(ed.rt1);
2085
2127
  const rt2sqrt = Math.sqrt(ed.rt2);
2086
- curve.radius.x = 1 / rt1sqrt;
2087
- curve.radius.y = 1 / rt2sqrt;
2088
- curve.rotation = Math.atan2(ed.sn, ed.cs);
2128
+ curve.rx = 1 / rt1sqrt;
2129
+ curve.ry = 1 / rt2sqrt;
2130
+ curve.rotate = Math.atan2(ed.sn, ed.cs);
2089
2131
  const isFullEllipse = (curve.endAngle - curve.startAngle) % (2 * Math.PI) < Number.EPSILON;
2090
2132
  if (!isFullEllipse) {
2091
2133
  const mDsqrt = tempTransform1$1.set(
@@ -2125,10 +2167,10 @@ function transfEllipseGeneric(curve, m) {
2125
2167
  function transfEllipseNoSkew(curve, m) {
2126
2168
  const sx = getTransformScaleX(m);
2127
2169
  const sy = getTransformScaleY(m);
2128
- curve.radius.x *= sx;
2129
- curve.radius.y *= sy;
2170
+ curve.rx *= sx;
2171
+ curve.ry *= sy;
2130
2172
  const theta = sx > Number.EPSILON ? Math.atan2(m.elements[1], m.elements[0]) : Math.atan2(-m.elements[3], m.elements[4]);
2131
- curve.rotation += theta;
2173
+ curve.rotate += theta;
2132
2174
  if (isTransformFlipped(m)) {
2133
2175
  curve.startAngle *= -1;
2134
2176
  curve.endAngle *= -1;
@@ -2196,31 +2238,49 @@ function eigenDecomposition(A, B, C) {
2196
2238
  return { rt1, rt2, cs, sn };
2197
2239
  }
2198
2240
 
2199
- class ArcCurve extends EllipseCurve {
2241
+ class ArcCurve extends RoundCurve {
2200
2242
  constructor(cx = 0, cy = 0, radius = 1, startAngle = 0, endAngle = Math.PI * 2, clockwise = false) {
2201
- super(cx, cy, radius, radius, 0, startAngle, endAngle, clockwise);
2243
+ super(
2244
+ new Vector2(cx, cy),
2245
+ new Vector2(radius, radius),
2246
+ new Vector2(0, 0),
2247
+ 0,
2248
+ startAngle,
2249
+ endAngle,
2250
+ clockwise
2251
+ );
2252
+ this.radius = radius;
2253
+ }
2254
+ drawTo(ctx) {
2255
+ const { cx, cy, radius, startAngle, endAngle, clockwise } = this;
2256
+ ctx.arc(
2257
+ cx,
2258
+ cy,
2259
+ radius,
2260
+ startAngle,
2261
+ endAngle,
2262
+ !clockwise
2263
+ );
2264
+ return this;
2202
2265
  }
2203
2266
  getAdaptivePointArray(output = []) {
2204
- const start = 0;
2205
- const end = 1;
2206
- const x = this.center.x;
2207
- const y = this.center.y;
2208
- const clockwise = this.clockwise;
2209
- const radius = this.radius.x;
2210
- let dist = Math.abs(start - end);
2211
- if (clockwise && end > start) {
2267
+ const { cx, cy, radius, startAngle, endAngle, clockwise } = this;
2268
+ let dist = Math.abs(startAngle - endAngle);
2269
+ if (!clockwise && startAngle > endAngle) {
2270
+ dist = 2 * Math.PI - dist;
2271
+ } else if (clockwise && endAngle > startAngle) {
2212
2272
  dist = 2 * Math.PI - dist;
2213
2273
  }
2214
2274
  let steps = Math.max(6, Math.floor(6 * radius ** (1 / 3) * (dist / Math.PI)));
2215
2275
  steps = Math.max(steps, 3);
2216
2276
  let f = dist / steps;
2217
- let t = start;
2218
- f *= clockwise ? -1 : 1;
2277
+ let t = startAngle;
2278
+ f *= !clockwise ? -1 : 1;
2219
2279
  for (let i = 0; i < steps + 1; i++) {
2220
2280
  const cs = Math.cos(t);
2221
2281
  const sn = Math.sin(t);
2222
- const nx = x + cs * radius;
2223
- const ny = y + sn * radius;
2282
+ const nx = cx + cs * radius;
2283
+ const ny = cy + sn * radius;
2224
2284
  output.push(nx, ny);
2225
2285
  t += f;
2226
2286
  }
@@ -2301,29 +2361,21 @@ class CompositeCurve extends Curve {
2301
2361
  }
2302
2362
 
2303
2363
  class CubicBezierCurve extends Curve {
2304
- p1;
2305
- cp1;
2306
- cp2;
2307
- p2;
2308
- static from(p1, cp1, cp2, p2) {
2364
+ constructor(p1, cp1, cp2, p2) {
2365
+ super();
2366
+ this.p1 = p1;
2367
+ this.cp1 = cp1;
2368
+ this.cp2 = cp2;
2369
+ this.p2 = p2;
2370
+ }
2371
+ static from(p1x, p1y, cp1x, cp1y, cp2x, cp2y, p2x, p2y) {
2309
2372
  return new CubicBezierCurve(
2310
- p1.x,
2311
- p1.y,
2312
- cp1.x,
2313
- cp1.y,
2314
- cp2.x,
2315
- cp2.y,
2316
- p2.x,
2317
- p2.y
2373
+ new Vector2(p1x, p1y),
2374
+ new Vector2(cp1x, cp1y),
2375
+ new Vector2(cp2x, cp2y),
2376
+ new Vector2(p2x, p2y)
2318
2377
  );
2319
2378
  }
2320
- constructor(p1x, p1y, cp1x, cp1y, cp2x, cp2y, p2x, p2y) {
2321
- super();
2322
- this.p1 = new Vector2(p1x, p1y);
2323
- this.cp1 = new Vector2(cp1x, cp1y);
2324
- this.cp2 = new Vector2(cp2x, cp2y);
2325
- this.p2 = new Vector2(p2x, p2y);
2326
- }
2327
2379
  getPoint(t, output = new Vector2()) {
2328
2380
  const { p1, cp1, cp2, p2 } = this;
2329
2381
  return output.set(
@@ -2409,16 +2461,44 @@ class CubicBezierCurve extends Curve {
2409
2461
  }
2410
2462
  }
2411
2463
 
2412
- class LineCurve extends Curve {
2413
- p1;
2414
- p2;
2415
- static from(p1, p2) {
2416
- return new LineCurve(p1.x, p1.y, p2.x, p2.y);
2464
+ class EllipseCurve extends RoundCurve {
2465
+ constructor(cx = 0, cy = 0, rx = 1, ry = 1, rotate = 0, startAngle = 0, endAngle = Math.PI * 2, clockwise = false) {
2466
+ super(
2467
+ new Vector2(cx, cy),
2468
+ new Vector2(rx, ry),
2469
+ new Vector2(),
2470
+ rotate,
2471
+ startAngle,
2472
+ endAngle,
2473
+ clockwise
2474
+ );
2475
+ }
2476
+ drawTo(ctx) {
2477
+ ctx.ellipse(
2478
+ this.cx,
2479
+ this.cy,
2480
+ this.rx,
2481
+ this.ry,
2482
+ this.rotate,
2483
+ this.startAngle,
2484
+ this.endAngle,
2485
+ !this.clockwise
2486
+ );
2487
+ return this;
2417
2488
  }
2418
- constructor(p1x, p1y, p2x, p2y) {
2489
+ }
2490
+
2491
+ class LineCurve extends Curve {
2492
+ constructor(p1, p2) {
2419
2493
  super();
2420
- this.p1 = new Vector2(p1x, p1y);
2421
- this.p2 = new Vector2(p2x, p2y);
2494
+ this.p1 = p1;
2495
+ this.p2 = p2;
2496
+ }
2497
+ static from(p1x, p1y, p2x, p2y) {
2498
+ return new LineCurve(
2499
+ new Vector2(p1x, p1y),
2500
+ new Vector2(p2x, p2y)
2501
+ );
2422
2502
  }
2423
2503
  getPoint(t, output = new Vector2()) {
2424
2504
  if (t === 1) {
@@ -2479,8 +2559,11 @@ class LineCurve extends Curve {
2479
2559
  }
2480
2560
 
2481
2561
  class PloygonCurve extends CompositeCurve {
2482
- static equilateral(cx = 0, cy = 0, radius = 1, sideCount = 3) {
2483
- const ploygon = new PloygonCurve();
2562
+ //
2563
+ }
2564
+
2565
+ class EquilateralPloygonCurve extends PloygonCurve {
2566
+ constructor(cx = 0, cy = 0, radius = 1, sideCount = 3) {
2484
2567
  const points = [];
2485
2568
  for (let i = 0; i < sideCount; i++) {
2486
2569
  const radian = i * 2 * Math.PI / sideCount - 0.5 * Math.PI;
@@ -2491,35 +2574,37 @@ class PloygonCurve extends CompositeCurve {
2491
2574
  ).add({ x: cx, y: cy })
2492
2575
  );
2493
2576
  }
2577
+ const curves = [];
2494
2578
  for (let i = 0; i < sideCount; i++) {
2495
- ploygon.curves.push(
2496
- LineCurve.from(points[i], points[(i + 1) % sideCount])
2579
+ curves.push(
2580
+ new LineCurve(
2581
+ points[i],
2582
+ points[(i + 1) % sideCount]
2583
+ )
2497
2584
  );
2498
2585
  }
2499
- return ploygon;
2586
+ super(curves);
2587
+ this.cx = cx;
2588
+ this.cy = cy;
2589
+ this.radius = radius;
2590
+ this.sideCount = sideCount;
2500
2591
  }
2501
2592
  }
2502
2593
 
2503
2594
  class QuadraticBezierCurve extends Curve {
2504
- p1;
2505
- cp;
2506
- p2;
2507
- static from(p1, cp, p2) {
2595
+ constructor(p1, cp, p2) {
2596
+ super();
2597
+ this.p1 = p1;
2598
+ this.cp = cp;
2599
+ this.p2 = p2;
2600
+ }
2601
+ static from(p1x, p1y, cpx, cpy, p2x, p2y) {
2508
2602
  return new QuadraticBezierCurve(
2509
- p1.x,
2510
- p1.y,
2511
- cp.x,
2512
- cp.y,
2513
- p2.x,
2514
- p2.y
2603
+ new Vector2(p1x, p1y),
2604
+ new Vector2(cpx, cpy),
2605
+ new Vector2(p2x, p2y)
2515
2606
  );
2516
2607
  }
2517
- constructor(p1x, p1y, cpx, cpy, p2x, p2y) {
2518
- super();
2519
- this.p1 = new Vector2(p1x, p1y);
2520
- this.cp = new Vector2(cpx, cpy);
2521
- this.p2 = new Vector2(p2x, p2y);
2522
- }
2523
2608
  getPoint(t, output = new Vector2()) {
2524
2609
  const { p1, cp, p2 } = this;
2525
2610
  output.set(
@@ -2586,16 +2671,20 @@ class RectangleCurve extends PloygonCurve {
2586
2671
  new Vector2(x, y + height)
2587
2672
  ];
2588
2673
  super([
2589
- LineCurve.from(points[0], points[1]),
2590
- LineCurve.from(points[1], points[2]),
2591
- LineCurve.from(points[2], points[3]),
2592
- LineCurve.from(points[3], points[0])
2674
+ new LineCurve(points[0], points[1]),
2675
+ new LineCurve(points[1], points[2]),
2676
+ new LineCurve(points[2], points[3]),
2677
+ new LineCurve(points[3], points[0])
2593
2678
  ]);
2594
2679
  this.x = x;
2595
2680
  this.y = y;
2596
2681
  this.width = width;
2597
2682
  this.height = height;
2598
2683
  }
2684
+ drawTo(ctx) {
2685
+ ctx.rect(this.x, this.y, this.width, this.height);
2686
+ return this;
2687
+ }
2599
2688
  fillTriangulate(options = {}) {
2600
2689
  let {
2601
2690
  vertices = [],
@@ -2640,6 +2729,34 @@ class RectangleCurve extends PloygonCurve {
2640
2729
  }
2641
2730
  }
2642
2731
 
2732
+ class RoundRectangleCurve extends RoundCurve {
2733
+ constructor(x = 0, y = 0, width = 1, height = 1, radius = 1) {
2734
+ const halfWidth = width / 2;
2735
+ const halfHeight = height / 2;
2736
+ const cx = x + halfWidth;
2737
+ const cy = y + halfHeight;
2738
+ const rx = Math.max(0, Math.min(radius, Math.min(halfWidth, halfHeight)));
2739
+ const ry = rx;
2740
+ const dx = halfWidth - rx;
2741
+ const dy = halfHeight - ry;
2742
+ super(
2743
+ new Vector2(cx, cy),
2744
+ new Vector2(rx, ry),
2745
+ new Vector2(dx, dy)
2746
+ );
2747
+ this.x = x;
2748
+ this.y = y;
2749
+ this.width = width;
2750
+ this.height = height;
2751
+ this.radius = radius;
2752
+ }
2753
+ drawTo(ctx) {
2754
+ const { x, y, width, height, radius } = this;
2755
+ ctx.roundRect(x, y, width, height, radius);
2756
+ return this;
2757
+ }
2758
+ }
2759
+
2643
2760
  class SplineCurve extends Curve {
2644
2761
  constructor(points = []) {
2645
2762
  super();
@@ -2734,7 +2851,7 @@ class CurvePath extends CompositeCurve {
2734
2851
  if (start) {
2735
2852
  const end = this.currentPoint;
2736
2853
  if (end && !start.equals(end)) {
2737
- this.curves.push(LineCurve.from(end, start));
2854
+ this.curves.push(new LineCurve(end, start));
2738
2855
  end.copy(start);
2739
2856
  }
2740
2857
  this.startPoint = void 0;
@@ -2750,7 +2867,7 @@ class CurvePath extends CompositeCurve {
2750
2867
  const start = this.currentPoint;
2751
2868
  if (!start?.equals({ x, y })) {
2752
2869
  this.curves.push(
2753
- new LineCurve(
2870
+ LineCurve.from(
2754
2871
  start?.x ?? 0,
2755
2872
  start?.y ?? 0,
2756
2873
  x,
@@ -2765,7 +2882,7 @@ class CurvePath extends CompositeCurve {
2765
2882
  const start = this.currentPoint;
2766
2883
  if (!start?.equals({ x, y })) {
2767
2884
  this.curves.push(
2768
- new CubicBezierCurve(
2885
+ CubicBezierCurve.from(
2769
2886
  start?.x ?? 0,
2770
2887
  start?.y ?? 0,
2771
2888
  cp1x,
@@ -2784,7 +2901,7 @@ class CurvePath extends CompositeCurve {
2784
2901
  const start = this.currentPoint;
2785
2902
  if (!start?.equals({ x, y })) {
2786
2903
  this.curves.push(
2787
- new QuadraticBezierCurve(
2904
+ QuadraticBezierCurve.from(
2788
2905
  start?.x ?? 0,
2789
2906
  start?.y ?? 0,
2790
2907
  cpx,
@@ -2845,8 +2962,15 @@ class CurvePath extends CompositeCurve {
2845
2962
  this.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise);
2846
2963
  return this;
2847
2964
  }
2848
- rect(x, y, w, h) {
2849
- const curve = new RectangleCurve(x, y, w, h);
2965
+ rect(x, y, width, height) {
2966
+ const curve = new RectangleCurve(x, y, width, height);
2967
+ this._connetLineTo(curve);
2968
+ this.curves.push(curve);
2969
+ this._setCurrentPoint({ x, y });
2970
+ return this;
2971
+ }
2972
+ roundRect(x, y, width, height, radii) {
2973
+ const curve = new RoundRectangleCurve(x, y, width, height, radii);
2850
2974
  this._connetLineTo(curve);
2851
2975
  this.curves.push(curve);
2852
2976
  this._setCurrentPoint({ x, y });
@@ -2987,8 +3111,12 @@ class Path2D extends CompositeCurve {
2987
3111
  this.currentCurve.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise);
2988
3112
  return this;
2989
3113
  }
2990
- rect(x, y, w, h) {
2991
- this.currentCurve.rect(x, y, w, h);
3114
+ rect(x, y, width, height) {
3115
+ this.currentCurve.rect(x, y, width, height);
3116
+ return this;
3117
+ }
3118
+ roundRect(x, y, width, height, radii) {
3119
+ this.currentCurve.roundRect(x, y, width, height, radii);
2992
3120
  return this;
2993
3121
  }
2994
3122
  addCommands(commands) {
@@ -3082,8 +3210,8 @@ class Path2D extends CompositeCurve {
3082
3210
  });
3083
3211
  return this;
3084
3212
  }
3085
- matrix(matrix) {
3086
- this.curves.forEach((curve) => curve.matrix(matrix));
3213
+ applyTransform(transform) {
3214
+ this.curves.forEach((curve) => curve.applyTransform(transform));
3087
3215
  return this;
3088
3216
  }
3089
3217
  getMinMax(min = Vector2.MAX, max = Vector2.MIN, withStyle = true) {
@@ -3242,6 +3370,33 @@ class Path2DSet {
3242
3370
  }
3243
3371
  }
3244
3372
 
3373
+ const dataUri = "data:image/svg+xml;";
3374
+ const base64DataUri = `${dataUri}base64,`;
3375
+ const utf8DataUri = `${dataUri}charset=utf8,`;
3376
+ function svgToDOM(svg) {
3377
+ if (typeof svg === "string") {
3378
+ let xml;
3379
+ if (svg.startsWith(base64DataUri)) {
3380
+ svg = svg.substring(base64DataUri.length, svg.length);
3381
+ xml = atob(svg);
3382
+ } else if (svg.startsWith(utf8DataUri)) {
3383
+ svg = svg.substring(utf8DataUri.length, svg.length);
3384
+ xml = decodeURIComponent(svg);
3385
+ } else {
3386
+ xml = svg;
3387
+ }
3388
+ const doc = new DOMParser().parseFromString(xml, "text/xml");
3389
+ const error = doc.querySelector("parsererror");
3390
+ if (error) {
3391
+ throw new Error(`${error.textContent ?? "parser error"}
3392
+ ${xml}`);
3393
+ }
3394
+ return doc.documentElement;
3395
+ } else {
3396
+ return svg;
3397
+ }
3398
+ }
3399
+
3245
3400
  const defaultUnit = "px";
3246
3401
  const defaultDPI = 90;
3247
3402
  const units = ["mm", "cm", "in", "pt", "pc", "px"];
@@ -3719,7 +3874,7 @@ function parseNode(node, style, paths = [], stylesheets = {}) {
3719
3874
  const transformStack = [];
3720
3875
  const transform = getNodeTransform(node, currentTransform, transformStack);
3721
3876
  if (path) {
3722
- path.matrix(currentTransform);
3877
+ path.applyTransform(currentTransform);
3723
3878
  paths.push(path);
3724
3879
  path.style = style;
3725
3880
  }
@@ -3741,34 +3896,8 @@ function parseNode(node, style, paths = [], stylesheets = {}) {
3741
3896
  return paths;
3742
3897
  }
3743
3898
 
3744
- const dataUri = "data:image/svg+xml;";
3745
- const base64DataUri = `${dataUri}base64,`;
3746
- const utf8DataUri = `${dataUri}charset=utf8,`;
3747
- function parseSVGToDOM(svg) {
3748
- if (typeof svg === "string") {
3749
- let xml;
3750
- if (svg.startsWith(base64DataUri)) {
3751
- svg = svg.substring(base64DataUri.length, svg.length);
3752
- xml = atob(svg);
3753
- } else if (svg.startsWith(utf8DataUri)) {
3754
- svg = svg.substring(utf8DataUri.length, svg.length);
3755
- xml = decodeURIComponent(svg);
3756
- } else {
3757
- xml = svg;
3758
- }
3759
- const doc = new DOMParser().parseFromString(xml, "text/xml");
3760
- const error = doc.querySelector("parsererror");
3761
- if (error) {
3762
- throw new Error(`${error.textContent ?? "parser error"}
3763
- ${xml}`);
3764
- }
3765
- return doc.documentElement;
3766
- } else {
3767
- return svg;
3768
- }
3769
- }
3770
- function parseSVG(svg) {
3771
- return new Path2DSet(parseNode(parseSVGToDOM(svg), {}));
3899
+ function svgToPath2DSet(svg) {
3900
+ return new Path2DSet(parseNode(svgToDOM(svg), {}));
3772
3901
  }
3773
3902
 
3774
3903
  exports.ArcCurve = ArcCurve;
@@ -3778,6 +3907,7 @@ exports.CubicBezierCurve = CubicBezierCurve;
3778
3907
  exports.Curve = Curve;
3779
3908
  exports.CurvePath = CurvePath;
3780
3909
  exports.EllipseCurve = EllipseCurve;
3910
+ exports.EquilateralPloygonCurve = EquilateralPloygonCurve;
3781
3911
  exports.LineCurve = LineCurve;
3782
3912
  exports.Matrix3 = Matrix3;
3783
3913
  exports.Path2D = Path2D;
@@ -3785,6 +3915,7 @@ exports.Path2DSet = Path2DSet;
3785
3915
  exports.PloygonCurve = PloygonCurve;
3786
3916
  exports.QuadraticBezierCurve = QuadraticBezierCurve;
3787
3917
  exports.RectangleCurve = RectangleCurve;
3918
+ exports.RoundRectangleCurve = RoundRectangleCurve;
3788
3919
  exports.SplineCurve = SplineCurve;
3789
3920
  exports.Vector2 = Vector2;
3790
3921
  exports.catmullRom = catmullRom;
@@ -3795,11 +3926,11 @@ exports.getAdaptiveCubicBezierCurvePoints = getAdaptiveCubicBezierCurvePoints;
3795
3926
  exports.getAdaptiveQuadraticBezierCurvePoints = getAdaptiveQuadraticBezierCurvePoints;
3796
3927
  exports.parseArcCommand = parseArcCommand;
3797
3928
  exports.parsePathDataArgs = parsePathDataArgs;
3798
- exports.parseSVG = parseSVG;
3799
- exports.parseSVGToDOM = parseSVGToDOM;
3800
3929
  exports.quadraticBezier = quadraticBezier;
3801
3930
  exports.setCanvasContext = setCanvasContext;
3802
3931
  exports.strokeTriangulate = strokeTriangulate;
3803
3932
  exports.svgPathCommandsAddToPath2D = svgPathCommandsAddToPath2D;
3804
3933
  exports.svgPathCommandsToData = svgPathCommandsToData;
3805
3934
  exports.svgPathDataToCommands = svgPathDataToCommands;
3935
+ exports.svgToDOM = svgToDOM;
3936
+ exports.svgToPath2DSet = svgToPath2DSet;