@leafer-ui/miniapp 1.0.0-rc.2 → 1.0.0-rc.20

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