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