modern-path2d 1.3.2 → 1.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/dist/index.mjs CHANGED
@@ -1029,7 +1029,7 @@ function cubicBezier(t, p0, p1, p2, p3) {
1029
1029
  return cubicBezierP0(t, p0) + cubicBezierP1(t, p1) + cubicBezierP2(t, p2) + cubicBezierP3(t, p3);
1030
1030
  }
1031
1031
 
1032
- function fillTriangulate(points, options = {}) {
1032
+ function fillTriangulate(pointArray, options = {}) {
1033
1033
  let {
1034
1034
  vertices = [],
1035
1035
  indices = [],
@@ -1038,17 +1038,17 @@ function fillTriangulate(points, options = {}) {
1038
1038
  verticesOffset = vertices.length / verticesStride,
1039
1039
  indicesOffset = indices.length
1040
1040
  } = options;
1041
- const triangles = earcut(points, holes, 2);
1042
- if (triangles) {
1041
+ const triangles = earcut(pointArray, holes, 2);
1042
+ if (triangles.length) {
1043
1043
  for (let i = 0; i < triangles.length; i += 3) {
1044
1044
  indices[indicesOffset++] = triangles[i] + verticesOffset;
1045
1045
  indices[indicesOffset++] = triangles[i + 1] + verticesOffset;
1046
1046
  indices[indicesOffset++] = triangles[i + 2] + verticesOffset;
1047
1047
  }
1048
1048
  let index = verticesOffset * verticesStride;
1049
- for (let i = 0; i < points.length; i += 2) {
1050
- vertices[index] = points[i];
1051
- vertices[index + 1] = points[i + 1];
1049
+ for (let i = 0; i < pointArray.length; i += 2) {
1050
+ vertices[index] = pointArray[i];
1051
+ vertices[index + 1] = pointArray[i + 1];
1052
1052
  index += verticesStride;
1053
1053
  }
1054
1054
  }
@@ -1175,6 +1175,35 @@ function recursive(points, x1, y1, x2, y2, x3, y3, distanceTolerance, level) {
1175
1175
  recursive(points, x123, y123, x23, y23, x3, y3, distanceTolerance, level + 1);
1176
1176
  }
1177
1177
 
1178
+ function getDirectedArea(vertices) {
1179
+ let area = 0;
1180
+ const n = vertices.length;
1181
+ for (let i = 0; i < n; i += 2) {
1182
+ const x0 = vertices[i];
1183
+ const y0 = vertices[i + 1];
1184
+ const x1 = vertices[(i + 2) % (n - 1)];
1185
+ const y1 = vertices[(i + 3) % n];
1186
+ area += x0 * y1 - x1 * y0;
1187
+ }
1188
+ return area / 2;
1189
+ }
1190
+
1191
+ function pointInPolygon(point, polygon) {
1192
+ let inside = false;
1193
+ const [x, y] = point;
1194
+ const len = polygon.length / 2;
1195
+ for (let i = 0, j = len - 1; i < len; j = i++) {
1196
+ const xi = polygon[i * 2];
1197
+ const yi = polygon[i * 2 + 1];
1198
+ const xj = polygon[j * 2];
1199
+ const yj = polygon[j * 2 + 1];
1200
+ if (yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi) {
1201
+ inside = !inside;
1202
+ }
1203
+ }
1204
+ return inside;
1205
+ }
1206
+
1178
1207
  function quadraticBezierP0(t, p) {
1179
1208
  const k = 1 - t;
1180
1209
  return k * k * p;
@@ -1603,7 +1632,7 @@ class Curve {
1603
1632
  });
1604
1633
  return this;
1605
1634
  }
1606
- getUnevenPointArray(count = 5, output = []) {
1635
+ getUnevenVertices(count = 5, output = []) {
1607
1636
  const p = new Vector2();
1608
1637
  for (let i = 0, len = Math.max(1, count) - 1; i <= len; i++) {
1609
1638
  this.getPoint(i / len, p);
@@ -1611,7 +1640,7 @@ class Curve {
1611
1640
  }
1612
1641
  return output;
1613
1642
  }
1614
- getSpacedPointArray(count = 5, output = []) {
1643
+ getSpacedVertices(count = 5, output = []) {
1615
1644
  const p = new Vector2();
1616
1645
  for (let i = 0, len = Math.max(1, count) - 1; i <= len; i++) {
1617
1646
  this.getPointAt(i / len, p);
@@ -1619,40 +1648,40 @@ class Curve {
1619
1648
  }
1620
1649
  return output;
1621
1650
  }
1622
- getAdaptivePointArray(output = []) {
1623
- return this.getUnevenPointArray(5, output);
1651
+ getAdaptiveVertices(output = []) {
1652
+ return this.getUnevenVertices(5, output);
1624
1653
  }
1625
- _pointArrayToPoint(array, output = []) {
1626
- for (let i = 0, len = array.length; i < len; i += 2) {
1627
- const x = array[i];
1628
- const y = array[i + 1];
1654
+ _verticesToPoints(vertices, output = []) {
1655
+ for (let i = 0, len = vertices.length; i < len; i += 2) {
1656
+ const x = vertices[i];
1657
+ const y = vertices[i + 1];
1629
1658
  output.push(new Vector2(x, y));
1630
1659
  }
1631
1660
  return output;
1632
1661
  }
1633
1662
  getSpacedPoints(count, output = []) {
1634
- const array = this.getSpacedPointArray(count);
1635
- this._pointArrayToPoint(array, output);
1663
+ const array = this.getSpacedVertices(count);
1664
+ this._verticesToPoints(array, output);
1636
1665
  return output;
1637
1666
  }
1638
1667
  getUnevenPoints(count, output = []) {
1639
- const array = this.getUnevenPointArray(count);
1640
- this._pointArrayToPoint(array, output);
1668
+ const array = this.getUnevenVertices(count);
1669
+ this._verticesToPoints(array, output);
1641
1670
  return output;
1642
1671
  }
1643
1672
  getAdaptivePoints(output = []) {
1644
- const array = this.getAdaptivePointArray();
1645
- this._pointArrayToPoint(array, output);
1673
+ const array = this.getAdaptiveVertices();
1674
+ this._verticesToPoints(array, output);
1646
1675
  return output;
1647
1676
  }
1648
1677
  getPoints(count, output = []) {
1649
1678
  let array;
1650
1679
  if (count) {
1651
- array = this.getUnevenPointArray(count);
1680
+ array = this.getUnevenVertices(count);
1652
1681
  } else {
1653
- array = this.getAdaptivePointArray();
1682
+ array = this.getAdaptiveVertices();
1654
1683
  }
1655
- this._pointArrayToPoint(array, output);
1684
+ this._verticesToPoints(array, output);
1656
1685
  return output;
1657
1686
  }
1658
1687
  getLength() {
@@ -1757,15 +1786,18 @@ class Curve {
1757
1786
  const { min, max } = this.getMinMax();
1758
1787
  return new BoundingBox(min.x, min.y, max.x - min.x, max.y - min.y);
1759
1788
  }
1789
+ getFillVertices(_options) {
1790
+ return this.getAdaptiveVertices();
1791
+ }
1760
1792
  fillTriangulate(options) {
1761
1793
  return fillTriangulate(
1762
- this.getAdaptivePointArray(),
1794
+ this.getFillVertices(options),
1763
1795
  options
1764
1796
  );
1765
1797
  }
1766
1798
  strokeTriangulate(options) {
1767
1799
  return strokeTriangulate(
1768
- this.getAdaptivePointArray(),
1800
+ this.getAdaptiveVertices(),
1769
1801
  options
1770
1802
  );
1771
1803
  }
@@ -1943,69 +1975,114 @@ class RoundCurve extends Curve {
1943
1975
  getControlPointRefs() {
1944
1976
  return [this._center];
1945
1977
  }
1946
- getAdaptivePointArray(output = []) {
1947
- const { cx, cy, rx, ry, startAngle, endAngle, clockwise } = this;
1948
- if (!(rx >= 0 && ry >= 0)) {
1949
- return output;
1950
- }
1951
- let deltaAngle = endAngle - startAngle;
1952
- if (!clockwise && deltaAngle > 0) {
1953
- deltaAngle -= 2 * Math.PI;
1954
- } else if (clockwise && deltaAngle < 0) {
1955
- deltaAngle += 2 * Math.PI;
1978
+ _getAdaptiveVerticesByArc(output = []) {
1979
+ const { cx, cy, rx, ry, dx, dy, startAngle, endAngle, clockwise: _clockwise } = this;
1980
+ const clockwise = !_clockwise;
1981
+ const x = cx;
1982
+ const y = cy;
1983
+ const start = startAngle;
1984
+ const end = endAngle;
1985
+ let dist = Math.abs(start - end);
1986
+ if (!clockwise && start > end) {
1987
+ dist = 2 * Math.PI - dist;
1988
+ } else if (clockwise && end > start) {
1989
+ dist = 2 * Math.PI - dist;
1956
1990
  }
1957
- const arcLength = Math.abs(deltaAngle);
1958
- const n = Math.max(1, Math.ceil(arcLength / (Math.PI / 16)));
1959
- for (let i = 0; i <= n; i++) {
1960
- const t = i / n;
1961
- const angle = startAngle + deltaAngle * t;
1962
- const x = cx + Math.cos(angle) * rx;
1963
- const y = cy + Math.sin(angle) * ry;
1964
- output.push(x, y);
1991
+ let steps = Math.max(6, Math.floor(6 * rx ** (1 / 3) * (dist / Math.PI)));
1992
+ steps = Math.max(steps, 3);
1993
+ let f = dist / steps;
1994
+ let t = start;
1995
+ f *= clockwise ? -1 : 1;
1996
+ for (let i = 0; i < steps + 1; i++) {
1997
+ const cs = Math.cos(t);
1998
+ const sn = Math.sin(t);
1999
+ const nx = x + dx + cs * rx;
2000
+ const ny = y + dy + sn * ry;
2001
+ output.push(nx, ny);
2002
+ t += f;
1965
2003
  }
1966
2004
  return output;
1967
2005
  }
1968
- fillTriangulate(options = {}) {
1969
- let {
1970
- vertices = [],
1971
- indices = [],
1972
- verticesStride = 2,
1973
- verticesOffset = vertices.length / verticesStride,
1974
- indicesOffset = indices.length
1975
- } = options;
1976
- const points = this.getAdaptivePointArray();
1977
- if (points.length === 0) {
1978
- return { vertices, indices };
2006
+ _getAdaptiveVerticesByCircle(output = []) {
2007
+ const { cx, cy, rx, ry, dx, dy } = this;
2008
+ if (!(rx >= 0 && ry >= 0 && dx >= 0 && dy >= 0)) {
2009
+ return output;
1979
2010
  }
1980
- let centerX = 0;
1981
- let centerY = 0;
1982
- for (let i = 0; i < points.length; i += 2) {
1983
- centerX += points[i];
1984
- centerY += points[i + 1];
2011
+ const n = Math.ceil(2.3 * Math.sqrt(rx + ry));
2012
+ const x = cx;
2013
+ const y = cy;
2014
+ const m = n * 8 + (dx ? 4 : 0) + (dy ? 4 : 0);
2015
+ if (m === 0) {
2016
+ return output;
1985
2017
  }
1986
- centerX /= points.length / 2;
1987
- centerY /= points.length / 2;
1988
- let count = verticesOffset;
1989
- vertices[count * verticesStride] = centerX;
1990
- vertices[count * verticesStride + 1] = centerY;
1991
- const centerIndex = count++;
1992
- for (let i = 0; i < points.length; i += 2) {
1993
- vertices[count * verticesStride] = points[i];
1994
- vertices[count * verticesStride + 1] = points[i + 1];
1995
- if (i > 0) {
1996
- indices[indicesOffset++] = count;
1997
- indices[indicesOffset++] = centerIndex;
1998
- indices[indicesOffset++] = count - 1;
1999
- }
2000
- count++;
2018
+ const start = output.length;
2019
+ if (n === 0) {
2020
+ output[start] = output[start + 6] = x + dx;
2021
+ output[start + 1] = output[start + 3] = y + dy;
2022
+ output[start + 2] = output[start + 4] = x - dx;
2023
+ output[start + 5] = output[start + 7] = y - dy;
2024
+ return output;
2001
2025
  }
2002
- indices[indicesOffset++] = centerIndex + 1;
2003
- indices[indicesOffset++] = centerIndex;
2004
- indices[indicesOffset++] = count - 1;
2005
- return {
2006
- vertices,
2007
- indices
2008
- };
2026
+ let j1 = start;
2027
+ let j2 = start + n * 4 + (dx ? 2 : 0) + 2;
2028
+ let j3 = j2;
2029
+ let j4 = m;
2030
+ let x0 = dx + rx;
2031
+ let y0 = dy;
2032
+ let x1 = x + x0;
2033
+ let x2 = x - x0;
2034
+ let y1 = y + y0;
2035
+ output[j1++] = x1;
2036
+ output[j1++] = y1;
2037
+ output[--j2] = y1;
2038
+ output[--j2] = x2;
2039
+ if (dy) {
2040
+ const y22 = y - y0;
2041
+ output[j3++] = x2;
2042
+ output[j3++] = y22;
2043
+ output[--j4] = y22;
2044
+ output[--j4] = x1;
2045
+ }
2046
+ for (let i = 1; i < n; i++) {
2047
+ const a = Math.PI / 2 * (i / n);
2048
+ const x02 = dx + Math.cos(a) * rx;
2049
+ const y02 = dy + Math.sin(a) * ry;
2050
+ const x12 = x + x02;
2051
+ const x22 = x - x02;
2052
+ const y12 = y + y02;
2053
+ const y22 = y - y02;
2054
+ output[j1++] = x12;
2055
+ output[j1++] = y12;
2056
+ output[--j2] = y12;
2057
+ output[--j2] = x22;
2058
+ output[j3++] = x22;
2059
+ output[j3++] = y22;
2060
+ output[--j4] = y22;
2061
+ output[--j4] = x12;
2062
+ }
2063
+ x0 = dx;
2064
+ y0 = dy + ry;
2065
+ x1 = x + x0;
2066
+ x2 = x - x0;
2067
+ y1 = y + y0;
2068
+ const y2 = y - y0;
2069
+ output[j1++] = x1;
2070
+ output[j1++] = y1;
2071
+ output[--j4] = y2;
2072
+ output[--j4] = x1;
2073
+ if (dx) {
2074
+ output[j1++] = x2;
2075
+ output[j1++] = y1;
2076
+ output[--j4] = y2;
2077
+ output[--j4] = x2;
2078
+ }
2079
+ return output;
2080
+ }
2081
+ getAdaptiveVertices(output = []) {
2082
+ if (this.startAngle === 0 && this.endAngle === Math.PI * 2) {
2083
+ return this._getAdaptiveVerticesByCircle(output);
2084
+ }
2085
+ return this._getAdaptiveVerticesByArc(output);
2009
2086
  }
2010
2087
  getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
2011
2088
  const { cx, cy, rx, ry, rotate } = this;
@@ -2202,7 +2279,7 @@ class ArcCurve extends RoundCurve {
2202
2279
  );
2203
2280
  return this;
2204
2281
  }
2205
- getAdaptivePointArray(output = []) {
2282
+ getAdaptiveVertices(output = []) {
2206
2283
  const { cx, cy, rx, startAngle, endAngle, clockwise } = this;
2207
2284
  let dist = Math.abs(startAngle - endAngle);
2208
2285
  if (!clockwise && startAngle > endAngle) {
@@ -2227,6 +2304,96 @@ class ArcCurve extends RoundCurve {
2227
2304
  }
2228
2305
  }
2229
2306
 
2307
+ class LineCurve extends Curve {
2308
+ constructor(p1 = new Vector2(), p2 = new Vector2()) {
2309
+ super();
2310
+ this.p1 = p1;
2311
+ this.p2 = p2;
2312
+ }
2313
+ static from(p1x, p1y, p2x, p2y) {
2314
+ return new LineCurve(
2315
+ new Vector2(p1x, p1y),
2316
+ new Vector2(p2x, p2y)
2317
+ );
2318
+ }
2319
+ getPoint(t, output = new Vector2()) {
2320
+ if (t === 1) {
2321
+ output.copy(this.p2);
2322
+ } else {
2323
+ output.copy(this.p2).sub(this.p1).scale(t).add(this.p1);
2324
+ }
2325
+ return output;
2326
+ }
2327
+ getPointAt(u, output = new Vector2()) {
2328
+ return this.getPoint(u, output);
2329
+ }
2330
+ getTangent(_t, output = new Vector2()) {
2331
+ return output.subVectors(this.p2, this.p1).normalize();
2332
+ }
2333
+ getTangentAt(u, output = new Vector2()) {
2334
+ return this.getTangent(u, output);
2335
+ }
2336
+ getControlPointRefs() {
2337
+ return [this.p1, this.p2];
2338
+ }
2339
+ getAdaptiveVertices(output = []) {
2340
+ output.push(
2341
+ this.p1.x,
2342
+ this.p1.y,
2343
+ this.p2.x,
2344
+ this.p2.y
2345
+ );
2346
+ return output;
2347
+ }
2348
+ getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
2349
+ const { p1, p2 } = this;
2350
+ min.x = Math.min(min.x, p1.x, p2.x);
2351
+ min.y = Math.min(min.y, p1.y, p2.y);
2352
+ max.x = Math.max(max.x, p1.x, p2.x);
2353
+ max.y = Math.max(max.y, p1.y, p2.y);
2354
+ return { min: min.finite(), max: max.finite() };
2355
+ }
2356
+ toCommands() {
2357
+ const { p1, p2 } = this;
2358
+ return [
2359
+ { type: "M", x: p1.x, y: p1.y },
2360
+ { type: "L", x: p2.x, y: p2.y }
2361
+ ];
2362
+ }
2363
+ getFillVertices(options = {}) {
2364
+ const minX = Math.min(this.p1.x, this.p2.x);
2365
+ const maxX = Math.max(this.p1.x, this.p2.x);
2366
+ const minY = Math.min(this.p1.y, this.p2.y);
2367
+ const maxY = Math.max(this.p1.y, this.p2.y);
2368
+ const x = minX;
2369
+ const y = minY;
2370
+ const width = maxX - minX || options.style?.strokeWidth || 0;
2371
+ const height = maxY - minY || options.style?.strokeWidth || 0;
2372
+ return [
2373
+ x,
2374
+ y,
2375
+ x + width,
2376
+ y,
2377
+ x + width,
2378
+ y + height,
2379
+ x,
2380
+ y + height
2381
+ ];
2382
+ }
2383
+ drawTo(ctx) {
2384
+ const { p1, p2 } = this;
2385
+ ctx.lineTo(p1.x, p1.y);
2386
+ ctx.lineTo(p2.x, p2.y);
2387
+ return this;
2388
+ }
2389
+ copy(source) {
2390
+ super.copy(source);
2391
+ this.p1.copy(source.p1);
2392
+ this.p2.copy(source.p2);
2393
+ return this;
2394
+ }
2395
+ }
2396
+
2230
2397
  class CompositeCurve extends Curve {
2231
2398
  constructor(curves = []) {
2232
2399
  super();
@@ -2281,10 +2448,10 @@ class CompositeCurve extends Curve {
2281
2448
  }
2282
2449
  return output;
2283
2450
  }
2284
- getSpacedPointArray(count = 5, output = []) {
2451
+ getSpacedVertices(count = 5, output = []) {
2285
2452
  let offset;
2286
2453
  this.curves.forEach((curve) => {
2287
- curve.getSpacedPointArray(count, output);
2454
+ curve.getSpacedVertices(count, output);
2288
2455
  if (offset) {
2289
2456
  this._removeNextPointIfEqualPrevPoint(output, offset);
2290
2457
  }
@@ -2292,10 +2459,10 @@ class CompositeCurve extends Curve {
2292
2459
  });
2293
2460
  return output;
2294
2461
  }
2295
- getAdaptivePointArray(output = []) {
2462
+ getAdaptiveVertices(output = []) {
2296
2463
  let offset;
2297
2464
  this.curves.forEach((curve) => {
2298
- curve.getAdaptivePointArray(output);
2465
+ curve.getAdaptiveVertices(output);
2299
2466
  if (offset) {
2300
2467
  this._removeNextPointIfEqualPrevPoint(output, offset);
2301
2468
  }
@@ -2310,11 +2477,26 @@ class CompositeCurve extends Curve {
2310
2477
  return super.strokeTriangulate(options);
2311
2478
  }
2312
2479
  }
2313
- fillTriangulate(options) {
2480
+ getFillVertices(options) {
2314
2481
  if (this.curves.length === 1) {
2315
- return this.curves[0].fillTriangulate(options);
2482
+ return this.curves[0].getFillVertices(options);
2316
2483
  } else {
2317
- return super.fillTriangulate(options);
2484
+ const output = [];
2485
+ let offset;
2486
+ this.curves.forEach((curve) => {
2487
+ let arr;
2488
+ if (curve instanceof LineCurve) {
2489
+ arr = curve.getAdaptiveVertices();
2490
+ } else {
2491
+ arr = curve.getFillVertices(options);
2492
+ }
2493
+ output.push(...arr);
2494
+ if (offset) {
2495
+ this._removeNextPointIfEqualPrevPoint(output, offset);
2496
+ }
2497
+ offset = output.length - 1;
2498
+ });
2499
+ return output;
2318
2500
  }
2319
2501
  }
2320
2502
  applyTransform(transform) {
@@ -2370,7 +2552,7 @@ class CubicBezierCurve extends Curve {
2370
2552
  cubicBezier(t, p1.y, cp1.y, cp2.y, p2.y)
2371
2553
  );
2372
2554
  }
2373
- getAdaptivePointArray(output = []) {
2555
+ getAdaptiveVertices(output = []) {
2374
2556
  return getAdaptiveCubicBezierCurvePoints(
2375
2557
  this.p1.x,
2376
2558
  this.p1.y,
@@ -2475,125 +2657,6 @@ class EllipseCurve extends RoundCurve {
2475
2657
  }
2476
2658
  }
2477
2659
 
2478
- class LineCurve extends Curve {
2479
- constructor(p1 = new Vector2(), p2 = new Vector2()) {
2480
- super();
2481
- this.p1 = p1;
2482
- this.p2 = p2;
2483
- }
2484
- static from(p1x, p1y, p2x, p2y) {
2485
- return new LineCurve(
2486
- new Vector2(p1x, p1y),
2487
- new Vector2(p2x, p2y)
2488
- );
2489
- }
2490
- getPoint(t, output = new Vector2()) {
2491
- if (t === 1) {
2492
- output.copy(this.p2);
2493
- } else {
2494
- output.copy(this.p2).sub(this.p1).scale(t).add(this.p1);
2495
- }
2496
- return output;
2497
- }
2498
- getPointAt(u, output = new Vector2()) {
2499
- return this.getPoint(u, output);
2500
- }
2501
- getTangent(_t, output = new Vector2()) {
2502
- return output.subVectors(this.p2, this.p1).normalize();
2503
- }
2504
- getTangentAt(u, output = new Vector2()) {
2505
- return this.getTangent(u, output);
2506
- }
2507
- getControlPointRefs() {
2508
- return [this.p1, this.p2];
2509
- }
2510
- getAdaptivePointArray(output = []) {
2511
- output.push(
2512
- this.p1.x,
2513
- this.p1.y,
2514
- this.p2.x,
2515
- this.p2.y
2516
- );
2517
- return output;
2518
- }
2519
- getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
2520
- const { p1, p2 } = this;
2521
- min.x = Math.min(min.x, p1.x, p2.x);
2522
- min.y = Math.min(min.y, p1.y, p2.y);
2523
- max.x = Math.max(max.x, p1.x, p2.x);
2524
- max.y = Math.max(max.y, p1.y, p2.y);
2525
- return { min: min.finite(), max: max.finite() };
2526
- }
2527
- toCommands() {
2528
- const { p1, p2 } = this;
2529
- return [
2530
- { type: "M", x: p1.x, y: p1.y },
2531
- { type: "L", x: p2.x, y: p2.y }
2532
- ];
2533
- }
2534
- fillTriangulate(options = {}) {
2535
- let {
2536
- vertices = [],
2537
- indices = [],
2538
- verticesStride = 2,
2539
- verticesOffset = vertices.length / verticesStride,
2540
- indicesOffset = indices.length
2541
- } = options;
2542
- const minX = Math.min(this.p1.x, this.p2.x);
2543
- const maxX = Math.max(this.p1.x, this.p2.x);
2544
- const minY = Math.min(this.p1.y, this.p2.y);
2545
- const maxY = Math.max(this.p1.y, this.p2.y);
2546
- const x = minX;
2547
- const y = minY;
2548
- const width = maxX - minX || options.style?.strokeWidth || 1;
2549
- const height = maxY - minY || options.style?.strokeWidth || 1;
2550
- const points = [
2551
- x,
2552
- y,
2553
- x + width,
2554
- y,
2555
- x + width,
2556
- y + height,
2557
- x,
2558
- y + height
2559
- ];
2560
- let count = 0;
2561
- verticesOffset *= verticesStride;
2562
- vertices[verticesOffset + count] = points[0];
2563
- vertices[verticesOffset + count + 1] = points[1];
2564
- count += verticesStride;
2565
- vertices[verticesOffset + count] = points[2];
2566
- vertices[verticesOffset + count + 1] = points[3];
2567
- count += verticesStride;
2568
- vertices[verticesOffset + count] = points[6];
2569
- vertices[verticesOffset + count + 1] = points[7];
2570
- count += verticesStride;
2571
- vertices[verticesOffset + count] = points[4];
2572
- vertices[verticesOffset + count + 1] = points[5];
2573
- count += verticesStride;
2574
- const verticesIndex = verticesOffset / verticesStride;
2575
- indices[indicesOffset++] = verticesIndex;
2576
- indices[indicesOffset++] = verticesIndex + 1;
2577
- indices[indicesOffset++] = verticesIndex + 2;
2578
- indices[indicesOffset++] = verticesIndex + 1;
2579
- indices[indicesOffset++] = verticesIndex + 3;
2580
- indices[indicesOffset++] = verticesIndex + 2;
2581
- return { vertices, indices };
2582
- }
2583
- drawTo(ctx) {
2584
- const { p1, p2 } = this;
2585
- ctx.lineTo(p1.x, p1.y);
2586
- ctx.lineTo(p2.x, p2.y);
2587
- return this;
2588
- }
2589
- copy(source) {
2590
- super.copy(source);
2591
- this.p1.copy(source.p1);
2592
- this.p2.copy(source.p2);
2593
- return this;
2594
- }
2595
- }
2596
-
2597
2660
  class PloygonCurve extends CompositeCurve {
2598
2661
  //
2599
2662
  }
@@ -2667,7 +2730,7 @@ class QuadraticBezierCurve extends Curve {
2667
2730
  getControlPointRefs() {
2668
2731
  return [this.p1, this.cp, this.p2];
2669
2732
  }
2670
- getAdaptivePointArray(output = []) {
2733
+ getAdaptiveVertices(output = []) {
2671
2734
  return getAdaptiveQuadraticBezierCurvePoints(
2672
2735
  this.p1.x,
2673
2736
  this.p1.y,
@@ -2742,16 +2805,9 @@ class RectangleCurve extends PloygonCurve {
2742
2805
  ctx.rect(this.x, this.y, this.width, this.height);
2743
2806
  return this;
2744
2807
  }
2745
- fillTriangulate(options = {}) {
2746
- let {
2747
- vertices = [],
2748
- indices = [],
2749
- verticesStride = 2,
2750
- verticesOffset = vertices.length / verticesStride,
2751
- indicesOffset = indices.length
2752
- } = options;
2808
+ getFillVertices(_options = {}) {
2753
2809
  const { x, y, width, height } = this;
2754
- const points = [
2810
+ return [
2755
2811
  x,
2756
2812
  y,
2757
2813
  x + width,
@@ -2761,28 +2817,6 @@ class RectangleCurve extends PloygonCurve {
2761
2817
  x,
2762
2818
  y + height
2763
2819
  ];
2764
- let count = 0;
2765
- verticesOffset *= verticesStride;
2766
- vertices[verticesOffset + count] = points[0];
2767
- vertices[verticesOffset + count + 1] = points[1];
2768
- count += verticesStride;
2769
- vertices[verticesOffset + count] = points[2];
2770
- vertices[verticesOffset + count + 1] = points[3];
2771
- count += verticesStride;
2772
- vertices[verticesOffset + count] = points[6];
2773
- vertices[verticesOffset + count + 1] = points[7];
2774
- count += verticesStride;
2775
- vertices[verticesOffset + count] = points[4];
2776
- vertices[verticesOffset + count + 1] = points[5];
2777
- count += verticesStride;
2778
- const verticesIndex = verticesOffset / verticesStride;
2779
- indices[indicesOffset++] = verticesIndex;
2780
- indices[indicesOffset++] = verticesIndex + 1;
2781
- indices[indicesOffset++] = verticesIndex + 2;
2782
- indices[indicesOffset++] = verticesIndex + 1;
2783
- indices[indicesOffset++] = verticesIndex + 3;
2784
- indices[indicesOffset++] = verticesIndex + 2;
2785
- return { vertices, indices };
2786
2820
  }
2787
2821
  copy(source) {
2788
2822
  super.copy(source);
@@ -2894,25 +2928,30 @@ class CurvePath extends CompositeCurve {
2894
2928
  this.addCommands(svgPathDataToCommands(data));
2895
2929
  return this;
2896
2930
  }
2897
- _closePointArray(output) {
2931
+ _closeVertices(output) {
2898
2932
  if (this.autoClose && output.length >= 4 && (output[0] !== output[output.length - 2] && output[1] !== output[output.length - 1])) {
2899
2933
  output.push(output[0], output[1]);
2900
2934
  }
2901
2935
  return output;
2902
2936
  }
2903
- getUnevenPointArray(count = 40, output = []) {
2904
- return this._closePointArray(
2905
- super.getUnevenPointArray(count, output)
2937
+ getUnevenVertices(count = 40, output = []) {
2938
+ return this._closeVertices(
2939
+ super.getUnevenVertices(count, output)
2940
+ );
2941
+ }
2942
+ getSpacedVertices(count = 40, output = []) {
2943
+ return this._closeVertices(
2944
+ super.getSpacedVertices(count, output)
2906
2945
  );
2907
2946
  }
2908
- getSpacedPointArray(count = 40, output = []) {
2909
- return this._closePointArray(
2910
- super.getSpacedPointArray(count, output)
2947
+ getAdaptiveVertices(output = []) {
2948
+ return this._closeVertices(
2949
+ super.getAdaptiveVertices(output)
2911
2950
  );
2912
2951
  }
2913
- getAdaptivePointArray(output = []) {
2914
- return this._closePointArray(
2915
- super.getAdaptivePointArray(output)
2952
+ getFillVertices(options) {
2953
+ return this._closeVertices(
2954
+ super.getFillVertices(options)
2916
2955
  );
2917
2956
  }
2918
2957
  _setCurrentPoint(point) {
@@ -3347,16 +3386,69 @@ class Path2D extends CompositeCurve {
3347
3386
  return { indices, vertices };
3348
3387
  }
3349
3388
  fillTriangulate(options) {
3350
- const indices = options?.indices ?? [];
3351
- const vertices = options?.vertices ?? [];
3352
- this.curves.forEach((curve) => {
3353
- curve.fillTriangulate({
3354
- ...options,
3355
- indices,
3356
- vertices,
3357
- style: { ...this.style }
3389
+ const _options = {
3390
+ ...options,
3391
+ style: {
3392
+ ...this.style,
3393
+ ...options?.style
3394
+ }
3395
+ };
3396
+ const indices = _options.indices ?? [];
3397
+ const vertices = _options.vertices ?? [];
3398
+ const fillRule = _options.style.fillRule ?? "nonzero";
3399
+ if (fillRule === "nonzero") {
3400
+ const pointArrays = this.curves.map((curve) => curve.getFillVertices(_options));
3401
+ const parentMap = /* @__PURE__ */ new Map();
3402
+ const parentd = /* @__PURE__ */ new Set();
3403
+ for (let i = 0; i < pointArrays.length; i++) {
3404
+ const parents = [];
3405
+ for (let j = 0; j < pointArrays.length; j++) {
3406
+ if (i === j)
3407
+ continue;
3408
+ if (pointInPolygon([pointArrays[i][0], pointArrays[i][1]], pointArrays[j])) {
3409
+ parents.push(j);
3410
+ }
3411
+ }
3412
+ if (parents.length) {
3413
+ parents.forEach((pi) => {
3414
+ let set = parentMap.get(pi);
3415
+ if (!set) {
3416
+ set = /* @__PURE__ */ new Set();
3417
+ parentMap.set(pi, set);
3418
+ }
3419
+ set.add(i);
3420
+ });
3421
+ parentd.add(i);
3422
+ }
3423
+ }
3424
+ pointArrays.forEach((pointArray, i) => {
3425
+ if (parentd.has(i) || !pointArray.length) {
3426
+ return;
3427
+ }
3428
+ const _pointArray = pointArray.slice();
3429
+ const holes = [];
3430
+ parentMap.get(i)?.forEach((ci) => {
3431
+ holes.push(_pointArray.length / 2);
3432
+ _pointArray.push(...pointArrays[ci]);
3433
+ });
3434
+ fillTriangulate(_pointArray, {
3435
+ ...options,
3436
+ indices,
3437
+ vertices,
3438
+ holes,
3439
+ style: { ...this.style }
3440
+ });
3358
3441
  });
3359
- });
3442
+ } else {
3443
+ this.curves.forEach((curve) => {
3444
+ curve.fillTriangulate({
3445
+ ...options,
3446
+ indices,
3447
+ vertices,
3448
+ style: { ...this.style }
3449
+ });
3450
+ });
3451
+ }
3360
3452
  return { indices, vertices };
3361
3453
  }
3362
3454
  getBoundingBox(withStyle = true) {
@@ -3469,7 +3561,7 @@ class Path2DSet {
3469
3561
  const p1 = getPoint(indices[i]);
3470
3562
  const p2 = getPoint(indices[i + 1]);
3471
3563
  const p3 = getPoint(indices[i + 2]);
3472
- polygonStr += `<polygon points="${p1.join(",")} ${p2.join(",")} ${p3.join(",")}" fill="none" stroke="black" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" />`;
3564
+ polygonStr += `<polygon points="${p1.join(",")} ${p2.join(",")} ${p3.join(",")}" fill="black" />`;
3473
3565
  }
3474
3566
  });
3475
3567
  const viewBox = [min.x, min.y, max.x - min.x, max.y - min.y];
@@ -4093,4 +4185,4 @@ function svgToPath2DSet(svg) {
4093
4185
  );
4094
4186
  }
4095
4187
 
4096
- export { ArcCurve, BoundingBox, CompositeCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, EquilateralPloygonCurve, FFDControlGrid, LineCurve, Matrix3, Path2D, Path2DSet, PloygonCurve, QuadraticBezierCurve, RectangleCurve, RoundRectangleCurve, SplineCurve, Vector2, applyFFD, catmullRom, cubicBezier, drawPoint, fillTriangulate, getAdaptiveCubicBezierCurvePoints, getAdaptiveQuadraticBezierCurvePoints, parseArcCommand, parsePathDataArgs, quadraticBezier, setCanvasContext, strokeTriangulate, svgPathCommandsAddToPath2D, svgPathCommandsToData, svgPathDataToCommands, svgToDOM, svgToPath2DSet };
4188
+ export { ArcCurve, BoundingBox, CompositeCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, EquilateralPloygonCurve, FFDControlGrid, LineCurve, Matrix3, Path2D, Path2DSet, PloygonCurve, QuadraticBezierCurve, RectangleCurve, RoundRectangleCurve, SplineCurve, Vector2, applyFFD, catmullRom, cubicBezier, drawPoint, fillTriangulate, getAdaptiveCubicBezierCurvePoints, getAdaptiveQuadraticBezierCurvePoints, getDirectedArea, parseArcCommand, parsePathDataArgs, pointInPolygon, quadraticBezier, setCanvasContext, strokeTriangulate, svgPathCommandsAddToPath2D, svgPathCommandsToData, svgPathDataToCommands, svgToDOM, svgToPath2DSet };