@mce/bigesj 0.18.3 → 0.18.5
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.js
CHANGED
|
@@ -1626,7 +1626,7 @@ function signedArea(data, start, end, dim) {
|
|
|
1626
1626
|
return sum;
|
|
1627
1627
|
}
|
|
1628
1628
|
//#endregion
|
|
1629
|
-
//#region ../../node_modules/.pnpm/modern-path2d@1.
|
|
1629
|
+
//#region ../../node_modules/.pnpm/modern-path2d@1.7.0/node_modules/modern-path2d/dist/index.mjs
|
|
1630
1630
|
function drawPoint(ctx, x, y, options = {}) {
|
|
1631
1631
|
const { radius = 1 } = options;
|
|
1632
1632
|
ctx.moveTo(x, y);
|
|
@@ -1732,7 +1732,7 @@ var Vector2 = class Vector2 {
|
|
|
1732
1732
|
return this.set(this._x * x, this._y * y);
|
|
1733
1733
|
}
|
|
1734
1734
|
divide(x = 0, y = x) {
|
|
1735
|
-
return this.set(this._x / x, this._y / y);
|
|
1735
|
+
return this.set(x === 0 ? this._x : this._x / x, y === 0 ? this._y : this._y / y);
|
|
1736
1736
|
}
|
|
1737
1737
|
cross(p) {
|
|
1738
1738
|
return this._x * p.y - this._y * p.x;
|
|
@@ -1910,9 +1910,9 @@ function getIntersectionPoint(p1, p2, q1, q2) {
|
|
|
1910
1910
|
const s = q2.clone().sub(q1);
|
|
1911
1911
|
const q1p1 = q1.clone().sub(p1);
|
|
1912
1912
|
const crossRS = r.cross(s);
|
|
1913
|
-
if (crossRS === 0) return
|
|
1913
|
+
if (crossRS === 0) return null;
|
|
1914
1914
|
const t = q1p1.cross(s) / crossRS;
|
|
1915
|
-
if (Math.abs(t) > 1) return
|
|
1915
|
+
if (Math.abs(t) > 1) return null;
|
|
1916
1916
|
return new Vector2(p1.x + t * r.x, p1.y + t * r.y);
|
|
1917
1917
|
}
|
|
1918
1918
|
var FUNCTIONS_RE = /([\w-]+)\((.+?)\)/g;
|
|
@@ -2118,7 +2118,7 @@ function recursive(points, x1, y1, x2, y2, x3, y3, distanceTolerance, level) {
|
|
|
2118
2118
|
function cross(ax, ay, bx, by, cx, cy) {
|
|
2119
2119
|
return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax);
|
|
2120
2120
|
}
|
|
2121
|
-
function windingNumber(px, py, polygon) {
|
|
2121
|
+
function windingNumber$1(px, py, polygon) {
|
|
2122
2122
|
const polygonLen = polygon.length;
|
|
2123
2123
|
let wn = 0;
|
|
2124
2124
|
for (let i = 0, j = polygonLen - 2; i < polygonLen; j = i, i += 2) {
|
|
@@ -2137,11 +2137,18 @@ function distance(p1, p2) {
|
|
|
2137
2137
|
const dy = p2[1] - p1[1];
|
|
2138
2138
|
return Math.sqrt(dx * dx + dy * dy);
|
|
2139
2139
|
}
|
|
2140
|
+
function aabbIntersects(a, b) {
|
|
2141
|
+
return a.minX <= b.maxX && a.maxX >= b.minX && a.minY <= b.maxY && a.maxY >= b.minY;
|
|
2142
|
+
}
|
|
2140
2143
|
function nonzeroFillRule(paths) {
|
|
2141
2144
|
const results = paths.map((_, i) => ({ index: i }));
|
|
2142
|
-
const
|
|
2145
|
+
const bboxes = [];
|
|
2146
|
+
const testPointsGroups = paths.map((path, pathIndex) => {
|
|
2143
2147
|
const len = path.length;
|
|
2144
|
-
if (!len)
|
|
2148
|
+
if (!len) {
|
|
2149
|
+
bboxes[pathIndex] = null;
|
|
2150
|
+
return [];
|
|
2151
|
+
}
|
|
2145
2152
|
let xMinYAuto = [Number.MAX_SAFE_INTEGER, 0];
|
|
2146
2153
|
let xAutoYMin = [0, Number.MAX_SAFE_INTEGER];
|
|
2147
2154
|
let xMaxYAuto = [Number.MIN_SAFE_INTEGER, 0];
|
|
@@ -2154,6 +2161,12 @@ function nonzeroFillRule(paths) {
|
|
|
2154
2161
|
if (xMaxYAuto[0] < x) xMaxYAuto = [x, y];
|
|
2155
2162
|
if (xAutoYMax[1] < y) xAutoYMax = [x, y];
|
|
2156
2163
|
}
|
|
2164
|
+
bboxes[pathIndex] = {
|
|
2165
|
+
minX: xMinYAuto[0],
|
|
2166
|
+
minY: xAutoYMin[1],
|
|
2167
|
+
maxX: xMaxYAuto[0],
|
|
2168
|
+
maxY: xAutoYMax[1]
|
|
2169
|
+
};
|
|
2157
2170
|
const mid = [(xMinYAuto[0] + xMaxYAuto[0]) / 2, (xAutoYMin[1] + xAutoYMax[1]) / 2];
|
|
2158
2171
|
let xMidYMinDx;
|
|
2159
2172
|
let xMidYMaxDx;
|
|
@@ -2199,13 +2212,16 @@ function nonzeroFillRule(paths) {
|
|
|
2199
2212
|
for (let i = 0, len = paths.length; i < len; i++) {
|
|
2200
2213
|
const _results = [];
|
|
2201
2214
|
const testPoints = testPointsGroups[i];
|
|
2215
|
+
const boxI = bboxes[i];
|
|
2202
2216
|
for (let j = 0; j < len; j++) {
|
|
2203
2217
|
if (i === j) continue;
|
|
2218
|
+
const boxJ = bboxes[j];
|
|
2219
|
+
if (!boxI || !boxJ || !aabbIntersects(boxI, boxJ)) continue;
|
|
2204
2220
|
const wnMap = {};
|
|
2205
2221
|
const wnList = [];
|
|
2206
2222
|
for (let p = 0, pLen = testPoints.length; p < pLen; p++) {
|
|
2207
2223
|
const [x, y] = testPoints[p];
|
|
2208
|
-
const winding = windingNumber(x, y, paths[j]);
|
|
2224
|
+
const winding = windingNumber$1(x, y, paths[j]);
|
|
2209
2225
|
wnMap[winding] = (wnMap[winding] ?? 0) + 1;
|
|
2210
2226
|
wnList.push(winding);
|
|
2211
2227
|
}
|
|
@@ -2223,6 +2239,88 @@ function nonzeroFillRule(paths) {
|
|
|
2223
2239
|
}
|
|
2224
2240
|
return results;
|
|
2225
2241
|
}
|
|
2242
|
+
function isLeft(ax, ay, bx, by, px, py) {
|
|
2243
|
+
return (bx - ax) * (py - ay) - (px - ax) * (by - ay);
|
|
2244
|
+
}
|
|
2245
|
+
function windingNumber(px, py, vertices) {
|
|
2246
|
+
const len = vertices.length;
|
|
2247
|
+
let wn = 0;
|
|
2248
|
+
for (let i = 0; i < len; i += 2) {
|
|
2249
|
+
const ax = vertices[i];
|
|
2250
|
+
const ay = vertices[i + 1];
|
|
2251
|
+
const k = (i + 2) % len;
|
|
2252
|
+
const bx = vertices[k];
|
|
2253
|
+
const by = vertices[k + 1];
|
|
2254
|
+
if (ay <= py) {
|
|
2255
|
+
if (by > py && isLeft(ax, ay, bx, by, px, py) > 0) wn++;
|
|
2256
|
+
} else if (by <= py && isLeft(ax, ay, bx, by, px, py) < 0) wn--;
|
|
2257
|
+
}
|
|
2258
|
+
return wn;
|
|
2259
|
+
}
|
|
2260
|
+
function crossingNumber(px, py, vertices) {
|
|
2261
|
+
const len = vertices.length;
|
|
2262
|
+
let cn = 0;
|
|
2263
|
+
for (let i = 0; i < len; i += 2) {
|
|
2264
|
+
const ax = vertices[i];
|
|
2265
|
+
const ay = vertices[i + 1];
|
|
2266
|
+
const k = (i + 2) % len;
|
|
2267
|
+
const bx = vertices[k];
|
|
2268
|
+
const by = vertices[k + 1];
|
|
2269
|
+
if (ay <= py && by > py || ay > py && by <= py) {
|
|
2270
|
+
if (px < ax + (py - ay) / (by - ay) * (bx - ax)) cn++;
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
return cn;
|
|
2274
|
+
}
|
|
2275
|
+
function segmentDistance(px, py, ax, ay, bx, by) {
|
|
2276
|
+
const dx = bx - ax;
|
|
2277
|
+
const dy = by - ay;
|
|
2278
|
+
const lenSq = dx * dx + dy * dy;
|
|
2279
|
+
let t = lenSq === 0 ? 0 : ((px - ax) * dx + (py - ay) * dy) / lenSq;
|
|
2280
|
+
if (t < 0) t = 0;
|
|
2281
|
+
else if (t > 1) t = 1;
|
|
2282
|
+
const cx = ax + t * dx;
|
|
2283
|
+
const cy = ay + t * dy;
|
|
2284
|
+
return Math.hypot(px - cx, py - cy);
|
|
2285
|
+
}
|
|
2286
|
+
function pointInPolygon(point, vertices, fillRule = "nonzero") {
|
|
2287
|
+
if (vertices.length < 6) return false;
|
|
2288
|
+
if (fillRule === "evenodd") return (crossingNumber(point.x, point.y, vertices) & 1) === 1;
|
|
2289
|
+
return windingNumber(point.x, point.y, vertices) !== 0;
|
|
2290
|
+
}
|
|
2291
|
+
function pointInPolygons(point, polygons, fillRule = "nonzero") {
|
|
2292
|
+
const { x, y } = point;
|
|
2293
|
+
if (fillRule === "evenodd") {
|
|
2294
|
+
let cn = 0;
|
|
2295
|
+
for (let i = 0, len = polygons.length; i < len; i++) {
|
|
2296
|
+
const ring = polygons[i];
|
|
2297
|
+
if (ring.length >= 6) cn += crossingNumber(x, y, ring);
|
|
2298
|
+
}
|
|
2299
|
+
return (cn & 1) === 1;
|
|
2300
|
+
}
|
|
2301
|
+
let wn = 0;
|
|
2302
|
+
for (let i = 0, len = polygons.length; i < len; i++) {
|
|
2303
|
+
const ring = polygons[i];
|
|
2304
|
+
if (ring.length >= 6) wn += windingNumber(x, y, ring);
|
|
2305
|
+
}
|
|
2306
|
+
return wn !== 0;
|
|
2307
|
+
}
|
|
2308
|
+
function pointToPolylineDistance(point, vertices, closed = false) {
|
|
2309
|
+
const len = vertices.length;
|
|
2310
|
+
if (len < 2) return Infinity;
|
|
2311
|
+
const { x: px, y: py } = point;
|
|
2312
|
+
if (len === 2) return Math.hypot(px - vertices[0], py - vertices[1]);
|
|
2313
|
+
let min = Infinity;
|
|
2314
|
+
for (let i = 0; i < len - 2; i += 2) {
|
|
2315
|
+
const d = segmentDistance(px, py, vertices[i], vertices[i + 1], vertices[i + 2], vertices[i + 3]);
|
|
2316
|
+
if (d < min) min = d;
|
|
2317
|
+
}
|
|
2318
|
+
if (closed && len >= 6) {
|
|
2319
|
+
const d = segmentDistance(px, py, vertices[len - 2], vertices[len - 1], vertices[0], vertices[1]);
|
|
2320
|
+
if (d < min) min = d;
|
|
2321
|
+
}
|
|
2322
|
+
return min;
|
|
2323
|
+
}
|
|
2226
2324
|
function quadraticBezierP0(t, p) {
|
|
2227
2325
|
const k = 1 - t;
|
|
2228
2326
|
return k * k * p;
|
|
@@ -3728,6 +3826,39 @@ function svgToPath2DSet(svg) {
|
|
|
3728
3826
|
var Curve = class {
|
|
3729
3827
|
arcLengthDivision = 200;
|
|
3730
3828
|
_lengths = [];
|
|
3829
|
+
_adaptiveCache;
|
|
3830
|
+
/**
|
|
3831
|
+
* Parent composite, set lazily when a composite caches its children. Lets
|
|
3832
|
+
* {@link invalidate} propagate up so an ancestor's caches refresh too.
|
|
3833
|
+
*/
|
|
3834
|
+
_owner;
|
|
3835
|
+
_invalidating = false;
|
|
3836
|
+
/**
|
|
3837
|
+
* Drop cached arc lengths and the cached sampled outline used by hit testing, then
|
|
3838
|
+
* bubble up to {@link _owner}. Called automatically by {@link applyTransform} and the
|
|
3839
|
+
* `Path2D` mutators; call it manually after mutating control-point coordinates in place —
|
|
3840
|
+
* the caches cannot observe such mutations.
|
|
3841
|
+
*/
|
|
3842
|
+
invalidate() {
|
|
3843
|
+
if (this._invalidating) return this;
|
|
3844
|
+
this._invalidating = true;
|
|
3845
|
+
this._invalidateSelf();
|
|
3846
|
+
this._owner?.invalidate();
|
|
3847
|
+
this._invalidating = false;
|
|
3848
|
+
return this;
|
|
3849
|
+
}
|
|
3850
|
+
/** Clears this curve's own caches. Composites also clear their children (see override). */
|
|
3851
|
+
_invalidateSelf() {
|
|
3852
|
+
this._lengths.length = 0;
|
|
3853
|
+
this._adaptiveCache = void 0;
|
|
3854
|
+
}
|
|
3855
|
+
/**
|
|
3856
|
+
* Sampled outline cached for repeated hit tests (read-only — do not mutate the result).
|
|
3857
|
+
* Invalidated by {@link invalidate}.
|
|
3858
|
+
*/
|
|
3859
|
+
_getCachedAdaptiveVertices() {
|
|
3860
|
+
return this._adaptiveCache ??= this.getAdaptiveVertices();
|
|
3861
|
+
}
|
|
3731
3862
|
getPointAt(u, output = new Vector2()) {
|
|
3732
3863
|
return this.getPoint(this.getUToTMapping(u), output);
|
|
3733
3864
|
}
|
|
@@ -3743,6 +3874,7 @@ var Curve = class {
|
|
|
3743
3874
|
if (isFunction) transform(p);
|
|
3744
3875
|
else transform.apply(p, p);
|
|
3745
3876
|
});
|
|
3877
|
+
this.invalidate();
|
|
3746
3878
|
return this;
|
|
3747
3879
|
}
|
|
3748
3880
|
getUnevenVertices(count = 5, output = []) {
|
|
@@ -3869,12 +4001,21 @@ var Curve = class {
|
|
|
3869
4001
|
return mid;
|
|
3870
4002
|
}
|
|
3871
4003
|
getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
|
|
3872
|
-
const
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
4004
|
+
const vertices = this.getAdaptiveVertices();
|
|
4005
|
+
let minX = min.x;
|
|
4006
|
+
let minY = min.y;
|
|
4007
|
+
let maxX = max.x;
|
|
4008
|
+
let maxY = max.y;
|
|
4009
|
+
for (let i = 0, len = vertices.length; i < len; i += 2) {
|
|
4010
|
+
const x = vertices[i];
|
|
4011
|
+
const y = vertices[i + 1];
|
|
4012
|
+
if (x < minX) minX = x;
|
|
4013
|
+
if (y < minY) minY = y;
|
|
4014
|
+
if (x > maxX) maxX = x;
|
|
4015
|
+
if (y > maxY) maxY = y;
|
|
3877
4016
|
}
|
|
4017
|
+
min.set(minX, minY);
|
|
4018
|
+
max.set(maxX, maxY);
|
|
3878
4019
|
return {
|
|
3879
4020
|
min: min.finite(),
|
|
3880
4021
|
max: max.finite()
|
|
@@ -3884,6 +4025,42 @@ var Curve = class {
|
|
|
3884
4025
|
const { min, max } = this.getMinMax();
|
|
3885
4026
|
return new BoundingBox(min.x, min.y, max.x - min.x, max.y - min.y);
|
|
3886
4027
|
}
|
|
4028
|
+
/**
|
|
4029
|
+
* Test whether a point lies inside the area enclosed by this curve.
|
|
4030
|
+
*
|
|
4031
|
+
* The curve is sampled via {@link getAdaptiveVertices} into a single implicitly closed
|
|
4032
|
+
* ring. This is purely geometric (it ignores any `fill`/`stroke` style), mirroring
|
|
4033
|
+
* `CanvasRenderingContext2D.isPointInPath`.
|
|
4034
|
+
*
|
|
4035
|
+
* Composites that hold multiple sub-paths (e.g. {@link Path2D}) override this so holes
|
|
4036
|
+
* are honored — a single `Curve` is always one ring.
|
|
4037
|
+
*/
|
|
4038
|
+
isPointInFill(point, options = {}) {
|
|
4039
|
+
return pointInPolygon(point, this._getCachedAdaptiveVertices(), options.fillRule);
|
|
4040
|
+
}
|
|
4041
|
+
/**
|
|
4042
|
+
* Test whether a point lies on this curve's stroke, i.e. within `strokeWidth / 2 + tolerance`
|
|
4043
|
+
* of the sampled outline. The point must be in the same coordinate space as the curve.
|
|
4044
|
+
*
|
|
4045
|
+
* Options: `strokeWidth` (path units, default `1`), `tolerance` (extra hit slack in path
|
|
4046
|
+
* units, default `0` — useful for thin strokes; no coordinate scaling is assumed, so convert
|
|
4047
|
+
* pixel tolerance to path units upstream if your path is normalized), and `closed` (whether
|
|
4048
|
+
* to include the closing edge from the last vertex back to the first).
|
|
4049
|
+
*/
|
|
4050
|
+
isPointInStroke(point, options = {}) {
|
|
4051
|
+
const { strokeWidth = 1, tolerance = 0, closed = false } = options;
|
|
4052
|
+
return pointToPolylineDistance(point, this._getCachedAdaptiveVertices(), closed) <= strokeWidth / 2 + tolerance;
|
|
4053
|
+
}
|
|
4054
|
+
/**
|
|
4055
|
+
* Concise PathKit-style fill containment test: `contains(x, y)` is shorthand for
|
|
4056
|
+
* {@link isPointInFill} with a `{ x, y }` point.
|
|
4057
|
+
*/
|
|
4058
|
+
contains(x, y, options = {}) {
|
|
4059
|
+
return this.isPointInFill({
|
|
4060
|
+
x,
|
|
4061
|
+
y
|
|
4062
|
+
}, options);
|
|
4063
|
+
}
|
|
3887
4064
|
getFillVertices(_options) {
|
|
3888
4065
|
return this.getAdaptiveVertices();
|
|
3889
4066
|
}
|
|
@@ -4013,6 +4190,64 @@ var RoundCurve = class extends Curve {
|
|
|
4013
4190
|
}
|
|
4014
4191
|
return output.set(_x, _y);
|
|
4015
4192
|
}
|
|
4193
|
+
/**
|
|
4194
|
+
* Point on the ellipse at an absolute angle (mirrors {@link getPoint}'s parameterization,
|
|
4195
|
+
* ignoring `_diff`).
|
|
4196
|
+
*/
|
|
4197
|
+
_pointAtAngle(angle, output) {
|
|
4198
|
+
let x = this.cx + this.rx * Math.cos(angle);
|
|
4199
|
+
let y = this.cy + this.ry * Math.sin(angle);
|
|
4200
|
+
if (this.rotate !== 0) {
|
|
4201
|
+
const cos = Math.cos(this.rotate);
|
|
4202
|
+
const sin = Math.sin(this.rotate);
|
|
4203
|
+
const tx = x - this.cx;
|
|
4204
|
+
const ty = y - this.cy;
|
|
4205
|
+
x = tx * cos - ty * sin + this.cx;
|
|
4206
|
+
y = tx * sin + ty * cos + this.cy;
|
|
4207
|
+
}
|
|
4208
|
+
return output.set(x, y);
|
|
4209
|
+
}
|
|
4210
|
+
/**
|
|
4211
|
+
* Analytical bounds of the (elliptical) arc: the start/end points plus the per-axis
|
|
4212
|
+
* extrema angles that fall within the swept interval. Matches {@link getPoint}, so it is
|
|
4213
|
+
* exact for `ArcCurve`/`EllipseCurve`. The `_diff` offset (used only by the legacy
|
|
4214
|
+
* `_getAdaptiveVerticesByCircle` path) is intentionally ignored here.
|
|
4215
|
+
*/
|
|
4216
|
+
getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
|
|
4217
|
+
const { startAngle, rotate } = this;
|
|
4218
|
+
const delta = this._getDeltaAngle();
|
|
4219
|
+
const cosT = Math.cos(rotate);
|
|
4220
|
+
const sinT = Math.sin(rotate);
|
|
4221
|
+
const p = tempV2;
|
|
4222
|
+
let minX = min.x;
|
|
4223
|
+
let minY = min.y;
|
|
4224
|
+
let maxX = max.x;
|
|
4225
|
+
let maxY = max.y;
|
|
4226
|
+
const consider = (angle) => {
|
|
4227
|
+
this._pointAtAngle(angle, p);
|
|
4228
|
+
if (p.x < minX) minX = p.x;
|
|
4229
|
+
if (p.y < minY) minY = p.y;
|
|
4230
|
+
if (p.x > maxX) maxX = p.x;
|
|
4231
|
+
if (p.y > maxY) maxY = p.y;
|
|
4232
|
+
};
|
|
4233
|
+
consider(startAngle);
|
|
4234
|
+
consider(startAngle + delta);
|
|
4235
|
+
const ax = Math.atan2(-this.ry * sinT, this.rx * cosT);
|
|
4236
|
+
const ay = Math.atan2(this.ry * cosT, this.rx * sinT);
|
|
4237
|
+
const bases = [
|
|
4238
|
+
ax,
|
|
4239
|
+
ax + Math.PI,
|
|
4240
|
+
ay,
|
|
4241
|
+
ay + Math.PI
|
|
4242
|
+
];
|
|
4243
|
+
for (let i = 0; i < 4; i++) if (angleInSweep(bases[i], startAngle, delta)) consider(bases[i]);
|
|
4244
|
+
min.set(minX, minY);
|
|
4245
|
+
max.set(maxX, maxY);
|
|
4246
|
+
return {
|
|
4247
|
+
min: min.finite(),
|
|
4248
|
+
max: max.finite()
|
|
4249
|
+
};
|
|
4250
|
+
}
|
|
4016
4251
|
toCommands() {
|
|
4017
4252
|
const { cx, cy, rx, ry, startAngle, endAngle, clockwise, rotate } = this;
|
|
4018
4253
|
const startX = cx + rx * Math.cos(startAngle) * Math.cos(rotate) - ry * Math.sin(startAngle) * Math.sin(rotate);
|
|
@@ -4083,6 +4318,7 @@ var RoundCurve = class extends Curve {
|
|
|
4083
4318
|
this.cy = tempV2.y;
|
|
4084
4319
|
if (isTransformSkewed(transform)) transfEllipseGeneric(this, transform);
|
|
4085
4320
|
else transfEllipseNoSkew(this, transform);
|
|
4321
|
+
this.invalidate();
|
|
4086
4322
|
return this;
|
|
4087
4323
|
}
|
|
4088
4324
|
getControlPointRefs() {
|
|
@@ -4212,6 +4448,18 @@ var RoundCurve = class extends Curve {
|
|
|
4212
4448
|
return this;
|
|
4213
4449
|
}
|
|
4214
4450
|
};
|
|
4451
|
+
function angleInSweep(a, start, delta) {
|
|
4452
|
+
const PI_2 = Math.PI * 2;
|
|
4453
|
+
const eps = 1e-9;
|
|
4454
|
+
if (Math.abs(delta) >= PI_2 - eps) return true;
|
|
4455
|
+
let off = (a - start) % PI_2;
|
|
4456
|
+
if (delta >= 0) {
|
|
4457
|
+
if (off < -1e-9) off += PI_2;
|
|
4458
|
+
return off >= -1e-9 && off <= delta + eps;
|
|
4459
|
+
}
|
|
4460
|
+
if (off > eps) off -= PI_2;
|
|
4461
|
+
return off <= eps && off >= delta - eps;
|
|
4462
|
+
}
|
|
4215
4463
|
function transfEllipseGeneric(curve, m) {
|
|
4216
4464
|
const a = curve.rx;
|
|
4217
4465
|
const b = curve.ry;
|
|
@@ -4412,6 +4660,22 @@ var CompositeCurve = class CompositeCurve extends Curve {
|
|
|
4412
4660
|
super();
|
|
4413
4661
|
this.curves = curves;
|
|
4414
4662
|
}
|
|
4663
|
+
_adaptiveCacheLen = -1;
|
|
4664
|
+
_invalidateSelf() {
|
|
4665
|
+
super._invalidateSelf();
|
|
4666
|
+
this._adaptiveCacheLen = -1;
|
|
4667
|
+
this.curves.forEach((curve) => curve.invalidate());
|
|
4668
|
+
}
|
|
4669
|
+
_getCachedAdaptiveVertices() {
|
|
4670
|
+
if (!this._adaptiveCache || this._adaptiveCacheLen !== this.curves.length) {
|
|
4671
|
+
this.curves.forEach((curve) => {
|
|
4672
|
+
curve._owner = this;
|
|
4673
|
+
});
|
|
4674
|
+
this._adaptiveCache = this.getAdaptiveVertices();
|
|
4675
|
+
this._adaptiveCacheLen = this.curves.length;
|
|
4676
|
+
}
|
|
4677
|
+
return this._adaptiveCache;
|
|
4678
|
+
}
|
|
4415
4679
|
getFlatCurves() {
|
|
4416
4680
|
return this.curves.flatMap((curve) => {
|
|
4417
4681
|
if (curve instanceof CompositeCurve) return curve.getFlatCurves();
|
|
@@ -4446,6 +4710,7 @@ var CompositeCurve = class CompositeCurve extends Curve {
|
|
|
4446
4710
|
updateLengths() {
|
|
4447
4711
|
const lengths = [];
|
|
4448
4712
|
for (let i = 0, sum = 0, len = this.curves.length; i < len; i++) {
|
|
4713
|
+
this.curves[i]._owner = this;
|
|
4449
4714
|
sum += this.curves[i].getLength();
|
|
4450
4715
|
lengths.push(sum);
|
|
4451
4716
|
}
|
|
@@ -4499,7 +4764,10 @@ var CompositeCurve = class CompositeCurve extends Curve {
|
|
|
4499
4764
|
}
|
|
4500
4765
|
}
|
|
4501
4766
|
applyTransform(transform) {
|
|
4767
|
+
this._invalidating = true;
|
|
4502
4768
|
this.curves.forEach((curve) => curve.applyTransform(transform));
|
|
4769
|
+
this._invalidating = false;
|
|
4770
|
+
this.invalidate();
|
|
4503
4771
|
return this;
|
|
4504
4772
|
}
|
|
4505
4773
|
getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
|
|
@@ -4756,7 +5024,7 @@ var RectangleCurve = class extends PolygonCurve {
|
|
|
4756
5024
|
return this;
|
|
4757
5025
|
}
|
|
4758
5026
|
};
|
|
4759
|
-
var RoundRectangleCurve = class extends
|
|
5027
|
+
var RoundRectangleCurve = class extends CompositeCurve {
|
|
4760
5028
|
constructor(x = 0, y = 0, width = 1, height = 1, radius = 1) {
|
|
4761
5029
|
super();
|
|
4762
5030
|
this.x = x;
|
|
@@ -4767,25 +5035,44 @@ var RoundRectangleCurve = class extends RoundCurve {
|
|
|
4767
5035
|
this.update();
|
|
4768
5036
|
}
|
|
4769
5037
|
update() {
|
|
4770
|
-
const { x, y, width, height
|
|
4771
|
-
const
|
|
4772
|
-
const
|
|
4773
|
-
const
|
|
4774
|
-
const
|
|
4775
|
-
const
|
|
4776
|
-
const
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
5038
|
+
const { x, y, width, height } = this;
|
|
5039
|
+
const r = Math.max(0, Math.min(this.radius, Math.abs(width) / 2, Math.abs(height) / 2));
|
|
5040
|
+
const x0 = x;
|
|
5041
|
+
const x1 = x + r;
|
|
5042
|
+
const x2 = x + width - r;
|
|
5043
|
+
const x3 = x + width;
|
|
5044
|
+
const y0 = y;
|
|
5045
|
+
const y1 = y + r;
|
|
5046
|
+
const y2 = y + height - r;
|
|
5047
|
+
const y3 = y + height;
|
|
5048
|
+
if (r <= 0) this.curves = [
|
|
5049
|
+
LineCurve.from(x0, y0, x3, y0),
|
|
5050
|
+
LineCurve.from(x3, y0, x3, y3),
|
|
5051
|
+
LineCurve.from(x3, y3, x0, y3),
|
|
5052
|
+
LineCurve.from(x0, y3, x0, y0)
|
|
5053
|
+
];
|
|
5054
|
+
else {
|
|
5055
|
+
const HALF_PI = Math.PI / 2;
|
|
5056
|
+
this.curves = [
|
|
5057
|
+
LineCurve.from(x1, y0, x2, y0),
|
|
5058
|
+
new ArcCurve(x2, y1, r, -HALF_PI, 0, true),
|
|
5059
|
+
LineCurve.from(x3, y1, x3, y2),
|
|
5060
|
+
new ArcCurve(x2, y2, r, 0, HALF_PI, true),
|
|
5061
|
+
LineCurve.from(x2, y3, x1, y3),
|
|
5062
|
+
new ArcCurve(x1, y2, r, HALF_PI, Math.PI, true),
|
|
5063
|
+
LineCurve.from(x0, y2, x0, y1),
|
|
5064
|
+
new ArcCurve(x1, y1, r, Math.PI, Math.PI * 1.5, true)
|
|
5065
|
+
];
|
|
5066
|
+
}
|
|
5067
|
+
this.invalidate();
|
|
4780
5068
|
return this;
|
|
4781
5069
|
}
|
|
4782
5070
|
drawTo(ctx) {
|
|
4783
|
-
|
|
4784
|
-
ctx.roundRect(x, y, width, height, radius);
|
|
5071
|
+
ctx.roundRect(this.x, this.y, this.width, this.height, this.radius);
|
|
4785
5072
|
return this;
|
|
4786
5073
|
}
|
|
4787
5074
|
copyFrom(source) {
|
|
4788
|
-
|
|
5075
|
+
this.arcLengthDivision = source.arcLengthDivision;
|
|
4789
5076
|
this.x = source.x;
|
|
4790
5077
|
this.y = source.y;
|
|
4791
5078
|
this.width = source.width;
|
|
@@ -4862,6 +5149,16 @@ var CurvePath = class extends CompositeCurve {
|
|
|
4862
5149
|
getFillVertices(options) {
|
|
4863
5150
|
return this._closeVertices(super.getFillVertices(options));
|
|
4864
5151
|
}
|
|
5152
|
+
/**
|
|
5153
|
+
* Same as {@link Curve.isPointInStroke}, but `closed` defaults to this sub-path's actual
|
|
5154
|
+
* closed-ness: explicitly `autoClose`, or geometrically closed (first vertex === last).
|
|
5155
|
+
*/
|
|
5156
|
+
isPointInStroke(point, options = {}) {
|
|
5157
|
+
const { strokeWidth = 1, tolerance = 0 } = options;
|
|
5158
|
+
const vertices = this._getCachedAdaptiveVertices();
|
|
5159
|
+
const len = vertices.length;
|
|
5160
|
+
return pointToPolylineDistance(point, vertices, options.closed ?? (this.autoClose || len >= 6 && vertices[0] === vertices[len - 2] && vertices[1] === vertices[len - 1])) <= strokeWidth / 2 + tolerance;
|
|
5161
|
+
}
|
|
4865
5162
|
_setCurrentPoint(point) {
|
|
4866
5163
|
this.currentPoint = new Vector2(point.x, point.y);
|
|
4867
5164
|
if (!this.startPoint) this.startPoint = this.currentPoint.clone();
|
|
@@ -4999,6 +5296,8 @@ var CurvePath = class extends CompositeCurve {
|
|
|
4999
5296
|
};
|
|
5000
5297
|
var Path2D = class Path2D extends CompositeCurve {
|
|
5001
5298
|
_meta;
|
|
5299
|
+
_ringsCache;
|
|
5300
|
+
_ringsCacheLen = -1;
|
|
5002
5301
|
currentCurve = new CurvePath();
|
|
5003
5302
|
style;
|
|
5004
5303
|
get startPoint() {
|
|
@@ -5110,6 +5409,7 @@ var Path2D = class Path2D extends CompositeCurve {
|
|
|
5110
5409
|
this.getControlPointRefs().forEach((point) => {
|
|
5111
5410
|
point.scale(sx, sy, target);
|
|
5112
5411
|
});
|
|
5412
|
+
this.invalidate();
|
|
5113
5413
|
return this;
|
|
5114
5414
|
}
|
|
5115
5415
|
skew(ax, ay = 0, target = {
|
|
@@ -5119,6 +5419,7 @@ var Path2D = class Path2D extends CompositeCurve {
|
|
|
5119
5419
|
this.getControlPointRefs().forEach((point) => {
|
|
5120
5420
|
point.skew(ax, ay, target);
|
|
5121
5421
|
});
|
|
5422
|
+
this.invalidate();
|
|
5122
5423
|
return this;
|
|
5123
5424
|
}
|
|
5124
5425
|
rotate(rad, target = {
|
|
@@ -5128,6 +5429,7 @@ var Path2D = class Path2D extends CompositeCurve {
|
|
|
5128
5429
|
this.getControlPointRefs().forEach((point) => {
|
|
5129
5430
|
point.rotate(rad, target);
|
|
5130
5431
|
});
|
|
5432
|
+
this.invalidate();
|
|
5131
5433
|
return this;
|
|
5132
5434
|
}
|
|
5133
5435
|
bold(b) {
|
|
@@ -5173,47 +5475,67 @@ var Path2D = class Path2D extends CompositeCurve {
|
|
|
5173
5475
|
}
|
|
5174
5476
|
});
|
|
5175
5477
|
});
|
|
5478
|
+
this.invalidate();
|
|
5176
5479
|
return this;
|
|
5177
5480
|
}
|
|
5481
|
+
/**
|
|
5482
|
+
* Test whether a point lies inside the filled area of this path.
|
|
5483
|
+
*
|
|
5484
|
+
* Each sub-path ({@link CurvePath}) is sampled into its own ring and all rings are
|
|
5485
|
+
* evaluated together via {@link pointInPolygons}, so holes (donut / hollow shapes) are
|
|
5486
|
+
* honored. This is purely geometric and ignores `style.fill` — for the `fill: 'none'`
|
|
5487
|
+
* fallback, gate the call upstream (see {@link Path2DSet.hitTest}).
|
|
5488
|
+
*
|
|
5489
|
+
* Defaults `fillRule` to `style.fillRule`, then `'nonzero'` (matching SVG/Canvas).
|
|
5490
|
+
*/
|
|
5491
|
+
_invalidateSelf() {
|
|
5492
|
+
super._invalidateSelf();
|
|
5493
|
+
this._ringsCache = void 0;
|
|
5494
|
+
this._ringsCacheLen = -1;
|
|
5495
|
+
}
|
|
5496
|
+
/** Per-sub-path sampled rings, cached for repeated hit tests. */
|
|
5497
|
+
_getRings() {
|
|
5498
|
+
if (!this._ringsCache || this._ringsCacheLen !== this.curves.length) {
|
|
5499
|
+
this._ringsCache = this.curves.map((curve) => {
|
|
5500
|
+
curve._owner = this;
|
|
5501
|
+
return curve.getAdaptiveVertices();
|
|
5502
|
+
});
|
|
5503
|
+
this._ringsCacheLen = this.curves.length;
|
|
5504
|
+
}
|
|
5505
|
+
return this._ringsCache;
|
|
5506
|
+
}
|
|
5507
|
+
isPointInFill(point, options = {}) {
|
|
5508
|
+
const fillRule = options.fillRule ?? this.style.fillRule ?? "nonzero";
|
|
5509
|
+
return pointInPolygons(point, this._getRings(), fillRule);
|
|
5510
|
+
}
|
|
5511
|
+
/**
|
|
5512
|
+
* Test whether a point lies on this path's stroke. A hit on any sub-path counts.
|
|
5513
|
+
*
|
|
5514
|
+
* Defaults `strokeWidth` to this path's own {@link strokeWidth} (which is `0` when
|
|
5515
|
+
* `style.stroke` is `'none'`). Each sub-path infers its own closed-ness unless `closed`
|
|
5516
|
+
* is given explicitly.
|
|
5517
|
+
*/
|
|
5518
|
+
isPointInStroke(point, options = {}) {
|
|
5519
|
+
const strokeWidth = options.strokeWidth ?? this.strokeWidth;
|
|
5520
|
+
const { tolerance = 0, closed } = options;
|
|
5521
|
+
return this.curves.some((curve) => curve.isPointInStroke(point, {
|
|
5522
|
+
strokeWidth,
|
|
5523
|
+
tolerance,
|
|
5524
|
+
closed
|
|
5525
|
+
}));
|
|
5526
|
+
}
|
|
5178
5527
|
getMinMax(min = Vector2.MAX, max = Vector2.MIN, withStyle = true) {
|
|
5179
|
-
const strokeWidth = this.strokeWidth;
|
|
5180
5528
|
this.curves.forEach((curve) => {
|
|
5181
5529
|
curve.getMinMax(min, max);
|
|
5182
|
-
if (withStyle) {
|
|
5183
|
-
if (strokeWidth > 1) {
|
|
5184
|
-
const halfStrokeWidth = strokeWidth / 2;
|
|
5185
|
-
const isClockwise = curve.isClockwise();
|
|
5186
|
-
const points = [];
|
|
5187
|
-
for (let t = 0; t <= 1; t += 1 / curve.arcLengthDivision) {
|
|
5188
|
-
const point = curve.getPoint(t);
|
|
5189
|
-
const normal = curve.getNormal(t);
|
|
5190
|
-
const dist1 = normal.clone().scale(isClockwise ? halfStrokeWidth : -halfStrokeWidth);
|
|
5191
|
-
const dist2 = normal.clone().scale(isClockwise ? -halfStrokeWidth : halfStrokeWidth);
|
|
5192
|
-
points.push(point.clone().add(dist1), point.clone().add(dist2), point.clone().add({
|
|
5193
|
-
x: halfStrokeWidth,
|
|
5194
|
-
y: 0
|
|
5195
|
-
}), point.clone().add({
|
|
5196
|
-
x: -halfStrokeWidth,
|
|
5197
|
-
y: 0
|
|
5198
|
-
}), point.clone().add({
|
|
5199
|
-
x: 0,
|
|
5200
|
-
y: halfStrokeWidth
|
|
5201
|
-
}), point.clone().add({
|
|
5202
|
-
x: 0,
|
|
5203
|
-
y: -halfStrokeWidth
|
|
5204
|
-
}), point.clone().add({
|
|
5205
|
-
x: halfStrokeWidth,
|
|
5206
|
-
y: halfStrokeWidth
|
|
5207
|
-
}), point.clone().add({
|
|
5208
|
-
x: -halfStrokeWidth,
|
|
5209
|
-
y: -halfStrokeWidth
|
|
5210
|
-
}));
|
|
5211
|
-
}
|
|
5212
|
-
min.clampMin(...points);
|
|
5213
|
-
max.clampMax(...points);
|
|
5214
|
-
}
|
|
5215
|
-
}
|
|
5216
5530
|
});
|
|
5531
|
+
if (withStyle) {
|
|
5532
|
+
const strokeWidth = this.strokeWidth;
|
|
5533
|
+
if (strokeWidth > 1 && Number.isFinite(min.x)) {
|
|
5534
|
+
const half = strokeWidth / 2;
|
|
5535
|
+
min.set(min.x - half, min.y - half);
|
|
5536
|
+
max.set(max.x + half, max.y + half);
|
|
5537
|
+
}
|
|
5538
|
+
}
|
|
5217
5539
|
return {
|
|
5218
5540
|
min: min.finite(),
|
|
5219
5541
|
max: max.finite()
|
|
@@ -5352,6 +5674,42 @@ var Path2DSet = class {
|
|
|
5352
5674
|
this.paths = paths;
|
|
5353
5675
|
this.viewBox = viewBox;
|
|
5354
5676
|
}
|
|
5677
|
+
/**
|
|
5678
|
+
* Test whether a point lies inside the filled area of any path in this set.
|
|
5679
|
+
* Purely geometric (ignores `fill: 'none'`); use {@link hitTest} for style-aware hits.
|
|
5680
|
+
*/
|
|
5681
|
+
isPointInFill(point, options = {}) {
|
|
5682
|
+
return this.paths.some((path) => path.isPointInFill(point, options));
|
|
5683
|
+
}
|
|
5684
|
+
/**
|
|
5685
|
+
* Concise PathKit-style fill containment test across the whole set; shorthand for
|
|
5686
|
+
* {@link isPointInFill} with a `{ x, y }` point.
|
|
5687
|
+
*/
|
|
5688
|
+
contains(x, y, options = {}) {
|
|
5689
|
+
return this.isPointInFill({
|
|
5690
|
+
x,
|
|
5691
|
+
y
|
|
5692
|
+
}, options);
|
|
5693
|
+
}
|
|
5694
|
+
/**
|
|
5695
|
+
* Find the topmost path hit by a point, or `undefined` if none.
|
|
5696
|
+
*
|
|
5697
|
+
* Paths are tested top-to-bottom (last drawn first). For each path a fill hit is checked
|
|
5698
|
+
* first (skipped when `style.fill` is `'none'`), then — if `stroke` is enabled — a stroke
|
|
5699
|
+
* hit (skipped when `style.stroke` is `'none'`). This honors the "fill: none falls back to
|
|
5700
|
+
* stroke" rule; the coordinate space of `point` must match the paths (no scaling assumed).
|
|
5701
|
+
*
|
|
5702
|
+
* Options: `stroke` (also test strokes, default `true`), `tolerance` (extra stroke hit slack
|
|
5703
|
+
* in path units, default `0`), and `fillRule` (overrides each path's own fill rule).
|
|
5704
|
+
*/
|
|
5705
|
+
hitTest(point, options = {}) {
|
|
5706
|
+
const { stroke = true, tolerance, fillRule } = options;
|
|
5707
|
+
for (let i = this.paths.length - 1; i >= 0; i--) {
|
|
5708
|
+
const path = this.paths[i];
|
|
5709
|
+
if ((path.style.fill ?? "#000") !== "none" && path.isPointInFill(point, { fillRule })) return path;
|
|
5710
|
+
if (stroke && (path.style.stroke ?? "none") !== "none" && path.isPointInStroke(point, { tolerance })) return path;
|
|
5711
|
+
}
|
|
5712
|
+
}
|
|
5355
5713
|
getBoundingBox(withStyle = true) {
|
|
5356
5714
|
if (!this.paths.length) return;
|
|
5357
5715
|
const min = Vector2.MAX;
|
|
@@ -5655,7 +6013,7 @@ function _createPresetShape(node, options) {
|
|
|
5655
6013
|
var root;
|
|
5656
6014
|
async function getRoot() {
|
|
5657
6015
|
if (!root) {
|
|
5658
|
-
const presetShapeDefinitions = await import("./presetShapeDefinitions-
|
|
6016
|
+
const presetShapeDefinitions = await import("./presetShapeDefinitions-NAoQKZ6z.js").then((rep) => rep.default);
|
|
5659
6017
|
root = OoxmlNode.fromXML(presetShapeDefinitions);
|
|
5660
6018
|
}
|
|
5661
6019
|
return root;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mce/bigesj",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.18.
|
|
4
|
+
"version": "0.18.5",
|
|
5
5
|
"description": "Plugin for mce",
|
|
6
6
|
"author": "wxm",
|
|
7
7
|
"license": "MIT",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"modern-openxml": "^1.10.1"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"mce": "0.18.
|
|
52
|
+
"mce": "0.18.5"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"mce": "^0"
|
|
File without changes
|