paperjs-offset 1.0.8 → 2.1.0

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.umd.js CHANGED
@@ -1,413 +1,827 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('paper')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'paper'], factory) :
4
- (global = global || self, factory(global.paperjsOffset = {}, global.paper));
5
- }(this, (function (exports, paper) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('paper')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'paper'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.paperjsOffset = {}, global.paper));
5
+ })(this, (function (exports, paper) { 'use strict';
6
6
 
7
- paper = paper && Object.prototype.hasOwnProperty.call(paper, 'default') ? paper['default'] : paper;
7
+ var MAX_RECURSION_TIME = 20;
8
+ var STRATEGIES = [
9
+ {
10
+ algorithm: 'adaptive',
11
+ splitSelfIntersectingCurves: true,
12
+ guardInsideJoins: true,
13
+ simplifySelfIntersectingStroke: true,
14
+ adaptiveFallback: true,
15
+ },
16
+ {
17
+ algorithm: 'robust',
18
+ splitSelfIntersectingCurves: true,
19
+ guardInsideJoins: true,
20
+ simplifySelfIntersectingStroke: true,
21
+ adaptiveFallback: false,
22
+ },
23
+ {
24
+ algorithm: 'split',
25
+ splitSelfIntersectingCurves: true,
26
+ guardInsideJoins: false,
27
+ simplifySelfIntersectingStroke: false,
28
+ adaptiveFallback: false,
29
+ },
30
+ {
31
+ algorithm: 'legacy',
32
+ splitSelfIntersectingCurves: false,
33
+ guardInsideJoins: false,
34
+ simplifySelfIntersectingStroke: false,
35
+ adaptiveFallback: false,
36
+ },
37
+ ];
38
+ function getStrategy(algorithm) {
39
+ if (algorithm === 'auto') {
40
+ return STRATEGIES[0];
41
+ }
42
+ return STRATEGIES.filter(function (strategy) { return strategy.algorithm === algorithm; })[0] || STRATEGIES[0];
43
+ }
44
+ /**
45
+ * Offset the start/terminal segment of a bezier curve
46
+ * @param segment segment to offset
47
+ * @param curve curve to offset
48
+ * @param handleNormal the normal of the the line formed of two handles
49
+ * @param offset offset value
50
+ */
51
+ function offsetSegment(segment, curve, handleNormal, offset) {
52
+ var isFirst = segment.curve === curve;
53
+ // get offset vector
54
+ var offsetVector = (curve.getNormalAtTime(isFirst ? 0 : 1)).multiply(offset);
55
+ // get offset point
56
+ var point = segment.point.add(offsetVector);
57
+ var newSegment = new paper.Segment(point);
58
+ // handleOut for start segment & handleIn for terminal segment
59
+ var handle = (isFirst ? 'handleOut' : 'handleIn');
60
+ newSegment[handle] = segment[handle].add(handleNormal.subtract(offsetVector).divide(2));
61
+ return newSegment;
62
+ }
63
+ /**
64
+ * Adaptive offset a curve by repeatly apply the approximation proposed by Tiller and Hanson.
65
+ * @param curve curve to offset
66
+ * @param offset offset value
67
+ */
68
+ function adaptiveOffsetCurve(curve, offset, strategy, recursionTime) {
69
+ if (recursionTime === void 0) { recursionTime = 0; }
70
+ var hNormal = (new paper.Curve(curve.segment1.handleOut.add(curve.segment1.point), new paper.Point(0, 0), new paper.Point(0, 0), curve.segment2.handleIn.add(curve.segment2.point))).getNormalAtTime(0.5).multiply(offset);
71
+ var segment1 = offsetSegment(curve.segment1, curve, hNormal, offset);
72
+ var segment2 = offsetSegment(curve.segment2, curve, hNormal, offset);
73
+ if (recursionTime > MAX_RECURSION_TIME) {
74
+ return [segment1, segment2];
75
+ }
76
+ // divide && re-offset
77
+ var offsetCurve = new paper.Curve(segment1, segment2);
78
+ var offsetCurveIntersections = offsetCurve.getIntersections(offsetCurve);
79
+ var threshold = Math.min(Math.abs(offset) / 10, 1);
80
+ var midOffset = offsetCurve.getPointAtTime(0.5).getDistance(curve.getPointAtTime(0.5));
81
+ var needsSplit = strategy.splitSelfIntersectingCurves
82
+ ? offsetCurveIntersections.length > 0 || Math.abs(midOffset - Math.abs(offset)) > threshold
83
+ : offsetCurveIntersections.length === 0 && Math.abs(midOffset - Math.abs(offset)) > threshold;
84
+ if (needsSplit) {
85
+ var subCurve = curve.divideAtTime(0.5);
86
+ if (subCurve != null) {
87
+ return adaptiveOffsetCurve(curve, offset, strategy, recursionTime + 1)
88
+ .concat(adaptiveOffsetCurve(subCurve, offset, strategy, recursionTime + 1));
89
+ }
90
+ }
91
+ return [segment1, segment2];
92
+ }
93
+ /**
94
+ * Create a round join segment between two adjacent segments.
95
+ */
96
+ function makeRoundJoin(segment1, segment2, originPoint, radius) {
97
+ var through = segment1.point.subtract(originPoint).add(segment2.point.subtract(originPoint))
98
+ .normalize(Math.abs(radius)).add(originPoint);
99
+ var arc = new paper.Path.Arc({ from: segment1.point, to: segment2.point, through: through, insert: false });
100
+ segment1.handleOut = arc.firstSegment.handleOut;
101
+ segment2.handleIn = arc.lastSegment.handleIn;
102
+ return arc.segments.length === 3 ? arc.segments[1] : null;
103
+ }
104
+ function det(p1, p2) {
105
+ return p1.x * p2.y - p1.y * p2.x;
106
+ }
107
+ /**
108
+ * Get the intersection point of point based lines
109
+ */
110
+ function getPointLineIntersections(p1, p2, p3, p4) {
111
+ var l1 = p1.subtract(p2);
112
+ var l2 = p3.subtract(p4);
113
+ var dl1 = det(p1, p2);
114
+ var dl2 = det(p3, p4);
115
+ return new paper.Point(dl1 * l2.x - l1.x * dl2, dl1 * l2.y - l1.y * dl2).divide(det(l1, l2));
116
+ }
117
+ /**
118
+ * Connect two adjacent bezier curve, each curve is represented by two segments,
119
+ * create different types of joins or simply removal redundant segment.
120
+ */
121
+ function isOutsideJoin(origin, offset) {
122
+ var _a;
123
+ var previousCurve = (_a = origin.previous) === null || _a === void 0 ? void 0 : _a.curve;
124
+ var nextCurve = origin.curve;
125
+ if (!previousCurve || !nextCurve) {
126
+ return true;
127
+ }
128
+ var tangentIn = previousCurve.getTangentAtTime(1);
129
+ var tangentOut = nextCurve.getTangentAtTime(0);
130
+ var turn = det(tangentIn, tangentOut);
131
+ return Math.abs(turn) < 1e-9 || turn * offset > 0;
132
+ }
133
+ function connectAdjacentBezier(segments1, segments2, origin, joinType, offset, limit, closed, strategy) {
134
+ var curve1 = new paper.Curve(segments1[0], segments1[1]);
135
+ var curve2 = new paper.Curve(segments2[0], segments2[1]);
136
+ var intersection = curve1.getIntersections(curve2);
137
+ var distance = segments1[1].point.getDistance(segments2[0].point);
138
+ var shouldJoin = !closed || !strategy.guardInsideJoins || isOutsideJoin(origin, offset);
139
+ if (origin.isSmooth()) {
140
+ segments2[0].handleOut = segments2[0].handleOut.project(origin.handleOut);
141
+ segments2[0].handleIn = segments1[1].handleIn.project(origin.handleIn);
142
+ segments2[0].point = segments1[1].point.add(segments2[0].point).divide(2);
143
+ segments1.pop();
144
+ }
145
+ else {
146
+ if (intersection.length === 0) {
147
+ if (distance > Math.abs(offset) * 0.1) {
148
+ // connect
149
+ switch (joinType) {
150
+ case 'miter':
151
+ if (shouldJoin) {
152
+ var join = getPointLineIntersections(curve1.point2, curve1.point2.add(curve1.getTangentAtTime(1)), curve2.point1, curve2.point1.add(curve2.getTangentAtTime(0)));
153
+ // prevent sharp angle
154
+ var joinOffset = Math.max(join.getDistance(curve1.point2), join.getDistance(curve2.point1));
155
+ if (joinOffset < Math.abs(offset) * limit) {
156
+ segments1.push(new paper.Segment(join));
157
+ }
158
+ }
159
+ break;
160
+ case 'round':
161
+ if (shouldJoin) {
162
+ var mid = makeRoundJoin(segments1[1], segments2[0], origin.point, offset);
163
+ if (mid) {
164
+ segments1.push(mid);
165
+ }
166
+ }
167
+ break;
168
+ }
169
+ }
170
+ else {
171
+ segments2[0].handleIn = segments1[1].handleIn;
172
+ segments1.pop();
173
+ }
174
+ }
175
+ else {
176
+ var second1 = curve1.divideAt(intersection[0]);
177
+ if (second1) {
178
+ var join = second1.segment1;
179
+ var second2 = curve2.divideAt(curve2.getIntersections(curve1)[0]);
180
+ join.handleOut = second2 ? second2.segment1.handleOut : segments2[0].handleOut;
181
+ segments1.pop();
182
+ segments2[0] = join;
183
+ }
184
+ else {
185
+ segments2[0].handleIn = segments1[1].handleIn;
186
+ segments1.pop();
187
+ }
188
+ }
189
+ }
190
+ }
191
+ /**
192
+ * Connect all the segments together.
193
+ */
194
+ function connectBeziers(rawSegments, join, source, offset, limit, strategy) {
195
+ var originSegments = source.segments;
196
+ var first = rawSegments[0].slice();
197
+ for (var i = 0; i < rawSegments.length - 1; ++i) {
198
+ connectAdjacentBezier(rawSegments[i], rawSegments[i + 1], originSegments[i + 1], join, offset, limit, source.closed, strategy);
199
+ }
200
+ if (source.closed) {
201
+ connectAdjacentBezier(rawSegments[rawSegments.length - 1], first, originSegments[0], join, offset, limit, source.closed, strategy);
202
+ rawSegments[0][0] = first[0];
203
+ }
204
+ return rawSegments;
205
+ }
206
+ function reduceSingleChildCompoundPath(path) {
207
+ if (path.children.length === 1) {
208
+ path = path.children[0];
209
+ path.remove(); // remove from parent, this is critical, or the style attributes will be ignored
210
+ }
211
+ return path;
212
+ }
213
+ /** Normalize a path, always clockwise, non-self-intersection, ignore really small components, and no one-component compound path. */
214
+ function normalize(path, areaThreshold) {
215
+ if (areaThreshold === void 0) { areaThreshold = 0.01; }
216
+ if (path.closed) {
217
+ var ignoreArea_1 = Math.abs(path.area * areaThreshold);
218
+ if (!path.clockwise) {
219
+ path.reverse();
220
+ }
221
+ path = path.unite(path, { insert: false });
222
+ path = path.resolveCrossings();
223
+ if (path instanceof paper.CompoundPath) {
224
+ path.children.filter(function (c) { return Math.abs(c.area) < ignoreArea_1; }).forEach(function (c) { return c.remove(); });
225
+ if (path.children.length === 1) {
226
+ return reduceSingleChildCompoundPath(path);
227
+ }
228
+ }
229
+ }
230
+ return path;
231
+ }
232
+ function cleanupStrokeOutline(path, offset, strategy) {
233
+ var result = normalize(path);
234
+ if (strategy.simplifySelfIntersectingStroke && countSelfIntersections(result) > 0) {
235
+ var simplified = result.clone({ insert: false });
236
+ simplified.simplify(Math.max(Math.min(Math.abs(offset) * 0.02, 0.5), 0.1));
237
+ result = normalize(simplified);
238
+ }
239
+ return result;
240
+ }
241
+ function isSameDirection(partialPath, fullPath) {
242
+ var offset1 = partialPath.segments[0].location.offset;
243
+ var offset2 = partialPath.segments[Math.max(1, Math.floor(partialPath.segments.length / 2))].location.offset;
244
+ var sampleOffset = (offset1 + offset2) / 3;
245
+ var originOffset1 = fullPath.getNearestLocation(partialPath.getPointAt(sampleOffset)).offset;
246
+ var originOffset2 = fullPath.getNearestLocation(partialPath.getPointAt(2 * sampleOffset)).offset;
247
+ return originOffset1 < originOffset2;
248
+ }
249
+ /** Remove self intersection when offset is negative by point direction dectection. */
250
+ function removeIntersection(path) {
251
+ if (path.closed) {
252
+ var newPath = path.unite(path, { insert: false });
253
+ if (newPath instanceof paper.CompoundPath) {
254
+ newPath.children.filter(function (c) {
255
+ if (c.segments.length > 1) {
256
+ return !isSameDirection(c, path);
257
+ }
258
+ else {
259
+ return true;
260
+ }
261
+ }).forEach(function (c) { return c.remove(); });
262
+ return reduceSingleChildCompoundPath(newPath);
263
+ }
264
+ }
265
+ return path;
266
+ }
267
+ function getSegments(path) {
268
+ if (path instanceof paper.CompoundPath) {
269
+ return path.children.map(function (c) { return c.segments; }).flat();
270
+ }
271
+ else {
272
+ return path.segments;
273
+ }
274
+ }
275
+ /**
276
+ * Remove impossible segments in negative offset condition.
277
+ */
278
+ function removeOutsiders(newPath, path) {
279
+ var segments = getSegments(newPath).slice();
280
+ segments.forEach(function (segment) {
281
+ if (!path.contains(segment.point)) {
282
+ segment.remove();
283
+ }
284
+ });
285
+ }
286
+ function preparePath(path, offset) {
287
+ var source = path.clone({ insert: false });
288
+ source.reduce({});
289
+ if (path.closed && !path.clockwise) {
290
+ source.reverse();
291
+ offset = -offset;
292
+ }
293
+ return [source, offset];
294
+ }
295
+ function offsetSimpleShape(path, offset, join, limit, strategy) {
296
+ var _a;
297
+ var source;
298
+ _a = preparePath(path, offset), source = _a[0], offset = _a[1];
299
+ var curves = source.curves.slice();
300
+ var offsetCurves = curves.map(function (curve) { return adaptiveOffsetCurve(curve, offset, strategy); }).flat();
301
+ var raws = [];
302
+ for (var i = 0; i < offsetCurves.length; i += 2) {
303
+ raws.push(offsetCurves.slice(i, i + 2));
304
+ }
305
+ var segments = connectBeziers(raws, join, source, offset, limit, strategy).flat();
306
+ var newPath = removeIntersection(new paper.Path({ segments: segments, insert: false, closed: path.closed }));
307
+ newPath.reduce({});
308
+ if (source.closed && ((source.clockwise && offset < 0) || (!source.clockwise && offset > 0))) {
309
+ removeOutsiders(newPath, path);
310
+ }
311
+ // recovery path
312
+ if (source.clockwise !== path.clockwise) {
313
+ newPath.reverse();
314
+ }
315
+ return normalize(newPath);
316
+ }
317
+ function makeRoundCap(from, to, offset) {
318
+ var origin = from.point.add(to.point).divide(2);
319
+ var normal = to.point.subtract(from.point).rotate(-90, new paper.Point(0, 0)).normalize(offset);
320
+ var through = origin.add(normal);
321
+ var arc = new paper.Path.Arc({ from: from.point, to: to.point, through: through, insert: false });
322
+ return arc.segments;
323
+ }
324
+ function connectSide(outer, inner, offset, cap) {
325
+ if (outer instanceof paper.CompoundPath) {
326
+ var cs = outer.children.map(function (c) { return ({ c: c, a: Math.abs(c.area) }); });
327
+ cs = cs.sort(function (c1, c2) { return c2.a - c1.a; });
328
+ outer = cs[0].c;
329
+ }
330
+ var oSegments = outer.segments.slice();
331
+ var iSegments = inner.segments.slice();
332
+ switch (cap) {
333
+ case 'round':
334
+ var heads = makeRoundCap(iSegments[iSegments.length - 1], oSegments[0], offset);
335
+ var tails = makeRoundCap(oSegments[oSegments.length - 1], iSegments[0], offset);
336
+ var result = new paper.Path({ segments: heads.concat(oSegments, tails, iSegments), closed: true, insert: false });
337
+ result.reduce({});
338
+ return result;
339
+ default: return new paper.Path({ segments: oSegments.concat(iSegments), closed: true, insert: false });
340
+ }
341
+ }
342
+ function offsetSimpleStroke(path, offset, join, cap, limit, strategy) {
343
+ offset = path.closed && !path.clockwise ? -offset : offset;
344
+ var positiveOffset = offsetSimpleShape(path, offset, join, limit, strategy);
345
+ var negativeOffset = offsetSimpleShape(path, -offset, join, limit, strategy);
346
+ if (path.closed) {
347
+ return cleanupStrokeOutline(positiveOffset.subtract(negativeOffset, { insert: false }), offset, strategy);
348
+ }
349
+ else {
350
+ var inner = negativeOffset;
351
+ var holes = new Array();
352
+ if (negativeOffset instanceof paper.CompoundPath) {
353
+ holes = negativeOffset.children.filter(function (c) { return c.closed; });
354
+ holes.forEach(function (h) { return h.remove(); });
355
+ inner = negativeOffset.children[0];
356
+ }
357
+ inner.reverse();
358
+ var final = connectSide(positiveOffset, inner, offset, cap);
359
+ if (holes.length > 0) {
360
+ for (var _i = 0, holes_1 = holes; _i < holes_1.length; _i++) {
361
+ var hole = holes_1[_i];
362
+ final = final.subtract(hole, { insert: false });
363
+ }
364
+ }
365
+ return cleanupStrokeOutline(final, offset, strategy);
366
+ }
367
+ }
368
+ function getChildPaths(path) {
369
+ if (path instanceof paper.CompoundPath) {
370
+ return path.children;
371
+ }
372
+ return [path];
373
+ }
374
+ function finiteNumber(value) {
375
+ return Number.isFinite(value);
376
+ }
377
+ function countSelfIntersections(path) {
378
+ if (!path.closed) {
379
+ return 0;
380
+ }
381
+ try {
382
+ var children_1 = getChildPaths(path);
383
+ var count_1 = 0;
384
+ children_1.forEach(function (child, index) {
385
+ count_1 += child.getIntersections(child).length;
386
+ for (var i = index + 1; i < children_1.length; i += 1) {
387
+ count_1 += child.getIntersections(children_1[i]).length;
388
+ }
389
+ });
390
+ return count_1;
391
+ }
392
+ catch (error) {
393
+ return 0;
394
+ }
395
+ }
396
+ function samplePoints(path, maxPerChild) {
397
+ if (maxPerChild === void 0) { maxPerChild = 16; }
398
+ var points = [];
399
+ getChildPaths(path).forEach(function (child) {
400
+ if (!child.length || child.segments.length === 0) {
401
+ return;
402
+ }
403
+ var count = Math.min(maxPerChild, Math.max(4, Math.ceil(child.length / 30)));
404
+ for (var i = 0; i < count; i += 1) {
405
+ var ratio = child.closed ? i / count : i / Math.max(count - 1, 1);
406
+ var point = child.getPointAt(child.length * ratio);
407
+ if (point) {
408
+ points.push(point);
409
+ }
410
+ }
411
+ });
412
+ return points;
413
+ }
414
+ function containsPoint(path, point) {
415
+ try {
416
+ return path.contains(point);
417
+ }
418
+ catch (error) {
419
+ return false;
420
+ }
421
+ }
422
+ function distanceToPath(path, point) {
423
+ try {
424
+ var nearest = path.getNearestPoint(point);
425
+ return nearest ? nearest.getDistance(point) : Number.POSITIVE_INFINITY;
426
+ }
427
+ catch (error) {
428
+ return Number.POSITIVE_INFINITY;
429
+ }
430
+ }
431
+ function addWarning(warnings, warning) {
432
+ if (warnings.indexOf(warning) === -1) {
433
+ warnings.push(warning);
434
+ }
435
+ }
436
+ function analyzeOffsetQuality(source, result, offset, options) {
437
+ if (options === void 0) { options = {}; }
438
+ var warnings = new Array();
439
+ var expectedClosed = options.stroke ? true : source.closed;
440
+ var segmentCount = getSegments(result).length;
441
+ var area = Math.abs(result.area || 0);
442
+ var absOffset = Math.abs(offset);
443
+ var score = segmentCount * 0.01;
444
+ var containmentErrors = 0;
445
+ var distanceErrors = 0;
446
+ var bounds = result.bounds;
447
+ if (segmentCount === 0) {
448
+ score += 100000;
449
+ addWarning(warnings, 'empty-result');
450
+ }
451
+ if (!bounds || !finiteNumber(bounds.x) || !finiteNumber(bounds.y) || !finiteNumber(bounds.width) || !finiteNumber(bounds.height)) {
452
+ score += 100000;
453
+ addWarning(warnings, 'non-finite-bounds');
454
+ }
455
+ if (result.closed !== expectedClosed) {
456
+ score += 50000;
457
+ addWarning(warnings, 'unexpected-closed-state');
458
+ }
459
+ var selfIntersections = countSelfIntersections(result);
460
+ if (selfIntersections > 0) {
461
+ score += selfIntersections * 1000;
462
+ addWarning(warnings, 'self-intersection');
463
+ }
464
+ if (source.closed && result.closed && !options.stroke) {
465
+ var sourceArea = Math.abs(source.area || 0);
466
+ if (sourceArea > 0 && offset > 0 && area < sourceArea * 0.95) {
467
+ score += ((sourceArea - area) / sourceArea) * 2000;
468
+ addWarning(warnings, 'positive-offset-area-shrank');
469
+ }
470
+ if (sourceArea > 0 && offset < 0 && area > sourceArea * 1.05) {
471
+ score += ((area - sourceArea) / sourceArea) * 2000;
472
+ addWarning(warnings, 'negative-offset-area-grew');
473
+ }
474
+ if (sourceArea > 0 && offset < 0) {
475
+ var areaRatio = area / sourceArea;
476
+ if (areaRatio < 0.25) {
477
+ score += (0.25 - areaRatio) * 4000;
478
+ addWarning(warnings, 'negative-offset-collapse');
479
+ }
480
+ }
481
+ if (sourceArea > 0 && offset > 0) {
482
+ var sourceBounds = source.bounds;
483
+ var centerShift = result.bounds.center.getDistance(sourceBounds.center);
484
+ var centerTolerance = Math.max(absOffset * 1.15, Math.min(sourceBounds.width, sourceBounds.height) * 0.08);
485
+ if (centerShift > centerTolerance) {
486
+ score += (centerShift - centerTolerance) * 80;
487
+ addWarning(warnings, 'offset-center-shift');
488
+ }
489
+ }
490
+ var containmentTolerance_1 = Math.max(absOffset * 0.08, 0.5);
491
+ var containmentSamples = offset >= 0 ? samplePoints(source) : samplePoints(result);
492
+ containmentSamples.forEach(function (point) {
493
+ var container = offset >= 0 ? result : source;
494
+ if (!containsPoint(container, point) && distanceToPath(container, point) > containmentTolerance_1) {
495
+ containmentErrors += 1;
496
+ }
497
+ });
498
+ if (containmentErrors > 0) {
499
+ score += containmentErrors * 150;
500
+ addWarning(warnings, offset >= 0 ? 'source-outside-positive-offset' : 'negative-offset-outside-source');
501
+ }
502
+ }
503
+ if (absOffset > 0.001) {
504
+ var distanceTolerance_1 = Math.max(absOffset * 0.18, 0.75);
505
+ samplePoints(result).forEach(function (point) {
506
+ var distance = distanceToPath(source, point);
507
+ if (finiteNumber(distance) && distance < distanceTolerance_1) {
508
+ distanceErrors += 1;
509
+ }
510
+ });
511
+ if (distanceErrors > 0) {
512
+ score += distanceErrors * 35;
513
+ addWarning(warnings, 'offset-distance-collapse');
514
+ }
515
+ }
516
+ return {
517
+ score: score,
518
+ warnings: warnings,
519
+ selfIntersections: selfIntersections,
520
+ containmentErrors: containmentErrors,
521
+ distanceErrors: distanceErrors,
522
+ segmentCount: segmentCount,
523
+ area: area,
524
+ };
525
+ }
526
+ function pickBestResult(source, offset, stroke, makeResult) {
527
+ var bestResult = null;
528
+ var bestQuality = null;
529
+ var firstError = null;
530
+ STRATEGIES.forEach(function (strategy) {
531
+ try {
532
+ var result = makeResult(strategy);
533
+ var quality = analyzeOffsetQuality(source, result, offset, { stroke: stroke });
534
+ quality.algorithm = strategy.algorithm;
535
+ if (!bestQuality || quality.score < bestQuality.score) {
536
+ bestResult = result;
537
+ bestQuality = quality;
538
+ }
539
+ }
540
+ catch (error) {
541
+ if (!firstError && error instanceof Error) {
542
+ firstError = error;
543
+ }
544
+ }
545
+ });
546
+ if (!bestResult) {
547
+ throw firstError || new Error('Unable to offset path with any algorithm');
548
+ }
549
+ return bestResult;
550
+ }
551
+ function getNonSelfIntersectionPath(path) {
552
+ if (path.closed) {
553
+ return path.unite(path, { insert: false });
554
+ }
555
+ return path;
556
+ }
557
+ function offsetCompoundChild(child, parent, offset, join, limit, strategy) {
558
+ if (child.segments.length <= 1) {
559
+ return null;
560
+ }
561
+ if (!isSameDirection(child, parent)) {
562
+ child.reverse();
563
+ }
564
+ var childOffset = offsetSimpleShape(child, offset, join, limit, strategy);
565
+ childOffset = normalize(childOffset);
566
+ if (childOffset.clockwise !== child.clockwise) {
567
+ childOffset.reverse();
568
+ }
569
+ if (childOffset instanceof paper.CompoundPath) {
570
+ childOffset.applyMatrix = true;
571
+ return childOffset.children;
572
+ }
573
+ return childOffset;
574
+ }
575
+ function offsetCompoundShape(path, offset, join, limit, strategy) {
576
+ var children = path.children.filter(function (child) { return child.segments.length > 1; });
577
+ var outers = children.filter(function (child) { return child.clockwise; });
578
+ var holes = children.filter(function (child) { return !child.clockwise; });
579
+ if (outers.length === 0 || holes.length === 0) {
580
+ var offsetParts = children.map(function (child) { return offsetCompoundChild(child, path, offset, join, limit, strategy); });
581
+ return new paper.CompoundPath({ children: offsetParts.flat().filter(function (child) { return !!child; }), insert: false });
582
+ }
583
+ var pieces = outers.map(function (outer) {
584
+ var outerOffset = offsetCompoundChild(outer, path, offset, join, limit, strategy);
585
+ var result = outerOffset instanceof Array
586
+ ? new paper.CompoundPath({ children: outerOffset, insert: false })
587
+ : outerOffset;
588
+ holes.forEach(function (hole) {
589
+ if (!outer.contains(hole.bounds.center)) {
590
+ return;
591
+ }
592
+ var holeOffset = offsetCompoundChild(hole, path, offset, join, limit, strategy);
593
+ if (!holeOffset) {
594
+ return;
595
+ }
596
+ var holePath = holeOffset instanceof Array
597
+ ? new paper.CompoundPath({ children: holeOffset, insert: false })
598
+ : holeOffset;
599
+ var next = result.subtract(holePath, { insert: false });
600
+ result.remove();
601
+ holePath.remove();
602
+ result = next;
603
+ });
604
+ return result;
605
+ });
606
+ if (pieces.length === 1) {
607
+ return pieces[0];
608
+ }
609
+ return pieces.slice(1).reduce(function (result, piece) {
610
+ var next = result.unite(piece, { insert: false });
611
+ result.remove();
612
+ piece.remove();
613
+ return next;
614
+ }, pieces[0]);
615
+ }
616
+ function hasCompoundHoles(path) {
617
+ if (!(path instanceof paper.CompoundPath)) {
618
+ return false;
619
+ }
620
+ var children = path.children;
621
+ return children.some(function (child) { return child.clockwise; }) && children.some(function (child) { return !child.clockwise; });
622
+ }
623
+ function withoutAdaptiveFallback(strategy) {
624
+ return {
625
+ algorithm: 'robust',
626
+ splitSelfIntersectingCurves: strategy.splitSelfIntersectingCurves,
627
+ guardInsideJoins: strategy.guardInsideJoins,
628
+ simplifySelfIntersectingStroke: strategy.simplifySelfIntersectingStroke,
629
+ adaptiveFallback: false,
630
+ };
631
+ }
632
+ function addAdaptiveCandidate(candidates, makeResult) {
633
+ try {
634
+ candidates.push(makeResult());
635
+ }
636
+ catch (error) {
637
+ // Keep adaptive mode opportunistic: a failed fallback should not hide valid strict results.
638
+ }
639
+ }
640
+ function pickBestCandidate(source, offset, stroke, candidates) {
641
+ var bestResult = candidates[0];
642
+ var bestQuality = analyzeOffsetQuality(source, bestResult, offset, { stroke: stroke });
643
+ for (var i = 1; i < candidates.length; i += 1) {
644
+ var quality = analyzeOffsetQuality(source, candidates[i], offset, { stroke: stroke });
645
+ if (quality.score < bestQuality.score) {
646
+ bestResult = candidates[i];
647
+ bestQuality = quality;
648
+ }
649
+ }
650
+ return bestResult;
651
+ }
652
+ function offsetPathAdaptive(path, offset, join, limit, strategy) {
653
+ var baseStrategy = withoutAdaptiveFallback(strategy);
654
+ var candidates = new Array();
655
+ addAdaptiveCandidate(candidates, function () { return offsetPathWithStrategy(path, offset, join, limit, baseStrategy); });
656
+ if (join !== 'round') {
657
+ addAdaptiveCandidate(candidates, function () { return offsetPathWithStrategy(path, offset, 'round', limit, baseStrategy); });
658
+ }
659
+ if (path.closed && offset < 0) {
660
+ [0.8, 0.65, 0.5, 0.35, 0.25].forEach(function (factor) {
661
+ var fallbackOffset = offset * factor;
662
+ addAdaptiveCandidate(candidates, function () { return offsetPathWithStrategy(path, fallbackOffset, join, limit, baseStrategy); });
663
+ if (join !== 'round') {
664
+ addAdaptiveCandidate(candidates, function () { return offsetPathWithStrategy(path, fallbackOffset, 'round', limit, baseStrategy); });
665
+ }
666
+ });
667
+ }
668
+ if (candidates.length === 0) {
669
+ return offsetPathWithStrategy(path, offset, join, limit, baseStrategy);
670
+ }
671
+ return pickBestCandidate(path, offset, false, candidates);
672
+ }
673
+ function offsetPathWithStrategy(path, offset, join, limit, strategy) {
674
+ if (strategy.adaptiveFallback) {
675
+ return offsetPathAdaptive(path, offset, join, limit, strategy);
676
+ }
677
+ var nonSIPath = getNonSelfIntersectionPath(path);
678
+ var shouldNormalizeResult = !hasCompoundHoles(nonSIPath);
679
+ var result = nonSIPath;
680
+ if (nonSIPath instanceof paper.Path) {
681
+ result = offsetSimpleShape(nonSIPath, offset, join, limit, strategy);
682
+ }
683
+ else {
684
+ result = offsetCompoundShape(nonSIPath, offset, join, limit, strategy);
685
+ }
686
+ if (shouldNormalizeResult) {
687
+ result = normalize(result);
688
+ }
689
+ result.copyAttributes(nonSIPath, false);
690
+ result.remove();
691
+ return result;
692
+ }
693
+ function offsetPath(path, offset, join, limit, algorithm) {
694
+ if (algorithm === void 0) { algorithm = 'auto'; }
695
+ if (algorithm === 'auto') {
696
+ return pickBestResult(path, offset, false, function (strategy) { return offsetPathWithStrategy(path, offset, join, limit, strategy); });
697
+ }
698
+ return offsetPathWithStrategy(path, offset, join, limit, getStrategy(algorithm));
699
+ }
700
+ function offsetStrokeWithStrategy(path, offset, join, cap, limit, strategy) {
701
+ if (strategy.adaptiveFallback) {
702
+ return offsetStrokeAdaptive(path, offset, join, cap, limit, strategy);
703
+ }
704
+ var nonSIPath = getNonSelfIntersectionPath(path);
705
+ var result = nonSIPath;
706
+ if (nonSIPath instanceof paper.Path) {
707
+ result = offsetSimpleStroke(nonSIPath, offset, join, cap, limit, strategy);
708
+ }
709
+ else {
710
+ var children = nonSIPath.children.flatMap(function (c) {
711
+ return offsetSimpleStroke(c, offset, join, cap, limit, strategy);
712
+ });
713
+ result = children.reduce(function (c1, c2) { return c1.unite(c2, { insert: false }); });
714
+ }
715
+ result.strokeWidth = 0;
716
+ result.fillColor = nonSIPath.strokeColor;
717
+ result.shadowBlur = nonSIPath.shadowBlur;
718
+ result.shadowColor = nonSIPath.shadowColor;
719
+ result.shadowOffset = nonSIPath.shadowOffset;
720
+ return result;
721
+ }
722
+ function offsetStrokeAdaptive(path, offset, join, cap, limit, strategy) {
723
+ var baseStrategy = withoutAdaptiveFallback(strategy);
724
+ var candidates = new Array();
725
+ addAdaptiveCandidate(candidates, function () { return offsetStrokeWithStrategy(path, offset, join, cap, limit, baseStrategy); });
726
+ if (join !== 'round') {
727
+ addAdaptiveCandidate(candidates, function () { return offsetStrokeWithStrategy(path, offset, 'round', cap, limit, baseStrategy); });
728
+ }
729
+ if (cap !== 'round') {
730
+ addAdaptiveCandidate(candidates, function () { return offsetStrokeWithStrategy(path, offset, join, 'round', limit, baseStrategy); });
731
+ }
732
+ if (join !== 'round' && cap !== 'round') {
733
+ addAdaptiveCandidate(candidates, function () { return offsetStrokeWithStrategy(path, offset, 'round', 'round', limit, baseStrategy); });
734
+ }
735
+ if (candidates.length === 0) {
736
+ return offsetStrokeWithStrategy(path, offset, join, cap, limit, baseStrategy);
737
+ }
738
+ return pickBestCandidate(path, offset, true, candidates);
739
+ }
740
+ function offsetStroke$1(path, offset, join, cap, limit, algorithm) {
741
+ if (algorithm === void 0) { algorithm = 'auto'; }
742
+ if (algorithm === 'auto') {
743
+ return pickBestResult(path, offset, true, function (strategy) { return offsetStrokeWithStrategy(path, offset, join, cap, limit, strategy); });
744
+ }
745
+ return offsetStrokeWithStrategy(path, offset, join, cap, limit, getStrategy(algorithm));
746
+ }
8
747
 
9
- /**
10
- * Offset the start/terminal segment of a bezier curve
11
- * @param segment segment to offset
12
- * @param curve curve to offset
13
- * @param handleNormal the normal of the the line formed of two handles
14
- * @param offset offset value
15
- */
16
- function offsetSegment(segment, curve, handleNormal, offset) {
17
- var isFirst = segment.curve === curve;
18
- // get offset vector
19
- var offsetVector = (curve.getNormalAtTime(isFirst ? 0 : 1)).multiply(offset);
20
- // get offset point
21
- var point = segment.point.add(offsetVector);
22
- var newSegment = new paper.Segment(point);
23
- // handleOut for start segment & handleIn for terminal segment
24
- var handle = (isFirst ? 'handleOut' : 'handleIn');
25
- newSegment[handle] = segment[handle].add(handleNormal.subtract(offsetVector).divide(2));
26
- return newSegment;
27
- }
28
- /**
29
- * Adaptive offset a curve by repeatly apply the approximation proposed by Tiller and Hanson.
30
- * @param curve curve to offset
31
- * @param offset offset value
32
- */
33
- function adaptiveOffsetCurve(curve, offset) {
34
- var hNormal = (new paper.Curve(curve.segment1.handleOut.add(curve.segment1.point), new paper.Point(0, 0), new paper.Point(0, 0), curve.segment2.handleIn.add(curve.segment2.point))).getNormalAtTime(0.5).multiply(offset);
35
- var segment1 = offsetSegment(curve.segment1, curve, hNormal, offset);
36
- var segment2 = offsetSegment(curve.segment2, curve, hNormal, offset);
37
- // divide && re-offset
38
- var offsetCurve = new paper.Curve(segment1, segment2);
39
- // if the offset curve is not self intersected, divide it
40
- if (offsetCurve.getIntersections(offsetCurve).length === 0) {
41
- var threshold = Math.min(Math.abs(offset) / 10, 1);
42
- var midOffset = offsetCurve.getPointAtTime(0.5).getDistance(curve.getPointAtTime(0.5));
43
- if (Math.abs(midOffset - Math.abs(offset)) > threshold) {
44
- var subCurve = curve.divideAtTime(0.5);
45
- if (subCurve != null) {
46
- return adaptiveOffsetCurve(curve, offset).concat(adaptiveOffsetCurve(subCurve, offset));
47
- }
48
- }
49
- }
50
- return [segment1, segment2];
51
- }
52
- /**
53
- * Create a round join segment between two adjacent segments.
54
- */
55
- function makeRoundJoin(segment1, segment2, originPoint, radius) {
56
- var through = segment1.point.subtract(originPoint).add(segment2.point.subtract(originPoint))
57
- .normalize(Math.abs(radius)).add(originPoint);
58
- var arc = new paper.Path.Arc({ from: segment1.point, to: segment2.point, through: through, insert: false });
59
- segment1.handleOut = arc.firstSegment.handleOut;
60
- segment2.handleIn = arc.lastSegment.handleIn;
61
- return arc.segments.length === 3 ? arc.segments[1] : null;
62
- }
63
- function det(p1, p2) {
64
- return p1.x * p2.y - p1.y * p2.x;
65
- }
66
- /**
67
- * Get the intersection point of point based lines
68
- */
69
- function getPointLineIntersections(p1, p2, p3, p4) {
70
- var l1 = p1.subtract(p2);
71
- var l2 = p3.subtract(p4);
72
- var dl1 = det(p1, p2);
73
- var dl2 = det(p3, p4);
74
- return new paper.Point(dl1 * l2.x - l1.x * dl2, dl1 * l2.y - l1.y * dl2).divide(det(l1, l2));
75
- }
76
- /**
77
- * Connect two adjacent bezier curve, each curve is represented by two segments,
78
- * create different types of joins or simply removal redundant segment.
79
- */
80
- function connectAdjacentBezier(segments1, segments2, origin, joinType, offset, limit) {
81
- var curve1 = new paper.Curve(segments1[0], segments1[1]);
82
- var curve2 = new paper.Curve(segments2[0], segments2[1]);
83
- var intersection = curve1.getIntersections(curve2);
84
- var distance = segments1[1].point.getDistance(segments2[0].point);
85
- if (origin.isSmooth()) {
86
- segments2[0].handleOut = segments2[0].handleOut.project(origin.handleOut);
87
- segments2[0].handleIn = segments1[1].handleIn.project(origin.handleIn);
88
- segments2[0].point = segments1[1].point.add(segments2[0].point).divide(2);
89
- segments1.pop();
90
- }
91
- else {
92
- if (intersection.length === 0) {
93
- if (distance > Math.abs(offset) * 0.1) {
94
- // connect
95
- switch (joinType) {
96
- case 'miter':
97
- var join = getPointLineIntersections(curve1.point2, curve1.point2.add(curve1.getTangentAtTime(1)), curve2.point1, curve2.point1.add(curve2.getTangentAtTime(0)));
98
- // prevent sharp angle
99
- var joinOffset = Math.max(join.getDistance(curve1.point2), join.getDistance(curve2.point1));
100
- if (joinOffset < Math.abs(offset) * limit) {
101
- segments1.push(new paper.Segment(join));
102
- }
103
- break;
104
- case 'round':
105
- var mid = makeRoundJoin(segments1[1], segments2[0], origin.point, offset);
106
- if (mid) {
107
- segments1.push(mid);
108
- }
109
- break;
110
- }
111
- }
112
- else {
113
- segments2[0].handleIn = segments1[1].handleIn;
114
- segments1.pop();
115
- }
116
- }
117
- else {
118
- var second1 = curve1.divideAt(intersection[0]);
119
- if (second1) {
120
- var join = second1.segment1;
121
- var second2 = curve2.divideAt(curve2.getIntersections(curve1)[0]);
122
- join.handleOut = second2 ? second2.segment1.handleOut : segments2[0].handleOut;
123
- segments1.pop();
124
- segments2[0] = join;
125
- }
126
- else {
127
- segments2[0].handleIn = segments1[1].handleIn;
128
- segments1.pop();
129
- }
130
- }
131
- }
132
- }
133
- /**
134
- * Connect all the segments together.
135
- */
136
- function connectBeziers(rawSegments, join, source, offset, limit) {
137
- var originSegments = source.segments;
138
- var first = rawSegments[0].slice();
139
- for (var i = 0; i < rawSegments.length - 1; ++i) {
140
- connectAdjacentBezier(rawSegments[i], rawSegments[i + 1], originSegments[i + 1], join, offset, limit);
141
- }
142
- if (source.closed) {
143
- connectAdjacentBezier(rawSegments[rawSegments.length - 1], first, originSegments[0], join, offset, limit);
144
- rawSegments[0][0] = first[0];
145
- }
146
- return rawSegments;
147
- }
148
- function reduceSingleChildCompoundPath(path) {
149
- if (path.children.length === 1) {
150
- path = path.children[0];
151
- path.remove(); // remove from parent, this is critical, or the style attributes will be ignored
152
- }
153
- return path;
154
- }
155
- /** Normalize a path, always clockwise, non-self-intersection, ignore really small components, and no one-component compound path. */
156
- function normalize(path, areaThreshold) {
157
- if (areaThreshold === void 0) { areaThreshold = 0.01; }
158
- if (path.closed) {
159
- var ignoreArea_1 = Math.abs(path.area * areaThreshold);
160
- if (!path.clockwise) {
161
- path.reverse();
162
- }
163
- path = path.unite(path, { insert: false });
164
- if (path instanceof paper.CompoundPath) {
165
- path.children.filter(function (c) { return Math.abs(c.area) < ignoreArea_1; }).forEach(function (c) { return c.remove(); });
166
- if (path.children.length === 1) {
167
- return reduceSingleChildCompoundPath(path);
168
- }
169
- }
170
- }
171
- return path;
172
- }
173
- function isSameDirection(partialPath, fullPath) {
174
- var offset1 = partialPath.segments[0].location.offset;
175
- var offset2 = partialPath.segments[Math.max(1, Math.floor(partialPath.segments.length / 2))].location.offset;
176
- var sampleOffset = (offset1 + offset2) / 3;
177
- var originOffset1 = fullPath.getNearestLocation(partialPath.getPointAt(sampleOffset)).offset;
178
- var originOffset2 = fullPath.getNearestLocation(partialPath.getPointAt(2 * sampleOffset)).offset;
179
- return originOffset1 < originOffset2;
180
- }
181
- /** Remove self intersection when offset is negative by point direction dectection. */
182
- function removeIntersection(path) {
183
- if (path.closed) {
184
- var newPath = path.unite(path, { insert: false });
185
- if (newPath instanceof paper.CompoundPath) {
186
- newPath.children.filter(function (c) {
187
- if (c.segments.length > 1) {
188
- return !isSameDirection(c, path);
189
- }
190
- else {
191
- return true;
192
- }
193
- }).forEach(function (c) { return c.remove(); });
194
- return reduceSingleChildCompoundPath(newPath);
195
- }
196
- }
197
- return path;
198
- }
199
- function getSegments(path) {
200
- if (path instanceof paper.CompoundPath) {
201
- return path.children.map(function (c) { return c.segments; }).flat();
202
- }
203
- else {
204
- return path.segments;
205
- }
206
- }
207
- /**
208
- * Remove impossible segments in negative offset condition.
209
- */
210
- function removeOutsiders(newPath, path) {
211
- var segments = getSegments(newPath).slice();
212
- segments.forEach(function (segment) {
213
- if (!path.contains(segment.point)) {
214
- segment.remove();
215
- }
216
- });
217
- }
218
- function preparePath(path, offset) {
219
- var source = path.clone({ insert: false });
220
- source.reduce({});
221
- if (!path.clockwise) {
222
- source.reverse();
223
- offset = -offset;
224
- }
225
- return [source, offset];
226
- }
227
- function offsetSimpleShape(path, offset, join, limit) {
228
- var _a;
229
- var source;
230
- _a = preparePath(path, offset), source = _a[0], offset = _a[1];
231
- var curves = source.curves.slice();
232
- var offsetCurves = curves.map(function (curve) { return adaptiveOffsetCurve(curve, offset); }).flat();
233
- var raws = [];
234
- for (var i = 0; i < offsetCurves.length; i += 2) {
235
- raws.push(offsetCurves.slice(i, i + 2));
236
- }
237
- var segments = connectBeziers(raws, join, source, offset, limit).flat();
238
- var newPath = removeIntersection(new paper.Path({ segments: segments, insert: false, closed: path.closed }));
239
- newPath.reduce({});
240
- if (source.closed && ((source.clockwise && offset < 0) || (!source.clockwise && offset > 0))) {
241
- removeOutsiders(newPath, path);
242
- }
243
- // recovery path
244
- if (source.clockwise !== path.clockwise) {
245
- newPath.reverse();
246
- }
247
- return normalize(newPath);
248
- }
249
- function makeRoundCap(from, to, offset) {
250
- var origin = from.point.add(to.point).divide(2);
251
- var normal = to.point.subtract(from.point).rotate(-90, new paper.Point(0, 0)).normalize(offset);
252
- var through = origin.add(normal);
253
- var arc = new paper.Path.Arc({ from: from.point, to: to.point, through: through, insert: false });
254
- return arc.segments;
255
- }
256
- function connectSide(outer, inner, offset, cap) {
257
- if (outer instanceof paper.CompoundPath) {
258
- var cs = outer.children.map(function (c) { return ({ c: c, a: Math.abs(c.area) }); });
259
- cs = cs.sort(function (c1, c2) { return c2.a - c1.a; });
260
- outer = cs[0].c;
261
- }
262
- var oSegments = outer.segments.slice();
263
- var iSegments = inner.segments.slice();
264
- switch (cap) {
265
- case 'round':
266
- var heads = makeRoundCap(iSegments[iSegments.length - 1], oSegments[0], offset);
267
- var tails = makeRoundCap(oSegments[oSegments.length - 1], iSegments[0], offset);
268
- var result = new paper.Path({ segments: heads.concat(oSegments, tails, iSegments), closed: true, insert: false });
269
- result.reduce({});
270
- return result;
271
- default: return new paper.Path({ segments: oSegments.concat(iSegments), closed: true, insert: false });
272
- }
273
- }
274
- function offsetSimpleStroke(path, offset, join, cap, limit) {
275
- offset = path.clockwise ? offset : -offset;
276
- var positiveOffset = offsetSimpleShape(path, offset, join, limit);
277
- var negativeOffset = offsetSimpleShape(path, -offset, join, limit);
278
- if (path.closed) {
279
- return positiveOffset.subtract(negativeOffset, { insert: false });
280
- }
281
- else {
282
- var inner = negativeOffset;
283
- var holes = new Array();
284
- if (negativeOffset instanceof paper.CompoundPath) {
285
- holes = negativeOffset.children.filter(function (c) { return c.closed; });
286
- holes.forEach(function (h) { return h.remove(); });
287
- inner = negativeOffset.children[0];
288
- }
289
- inner.reverse();
290
- var final = connectSide(positiveOffset, inner, offset, cap);
291
- if (holes.length > 0) {
292
- for (var _i = 0, holes_1 = holes; _i < holes_1.length; _i++) {
293
- var hole = holes_1[_i];
294
- final = final.subtract(hole, { insert: false });
295
- }
296
- }
297
- return final;
298
- }
299
- }
300
- function getNonSelfItersectionPath(path) {
301
- if (path.closed) {
302
- return path.unite(path, { insert: false });
303
- }
304
- return path;
305
- }
306
- function offsetPath(path, offset, join, limit) {
307
- var nonSIPath = getNonSelfItersectionPath(path);
308
- var result = nonSIPath;
309
- if (nonSIPath instanceof paper.Path) {
310
- result = offsetSimpleShape(nonSIPath, offset, join, limit);
311
- }
312
- else {
313
- var offsetParts = nonSIPath.children.map(function (c) {
314
- if (c.segments.length > 1) {
315
- if (!isSameDirection(c, path)) {
316
- c.reverse();
317
- }
318
- var offseted = offsetSimpleShape(c, offset, join, limit);
319
- offseted = normalize(offseted);
320
- if (offseted.clockwise !== c.clockwise) {
321
- offseted.reverse();
322
- }
323
- if (offseted instanceof paper.CompoundPath) {
324
- offseted.applyMatrix = true;
325
- return offseted.children;
326
- }
327
- else {
328
- return offseted;
329
- }
330
- }
331
- else {
332
- return null;
333
- }
334
- });
335
- var children = offsetParts.flat().filter(function (c) { return !!c; });
336
- result = new paper.CompoundPath({ children: children, insert: false });
337
- }
338
- result.copyAttributes(nonSIPath, false);
339
- result.remove();
340
- return result;
341
- }
342
- function offsetStroke(path, offset, join, cap, limit) {
343
- var nonSIPath = getNonSelfItersectionPath(path);
344
- var result = nonSIPath;
345
- if (nonSIPath instanceof paper.Path) {
346
- result = offsetSimpleStroke(nonSIPath, offset, join, cap, limit);
347
- }
348
- else {
349
- var children = nonSIPath.children.flatMap(function (c) {
350
- return offsetSimpleStroke(c, offset, join, cap, limit);
351
- });
352
- result = children.reduce(function (c1, c2) { return c1.unite(c2, { insert: false }); });
353
- }
354
- result.strokeWidth = 0;
355
- result.fillColor = nonSIPath.strokeColor;
356
- result.shadowBlur = nonSIPath.shadowBlur;
357
- result.shadowColor = nonSIPath.shadowColor;
358
- result.shadowOffset = nonSIPath.shadowOffset;
359
- return result;
360
- }
748
+ function resolveOptions(options) {
749
+ var _a, _b, _c, _d;
750
+ return {
751
+ join: (_a = options === null || options === void 0 ? void 0 : options.join) !== null && _a !== void 0 ? _a : 'miter',
752
+ cap: (_b = options === null || options === void 0 ? void 0 : options.cap) !== null && _b !== void 0 ? _b : 'butt',
753
+ limit: (_c = options === null || options === void 0 ? void 0 : options.limit) !== null && _c !== void 0 ? _c : 10,
754
+ algorithm: (_d = options === null || options === void 0 ? void 0 : options.algorithm) !== null && _d !== void 0 ? _d : 'auto',
755
+ };
756
+ }
757
+ function insertResult(source, result, options) {
758
+ if (!options || options.insert !== false) {
759
+ (source.parent || paper.project.activeLayer).addChild(result);
760
+ }
761
+ }
762
+ function offset(path, distance, options) {
763
+ var resolvedOptions = resolveOptions(options);
764
+ var newPath = offsetPath(path, distance, resolvedOptions.join, resolvedOptions.limit, resolvedOptions.algorithm);
765
+ insertResult(path, newPath, options);
766
+ return newPath;
767
+ }
768
+ function offsetStroke(path, distance, options) {
769
+ var resolvedOptions = resolveOptions(options);
770
+ var newPath = offsetStroke$1(path, distance, resolvedOptions.join, resolvedOptions.cap, resolvedOptions.limit, resolvedOptions.algorithm);
771
+ insertResult(path, newPath, options);
772
+ return newPath;
773
+ }
774
+ function analyze(source, result, distance, options) {
775
+ return analyzeOffsetQuality(source, result, distance, options || {});
776
+ }
777
+ var PaperOffset = /** @class */ (function () {
778
+ function PaperOffset() {
779
+ }
780
+ PaperOffset.offset = function (path, distance, options) {
781
+ return offset(path, distance, options);
782
+ };
783
+ PaperOffset.offsetStroke = function (path, distance, options) {
784
+ return offsetStroke(path, distance, options);
785
+ };
786
+ PaperOffset.analyze = function (source, result, distance, options) {
787
+ return analyze(source, result, distance, options);
788
+ };
789
+ return PaperOffset;
790
+ }());
791
+ /**
792
+ * @deprecated EXTEND existing paper module is not recommend anymore
793
+ */
794
+ function ExtendPaperJs(paperNs) {
795
+ paperNs.Path.prototype.offset = function (distance, options) {
796
+ return offset(this, distance, options);
797
+ };
798
+ paperNs.Path.prototype.offsetStroke = function (distance, options) {
799
+ return offsetStroke(this, distance, options);
800
+ };
801
+ paperNs.CompoundPath.prototype.offset = function (distance, options) {
802
+ return offset(this, distance, options);
803
+ };
804
+ paperNs.CompoundPath.prototype.offsetStroke = function (distance, options) {
805
+ return offsetStroke(this, distance, options);
806
+ };
807
+ }
361
808
 
362
- var PaperOffset = /** @class */ (function () {
363
- function PaperOffset() {
364
- }
365
- PaperOffset.offset = function (path, offset, options) {
366
- options = options || {};
367
- var newPath = offsetPath(path, offset, options.join || 'miter', options.limit || 10);
368
- if (options.insert === undefined) {
369
- options.insert = true;
370
- }
371
- if (options.insert) {
372
- (path.parent || paper.project.activeLayer).addChild(newPath);
373
- }
374
- return newPath;
375
- };
376
- PaperOffset.offsetStroke = function (path, offset, options) {
377
- options = options || {};
378
- var newPath = offsetStroke(path, offset, options.join || 'miter', options.cap || 'butt', options.limit || 10);
379
- if (options.insert === undefined) {
380
- options.insert = true;
381
- }
382
- if (options.insert) {
383
- (path.parent || paper.project.activeLayer).addChild(newPath);
384
- }
385
- return newPath;
386
- };
387
- return PaperOffset;
388
- }());
389
- /**
390
- * @deprecated EXTEND existing paper module is not recommend anymore
391
- */
392
- function ExtendPaperJs(paperNs) {
393
- paperNs.Path.prototype.offset = function (offset, options) {
394
- return PaperOffset.offset(this, offset, options);
395
- };
396
- paperNs.Path.prototype.offsetStroke = function (offset, options) {
397
- return PaperOffset.offsetStroke(this, offset, options);
398
- };
399
- paperNs.CompoundPath.prototype.offset = function (offset, options) {
400
- return PaperOffset.offset(this, offset, options);
401
- };
402
- paperNs.CompoundPath.prototype.offsetStroke = function (offset, options) {
403
- return PaperOffset.offsetStroke(this, offset, options);
404
- };
405
- }
809
+ exports.PaperOffset = PaperOffset;
810
+ exports.analyze = analyze;
811
+ exports.default = ExtendPaperJs;
812
+ exports.extendPaperJs = ExtendPaperJs;
813
+ exports.offset = offset;
814
+ exports.offsetStroke = offsetStroke;
406
815
 
407
- exports.PaperOffset = PaperOffset;
408
- exports.default = ExtendPaperJs;
816
+ Object.defineProperty(exports, '__esModule', { value: true });
409
817
 
410
- Object.defineProperty(exports, '__esModule', { value: true });
818
+ }));
411
819
 
412
- })));
820
+ ;(function(global) {
821
+ if (!global || !global.paperjsOffset) return;
822
+ global.PaperOffset = global.paperjsOffset;
823
+ if (global.paper && typeof global.paperjsOffset.default === 'function') {
824
+ global.paperjsOffset.default(global.paper);
825
+ }
826
+ })(typeof globalThis !== 'undefined' ? globalThis : typeof self !== 'undefined' ? self : this);
413
827
  //# sourceMappingURL=index.umd.js.map