leafer-draw 1.0.1 → 1.0.3

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