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.cjs CHANGED
@@ -1035,7 +1035,7 @@ function cubicBezier(t, p0, p1, p2, p3) {
1035
1035
  return cubicBezierP0(t, p0) + cubicBezierP1(t, p1) + cubicBezierP2(t, p2) + cubicBezierP3(t, p3);
1036
1036
  }
1037
1037
 
1038
- function fillTriangulate(points, options = {}) {
1038
+ function fillTriangulate(pointArray, options = {}) {
1039
1039
  let {
1040
1040
  vertices = [],
1041
1041
  indices = [],
@@ -1044,17 +1044,17 @@ function fillTriangulate(points, options = {}) {
1044
1044
  verticesOffset = vertices.length / verticesStride,
1045
1045
  indicesOffset = indices.length
1046
1046
  } = options;
1047
- const triangles = earcut__default(points, holes, 2);
1048
- if (triangles) {
1047
+ const triangles = earcut__default(pointArray, holes, 2);
1048
+ if (triangles.length) {
1049
1049
  for (let i = 0; i < triangles.length; i += 3) {
1050
1050
  indices[indicesOffset++] = triangles[i] + verticesOffset;
1051
1051
  indices[indicesOffset++] = triangles[i + 1] + verticesOffset;
1052
1052
  indices[indicesOffset++] = triangles[i + 2] + verticesOffset;
1053
1053
  }
1054
1054
  let index = verticesOffset * verticesStride;
1055
- for (let i = 0; i < points.length; i += 2) {
1056
- vertices[index] = points[i];
1057
- vertices[index + 1] = points[i + 1];
1055
+ for (let i = 0; i < pointArray.length; i += 2) {
1056
+ vertices[index] = pointArray[i];
1057
+ vertices[index + 1] = pointArray[i + 1];
1058
1058
  index += verticesStride;
1059
1059
  }
1060
1060
  }
@@ -1181,6 +1181,35 @@ function recursive(points, x1, y1, x2, y2, x3, y3, distanceTolerance, level) {
1181
1181
  recursive(points, x123, y123, x23, y23, x3, y3, distanceTolerance, level + 1);
1182
1182
  }
1183
1183
 
1184
+ function getDirectedArea(vertices) {
1185
+ let area = 0;
1186
+ const n = vertices.length;
1187
+ for (let i = 0; i < n; i += 2) {
1188
+ const x0 = vertices[i];
1189
+ const y0 = vertices[i + 1];
1190
+ const x1 = vertices[(i + 2) % (n - 1)];
1191
+ const y1 = vertices[(i + 3) % n];
1192
+ area += x0 * y1 - x1 * y0;
1193
+ }
1194
+ return area / 2;
1195
+ }
1196
+
1197
+ function pointInPolygon(point, polygon) {
1198
+ let inside = false;
1199
+ const [x, y] = point;
1200
+ const len = polygon.length / 2;
1201
+ for (let i = 0, j = len - 1; i < len; j = i++) {
1202
+ const xi = polygon[i * 2];
1203
+ const yi = polygon[i * 2 + 1];
1204
+ const xj = polygon[j * 2];
1205
+ const yj = polygon[j * 2 + 1];
1206
+ if (yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi) {
1207
+ inside = !inside;
1208
+ }
1209
+ }
1210
+ return inside;
1211
+ }
1212
+
1184
1213
  function quadraticBezierP0(t, p) {
1185
1214
  const k = 1 - t;
1186
1215
  return k * k * p;
@@ -1609,7 +1638,7 @@ class Curve {
1609
1638
  });
1610
1639
  return this;
1611
1640
  }
1612
- getUnevenPointArray(count = 5, output = []) {
1641
+ getUnevenVertices(count = 5, output = []) {
1613
1642
  const p = new Vector2();
1614
1643
  for (let i = 0, len = Math.max(1, count) - 1; i <= len; i++) {
1615
1644
  this.getPoint(i / len, p);
@@ -1617,7 +1646,7 @@ class Curve {
1617
1646
  }
1618
1647
  return output;
1619
1648
  }
1620
- getSpacedPointArray(count = 5, output = []) {
1649
+ getSpacedVertices(count = 5, output = []) {
1621
1650
  const p = new Vector2();
1622
1651
  for (let i = 0, len = Math.max(1, count) - 1; i <= len; i++) {
1623
1652
  this.getPointAt(i / len, p);
@@ -1625,40 +1654,40 @@ class Curve {
1625
1654
  }
1626
1655
  return output;
1627
1656
  }
1628
- getAdaptivePointArray(output = []) {
1629
- return this.getUnevenPointArray(5, output);
1657
+ getAdaptiveVertices(output = []) {
1658
+ return this.getUnevenVertices(5, output);
1630
1659
  }
1631
- _pointArrayToPoint(array, output = []) {
1632
- for (let i = 0, len = array.length; i < len; i += 2) {
1633
- const x = array[i];
1634
- const y = array[i + 1];
1660
+ _verticesToPoints(vertices, output = []) {
1661
+ for (let i = 0, len = vertices.length; i < len; i += 2) {
1662
+ const x = vertices[i];
1663
+ const y = vertices[i + 1];
1635
1664
  output.push(new Vector2(x, y));
1636
1665
  }
1637
1666
  return output;
1638
1667
  }
1639
1668
  getSpacedPoints(count, output = []) {
1640
- const array = this.getSpacedPointArray(count);
1641
- this._pointArrayToPoint(array, output);
1669
+ const array = this.getSpacedVertices(count);
1670
+ this._verticesToPoints(array, output);
1642
1671
  return output;
1643
1672
  }
1644
1673
  getUnevenPoints(count, output = []) {
1645
- const array = this.getUnevenPointArray(count);
1646
- this._pointArrayToPoint(array, output);
1674
+ const array = this.getUnevenVertices(count);
1675
+ this._verticesToPoints(array, output);
1647
1676
  return output;
1648
1677
  }
1649
1678
  getAdaptivePoints(output = []) {
1650
- const array = this.getAdaptivePointArray();
1651
- this._pointArrayToPoint(array, output);
1679
+ const array = this.getAdaptiveVertices();
1680
+ this._verticesToPoints(array, output);
1652
1681
  return output;
1653
1682
  }
1654
1683
  getPoints(count, output = []) {
1655
1684
  let array;
1656
1685
  if (count) {
1657
- array = this.getUnevenPointArray(count);
1686
+ array = this.getUnevenVertices(count);
1658
1687
  } else {
1659
- array = this.getAdaptivePointArray();
1688
+ array = this.getAdaptiveVertices();
1660
1689
  }
1661
- this._pointArrayToPoint(array, output);
1690
+ this._verticesToPoints(array, output);
1662
1691
  return output;
1663
1692
  }
1664
1693
  getLength() {
@@ -1763,15 +1792,18 @@ class Curve {
1763
1792
  const { min, max } = this.getMinMax();
1764
1793
  return new BoundingBox(min.x, min.y, max.x - min.x, max.y - min.y);
1765
1794
  }
1795
+ getFillVertices(_options) {
1796
+ return this.getAdaptiveVertices();
1797
+ }
1766
1798
  fillTriangulate(options) {
1767
1799
  return fillTriangulate(
1768
- this.getAdaptivePointArray(),
1800
+ this.getFillVertices(options),
1769
1801
  options
1770
1802
  );
1771
1803
  }
1772
1804
  strokeTriangulate(options) {
1773
1805
  return strokeTriangulate(
1774
- this.getAdaptivePointArray(),
1806
+ this.getAdaptiveVertices(),
1775
1807
  options
1776
1808
  );
1777
1809
  }
@@ -1949,69 +1981,114 @@ class RoundCurve extends Curve {
1949
1981
  getControlPointRefs() {
1950
1982
  return [this._center];
1951
1983
  }
1952
- getAdaptivePointArray(output = []) {
1953
- const { cx, cy, rx, ry, startAngle, endAngle, clockwise } = this;
1954
- if (!(rx >= 0 && ry >= 0)) {
1955
- return output;
1956
- }
1957
- let deltaAngle = endAngle - startAngle;
1958
- if (!clockwise && deltaAngle > 0) {
1959
- deltaAngle -= 2 * Math.PI;
1960
- } else if (clockwise && deltaAngle < 0) {
1961
- deltaAngle += 2 * Math.PI;
1984
+ _getAdaptiveVerticesByArc(output = []) {
1985
+ const { cx, cy, rx, ry, dx, dy, startAngle, endAngle, clockwise: _clockwise } = this;
1986
+ const clockwise = !_clockwise;
1987
+ const x = cx;
1988
+ const y = cy;
1989
+ const start = startAngle;
1990
+ const end = endAngle;
1991
+ let dist = Math.abs(start - end);
1992
+ if (!clockwise && start > end) {
1993
+ dist = 2 * Math.PI - dist;
1994
+ } else if (clockwise && end > start) {
1995
+ dist = 2 * Math.PI - dist;
1962
1996
  }
1963
- const arcLength = Math.abs(deltaAngle);
1964
- const n = Math.max(1, Math.ceil(arcLength / (Math.PI / 16)));
1965
- for (let i = 0; i <= n; i++) {
1966
- const t = i / n;
1967
- const angle = startAngle + deltaAngle * t;
1968
- const x = cx + Math.cos(angle) * rx;
1969
- const y = cy + Math.sin(angle) * ry;
1970
- output.push(x, y);
1997
+ let steps = Math.max(6, Math.floor(6 * rx ** (1 / 3) * (dist / Math.PI)));
1998
+ steps = Math.max(steps, 3);
1999
+ let f = dist / steps;
2000
+ let t = start;
2001
+ f *= clockwise ? -1 : 1;
2002
+ for (let i = 0; i < steps + 1; i++) {
2003
+ const cs = Math.cos(t);
2004
+ const sn = Math.sin(t);
2005
+ const nx = x + dx + cs * rx;
2006
+ const ny = y + dy + sn * ry;
2007
+ output.push(nx, ny);
2008
+ t += f;
1971
2009
  }
1972
2010
  return output;
1973
2011
  }
1974
- fillTriangulate(options = {}) {
1975
- let {
1976
- vertices = [],
1977
- indices = [],
1978
- verticesStride = 2,
1979
- verticesOffset = vertices.length / verticesStride,
1980
- indicesOffset = indices.length
1981
- } = options;
1982
- const points = this.getAdaptivePointArray();
1983
- if (points.length === 0) {
1984
- return { vertices, indices };
2012
+ _getAdaptiveVerticesByCircle(output = []) {
2013
+ const { cx, cy, rx, ry, dx, dy } = this;
2014
+ if (!(rx >= 0 && ry >= 0 && dx >= 0 && dy >= 0)) {
2015
+ return output;
1985
2016
  }
1986
- let centerX = 0;
1987
- let centerY = 0;
1988
- for (let i = 0; i < points.length; i += 2) {
1989
- centerX += points[i];
1990
- centerY += points[i + 1];
2017
+ const n = Math.ceil(2.3 * Math.sqrt(rx + ry));
2018
+ const x = cx;
2019
+ const y = cy;
2020
+ const m = n * 8 + (dx ? 4 : 0) + (dy ? 4 : 0);
2021
+ if (m === 0) {
2022
+ return output;
1991
2023
  }
1992
- centerX /= points.length / 2;
1993
- centerY /= points.length / 2;
1994
- let count = verticesOffset;
1995
- vertices[count * verticesStride] = centerX;
1996
- vertices[count * verticesStride + 1] = centerY;
1997
- const centerIndex = count++;
1998
- for (let i = 0; i < points.length; i += 2) {
1999
- vertices[count * verticesStride] = points[i];
2000
- vertices[count * verticesStride + 1] = points[i + 1];
2001
- if (i > 0) {
2002
- indices[indicesOffset++] = count;
2003
- indices[indicesOffset++] = centerIndex;
2004
- indices[indicesOffset++] = count - 1;
2005
- }
2006
- count++;
2024
+ const start = output.length;
2025
+ if (n === 0) {
2026
+ output[start] = output[start + 6] = x + dx;
2027
+ output[start + 1] = output[start + 3] = y + dy;
2028
+ output[start + 2] = output[start + 4] = x - dx;
2029
+ output[start + 5] = output[start + 7] = y - dy;
2030
+ return output;
2007
2031
  }
2008
- indices[indicesOffset++] = centerIndex + 1;
2009
- indices[indicesOffset++] = centerIndex;
2010
- indices[indicesOffset++] = count - 1;
2011
- return {
2012
- vertices,
2013
- indices
2014
- };
2032
+ let j1 = start;
2033
+ let j2 = start + n * 4 + (dx ? 2 : 0) + 2;
2034
+ let j3 = j2;
2035
+ let j4 = m;
2036
+ let x0 = dx + rx;
2037
+ let y0 = dy;
2038
+ let x1 = x + x0;
2039
+ let x2 = x - x0;
2040
+ let y1 = y + y0;
2041
+ output[j1++] = x1;
2042
+ output[j1++] = y1;
2043
+ output[--j2] = y1;
2044
+ output[--j2] = x2;
2045
+ if (dy) {
2046
+ const y22 = y - y0;
2047
+ output[j3++] = x2;
2048
+ output[j3++] = y22;
2049
+ output[--j4] = y22;
2050
+ output[--j4] = x1;
2051
+ }
2052
+ for (let i = 1; i < n; i++) {
2053
+ const a = Math.PI / 2 * (i / n);
2054
+ const x02 = dx + Math.cos(a) * rx;
2055
+ const y02 = dy + Math.sin(a) * ry;
2056
+ const x12 = x + x02;
2057
+ const x22 = x - x02;
2058
+ const y12 = y + y02;
2059
+ const y22 = y - y02;
2060
+ output[j1++] = x12;
2061
+ output[j1++] = y12;
2062
+ output[--j2] = y12;
2063
+ output[--j2] = x22;
2064
+ output[j3++] = x22;
2065
+ output[j3++] = y22;
2066
+ output[--j4] = y22;
2067
+ output[--j4] = x12;
2068
+ }
2069
+ x0 = dx;
2070
+ y0 = dy + ry;
2071
+ x1 = x + x0;
2072
+ x2 = x - x0;
2073
+ y1 = y + y0;
2074
+ const y2 = y - y0;
2075
+ output[j1++] = x1;
2076
+ output[j1++] = y1;
2077
+ output[--j4] = y2;
2078
+ output[--j4] = x1;
2079
+ if (dx) {
2080
+ output[j1++] = x2;
2081
+ output[j1++] = y1;
2082
+ output[--j4] = y2;
2083
+ output[--j4] = x2;
2084
+ }
2085
+ return output;
2086
+ }
2087
+ getAdaptiveVertices(output = []) {
2088
+ if (this.startAngle === 0 && this.endAngle === Math.PI * 2) {
2089
+ return this._getAdaptiveVerticesByCircle(output);
2090
+ }
2091
+ return this._getAdaptiveVerticesByArc(output);
2015
2092
  }
2016
2093
  getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
2017
2094
  const { cx, cy, rx, ry, rotate } = this;
@@ -2208,7 +2285,7 @@ class ArcCurve extends RoundCurve {
2208
2285
  );
2209
2286
  return this;
2210
2287
  }
2211
- getAdaptivePointArray(output = []) {
2288
+ getAdaptiveVertices(output = []) {
2212
2289
  const { cx, cy, rx, startAngle, endAngle, clockwise } = this;
2213
2290
  let dist = Math.abs(startAngle - endAngle);
2214
2291
  if (!clockwise && startAngle > endAngle) {
@@ -2233,6 +2310,96 @@ class ArcCurve extends RoundCurve {
2233
2310
  }
2234
2311
  }
2235
2312
 
2313
+ class LineCurve extends Curve {
2314
+ constructor(p1 = new Vector2(), p2 = new Vector2()) {
2315
+ super();
2316
+ this.p1 = p1;
2317
+ this.p2 = p2;
2318
+ }
2319
+ static from(p1x, p1y, p2x, p2y) {
2320
+ return new LineCurve(
2321
+ new Vector2(p1x, p1y),
2322
+ new Vector2(p2x, p2y)
2323
+ );
2324
+ }
2325
+ getPoint(t, output = new Vector2()) {
2326
+ if (t === 1) {
2327
+ output.copy(this.p2);
2328
+ } else {
2329
+ output.copy(this.p2).sub(this.p1).scale(t).add(this.p1);
2330
+ }
2331
+ return output;
2332
+ }
2333
+ getPointAt(u, output = new Vector2()) {
2334
+ return this.getPoint(u, output);
2335
+ }
2336
+ getTangent(_t, output = new Vector2()) {
2337
+ return output.subVectors(this.p2, this.p1).normalize();
2338
+ }
2339
+ getTangentAt(u, output = new Vector2()) {
2340
+ return this.getTangent(u, output);
2341
+ }
2342
+ getControlPointRefs() {
2343
+ return [this.p1, this.p2];
2344
+ }
2345
+ getAdaptiveVertices(output = []) {
2346
+ output.push(
2347
+ this.p1.x,
2348
+ this.p1.y,
2349
+ this.p2.x,
2350
+ this.p2.y
2351
+ );
2352
+ return output;
2353
+ }
2354
+ getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
2355
+ const { p1, p2 } = this;
2356
+ min.x = Math.min(min.x, p1.x, p2.x);
2357
+ min.y = Math.min(min.y, p1.y, p2.y);
2358
+ max.x = Math.max(max.x, p1.x, p2.x);
2359
+ max.y = Math.max(max.y, p1.y, p2.y);
2360
+ return { min: min.finite(), max: max.finite() };
2361
+ }
2362
+ toCommands() {
2363
+ const { p1, p2 } = this;
2364
+ return [
2365
+ { type: "M", x: p1.x, y: p1.y },
2366
+ { type: "L", x: p2.x, y: p2.y }
2367
+ ];
2368
+ }
2369
+ getFillVertices(options = {}) {
2370
+ const minX = Math.min(this.p1.x, this.p2.x);
2371
+ const maxX = Math.max(this.p1.x, this.p2.x);
2372
+ const minY = Math.min(this.p1.y, this.p2.y);
2373
+ const maxY = Math.max(this.p1.y, this.p2.y);
2374
+ const x = minX;
2375
+ const y = minY;
2376
+ const width = maxX - minX || options.style?.strokeWidth || 0;
2377
+ const height = maxY - minY || options.style?.strokeWidth || 0;
2378
+ return [
2379
+ x,
2380
+ y,
2381
+ x + width,
2382
+ y,
2383
+ x + width,
2384
+ y + height,
2385
+ x,
2386
+ y + height
2387
+ ];
2388
+ }
2389
+ drawTo(ctx) {
2390
+ const { p1, p2 } = this;
2391
+ ctx.lineTo(p1.x, p1.y);
2392
+ ctx.lineTo(p2.x, p2.y);
2393
+ return this;
2394
+ }
2395
+ copy(source) {
2396
+ super.copy(source);
2397
+ this.p1.copy(source.p1);
2398
+ this.p2.copy(source.p2);
2399
+ return this;
2400
+ }
2401
+ }
2402
+
2236
2403
  class CompositeCurve extends Curve {
2237
2404
  constructor(curves = []) {
2238
2405
  super();
@@ -2287,10 +2454,10 @@ class CompositeCurve extends Curve {
2287
2454
  }
2288
2455
  return output;
2289
2456
  }
2290
- getSpacedPointArray(count = 5, output = []) {
2457
+ getSpacedVertices(count = 5, output = []) {
2291
2458
  let offset;
2292
2459
  this.curves.forEach((curve) => {
2293
- curve.getSpacedPointArray(count, output);
2460
+ curve.getSpacedVertices(count, output);
2294
2461
  if (offset) {
2295
2462
  this._removeNextPointIfEqualPrevPoint(output, offset);
2296
2463
  }
@@ -2298,10 +2465,10 @@ class CompositeCurve extends Curve {
2298
2465
  });
2299
2466
  return output;
2300
2467
  }
2301
- getAdaptivePointArray(output = []) {
2468
+ getAdaptiveVertices(output = []) {
2302
2469
  let offset;
2303
2470
  this.curves.forEach((curve) => {
2304
- curve.getAdaptivePointArray(output);
2471
+ curve.getAdaptiveVertices(output);
2305
2472
  if (offset) {
2306
2473
  this._removeNextPointIfEqualPrevPoint(output, offset);
2307
2474
  }
@@ -2316,11 +2483,26 @@ class CompositeCurve extends Curve {
2316
2483
  return super.strokeTriangulate(options);
2317
2484
  }
2318
2485
  }
2319
- fillTriangulate(options) {
2486
+ getFillVertices(options) {
2320
2487
  if (this.curves.length === 1) {
2321
- return this.curves[0].fillTriangulate(options);
2488
+ return this.curves[0].getFillVertices(options);
2322
2489
  } else {
2323
- return super.fillTriangulate(options);
2490
+ const output = [];
2491
+ let offset;
2492
+ this.curves.forEach((curve) => {
2493
+ let arr;
2494
+ if (curve instanceof LineCurve) {
2495
+ arr = curve.getAdaptiveVertices();
2496
+ } else {
2497
+ arr = curve.getFillVertices(options);
2498
+ }
2499
+ output.push(...arr);
2500
+ if (offset) {
2501
+ this._removeNextPointIfEqualPrevPoint(output, offset);
2502
+ }
2503
+ offset = output.length - 1;
2504
+ });
2505
+ return output;
2324
2506
  }
2325
2507
  }
2326
2508
  applyTransform(transform) {
@@ -2376,7 +2558,7 @@ class CubicBezierCurve extends Curve {
2376
2558
  cubicBezier(t, p1.y, cp1.y, cp2.y, p2.y)
2377
2559
  );
2378
2560
  }
2379
- getAdaptivePointArray(output = []) {
2561
+ getAdaptiveVertices(output = []) {
2380
2562
  return getAdaptiveCubicBezierCurvePoints(
2381
2563
  this.p1.x,
2382
2564
  this.p1.y,
@@ -2481,125 +2663,6 @@ class EllipseCurve extends RoundCurve {
2481
2663
  }
2482
2664
  }
2483
2665
 
2484
- class LineCurve extends Curve {
2485
- constructor(p1 = new Vector2(), p2 = new Vector2()) {
2486
- super();
2487
- this.p1 = p1;
2488
- this.p2 = p2;
2489
- }
2490
- static from(p1x, p1y, p2x, p2y) {
2491
- return new LineCurve(
2492
- new Vector2(p1x, p1y),
2493
- new Vector2(p2x, p2y)
2494
- );
2495
- }
2496
- getPoint(t, output = new Vector2()) {
2497
- if (t === 1) {
2498
- output.copy(this.p2);
2499
- } else {
2500
- output.copy(this.p2).sub(this.p1).scale(t).add(this.p1);
2501
- }
2502
- return output;
2503
- }
2504
- getPointAt(u, output = new Vector2()) {
2505
- return this.getPoint(u, output);
2506
- }
2507
- getTangent(_t, output = new Vector2()) {
2508
- return output.subVectors(this.p2, this.p1).normalize();
2509
- }
2510
- getTangentAt(u, output = new Vector2()) {
2511
- return this.getTangent(u, output);
2512
- }
2513
- getControlPointRefs() {
2514
- return [this.p1, this.p2];
2515
- }
2516
- getAdaptivePointArray(output = []) {
2517
- output.push(
2518
- this.p1.x,
2519
- this.p1.y,
2520
- this.p2.x,
2521
- this.p2.y
2522
- );
2523
- return output;
2524
- }
2525
- getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
2526
- const { p1, p2 } = this;
2527
- min.x = Math.min(min.x, p1.x, p2.x);
2528
- min.y = Math.min(min.y, p1.y, p2.y);
2529
- max.x = Math.max(max.x, p1.x, p2.x);
2530
- max.y = Math.max(max.y, p1.y, p2.y);
2531
- return { min: min.finite(), max: max.finite() };
2532
- }
2533
- toCommands() {
2534
- const { p1, p2 } = this;
2535
- return [
2536
- { type: "M", x: p1.x, y: p1.y },
2537
- { type: "L", x: p2.x, y: p2.y }
2538
- ];
2539
- }
2540
- fillTriangulate(options = {}) {
2541
- let {
2542
- vertices = [],
2543
- indices = [],
2544
- verticesStride = 2,
2545
- verticesOffset = vertices.length / verticesStride,
2546
- indicesOffset = indices.length
2547
- } = options;
2548
- const minX = Math.min(this.p1.x, this.p2.x);
2549
- const maxX = Math.max(this.p1.x, this.p2.x);
2550
- const minY = Math.min(this.p1.y, this.p2.y);
2551
- const maxY = Math.max(this.p1.y, this.p2.y);
2552
- const x = minX;
2553
- const y = minY;
2554
- const width = maxX - minX || options.style?.strokeWidth || 1;
2555
- const height = maxY - minY || options.style?.strokeWidth || 1;
2556
- const points = [
2557
- x,
2558
- y,
2559
- x + width,
2560
- y,
2561
- x + width,
2562
- y + height,
2563
- x,
2564
- y + height
2565
- ];
2566
- let count = 0;
2567
- verticesOffset *= verticesStride;
2568
- vertices[verticesOffset + count] = points[0];
2569
- vertices[verticesOffset + count + 1] = points[1];
2570
- count += verticesStride;
2571
- vertices[verticesOffset + count] = points[2];
2572
- vertices[verticesOffset + count + 1] = points[3];
2573
- count += verticesStride;
2574
- vertices[verticesOffset + count] = points[6];
2575
- vertices[verticesOffset + count + 1] = points[7];
2576
- count += verticesStride;
2577
- vertices[verticesOffset + count] = points[4];
2578
- vertices[verticesOffset + count + 1] = points[5];
2579
- count += verticesStride;
2580
- const verticesIndex = verticesOffset / verticesStride;
2581
- indices[indicesOffset++] = verticesIndex;
2582
- indices[indicesOffset++] = verticesIndex + 1;
2583
- indices[indicesOffset++] = verticesIndex + 2;
2584
- indices[indicesOffset++] = verticesIndex + 1;
2585
- indices[indicesOffset++] = verticesIndex + 3;
2586
- indices[indicesOffset++] = verticesIndex + 2;
2587
- return { vertices, indices };
2588
- }
2589
- drawTo(ctx) {
2590
- const { p1, p2 } = this;
2591
- ctx.lineTo(p1.x, p1.y);
2592
- ctx.lineTo(p2.x, p2.y);
2593
- return this;
2594
- }
2595
- copy(source) {
2596
- super.copy(source);
2597
- this.p1.copy(source.p1);
2598
- this.p2.copy(source.p2);
2599
- return this;
2600
- }
2601
- }
2602
-
2603
2666
  class PloygonCurve extends CompositeCurve {
2604
2667
  //
2605
2668
  }
@@ -2673,7 +2736,7 @@ class QuadraticBezierCurve extends Curve {
2673
2736
  getControlPointRefs() {
2674
2737
  return [this.p1, this.cp, this.p2];
2675
2738
  }
2676
- getAdaptivePointArray(output = []) {
2739
+ getAdaptiveVertices(output = []) {
2677
2740
  return getAdaptiveQuadraticBezierCurvePoints(
2678
2741
  this.p1.x,
2679
2742
  this.p1.y,
@@ -2748,16 +2811,9 @@ class RectangleCurve extends PloygonCurve {
2748
2811
  ctx.rect(this.x, this.y, this.width, this.height);
2749
2812
  return this;
2750
2813
  }
2751
- fillTriangulate(options = {}) {
2752
- let {
2753
- vertices = [],
2754
- indices = [],
2755
- verticesStride = 2,
2756
- verticesOffset = vertices.length / verticesStride,
2757
- indicesOffset = indices.length
2758
- } = options;
2814
+ getFillVertices(_options = {}) {
2759
2815
  const { x, y, width, height } = this;
2760
- const points = [
2816
+ return [
2761
2817
  x,
2762
2818
  y,
2763
2819
  x + width,
@@ -2767,28 +2823,6 @@ class RectangleCurve extends PloygonCurve {
2767
2823
  x,
2768
2824
  y + height
2769
2825
  ];
2770
- let count = 0;
2771
- verticesOffset *= verticesStride;
2772
- vertices[verticesOffset + count] = points[0];
2773
- vertices[verticesOffset + count + 1] = points[1];
2774
- count += verticesStride;
2775
- vertices[verticesOffset + count] = points[2];
2776
- vertices[verticesOffset + count + 1] = points[3];
2777
- count += verticesStride;
2778
- vertices[verticesOffset + count] = points[6];
2779
- vertices[verticesOffset + count + 1] = points[7];
2780
- count += verticesStride;
2781
- vertices[verticesOffset + count] = points[4];
2782
- vertices[verticesOffset + count + 1] = points[5];
2783
- count += verticesStride;
2784
- const verticesIndex = verticesOffset / verticesStride;
2785
- indices[indicesOffset++] = verticesIndex;
2786
- indices[indicesOffset++] = verticesIndex + 1;
2787
- indices[indicesOffset++] = verticesIndex + 2;
2788
- indices[indicesOffset++] = verticesIndex + 1;
2789
- indices[indicesOffset++] = verticesIndex + 3;
2790
- indices[indicesOffset++] = verticesIndex + 2;
2791
- return { vertices, indices };
2792
2826
  }
2793
2827
  copy(source) {
2794
2828
  super.copy(source);
@@ -2900,25 +2934,30 @@ class CurvePath extends CompositeCurve {
2900
2934
  this.addCommands(svgPathDataToCommands(data));
2901
2935
  return this;
2902
2936
  }
2903
- _closePointArray(output) {
2937
+ _closeVertices(output) {
2904
2938
  if (this.autoClose && output.length >= 4 && (output[0] !== output[output.length - 2] && output[1] !== output[output.length - 1])) {
2905
2939
  output.push(output[0], output[1]);
2906
2940
  }
2907
2941
  return output;
2908
2942
  }
2909
- getUnevenPointArray(count = 40, output = []) {
2910
- return this._closePointArray(
2911
- super.getUnevenPointArray(count, output)
2943
+ getUnevenVertices(count = 40, output = []) {
2944
+ return this._closeVertices(
2945
+ super.getUnevenVertices(count, output)
2946
+ );
2947
+ }
2948
+ getSpacedVertices(count = 40, output = []) {
2949
+ return this._closeVertices(
2950
+ super.getSpacedVertices(count, output)
2912
2951
  );
2913
2952
  }
2914
- getSpacedPointArray(count = 40, output = []) {
2915
- return this._closePointArray(
2916
- super.getSpacedPointArray(count, output)
2953
+ getAdaptiveVertices(output = []) {
2954
+ return this._closeVertices(
2955
+ super.getAdaptiveVertices(output)
2917
2956
  );
2918
2957
  }
2919
- getAdaptivePointArray(output = []) {
2920
- return this._closePointArray(
2921
- super.getAdaptivePointArray(output)
2958
+ getFillVertices(options) {
2959
+ return this._closeVertices(
2960
+ super.getFillVertices(options)
2922
2961
  );
2923
2962
  }
2924
2963
  _setCurrentPoint(point) {
@@ -3353,16 +3392,69 @@ class Path2D extends CompositeCurve {
3353
3392
  return { indices, vertices };
3354
3393
  }
3355
3394
  fillTriangulate(options) {
3356
- const indices = options?.indices ?? [];
3357
- const vertices = options?.vertices ?? [];
3358
- this.curves.forEach((curve) => {
3359
- curve.fillTriangulate({
3360
- ...options,
3361
- indices,
3362
- vertices,
3363
- style: { ...this.style }
3395
+ const _options = {
3396
+ ...options,
3397
+ style: {
3398
+ ...this.style,
3399
+ ...options?.style
3400
+ }
3401
+ };
3402
+ const indices = _options.indices ?? [];
3403
+ const vertices = _options.vertices ?? [];
3404
+ const fillRule = _options.style.fillRule ?? "nonzero";
3405
+ if (fillRule === "nonzero") {
3406
+ const pointArrays = this.curves.map((curve) => curve.getFillVertices(_options));
3407
+ const parentMap = /* @__PURE__ */ new Map();
3408
+ const parentd = /* @__PURE__ */ new Set();
3409
+ for (let i = 0; i < pointArrays.length; i++) {
3410
+ const parents = [];
3411
+ for (let j = 0; j < pointArrays.length; j++) {
3412
+ if (i === j)
3413
+ continue;
3414
+ if (pointInPolygon([pointArrays[i][0], pointArrays[i][1]], pointArrays[j])) {
3415
+ parents.push(j);
3416
+ }
3417
+ }
3418
+ if (parents.length) {
3419
+ parents.forEach((pi) => {
3420
+ let set = parentMap.get(pi);
3421
+ if (!set) {
3422
+ set = /* @__PURE__ */ new Set();
3423
+ parentMap.set(pi, set);
3424
+ }
3425
+ set.add(i);
3426
+ });
3427
+ parentd.add(i);
3428
+ }
3429
+ }
3430
+ pointArrays.forEach((pointArray, i) => {
3431
+ if (parentd.has(i) || !pointArray.length) {
3432
+ return;
3433
+ }
3434
+ const _pointArray = pointArray.slice();
3435
+ const holes = [];
3436
+ parentMap.get(i)?.forEach((ci) => {
3437
+ holes.push(_pointArray.length / 2);
3438
+ _pointArray.push(...pointArrays[ci]);
3439
+ });
3440
+ fillTriangulate(_pointArray, {
3441
+ ...options,
3442
+ indices,
3443
+ vertices,
3444
+ holes,
3445
+ style: { ...this.style }
3446
+ });
3364
3447
  });
3365
- });
3448
+ } else {
3449
+ this.curves.forEach((curve) => {
3450
+ curve.fillTriangulate({
3451
+ ...options,
3452
+ indices,
3453
+ vertices,
3454
+ style: { ...this.style }
3455
+ });
3456
+ });
3457
+ }
3366
3458
  return { indices, vertices };
3367
3459
  }
3368
3460
  getBoundingBox(withStyle = true) {
@@ -3475,7 +3567,7 @@ class Path2DSet {
3475
3567
  const p1 = getPoint(indices[i]);
3476
3568
  const p2 = getPoint(indices[i + 1]);
3477
3569
  const p3 = getPoint(indices[i + 2]);
3478
- polygonStr += `<polygon points="${p1.join(",")} ${p2.join(",")} ${p3.join(",")}" fill="none" stroke="black" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" />`;
3570
+ polygonStr += `<polygon points="${p1.join(",")} ${p2.join(",")} ${p3.join(",")}" fill="black" />`;
3479
3571
  }
3480
3572
  });
3481
3573
  const viewBox = [min.x, min.y, max.x - min.x, max.y - min.y];
@@ -4125,8 +4217,10 @@ exports.drawPoint = drawPoint;
4125
4217
  exports.fillTriangulate = fillTriangulate;
4126
4218
  exports.getAdaptiveCubicBezierCurvePoints = getAdaptiveCubicBezierCurvePoints;
4127
4219
  exports.getAdaptiveQuadraticBezierCurvePoints = getAdaptiveQuadraticBezierCurvePoints;
4220
+ exports.getDirectedArea = getDirectedArea;
4128
4221
  exports.parseArcCommand = parseArcCommand;
4129
4222
  exports.parsePathDataArgs = parsePathDataArgs;
4223
+ exports.pointInPolygon = pointInPolygon;
4130
4224
  exports.quadraticBezier = quadraticBezier;
4131
4225
  exports.setCanvasContext = setCanvasContext;
4132
4226
  exports.strokeTriangulate = strokeTriangulate;