modern-path2d 1.3.2 → 1.3.4

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
@@ -506,7 +506,6 @@ function parseArcCommand(path, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, s
506
506
  }
507
507
 
508
508
  const RE$3 = {
509
- SEPARATOR: /[ \t\r\n,.\-+]/,
510
509
  WHITESPACE: /[ \t\r\n]/,
511
510
  DIGIT: /\d/,
512
511
  SIGN: /[-+]/,
@@ -1029,7 +1028,7 @@ function cubicBezier(t, p0, p1, p2, p3) {
1029
1028
  return cubicBezierP0(t, p0) + cubicBezierP1(t, p1) + cubicBezierP2(t, p2) + cubicBezierP3(t, p3);
1030
1029
  }
1031
1030
 
1032
- function fillTriangulate(points, options = {}) {
1031
+ function fillTriangulate(pointArray, options = {}) {
1033
1032
  let {
1034
1033
  vertices = [],
1035
1034
  indices = [],
@@ -1038,17 +1037,17 @@ function fillTriangulate(points, options = {}) {
1038
1037
  verticesOffset = vertices.length / verticesStride,
1039
1038
  indicesOffset = indices.length
1040
1039
  } = options;
1041
- const triangles = earcut(points, holes, 2);
1042
- if (triangles) {
1040
+ const triangles = earcut(pointArray, holes, 2);
1041
+ if (triangles.length) {
1043
1042
  for (let i = 0; i < triangles.length; i += 3) {
1044
1043
  indices[indicesOffset++] = triangles[i] + verticesOffset;
1045
1044
  indices[indicesOffset++] = triangles[i + 1] + verticesOffset;
1046
1045
  indices[indicesOffset++] = triangles[i + 2] + verticesOffset;
1047
1046
  }
1048
1047
  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];
1048
+ for (let i = 0; i < pointArray.length; i += 2) {
1049
+ vertices[index] = pointArray[i];
1050
+ vertices[index + 1] = pointArray[i + 1];
1052
1051
  index += verticesStride;
1053
1052
  }
1054
1053
  }
@@ -1175,6 +1174,35 @@ function recursive(points, x1, y1, x2, y2, x3, y3, distanceTolerance, level) {
1175
1174
  recursive(points, x123, y123, x23, y23, x3, y3, distanceTolerance, level + 1);
1176
1175
  }
1177
1176
 
1177
+ function getDirectedArea(vertices) {
1178
+ let area = 0;
1179
+ const n = vertices.length;
1180
+ for (let i = 0; i < n; i += 2) {
1181
+ const x0 = vertices[i];
1182
+ const y0 = vertices[i + 1];
1183
+ const x1 = vertices[(i + 2) % (n - 1)];
1184
+ const y1 = vertices[(i + 3) % n];
1185
+ area += x0 * y1 - x1 * y0;
1186
+ }
1187
+ return area / 2;
1188
+ }
1189
+
1190
+ function pointInPolygon(point, polygon) {
1191
+ let inside = false;
1192
+ const [x, y] = point;
1193
+ const len = polygon.length / 2;
1194
+ for (let i = 0, j = len - 1; i < len; j = i++) {
1195
+ const xi = polygon[i * 2];
1196
+ const yi = polygon[i * 2 + 1];
1197
+ const xj = polygon[j * 2];
1198
+ const yj = polygon[j * 2 + 1];
1199
+ if (yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi) {
1200
+ inside = !inside;
1201
+ }
1202
+ }
1203
+ return inside;
1204
+ }
1205
+
1178
1206
  function quadraticBezierP0(t, p) {
1179
1207
  const k = 1 - t;
1180
1208
  return k * k * p;
@@ -1603,7 +1631,7 @@ class Curve {
1603
1631
  });
1604
1632
  return this;
1605
1633
  }
1606
- getUnevenPointArray(count = 5, output = []) {
1634
+ getUnevenVertices(count = 5, output = []) {
1607
1635
  const p = new Vector2();
1608
1636
  for (let i = 0, len = Math.max(1, count) - 1; i <= len; i++) {
1609
1637
  this.getPoint(i / len, p);
@@ -1611,7 +1639,7 @@ class Curve {
1611
1639
  }
1612
1640
  return output;
1613
1641
  }
1614
- getSpacedPointArray(count = 5, output = []) {
1642
+ getSpacedVertices(count = 5, output = []) {
1615
1643
  const p = new Vector2();
1616
1644
  for (let i = 0, len = Math.max(1, count) - 1; i <= len; i++) {
1617
1645
  this.getPointAt(i / len, p);
@@ -1619,40 +1647,40 @@ class Curve {
1619
1647
  }
1620
1648
  return output;
1621
1649
  }
1622
- getAdaptivePointArray(output = []) {
1623
- return this.getUnevenPointArray(5, output);
1650
+ getAdaptiveVertices(output = []) {
1651
+ return this.getUnevenVertices(5, output);
1624
1652
  }
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];
1653
+ _verticesToPoints(vertices, output = []) {
1654
+ for (let i = 0, len = vertices.length; i < len; i += 2) {
1655
+ const x = vertices[i];
1656
+ const y = vertices[i + 1];
1629
1657
  output.push(new Vector2(x, y));
1630
1658
  }
1631
1659
  return output;
1632
1660
  }
1633
1661
  getSpacedPoints(count, output = []) {
1634
- const array = this.getSpacedPointArray(count);
1635
- this._pointArrayToPoint(array, output);
1662
+ const array = this.getSpacedVertices(count);
1663
+ this._verticesToPoints(array, output);
1636
1664
  return output;
1637
1665
  }
1638
1666
  getUnevenPoints(count, output = []) {
1639
- const array = this.getUnevenPointArray(count);
1640
- this._pointArrayToPoint(array, output);
1667
+ const array = this.getUnevenVertices(count);
1668
+ this._verticesToPoints(array, output);
1641
1669
  return output;
1642
1670
  }
1643
1671
  getAdaptivePoints(output = []) {
1644
- const array = this.getAdaptivePointArray();
1645
- this._pointArrayToPoint(array, output);
1672
+ const array = this.getAdaptiveVertices();
1673
+ this._verticesToPoints(array, output);
1646
1674
  return output;
1647
1675
  }
1648
1676
  getPoints(count, output = []) {
1649
1677
  let array;
1650
1678
  if (count) {
1651
- array = this.getUnevenPointArray(count);
1679
+ array = this.getUnevenVertices(count);
1652
1680
  } else {
1653
- array = this.getAdaptivePointArray();
1681
+ array = this.getAdaptiveVertices();
1654
1682
  }
1655
- this._pointArrayToPoint(array, output);
1683
+ this._verticesToPoints(array, output);
1656
1684
  return output;
1657
1685
  }
1658
1686
  getLength() {
@@ -1757,15 +1785,18 @@ class Curve {
1757
1785
  const { min, max } = this.getMinMax();
1758
1786
  return new BoundingBox(min.x, min.y, max.x - min.x, max.y - min.y);
1759
1787
  }
1788
+ getFillVertices(_options) {
1789
+ return this.getAdaptiveVertices();
1790
+ }
1760
1791
  fillTriangulate(options) {
1761
1792
  return fillTriangulate(
1762
- this.getAdaptivePointArray(),
1793
+ this.getFillVertices(options),
1763
1794
  options
1764
1795
  );
1765
1796
  }
1766
1797
  strokeTriangulate(options) {
1767
1798
  return strokeTriangulate(
1768
- this.getAdaptivePointArray(),
1799
+ this.getAdaptiveVertices(),
1769
1800
  options
1770
1801
  );
1771
1802
  }
@@ -1943,69 +1974,115 @@ class RoundCurve extends Curve {
1943
1974
  getControlPointRefs() {
1944
1975
  return [this._center];
1945
1976
  }
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;
1977
+ _getAdaptiveVerticesByArc(output = []) {
1978
+ const { cx, cy, rx, ry, dx, dy, startAngle, endAngle, clockwise: _clockwise } = this;
1979
+ const clockwise = !_clockwise;
1980
+ const x = cx;
1981
+ const y = cy;
1982
+ const start = startAngle;
1983
+ const end = endAngle;
1984
+ let dist = Math.abs(start - end);
1985
+ if (!clockwise && start > end) {
1986
+ dist = 2 * Math.PI - dist;
1987
+ } else if (clockwise && end > start) {
1988
+ dist = 2 * Math.PI - dist;
1956
1989
  }
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);
1990
+ let steps = Math.max(6, Math.floor(6 * rx ** (1 / 3) * (dist / Math.PI)));
1991
+ steps = Math.max(steps, 3);
1992
+ 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) {
@@ -2939,7 +2978,7 @@ class CurvePath extends CompositeCurve {
2939
2978
  this.curves.push(new LineCurve(end.clone(), start.clone()));
2940
2979
  end.copy(start);
2941
2980
  }
2942
- this.startPoint = undefined;
2981
+ this.startPoint = void 0;
2943
2982
  }
2944
2983
  return this;
2945
2984
  }
@@ -3347,20 +3386,73 @@ 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) {
3363
- const { min, max } = this.getMinMax(undefined, undefined, withStyle);
3455
+ const { min, max } = this.getMinMax(void 0, void 0, withStyle);
3364
3456
  return new BoundingBox(min.x, min.y, max.x - min.x, max.y - min.y);
3365
3457
  }
3366
3458
  drawTo(ctx, style = {}) {
@@ -3413,7 +3505,7 @@ class Path2D extends CompositeCurve {
3413
3505
  };
3414
3506
  const cssStyle = {};
3415
3507
  for (const key in style) {
3416
- if (style[key] !== undefined) {
3508
+ if (style[key] !== void 0) {
3417
3509
  cssStyle[toKebabCase(key)] = style[key];
3418
3510
  }
3419
3511
  }
@@ -3422,7 +3514,7 @@ class Path2D extends CompositeCurve {
3422
3514
  });
3423
3515
  let cssText = "";
3424
3516
  for (const key in cssStyle) {
3425
- if (cssStyle[key] !== undefined) {
3517
+ if (cssStyle[key] !== void 0) {
3426
3518
  cssText += `${key}:${cssStyle[key]};`;
3427
3519
  }
3428
3520
  }
@@ -3443,7 +3535,7 @@ class Path2DSet {
3443
3535
  }
3444
3536
  getBoundingBox(withStyle = true) {
3445
3537
  if (!this.paths.length) {
3446
- return undefined;
3538
+ return void 0;
3447
3539
  }
3448
3540
  const min = Vector2.MAX;
3449
3541
  const max = Vector2.MIN;
@@ -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];
@@ -3641,7 +3733,7 @@ const unitConversion = {
3641
3733
  };
3642
3734
  function parseFloatWithUnits(string) {
3643
3735
  let theUnit = "px";
3644
- if (typeof string === "string" || string instanceof String) {
3736
+ if (typeof string === "string") {
3645
3737
  for (let i = 0, n = units.length; i < n; i++) {
3646
3738
  const u = units[i];
3647
3739
  if (string.endsWith(u)) {
@@ -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 };