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