@leafer-draw/worker 1.0.0-rc.10

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,2224 @@
1
+ import { LeaferCanvasBase, Platform, canvasPatch, Creator, LeaferImage, FileHelper, LeafList, DataHelper, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, Bounds, LeafBoundsHelper, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, AnimateEvent, ResizeEvent, BoundsHelper, MatrixHelper, ImageEvent, PointHelper, Direction4, TwoPointBoundsHelper, TaskProcessor, Matrix } from '@leafer/core';
2
+ export * from '@leafer/core';
3
+ export { LeaferImage } from '@leafer/core';
4
+ import { ColorConvert, Export, Group, TextConvert, Paint, PaintImage as PaintImage$1, PaintGradient as PaintGradient$1, Effect } from '@leafer-ui/draw';
5
+ export * from '@leafer-ui/draw';
6
+
7
+ class LeaferCanvas extends LeaferCanvasBase {
8
+ get allowBackgroundColor() { return true; }
9
+ init() {
10
+ this.__createView();
11
+ this.__createContext();
12
+ this.resize(this.config);
13
+ }
14
+ __createView() {
15
+ this.view = Platform.origin.createCanvas(1, 1);
16
+ }
17
+ updateViewSize() {
18
+ const { width, height, pixelRatio } = this;
19
+ this.view.width = Math.ceil(width * pixelRatio);
20
+ this.view.height = Math.ceil(height * pixelRatio);
21
+ this.clientBounds = this.bounds;
22
+ }
23
+ }
24
+
25
+ canvasPatch(OffscreenCanvasRenderingContext2D.prototype);
26
+ canvasPatch(Path2D.prototype);
27
+
28
+ const { mineType } = FileHelper;
29
+ Object.assign(Creator, {
30
+ canvas: (options, manager) => new LeaferCanvas(options, manager),
31
+ image: (options) => new LeaferImage(options)
32
+ });
33
+ function useCanvas(_canvasType, _power) {
34
+ Platform.origin = {
35
+ createCanvas: (width, height) => new OffscreenCanvas(width, height),
36
+ canvasToDataURL: (canvas, type, quality) => {
37
+ return new Promise((resolve, reject) => {
38
+ canvas.convertToBlob({ type: mineType(type), quality }).then((blob) => {
39
+ var reader = new FileReader();
40
+ reader.onload = (e) => resolve(e.target.result);
41
+ reader.onerror = (e) => reject(e);
42
+ reader.readAsDataURL(blob);
43
+ }).catch((e) => {
44
+ reject(e);
45
+ });
46
+ });
47
+ },
48
+ canvasToBolb: (canvas, type, quality) => canvas.convertToBlob({ type: mineType(type), quality }),
49
+ canvasSaveAs: (_canvas, _filename, _quality) => new Promise((resolve) => resolve()),
50
+ loadImage(src) {
51
+ return new Promise((resolve, reject) => {
52
+ if (!src.startsWith('data:') && Platform.image.suffix)
53
+ src += (src.includes("?") ? "&" : "?") + Platform.image.suffix;
54
+ let req = new XMLHttpRequest();
55
+ req.open('GET', src, true);
56
+ req.responseType = "blob";
57
+ req.onload = () => {
58
+ createImageBitmap(req.response).then(img => {
59
+ resolve(img);
60
+ }).catch(e => {
61
+ reject(e);
62
+ });
63
+ };
64
+ req.onerror = (e) => reject(e);
65
+ req.send();
66
+ });
67
+ }
68
+ };
69
+ Platform.canvas = Creator.canvas();
70
+ Platform.conicGradientSupport = !!Platform.canvas.context.createConicGradient;
71
+ }
72
+ Platform.name = 'web';
73
+ Platform.isWorker = true;
74
+ Platform.requestRender = function (render) { requestAnimationFrame(render); };
75
+ Platform.devicePixelRatio = 1;
76
+ const { userAgent } = navigator;
77
+ if (userAgent.indexOf("Firefox") > -1) {
78
+ Platform.conicGradientRotate90 = true;
79
+ Platform.intWheelDeltaY = true;
80
+ }
81
+ else if (userAgent.indexOf("Safari") > -1 && userAgent.indexOf("Chrome") === -1) {
82
+ Platform.fullImageShadow = true;
83
+ }
84
+ if (userAgent.indexOf('Windows') > -1) {
85
+ Platform.os = 'Windows';
86
+ Platform.intWheelDeltaY = true;
87
+ }
88
+ else if (userAgent.indexOf('Mac') > -1) {
89
+ Platform.os = 'Mac';
90
+ }
91
+ else if (userAgent.indexOf('Linux') > -1) {
92
+ Platform.os = 'Linux';
93
+ }
94
+
95
+ class Watcher {
96
+ get childrenChanged() { return this.hasAdd || this.hasRemove || this.hasVisible; }
97
+ get updatedList() {
98
+ if (this.hasRemove) {
99
+ const updatedList = new LeafList();
100
+ this.__updatedList.list.forEach(item => { if (item.leafer)
101
+ updatedList.add(item); });
102
+ return updatedList;
103
+ }
104
+ else {
105
+ return this.__updatedList;
106
+ }
107
+ }
108
+ constructor(target, userConfig) {
109
+ this.totalTimes = 0;
110
+ this.config = {};
111
+ this.__updatedList = new LeafList();
112
+ this.target = target;
113
+ if (userConfig)
114
+ this.config = DataHelper.default(userConfig, this.config);
115
+ this.__listenEvents();
116
+ }
117
+ start() {
118
+ if (this.disabled)
119
+ return;
120
+ this.running = true;
121
+ }
122
+ stop() {
123
+ this.running = false;
124
+ }
125
+ disable() {
126
+ this.stop();
127
+ this.__removeListenEvents();
128
+ this.disabled = true;
129
+ }
130
+ update() {
131
+ this.changed = true;
132
+ if (this.running)
133
+ this.target.emit(RenderEvent.REQUEST);
134
+ }
135
+ __onAttrChange(event) {
136
+ this.__updatedList.add(event.target);
137
+ this.update();
138
+ }
139
+ __onChildEvent(event) {
140
+ if (event.type === ChildEvent.ADD) {
141
+ this.hasAdd = true;
142
+ this.__pushChild(event.child);
143
+ }
144
+ else {
145
+ this.hasRemove = true;
146
+ this.__updatedList.add(event.parent);
147
+ }
148
+ this.update();
149
+ }
150
+ __pushChild(child) {
151
+ this.__updatedList.add(child);
152
+ if (child.isBranch)
153
+ this.__loopChildren(child);
154
+ }
155
+ __loopChildren(parent) {
156
+ const { children } = parent;
157
+ for (let i = 0, len = children.length; i < len; i++)
158
+ this.__pushChild(children[i]);
159
+ }
160
+ __onRquestData() {
161
+ this.target.emitEvent(new WatchEvent(WatchEvent.DATA, { updatedList: this.updatedList }));
162
+ this.__updatedList = new LeafList();
163
+ this.totalTimes++;
164
+ this.changed = false;
165
+ this.hasVisible = false;
166
+ this.hasRemove = false;
167
+ this.hasAdd = false;
168
+ }
169
+ __listenEvents() {
170
+ const { target } = this;
171
+ this.__eventIds = [
172
+ target.on_(PropertyEvent.CHANGE, this.__onAttrChange, this),
173
+ target.on_([ChildEvent.ADD, ChildEvent.REMOVE], this.__onChildEvent, this),
174
+ target.on_(WatchEvent.REQUEST, this.__onRquestData, this)
175
+ ];
176
+ }
177
+ __removeListenEvents() {
178
+ this.target.off_(this.__eventIds);
179
+ }
180
+ destroy() {
181
+ if (this.target) {
182
+ this.stop();
183
+ this.__removeListenEvents();
184
+ this.target = null;
185
+ this.__updatedList = null;
186
+ }
187
+ }
188
+ }
189
+
190
+ const { updateAllMatrix: updateAllMatrix$1, updateBounds: updateOneBounds, updateAllWorldOpacity } = LeafHelper;
191
+ const { pushAllChildBranch, pushAllParent } = BranchHelper;
192
+ function updateMatrix(updateList, levelList) {
193
+ let layout;
194
+ updateList.list.forEach(leaf => {
195
+ layout = leaf.__layout;
196
+ if (levelList.without(leaf) && !layout.proxyZoom) {
197
+ if (layout.matrixChanged) {
198
+ updateAllMatrix$1(leaf, true);
199
+ levelList.add(leaf);
200
+ if (leaf.isBranch)
201
+ pushAllChildBranch(leaf, levelList);
202
+ pushAllParent(leaf, levelList);
203
+ }
204
+ else if (layout.boundsChanged) {
205
+ levelList.add(leaf);
206
+ if (leaf.isBranch)
207
+ leaf.__tempNumber = 0;
208
+ pushAllParent(leaf, levelList);
209
+ }
210
+ }
211
+ });
212
+ }
213
+ function updateBounds(boundsList) {
214
+ let list, branch, children;
215
+ boundsList.sort(true);
216
+ boundsList.levels.forEach(level => {
217
+ list = boundsList.levelMap[level];
218
+ for (let i = 0, len = list.length; i < len; i++) {
219
+ branch = list[i];
220
+ if (branch.isBranch && branch.__tempNumber) {
221
+ children = branch.children;
222
+ for (let j = 0, jLen = children.length; j < jLen; j++) {
223
+ if (!children[j].isBranch) {
224
+ updateOneBounds(children[j]);
225
+ }
226
+ }
227
+ }
228
+ updateOneBounds(branch);
229
+ }
230
+ });
231
+ }
232
+ function updateChange(updateList) {
233
+ updateList.list.forEach(leaf => {
234
+ if (leaf.__layout.opacityChanged)
235
+ updateAllWorldOpacity(leaf);
236
+ leaf.__updateChange();
237
+ });
238
+ }
239
+
240
+ const { worldBounds } = LeafBoundsHelper;
241
+ const bigBounds = { x: 0, y: 0, width: 100000, height: 100000 };
242
+ class LayoutBlockData {
243
+ constructor(list) {
244
+ this.updatedBounds = new Bounds();
245
+ this.beforeBounds = new Bounds();
246
+ this.afterBounds = new Bounds();
247
+ if (list instanceof Array)
248
+ list = new LeafList(list);
249
+ this.updatedList = list;
250
+ }
251
+ setBefore() {
252
+ this.beforeBounds.setListWithFn(this.updatedList.list, worldBounds);
253
+ }
254
+ setAfter() {
255
+ const { list } = this.updatedList;
256
+ if (list.some(leaf => leaf.noBounds)) {
257
+ this.afterBounds.set(bigBounds);
258
+ }
259
+ else {
260
+ this.afterBounds.setListWithFn(list, worldBounds);
261
+ }
262
+ this.updatedBounds.setList([this.beforeBounds, this.afterBounds]);
263
+ }
264
+ merge(data) {
265
+ this.updatedList.addList(data.updatedList.list);
266
+ this.beforeBounds.add(data.beforeBounds);
267
+ this.afterBounds.add(data.afterBounds);
268
+ this.updatedBounds.add(data.updatedBounds);
269
+ }
270
+ destroy() {
271
+ this.updatedList = null;
272
+ }
273
+ }
274
+
275
+ const { updateAllMatrix, updateAllChange } = LeafHelper;
276
+ const debug$1 = Debug.get('Layouter');
277
+ class Layouter {
278
+ constructor(target, userConfig) {
279
+ this.totalTimes = 0;
280
+ this.config = {};
281
+ this.__levelList = new LeafLevelList();
282
+ this.target = target;
283
+ if (userConfig)
284
+ this.config = DataHelper.default(userConfig, this.config);
285
+ this.__listenEvents();
286
+ }
287
+ start() {
288
+ if (this.disabled)
289
+ return;
290
+ this.running = true;
291
+ }
292
+ stop() {
293
+ this.running = false;
294
+ }
295
+ disable() {
296
+ this.stop();
297
+ this.__removeListenEvents();
298
+ this.disabled = true;
299
+ }
300
+ layout() {
301
+ if (!this.running)
302
+ return;
303
+ const { target } = this;
304
+ this.times = 0;
305
+ try {
306
+ target.emit(LayoutEvent.START);
307
+ this.layoutOnce();
308
+ target.emitEvent(new LayoutEvent(LayoutEvent.END, this.layoutedBlocks, this.times));
309
+ }
310
+ catch (e) {
311
+ debug$1.error(e);
312
+ }
313
+ this.layoutedBlocks = null;
314
+ }
315
+ layoutAgain() {
316
+ if (this.layouting) {
317
+ this.waitAgain = true;
318
+ }
319
+ else {
320
+ this.layoutOnce();
321
+ }
322
+ }
323
+ layoutOnce() {
324
+ if (this.layouting)
325
+ return debug$1.warn('layouting');
326
+ if (this.times > 3)
327
+ return debug$1.warn('layout max times');
328
+ this.times++;
329
+ this.totalTimes++;
330
+ this.layouting = true;
331
+ this.target.emit(WatchEvent.REQUEST);
332
+ if (this.totalTimes > 1) {
333
+ this.partLayout();
334
+ }
335
+ else {
336
+ this.fullLayout();
337
+ }
338
+ this.layouting = false;
339
+ if (this.waitAgain) {
340
+ this.waitAgain = false;
341
+ this.layoutOnce();
342
+ }
343
+ }
344
+ partLayout() {
345
+ var _a;
346
+ if (!((_a = this.__updatedList) === null || _a === void 0 ? void 0 : _a.length))
347
+ return;
348
+ const t = Run.start('PartLayout');
349
+ const { target, __updatedList: updateList } = this;
350
+ const { BEFORE, LAYOUT, AFTER } = LayoutEvent;
351
+ const blocks = this.getBlocks(updateList);
352
+ blocks.forEach(item => item.setBefore());
353
+ target.emitEvent(new LayoutEvent(BEFORE, blocks, this.times));
354
+ this.extraBlock = null;
355
+ updateList.sort();
356
+ updateMatrix(updateList, this.__levelList);
357
+ updateBounds(this.__levelList);
358
+ updateChange(updateList);
359
+ if (this.extraBlock)
360
+ blocks.push(this.extraBlock);
361
+ blocks.forEach(item => item.setAfter());
362
+ target.emitEvent(new LayoutEvent(LAYOUT, blocks, this.times));
363
+ target.emitEvent(new LayoutEvent(AFTER, blocks, this.times));
364
+ this.addBlocks(blocks);
365
+ this.__levelList.reset();
366
+ this.__updatedList = null;
367
+ Run.end(t);
368
+ }
369
+ fullLayout() {
370
+ const t = Run.start('FullLayout');
371
+ const { target } = this;
372
+ const { BEFORE, LAYOUT, AFTER } = LayoutEvent;
373
+ const blocks = this.getBlocks(new LeafList(target));
374
+ target.emitEvent(new LayoutEvent(BEFORE, blocks, this.times));
375
+ Layouter.fullLayout(target);
376
+ blocks.forEach(item => { item.setAfter(); });
377
+ target.emitEvent(new LayoutEvent(LAYOUT, blocks, this.times));
378
+ target.emitEvent(new LayoutEvent(AFTER, blocks, this.times));
379
+ this.addBlocks(blocks);
380
+ Run.end(t);
381
+ }
382
+ static fullLayout(target) {
383
+ updateAllMatrix(target, true);
384
+ if (target.isBranch) {
385
+ BranchHelper.updateBounds(target);
386
+ }
387
+ else {
388
+ LeafHelper.updateBounds(target);
389
+ }
390
+ updateAllChange(target);
391
+ }
392
+ addExtra(leaf) {
393
+ const block = this.extraBlock || (this.extraBlock = new LayoutBlockData([]));
394
+ block.updatedList.add(leaf);
395
+ block.beforeBounds.add(leaf.__world);
396
+ }
397
+ createBlock(data) {
398
+ return new LayoutBlockData(data);
399
+ }
400
+ getBlocks(list) {
401
+ return [this.createBlock(list)];
402
+ }
403
+ addBlocks(current) {
404
+ this.layoutedBlocks ? this.layoutedBlocks.push(...current) : this.layoutedBlocks = current;
405
+ }
406
+ __onReceiveWatchData(event) {
407
+ this.__updatedList = event.data.updatedList;
408
+ }
409
+ __listenEvents() {
410
+ const { target } = this;
411
+ this.__eventIds = [
412
+ target.on_(LayoutEvent.REQUEST, this.layout, this),
413
+ target.on_(LayoutEvent.AGAIN, this.layoutAgain, this),
414
+ target.on_(WatchEvent.DATA, this.__onReceiveWatchData, this)
415
+ ];
416
+ }
417
+ __removeListenEvents() {
418
+ this.target.off_(this.__eventIds);
419
+ }
420
+ destroy() {
421
+ if (this.target) {
422
+ this.stop();
423
+ this.__removeListenEvents();
424
+ this.target = this.config = null;
425
+ }
426
+ }
427
+ }
428
+
429
+ const debug = Debug.get('Renderer');
430
+ class Renderer {
431
+ get needFill() { return !!(!this.canvas.allowBackgroundColor && this.config.fill); }
432
+ constructor(target, canvas, userConfig) {
433
+ this.FPS = 60;
434
+ this.totalTimes = 0;
435
+ this.times = 0;
436
+ this.config = {
437
+ usePartRender: true,
438
+ maxFPS: 60
439
+ };
440
+ this.target = target;
441
+ this.canvas = canvas;
442
+ if (userConfig)
443
+ this.config = DataHelper.default(userConfig, this.config);
444
+ this.__listenEvents();
445
+ this.__requestRender();
446
+ }
447
+ start() {
448
+ this.running = true;
449
+ }
450
+ stop() {
451
+ this.running = false;
452
+ }
453
+ update() {
454
+ this.changed = true;
455
+ }
456
+ requestLayout() {
457
+ this.target.emit(LayoutEvent.REQUEST);
458
+ }
459
+ render(callback) {
460
+ if (!(this.running && this.canvas.view)) {
461
+ this.changed = true;
462
+ return;
463
+ }
464
+ const { target } = this;
465
+ this.times = 0;
466
+ this.totalBounds = new Bounds();
467
+ debug.log(target.innerName, '--->');
468
+ try {
469
+ this.emitRender(RenderEvent.START);
470
+ this.renderOnce(callback);
471
+ this.emitRender(RenderEvent.END, this.totalBounds);
472
+ ImageManager.clearRecycled();
473
+ }
474
+ catch (e) {
475
+ this.rendering = false;
476
+ debug.error(e);
477
+ }
478
+ debug.log('-------------|');
479
+ }
480
+ renderAgain() {
481
+ if (this.rendering) {
482
+ this.waitAgain = true;
483
+ }
484
+ else {
485
+ this.renderOnce();
486
+ }
487
+ }
488
+ renderOnce(callback) {
489
+ if (this.rendering)
490
+ return debug.warn('rendering');
491
+ if (this.times > 3)
492
+ return debug.warn('render max times');
493
+ this.times++;
494
+ this.totalTimes++;
495
+ this.rendering = true;
496
+ this.changed = false;
497
+ this.renderBounds = new Bounds();
498
+ this.renderOptions = {};
499
+ if (callback) {
500
+ this.emitRender(RenderEvent.BEFORE);
501
+ callback();
502
+ }
503
+ else {
504
+ this.requestLayout();
505
+ this.emitRender(RenderEvent.BEFORE);
506
+ if (this.config.usePartRender && this.totalTimes > 1) {
507
+ this.partRender();
508
+ }
509
+ else {
510
+ this.fullRender();
511
+ }
512
+ }
513
+ this.emitRender(RenderEvent.RENDER, this.renderBounds, this.renderOptions);
514
+ this.emitRender(RenderEvent.AFTER, this.renderBounds, this.renderOptions);
515
+ this.updateBlocks = null;
516
+ this.rendering = false;
517
+ if (this.waitAgain) {
518
+ this.waitAgain = false;
519
+ this.renderOnce();
520
+ }
521
+ }
522
+ partRender() {
523
+ const { canvas, updateBlocks: list } = this;
524
+ if (!list)
525
+ return debug.warn('PartRender: need update attr');
526
+ this.mergeBlocks();
527
+ list.forEach(block => { if (canvas.bounds.hit(block) && !block.isEmpty())
528
+ this.clipRender(block); });
529
+ }
530
+ clipRender(block) {
531
+ const t = Run.start('PartRender');
532
+ const { canvas } = this;
533
+ const bounds = block.getIntersect(canvas.bounds);
534
+ const includes = block.includes(this.target.__world);
535
+ const realBounds = new Bounds(bounds);
536
+ canvas.save();
537
+ if (includes && !Debug.showRepaint) {
538
+ canvas.clear();
539
+ }
540
+ else {
541
+ bounds.spread(1 + 1 / this.canvas.pixelRatio).ceil();
542
+ canvas.clearWorld(bounds, true);
543
+ canvas.clipWorld(bounds, true);
544
+ }
545
+ this.__render(bounds, includes, realBounds);
546
+ canvas.restore();
547
+ Run.end(t);
548
+ }
549
+ fullRender() {
550
+ const t = Run.start('FullRender');
551
+ const { canvas } = this;
552
+ canvas.save();
553
+ canvas.clear();
554
+ this.__render(canvas.bounds, true);
555
+ canvas.restore();
556
+ Run.end(t);
557
+ }
558
+ __render(bounds, includes, realBounds) {
559
+ const options = bounds.includes(this.target.__world) ? { includes } : { bounds, includes };
560
+ if (this.needFill)
561
+ this.canvas.fillWorld(bounds, this.config.fill);
562
+ if (Debug.showRepaint)
563
+ this.canvas.strokeWorld(bounds, 'red');
564
+ this.target.__render(this.canvas, options);
565
+ this.renderBounds = realBounds || bounds;
566
+ this.renderOptions = options;
567
+ this.totalBounds.isEmpty() ? this.totalBounds = this.renderBounds : this.totalBounds.add(this.renderBounds);
568
+ if (Debug.showHitView)
569
+ this.renderHitView(options);
570
+ if (Debug.showBoundsView)
571
+ this.renderBoundsView(options);
572
+ this.canvas.updateRender();
573
+ }
574
+ renderHitView(_options) { }
575
+ renderBoundsView(_options) { }
576
+ addBlock(block) {
577
+ if (!this.updateBlocks)
578
+ this.updateBlocks = [];
579
+ this.updateBlocks.push(block);
580
+ }
581
+ mergeBlocks() {
582
+ const { updateBlocks: list } = this;
583
+ if (list) {
584
+ const bounds = new Bounds();
585
+ bounds.setList(list);
586
+ list.length = 0;
587
+ list.push(bounds);
588
+ }
589
+ }
590
+ __requestRender() {
591
+ const startTime = Date.now();
592
+ Platform.requestRender(() => {
593
+ this.FPS = Math.min(60, Math.ceil(1000 / (Date.now() - startTime)));
594
+ if (this.running) {
595
+ this.target.emit(AnimateEvent.FRAME);
596
+ if (this.changed && this.canvas.view)
597
+ this.render();
598
+ this.target.emit(RenderEvent.NEXT);
599
+ }
600
+ if (this.target)
601
+ this.__requestRender();
602
+ });
603
+ }
604
+ __onResize(e) {
605
+ if (this.canvas.unreal)
606
+ return;
607
+ if (e.bigger || !e.samePixelRatio) {
608
+ const { width, height } = e.old;
609
+ const bounds = new Bounds(0, 0, width, height);
610
+ if (!bounds.includes(this.target.__world) || this.needFill || !e.samePixelRatio) {
611
+ this.addBlock(this.canvas.bounds);
612
+ this.target.forceUpdate('surface');
613
+ }
614
+ }
615
+ }
616
+ __onLayoutEnd(event) {
617
+ if (event.data)
618
+ event.data.map(item => {
619
+ let empty;
620
+ if (item.updatedList)
621
+ item.updatedList.list.some(leaf => {
622
+ empty = (!leaf.__world.width || !leaf.__world.height);
623
+ if (empty) {
624
+ if (!leaf.isLeafer)
625
+ debug.tip(leaf.innerName, ': empty');
626
+ empty = (!leaf.isBranch || leaf.isBranchLeaf);
627
+ }
628
+ return empty;
629
+ });
630
+ this.addBlock(empty ? this.canvas.bounds : item.updatedBounds);
631
+ });
632
+ }
633
+ emitRender(type, bounds, options) {
634
+ this.target.emitEvent(new RenderEvent(type, this.times, bounds, options));
635
+ }
636
+ __listenEvents() {
637
+ const { target } = this;
638
+ this.__eventIds = [
639
+ target.on_(RenderEvent.REQUEST, this.update, this),
640
+ target.on_(LayoutEvent.END, this.__onLayoutEnd, this),
641
+ target.on_(RenderEvent.AGAIN, this.renderAgain, this),
642
+ target.on_(ResizeEvent.RESIZE, this.__onResize, this)
643
+ ];
644
+ }
645
+ __removeListenEvents() {
646
+ this.target.off_(this.__eventIds);
647
+ }
648
+ destroy() {
649
+ if (this.target) {
650
+ this.stop();
651
+ this.__removeListenEvents();
652
+ this.target = null;
653
+ this.canvas = null;
654
+ this.config = null;
655
+ }
656
+ }
657
+ }
658
+
659
+ Object.assign(Creator, {
660
+ watcher: (target, options) => new Watcher(target, options),
661
+ layouter: (target, options) => new Layouter(target, options),
662
+ renderer: (target, canvas, options) => new Renderer(target, canvas, options),
663
+ selector: (_target, _options) => undefined,
664
+ interaction: (_target, _canvas, _selector, _options) => undefined
665
+ });
666
+ Platform.layout = Layouter.fullLayout;
667
+
668
+ const PaintImage = {};
669
+ const PaintGradient = {};
670
+
671
+ function fillText(ui, canvas) {
672
+ let row;
673
+ const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
674
+ for (let i = 0, len = rows.length; i < len; i++) {
675
+ row = rows[i];
676
+ if (row.text) {
677
+ canvas.fillText(row.text, row.x, row.y);
678
+ }
679
+ else if (row.data) {
680
+ row.data.forEach(charData => {
681
+ canvas.fillText(charData.char, charData.x, row.y);
682
+ });
683
+ }
684
+ if (decorationY)
685
+ canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight);
686
+ }
687
+ }
688
+
689
+ function fill(fill, ui, canvas) {
690
+ canvas.fillStyle = fill;
691
+ ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
692
+ }
693
+ function fills(fills, ui, canvas) {
694
+ let item;
695
+ const { windingRule, __font } = ui.__;
696
+ for (let i = 0, len = fills.length; i < len; i++) {
697
+ item = fills[i];
698
+ if (item.image && PaintImage.checkImage(ui, canvas, item, !__font))
699
+ continue;
700
+ if (item.style) {
701
+ canvas.fillStyle = item.style;
702
+ if (item.transform) {
703
+ canvas.save();
704
+ canvas.transform(item.transform);
705
+ if (item.blendMode)
706
+ canvas.blendMode = item.blendMode;
707
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
708
+ canvas.restore();
709
+ }
710
+ else {
711
+ if (item.blendMode) {
712
+ canvas.saveBlendMode(item.blendMode);
713
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
714
+ canvas.restoreBlendMode();
715
+ }
716
+ else {
717
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
718
+ }
719
+ }
720
+ }
721
+ }
722
+ }
723
+
724
+ function strokeText(stroke, ui, canvas) {
725
+ const { strokeAlign } = ui.__;
726
+ const isStrokes = typeof stroke !== 'string';
727
+ switch (strokeAlign) {
728
+ case 'center':
729
+ canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
730
+ isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
731
+ break;
732
+ case 'inside':
733
+ drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
734
+ break;
735
+ case 'outside':
736
+ drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
737
+ break;
738
+ }
739
+ }
740
+ function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
741
+ const { __strokeWidth, __font } = ui.__;
742
+ const out = canvas.getSameCanvas(true, true);
743
+ out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__);
744
+ out.font = __font;
745
+ isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
746
+ out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
747
+ fillText(ui, out);
748
+ out.blendMode = 'normal';
749
+ if (ui.__worldFlipped) {
750
+ canvas.copyWorldByReset(out, ui.__nowWorld);
751
+ }
752
+ else {
753
+ canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
754
+ }
755
+ out.recycle(ui.__nowWorld);
756
+ }
757
+ function drawTextStroke(ui, canvas) {
758
+ let row;
759
+ const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
760
+ for (let i = 0, len = rows.length; i < len; i++) {
761
+ row = rows[i];
762
+ if (row.text) {
763
+ canvas.strokeText(row.text, row.x, row.y);
764
+ }
765
+ else if (row.data) {
766
+ row.data.forEach(charData => {
767
+ canvas.strokeText(charData.char, charData.x, row.y);
768
+ });
769
+ }
770
+ if (decorationY)
771
+ canvas.strokeRect(row.x, row.y + decorationY, row.width, decorationHeight);
772
+ }
773
+ }
774
+ function drawStrokesStyle(strokes, isText, ui, canvas) {
775
+ let item;
776
+ for (let i = 0, len = strokes.length; i < len; i++) {
777
+ item = strokes[i];
778
+ if (item.image && PaintImage.checkImage(ui, canvas, item, false))
779
+ continue;
780
+ if (item.style) {
781
+ canvas.strokeStyle = item.style;
782
+ if (item.blendMode) {
783
+ canvas.saveBlendMode(item.blendMode);
784
+ isText ? drawTextStroke(ui, canvas) : canvas.stroke();
785
+ canvas.restoreBlendMode();
786
+ }
787
+ else {
788
+ isText ? drawTextStroke(ui, canvas) : canvas.stroke();
789
+ }
790
+ }
791
+ }
792
+ }
793
+
794
+ function stroke(stroke, ui, canvas) {
795
+ const options = ui.__;
796
+ const { __strokeWidth, strokeAlign, __font } = options;
797
+ if (!__strokeWidth)
798
+ return;
799
+ if (__font) {
800
+ strokeText(stroke, ui, canvas);
801
+ }
802
+ else {
803
+ switch (strokeAlign) {
804
+ case 'center':
805
+ canvas.setStroke(stroke, __strokeWidth, options);
806
+ canvas.stroke();
807
+ break;
808
+ case 'inside':
809
+ canvas.save();
810
+ canvas.setStroke(stroke, __strokeWidth * 2, options);
811
+ options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
812
+ canvas.stroke();
813
+ canvas.restore();
814
+ break;
815
+ case 'outside':
816
+ const out = canvas.getSameCanvas(true, true);
817
+ out.setStroke(stroke, __strokeWidth * 2, options);
818
+ ui.__drawRenderPath(out);
819
+ out.stroke();
820
+ options.windingRule ? out.clip(options.windingRule) : out.clip();
821
+ out.clearWorld(ui.__layout.renderBounds);
822
+ if (ui.__worldFlipped) {
823
+ canvas.copyWorldByReset(out, ui.__nowWorld);
824
+ }
825
+ else {
826
+ canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
827
+ }
828
+ out.recycle(ui.__nowWorld);
829
+ break;
830
+ }
831
+ }
832
+ }
833
+ function strokes(strokes, ui, canvas) {
834
+ const options = ui.__;
835
+ const { __strokeWidth, strokeAlign, __font } = options;
836
+ if (!__strokeWidth)
837
+ return;
838
+ if (__font) {
839
+ strokeText(strokes, ui, canvas);
840
+ }
841
+ else {
842
+ switch (strokeAlign) {
843
+ case 'center':
844
+ canvas.setStroke(undefined, __strokeWidth, options);
845
+ drawStrokesStyle(strokes, false, ui, canvas);
846
+ break;
847
+ case 'inside':
848
+ canvas.save();
849
+ canvas.setStroke(undefined, __strokeWidth * 2, options);
850
+ options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
851
+ drawStrokesStyle(strokes, false, ui, canvas);
852
+ canvas.restore();
853
+ break;
854
+ case 'outside':
855
+ const { renderBounds } = ui.__layout;
856
+ const out = canvas.getSameCanvas(true, true);
857
+ ui.__drawRenderPath(out);
858
+ out.setStroke(undefined, __strokeWidth * 2, options);
859
+ drawStrokesStyle(strokes, false, ui, out);
860
+ options.windingRule ? out.clip(options.windingRule) : out.clip();
861
+ out.clearWorld(renderBounds);
862
+ if (ui.__worldFlipped) {
863
+ canvas.copyWorldByReset(out, ui.__nowWorld);
864
+ }
865
+ else {
866
+ canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
867
+ }
868
+ out.recycle(ui.__nowWorld);
869
+ break;
870
+ }
871
+ }
872
+ }
873
+
874
+ const { getSpread, getOuterOf, getByMove, getIntersectData } = BoundsHelper;
875
+ function shape(ui, current, options) {
876
+ const canvas = current.getSameCanvas();
877
+ const nowWorld = ui.__nowWorld;
878
+ let bounds, fitMatrix, shapeBounds, worldCanvas;
879
+ let { scaleX, scaleY } = nowWorld;
880
+ if (scaleX < 0)
881
+ scaleX = -scaleX;
882
+ if (scaleY < 0)
883
+ scaleY = -scaleY;
884
+ if (current.bounds.includes(nowWorld)) {
885
+ worldCanvas = canvas;
886
+ bounds = shapeBounds = nowWorld;
887
+ }
888
+ else {
889
+ const { renderShapeSpread: spread } = ui.__layout;
890
+ const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, spread * scaleX, spread * scaleY) : current.bounds, nowWorld);
891
+ fitMatrix = current.bounds.getFitMatrix(worldClipBounds);
892
+ let { a: fitScaleX, d: fitScaleY } = fitMatrix;
893
+ if (fitMatrix.a < 1) {
894
+ worldCanvas = current.getSameCanvas();
895
+ ui.__renderShape(worldCanvas, options);
896
+ scaleX *= fitScaleX;
897
+ scaleY *= fitScaleY;
898
+ }
899
+ shapeBounds = getOuterOf(nowWorld, fitMatrix);
900
+ bounds = getByMove(shapeBounds, -fitMatrix.e, -fitMatrix.f);
901
+ if (options.matrix) {
902
+ const { matrix } = options;
903
+ fitMatrix.multiply(matrix);
904
+ fitScaleX *= matrix.scaleX;
905
+ fitScaleY *= matrix.scaleY;
906
+ }
907
+ options = Object.assign(Object.assign({}, options), { matrix: fitMatrix.withScale(fitScaleX, fitScaleY) });
908
+ }
909
+ ui.__renderShape(canvas, options);
910
+ return {
911
+ canvas, matrix: fitMatrix, bounds,
912
+ worldCanvas, shapeBounds, scaleX, scaleY
913
+ };
914
+ }
915
+
916
+ let recycleMap;
917
+ function compute(attrName, ui) {
918
+ const data = ui.__, leafPaints = [];
919
+ let paints = data.__input[attrName], hasOpacityPixel;
920
+ if (!(paints instanceof Array))
921
+ paints = [paints];
922
+ recycleMap = PaintImage.recycleImage(attrName, data);
923
+ for (let i = 0, len = paints.length, item; i < len; i++) {
924
+ item = getLeafPaint(attrName, paints[i], ui);
925
+ if (item)
926
+ leafPaints.push(item);
927
+ }
928
+ data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
929
+ if (leafPaints.length && leafPaints[0].image)
930
+ hasOpacityPixel = leafPaints[0].image.hasOpacityPixel;
931
+ if (attrName === 'fill') {
932
+ data.__pixelFill = hasOpacityPixel;
933
+ }
934
+ else {
935
+ data.__pixelStroke = hasOpacityPixel;
936
+ }
937
+ }
938
+ function getLeafPaint(attrName, paint, ui) {
939
+ if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
940
+ return undefined;
941
+ const { boxBounds } = ui.__layout;
942
+ switch (paint.type) {
943
+ case 'solid':
944
+ let { type, blendMode, color, opacity } = paint;
945
+ return { type, blendMode, style: ColorConvert.string(color, opacity) };
946
+ case 'image':
947
+ return PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
948
+ case 'linear':
949
+ return PaintGradient.linearGradient(paint, boxBounds);
950
+ case 'radial':
951
+ return PaintGradient.radialGradient(paint, boxBounds);
952
+ case 'angular':
953
+ return PaintGradient.conicGradient(paint, boxBounds);
954
+ default:
955
+ return paint.r ? { type: 'solid', style: ColorConvert.string(paint) } : undefined;
956
+ }
957
+ }
958
+
959
+ const PaintModule = {
960
+ compute,
961
+ fill,
962
+ fills,
963
+ fillText,
964
+ stroke,
965
+ strokes,
966
+ strokeText,
967
+ drawTextStroke,
968
+ shape
969
+ };
970
+
971
+ let origin = {};
972
+ const { get: get$4, rotateOfOuter: rotateOfOuter$2, translate: translate$1, scaleOfOuter: scaleOfOuter$2, scale: scaleHelper, rotate } = MatrixHelper;
973
+ function fillOrFitMode(data, mode, box, width, height, rotation) {
974
+ const transform = get$4();
975
+ const swap = rotation && rotation !== 180;
976
+ const sw = box.width / (swap ? height : width);
977
+ const sh = box.height / (swap ? width : height);
978
+ const scale = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
979
+ const x = box.x + (box.width - width * scale) / 2;
980
+ const y = box.y + (box.height - height * scale) / 2;
981
+ translate$1(transform, x, y);
982
+ scaleHelper(transform, scale);
983
+ if (rotation)
984
+ rotateOfOuter$2(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
985
+ data.scaleX = data.scaleY = scale;
986
+ data.transform = transform;
987
+ }
988
+ function clipMode(data, box, x, y, scaleX, scaleY, rotation) {
989
+ const transform = get$4();
990
+ translate$1(transform, box.x, box.y);
991
+ if (x || y)
992
+ translate$1(transform, x, y);
993
+ if (scaleX) {
994
+ scaleHelper(transform, scaleX, scaleY);
995
+ data.scaleX = transform.a;
996
+ data.scaleY = transform.d;
997
+ }
998
+ if (rotation)
999
+ rotate(transform, rotation);
1000
+ data.transform = transform;
1001
+ }
1002
+ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation) {
1003
+ const transform = get$4();
1004
+ if (rotation) {
1005
+ rotate(transform, rotation);
1006
+ switch (rotation) {
1007
+ case 90:
1008
+ translate$1(transform, height, 0);
1009
+ break;
1010
+ case 180:
1011
+ translate$1(transform, width, height);
1012
+ break;
1013
+ case 270:
1014
+ translate$1(transform, 0, width);
1015
+ break;
1016
+ }
1017
+ }
1018
+ origin.x = box.x;
1019
+ origin.y = box.y;
1020
+ if (x || y)
1021
+ origin.x += x, origin.y += y;
1022
+ translate$1(transform, origin.x, origin.y);
1023
+ if (scaleX) {
1024
+ scaleOfOuter$2(transform, origin, scaleX, scaleY);
1025
+ data.scaleX = scaleX;
1026
+ data.scaleY = scaleY;
1027
+ }
1028
+ data.transform = transform;
1029
+ }
1030
+
1031
+ const { get: get$3, translate } = MatrixHelper;
1032
+ function createData(leafPaint, image, paint, box) {
1033
+ let { width, height } = image;
1034
+ const { opacity, mode, offset, scale, size, rotation, blendMode, repeat } = paint;
1035
+ const sameBox = box.width === width && box.height === height;
1036
+ if (blendMode)
1037
+ leafPaint.blendMode = blendMode;
1038
+ const data = leafPaint.data = { mode };
1039
+ let x, y, scaleX, scaleY;
1040
+ if (offset)
1041
+ x = offset.x, y = offset.y;
1042
+ if (size) {
1043
+ scaleX = (typeof size === 'number' ? size : size.width) / width;
1044
+ scaleY = (typeof size === 'number' ? size : size.height) / height;
1045
+ }
1046
+ else if (scale) {
1047
+ scaleX = typeof scale === 'number' ? scale : scale.x;
1048
+ scaleY = typeof scale === 'number' ? scale : scale.y;
1049
+ }
1050
+ switch (mode) {
1051
+ case 'strench':
1052
+ if (!sameBox)
1053
+ width = box.width, height = box.height;
1054
+ if (box.x || box.y) {
1055
+ data.transform = get$3();
1056
+ translate(data.transform, box.x, box.y);
1057
+ }
1058
+ break;
1059
+ case 'clip':
1060
+ if (offset || scaleX || rotation)
1061
+ clipMode(data, box, x, y, scaleX, scaleY, rotation);
1062
+ break;
1063
+ case 'repeat':
1064
+ if (!sameBox || scaleX || rotation)
1065
+ repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation);
1066
+ if (!repeat)
1067
+ data.repeat = 'repeat';
1068
+ break;
1069
+ case 'fit':
1070
+ case 'cover':
1071
+ default:
1072
+ if (!sameBox || rotation)
1073
+ fillOrFitMode(data, mode, box, width, height, rotation);
1074
+ }
1075
+ data.width = width;
1076
+ data.height = height;
1077
+ if (opacity)
1078
+ data.opacity = opacity;
1079
+ if (repeat)
1080
+ data.repeat = typeof repeat === 'string' ? (repeat === 'x' ? 'repeat-x' : 'repeat-y') : 'repeat';
1081
+ }
1082
+
1083
+ let cache, box = new Bounds();
1084
+ const { isSame } = BoundsHelper;
1085
+ function image(ui, attrName, paint, boxBounds, firstUse) {
1086
+ let leafPaint, event;
1087
+ const image = ImageManager.get(paint);
1088
+ if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
1089
+ leafPaint = cache.leafPaint;
1090
+ }
1091
+ else {
1092
+ leafPaint = { type: paint.type };
1093
+ leafPaint.image = image;
1094
+ cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
1095
+ }
1096
+ if (firstUse || image.loading)
1097
+ event = { image, attrName, attrValue: paint };
1098
+ if (image.ready) {
1099
+ checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
1100
+ if (firstUse) {
1101
+ onLoad(ui, event);
1102
+ onLoadSuccess(ui, event);
1103
+ }
1104
+ }
1105
+ else if (image.error) {
1106
+ if (firstUse)
1107
+ onLoadError(ui, event, image.error);
1108
+ }
1109
+ else {
1110
+ if (firstUse)
1111
+ onLoad(ui, event);
1112
+ leafPaint.loadId = image.load(() => {
1113
+ if (!ui.destroyed) {
1114
+ if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds))
1115
+ ui.forceUpdate('surface');
1116
+ onLoadSuccess(ui, event);
1117
+ }
1118
+ leafPaint.loadId = null;
1119
+ }, (error) => {
1120
+ onLoadError(ui, event, error);
1121
+ leafPaint.loadId = null;
1122
+ });
1123
+ }
1124
+ return leafPaint;
1125
+ }
1126
+ function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
1127
+ if (attrName === 'fill' && !ui.__.__naturalWidth) {
1128
+ const data = ui.__;
1129
+ data.__naturalWidth = image.width;
1130
+ data.__naturalHeight = image.height;
1131
+ if (data.__autoWidth || data.__autoHeight) {
1132
+ ui.forceUpdate('width');
1133
+ if (ui.__proxyData) {
1134
+ ui.setProxyAttr('width', data.width);
1135
+ ui.setProxyAttr('height', data.height);
1136
+ }
1137
+ return false;
1138
+ }
1139
+ }
1140
+ if (!leafPaint.data)
1141
+ createData(leafPaint, image, paint, boxBounds);
1142
+ return true;
1143
+ }
1144
+ function onLoad(ui, event) {
1145
+ emit(ui, ImageEvent.LOAD, event);
1146
+ }
1147
+ function onLoadSuccess(ui, event) {
1148
+ emit(ui, ImageEvent.LOADED, event);
1149
+ }
1150
+ function onLoadError(ui, event, error) {
1151
+ event.error = error;
1152
+ ui.forceUpdate('surface');
1153
+ emit(ui, ImageEvent.ERROR, event);
1154
+ }
1155
+ function emit(ui, type, data) {
1156
+ if (ui.hasEvent(type))
1157
+ ui.emitEvent(new ImageEvent(type, data));
1158
+ }
1159
+
1160
+ const { get: get$2, scale, copy: copy$1 } = MatrixHelper;
1161
+ const { round, abs: abs$1 } = Math;
1162
+ function createPattern(ui, paint, pixelRatio) {
1163
+ let { scaleX, scaleY } = ui.__world;
1164
+ const id = scaleX + '-' + scaleY;
1165
+ if (paint.patternId !== id && !ui.destroyed) {
1166
+ scaleX = abs$1(scaleX);
1167
+ scaleY = abs$1(scaleY);
1168
+ const { image, data } = paint;
1169
+ let imageScale, imageMatrix, { width, height, scaleX: sx, scaleY: sy, opacity, transform, repeat } = data;
1170
+ if (sx) {
1171
+ imageMatrix = get$2();
1172
+ copy$1(imageMatrix, transform);
1173
+ scale(imageMatrix, 1 / sx, 1 / sy);
1174
+ scaleX *= sx;
1175
+ scaleY *= sy;
1176
+ }
1177
+ scaleX *= pixelRatio;
1178
+ scaleY *= pixelRatio;
1179
+ width *= scaleX;
1180
+ height *= scaleY;
1181
+ const size = width * height;
1182
+ if (!repeat) {
1183
+ if (size > Platform.image.maxCacheSize)
1184
+ return false;
1185
+ }
1186
+ let maxSize = Platform.image.maxPatternSize;
1187
+ if (!image.isSVG) {
1188
+ const imageSize = image.width * image.height;
1189
+ if (maxSize > imageSize)
1190
+ maxSize = imageSize;
1191
+ }
1192
+ if (size > maxSize)
1193
+ imageScale = Math.sqrt(size / maxSize);
1194
+ if (imageScale) {
1195
+ scaleX /= imageScale;
1196
+ scaleY /= imageScale;
1197
+ width /= imageScale;
1198
+ height /= imageScale;
1199
+ }
1200
+ if (sx) {
1201
+ scaleX /= sx;
1202
+ scaleY /= sy;
1203
+ }
1204
+ if (transform || scaleX !== 1 || scaleY !== 1) {
1205
+ if (!imageMatrix) {
1206
+ imageMatrix = get$2();
1207
+ if (transform)
1208
+ copy$1(imageMatrix, transform);
1209
+ }
1210
+ scale(imageMatrix, 1 / scaleX, 1 / scaleY);
1211
+ }
1212
+ const canvas = image.getCanvas(width < 1 ? 1 : round(width), height < 1 ? 1 : round(height), opacity);
1213
+ const pattern = image.getPattern(canvas, repeat || (Platform.origin.noRepeat || 'no-repeat'), imageMatrix, paint);
1214
+ paint.style = pattern;
1215
+ paint.patternId = id;
1216
+ return true;
1217
+ }
1218
+ else {
1219
+ return false;
1220
+ }
1221
+ }
1222
+
1223
+ /******************************************************************************
1224
+ Copyright (c) Microsoft Corporation.
1225
+
1226
+ Permission to use, copy, modify, and/or distribute this software for any
1227
+ purpose with or without fee is hereby granted.
1228
+
1229
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
1230
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1231
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
1232
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1233
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
1234
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1235
+ PERFORMANCE OF THIS SOFTWARE.
1236
+ ***************************************************************************** */
1237
+ /* global Reflect, Promise, SuppressedError, Symbol */
1238
+
1239
+
1240
+ function __awaiter(thisArg, _arguments, P, generator) {
1241
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
1242
+ return new (P || (P = Promise))(function (resolve, reject) {
1243
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
1244
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
1245
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
1246
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
1247
+ });
1248
+ }
1249
+
1250
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
1251
+ var e = new Error(message);
1252
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1253
+ };
1254
+
1255
+ const { abs } = Math;
1256
+ function checkImage(ui, canvas, paint, allowPaint) {
1257
+ const { scaleX, scaleY } = ui.__world;
1258
+ if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
1259
+ return false;
1260
+ }
1261
+ else {
1262
+ const { data } = paint;
1263
+ if (allowPaint) {
1264
+ if (!data.repeat) {
1265
+ let { width, height } = data;
1266
+ width *= abs(scaleX) * canvas.pixelRatio;
1267
+ height *= abs(scaleY) * canvas.pixelRatio;
1268
+ if (data.scaleX) {
1269
+ width *= data.scaleX;
1270
+ height *= data.scaleY;
1271
+ }
1272
+ allowPaint = width * height > Platform.image.maxCacheSize;
1273
+ }
1274
+ else {
1275
+ allowPaint = false;
1276
+ }
1277
+ }
1278
+ if (allowPaint) {
1279
+ canvas.save();
1280
+ canvas.clip();
1281
+ if (paint.blendMode)
1282
+ canvas.blendMode = paint.blendMode;
1283
+ if (data.opacity)
1284
+ canvas.opacity *= data.opacity;
1285
+ if (data.transform)
1286
+ canvas.transform(data.transform);
1287
+ canvas.drawImage(paint.image.view, 0, 0, data.width, data.height);
1288
+ canvas.restore();
1289
+ return true;
1290
+ }
1291
+ else {
1292
+ if (!paint.style || Export.running) {
1293
+ createPattern(ui, paint, canvas.pixelRatio);
1294
+ }
1295
+ else {
1296
+ if (!paint.patternTask) {
1297
+ paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
1298
+ paint.patternTask = null;
1299
+ if (canvas.bounds.hit(ui.__world))
1300
+ createPattern(ui, paint, canvas.pixelRatio);
1301
+ ui.forceUpdate('surface');
1302
+ }), 300);
1303
+ }
1304
+ }
1305
+ return false;
1306
+ }
1307
+ }
1308
+ }
1309
+
1310
+ function recycleImage(attrName, data) {
1311
+ const paints = data['_' + attrName];
1312
+ if (paints instanceof Array) {
1313
+ let image, recycleMap, input, url;
1314
+ for (let i = 0, len = paints.length; i < len; i++) {
1315
+ image = paints[i].image;
1316
+ url = image && image.url;
1317
+ if (url) {
1318
+ if (!recycleMap)
1319
+ recycleMap = {};
1320
+ recycleMap[url] = true;
1321
+ ImageManager.recycle(image);
1322
+ if (image.loading) {
1323
+ if (!input) {
1324
+ input = (data.__input && data.__input[attrName]) || [];
1325
+ if (!(input instanceof Array))
1326
+ input = [input];
1327
+ }
1328
+ image.unload(paints[i].loadId, !input.some((item) => item.url === url));
1329
+ }
1330
+ }
1331
+ }
1332
+ return recycleMap;
1333
+ }
1334
+ return null;
1335
+ }
1336
+
1337
+ const PaintImageModule = {
1338
+ image,
1339
+ createData,
1340
+ fillOrFitMode,
1341
+ clipMode,
1342
+ repeatMode,
1343
+ createPattern,
1344
+ checkImage,
1345
+ recycleImage
1346
+ };
1347
+
1348
+ const defaultFrom$2 = { x: 0.5, y: 0 };
1349
+ const defaultTo$2 = { x: 0.5, y: 1 };
1350
+ function linearGradient(paint, box) {
1351
+ let { from, to, type, blendMode, opacity } = paint;
1352
+ from || (from = defaultFrom$2);
1353
+ to || (to = defaultTo$2);
1354
+ 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);
1355
+ applyStops(style, paint.stops, opacity);
1356
+ const data = { type, style };
1357
+ if (blendMode)
1358
+ data.blendMode = blendMode;
1359
+ return data;
1360
+ }
1361
+ function applyStops(gradient, stops, opacity) {
1362
+ let stop;
1363
+ for (let i = 0, len = stops.length; i < len; i++) {
1364
+ stop = stops[i];
1365
+ gradient.addColorStop(stop.offset, ColorConvert.string(stop.color, opacity));
1366
+ }
1367
+ }
1368
+
1369
+ const { set: set$1, getAngle: getAngle$1, getDistance: getDistance$1 } = PointHelper;
1370
+ const { get: get$1, rotateOfOuter: rotateOfOuter$1, scaleOfOuter: scaleOfOuter$1 } = MatrixHelper;
1371
+ const defaultFrom$1 = { x: 0.5, y: 0.5 };
1372
+ const defaultTo$1 = { x: 0.5, y: 1 };
1373
+ const realFrom$1 = {};
1374
+ const realTo$1 = {};
1375
+ function radialGradient(paint, box) {
1376
+ let { from, to, type, opacity, blendMode, stretch } = paint;
1377
+ from || (from = defaultFrom$1);
1378
+ to || (to = defaultTo$1);
1379
+ const { x, y, width, height } = box;
1380
+ set$1(realFrom$1, x + from.x * width, y + from.y * height);
1381
+ set$1(realTo$1, x + to.x * width, y + to.y * height);
1382
+ let transform;
1383
+ if (width !== height || stretch) {
1384
+ transform = get$1();
1385
+ scaleOfOuter$1(transform, realFrom$1, width / height * (stretch || 1), 1);
1386
+ rotateOfOuter$1(transform, realFrom$1, getAngle$1(realFrom$1, realTo$1) + 90);
1387
+ }
1388
+ const style = Platform.canvas.createRadialGradient(realFrom$1.x, realFrom$1.y, 0, realFrom$1.x, realFrom$1.y, getDistance$1(realFrom$1, realTo$1));
1389
+ applyStops(style, paint.stops, opacity);
1390
+ const data = { type, style, transform };
1391
+ if (blendMode)
1392
+ data.blendMode = blendMode;
1393
+ return data;
1394
+ }
1395
+
1396
+ const { set, getAngle, getDistance } = PointHelper;
1397
+ const { get, rotateOfOuter, scaleOfOuter } = MatrixHelper;
1398
+ const defaultFrom = { x: 0.5, y: 0.5 };
1399
+ const defaultTo = { x: 0.5, y: 1 };
1400
+ const realFrom = {};
1401
+ const realTo = {};
1402
+ function conicGradient(paint, box) {
1403
+ let { from, to, type, opacity, blendMode, stretch } = paint;
1404
+ from || (from = defaultFrom);
1405
+ to || (to = defaultTo);
1406
+ const { x, y, width, height } = box;
1407
+ set(realFrom, x + from.x * width, y + from.y * height);
1408
+ set(realTo, x + to.x * width, y + to.y * height);
1409
+ const transform = get();
1410
+ const angle = getAngle(realFrom, realTo);
1411
+ if (Platform.conicGradientRotate90) {
1412
+ scaleOfOuter(transform, realFrom, width / height * (stretch || 1), 1);
1413
+ rotateOfOuter(transform, realFrom, angle + 90);
1414
+ }
1415
+ else {
1416
+ scaleOfOuter(transform, realFrom, 1, width / height * (stretch || 1));
1417
+ rotateOfOuter(transform, realFrom, angle);
1418
+ }
1419
+ 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));
1420
+ applyStops(style, paint.stops, opacity);
1421
+ const data = { type, style, transform };
1422
+ if (blendMode)
1423
+ data.blendMode = blendMode;
1424
+ return data;
1425
+ }
1426
+
1427
+ const PaintGradientModule = {
1428
+ linearGradient,
1429
+ radialGradient,
1430
+ conicGradient
1431
+ };
1432
+
1433
+ const { copy, toOffsetOutBounds: toOffsetOutBounds$1 } = BoundsHelper;
1434
+ const tempBounds = {};
1435
+ const offsetOutBounds$1 = {};
1436
+ function shadow(ui, current, shape) {
1437
+ let copyBounds, spreadScale;
1438
+ const { __nowWorld: nowWorld, __layout } = ui;
1439
+ const { shadow } = ui.__;
1440
+ const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
1441
+ const other = current.getSameCanvas();
1442
+ const end = shadow.length - 1;
1443
+ toOffsetOutBounds$1(bounds, offsetOutBounds$1);
1444
+ shadow.forEach((item, index) => {
1445
+ other.setWorldShadow((offsetOutBounds$1.offsetX + item.x * scaleX), (offsetOutBounds$1.offsetY + item.y * scaleY), item.blur * scaleX, item.color);
1446
+ spreadScale = item.spread ? 1 + item.spread * 2 / (__layout.boxBounds.width + (__layout.strokeBoxSpread || 0) * 2) : 0;
1447
+ drawWorldShadow(other, offsetOutBounds$1, spreadScale, shape);
1448
+ copyBounds = bounds;
1449
+ if (item.box) {
1450
+ other.restore();
1451
+ other.save();
1452
+ if (worldCanvas) {
1453
+ other.copyWorld(other, bounds, nowWorld, 'copy');
1454
+ copyBounds = nowWorld;
1455
+ }
1456
+ worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
1457
+ }
1458
+ if (ui.__worldFlipped) {
1459
+ current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1460
+ }
1461
+ else {
1462
+ current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1463
+ }
1464
+ if (end && index < end)
1465
+ other.clearWorld(copyBounds, true);
1466
+ });
1467
+ other.recycle(copyBounds);
1468
+ }
1469
+ function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
1470
+ const { bounds, shapeBounds } = shape;
1471
+ if (Platform.fullImageShadow) {
1472
+ copy(tempBounds, canvas.bounds);
1473
+ tempBounds.x += (outBounds.x - shapeBounds.x);
1474
+ tempBounds.y += (outBounds.y - shapeBounds.y);
1475
+ if (spreadScale) {
1476
+ const { matrix } = shape;
1477
+ tempBounds.x -= (bounds.x + (matrix ? matrix.e : 0) + bounds.width / 2) * (spreadScale - 1);
1478
+ tempBounds.y -= (bounds.y + (matrix ? matrix.f : 0) + bounds.height / 2) * (spreadScale - 1);
1479
+ tempBounds.width *= spreadScale;
1480
+ tempBounds.height *= spreadScale;
1481
+ }
1482
+ canvas.copyWorld(shape.canvas, canvas.bounds, tempBounds);
1483
+ }
1484
+ else {
1485
+ if (spreadScale) {
1486
+ copy(tempBounds, outBounds);
1487
+ tempBounds.x -= (outBounds.width / 2) * (spreadScale - 1);
1488
+ tempBounds.y -= (outBounds.height / 2) * (spreadScale - 1);
1489
+ tempBounds.width *= spreadScale;
1490
+ tempBounds.height *= spreadScale;
1491
+ }
1492
+ canvas.copyWorld(shape.canvas, shapeBounds, spreadScale ? tempBounds : outBounds);
1493
+ }
1494
+ }
1495
+
1496
+ const { toOffsetOutBounds } = BoundsHelper;
1497
+ const offsetOutBounds = {};
1498
+ function innerShadow(ui, current, shape) {
1499
+ let copyBounds, spreadScale;
1500
+ const { __nowWorld: nowWorld, __layout: __layout } = ui;
1501
+ const { innerShadow } = ui.__;
1502
+ const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
1503
+ const other = current.getSameCanvas();
1504
+ const end = innerShadow.length - 1;
1505
+ toOffsetOutBounds(bounds, offsetOutBounds);
1506
+ innerShadow.forEach((item, index) => {
1507
+ other.save();
1508
+ other.setWorldShadow((offsetOutBounds.offsetX + item.x * scaleX), (offsetOutBounds.offsetY + item.y * scaleY), item.blur * scaleX);
1509
+ spreadScale = item.spread ? 1 - item.spread * 2 / (__layout.boxBounds.width + (__layout.strokeBoxSpread || 0) * 2) : 0;
1510
+ drawWorldShadow(other, offsetOutBounds, spreadScale, shape);
1511
+ other.restore();
1512
+ if (worldCanvas) {
1513
+ other.copyWorld(other, bounds, nowWorld, 'copy');
1514
+ other.copyWorld(worldCanvas, nowWorld, nowWorld, 'source-out');
1515
+ copyBounds = nowWorld;
1516
+ }
1517
+ else {
1518
+ other.copyWorld(shape.canvas, shapeBounds, bounds, 'source-out');
1519
+ copyBounds = bounds;
1520
+ }
1521
+ other.fillWorld(copyBounds, item.color, 'source-in');
1522
+ if (ui.__worldFlipped) {
1523
+ current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1524
+ }
1525
+ else {
1526
+ current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1527
+ }
1528
+ if (end && index < end)
1529
+ other.clearWorld(copyBounds, true);
1530
+ });
1531
+ other.recycle(copyBounds);
1532
+ }
1533
+
1534
+ function blur(ui, current, origin) {
1535
+ const { blur } = ui.__;
1536
+ origin.setWorldBlur(blur * ui.__world.a);
1537
+ origin.copyWorldToInner(current, ui.__world, ui.__layout.renderBounds);
1538
+ origin.filter = 'none';
1539
+ }
1540
+
1541
+ function backgroundBlur(_ui, _current, _shape) {
1542
+ }
1543
+
1544
+ const EffectModule = {
1545
+ shadow,
1546
+ innerShadow,
1547
+ blur,
1548
+ backgroundBlur
1549
+ };
1550
+
1551
+ const { excludeRenderBounds } = LeafBoundsHelper;
1552
+ Group.prototype.__renderMask = function (canvas, options) {
1553
+ let child, maskCanvas, contentCanvas, maskOpacity, currentMask;
1554
+ const { children } = this;
1555
+ for (let i = 0, len = children.length; i < len; i++) {
1556
+ child = children[i];
1557
+ if (child.__.mask) {
1558
+ if (currentMask) {
1559
+ maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
1560
+ maskCanvas = contentCanvas = null;
1561
+ }
1562
+ if (child.__.maskType === 'path') {
1563
+ if (child.opacity < 1) {
1564
+ currentMask = 'opacity-path';
1565
+ maskOpacity = child.opacity;
1566
+ if (!contentCanvas)
1567
+ contentCanvas = getCanvas(canvas);
1568
+ }
1569
+ else {
1570
+ currentMask = 'path';
1571
+ canvas.save();
1572
+ }
1573
+ child.__clip(contentCanvas || canvas, options);
1574
+ }
1575
+ else {
1576
+ currentMask = 'alpha';
1577
+ if (!maskCanvas)
1578
+ maskCanvas = getCanvas(canvas);
1579
+ if (!contentCanvas)
1580
+ contentCanvas = getCanvas(canvas);
1581
+ child.__render(maskCanvas, options);
1582
+ }
1583
+ if (child.__.maskType !== 'clipping')
1584
+ continue;
1585
+ }
1586
+ if (excludeRenderBounds(child, options))
1587
+ continue;
1588
+ child.__render(contentCanvas || canvas, options);
1589
+ }
1590
+ maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
1591
+ };
1592
+ function maskEnd(leaf, maskMode, canvas, contentCanvas, maskCanvas, maskOpacity) {
1593
+ switch (maskMode) {
1594
+ case 'alpha':
1595
+ usePixelMask(leaf, canvas, contentCanvas, maskCanvas);
1596
+ break;
1597
+ case 'opacity-path':
1598
+ copyContent(leaf, canvas, contentCanvas, maskOpacity);
1599
+ break;
1600
+ case 'path':
1601
+ canvas.restore();
1602
+ }
1603
+ }
1604
+ function getCanvas(canvas) {
1605
+ return canvas.getSameCanvas(false, true);
1606
+ }
1607
+ function usePixelMask(leaf, canvas, content, mask) {
1608
+ const realBounds = leaf.__nowWorld;
1609
+ content.resetTransform();
1610
+ content.opacity = 1;
1611
+ content.useMask(mask, realBounds);
1612
+ mask.recycle(realBounds);
1613
+ copyContent(leaf, canvas, content, 1);
1614
+ }
1615
+ function copyContent(leaf, canvas, content, maskOpacity) {
1616
+ const realBounds = leaf.__nowWorld;
1617
+ canvas.resetTransform();
1618
+ canvas.opacity = maskOpacity;
1619
+ canvas.copyWorld(content, realBounds);
1620
+ content.recycle(realBounds);
1621
+ }
1622
+
1623
+ const money = '¥¥$€££¢¢';
1624
+ const letter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
1625
+ const langBefore = '《(「〈『〖【〔{┌<‘“=' + money;
1626
+ const langAfter = '》)」〉』〗】〕}┐>’”!?,、。:;‰';
1627
+ const langSymbol = '≮≯≈≠=…';
1628
+ const langBreak$1 = '—/~|┆·';
1629
+ const beforeChar = '{[(<\'"' + langBefore;
1630
+ const afterChar = '>)]}%!?,.:;\'"' + langAfter;
1631
+ const symbolChar = afterChar + '_#~&*+\\=|' + langSymbol;
1632
+ const breakChar = '- ' + langBreak$1;
1633
+ const cjkRangeList = [
1634
+ [0x4E00, 0x9FFF],
1635
+ [0x3400, 0x4DBF],
1636
+ [0x20000, 0x2A6DF],
1637
+ [0x2A700, 0x2B73F],
1638
+ [0x2B740, 0x2B81F],
1639
+ [0x2B820, 0x2CEAF],
1640
+ [0x2CEB0, 0x2EBEF],
1641
+ [0x30000, 0x3134F],
1642
+ [0x31350, 0x323AF],
1643
+ [0x2E80, 0x2EFF],
1644
+ [0x2F00, 0x2FDF],
1645
+ [0x2FF0, 0x2FFF],
1646
+ [0x3000, 0x303F],
1647
+ [0x31C0, 0x31EF],
1648
+ [0x3200, 0x32FF],
1649
+ [0x3300, 0x33FF],
1650
+ [0xF900, 0xFAFF],
1651
+ [0xFE30, 0xFE4F],
1652
+ [0x1F200, 0x1F2FF],
1653
+ [0x2F800, 0x2FA1F],
1654
+ ];
1655
+ const cjkReg = new RegExp(cjkRangeList.map(([start, end]) => `[\\u${start.toString(16)}-\\u${end.toString(16)}]`).join('|'));
1656
+ function mapChar(str) {
1657
+ const map = {};
1658
+ str.split('').forEach(char => map[char] = true);
1659
+ return map;
1660
+ }
1661
+ const letterMap = mapChar(letter);
1662
+ const beforeMap = mapChar(beforeChar);
1663
+ const afterMap = mapChar(afterChar);
1664
+ const symbolMap = mapChar(symbolChar);
1665
+ const breakMap = mapChar(breakChar);
1666
+ var CharType;
1667
+ (function (CharType) {
1668
+ CharType[CharType["Letter"] = 0] = "Letter";
1669
+ CharType[CharType["Single"] = 1] = "Single";
1670
+ CharType[CharType["Before"] = 2] = "Before";
1671
+ CharType[CharType["After"] = 3] = "After";
1672
+ CharType[CharType["Symbol"] = 4] = "Symbol";
1673
+ CharType[CharType["Break"] = 5] = "Break";
1674
+ })(CharType || (CharType = {}));
1675
+ const { Letter: Letter$1, Single: Single$1, Before: Before$1, After: After$1, Symbol: Symbol$1, Break: Break$1 } = CharType;
1676
+ function getCharType(char) {
1677
+ if (letterMap[char]) {
1678
+ return Letter$1;
1679
+ }
1680
+ else if (breakMap[char]) {
1681
+ return Break$1;
1682
+ }
1683
+ else if (beforeMap[char]) {
1684
+ return Before$1;
1685
+ }
1686
+ else if (afterMap[char]) {
1687
+ return After$1;
1688
+ }
1689
+ else if (symbolMap[char]) {
1690
+ return Symbol$1;
1691
+ }
1692
+ else if (cjkReg.test(char)) {
1693
+ return Single$1;
1694
+ }
1695
+ else {
1696
+ return Letter$1;
1697
+ }
1698
+ }
1699
+
1700
+ const TextRowHelper = {
1701
+ trimRight(row) {
1702
+ const { words } = row;
1703
+ let trimRight = 0, len = words.length, char;
1704
+ for (let i = len - 1; i > -1; i--) {
1705
+ char = words[i].data[0];
1706
+ if (char.char === ' ') {
1707
+ trimRight++;
1708
+ row.width -= char.width;
1709
+ }
1710
+ else {
1711
+ break;
1712
+ }
1713
+ }
1714
+ if (trimRight)
1715
+ words.splice(len - trimRight, trimRight);
1716
+ }
1717
+ };
1718
+
1719
+ function getTextCase(char, textCase, firstChar) {
1720
+ switch (textCase) {
1721
+ case 'title':
1722
+ return firstChar ? char.toUpperCase() : char;
1723
+ case 'upper':
1724
+ return char.toUpperCase();
1725
+ case 'lower':
1726
+ return char.toLowerCase();
1727
+ default:
1728
+ return char;
1729
+ }
1730
+ }
1731
+
1732
+ const { trimRight } = TextRowHelper;
1733
+ const { Letter, Single, Before, After, Symbol, Break } = CharType;
1734
+ let word, row, wordWidth, rowWidth, realWidth;
1735
+ let char, charWidth, startCharSize, charSize, charType, lastCharType, langBreak, afterBreak, paraStart;
1736
+ let textDrawData, rows = [], bounds;
1737
+ function createRows(drawData, content, style) {
1738
+ textDrawData = drawData;
1739
+ rows = drawData.rows;
1740
+ bounds = drawData.bounds;
1741
+ const { __letterSpacing, paraIndent, textCase } = style;
1742
+ const { canvas } = Platform;
1743
+ const { width, height } = bounds;
1744
+ const charMode = width || height || __letterSpacing || (textCase !== 'none');
1745
+ if (charMode) {
1746
+ const wrap = style.textWrap !== 'none';
1747
+ const breakAll = style.textWrap === 'break';
1748
+ paraStart = true;
1749
+ lastCharType = null;
1750
+ startCharSize = charWidth = charSize = wordWidth = rowWidth = 0;
1751
+ word = { data: [] }, row = { words: [] };
1752
+ for (let i = 0, len = content.length; i < len; i++) {
1753
+ char = content[i];
1754
+ if (char === '\n') {
1755
+ if (wordWidth)
1756
+ addWord();
1757
+ row.paraEnd = true;
1758
+ addRow();
1759
+ paraStart = true;
1760
+ }
1761
+ else {
1762
+ charType = getCharType(char);
1763
+ if (charType === Letter && textCase !== 'none')
1764
+ char = getTextCase(char, textCase, !wordWidth);
1765
+ charWidth = canvas.measureText(char).width;
1766
+ if (__letterSpacing) {
1767
+ if (__letterSpacing < 0)
1768
+ charSize = charWidth;
1769
+ charWidth += __letterSpacing;
1770
+ }
1771
+ langBreak = (charType === Single && (lastCharType === Single || lastCharType === Letter)) || (lastCharType === Single && charType !== After);
1772
+ afterBreak = ((charType === Before || charType === Single) && (lastCharType === Symbol || lastCharType === After));
1773
+ realWidth = paraStart && paraIndent ? width - paraIndent : width;
1774
+ if (wrap && (width && rowWidth + wordWidth + charWidth > realWidth)) {
1775
+ if (breakAll) {
1776
+ if (wordWidth)
1777
+ addWord();
1778
+ addRow();
1779
+ }
1780
+ else {
1781
+ if (!afterBreak)
1782
+ afterBreak = charType === Letter && lastCharType == After;
1783
+ if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
1784
+ if (wordWidth)
1785
+ addWord();
1786
+ addRow();
1787
+ }
1788
+ else {
1789
+ addRow();
1790
+ }
1791
+ }
1792
+ }
1793
+ if (char === ' ' && paraStart !== true && (rowWidth + wordWidth) === 0) ;
1794
+ else {
1795
+ if (charType === Break) {
1796
+ if (char === ' ' && wordWidth)
1797
+ addWord();
1798
+ addChar(char, charWidth);
1799
+ addWord();
1800
+ }
1801
+ else if (langBreak || afterBreak) {
1802
+ if (wordWidth)
1803
+ addWord();
1804
+ addChar(char, charWidth);
1805
+ }
1806
+ else {
1807
+ addChar(char, charWidth);
1808
+ }
1809
+ }
1810
+ lastCharType = charType;
1811
+ }
1812
+ }
1813
+ if (wordWidth)
1814
+ addWord();
1815
+ if (rowWidth)
1816
+ addRow();
1817
+ rows.length > 0 && (rows[rows.length - 1].paraEnd = true);
1818
+ }
1819
+ else {
1820
+ content.split('\n').forEach(content => {
1821
+ textDrawData.paraNumber++;
1822
+ rows.push({ x: paraIndent || 0, text: content, width: canvas.measureText(content).width, paraStart: true });
1823
+ });
1824
+ }
1825
+ }
1826
+ function addChar(char, width) {
1827
+ if (charSize && !startCharSize)
1828
+ startCharSize = charSize;
1829
+ word.data.push({ char, width });
1830
+ wordWidth += width;
1831
+ }
1832
+ function addWord() {
1833
+ rowWidth += wordWidth;
1834
+ word.width = wordWidth;
1835
+ row.words.push(word);
1836
+ word = { data: [] };
1837
+ wordWidth = 0;
1838
+ }
1839
+ function addRow() {
1840
+ if (paraStart) {
1841
+ textDrawData.paraNumber++;
1842
+ row.paraStart = true;
1843
+ paraStart = false;
1844
+ }
1845
+ if (charSize) {
1846
+ row.startCharSize = startCharSize;
1847
+ row.endCharSize = charSize;
1848
+ startCharSize = 0;
1849
+ }
1850
+ row.width = rowWidth;
1851
+ if (bounds.width)
1852
+ trimRight(row);
1853
+ rows.push(row);
1854
+ row = { words: [] };
1855
+ rowWidth = 0;
1856
+ }
1857
+
1858
+ const CharMode = 0;
1859
+ const WordMode = 1;
1860
+ const TextMode = 2;
1861
+ function layoutChar(drawData, style, width, _height) {
1862
+ const { rows } = drawData;
1863
+ const { textAlign, paraIndent, letterSpacing } = style;
1864
+ let charX, addWordWidth, indentWidth, mode, wordChar;
1865
+ rows.forEach(row => {
1866
+ if (row.words) {
1867
+ indentWidth = paraIndent && row.paraStart ? paraIndent : 0;
1868
+ addWordWidth = (width && textAlign === 'justify' && row.words.length > 1) ? (width - row.width - indentWidth) / (row.words.length - 1) : 0;
1869
+ mode = (letterSpacing || row.isOverflow) ? CharMode : (addWordWidth > 0.01 ? WordMode : TextMode);
1870
+ if (row.isOverflow && !letterSpacing)
1871
+ row.textMode = true;
1872
+ if (mode === TextMode) {
1873
+ row.x += indentWidth;
1874
+ toTextChar$1(row);
1875
+ }
1876
+ else {
1877
+ row.x += indentWidth;
1878
+ charX = row.x;
1879
+ row.data = [];
1880
+ row.words.forEach(word => {
1881
+ if (mode === WordMode) {
1882
+ wordChar = { char: '', x: charX };
1883
+ charX = toWordChar(word.data, charX, wordChar);
1884
+ if (wordChar.char !== ' ')
1885
+ row.data.push(wordChar);
1886
+ }
1887
+ else {
1888
+ charX = toChar(word.data, charX, row.data);
1889
+ }
1890
+ if (!row.paraEnd && addWordWidth) {
1891
+ charX += addWordWidth;
1892
+ row.width += addWordWidth;
1893
+ }
1894
+ });
1895
+ }
1896
+ row.words = null;
1897
+ }
1898
+ });
1899
+ }
1900
+ function toTextChar$1(row) {
1901
+ row.text = '';
1902
+ row.words.forEach(word => {
1903
+ word.data.forEach(char => {
1904
+ row.text += char.char;
1905
+ });
1906
+ });
1907
+ }
1908
+ function toWordChar(data, charX, wordChar) {
1909
+ data.forEach(char => {
1910
+ wordChar.char += char.char;
1911
+ charX += char.width;
1912
+ });
1913
+ return charX;
1914
+ }
1915
+ function toChar(data, charX, rowData) {
1916
+ data.forEach(char => {
1917
+ if (char.char !== ' ') {
1918
+ char.x = charX;
1919
+ rowData.push(char);
1920
+ }
1921
+ charX += char.width;
1922
+ });
1923
+ return charX;
1924
+ }
1925
+
1926
+ function layoutText(drawData, style) {
1927
+ const { rows, bounds } = drawData;
1928
+ const { __lineHeight, __baseLine, __letterSpacing, __clipText, textAlign, verticalAlign, paraSpacing } = style;
1929
+ let { x, y, width, height } = bounds, realHeight = __lineHeight * rows.length + (paraSpacing ? paraSpacing * (drawData.paraNumber - 1) : 0);
1930
+ let starY = __baseLine;
1931
+ if (__clipText && realHeight > height) {
1932
+ realHeight = Math.max(height, __lineHeight);
1933
+ drawData.overflow = rows.length;
1934
+ }
1935
+ else {
1936
+ switch (verticalAlign) {
1937
+ case 'middle':
1938
+ y += (height - realHeight) / 2;
1939
+ break;
1940
+ case 'bottom':
1941
+ y += (height - realHeight);
1942
+ }
1943
+ }
1944
+ starY += y;
1945
+ let row, rowX, rowWidth;
1946
+ for (let i = 0, len = rows.length; i < len; i++) {
1947
+ row = rows[i];
1948
+ row.x = x;
1949
+ switch (textAlign) {
1950
+ case 'center':
1951
+ row.x += (width - row.width) / 2;
1952
+ break;
1953
+ case 'right':
1954
+ row.x += width - row.width;
1955
+ }
1956
+ if (row.paraStart && paraSpacing && i > 0)
1957
+ starY += paraSpacing;
1958
+ row.y = starY;
1959
+ starY += __lineHeight;
1960
+ if (drawData.overflow > i && starY > realHeight) {
1961
+ row.isOverflow = true;
1962
+ drawData.overflow = i + 1;
1963
+ }
1964
+ rowX = row.x;
1965
+ rowWidth = row.width;
1966
+ if (__letterSpacing < 0) {
1967
+ if (row.width < 0) {
1968
+ rowWidth = -row.width + style.fontSize + __letterSpacing;
1969
+ rowX -= rowWidth;
1970
+ rowWidth += style.fontSize;
1971
+ }
1972
+ else {
1973
+ rowWidth -= __letterSpacing;
1974
+ }
1975
+ }
1976
+ if (rowX < bounds.x)
1977
+ bounds.x = rowX;
1978
+ if (rowWidth > bounds.width)
1979
+ bounds.width = rowWidth;
1980
+ if (__clipText && width && width < rowWidth) {
1981
+ row.isOverflow = true;
1982
+ if (!drawData.overflow)
1983
+ drawData.overflow = rows.length;
1984
+ }
1985
+ }
1986
+ bounds.y = y;
1987
+ bounds.height = realHeight;
1988
+ }
1989
+
1990
+ function clipText(drawData, style) {
1991
+ const { rows, overflow } = drawData;
1992
+ let { textOverflow } = style;
1993
+ rows.splice(overflow);
1994
+ if (textOverflow !== 'hide') {
1995
+ if (textOverflow === 'ellipsis')
1996
+ textOverflow = '...';
1997
+ let char, charRight;
1998
+ const ellipsisWidth = Platform.canvas.measureText(textOverflow).width;
1999
+ const right = style.x + style.width - ellipsisWidth;
2000
+ const list = style.textWrap === 'none' ? rows : [rows[overflow - 1]];
2001
+ list.forEach(row => {
2002
+ if (row.isOverflow && row.data) {
2003
+ let end = row.data.length - 1;
2004
+ for (let i = end; i > -1; i--) {
2005
+ char = row.data[i];
2006
+ charRight = char.x + char.width;
2007
+ if (i === end && charRight < right) {
2008
+ break;
2009
+ }
2010
+ else if (charRight < right && char.char !== ' ') {
2011
+ row.data.splice(i + 1);
2012
+ row.width -= char.width;
2013
+ break;
2014
+ }
2015
+ row.width -= char.width;
2016
+ }
2017
+ row.width += ellipsisWidth;
2018
+ row.data.push({ char: textOverflow, x: charRight });
2019
+ if (row.textMode)
2020
+ toTextChar(row);
2021
+ }
2022
+ });
2023
+ }
2024
+ }
2025
+ function toTextChar(row) {
2026
+ row.text = '';
2027
+ row.data.forEach(char => {
2028
+ row.text += char.char;
2029
+ });
2030
+ row.data = null;
2031
+ }
2032
+
2033
+ function decorationText(drawData, style) {
2034
+ const { fontSize } = style;
2035
+ drawData.decorationHeight = fontSize / 11;
2036
+ switch (style.textDecoration) {
2037
+ case 'under':
2038
+ drawData.decorationY = fontSize * 0.15;
2039
+ break;
2040
+ case 'delete':
2041
+ drawData.decorationY = -fontSize * 0.35;
2042
+ }
2043
+ }
2044
+
2045
+ const { top, right, bottom, left } = Direction4;
2046
+ function getDrawData(content, style) {
2047
+ if (typeof content !== 'string')
2048
+ content = String(content);
2049
+ let x = 0, y = 0;
2050
+ let width = style.__getInput('width') || 0;
2051
+ let height = style.__getInput('height') || 0;
2052
+ const { textDecoration, __font, __padding: padding } = style;
2053
+ if (padding) {
2054
+ if (width) {
2055
+ x = padding[left];
2056
+ width -= (padding[right] + padding[left]);
2057
+ }
2058
+ if (height) {
2059
+ y = padding[top];
2060
+ height -= (padding[top] + padding[bottom]);
2061
+ }
2062
+ }
2063
+ const drawData = {
2064
+ bounds: { x, y, width, height },
2065
+ rows: [],
2066
+ paraNumber: 0,
2067
+ font: Platform.canvas.font = __font
2068
+ };
2069
+ createRows(drawData, content, style);
2070
+ if (padding)
2071
+ padAutoText(padding, drawData, style, width, height);
2072
+ layoutText(drawData, style);
2073
+ layoutChar(drawData, style, width);
2074
+ if (drawData.overflow)
2075
+ clipText(drawData, style);
2076
+ if (textDecoration !== 'none')
2077
+ decorationText(drawData, style);
2078
+ return drawData;
2079
+ }
2080
+ function padAutoText(padding, drawData, style, width, height) {
2081
+ if (!width) {
2082
+ switch (style.textAlign) {
2083
+ case 'left':
2084
+ offsetText(drawData, 'x', padding[left]);
2085
+ break;
2086
+ case 'right':
2087
+ offsetText(drawData, 'x', -padding[right]);
2088
+ }
2089
+ }
2090
+ if (!height) {
2091
+ switch (style.verticalAlign) {
2092
+ case 'top':
2093
+ offsetText(drawData, 'y', padding[top]);
2094
+ break;
2095
+ case 'bottom':
2096
+ offsetText(drawData, 'y', -padding[bottom]);
2097
+ }
2098
+ }
2099
+ }
2100
+ function offsetText(drawData, attrName, value) {
2101
+ const { bounds, rows } = drawData;
2102
+ bounds[attrName] += value;
2103
+ for (let i = 0; i < rows.length; i++)
2104
+ rows[i][attrName] += value;
2105
+ }
2106
+
2107
+ const TextConvertModule = {
2108
+ getDrawData
2109
+ };
2110
+
2111
+ function string(color, opacity) {
2112
+ if (typeof color === 'string')
2113
+ return color;
2114
+ let a = color.a === undefined ? 1 : color.a;
2115
+ if (opacity)
2116
+ a *= opacity;
2117
+ const rgb = color.r + ',' + color.g + ',' + color.b;
2118
+ return a === 1 ? 'rgb(' + rgb + ')' : 'rgba(' + rgb + ',' + a + ')';
2119
+ }
2120
+
2121
+ const ColorConvertModule = {
2122
+ string
2123
+ };
2124
+
2125
+ const { setPoint, addPoint, toBounds } = TwoPointBoundsHelper;
2126
+ function getTrimBounds(canvas) {
2127
+ const { width, height } = canvas.view;
2128
+ const { data } = canvas.context.getImageData(0, 0, width, height);
2129
+ let x, y, pointBounds, index = 0;
2130
+ for (let i = 0; i < data.length; i += 4) {
2131
+ if (data[i + 3] !== 0) {
2132
+ x = index % width;
2133
+ y = (index - x) / width;
2134
+ pointBounds ? addPoint(pointBounds, x, y) : setPoint(pointBounds = {}, x, y);
2135
+ }
2136
+ index++;
2137
+ }
2138
+ const bounds = new Bounds();
2139
+ toBounds(pointBounds, bounds);
2140
+ return bounds.scale(1 / canvas.pixelRatio).ceil();
2141
+ }
2142
+
2143
+ const ExportModule = {
2144
+ export(leaf, filename, options) {
2145
+ this.running = true;
2146
+ return addTask((success) => new Promise((resolve) => {
2147
+ const over = (result) => {
2148
+ success(result);
2149
+ resolve();
2150
+ this.running = false;
2151
+ };
2152
+ const { leafer } = leaf;
2153
+ if (leafer) {
2154
+ leafer.waitViewCompleted(() => __awaiter(this, void 0, void 0, function* () {
2155
+ let renderBounds, trimBounds, scaleX = 1, scaleY = 1;
2156
+ options = FileHelper.getExportOptions(options);
2157
+ const { scale, pixelRatio, slice, trim } = options;
2158
+ const screenshot = options.screenshot || leaf.isApp;
2159
+ const fill = options.fill === undefined ? ((leaf.isLeafer && screenshot) ? leaf.fill : '') : options.fill;
2160
+ const needFill = FileHelper.isOpaqueImage(filename) || fill, matrix = new Matrix();
2161
+ if (screenshot) {
2162
+ renderBounds = screenshot === true ? (leaf.isLeafer ? leafer.canvas.bounds : leaf.worldRenderBounds) : screenshot;
2163
+ }
2164
+ else {
2165
+ const { localTransform, __world: world } = leaf;
2166
+ matrix.set(world).divide(localTransform).invert();
2167
+ scaleX = 1 / (world.scaleX / leaf.scaleX);
2168
+ scaleY = 1 / (world.scaleY / leaf.scaleY);
2169
+ renderBounds = leaf.getBounds('render', 'local');
2170
+ }
2171
+ let { x, y, width, height } = renderBounds;
2172
+ if (scale) {
2173
+ matrix.scale(scale);
2174
+ width *= scale, height *= scale;
2175
+ scaleX *= scale, scaleY *= scale;
2176
+ }
2177
+ let canvas = Creator.canvas({ width, height, pixelRatio });
2178
+ const renderOptions = { matrix: matrix.translate(-x, -y).withScale(scaleX, scaleY) };
2179
+ if (slice) {
2180
+ leaf = leafer;
2181
+ renderOptions.bounds = canvas.bounds;
2182
+ }
2183
+ canvas.save();
2184
+ leaf.__render(canvas, renderOptions);
2185
+ canvas.restore();
2186
+ if (trim) {
2187
+ trimBounds = getTrimBounds(canvas);
2188
+ const old = canvas, { width, height } = trimBounds;
2189
+ const config = { x: 0, y: 0, width, height, pixelRatio };
2190
+ canvas = Creator.canvas(config);
2191
+ canvas.copyWorld(old, trimBounds, config);
2192
+ }
2193
+ if (needFill)
2194
+ canvas.fillWorld(canvas.bounds, fill || '#FFFFFF', 'destination-over');
2195
+ const data = filename === 'canvas' ? canvas : yield canvas.export(filename, options);
2196
+ over({ data, renderBounds, trimBounds });
2197
+ }));
2198
+ }
2199
+ else {
2200
+ over({ data: false });
2201
+ }
2202
+ }));
2203
+ }
2204
+ };
2205
+ let tasker;
2206
+ function addTask(task) {
2207
+ if (!tasker)
2208
+ tasker = new TaskProcessor();
2209
+ return new Promise((resolve) => {
2210
+ tasker.add(() => __awaiter(this, void 0, void 0, function* () { return yield task(resolve); }), { parallel: false });
2211
+ });
2212
+ }
2213
+
2214
+ Object.assign(TextConvert, TextConvertModule);
2215
+ Object.assign(ColorConvert, ColorConvertModule);
2216
+ Object.assign(Paint, PaintModule);
2217
+ Object.assign(PaintImage$1, PaintImageModule);
2218
+ Object.assign(PaintGradient$1, PaintGradientModule);
2219
+ Object.assign(Effect, EffectModule);
2220
+ Object.assign(Export, ExportModule);
2221
+
2222
+ useCanvas();
2223
+
2224
+ export { Layouter, LeaferCanvas, Renderer, Watcher, useCanvas };