@leafer-ui/node 1.0.0-rc.3 → 1.0.0-rc.30

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