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