leafer-ui 1.0.0-beta.8 → 1.0.0-rc.2

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.
@@ -0,0 +1,2652 @@
1
+ import { LeafList, DataHelper, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, Bounds, LeafBoundsHelper, BoundsHelper, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, Platform, AnimateEvent, ResizeEvent, Creator, LeaferCanvasBase, Cursor, canvasSizeAttrs, canvasPatch, InteractionHelper, MathHelper, InteractionBase, LeaferImage, FileHelper, MatrixHelper, ImageEvent, PointHelper, TaskProcessor } from '@leafer/core';
2
+ export * from '@leafer/core';
3
+ export { LeaferImage } from '@leafer/core';
4
+ import { ColorConvert as ColorConvert$1, Paint, Effect, TextConvert as TextConvert$1, Export as Export$1 } from '@leafer-ui/core';
5
+ export * from '@leafer-ui/core';
6
+
7
+ class Watcher {
8
+ get childrenChanged() { return this.hasAdd || this.hasRemove || this.hasVisible; }
9
+ get updatedList() {
10
+ if (this.hasRemove) {
11
+ const updatedList = new LeafList();
12
+ this.__updatedList.list.forEach(item => { if (item.leafer)
13
+ updatedList.push(item); });
14
+ return updatedList;
15
+ }
16
+ else {
17
+ return this.__updatedList;
18
+ }
19
+ }
20
+ constructor(target, userConfig) {
21
+ this.totalTimes = 0;
22
+ this.config = {};
23
+ this.__updatedList = new LeafList();
24
+ this.target = target;
25
+ if (userConfig)
26
+ this.config = DataHelper.default(userConfig, this.config);
27
+ this.__listenEvents();
28
+ }
29
+ start() {
30
+ if (this.disabled)
31
+ return;
32
+ this.running = true;
33
+ }
34
+ stop() {
35
+ this.running = false;
36
+ }
37
+ disable() {
38
+ this.stop();
39
+ this.__removeListenEvents();
40
+ this.disabled = true;
41
+ }
42
+ update() {
43
+ this.changed = true;
44
+ if (this.running)
45
+ this.target.emit(RenderEvent.REQUEST);
46
+ }
47
+ __onAttrChange(event) {
48
+ this.__updatedList.push(event.target);
49
+ this.update();
50
+ }
51
+ __onChildEvent(event) {
52
+ if (event.type === ChildEvent.ADD) {
53
+ this.hasAdd = true;
54
+ this.__pushChild(event.child);
55
+ }
56
+ else {
57
+ this.hasRemove = true;
58
+ this.__updatedList.push(event.parent);
59
+ }
60
+ this.update();
61
+ }
62
+ __pushChild(child) {
63
+ this.__updatedList.push(child);
64
+ if (child.isBranch)
65
+ this.__loopChildren(child);
66
+ }
67
+ __loopChildren(parent) {
68
+ const { children } = parent;
69
+ for (let i = 0, len = children.length; i < len; i++)
70
+ this.__pushChild(children[i]);
71
+ }
72
+ __onRquestData() {
73
+ this.target.emitEvent(new WatchEvent(WatchEvent.DATA, { updatedList: this.updatedList }));
74
+ this.__updatedList = new LeafList();
75
+ this.totalTimes++;
76
+ this.changed = false;
77
+ this.hasVisible = false;
78
+ this.hasRemove = false;
79
+ this.hasAdd = false;
80
+ }
81
+ __listenEvents() {
82
+ const { target } = this;
83
+ this.__eventIds = [
84
+ target.on_(PropertyEvent.CHANGE, this.__onAttrChange, this),
85
+ target.on_([ChildEvent.ADD, ChildEvent.REMOVE], this.__onChildEvent, this),
86
+ target.on_(WatchEvent.REQUEST, this.__onRquestData, this)
87
+ ];
88
+ }
89
+ __removeListenEvents() {
90
+ this.target.off_(this.__eventIds);
91
+ }
92
+ destroy() {
93
+ if (this.target) {
94
+ this.stop();
95
+ this.__removeListenEvents();
96
+ this.target = null;
97
+ this.__updatedList = null;
98
+ }
99
+ }
100
+ }
101
+
102
+ const { updateAllWorldMatrix: updateAllWorldMatrix$1, updateAllWorldOpacity } = LeafHelper;
103
+ const { pushAllChildBranch, pushAllParent } = BranchHelper;
104
+ function updateMatrix(updateList, levelList) {
105
+ let layout;
106
+ updateList.list.forEach(leaf => {
107
+ layout = leaf.__layout;
108
+ if (levelList.without(leaf) && !layout.useZoomProxy) {
109
+ if (layout.matrixChanged) {
110
+ updateAllWorldMatrix$1(leaf);
111
+ levelList.push(leaf);
112
+ if (leaf.isBranch)
113
+ pushAllChildBranch(leaf, levelList);
114
+ pushAllParent(leaf, levelList);
115
+ }
116
+ else if (layout.boundsChanged) {
117
+ levelList.push(leaf);
118
+ if (leaf.isBranch)
119
+ leaf.__tempNumber = 0;
120
+ pushAllParent(leaf, levelList);
121
+ }
122
+ }
123
+ });
124
+ }
125
+ function updateBounds(boundsList) {
126
+ let itemList, branch;
127
+ boundsList.sort(true);
128
+ boundsList.levels.forEach(level => {
129
+ itemList = boundsList.levelMap[level];
130
+ for (let i = 0, len = itemList.length; i < len; i++) {
131
+ branch = itemList[i];
132
+ if (branch.isBranch && branch.__tempNumber) {
133
+ for (let j = 0, jLen = branch.children.length; j < jLen; j++) {
134
+ if (!branch.children[j].isBranch) {
135
+ branch.children[j].__updateWorldBounds();
136
+ }
137
+ }
138
+ }
139
+ branch.__updateWorldBounds();
140
+ }
141
+ });
142
+ }
143
+ function updateChange(updateList) {
144
+ updateList.list.forEach(leaf => {
145
+ if (leaf.__layout.opacityChanged)
146
+ updateAllWorldOpacity(leaf);
147
+ leaf.__updateChange();
148
+ });
149
+ }
150
+
151
+ const { worldBounds } = LeafBoundsHelper;
152
+ const { setByListWithHandle } = BoundsHelper;
153
+ class LayoutBlockData {
154
+ constructor(list) {
155
+ this.updatedBounds = new Bounds();
156
+ this.beforeBounds = new Bounds();
157
+ this.afterBounds = new Bounds();
158
+ if (list instanceof Array)
159
+ list = new LeafList(list);
160
+ this.updatedList = list;
161
+ }
162
+ setBefore() {
163
+ setByListWithHandle(this.beforeBounds, this.updatedList.list, worldBounds);
164
+ }
165
+ setAfter() {
166
+ setByListWithHandle(this.afterBounds, this.updatedList.list, worldBounds);
167
+ this.updatedBounds.setByList([this.beforeBounds, this.afterBounds]);
168
+ }
169
+ merge(data) {
170
+ this.updatedList.pushList(data.updatedList.list);
171
+ this.beforeBounds.add(data.beforeBounds);
172
+ this.afterBounds.add(data.afterBounds);
173
+ this.updatedBounds.add(data.updatedBounds);
174
+ }
175
+ destroy() {
176
+ this.updatedList = null;
177
+ }
178
+ }
179
+
180
+ const { updateAllWorldMatrix, updateAllChange } = LeafHelper;
181
+ const { pushAllBranchStack, updateWorldBoundsByBranchStack } = BranchHelper;
182
+ const debug$2 = Debug.get('Layouter');
183
+ class Layouter {
184
+ constructor(target, userConfig) {
185
+ this.totalTimes = 0;
186
+ this.config = {};
187
+ this.__levelList = new LeafLevelList();
188
+ this.target = target;
189
+ if (userConfig)
190
+ this.config = DataHelper.default(userConfig, this.config);
191
+ this.__listenEvents();
192
+ }
193
+ start() {
194
+ if (this.disabled)
195
+ return;
196
+ this.running = true;
197
+ }
198
+ stop() {
199
+ this.running = false;
200
+ }
201
+ disable() {
202
+ this.stop();
203
+ this.__removeListenEvents();
204
+ this.disabled = true;
205
+ }
206
+ layout() {
207
+ if (!this.running)
208
+ return;
209
+ const { target } = this;
210
+ this.times = 0;
211
+ try {
212
+ target.emit(LayoutEvent.START);
213
+ this.layoutOnce();
214
+ target.emitEvent(new LayoutEvent(LayoutEvent.END, this.layoutedBlocks, this.times));
215
+ }
216
+ catch (e) {
217
+ debug$2.error(e);
218
+ }
219
+ this.layoutedBlocks = null;
220
+ }
221
+ layoutAgain() {
222
+ if (this.layouting) {
223
+ this.waitAgain = true;
224
+ }
225
+ else {
226
+ this.layoutOnce();
227
+ }
228
+ }
229
+ layoutOnce() {
230
+ if (this.layouting)
231
+ return debug$2.warn('layouting');
232
+ if (this.times > 3)
233
+ return debug$2.warn('layout max times');
234
+ this.times++;
235
+ this.totalTimes++;
236
+ this.layouting = true;
237
+ this.target.emit(WatchEvent.REQUEST);
238
+ if (this.totalTimes > 1) {
239
+ this.partLayout();
240
+ }
241
+ else {
242
+ this.fullLayout();
243
+ }
244
+ this.layouting = false;
245
+ if (this.waitAgain) {
246
+ this.waitAgain = false;
247
+ this.layoutOnce();
248
+ }
249
+ }
250
+ partLayout() {
251
+ var _a;
252
+ if (!((_a = this.__updatedList) === null || _a === void 0 ? void 0 : _a.length))
253
+ return;
254
+ const t = Run.start('PartLayout');
255
+ const { target, __updatedList: updateList } = this;
256
+ const { BEFORE, LAYOUT, AFTER } = LayoutEvent;
257
+ const blocks = this.getBlocks(updateList);
258
+ blocks.forEach(item => { item.setBefore(); });
259
+ target.emitEvent(new LayoutEvent(BEFORE, blocks, this.times));
260
+ updateList.sort();
261
+ updateMatrix(updateList, this.__levelList);
262
+ updateBounds(this.__levelList);
263
+ updateChange(updateList);
264
+ blocks.forEach(item => item.setAfter());
265
+ target.emitEvent(new LayoutEvent(LAYOUT, blocks, this.times));
266
+ target.emitEvent(new LayoutEvent(AFTER, blocks, this.times));
267
+ this.addBlocks(blocks);
268
+ this.__levelList.reset();
269
+ this.__updatedList = null;
270
+ Run.end(t);
271
+ }
272
+ fullLayout() {
273
+ const t = Run.start('FullLayout');
274
+ const { target } = this;
275
+ const { BEFORE, LAYOUT, AFTER } = LayoutEvent;
276
+ const blocks = this.getBlocks(new LeafList(target));
277
+ target.emitEvent(new LayoutEvent(BEFORE, blocks, this.times));
278
+ Layouter.fullLayout(target);
279
+ blocks.forEach(item => { item.setAfter(); });
280
+ target.emitEvent(new LayoutEvent(LAYOUT, blocks, this.times));
281
+ target.emitEvent(new LayoutEvent(AFTER, blocks, this.times));
282
+ this.addBlocks(blocks);
283
+ Run.end(t);
284
+ }
285
+ static fullLayout(target) {
286
+ updateAllWorldMatrix(target);
287
+ if (target.isBranch) {
288
+ const branchStack = [target];
289
+ pushAllBranchStack(target, branchStack);
290
+ updateWorldBoundsByBranchStack(branchStack);
291
+ }
292
+ else {
293
+ target.__updateWorldBounds();
294
+ }
295
+ updateAllChange(target);
296
+ }
297
+ createBlock(data) {
298
+ return new LayoutBlockData(data);
299
+ }
300
+ getBlocks(list) {
301
+ return [this.createBlock(list)];
302
+ }
303
+ addBlocks(current) {
304
+ this.layoutedBlocks ? this.layoutedBlocks.push(...current) : this.layoutedBlocks = current;
305
+ }
306
+ __onReceiveWatchData(event) {
307
+ this.__updatedList = event.data.updatedList;
308
+ }
309
+ __listenEvents() {
310
+ const { target } = this;
311
+ this.__eventIds = [
312
+ target.on_(LayoutEvent.REQUEST, this.layout, this),
313
+ target.on_(LayoutEvent.AGAIN, this.layoutAgain, this),
314
+ target.on_(WatchEvent.DATA, this.__onReceiveWatchData, this)
315
+ ];
316
+ }
317
+ __removeListenEvents() {
318
+ this.target.off_(this.__eventIds);
319
+ }
320
+ destroy() {
321
+ if (this.target) {
322
+ this.stop();
323
+ this.__removeListenEvents();
324
+ this.target = null;
325
+ this.config = null;
326
+ }
327
+ }
328
+ }
329
+
330
+ const debug$1 = Debug.get('Renderer');
331
+ class Renderer {
332
+ get needFill() { return !!(!this.canvas.allowBackgroundColor && this.config.fill); }
333
+ constructor(target, canvas, userConfig) {
334
+ this.FPS = 60;
335
+ this.totalTimes = 0;
336
+ this.times = 0;
337
+ this.config = {
338
+ usePartRender: true,
339
+ maxFPS: 60
340
+ };
341
+ this.target = target;
342
+ this.canvas = canvas;
343
+ if (userConfig)
344
+ this.config = DataHelper.default(userConfig, this.config);
345
+ this.__listenEvents();
346
+ this.__requestRender();
347
+ }
348
+ start() {
349
+ this.running = true;
350
+ }
351
+ stop() {
352
+ this.running = false;
353
+ }
354
+ update() {
355
+ this.changed = true;
356
+ }
357
+ requestLayout() {
358
+ this.target.emit(LayoutEvent.REQUEST);
359
+ }
360
+ render(callback) {
361
+ if (!(this.running && this.canvas.view)) {
362
+ this.changed = true;
363
+ return;
364
+ }
365
+ const { target } = this;
366
+ this.times = 0;
367
+ this.totalBounds = new Bounds();
368
+ debug$1.log(target.innerName, '--->');
369
+ try {
370
+ this.emitRender(RenderEvent.START);
371
+ this.renderOnce(callback);
372
+ this.emitRender(RenderEvent.END, this.totalBounds);
373
+ ImageManager.clearRecycled();
374
+ }
375
+ catch (e) {
376
+ this.rendering = false;
377
+ debug$1.error(e);
378
+ }
379
+ debug$1.log('-------------|');
380
+ }
381
+ renderAgain() {
382
+ if (this.rendering) {
383
+ this.waitAgain = true;
384
+ }
385
+ else {
386
+ this.renderOnce();
387
+ }
388
+ }
389
+ renderOnce(callback) {
390
+ if (this.rendering)
391
+ return debug$1.warn('rendering');
392
+ if (this.times > 3)
393
+ return debug$1.warn('render max times');
394
+ this.times++;
395
+ this.totalTimes++;
396
+ this.rendering = true;
397
+ this.changed = false;
398
+ this.renderBounds = new Bounds();
399
+ this.renderOptions = {};
400
+ if (callback) {
401
+ this.emitRender(RenderEvent.BEFORE);
402
+ callback();
403
+ }
404
+ else {
405
+ this.requestLayout();
406
+ this.emitRender(RenderEvent.BEFORE);
407
+ if (this.config.usePartRender && this.totalTimes > 1) {
408
+ this.partRender();
409
+ }
410
+ else {
411
+ this.fullRender();
412
+ }
413
+ }
414
+ this.emitRender(RenderEvent.RENDER, this.renderBounds, this.renderOptions);
415
+ this.emitRender(RenderEvent.AFTER, this.renderBounds, this.renderOptions);
416
+ this.updateBlocks = null;
417
+ this.rendering = false;
418
+ if (this.waitAgain) {
419
+ this.waitAgain = false;
420
+ this.renderOnce();
421
+ }
422
+ }
423
+ partRender() {
424
+ const { canvas, updateBlocks: list } = this;
425
+ if (!list)
426
+ return debug$1.warn('PartRender: need update attr');
427
+ if (list.some(block => block.includes(this.target.__world)))
428
+ this.mergeBlocks();
429
+ list.forEach(block => { if (canvas.bounds.hit(block) && !block.isEmpty())
430
+ this.clipRender(block); });
431
+ }
432
+ clipRender(block) {
433
+ const t = Run.start('PartRender');
434
+ const { canvas } = this;
435
+ const bounds = block.getIntersect(canvas.bounds);
436
+ const includes = block.includes(this.target.__world);
437
+ const realBounds = new Bounds().copy(bounds);
438
+ canvas.save();
439
+ if (includes && !Debug.showRepaint) {
440
+ canvas.clear();
441
+ }
442
+ else {
443
+ bounds.spread(1 + 1 / this.canvas.pixelRatio).ceil();
444
+ canvas.clearWorld(bounds, true);
445
+ canvas.clipWorld(bounds, true);
446
+ }
447
+ this.__render(bounds, realBounds);
448
+ canvas.restore();
449
+ Run.end(t);
450
+ }
451
+ fullRender() {
452
+ const t = Run.start('FullRender');
453
+ const { canvas } = this;
454
+ canvas.save();
455
+ canvas.clear();
456
+ this.__render(canvas.bounds);
457
+ canvas.restore();
458
+ Run.end(t);
459
+ }
460
+ __render(bounds, realBounds) {
461
+ const options = (bounds === null || bounds === void 0 ? void 0 : bounds.includes(this.target.__world)) ? {} : { bounds };
462
+ if (this.needFill)
463
+ this.canvas.fillWorld(bounds, this.config.fill);
464
+ if (Debug.showRepaint)
465
+ this.canvas.strokeWorld(bounds, 'red');
466
+ this.target.__render(this.canvas, options);
467
+ this.renderBounds = realBounds || bounds;
468
+ this.renderOptions = options;
469
+ this.totalBounds.isEmpty() ? this.totalBounds = this.renderBounds : this.totalBounds.add(this.renderBounds);
470
+ if (Debug.showHitView)
471
+ this.renderHitView(options);
472
+ if (Debug.showBoundsView)
473
+ this.renderBoundsView(options);
474
+ this.canvas.updateRender();
475
+ }
476
+ renderHitView(_options) { }
477
+ renderBoundsView(_options) { }
478
+ addBlock(block) {
479
+ if (!this.updateBlocks)
480
+ this.updateBlocks = [];
481
+ this.updateBlocks.push(block);
482
+ }
483
+ mergeBlocks() {
484
+ const { updateBlocks: list } = this;
485
+ if (list) {
486
+ const bounds = new Bounds();
487
+ bounds.setByList(list);
488
+ list.length = 0;
489
+ list.push(bounds);
490
+ }
491
+ }
492
+ __requestRender() {
493
+ const startTime = Date.now();
494
+ Platform.requestRender(() => {
495
+ this.FPS = Math.min(60, Math.ceil(1000 / (Date.now() - startTime)));
496
+ if (this.changed) {
497
+ if (this.running && this.canvas.view)
498
+ this.render();
499
+ }
500
+ if (this.running)
501
+ this.target.emit(AnimateEvent.FRAME);
502
+ if (this.target)
503
+ this.__requestRender();
504
+ });
505
+ }
506
+ __onResize(e) {
507
+ if (this.canvas.unreal)
508
+ return;
509
+ if (e.bigger || !e.samePixelRatio) {
510
+ const { width, height } = e.old;
511
+ const bounds = new Bounds(0, 0, width, height);
512
+ if (!bounds.includes(this.target.__world) || this.needFill || !e.samePixelRatio) {
513
+ this.addBlock(this.canvas.bounds);
514
+ this.target.forceUpdate('blendMode');
515
+ }
516
+ }
517
+ }
518
+ __onLayoutEnd(event) {
519
+ if (event.data)
520
+ event.data.map(item => {
521
+ let empty;
522
+ if (item.updatedList)
523
+ item.updatedList.list.some(leaf => {
524
+ empty = (!leaf.__world.width || !leaf.__world.height);
525
+ if (empty) {
526
+ if (!leaf.isLeafer)
527
+ debug$1.warn(leaf.innerName, ': empty');
528
+ empty = (!leaf.isBranch || leaf.isBranchLeaf);
529
+ }
530
+ return empty;
531
+ });
532
+ this.addBlock(empty ? this.canvas.bounds : item.updatedBounds);
533
+ });
534
+ }
535
+ emitRender(type, bounds, options) {
536
+ this.target.emitEvent(new RenderEvent(type, this.times, bounds, options));
537
+ }
538
+ __listenEvents() {
539
+ const { target } = this;
540
+ this.__eventIds = [
541
+ target.on_(RenderEvent.REQUEST, this.update, this),
542
+ target.on_(LayoutEvent.END, this.__onLayoutEnd, this),
543
+ target.on_(RenderEvent.AGAIN, this.renderAgain, this),
544
+ target.on_(ResizeEvent.RESIZE, this.__onResize, this)
545
+ ];
546
+ }
547
+ __removeListenEvents() {
548
+ this.target.off_(this.__eventIds);
549
+ }
550
+ destroy() {
551
+ if (this.target) {
552
+ this.stop();
553
+ this.__removeListenEvents();
554
+ this.target = null;
555
+ this.canvas = null;
556
+ this.config = null;
557
+ }
558
+ }
559
+ }
560
+
561
+ const { hitRadiusPoint } = BoundsHelper;
562
+ class FindPath {
563
+ constructor(target, selector) {
564
+ this.target = target;
565
+ this.selector = selector;
566
+ }
567
+ getByPoint(hitPoint, hitRadius, options) {
568
+ if (!hitRadius)
569
+ hitRadius = 0;
570
+ if (!options)
571
+ options = {};
572
+ const through = options.through || false;
573
+ const ignoreHittable = options.ignoreHittable || false;
574
+ this.exclude = options.exclude || null;
575
+ this.point = { x: hitPoint.x, y: hitPoint.y, radiusX: hitRadius, radiusY: hitRadius };
576
+ this.findList = [];
577
+ this.eachFind(this.target.children, this.target.__onlyHitMask);
578
+ const list = this.findList;
579
+ const leaf = this.getBestMatchLeaf();
580
+ const path = ignoreHittable ? this.getPath(leaf) : this.getHitablePath(leaf);
581
+ this.clear();
582
+ return through ? { path, leaf, throughPath: list.length ? this.getThroughPath(list) : path } : { path, leaf };
583
+ }
584
+ getBestMatchLeaf() {
585
+ const { findList: targets } = this;
586
+ if (targets.length > 1) {
587
+ let find;
588
+ this.findList = [];
589
+ const { x, y } = this.point;
590
+ const point = { x, y, radiusX: 0, radiusY: 0 };
591
+ for (let i = 0, len = targets.length; i < len; i++) {
592
+ find = targets[i];
593
+ if (LeafHelper.worldHittable(find)) {
594
+ this.hitChild(find, point);
595
+ if (this.findList.length)
596
+ return this.findList[0];
597
+ }
598
+ }
599
+ }
600
+ return targets[0];
601
+ }
602
+ getPath(leaf) {
603
+ const path = new LeafList();
604
+ while (leaf) {
605
+ path.push(leaf);
606
+ leaf = leaf.parent;
607
+ }
608
+ path.push(this.target);
609
+ return path;
610
+ }
611
+ getHitablePath(leaf) {
612
+ const path = this.getPath(leaf);
613
+ let item, hittablePath = new LeafList();
614
+ for (let i = path.list.length - 1; i > -1; i--) {
615
+ item = path.list[i];
616
+ if (!item.__.hittable)
617
+ break;
618
+ hittablePath.unshift(item);
619
+ if (!item.__.hitChildren)
620
+ break;
621
+ }
622
+ return hittablePath;
623
+ }
624
+ getThroughPath(list) {
625
+ const throughPath = new LeafList();
626
+ const pathList = [];
627
+ for (let i = list.length - 1; i > -1; i--) {
628
+ pathList.push(this.getPath(list[i]));
629
+ }
630
+ let path, nextPath, leaf;
631
+ for (let i = 0, len = pathList.length; i < len; i++) {
632
+ path = pathList[i], nextPath = pathList[i + 1];
633
+ for (let j = 0, jLen = path.length; j < jLen; j++) {
634
+ leaf = path.list[j];
635
+ if (nextPath && nextPath.has(leaf))
636
+ break;
637
+ throughPath.push(leaf);
638
+ }
639
+ }
640
+ return throughPath;
641
+ }
642
+ eachFind(children, hitMask) {
643
+ let child, hit;
644
+ const { point } = this, len = children.length;
645
+ for (let i = len - 1; i > -1; i--) {
646
+ child = children[i];
647
+ if (!child.__.visible || (hitMask && !child.__.isMask))
648
+ continue;
649
+ hit = child.__.hitRadius ? true : hitRadiusPoint(child.__world, point);
650
+ if (child.isBranch) {
651
+ if (hit || child.__ignoreHitWorld) {
652
+ this.eachFind(child.children, child.__onlyHitMask);
653
+ if (child.isBranchLeaf && !this.findList.length)
654
+ this.hitChild(child, point);
655
+ }
656
+ }
657
+ else {
658
+ if (hit)
659
+ this.hitChild(child, point);
660
+ }
661
+ }
662
+ }
663
+ hitChild(child, point) {
664
+ if (this.exclude && this.exclude.has(child))
665
+ return;
666
+ if (child.__hitWorld(point))
667
+ this.findList.push(child);
668
+ }
669
+ clear() {
670
+ this.point = null;
671
+ this.findList = null;
672
+ this.exclude = null;
673
+ }
674
+ destroy() {
675
+ this.clear();
676
+ }
677
+ }
678
+
679
+ class Selector {
680
+ constructor(target, userConfig) {
681
+ this.config = {};
682
+ this.innerIdList = {};
683
+ this.idList = {};
684
+ this.classNameList = {};
685
+ this.tagNameList = {};
686
+ this.target = target;
687
+ if (userConfig)
688
+ this.config = DataHelper.default(userConfig, this.config);
689
+ this.findPath = new FindPath(target, this);
690
+ this.__listenEvents();
691
+ }
692
+ getByPoint(hitPoint, hitRadius, options) {
693
+ if (Platform.name === 'node')
694
+ this.target.emit(LayoutEvent.CHECK_UPDATE);
695
+ return this.findPath.getByPoint(hitPoint, hitRadius, options);
696
+ }
697
+ find(name, branch) {
698
+ if (typeof name === 'number') {
699
+ return this.getByInnerId(name, branch);
700
+ }
701
+ else if (name.startsWith('#')) {
702
+ return this.getById(name.substring(1), branch);
703
+ }
704
+ else if (name.startsWith('.')) {
705
+ return this.getByClassName(name.substring(1), branch);
706
+ }
707
+ else {
708
+ return this.getByTagName(name, branch);
709
+ }
710
+ }
711
+ getByInnerId(name, branch) {
712
+ let cache = this.innerIdList[name];
713
+ if (cache)
714
+ return cache;
715
+ if (!branch)
716
+ branch = this.target;
717
+ let find;
718
+ this.loopFind(branch, (leaf) => {
719
+ if (leaf.innerId === name) {
720
+ find = leaf;
721
+ this.innerIdList[name] = find;
722
+ return true;
723
+ }
724
+ else {
725
+ return false;
726
+ }
727
+ });
728
+ return find;
729
+ }
730
+ getById(name, branch) {
731
+ let cache = this.idList[name];
732
+ if (cache)
733
+ return cache;
734
+ if (!branch)
735
+ branch = this.target;
736
+ let find;
737
+ this.loopFind(branch, (leaf) => {
738
+ if (leaf.id === name) {
739
+ find = leaf;
740
+ this.idList[name] = find;
741
+ return true;
742
+ }
743
+ else {
744
+ return false;
745
+ }
746
+ });
747
+ return find;
748
+ }
749
+ getByClassName(name, branch) {
750
+ if (!branch)
751
+ branch = this.target;
752
+ let find = [];
753
+ this.loopFind(branch, (leaf) => {
754
+ if (leaf.className === name)
755
+ find.push(leaf);
756
+ return false;
757
+ });
758
+ return find;
759
+ }
760
+ getByTagName(name, branch) {
761
+ if (!branch)
762
+ branch = this.target;
763
+ let find = [];
764
+ this.loopFind(branch, (leaf) => {
765
+ if (leaf.__tag === name)
766
+ find.push(leaf);
767
+ return false;
768
+ });
769
+ return find;
770
+ }
771
+ loopFind(branch, find) {
772
+ if (find(branch))
773
+ return;
774
+ const { children } = branch;
775
+ for (let i = 0, len = children.length; i < len; i++) {
776
+ branch = children[i];
777
+ if (find(branch))
778
+ return;
779
+ if (branch.isBranch)
780
+ this.loopFind(branch, find);
781
+ }
782
+ }
783
+ __onRemoveChild(event) {
784
+ const target = event.target;
785
+ if (this.idList[target.id])
786
+ this.idList[target.id] = null;
787
+ if (this.innerIdList[target.id])
788
+ this.innerIdList[target.innerId] = null;
789
+ }
790
+ __listenEvents() {
791
+ this.__eventIds = [
792
+ this.target.on_(ChildEvent.REMOVE, this.__onRemoveChild, this)
793
+ ];
794
+ }
795
+ __removeListenEvents() {
796
+ this.target.off_(this.__eventIds);
797
+ this.__eventIds.length = 0;
798
+ }
799
+ destroy() {
800
+ if (this.__eventIds.length) {
801
+ this.__removeListenEvents();
802
+ this.findPath.destroy();
803
+ this.innerIdList = {};
804
+ this.idList = {};
805
+ this.classNameList = {};
806
+ this.tagNameList = {};
807
+ }
808
+ }
809
+ }
810
+
811
+ Object.assign(Creator, {
812
+ watcher: (target, options) => new Watcher(target, options),
813
+ layouter: (target, options) => new Layouter(target, options),
814
+ renderer: (target, canvas, options) => new Renderer(target, canvas, options),
815
+ selector: (target, options) => new Selector(target, options)
816
+ });
817
+ Platform.layout = Layouter.fullLayout;
818
+
819
+ const debug = Debug.get('LeaferCanvas');
820
+ class LeaferCanvas extends LeaferCanvasBase {
821
+ init() {
822
+ const { view } = this.config;
823
+ view ? this.__createViewFrom(view) : this.__createView();
824
+ const { style } = this.view;
825
+ style.display || (style.display = 'block');
826
+ this.parentView = this.view.parentElement;
827
+ if (Platform.syncDomFont && !this.parentView) {
828
+ this.view.style.display = 'none';
829
+ document.body.appendChild(this.view);
830
+ }
831
+ this.__createContext();
832
+ if (!this.autoLayout)
833
+ this.resize(this.config);
834
+ }
835
+ set backgroundColor(color) { this.view.style.backgroundColor = color; }
836
+ get backgroundColor() { return this.view.style.backgroundColor; }
837
+ set hittable(hittable) { this.view.style.pointerEvents = hittable ? 'auto' : 'none'; }
838
+ get hittable() { return this.view.style.pointerEvents !== 'none'; }
839
+ __createView() {
840
+ this.view = document.createElement('canvas');
841
+ }
842
+ setCursor(cursor) {
843
+ const list = [];
844
+ this.eachCursor(cursor, list);
845
+ if (typeof list[list.length - 1] === 'object')
846
+ list.push('default');
847
+ this.view.style.cursor = list.map(item => (typeof item === 'object') ? `url(${item.url}) ${item.x || 0} ${item.y || 0}` : item).join(',');
848
+ }
849
+ eachCursor(cursor, list, level = 0) {
850
+ level++;
851
+ if (cursor instanceof Array) {
852
+ cursor.forEach(item => this.eachCursor(item, list, level));
853
+ }
854
+ else {
855
+ const custom = typeof cursor === 'string' && Cursor.get(cursor);
856
+ if (custom && level < 2) {
857
+ this.eachCursor(custom, list, level);
858
+ }
859
+ else {
860
+ list.push(cursor);
861
+ }
862
+ }
863
+ }
864
+ __createViewFrom(inputView) {
865
+ let find = (typeof inputView === 'string') ? document.getElementById(inputView) : inputView;
866
+ if (find) {
867
+ if (find instanceof HTMLCanvasElement) {
868
+ this.view = find;
869
+ }
870
+ else {
871
+ let parent = find;
872
+ if (find === window || find === document) {
873
+ const div = document.createElement('div');
874
+ const { style } = div;
875
+ style.position = 'absolute';
876
+ style.top = style.bottom = style.left = style.right = '0px';
877
+ document.body.appendChild(div);
878
+ parent = div;
879
+ }
880
+ this.__createView();
881
+ const view = this.view;
882
+ if (parent.hasChildNodes()) {
883
+ const { style } = view;
884
+ style.position = 'absolute';
885
+ style.top = style.left = '0px';
886
+ parent.style.position || (parent.style.position = 'relative');
887
+ }
888
+ parent.appendChild(view);
889
+ }
890
+ }
891
+ else {
892
+ debug.error(`no id: ${inputView}`);
893
+ this.__createView();
894
+ }
895
+ }
896
+ updateViewSize() {
897
+ const { width, height, pixelRatio } = this;
898
+ const { style } = this.view;
899
+ style.width = width + 'px';
900
+ style.height = height + 'px';
901
+ this.view.width = width * pixelRatio;
902
+ this.view.height = height * pixelRatio;
903
+ }
904
+ updateClientBounds() {
905
+ this.clientBounds = this.view.getBoundingClientRect();
906
+ }
907
+ startAutoLayout(autoBounds, listener) {
908
+ this.autoBounds = autoBounds;
909
+ this.resizeListener = listener;
910
+ try {
911
+ this.resizeObserver = new ResizeObserver((entries) => {
912
+ this.updateClientBounds();
913
+ for (const entry of entries)
914
+ this.checkAutoBounds(entry.contentRect);
915
+ });
916
+ const parent = this.parentView;
917
+ if (parent) {
918
+ this.resizeObserver.observe(parent);
919
+ this.checkAutoBounds(parent.getBoundingClientRect());
920
+ }
921
+ }
922
+ catch (_a) {
923
+ this.imitateResizeObserver();
924
+ }
925
+ }
926
+ imitateResizeObserver() {
927
+ if (this.autoLayout) {
928
+ if (this.parentView)
929
+ this.checkAutoBounds(this.parentView.getBoundingClientRect());
930
+ Platform.requestRender(this.imitateResizeObserver.bind(this));
931
+ }
932
+ }
933
+ checkAutoBounds(parentSize) {
934
+ const view = this.view;
935
+ const { x, y, width, height } = this.autoBounds.getBoundsFrom(parentSize);
936
+ if (width !== this.width || height !== this.height) {
937
+ const { style } = view;
938
+ const { pixelRatio } = this;
939
+ style.marginLeft = x + 'px';
940
+ style.marginTop = y + 'px';
941
+ const size = { width, height, pixelRatio };
942
+ const oldSize = {};
943
+ DataHelper.copyAttrs(oldSize, this, canvasSizeAttrs);
944
+ this.resize(size);
945
+ if (this.width !== undefined)
946
+ this.resizeListener(new ResizeEvent(size, oldSize));
947
+ }
948
+ }
949
+ stopAutoLayout() {
950
+ this.autoLayout = false;
951
+ this.resizeListener = null;
952
+ if (this.resizeObserver) {
953
+ this.resizeObserver.disconnect();
954
+ this.resizeObserver = null;
955
+ }
956
+ }
957
+ unrealCanvas() {
958
+ if (!this.unreal && this.parentView) {
959
+ const view = this.view;
960
+ if (view)
961
+ view.remove();
962
+ this.view = this.parentView;
963
+ this.unreal = true;
964
+ }
965
+ }
966
+ destroy() {
967
+ if (this.view) {
968
+ this.stopAutoLayout();
969
+ if (!this.unreal) {
970
+ const view = this.view;
971
+ if (view.parentElement)
972
+ view.remove();
973
+ }
974
+ super.destroy();
975
+ }
976
+ }
977
+ }
978
+
979
+ canvasPatch(CanvasRenderingContext2D.prototype);
980
+ canvasPatch(Path2D.prototype);
981
+
982
+ const PointerEventHelper = {
983
+ convert(e, local) {
984
+ const base = InteractionHelper.getBase(e);
985
+ const data = Object.assign(Object.assign({}, base), { x: local.x, y: local.y, width: e.width, height: e.height, pointerType: e.pointerType, pressure: e.pressure });
986
+ if (data.pointerType === 'pen') {
987
+ data.tangentialPressure = e.tangentialPressure;
988
+ data.tiltX = e.tiltX;
989
+ data.tiltY = e.tiltY;
990
+ data.twist = e.twist;
991
+ }
992
+ return data;
993
+ },
994
+ convertMouse(e, local) {
995
+ const base = InteractionHelper.getBase(e);
996
+ return Object.assign(Object.assign({}, base), { x: local.x, y: local.y, width: 1, height: 1, pointerType: 'mouse', pressure: 0.5 });
997
+ },
998
+ convertTouch(e, local) {
999
+ const touch = PointerEventHelper.getTouch(e);
1000
+ const base = InteractionHelper.getBase(e);
1001
+ return Object.assign(Object.assign({}, base), { x: local.x, y: local.y, width: 1, height: 1, pointerType: 'touch', pressure: touch.force });
1002
+ },
1003
+ getTouch(e) {
1004
+ return e.targetTouches[0] || e.changedTouches[0];
1005
+ }
1006
+ };
1007
+
1008
+ const WheelEventHelper = {
1009
+ getMove(e, config) {
1010
+ let { moveSpeed } = config;
1011
+ let { deltaX, deltaY } = e;
1012
+ if (e.shiftKey && !deltaX) {
1013
+ deltaX = deltaY;
1014
+ deltaY = 0;
1015
+ }
1016
+ if (deltaX > 50)
1017
+ deltaX = Math.max(50, deltaX / 3);
1018
+ if (deltaY > 50)
1019
+ deltaY = Math.max(50, deltaY / 3);
1020
+ return { x: -deltaX * moveSpeed * 2, y: -deltaY * moveSpeed * 2 };
1021
+ },
1022
+ getScale(e, config) {
1023
+ let zoom;
1024
+ let scale = 1;
1025
+ let { zoomMode, zoomSpeed } = config;
1026
+ const delta = e.deltaY || e.deltaX;
1027
+ if (zoomMode) {
1028
+ zoom = !e.deltaX && (Platform.intWheelDeltaY ? Math.abs(delta) > 17 : Math.ceil(delta) !== delta);
1029
+ if (e.shiftKey || e.metaKey || e.ctrlKey)
1030
+ zoom = true;
1031
+ }
1032
+ else {
1033
+ zoom = !e.shiftKey && (e.metaKey || e.ctrlKey);
1034
+ }
1035
+ if (zoom) {
1036
+ zoomSpeed = MathHelper.within(zoomSpeed, 0, 1);
1037
+ const min = e.deltaY ? config.delta.y : config.delta.x;
1038
+ scale = 1 - delta / (min * 25 * (1 - zoomSpeed) + 10);
1039
+ if (scale < 0.5)
1040
+ scale = 0.5;
1041
+ if (scale >= 1.5)
1042
+ scale = 1.5;
1043
+ }
1044
+ return scale;
1045
+ }
1046
+ };
1047
+
1048
+ const KeyEventHelper = {
1049
+ convert(e) {
1050
+ const base = InteractionHelper.getBase(e);
1051
+ const data = Object.assign(Object.assign({}, base), { code: e.code, key: e.key });
1052
+ return data;
1053
+ }
1054
+ };
1055
+
1056
+ const { getMoveEventData, getZoomEventData, getRotateEventData } = InteractionHelper;
1057
+ class Interaction extends InteractionBase {
1058
+ __listenEvents() {
1059
+ super.__listenEvents();
1060
+ const view = this.view = this.canvas.view;
1061
+ this.viewEvents = {
1062
+ 'pointerdown': this.onPointerDown,
1063
+ 'mousedown': this.onMouseDown,
1064
+ 'touchstart': this.onTouchStart,
1065
+ 'wheel': this.onWheel,
1066
+ 'gesturestart': this.onGesturestart,
1067
+ 'gesturechange': this.onGesturechange,
1068
+ 'gestureend': this.onGestureend
1069
+ };
1070
+ this.windowEvents = {
1071
+ 'pointermove': this.onPointerMove,
1072
+ 'pointerup': this.onPointerUp,
1073
+ 'pointercancel': this.onPointerCancel,
1074
+ 'mousemove': this.onMouseMove,
1075
+ 'mouseup': this.onMouseUp,
1076
+ 'touchmove': this.onTouchMove,
1077
+ 'touchend': this.onTouchEnd,
1078
+ 'touchcancel': this.onTouchCancel,
1079
+ 'keydown': this.onKeyDown,
1080
+ 'keyup': this.onKeyUp,
1081
+ 'scroll': this.onScroll
1082
+ };
1083
+ const { viewEvents, windowEvents } = this;
1084
+ for (let name in viewEvents) {
1085
+ viewEvents[name] = viewEvents[name].bind(this);
1086
+ view.addEventListener(name, viewEvents[name]);
1087
+ }
1088
+ for (let name in windowEvents) {
1089
+ windowEvents[name] = windowEvents[name].bind(this);
1090
+ window.addEventListener(name, windowEvents[name]);
1091
+ }
1092
+ }
1093
+ __removeListenEvents() {
1094
+ super.__removeListenEvents();
1095
+ const { viewEvents, windowEvents } = this;
1096
+ for (let name in viewEvents) {
1097
+ this.view.removeEventListener(name, viewEvents[name]);
1098
+ this.viewEvents = {};
1099
+ }
1100
+ for (let name in windowEvents) {
1101
+ window.removeEventListener(name, windowEvents[name]);
1102
+ this.windowEvents = {};
1103
+ }
1104
+ }
1105
+ getLocal(p, updateClient) {
1106
+ if (updateClient)
1107
+ this.canvas.updateClientBounds();
1108
+ const { clientBounds } = this.canvas;
1109
+ return { x: p.clientX - clientBounds.x, y: p.clientY - clientBounds.y };
1110
+ }
1111
+ getTouches(touches) {
1112
+ const list = [];
1113
+ for (let i = 0, len = touches.length; i < len; i++) {
1114
+ list.push(touches[i]);
1115
+ }
1116
+ return list;
1117
+ }
1118
+ preventDefaultPointer(e) {
1119
+ const { pointer } = this.config;
1120
+ if (pointer.preventDefault)
1121
+ e.preventDefault();
1122
+ }
1123
+ preventDefaultWheel(e) {
1124
+ const { wheel } = this.config;
1125
+ if (wheel.preventDefault)
1126
+ e.preventDefault();
1127
+ }
1128
+ preventWindowPointer(e) {
1129
+ return !this.downData && e.target !== this.view;
1130
+ }
1131
+ onKeyDown(e) {
1132
+ this.keyDown(KeyEventHelper.convert(e));
1133
+ }
1134
+ onKeyUp(e) {
1135
+ this.keyUp(KeyEventHelper.convert(e));
1136
+ }
1137
+ onScroll() {
1138
+ this.canvas.updateClientBounds();
1139
+ }
1140
+ onPointerDown(e) {
1141
+ this.preventDefaultPointer(e);
1142
+ this.usePointer || (this.usePointer = true);
1143
+ if (this.useMultiTouch)
1144
+ return;
1145
+ this.pointerDown(PointerEventHelper.convert(e, this.getLocal(e)));
1146
+ }
1147
+ onPointerMove(e) {
1148
+ this.usePointer || (this.usePointer = true);
1149
+ if (this.useMultiTouch || this.preventWindowPointer(e))
1150
+ return;
1151
+ this.pointerMove(PointerEventHelper.convert(e, this.getLocal(e, true)));
1152
+ }
1153
+ onPointerUp(e) {
1154
+ if (this.downData)
1155
+ this.preventDefaultPointer(e);
1156
+ if (this.useMultiTouch || this.preventWindowPointer(e))
1157
+ return;
1158
+ this.pointerUp(PointerEventHelper.convert(e, this.getLocal(e)));
1159
+ }
1160
+ onPointerCancel() {
1161
+ if (this.useMultiTouch)
1162
+ return;
1163
+ this.pointerCancel();
1164
+ }
1165
+ onMouseDown(e) {
1166
+ this.preventDefaultPointer(e);
1167
+ if (this.useTouch || this.usePointer)
1168
+ return;
1169
+ this.pointerDown(PointerEventHelper.convertMouse(e, this.getLocal(e)));
1170
+ }
1171
+ onMouseMove(e) {
1172
+ if (this.useTouch || this.usePointer || this.preventWindowPointer(e))
1173
+ return;
1174
+ this.pointerMove(PointerEventHelper.convertMouse(e, this.getLocal(e, true)));
1175
+ }
1176
+ onMouseUp(e) {
1177
+ if (this.downData)
1178
+ this.preventDefaultPointer(e);
1179
+ if (this.useTouch || this.usePointer || this.preventWindowPointer(e))
1180
+ return;
1181
+ this.pointerUp(PointerEventHelper.convertMouse(e, this.getLocal(e)));
1182
+ }
1183
+ onMouseCancel() {
1184
+ if (this.useTouch || this.usePointer)
1185
+ return;
1186
+ this.pointerCancel();
1187
+ }
1188
+ onTouchStart(e) {
1189
+ e.preventDefault();
1190
+ this.multiTouchStart(e);
1191
+ if (this.usePointer)
1192
+ return;
1193
+ if (this.touchTimer) {
1194
+ window.clearTimeout(this.touchTimer);
1195
+ this.touchTimer = 0;
1196
+ }
1197
+ this.useTouch = true;
1198
+ const touch = PointerEventHelper.getTouch(e);
1199
+ this.pointerDown(PointerEventHelper.convertTouch(e, this.getLocal(touch, true)));
1200
+ }
1201
+ onTouchMove(e) {
1202
+ this.multiTouchMove(e);
1203
+ if (this.usePointer || this.preventWindowPointer(e))
1204
+ return;
1205
+ const touch = PointerEventHelper.getTouch(e);
1206
+ this.pointerMove(PointerEventHelper.convertTouch(e, this.getLocal(touch)));
1207
+ }
1208
+ onTouchEnd(e) {
1209
+ this.multiTouchEnd();
1210
+ if (this.usePointer || this.preventWindowPointer(e))
1211
+ return;
1212
+ if (this.touchTimer)
1213
+ clearTimeout(this.touchTimer);
1214
+ this.touchTimer = setTimeout(() => {
1215
+ this.useTouch = false;
1216
+ }, 500);
1217
+ const touch = PointerEventHelper.getTouch(e);
1218
+ this.pointerUp(PointerEventHelper.convertTouch(e, this.getLocal(touch)));
1219
+ }
1220
+ onTouchCancel() {
1221
+ if (this.usePointer)
1222
+ return;
1223
+ this.pointerCancel();
1224
+ }
1225
+ multiTouchStart(e) {
1226
+ this.useMultiTouch = (e.touches.length >= 2);
1227
+ this.touches = this.useMultiTouch ? this.getTouches(e.touches) : undefined;
1228
+ if (this.useMultiTouch)
1229
+ this.pointerCancel();
1230
+ }
1231
+ multiTouchMove(e) {
1232
+ if (!this.useMultiTouch)
1233
+ return;
1234
+ if (e.touches.length > 1) {
1235
+ const touches = this.getTouches(e.touches);
1236
+ const list = this.getKeepTouchList(this.touches, touches);
1237
+ if (list.length > 1) {
1238
+ this.multiTouch(InteractionHelper.getBase(e), list);
1239
+ this.touches = touches;
1240
+ }
1241
+ }
1242
+ }
1243
+ multiTouchEnd() {
1244
+ this.touches = null;
1245
+ this.useMultiTouch = false;
1246
+ this.transformEnd();
1247
+ }
1248
+ getKeepTouchList(old, touches) {
1249
+ let to;
1250
+ const list = [];
1251
+ old.forEach(from => {
1252
+ to = touches.find(touch => touch.identifier === from.identifier);
1253
+ if (to)
1254
+ list.push({ from: this.getLocal(from), to: this.getLocal(to) });
1255
+ });
1256
+ return list;
1257
+ }
1258
+ getLocalTouchs(points) {
1259
+ return points.map(point => this.getLocal(point));
1260
+ }
1261
+ onWheel(e) {
1262
+ this.preventDefaultWheel(e);
1263
+ const { wheel } = this.config;
1264
+ const scale = wheel.getScale ? wheel.getScale(e, wheel) : WheelEventHelper.getScale(e, wheel);
1265
+ const local = this.getLocal(e);
1266
+ const eventBase = InteractionHelper.getBase(e);
1267
+ scale !== 1 ? this.zoom(getZoomEventData(local, scale, eventBase)) : this.move(getMoveEventData(local, wheel.getMove ? wheel.getMove(e, wheel) : WheelEventHelper.getMove(e, wheel), eventBase));
1268
+ }
1269
+ onGesturestart(e) {
1270
+ this.preventDefaultWheel(e);
1271
+ this.lastGestureScale = 1;
1272
+ this.lastGestureRotation = 0;
1273
+ }
1274
+ onGesturechange(e) {
1275
+ this.preventDefaultWheel(e);
1276
+ const local = this.getLocal(e);
1277
+ const eventBase = InteractionHelper.getBase(e);
1278
+ const changeScale = e.scale / this.lastGestureScale;
1279
+ const changeAngle = e.rotation - this.lastGestureRotation;
1280
+ let { rotateSpeed } = this.config.wheel;
1281
+ rotateSpeed = MathHelper.within(rotateSpeed, 0, 1);
1282
+ this.zoom(getZoomEventData(local, changeScale * changeScale, eventBase));
1283
+ this.rotate(getRotateEventData(local, changeAngle / Math.PI * 180 * (rotateSpeed / 4 + 0.1), eventBase));
1284
+ this.lastGestureScale = e.scale;
1285
+ this.lastGestureRotation = e.rotation;
1286
+ }
1287
+ onGestureend(e) {
1288
+ this.preventDefaultWheel(e);
1289
+ this.transformEnd();
1290
+ }
1291
+ destroy() {
1292
+ if (this.view) {
1293
+ super.destroy();
1294
+ this.view = null;
1295
+ this.touches = null;
1296
+ }
1297
+ }
1298
+ }
1299
+
1300
+ const { mineType, fileType } = FileHelper;
1301
+ Object.assign(Creator, {
1302
+ canvas: (options, manager) => new LeaferCanvas(options, manager),
1303
+ image: (options) => new LeaferImage(options),
1304
+ hitCanvas: (options, manager) => new LeaferCanvas(options, manager),
1305
+ interaction: (target, canvas, selector, options) => new Interaction(target, canvas, selector, options),
1306
+ });
1307
+ function useCanvas(_canvasType, _power) {
1308
+ Platform.origin = {
1309
+ createCanvas(width, height) {
1310
+ const canvas = document.createElement('canvas');
1311
+ canvas.width = width;
1312
+ canvas.height = height;
1313
+ return canvas;
1314
+ },
1315
+ canvasToDataURL: (canvas, type, quality) => canvas.toDataURL(mineType(type), quality),
1316
+ canvasToBolb: (canvas, type, quality) => new Promise((resolve) => canvas.toBlob(resolve, mineType(type), quality)),
1317
+ canvasSaveAs: (canvas, filename, quality) => {
1318
+ return new Promise((resolve) => {
1319
+ let el = document.createElement('a');
1320
+ el.href = canvas.toDataURL(mineType(fileType(filename)), quality);
1321
+ el.download = filename;
1322
+ document.body.appendChild(el);
1323
+ el.click();
1324
+ document.body.removeChild(el);
1325
+ resolve();
1326
+ });
1327
+ },
1328
+ loadImage(src) {
1329
+ return new Promise((resolve, reject) => {
1330
+ const img = new Image();
1331
+ img.setAttribute('crossOrigin', 'anonymous');
1332
+ img.crossOrigin = 'anonymous';
1333
+ img.onload = () => { resolve(img); };
1334
+ img.onerror = (e) => { reject(e); };
1335
+ if (!src.startsWith('data:') && Platform.imageSuffix)
1336
+ src += (src.includes("?") ? "&" : "?") + Platform.imageSuffix;
1337
+ img.src = src;
1338
+ });
1339
+ }
1340
+ };
1341
+ Platform.canvas = Creator.canvas();
1342
+ Platform.conicGradientSupport = !!Platform.canvas.context.createConicGradient;
1343
+ }
1344
+ Platform.name = 'web';
1345
+ Platform.isMobile = 'ontouchstart' in window;
1346
+ Platform.requestRender = function (render) { window.requestAnimationFrame(render); };
1347
+ Platform.devicePixelRatio = devicePixelRatio;
1348
+ Platform.realtimeLayout = true;
1349
+ const { userAgent } = navigator;
1350
+ if (userAgent.indexOf("Firefox") > -1) {
1351
+ Platform.conicGradientRotate90 = true;
1352
+ Platform.intWheelDeltaY = true;
1353
+ Platform.syncDomFont = true;
1354
+ }
1355
+ else if (userAgent.indexOf("Safari") > -1 && userAgent.indexOf("Chrome") === -1) {
1356
+ Platform.fullImageShadow = true;
1357
+ }
1358
+ if (userAgent.indexOf('Windows') > -1) {
1359
+ Platform.os = 'Windows';
1360
+ Platform.intWheelDeltaY = true;
1361
+ }
1362
+ else if (userAgent.indexOf('Mac') > -1) {
1363
+ Platform.os = 'Mac';
1364
+ }
1365
+ else if (userAgent.indexOf('Linux') > -1) {
1366
+ Platform.os = 'Linux';
1367
+ }
1368
+
1369
+ const { get: get$4, rotateOfOuter: rotateOfOuter$2, translate: translate$1, scaleOfOuter: scaleOfOuter$2, scale: scaleHelper$1, rotate } = MatrixHelper;
1370
+ function fillOrFitMode(data, mode, box, width, height, rotation) {
1371
+ const transform = get$4();
1372
+ const swap = rotation && rotation !== 180;
1373
+ const sw = box.width / (swap ? height : width);
1374
+ const sh = box.height / (swap ? width : height);
1375
+ const scale = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
1376
+ const x = box.x + (box.width - width * scale) / 2;
1377
+ const y = box.y + (box.height - height * scale) / 2;
1378
+ translate$1(transform, x, y);
1379
+ scaleHelper$1(transform, scale);
1380
+ if (rotation)
1381
+ rotateOfOuter$2(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
1382
+ data.scaleX = data.scaleY = scale;
1383
+ data.transform = transform;
1384
+ }
1385
+ function clipMode(data, box, offset, scale, rotation) {
1386
+ const transform = get$4();
1387
+ translate$1(transform, box.x, box.y);
1388
+ if (offset)
1389
+ translate$1(transform, offset.x, offset.y);
1390
+ if (scale) {
1391
+ typeof scale === 'number' ? scaleHelper$1(transform, scale) : scaleHelper$1(transform, scale.x, scale.y);
1392
+ data.scaleX = transform.a;
1393
+ data.scaleY = transform.d;
1394
+ }
1395
+ if (rotation)
1396
+ rotate(transform, rotation);
1397
+ data.transform = transform;
1398
+ }
1399
+ function repeatMode(data, box, width, height, scale, rotation) {
1400
+ const transform = get$4();
1401
+ if (rotation) {
1402
+ rotate(transform, rotation);
1403
+ switch (rotation) {
1404
+ case 90:
1405
+ translate$1(transform, height, 0);
1406
+ break;
1407
+ case 180:
1408
+ translate$1(transform, width, height);
1409
+ break;
1410
+ case 270:
1411
+ translate$1(transform, 0, width);
1412
+ break;
1413
+ }
1414
+ }
1415
+ translate$1(transform, box.x, box.y);
1416
+ if (scale) {
1417
+ scaleOfOuter$2(transform, box, scale);
1418
+ data.scaleX = data.scaleY = scale;
1419
+ }
1420
+ data.transform = transform;
1421
+ }
1422
+
1423
+ const { get: get$3, translate } = MatrixHelper;
1424
+ function createData(leafPaint, image, paint, box) {
1425
+ let { width, height } = image;
1426
+ const { opacity, mode, offset, scale, rotation, blendMode } = paint;
1427
+ const sameBox = box.width === width && box.height === height;
1428
+ if (blendMode)
1429
+ leafPaint.blendMode = blendMode;
1430
+ const data = leafPaint.data = { mode };
1431
+ switch (mode) {
1432
+ case 'strench':
1433
+ if (!sameBox)
1434
+ width = box.width, height = box.height;
1435
+ if (box.x || box.y) {
1436
+ data.transform = get$3();
1437
+ translate(data.transform, box.x, box.y);
1438
+ }
1439
+ break;
1440
+ case 'clip':
1441
+ if (offset || scale || rotation)
1442
+ clipMode(data, box, offset, scale, rotation);
1443
+ break;
1444
+ case 'repeat':
1445
+ if (!sameBox || scale || rotation)
1446
+ repeatMode(data, box, width, height, scale, rotation);
1447
+ break;
1448
+ case 'fit':
1449
+ case 'cover':
1450
+ default:
1451
+ if (!sameBox || rotation)
1452
+ fillOrFitMode(data, mode, box, width, height, rotation);
1453
+ }
1454
+ data.width = width;
1455
+ data.height = height;
1456
+ if (opacity)
1457
+ data.opacity = opacity;
1458
+ }
1459
+
1460
+ function image(ui, attrName, attrValue, box, firstUse) {
1461
+ const leafPaint = { type: attrValue.type };
1462
+ const image = leafPaint.image = ImageManager.get(attrValue);
1463
+ const event = (firstUse || image.loading) && { target: ui, image, attrName, attrValue };
1464
+ if (image.ready) {
1465
+ if (hasNaturalSize(ui, attrName, image))
1466
+ createData(leafPaint, image, attrValue, box);
1467
+ if (firstUse) {
1468
+ emit(ImageEvent.LOAD, event);
1469
+ emit(ImageEvent.LOADED, event);
1470
+ }
1471
+ }
1472
+ else if (image.error) {
1473
+ if (firstUse) {
1474
+ ui.forceUpdate('surface');
1475
+ event.error = image.error;
1476
+ emit(ImageEvent.ERROR, event);
1477
+ }
1478
+ }
1479
+ else {
1480
+ if (firstUse)
1481
+ emit(ImageEvent.LOAD, event);
1482
+ leafPaint.loadId = image.load(() => {
1483
+ if (!ui.destroyed) {
1484
+ if (hasNaturalSize(ui, attrName, image)) {
1485
+ createData(leafPaint, image, attrValue, box);
1486
+ ui.forceUpdate('surface');
1487
+ }
1488
+ emit(ImageEvent.LOADED, event);
1489
+ }
1490
+ }, (error) => {
1491
+ ui.forceUpdate('surface');
1492
+ event.error = error;
1493
+ emit(ImageEvent.ERROR, event);
1494
+ });
1495
+ }
1496
+ return leafPaint;
1497
+ }
1498
+ function hasNaturalSize(ui, attrName, image) {
1499
+ if (attrName === 'fill' && !ui.__.__naturalWidth) {
1500
+ const { __: d } = ui;
1501
+ d.__naturalWidth = image.width;
1502
+ d.__naturalHeight = image.height;
1503
+ if (!d.__getInput('width') || !d.__getInput('height')) {
1504
+ ui.forceUpdate('width');
1505
+ return false;
1506
+ }
1507
+ }
1508
+ return true;
1509
+ }
1510
+ function emit(type, data) {
1511
+ if (data.target.hasEvent(type))
1512
+ data.target.emitEvent(new ImageEvent(type, data));
1513
+ }
1514
+
1515
+ /******************************************************************************
1516
+ Copyright (c) Microsoft Corporation.
1517
+
1518
+ Permission to use, copy, modify, and/or distribute this software for any
1519
+ purpose with or without fee is hereby granted.
1520
+
1521
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
1522
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1523
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
1524
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1525
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
1526
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1527
+ PERFORMANCE OF THIS SOFTWARE.
1528
+ ***************************************************************************** */
1529
+ /* global Reflect, Promise, SuppressedError, Symbol */
1530
+
1531
+
1532
+ function __awaiter(thisArg, _arguments, P, generator) {
1533
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
1534
+ return new (P || (P = Promise))(function (resolve, reject) {
1535
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
1536
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
1537
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
1538
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
1539
+ });
1540
+ }
1541
+
1542
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
1543
+ var e = new Error(message);
1544
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1545
+ };
1546
+
1547
+ const { get: get$2, scale: scaleHelper, copy: copy$1 } = MatrixHelper;
1548
+ function createPattern(ui, paint, pixelRatio) {
1549
+ let { scaleX, scaleY } = ui.__world;
1550
+ const id = scaleX + '-' + scaleY;
1551
+ if (paint.patternId !== id && !ui.destroyed) {
1552
+ paint.patternId = id;
1553
+ scaleX = Math.abs(scaleX);
1554
+ scaleY = Math.abs(scaleY);
1555
+ const { image, data } = paint;
1556
+ const maxWidth = image.isSVG ? 4096 : Math.min(image.width, 4096);
1557
+ const maxHeight = image.isSVG ? 4096 : Math.min(image.height, 4096);
1558
+ let scale, matrix, { width, height, scaleX: sx, scaleY: sy, opacity, transform, mode } = data;
1559
+ if (sx) {
1560
+ matrix = get$2();
1561
+ copy$1(matrix, transform);
1562
+ scaleHelper(matrix, 1 / sx, 1 / sy);
1563
+ scaleX *= sx;
1564
+ scaleY *= sy;
1565
+ }
1566
+ scaleX *= pixelRatio;
1567
+ scaleY *= pixelRatio;
1568
+ width *= scaleX;
1569
+ height *= scaleY;
1570
+ if (width > maxWidth || height > maxHeight) {
1571
+ scale = Math.max(width / maxWidth, height / maxHeight);
1572
+ }
1573
+ if (scale) {
1574
+ scaleX /= scale;
1575
+ scaleY /= scale;
1576
+ width /= scale;
1577
+ height /= scale;
1578
+ }
1579
+ if (sx) {
1580
+ scaleX /= sx;
1581
+ scaleY /= sy;
1582
+ }
1583
+ if (transform || scaleX !== 1 || scaleY !== 1) {
1584
+ if (!matrix) {
1585
+ matrix = get$2();
1586
+ if (transform)
1587
+ copy$1(matrix, transform);
1588
+ }
1589
+ scaleHelper(matrix, 1 / scaleX, 1 / scaleY);
1590
+ }
1591
+ const style = Platform.canvas.createPattern(image.getCanvas(width < 1 ? 1 : width, height < 1 ? 1 : height, opacity), mode === 'repeat' ? 'repeat' : (Platform.origin.noRepeat || 'no-repeat'));
1592
+ try {
1593
+ if (paint.transform)
1594
+ paint.transform = null;
1595
+ if (matrix)
1596
+ style.setTransform ? style.setTransform(matrix) : paint.transform = matrix;
1597
+ }
1598
+ catch (_a) {
1599
+ paint.transform = matrix;
1600
+ }
1601
+ paint.style = style;
1602
+ return true;
1603
+ }
1604
+ else {
1605
+ return false;
1606
+ }
1607
+ }
1608
+
1609
+ function checkImage(ui, canvas, paint, allowPaint) {
1610
+ const { scaleX, scaleY } = ui.__world;
1611
+ if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
1612
+ return false;
1613
+ }
1614
+ else {
1615
+ if (allowPaint) {
1616
+ if (paint.image.isSVG && paint.data.mode !== 'repeat') {
1617
+ let { width, height } = paint.data;
1618
+ width *= scaleX * canvas.pixelRatio;
1619
+ height *= scaleY * canvas.pixelRatio;
1620
+ allowPaint = width > 4096 || height > 4096;
1621
+ }
1622
+ else {
1623
+ allowPaint = false;
1624
+ }
1625
+ }
1626
+ if (allowPaint) {
1627
+ canvas.save();
1628
+ canvas.clip();
1629
+ const { data } = paint;
1630
+ if (paint.blendMode)
1631
+ canvas.blendMode = paint.blendMode;
1632
+ if (data.opacity)
1633
+ canvas.opacity *= data.opacity;
1634
+ if (data.transform)
1635
+ canvas.transform(data.transform);
1636
+ canvas.drawImage(paint.image.view, 0, 0, data.width, data.height);
1637
+ canvas.restore();
1638
+ return true;
1639
+ }
1640
+ else {
1641
+ if (!paint.style) {
1642
+ createPattern(ui, paint, canvas.pixelRatio);
1643
+ }
1644
+ else {
1645
+ ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
1646
+ if (canvas.bounds.hit(ui.__world) && createPattern(ui, paint, canvas.pixelRatio))
1647
+ ui.forceUpdate('surface');
1648
+ }), 300);
1649
+ }
1650
+ return false;
1651
+ }
1652
+ }
1653
+ }
1654
+
1655
+ function recycleImage(data, attrName) {
1656
+ const paints = (attrName === 'fill' ? data._fill : data._stroke);
1657
+ if (paints instanceof Array) {
1658
+ let image, recycleMap, input, url;
1659
+ for (let i = 0, len = paints.length; i < len; i++) {
1660
+ image = paints[i].image;
1661
+ url = image && image.url;
1662
+ if (url) {
1663
+ if (!recycleMap)
1664
+ recycleMap = {};
1665
+ recycleMap[url] = true;
1666
+ ImageManager.recycle(image);
1667
+ if (image.loading) {
1668
+ if (!input) {
1669
+ input = (data.__input && data.__input[attrName]) || [];
1670
+ if (!(input instanceof Array))
1671
+ input = [input];
1672
+ }
1673
+ image.unload(paints[i].loadId, !input.some((item) => item.url === url));
1674
+ }
1675
+ }
1676
+ }
1677
+ return recycleMap;
1678
+ }
1679
+ return null;
1680
+ }
1681
+
1682
+ function fillText(ui, canvas) {
1683
+ let row;
1684
+ const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
1685
+ for (let i = 0, len = rows.length; i < len; i++) {
1686
+ row = rows[i];
1687
+ if (row.text) {
1688
+ canvas.fillText(row.text, row.x, row.y);
1689
+ }
1690
+ else if (row.data) {
1691
+ row.data.forEach(charData => {
1692
+ canvas.fillText(charData.char, charData.x, row.y);
1693
+ });
1694
+ }
1695
+ if (decorationY)
1696
+ canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight);
1697
+ }
1698
+ }
1699
+
1700
+ function fill(ui, canvas, fill) {
1701
+ canvas.fillStyle = fill;
1702
+ ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
1703
+ }
1704
+ function fills(ui, canvas, fills) {
1705
+ let item;
1706
+ const { windingRule, __font } = ui.__;
1707
+ for (let i = 0, len = fills.length; i < len; i++) {
1708
+ item = fills[i];
1709
+ if (item.image && checkImage(ui, canvas, item, !__font))
1710
+ continue;
1711
+ if (item.style) {
1712
+ canvas.fillStyle = item.style;
1713
+ if (item.transform) {
1714
+ canvas.save();
1715
+ canvas.transform(item.transform);
1716
+ if (item.blendMode)
1717
+ canvas.blendMode = item.blendMode;
1718
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1719
+ canvas.restore();
1720
+ }
1721
+ else {
1722
+ if (item.blendMode) {
1723
+ canvas.saveBlendMode(item.blendMode);
1724
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1725
+ canvas.restoreBlendMode();
1726
+ }
1727
+ else {
1728
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1729
+ }
1730
+ }
1731
+ }
1732
+ }
1733
+ }
1734
+
1735
+ function strokeText(ui, canvas, stroke) {
1736
+ const { strokeAlign } = ui.__;
1737
+ const isStrokes = typeof stroke !== 'string';
1738
+ switch (strokeAlign) {
1739
+ case 'center':
1740
+ canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
1741
+ isStrokes ? drawStrokesStyle(ui, stroke, canvas, true) : drawTextStroke(ui, canvas);
1742
+ break;
1743
+ case 'inside':
1744
+ drawAlignStroke(ui, canvas, stroke, 'inside', isStrokes);
1745
+ break;
1746
+ case 'outside':
1747
+ drawAlignStroke(ui, canvas, stroke, 'outside', isStrokes);
1748
+ break;
1749
+ }
1750
+ }
1751
+ function drawAlignStroke(ui, canvas, stroke, align, isStrokes) {
1752
+ const { strokeWidth, __font } = ui.__;
1753
+ const out = canvas.getSameCanvas(true);
1754
+ out.setStroke(isStrokes ? undefined : stroke, strokeWidth * 2, ui.__);
1755
+ out.font = __font;
1756
+ isStrokes ? drawStrokesStyle(ui, stroke, out, true) : drawTextStroke(ui, out);
1757
+ out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
1758
+ fillText(ui, out);
1759
+ out.blendMode = 'normal';
1760
+ canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds);
1761
+ out.recycle();
1762
+ }
1763
+ function drawTextStroke(ui, canvas) {
1764
+ let row;
1765
+ const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
1766
+ for (let i = 0, len = rows.length; i < len; i++) {
1767
+ row = rows[i];
1768
+ if (row.text) {
1769
+ canvas.strokeText(row.text, row.x, row.y);
1770
+ }
1771
+ else if (row.data) {
1772
+ row.data.forEach(charData => {
1773
+ canvas.strokeText(charData.char, charData.x, row.y);
1774
+ });
1775
+ }
1776
+ if (decorationY)
1777
+ canvas.strokeRect(row.x, row.y + decorationY, row.width, decorationHeight);
1778
+ }
1779
+ }
1780
+ function drawStrokesStyle(ui, strokes, canvas, isText) {
1781
+ let item;
1782
+ for (let i = 0, len = strokes.length; i < len; i++) {
1783
+ item = strokes[i];
1784
+ if (item.image && checkImage(ui, canvas, item, false))
1785
+ continue;
1786
+ if (item.style) {
1787
+ canvas.strokeStyle = item.style;
1788
+ if (item.blendMode) {
1789
+ canvas.saveBlendMode(item.blendMode);
1790
+ isText ? drawTextStroke(ui, canvas) : canvas.stroke();
1791
+ canvas.restoreBlendMode();
1792
+ }
1793
+ else {
1794
+ isText ? drawTextStroke(ui, canvas) : canvas.stroke();
1795
+ }
1796
+ }
1797
+ }
1798
+ }
1799
+
1800
+ function stroke(ui, canvas, stroke) {
1801
+ const options = ui.__;
1802
+ const { strokeWidth, strokeAlign, __font } = options;
1803
+ if (!strokeWidth)
1804
+ return;
1805
+ if (__font) {
1806
+ strokeText(ui, canvas, stroke);
1807
+ }
1808
+ else {
1809
+ switch (strokeAlign) {
1810
+ case 'center':
1811
+ canvas.setStroke(stroke, strokeWidth, options);
1812
+ canvas.stroke();
1813
+ break;
1814
+ case 'inside':
1815
+ canvas.save();
1816
+ canvas.setStroke(stroke, strokeWidth * 2, options);
1817
+ options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1818
+ canvas.stroke();
1819
+ canvas.restore();
1820
+ break;
1821
+ case 'outside':
1822
+ const out = canvas.getSameCanvas(true);
1823
+ out.setStroke(stroke, strokeWidth * 2, ui.__);
1824
+ ui.__drawRenderPath(out);
1825
+ out.stroke();
1826
+ options.windingRule ? out.clip(options.windingRule) : out.clip();
1827
+ out.clearWorld(ui.__layout.renderBounds);
1828
+ canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds);
1829
+ out.recycle();
1830
+ break;
1831
+ }
1832
+ }
1833
+ }
1834
+ function strokes(ui, canvas, strokes) {
1835
+ const options = ui.__;
1836
+ const { strokeWidth, strokeAlign, __font } = options;
1837
+ if (!strokeWidth)
1838
+ return;
1839
+ if (__font) {
1840
+ strokeText(ui, canvas, strokes);
1841
+ }
1842
+ else {
1843
+ switch (strokeAlign) {
1844
+ case 'center':
1845
+ canvas.setStroke(undefined, strokeWidth, options);
1846
+ drawStrokesStyle(ui, strokes, canvas);
1847
+ break;
1848
+ case 'inside':
1849
+ canvas.save();
1850
+ canvas.setStroke(undefined, strokeWidth * 2, options);
1851
+ options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1852
+ drawStrokesStyle(ui, strokes, canvas);
1853
+ canvas.restore();
1854
+ break;
1855
+ case 'outside':
1856
+ const { renderBounds } = ui.__layout;
1857
+ const out = canvas.getSameCanvas(true);
1858
+ ui.__drawRenderPath(out);
1859
+ out.setStroke(undefined, strokeWidth * 2, ui.__);
1860
+ drawStrokesStyle(ui, strokes, out);
1861
+ options.windingRule ? out.clip(options.windingRule) : out.clip();
1862
+ out.clearWorld(renderBounds);
1863
+ canvas.copyWorldToInner(out, ui.__world, renderBounds);
1864
+ out.recycle();
1865
+ break;
1866
+ }
1867
+ }
1868
+ }
1869
+
1870
+ const { getSpread, getOuterOf, getByMove, getIntersectData } = BoundsHelper;
1871
+ function shape(ui, current, options) {
1872
+ const canvas = current.getSameCanvas();
1873
+ let bounds, matrix, shapeBounds;
1874
+ let worldCanvas;
1875
+ const { __world } = ui;
1876
+ let { scaleX, scaleY } = __world;
1877
+ if (scaleX < 0)
1878
+ scaleX = -scaleX;
1879
+ if (scaleY < 0)
1880
+ scaleY = -scaleY;
1881
+ if (!current.bounds.includes(__world, options.matrix)) {
1882
+ const { renderShapeSpread: spread } = ui.__layout;
1883
+ const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, spread * scaleX, spread * scaleY) : current.bounds, __world, options.matrix);
1884
+ matrix = current.bounds.getFitMatrix(worldClipBounds);
1885
+ if (matrix.a < 1) {
1886
+ worldCanvas = current.getSameCanvas();
1887
+ ui.__renderShape(worldCanvas, options);
1888
+ scaleX *= matrix.a;
1889
+ scaleY *= matrix.d;
1890
+ }
1891
+ shapeBounds = getOuterOf(__world, matrix);
1892
+ bounds = getByMove(shapeBounds, -matrix.e, -matrix.f);
1893
+ if (options.matrix)
1894
+ matrix.multiply(options.matrix);
1895
+ options = Object.assign(Object.assign({}, options), { matrix });
1896
+ }
1897
+ else {
1898
+ if (options.matrix) {
1899
+ scaleX *= options.matrix.a;
1900
+ scaleY *= options.matrix.d;
1901
+ bounds = shapeBounds = getOuterOf(__world, options.matrix);
1902
+ }
1903
+ else {
1904
+ bounds = shapeBounds = __world;
1905
+ }
1906
+ worldCanvas = canvas;
1907
+ }
1908
+ ui.__renderShape(canvas, options);
1909
+ return {
1910
+ canvas, matrix, bounds,
1911
+ worldCanvas, shapeBounds, scaleX, scaleY
1912
+ };
1913
+ }
1914
+
1915
+ const defaultFrom$2 = { x: 0.5, y: 0 };
1916
+ const defaultTo$2 = { x: 0.5, y: 1 };
1917
+ function linearGradient(paint, box) {
1918
+ let { from, to, type, blendMode, opacity } = paint;
1919
+ from || (from = defaultFrom$2);
1920
+ to || (to = defaultTo$2);
1921
+ const style = Platform.canvas.createLinearGradient(box.x + from.x * box.width, box.y + from.y * box.height, box.x + to.x * box.width, box.y + to.y * box.height);
1922
+ applyStops(style, paint.stops, opacity);
1923
+ const data = { type, style };
1924
+ if (blendMode)
1925
+ data.blendMode = blendMode;
1926
+ return data;
1927
+ }
1928
+ function applyStops(gradient, stops, opacity) {
1929
+ let stop;
1930
+ for (let i = 0, len = stops.length; i < len; i++) {
1931
+ stop = stops[i];
1932
+ gradient.addColorStop(stop.offset, ColorConvert$1.string(stop.color, opacity));
1933
+ }
1934
+ }
1935
+
1936
+ const { set: set$1, getAngle: getAngle$1, getDistance: getDistance$1 } = PointHelper;
1937
+ const { get: get$1, rotateOfOuter: rotateOfOuter$1, scaleOfOuter: scaleOfOuter$1 } = MatrixHelper;
1938
+ const defaultFrom$1 = { x: 0.5, y: 0.5 };
1939
+ const defaultTo$1 = { x: 0.5, y: 1 };
1940
+ const realFrom$1 = {};
1941
+ const realTo$1 = {};
1942
+ function radialGradient(paint, box) {
1943
+ let { from, to, type, opacity, blendMode, stretch } = paint;
1944
+ from || (from = defaultFrom$1);
1945
+ to || (to = defaultTo$1);
1946
+ const { x, y, width, height } = box;
1947
+ set$1(realFrom$1, x + from.x * width, y + from.y * height);
1948
+ set$1(realTo$1, x + to.x * width, y + to.y * height);
1949
+ let transform;
1950
+ if (width !== height || stretch) {
1951
+ transform = get$1();
1952
+ scaleOfOuter$1(transform, realFrom$1, width / height * (stretch || 1), 1);
1953
+ rotateOfOuter$1(transform, realFrom$1, getAngle$1(realFrom$1, realTo$1) + 90);
1954
+ }
1955
+ const style = Platform.canvas.createRadialGradient(realFrom$1.x, realFrom$1.y, 0, realFrom$1.x, realFrom$1.y, getDistance$1(realFrom$1, realTo$1));
1956
+ applyStops(style, paint.stops, opacity);
1957
+ const data = { type, style, transform };
1958
+ if (blendMode)
1959
+ data.blendMode = blendMode;
1960
+ return data;
1961
+ }
1962
+
1963
+ const { set, getAngle, getDistance } = PointHelper;
1964
+ const { get, rotateOfOuter, scaleOfOuter } = MatrixHelper;
1965
+ const defaultFrom = { x: 0.5, y: 0.5 };
1966
+ const defaultTo = { x: 0.5, y: 1 };
1967
+ const realFrom = {};
1968
+ const realTo = {};
1969
+ function conicGradient(paint, box) {
1970
+ let { from, to, type, opacity, blendMode, stretch } = paint;
1971
+ from || (from = defaultFrom);
1972
+ to || (to = defaultTo);
1973
+ const { x, y, width, height } = box;
1974
+ set(realFrom, x + from.x * width, y + from.y * height);
1975
+ set(realTo, x + to.x * width, y + to.y * height);
1976
+ const transform = get();
1977
+ const angle = getAngle(realFrom, realTo);
1978
+ if (Platform.conicGradientRotate90) {
1979
+ scaleOfOuter(transform, realFrom, width / height * (stretch || 1), 1);
1980
+ rotateOfOuter(transform, realFrom, angle + 90);
1981
+ }
1982
+ else {
1983
+ scaleOfOuter(transform, realFrom, 1, width / height * (stretch || 1));
1984
+ rotateOfOuter(transform, realFrom, angle);
1985
+ }
1986
+ const style = Platform.conicGradientSupport ? Platform.canvas.createConicGradient(0, realFrom.x, realFrom.y) : Platform.canvas.createRadialGradient(realFrom.x, realFrom.y, 0, realFrom.x, realFrom.y, getDistance(realFrom, realTo));
1987
+ applyStops(style, paint.stops, opacity);
1988
+ const data = { type, style, transform };
1989
+ if (blendMode)
1990
+ data.blendMode = blendMode;
1991
+ return data;
1992
+ }
1993
+
1994
+ let recycleMap;
1995
+ function compute(ui, attrName) {
1996
+ const value = [];
1997
+ let item;
1998
+ let paints = ui.__.__input[attrName];
1999
+ if (!(paints instanceof Array))
2000
+ paints = [paints];
2001
+ recycleMap = recycleImage(ui.__, attrName);
2002
+ for (let i = 0, len = paints.length; i < len; i++) {
2003
+ item = getLeafPaint(ui, paints[i], attrName);
2004
+ if (item)
2005
+ value.push(item);
2006
+ }
2007
+ ui.__['_' + attrName] = value.length ? value : undefined;
2008
+ }
2009
+ function getLeafPaint(ui, paint, attrName) {
2010
+ if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
2011
+ return undefined;
2012
+ const { boxBounds } = ui.__layout;
2013
+ switch (paint.type) {
2014
+ case 'solid':
2015
+ let { type, blendMode, color, opacity } = paint;
2016
+ return { type, blendMode, style: ColorConvert$1.string(color, opacity) };
2017
+ case 'image':
2018
+ return image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
2019
+ case 'linear':
2020
+ return linearGradient(paint, boxBounds);
2021
+ case 'radial':
2022
+ return radialGradient(paint, boxBounds);
2023
+ case 'angular':
2024
+ return conicGradient(paint, boxBounds);
2025
+ default:
2026
+ return paint.r ? { type: 'solid', style: ColorConvert$1.string(paint) } : undefined;
2027
+ }
2028
+ }
2029
+
2030
+ var UIPaint = /*#__PURE__*/Object.freeze({
2031
+ __proto__: null,
2032
+ compute: compute,
2033
+ drawTextStroke: drawTextStroke,
2034
+ fill: fill,
2035
+ fillText: fillText,
2036
+ fills: fills,
2037
+ recycleImage: recycleImage,
2038
+ shape: shape,
2039
+ stroke: stroke,
2040
+ strokeText: strokeText,
2041
+ strokes: strokes
2042
+ });
2043
+
2044
+ const { copy, toOffsetOutBounds: toOffsetOutBounds$1 } = BoundsHelper;
2045
+ const tempBounds = {};
2046
+ const offsetOutBounds$1 = {};
2047
+ function shadow(ui, current, shape, _options) {
2048
+ let copyBounds, spreadScale;
2049
+ const { __world, __layout } = ui;
2050
+ const { shadow } = ui.__;
2051
+ const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
2052
+ const other = current.getSameCanvas();
2053
+ const end = shadow.length - 1;
2054
+ toOffsetOutBounds$1(bounds, offsetOutBounds$1);
2055
+ shadow.forEach((item, index) => {
2056
+ other.setWorldShadow((offsetOutBounds$1.offsetX + item.x * scaleX), (offsetOutBounds$1.offsetY + item.y * scaleY), item.blur * scaleX, item.color);
2057
+ spreadScale = item.spread ? 1 + item.spread * 2 / (__layout.boxBounds.width + (__layout.strokeBoxSpread || 0) * 2) : 0;
2058
+ drawWorldShadow(other, offsetOutBounds$1, spreadScale, shape);
2059
+ copyBounds = bounds;
2060
+ if (item.box) {
2061
+ other.restore();
2062
+ other.save();
2063
+ if (worldCanvas) {
2064
+ other.copyWorld(other, bounds, __world, 'copy');
2065
+ copyBounds = __world;
2066
+ }
2067
+ worldCanvas ? other.copyWorld(worldCanvas, __world, __world, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
2068
+ }
2069
+ if (ui.__hasMirror) {
2070
+ current.copyWorldByReset(other, copyBounds, __world, item.blendMode);
2071
+ }
2072
+ else {
2073
+ current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
2074
+ }
2075
+ if (end && index < end)
2076
+ other.clear();
2077
+ });
2078
+ other.recycle();
2079
+ }
2080
+ function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
2081
+ const { bounds, shapeBounds } = shape;
2082
+ if (Platform.fullImageShadow) {
2083
+ copy(tempBounds, canvas.bounds);
2084
+ tempBounds.x += (outBounds.x - shapeBounds.x);
2085
+ tempBounds.y += (outBounds.y - shapeBounds.y);
2086
+ if (spreadScale) {
2087
+ const { matrix } = shape;
2088
+ tempBounds.x -= (bounds.x + (matrix ? matrix.e : 0) + bounds.width / 2) * (spreadScale - 1);
2089
+ tempBounds.y -= (bounds.y + (matrix ? matrix.f : 0) + bounds.height / 2) * (spreadScale - 1);
2090
+ tempBounds.width *= spreadScale;
2091
+ tempBounds.height *= spreadScale;
2092
+ }
2093
+ canvas.copyWorld(shape.canvas, canvas.bounds, tempBounds);
2094
+ }
2095
+ else {
2096
+ if (spreadScale) {
2097
+ copy(tempBounds, outBounds);
2098
+ tempBounds.x -= (outBounds.width / 2) * (spreadScale - 1);
2099
+ tempBounds.y -= (outBounds.height / 2) * (spreadScale - 1);
2100
+ tempBounds.width *= spreadScale;
2101
+ tempBounds.height *= spreadScale;
2102
+ }
2103
+ canvas.copyWorld(shape.canvas, shapeBounds, spreadScale ? tempBounds : outBounds);
2104
+ }
2105
+ }
2106
+
2107
+ const { toOffsetOutBounds } = BoundsHelper;
2108
+ const offsetOutBounds = {};
2109
+ function innerShadow(ui, current, shape, _options) {
2110
+ let copyBounds, spreadScale;
2111
+ const { __world, __layout: __layout } = ui;
2112
+ const { innerShadow } = ui.__;
2113
+ const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
2114
+ const other = current.getSameCanvas();
2115
+ const end = innerShadow.length - 1;
2116
+ toOffsetOutBounds(bounds, offsetOutBounds);
2117
+ innerShadow.forEach((item, index) => {
2118
+ other.save();
2119
+ other.setWorldShadow((offsetOutBounds.offsetX + item.x * scaleX), (offsetOutBounds.offsetY + item.y * scaleY), item.blur * scaleX);
2120
+ spreadScale = item.spread ? 1 - item.spread * 2 / (__layout.boxBounds.width + (__layout.strokeBoxSpread || 0) * 2) : 0;
2121
+ drawWorldShadow(other, offsetOutBounds, spreadScale, shape);
2122
+ other.restore();
2123
+ if (worldCanvas) {
2124
+ other.copyWorld(other, bounds, __world, 'copy');
2125
+ other.copyWorld(worldCanvas, __world, __world, 'source-out');
2126
+ copyBounds = __world;
2127
+ }
2128
+ else {
2129
+ other.copyWorld(shape.canvas, shapeBounds, bounds, 'source-out');
2130
+ copyBounds = bounds;
2131
+ }
2132
+ other.fillWorld(copyBounds, item.color, 'source-in');
2133
+ if (ui.__hasMirror) {
2134
+ current.copyWorldByReset(other, copyBounds, __world, item.blendMode);
2135
+ }
2136
+ else {
2137
+ current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
2138
+ }
2139
+ if (end && index < end)
2140
+ other.clear();
2141
+ });
2142
+ other.recycle();
2143
+ }
2144
+
2145
+ function blur(ui, current, origin) {
2146
+ const { blur } = ui.__;
2147
+ origin.setWorldBlur(blur * ui.__world.a);
2148
+ origin.copyWorldToInner(current, ui.__world, ui.__layout.renderBounds);
2149
+ origin.filter = 'none';
2150
+ }
2151
+
2152
+ var UIEffect = /*#__PURE__*/Object.freeze({
2153
+ __proto__: null,
2154
+ blur: blur,
2155
+ innerShadow: innerShadow,
2156
+ shadow: shadow
2157
+ });
2158
+
2159
+ const money = '¥¥$€££¢¢';
2160
+ const letter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
2161
+ const langBefore = '《(「〈『〖【〔{┌<‘“=' + money;
2162
+ const langAfter = '》)」〉』〗】〕}┐>’”!?,、。:;‰';
2163
+ const langSymbol = '≮≯≈≠=…';
2164
+ const langBreak$1 = '—/~|┆·';
2165
+ const beforeChar = '{[(<\'"' + langBefore;
2166
+ const afterChar = '>)]}%!?,.:;\'"' + langAfter;
2167
+ const symbolChar = afterChar + '_#~&*+\\=|' + langSymbol;
2168
+ const breakChar = '- ' + langBreak$1;
2169
+ const cjkRangeList = [
2170
+ [0x4E00, 0x9FFF],
2171
+ [0x3400, 0x4DBF],
2172
+ [0x20000, 0x2A6DF],
2173
+ [0x2A700, 0x2B73F],
2174
+ [0x2B740, 0x2B81F],
2175
+ [0x2B820, 0x2CEAF],
2176
+ [0x2CEB0, 0x2EBEF],
2177
+ [0x30000, 0x3134F],
2178
+ [0x31350, 0x323AF],
2179
+ [0x2E80, 0x2EFF],
2180
+ [0x2F00, 0x2FDF],
2181
+ [0x2FF0, 0x2FFF],
2182
+ [0x3000, 0x303F],
2183
+ [0x31C0, 0x31EF],
2184
+ [0x3200, 0x32FF],
2185
+ [0x3300, 0x33FF],
2186
+ [0xF900, 0xFAFF],
2187
+ [0xFE30, 0xFE4F],
2188
+ [0x1F200, 0x1F2FF],
2189
+ [0x2F800, 0x2FA1F],
2190
+ ];
2191
+ const cjkReg = new RegExp(cjkRangeList.map(([start, end]) => `[\\u${start.toString(16)}-\\u${end.toString(16)}]`).join('|'));
2192
+ function mapChar(str) {
2193
+ const map = {};
2194
+ str.split('').forEach(char => map[char] = true);
2195
+ return map;
2196
+ }
2197
+ const letterMap = mapChar(letter);
2198
+ const beforeMap = mapChar(beforeChar);
2199
+ const afterMap = mapChar(afterChar);
2200
+ const symbolMap = mapChar(symbolChar);
2201
+ const breakMap = mapChar(breakChar);
2202
+ var CharType;
2203
+ (function (CharType) {
2204
+ CharType[CharType["Letter"] = 0] = "Letter";
2205
+ CharType[CharType["Single"] = 1] = "Single";
2206
+ CharType[CharType["Before"] = 2] = "Before";
2207
+ CharType[CharType["After"] = 3] = "After";
2208
+ CharType[CharType["Symbol"] = 4] = "Symbol";
2209
+ CharType[CharType["Break"] = 5] = "Break";
2210
+ })(CharType || (CharType = {}));
2211
+ const { Letter: Letter$1, Single: Single$1, Before: Before$1, After: After$1, Symbol: Symbol$1, Break: Break$1 } = CharType;
2212
+ function getCharType(char) {
2213
+ if (letterMap[char]) {
2214
+ return Letter$1;
2215
+ }
2216
+ else if (breakMap[char]) {
2217
+ return Break$1;
2218
+ }
2219
+ else if (beforeMap[char]) {
2220
+ return Before$1;
2221
+ }
2222
+ else if (afterMap[char]) {
2223
+ return After$1;
2224
+ }
2225
+ else if (symbolMap[char]) {
2226
+ return Symbol$1;
2227
+ }
2228
+ else if (cjkReg.test(char)) {
2229
+ return Single$1;
2230
+ }
2231
+ else {
2232
+ return Letter$1;
2233
+ }
2234
+ }
2235
+
2236
+ const TextRowHelper = {
2237
+ trimRight(row) {
2238
+ const { words } = row;
2239
+ let trimRight = 0, len = words.length, char;
2240
+ for (let i = len - 1; i > -1; i--) {
2241
+ char = words[i].data[0];
2242
+ if (char.char === ' ') {
2243
+ trimRight++;
2244
+ row.width -= char.width;
2245
+ }
2246
+ else {
2247
+ break;
2248
+ }
2249
+ }
2250
+ if (trimRight)
2251
+ words.splice(len - trimRight, trimRight);
2252
+ }
2253
+ };
2254
+
2255
+ function getTextCase(char, textCase, firstChar) {
2256
+ switch (textCase) {
2257
+ case 'title':
2258
+ return firstChar ? char.toUpperCase() : char;
2259
+ case 'upper':
2260
+ return char.toUpperCase();
2261
+ case 'lower':
2262
+ return char.toLowerCase();
2263
+ default:
2264
+ return char;
2265
+ }
2266
+ }
2267
+
2268
+ const { trimRight } = TextRowHelper;
2269
+ const { Letter, Single, Before, After, Symbol, Break } = CharType;
2270
+ let word, row, wordWidth, rowWidth, realWidth;
2271
+ let char, charWidth, charType, lastCharType, langBreak, afterBreak, paraStart;
2272
+ let textDrawData, rows = [], bounds;
2273
+ function createRows(drawData, content, style) {
2274
+ textDrawData = drawData;
2275
+ rows = drawData.rows;
2276
+ bounds = drawData.bounds;
2277
+ const { __letterSpacing, paraIndent, textCase } = style;
2278
+ const { canvas } = Platform;
2279
+ const { width, height } = bounds;
2280
+ const charMode = width || height || __letterSpacing || (textCase !== 'none');
2281
+ if (charMode) {
2282
+ paraStart = true;
2283
+ lastCharType = null;
2284
+ wordWidth = rowWidth = 0;
2285
+ word = { data: [] }, row = { words: [] };
2286
+ for (let i = 0, len = content.length; i < len; i++) {
2287
+ char = content[i];
2288
+ if (char === '\n') {
2289
+ if (wordWidth)
2290
+ addWord();
2291
+ row.paraEnd = true;
2292
+ addRow();
2293
+ paraStart = true;
2294
+ }
2295
+ else {
2296
+ charType = getCharType(char);
2297
+ if (charType === Letter && textCase !== 'none')
2298
+ char = getTextCase(char, textCase, !wordWidth);
2299
+ charWidth = canvas.measureText(char).width;
2300
+ if (__letterSpacing)
2301
+ charWidth += __letterSpacing;
2302
+ langBreak = (charType === Single && (lastCharType === Single || lastCharType === Letter)) || (lastCharType === Single && charType !== After);
2303
+ afterBreak = ((charType === Before || charType === Single) && (lastCharType === Symbol || lastCharType === After));
2304
+ realWidth = paraStart && paraIndent ? width - paraIndent : width;
2305
+ if (width && rowWidth + wordWidth + charWidth > realWidth) {
2306
+ if (!afterBreak)
2307
+ afterBreak = charType === Letter && lastCharType == After;
2308
+ if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
2309
+ if (wordWidth)
2310
+ addWord();
2311
+ addRow();
2312
+ }
2313
+ else {
2314
+ addRow();
2315
+ }
2316
+ }
2317
+ if (char === ' ' && paraStart !== true && (rowWidth + wordWidth) === 0) ;
2318
+ else {
2319
+ if (charType === Break) {
2320
+ if (char === ' ' && wordWidth)
2321
+ addWord();
2322
+ addChar(char, charWidth);
2323
+ addWord();
2324
+ }
2325
+ else if (langBreak || afterBreak) {
2326
+ if (wordWidth)
2327
+ addWord();
2328
+ addChar(char, charWidth);
2329
+ }
2330
+ else {
2331
+ addChar(char, charWidth);
2332
+ }
2333
+ }
2334
+ lastCharType = charType;
2335
+ }
2336
+ }
2337
+ if (wordWidth)
2338
+ addWord();
2339
+ if (rowWidth)
2340
+ addRow();
2341
+ rows.length > 0 && (rows[rows.length - 1].paraEnd = true);
2342
+ }
2343
+ else {
2344
+ content.split('\n').forEach(content => {
2345
+ textDrawData.paraNumber++;
2346
+ rows.push({ x: paraIndent || 0, text: content, width: canvas.measureText(content).width, paraStart: true });
2347
+ });
2348
+ }
2349
+ }
2350
+ function addChar(char, width) {
2351
+ word.data.push({ char, width });
2352
+ wordWidth += width;
2353
+ }
2354
+ function addWord() {
2355
+ rowWidth += wordWidth;
2356
+ word.width = wordWidth;
2357
+ row.words.push(word);
2358
+ word = { data: [] };
2359
+ wordWidth = 0;
2360
+ }
2361
+ function addRow() {
2362
+ if (paraStart) {
2363
+ textDrawData.paraNumber++;
2364
+ row.paraStart = true;
2365
+ paraStart = false;
2366
+ }
2367
+ row.width = rowWidth;
2368
+ if (bounds.width)
2369
+ trimRight(row);
2370
+ rows.push(row);
2371
+ row = { words: [] };
2372
+ rowWidth = 0;
2373
+ }
2374
+
2375
+ const CharMode = 0;
2376
+ const WordMode = 1;
2377
+ const RowMode = 2;
2378
+ function layoutChar(drawData, style, width, _height) {
2379
+ const { rows } = drawData;
2380
+ const { textAlign, paraIndent, letterSpacing } = style;
2381
+ let charX, addWordWidth, indentWidth, mode, wordChar;
2382
+ rows.forEach(row => {
2383
+ if (row.words) {
2384
+ indentWidth = paraIndent && row.paraStart ? paraIndent : 0;
2385
+ addWordWidth = (width && textAlign === 'justify' && row.words.length > 1) ? (width - row.width - indentWidth) / (row.words.length - 1) : 0;
2386
+ mode = (letterSpacing || row.isOverflow) ? CharMode : (addWordWidth > 0.01 ? WordMode : RowMode);
2387
+ if (mode === RowMode) {
2388
+ row.text = '';
2389
+ row.x += indentWidth;
2390
+ row.words.forEach(word => {
2391
+ word.data.forEach(char => {
2392
+ row.text += char.char;
2393
+ });
2394
+ });
2395
+ }
2396
+ else {
2397
+ row.x += indentWidth;
2398
+ charX = row.x;
2399
+ row.data = [];
2400
+ row.words.forEach(word => {
2401
+ if (mode === WordMode) {
2402
+ wordChar = { char: '', x: charX };
2403
+ charX = toWordChar(word.data, charX, wordChar);
2404
+ if (wordChar.char !== ' ')
2405
+ row.data.push(wordChar);
2406
+ }
2407
+ else {
2408
+ charX = toChar(word.data, charX, row.data);
2409
+ }
2410
+ if (!row.paraEnd && addWordWidth) {
2411
+ charX += addWordWidth;
2412
+ row.width += addWordWidth;
2413
+ }
2414
+ });
2415
+ }
2416
+ row.words = null;
2417
+ }
2418
+ });
2419
+ }
2420
+ function toWordChar(data, charX, wordChar) {
2421
+ data.forEach(char => {
2422
+ wordChar.char += char.char;
2423
+ charX += char.width;
2424
+ });
2425
+ return charX;
2426
+ }
2427
+ function toChar(data, charX, rowData) {
2428
+ data.forEach(char => {
2429
+ if (char.char !== ' ') {
2430
+ char.x = charX;
2431
+ rowData.push(char);
2432
+ }
2433
+ charX += char.width;
2434
+ });
2435
+ return charX;
2436
+ }
2437
+
2438
+ function layoutText(drawData, style) {
2439
+ const { rows, bounds } = drawData;
2440
+ const { __lineHeight, __baseLine, textAlign, verticalAlign, paraSpacing, textOverflow } = style;
2441
+ let { x, y, width, height } = bounds, realHeight = __lineHeight * rows.length + (paraSpacing ? paraSpacing * (drawData.paraNumber - 1) : 0);
2442
+ let starY = __baseLine;
2443
+ if (textOverflow !== 'show' && realHeight > height) {
2444
+ realHeight = Math.max(height, __lineHeight);
2445
+ drawData.overflow = rows.length;
2446
+ }
2447
+ else {
2448
+ switch (verticalAlign) {
2449
+ case 'middle':
2450
+ y += (height - realHeight) / 2;
2451
+ break;
2452
+ case 'bottom':
2453
+ y += (height - realHeight);
2454
+ }
2455
+ }
2456
+ starY += y;
2457
+ let row;
2458
+ for (let i = 0, len = rows.length; i < len; i++) {
2459
+ row = rows[i];
2460
+ row.x = x;
2461
+ switch (textAlign) {
2462
+ case 'center':
2463
+ row.x += (width - row.width) / 2;
2464
+ break;
2465
+ case 'right':
2466
+ row.x += width - row.width;
2467
+ }
2468
+ if (row.paraStart && paraSpacing && i > 0)
2469
+ starY += paraSpacing;
2470
+ row.y = starY;
2471
+ starY += __lineHeight;
2472
+ if (drawData.overflow > i && starY > realHeight) {
2473
+ row.isOverflow = true;
2474
+ drawData.overflow = i + 1;
2475
+ }
2476
+ if (row.width < 0) {
2477
+ const charWidth = row.words[0].data[0].width;
2478
+ const rowX = row.x + row.width;
2479
+ if (rowX < bounds.x)
2480
+ bounds.x = rowX - charWidth;
2481
+ if (-row.width > bounds.width)
2482
+ bounds.width = -row.width + style.fontSize + charWidth;
2483
+ }
2484
+ else {
2485
+ if (row.x < bounds.x)
2486
+ bounds.x = row.x;
2487
+ if (row.width > bounds.width)
2488
+ bounds.width = row.width;
2489
+ }
2490
+ }
2491
+ bounds.y = y;
2492
+ bounds.height = realHeight;
2493
+ }
2494
+
2495
+ function clipText(drawData, textOverflow) {
2496
+ const { rows, overflow } = drawData;
2497
+ rows.splice(overflow);
2498
+ if (textOverflow !== 'hide') {
2499
+ if (textOverflow === 'ellipsis')
2500
+ textOverflow = '...';
2501
+ const ellipsisWidth = Platform.canvas.measureText(textOverflow).width;
2502
+ const row = rows[overflow - 1];
2503
+ let char, end = row.data.length - 1, charRight;
2504
+ const { x, width } = drawData.bounds;
2505
+ const right = x + width - ellipsisWidth;
2506
+ for (let i = end; i > -1; i--) {
2507
+ char = row.data[i];
2508
+ charRight = char.x + char.width;
2509
+ if (i === end && charRight < right) {
2510
+ break;
2511
+ }
2512
+ else if (charRight < right && char.char !== ' ') {
2513
+ row.data.splice(i + 1);
2514
+ row.width -= char.width;
2515
+ break;
2516
+ }
2517
+ row.width -= char.width;
2518
+ }
2519
+ row.width += ellipsisWidth;
2520
+ row.data.push({ char: textOverflow, x: charRight });
2521
+ }
2522
+ }
2523
+
2524
+ function decorationText(drawData, style) {
2525
+ const { fontSize } = style;
2526
+ drawData.decorationHeight = fontSize / 11;
2527
+ switch (style.textDecoration) {
2528
+ case 'under':
2529
+ drawData.decorationY = fontSize * 0.15;
2530
+ break;
2531
+ case 'delete':
2532
+ drawData.decorationY = -fontSize * 0.35;
2533
+ }
2534
+ }
2535
+
2536
+ const TextConvert = {
2537
+ getDrawData(content, style) {
2538
+ if (typeof content !== 'string')
2539
+ content = String(content);
2540
+ let x = 0, y = 0;
2541
+ let { width, height, padding } = style;
2542
+ const { textDecoration, textOverflow, __font } = style;
2543
+ if (!width)
2544
+ width = 0;
2545
+ if (padding) {
2546
+ const [top, right, bottom, left] = MathHelper.fourNumber(padding);
2547
+ if (width) {
2548
+ x = left;
2549
+ width -= (right + left);
2550
+ }
2551
+ if (height) {
2552
+ y = top;
2553
+ height -= (top + bottom);
2554
+ }
2555
+ }
2556
+ const drawData = {
2557
+ bounds: { x, y, width, height },
2558
+ rows: [],
2559
+ paraNumber: 0,
2560
+ font: Platform.canvas.font = __font
2561
+ };
2562
+ createRows(drawData, content, style);
2563
+ layoutText(drawData, style);
2564
+ layoutChar(drawData, style, width);
2565
+ if (drawData.overflow)
2566
+ clipText(drawData, textOverflow);
2567
+ if (textDecoration !== 'none')
2568
+ decorationText(drawData, style);
2569
+ return drawData;
2570
+ }
2571
+ };
2572
+
2573
+ const ColorConvert = {
2574
+ string(color, opacity) {
2575
+ if (typeof color === 'string')
2576
+ return color;
2577
+ let a = color.a === undefined ? 1 : color.a;
2578
+ if (opacity)
2579
+ a *= opacity;
2580
+ const rgb = color.r + ',' + color.g + ',' + color.b;
2581
+ return a === 1 ? 'rgb(' + rgb + ')' : 'rgba(' + rgb + ',' + a + ')';
2582
+ }
2583
+ };
2584
+
2585
+ const Export = {
2586
+ export(leaf, filename, options) {
2587
+ return addTask((success) => new Promise((resolve) => {
2588
+ const { leafer } = leaf;
2589
+ if (leafer) {
2590
+ leafer.waitViewCompleted(() => __awaiter(this, void 0, void 0, function* () {
2591
+ let quality, blob;
2592
+ let { canvas } = leafer;
2593
+ let { unreal } = canvas;
2594
+ if (unreal) {
2595
+ canvas = canvas.getSameCanvas();
2596
+ canvas.backgroundColor = leafer.config.fill;
2597
+ leafer.__render(canvas, {});
2598
+ }
2599
+ switch (typeof options) {
2600
+ case 'object':
2601
+ if (options.quality)
2602
+ quality = options.quality;
2603
+ if (options.blob)
2604
+ blob = true;
2605
+ break;
2606
+ case 'number':
2607
+ quality = options;
2608
+ break;
2609
+ case 'boolean':
2610
+ blob = options;
2611
+ }
2612
+ let data;
2613
+ if (filename.includes('.')) {
2614
+ data = yield canvas.saveAs(filename, quality);
2615
+ }
2616
+ else if (blob) {
2617
+ data = yield canvas.toBlob(filename, quality);
2618
+ }
2619
+ else {
2620
+ data = yield canvas.toDataURL(filename, quality);
2621
+ }
2622
+ success({ data });
2623
+ resolve();
2624
+ if (unreal)
2625
+ canvas.recycle();
2626
+ }));
2627
+ }
2628
+ else {
2629
+ success({ data: false });
2630
+ resolve();
2631
+ }
2632
+ }));
2633
+ }
2634
+ };
2635
+ let tasker;
2636
+ function addTask(task) {
2637
+ if (!tasker)
2638
+ tasker = new TaskProcessor();
2639
+ return new Promise((resolve) => {
2640
+ tasker.add(() => __awaiter(this, void 0, void 0, function* () { return yield task(resolve); }), { parallel: false });
2641
+ });
2642
+ }
2643
+
2644
+ Object.assign(Paint, UIPaint);
2645
+ Object.assign(Effect, UIEffect);
2646
+ Object.assign(TextConvert$1, TextConvert);
2647
+ Object.assign(ColorConvert$1, ColorConvert);
2648
+ Object.assign(Export$1, Export);
2649
+
2650
+ useCanvas();
2651
+
2652
+ export { Interaction, Layouter, LeaferCanvas, Renderer, Selector, Watcher, useCanvas };