@leafer-ui/node 1.0.0-rc.2 → 1.0.0-rc.21

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
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
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,7 +550,7 @@ 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();
@@ -443,7 +560,7 @@ class Renderer {
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,7 +627,7 @@ 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');
514
631
  }
515
632
  }
516
633
  }
@@ -523,7 +640,7 @@ class Renderer {
523
640
  empty = (!leaf.__world.width || !leaf.__world.height);
524
641
  if (empty) {
525
642
  if (!leaf.isLeafer)
526
- debug.warn(leaf.innerName, ': empty');
643
+ debug$1.tip(leaf.innerName, ': empty');
527
644
  empty = (!leaf.isBranch || leaf.isBranchLeaf);
528
645
  }
529
646
  return empty;
@@ -550,15 +667,13 @@ class Renderer {
550
667
  if (this.target) {
551
668
  this.stop();
552
669
  this.__removeListenEvents();
553
- this.target = null;
554
- this.canvas = null;
555
- this.config = null;
670
+ this.target = this.canvas = this.config = null;
556
671
  }
557
672
  }
558
673
  }
559
674
 
560
675
  const { hitRadiusPoint } = core.BoundsHelper;
561
- class FindPath {
676
+ class Picker {
562
677
  constructor(target, selector) {
563
678
  this.target = target;
564
679
  this.selector = selector;
@@ -570,15 +685,17 @@ class FindPath {
570
685
  options = {};
571
686
  const through = options.through || false;
572
687
  const ignoreHittable = options.ignoreHittable || false;
688
+ const target = options.target || this.target;
573
689
  this.exclude = options.exclude || null;
574
690
  this.point = { x: hitPoint.x, y: hitPoint.y, radiusX: hitRadius, radiusY: hitRadius };
575
- this.findList = [];
576
- this.eachFind(this.target.children, this.target.__onlyHitMask);
691
+ this.findList = options.findList || [];
692
+ if (!options.findList)
693
+ this.eachFind(target.children, target.__onlyHitMask);
577
694
  const list = this.findList;
578
695
  const leaf = this.getBestMatchLeaf();
579
696
  const path = ignoreHittable ? this.getPath(leaf) : this.getHitablePath(leaf);
580
697
  this.clear();
581
- return through ? { path, leaf, throughPath: list.length ? this.getThroughPath(list) : path } : { path, leaf };
698
+ return through ? { path, target: leaf, throughPath: list.length ? this.getThroughPath(list) : path } : { path, target: leaf };
582
699
  }
583
700
  getBestMatchLeaf() {
584
701
  const { findList: targets } = this;
@@ -601,20 +718,20 @@ class FindPath {
601
718
  getPath(leaf) {
602
719
  const path = new core.LeafList();
603
720
  while (leaf) {
604
- path.push(leaf);
721
+ path.add(leaf);
605
722
  leaf = leaf.parent;
606
723
  }
607
- path.push(this.target);
724
+ path.add(this.target);
608
725
  return path;
609
726
  }
610
727
  getHitablePath(leaf) {
611
- const path = this.getPath(leaf);
728
+ const path = this.getPath(leaf && leaf.hittable ? leaf : null);
612
729
  let item, hittablePath = new core.LeafList();
613
730
  for (let i = path.list.length - 1; i > -1; i--) {
614
731
  item = path.list[i];
615
732
  if (!item.__.hittable)
616
733
  break;
617
- hittablePath.unshift(item);
734
+ hittablePath.addAt(item, 0);
618
735
  if (!item.__.hitChildren)
619
736
  break;
620
737
  }
@@ -633,7 +750,7 @@ class FindPath {
633
750
  leaf = path.list[j];
634
751
  if (nextPath && nextPath.has(leaf))
635
752
  break;
636
- throughPath.push(leaf);
753
+ throughPath.add(leaf);
637
754
  }
638
755
  }
639
756
  return throughPath;
@@ -643,7 +760,7 @@ class FindPath {
643
760
  const { point } = this, len = children.length;
644
761
  for (let i = len - 1; i > -1; i--) {
645
762
  child = children[i];
646
- if (!child.__.visible || (hitMask && !child.__.isMask))
763
+ if (!child.__.visible || (hitMask && !child.__.mask))
647
764
  continue;
648
765
  hit = child.__.hitRadius ? true : hitRadiusPoint(child.__world, point);
649
766
  if (child.isBranch) {
@@ -675,120 +792,113 @@ class FindPath {
675
792
  }
676
793
  }
677
794
 
795
+ const { Yes, NoAndSkip, YesAndSkip } = core.Answer;
678
796
  class Selector {
679
797
  constructor(target, userConfig) {
680
798
  this.config = {};
681
- this.innerIdList = {};
682
- this.idList = {};
683
- this.classNameList = {};
684
- this.tagNameList = {};
799
+ this.innerIdMap = {};
800
+ this.idMap = {};
801
+ this.methods = {
802
+ id: (leaf, name) => leaf.id === name ? (this.idMap[name] = leaf, 1) : 0,
803
+ innerId: (leaf, innerId) => leaf.innerId === innerId ? (this.innerIdMap[innerId] = leaf, 1) : 0,
804
+ className: (leaf, name) => leaf.className === name ? 1 : 0,
805
+ tag: (leaf, name) => leaf.__tag === name ? 1 : 0
806
+ };
685
807
  this.target = target;
686
808
  if (userConfig)
687
809
  this.config = core.DataHelper.default(userConfig, this.config);
688
- this.findPath = new FindPath(target, this);
810
+ this.picker = new Picker(target, this);
689
811
  this.__listenEvents();
690
812
  }
813
+ getBy(condition, branch, one, options) {
814
+ switch (typeof condition) {
815
+ case 'number':
816
+ const leaf = this.getByInnerId(condition, branch);
817
+ return one ? leaf : (leaf ? [leaf] : []);
818
+ case 'string':
819
+ switch (condition[0]) {
820
+ case '#':
821
+ const leaf = this.getById(condition.substring(1), branch);
822
+ return one ? leaf : (leaf ? [leaf] : []);
823
+ case '.':
824
+ return this.getByMethod(this.methods.className, branch, one, condition.substring(1));
825
+ default:
826
+ return this.getByMethod(this.methods.tag, branch, one, condition);
827
+ }
828
+ case 'function':
829
+ return this.getByMethod(condition, branch, one, options);
830
+ }
831
+ }
691
832
  getByPoint(hitPoint, hitRadius, options) {
692
833
  if (core.Platform.name === 'node')
693
834
  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
- }
835
+ return this.picker.getByPoint(hitPoint, hitRadius, options);
709
836
  }
710
- getByInnerId(name, branch) {
711
- let cache = this.innerIdList[name];
837
+ getByInnerId(innerId, branch) {
838
+ const cache = this.innerIdMap[innerId];
712
839
  if (cache)
713
840
  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;
841
+ this.eachFind(this.toChildren(branch), this.methods.innerId, null, innerId);
842
+ return this.findLeaf;
728
843
  }
729
- getById(name, branch) {
730
- let cache = this.idList[name];
731
- if (cache)
844
+ getById(id, branch) {
845
+ const cache = this.idMap[id];
846
+ if (cache && core.LeafHelper.hasParent(cache, branch || this.target))
732
847
  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;
848
+ this.eachFind(this.toChildren(branch), this.methods.id, null, id);
849
+ return this.findLeaf;
769
850
  }
770
- loopFind(branch, find) {
771
- if (find(branch))
772
- return;
773
- const { children } = branch;
851
+ getByClassName(className, branch) {
852
+ return this.getByMethod(this.methods.className, branch, false, className);
853
+ }
854
+ getByTag(tag, branch) {
855
+ return this.getByMethod(this.methods.tag, branch, false, tag);
856
+ }
857
+ getByMethod(method, branch, one, options) {
858
+ const list = one ? null : [];
859
+ this.eachFind(this.toChildren(branch), method, list, options);
860
+ return list || this.findLeaf;
861
+ }
862
+ eachFind(children, method, list, options) {
863
+ let child, result;
774
864
  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);
865
+ child = children[i];
866
+ result = method(child, options);
867
+ if (result === Yes || result === YesAndSkip) {
868
+ if (list) {
869
+ list.push(child);
870
+ }
871
+ else {
872
+ this.findLeaf = child;
873
+ return;
874
+ }
875
+ }
876
+ if (child.isBranch && result < NoAndSkip)
877
+ this.eachFind(child.children, method, list, options);
780
878
  }
781
879
  }
880
+ toChildren(branch) {
881
+ this.findLeaf = null;
882
+ return [branch || this.target];
883
+ }
782
884
  __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;
885
+ const { id, innerId } = event.child;
886
+ if (this.idMap[id])
887
+ delete this.idMap[id];
888
+ if (this.innerIdMap[innerId])
889
+ delete this.innerIdMap[innerId];
890
+ }
891
+ __checkIdChange(event) {
892
+ if (event.attrName === 'id') {
893
+ const id = event.oldValue;
894
+ if (this.idMap[id])
895
+ delete this.idMap[id];
896
+ }
788
897
  }
789
898
  __listenEvents() {
790
899
  this.__eventIds = [
791
- this.target.on_(core.ChildEvent.REMOVE, this.__onRemoveChild, this)
900
+ this.target.on_(core.ChildEvent.REMOVE, this.__onRemoveChild, this),
901
+ this.target.on_(core.PropertyEvent.CHANGE, this.__checkIdChange, this)
792
902
  ];
793
903
  }
794
904
  __removeListenEvents() {
@@ -798,11 +908,10 @@ class Selector {
798
908
  destroy() {
799
909
  if (this.__eventIds.length) {
800
910
  this.__removeListenEvents();
801
- this.findPath.destroy();
802
- this.innerIdList = {};
803
- this.idList = {};
804
- this.classNameList = {};
805
- this.tagNameList = {};
911
+ this.picker.destroy();
912
+ this.findLeaf = null;
913
+ this.innerIdMap = {};
914
+ this.idMap = {};
806
915
  }
807
916
  }
808
917
  }
@@ -815,444 +924,91 @@ Object.assign(core.Creator, {
815
924
  });
816
925
  core.Platform.layout = Layouter.fullLayout;
817
926
 
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;
927
+ function fillText(ui, canvas) {
928
+ let row;
929
+ const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
930
+ for (let i = 0, len = rows.length; i < len; i++) {
931
+ row = rows[i];
932
+ if (row.text) {
933
+ canvas.fillText(row.text, row.x, row.y);
934
+ }
935
+ else if (row.data) {
936
+ row.data.forEach(charData => {
937
+ canvas.fillText(charData.char, charData.x, row.y);
938
+ });
939
+ }
940
+ if (decorationY)
941
+ canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight);
833
942
  }
834
943
  }
835
944
 
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
- };
945
+ function fill(fill, ui, canvas) {
946
+ canvas.fillStyle = fill;
947
+ ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
948
+ }
949
+ function fills(fills, ui, canvas) {
950
+ let item;
951
+ const { windingRule, __font } = ui.__;
952
+ for (let i = 0, len = fills.length; i < len; i++) {
953
+ item = fills[i];
954
+ if (item.image && draw.PaintImage.checkImage(ui, canvas, item, !__font))
955
+ continue;
956
+ if (item.style) {
957
+ canvas.fillStyle = item.style;
958
+ if (item.transform) {
959
+ canvas.save();
960
+ canvas.transform(item.transform);
961
+ if (item.blendMode)
962
+ canvas.blendMode = item.blendMode;
963
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
964
+ canvas.restore();
965
+ }
966
+ else {
967
+ if (item.blendMode) {
968
+ canvas.saveBlendMode(item.blendMode);
969
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
970
+ canvas.restoreBlendMode();
971
+ }
972
+ else {
973
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
974
+ }
975
+ }
853
976
  }
854
- core.Platform.canvas = core.Creator.canvas();
855
977
  }
856
978
  }
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
979
 
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;
980
+ function strokeText(stroke, ui, canvas) {
981
+ const { strokeAlign } = ui.__;
982
+ const isStrokes = typeof stroke !== 'string';
983
+ switch (strokeAlign) {
984
+ case 'center':
985
+ canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
986
+ isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
987
+ break;
988
+ case 'inside':
989
+ drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
990
+ break;
991
+ case 'outside':
992
+ drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
993
+ break;
994
+ }
878
995
  }
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;
996
+ function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
997
+ const { __strokeWidth, __font } = ui.__;
998
+ const out = canvas.getSameCanvas(true, true);
999
+ out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__);
1000
+ out.font = __font;
1001
+ isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
1002
+ out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
1003
+ fillText(ui, out);
1004
+ out.blendMode = 'normal';
1005
+ if (ui.__worldFlipped) {
1006
+ canvas.copyWorldByReset(out, ui.__nowWorld);
888
1007
  }
889
- if (rotation)
890
- rotate(transform, rotation);
891
- data.transform = transform;
892
- }
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;
907
- }
908
- }
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
- }
916
-
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
- }
933
- break;
934
- case 'clip':
935
- if (offset || scale || rotation)
936
- clipMode(data, box, offset, scale, rotation);
937
- break;
938
- case 'repeat':
939
- if (!sameBox || scale || rotation)
940
- repeatMode(data, box, width, height, scale, rotation);
941
- break;
942
- case 'fit':
943
- case 'cover':
944
- default:
945
- if (!sameBox || rotation)
946
- fillOrFitMode(data, mode, box, width, height, rotation);
947
- }
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
- }
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.__);
1249
- out.font = __font;
1250
- isStrokes ? drawStrokesStyle(ui, stroke, out, true) : drawTextStroke(ui, out);
1251
- out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
1252
- fillText(ui, out);
1253
- out.blendMode = 'normal';
1254
- canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds);
1255
- out.recycle();
1008
+ else {
1009
+ canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
1010
+ }
1011
+ out.recycle(ui.__nowWorld);
1256
1012
  }
1257
1013
  function drawTextStroke(ui, canvas) {
1258
1014
  let row;
@@ -1271,11 +1027,11 @@ function drawTextStroke(ui, canvas) {
1271
1027
  canvas.strokeRect(row.x, row.y + decorationY, row.width, decorationHeight);
1272
1028
  }
1273
1029
  }
1274
- function drawStrokesStyle(ui, strokes, canvas, isText) {
1030
+ function drawStrokesStyle(strokes, isText, ui, canvas) {
1275
1031
  let item;
1276
1032
  for (let i = 0, len = strokes.length; i < len; i++) {
1277
1033
  item = strokes[i];
1278
- if (item.image && checkImage(ui, canvas, item, false))
1034
+ if (item.image && draw.PaintImage.checkImage(ui, canvas, item, false))
1279
1035
  continue;
1280
1036
  if (item.style) {
1281
1037
  canvas.strokeStyle = item.style;
@@ -1291,121 +1047,543 @@ function drawStrokesStyle(ui, strokes, canvas, isText) {
1291
1047
  }
1292
1048
  }
1293
1049
 
1294
- function stroke(ui, canvas, stroke) {
1050
+ function stroke(stroke, ui, canvas) {
1295
1051
  const options = ui.__;
1296
- const { strokeWidth, strokeAlign, __font } = options;
1297
- if (!strokeWidth)
1052
+ const { __strokeWidth, strokeAlign, __font } = options;
1053
+ if (!__strokeWidth)
1298
1054
  return;
1299
1055
  if (__font) {
1300
- strokeText(ui, canvas, stroke);
1056
+ strokeText(stroke, ui, canvas);
1301
1057
  }
1302
1058
  else {
1303
1059
  switch (strokeAlign) {
1304
1060
  case 'center':
1305
- canvas.setStroke(stroke, strokeWidth, options);
1061
+ canvas.setStroke(stroke, __strokeWidth, options);
1306
1062
  canvas.stroke();
1307
1063
  break;
1308
1064
  case 'inside':
1309
1065
  canvas.save();
1310
- canvas.setStroke(stroke, strokeWidth * 2, options);
1066
+ canvas.setStroke(stroke, __strokeWidth * 2, options);
1311
1067
  options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1312
1068
  canvas.stroke();
1313
1069
  canvas.restore();
1314
1070
  break;
1315
1071
  case 'outside':
1316
- const out = canvas.getSameCanvas(true);
1317
- out.setStroke(stroke, strokeWidth * 2, ui.__);
1072
+ const out = canvas.getSameCanvas(true, true);
1073
+ out.setStroke(stroke, __strokeWidth * 2, options);
1318
1074
  ui.__drawRenderPath(out);
1319
1075
  out.stroke();
1320
1076
  options.windingRule ? out.clip(options.windingRule) : out.clip();
1321
1077
  out.clearWorld(ui.__layout.renderBounds);
1322
- canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds);
1323
- out.recycle();
1078
+ if (ui.__worldFlipped) {
1079
+ canvas.copyWorldByReset(out, ui.__nowWorld);
1080
+ }
1081
+ else {
1082
+ canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
1083
+ }
1084
+ out.recycle(ui.__nowWorld);
1085
+ break;
1086
+ }
1087
+ }
1088
+ }
1089
+ function strokes(strokes, ui, canvas) {
1090
+ const options = ui.__;
1091
+ const { __strokeWidth, strokeAlign, __font } = options;
1092
+ if (!__strokeWidth)
1093
+ return;
1094
+ if (__font) {
1095
+ strokeText(strokes, ui, canvas);
1096
+ }
1097
+ else {
1098
+ switch (strokeAlign) {
1099
+ case 'center':
1100
+ canvas.setStroke(undefined, __strokeWidth, options);
1101
+ drawStrokesStyle(strokes, false, ui, canvas);
1102
+ break;
1103
+ case 'inside':
1104
+ canvas.save();
1105
+ canvas.setStroke(undefined, __strokeWidth * 2, options);
1106
+ options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1107
+ drawStrokesStyle(strokes, false, ui, canvas);
1108
+ canvas.restore();
1109
+ break;
1110
+ case 'outside':
1111
+ const { renderBounds } = ui.__layout;
1112
+ const out = canvas.getSameCanvas(true, true);
1113
+ ui.__drawRenderPath(out);
1114
+ out.setStroke(undefined, __strokeWidth * 2, options);
1115
+ drawStrokesStyle(strokes, false, ui, out);
1116
+ options.windingRule ? out.clip(options.windingRule) : out.clip();
1117
+ out.clearWorld(renderBounds);
1118
+ if (ui.__worldFlipped) {
1119
+ canvas.copyWorldByReset(out, ui.__nowWorld);
1120
+ }
1121
+ else {
1122
+ canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
1123
+ }
1124
+ out.recycle(ui.__nowWorld);
1125
+ break;
1126
+ }
1127
+ }
1128
+ }
1129
+
1130
+ const { getSpread, getOuterOf, getByMove, getIntersectData } = core.BoundsHelper;
1131
+ function shape(ui, current, options) {
1132
+ const canvas = current.getSameCanvas();
1133
+ const nowWorld = ui.__nowWorld;
1134
+ let bounds, fitMatrix, shapeBounds, worldCanvas;
1135
+ let { scaleX, scaleY } = nowWorld;
1136
+ if (scaleX < 0)
1137
+ scaleX = -scaleX;
1138
+ if (scaleY < 0)
1139
+ scaleY = -scaleY;
1140
+ if (current.bounds.includes(nowWorld)) {
1141
+ worldCanvas = canvas;
1142
+ bounds = shapeBounds = nowWorld;
1143
+ }
1144
+ else {
1145
+ const { renderShapeSpread: spread } = ui.__layout;
1146
+ const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, spread * scaleX, spread * scaleY) : current.bounds, nowWorld);
1147
+ fitMatrix = current.bounds.getFitMatrix(worldClipBounds);
1148
+ let { a: fitScaleX, d: fitScaleY } = fitMatrix;
1149
+ if (fitMatrix.a < 1) {
1150
+ worldCanvas = current.getSameCanvas();
1151
+ ui.__renderShape(worldCanvas, options);
1152
+ scaleX *= fitScaleX;
1153
+ scaleY *= fitScaleY;
1154
+ }
1155
+ shapeBounds = getOuterOf(nowWorld, fitMatrix);
1156
+ bounds = getByMove(shapeBounds, -fitMatrix.e, -fitMatrix.f);
1157
+ if (options.matrix) {
1158
+ const { matrix } = options;
1159
+ fitMatrix.multiply(matrix);
1160
+ fitScaleX *= matrix.scaleX;
1161
+ fitScaleY *= matrix.scaleY;
1162
+ }
1163
+ options = Object.assign(Object.assign({}, options), { matrix: fitMatrix.withScale(fitScaleX, fitScaleY) });
1164
+ }
1165
+ ui.__renderShape(canvas, options);
1166
+ return {
1167
+ canvas, matrix: fitMatrix, bounds,
1168
+ worldCanvas, shapeBounds, scaleX, scaleY
1169
+ };
1170
+ }
1171
+
1172
+ let recycleMap;
1173
+ function compute(attrName, ui) {
1174
+ const data = ui.__, leafPaints = [];
1175
+ let paints = data.__input[attrName], hasOpacityPixel;
1176
+ if (!(paints instanceof Array))
1177
+ paints = [paints];
1178
+ recycleMap = draw.PaintImage.recycleImage(attrName, data);
1179
+ for (let i = 0, len = paints.length, item; i < len; i++) {
1180
+ item = getLeafPaint(attrName, paints[i], ui);
1181
+ if (item)
1182
+ leafPaints.push(item);
1183
+ }
1184
+ data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
1185
+ if (leafPaints.length && leafPaints[0].image)
1186
+ hasOpacityPixel = leafPaints[0].image.hasOpacityPixel;
1187
+ if (attrName === 'fill') {
1188
+ data.__pixelFill = hasOpacityPixel;
1189
+ }
1190
+ else {
1191
+ data.__pixelStroke = hasOpacityPixel;
1192
+ }
1193
+ }
1194
+ function getLeafPaint(attrName, paint, ui) {
1195
+ if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
1196
+ return undefined;
1197
+ const { boxBounds } = ui.__layout;
1198
+ switch (paint.type) {
1199
+ case 'solid':
1200
+ let { type, blendMode, color, opacity } = paint;
1201
+ return { type, blendMode, style: draw.ColorConvert.string(color, opacity) };
1202
+ case 'image':
1203
+ return draw.PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1204
+ case 'linear':
1205
+ return draw.PaintGradient.linearGradient(paint, boxBounds);
1206
+ case 'radial':
1207
+ return draw.PaintGradient.radialGradient(paint, boxBounds);
1208
+ case 'angular':
1209
+ return draw.PaintGradient.conicGradient(paint, boxBounds);
1210
+ default:
1211
+ return paint.r ? { type: 'solid', style: draw.ColorConvert.string(paint) } : undefined;
1212
+ }
1213
+ }
1214
+
1215
+ const PaintModule = {
1216
+ compute,
1217
+ fill,
1218
+ fills,
1219
+ fillText,
1220
+ stroke,
1221
+ strokes,
1222
+ strokeText,
1223
+ drawTextStroke,
1224
+ shape
1225
+ };
1226
+
1227
+ let origin = {};
1228
+ const { get: get$4, rotateOfOuter: rotateOfOuter$2, translate: translate$1, scaleOfOuter: scaleOfOuter$2, scale: scaleHelper, rotate } = core.MatrixHelper;
1229
+ function fillOrFitMode(data, mode, box, width, height, rotation) {
1230
+ const transform = get$4();
1231
+ const swap = rotation && rotation !== 180;
1232
+ const sw = box.width / (swap ? height : width);
1233
+ const sh = box.height / (swap ? width : height);
1234
+ const scale = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
1235
+ const x = box.x + (box.width - width * scale) / 2;
1236
+ const y = box.y + (box.height - height * scale) / 2;
1237
+ translate$1(transform, x, y);
1238
+ scaleHelper(transform, scale);
1239
+ if (rotation)
1240
+ rotateOfOuter$2(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
1241
+ data.scaleX = data.scaleY = scale;
1242
+ data.transform = transform;
1243
+ }
1244
+ function clipMode(data, box, x, y, scaleX, scaleY, rotation) {
1245
+ const transform = get$4();
1246
+ translate$1(transform, box.x, box.y);
1247
+ if (x || y)
1248
+ translate$1(transform, x, y);
1249
+ if (scaleX) {
1250
+ scaleHelper(transform, scaleX, scaleY);
1251
+ data.scaleX = transform.a;
1252
+ data.scaleY = transform.d;
1253
+ }
1254
+ if (rotation)
1255
+ rotate(transform, rotation);
1256
+ data.transform = transform;
1257
+ }
1258
+ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation) {
1259
+ const transform = get$4();
1260
+ if (rotation) {
1261
+ rotate(transform, rotation);
1262
+ switch (rotation) {
1263
+ case 90:
1264
+ translate$1(transform, height, 0);
1324
1265
  break;
1266
+ case 180:
1267
+ translate$1(transform, width, height);
1268
+ break;
1269
+ case 270:
1270
+ translate$1(transform, 0, width);
1271
+ break;
1272
+ }
1273
+ }
1274
+ origin.x = box.x;
1275
+ origin.y = box.y;
1276
+ if (x || y)
1277
+ origin.x += x, origin.y += y;
1278
+ translate$1(transform, origin.x, origin.y);
1279
+ if (scaleX) {
1280
+ scaleOfOuter$2(transform, origin, scaleX, scaleY);
1281
+ data.scaleX = scaleX;
1282
+ data.scaleY = scaleY;
1283
+ }
1284
+ data.transform = transform;
1285
+ }
1286
+
1287
+ const { get: get$3, translate } = core.MatrixHelper;
1288
+ const tempBox = new core.Bounds();
1289
+ function createData(leafPaint, image, paint, box) {
1290
+ let { width, height } = image;
1291
+ if (paint.padding)
1292
+ box = tempBox.set(box).shrink(paint.padding);
1293
+ const { opacity, mode, offset, scale, size, rotation, blendMode, repeat } = paint;
1294
+ const sameBox = box.width === width && box.height === height;
1295
+ if (blendMode)
1296
+ leafPaint.blendMode = blendMode;
1297
+ const data = leafPaint.data = { mode };
1298
+ let x, y, scaleX, scaleY;
1299
+ if (offset)
1300
+ x = offset.x, y = offset.y;
1301
+ if (size) {
1302
+ scaleX = (typeof size === 'number' ? size : size.width) / width;
1303
+ scaleY = (typeof size === 'number' ? size : size.height) / height;
1304
+ }
1305
+ else if (scale) {
1306
+ scaleX = typeof scale === 'number' ? scale : scale.x;
1307
+ scaleY = typeof scale === 'number' ? scale : scale.y;
1308
+ }
1309
+ switch (mode) {
1310
+ case 'strench':
1311
+ if (!sameBox)
1312
+ width = box.width, height = box.height;
1313
+ break;
1314
+ case 'clip':
1315
+ if (offset || scaleX || rotation)
1316
+ clipMode(data, box, x, y, scaleX, scaleY, rotation);
1317
+ break;
1318
+ case 'repeat':
1319
+ if (!sameBox || scaleX || rotation)
1320
+ repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation);
1321
+ if (!repeat)
1322
+ data.repeat = 'repeat';
1323
+ break;
1324
+ case 'fit':
1325
+ case 'cover':
1326
+ default:
1327
+ if (!sameBox || rotation)
1328
+ fillOrFitMode(data, mode, box, width, height, rotation);
1329
+ }
1330
+ if (!data.transform) {
1331
+ if (box.x || box.y) {
1332
+ data.transform = get$3();
1333
+ translate(data.transform, box.x, box.y);
1334
+ }
1335
+ }
1336
+ data.width = width;
1337
+ data.height = height;
1338
+ if (opacity)
1339
+ data.opacity = opacity;
1340
+ if (repeat)
1341
+ data.repeat = typeof repeat === 'string' ? (repeat === 'x' ? 'repeat-x' : 'repeat-y') : 'repeat';
1342
+ }
1343
+
1344
+ let cache, box = new core.Bounds();
1345
+ const { isSame } = core.BoundsHelper;
1346
+ function image(ui, attrName, paint, boxBounds, firstUse) {
1347
+ let leafPaint, event;
1348
+ const image = core.ImageManager.get(paint);
1349
+ if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
1350
+ leafPaint = cache.leafPaint;
1351
+ }
1352
+ else {
1353
+ leafPaint = { type: paint.type, image };
1354
+ cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
1355
+ }
1356
+ if (firstUse || image.loading)
1357
+ event = { image, attrName, attrValue: paint };
1358
+ if (image.ready) {
1359
+ checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
1360
+ if (firstUse) {
1361
+ onLoad(ui, event);
1362
+ onLoadSuccess(ui, event);
1363
+ }
1364
+ }
1365
+ else if (image.error) {
1366
+ if (firstUse)
1367
+ onLoadError(ui, event, image.error);
1368
+ }
1369
+ else {
1370
+ ignoreRender(ui, true);
1371
+ if (firstUse)
1372
+ onLoad(ui, event);
1373
+ leafPaint.loadId = image.load(() => {
1374
+ ignoreRender(ui, false);
1375
+ if (!ui.destroyed) {
1376
+ if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1377
+ if (image.hasOpacityPixel)
1378
+ ui.__layout.hitCanvasChanged = true;
1379
+ ui.forceUpdate('surface');
1380
+ }
1381
+ onLoadSuccess(ui, event);
1382
+ }
1383
+ leafPaint.loadId = null;
1384
+ }, (error) => {
1385
+ ignoreRender(ui, false);
1386
+ onLoadError(ui, event, error);
1387
+ leafPaint.loadId = null;
1388
+ });
1389
+ }
1390
+ return leafPaint;
1391
+ }
1392
+ function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
1393
+ if (attrName === 'fill' && !ui.__.__naturalWidth) {
1394
+ const data = ui.__;
1395
+ data.__naturalWidth = image.width / data.pixelRatio;
1396
+ data.__naturalHeight = image.height / data.pixelRatio;
1397
+ if (data.__autoSide) {
1398
+ ui.forceUpdate('width');
1399
+ if (ui.__proxyData) {
1400
+ ui.setProxyAttr('width', data.width);
1401
+ ui.setProxyAttr('height', data.height);
1402
+ }
1403
+ return false;
1325
1404
  }
1326
1405
  }
1406
+ if (!leafPaint.data)
1407
+ createData(leafPaint, image, paint, boxBounds);
1408
+ return true;
1327
1409
  }
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);
1410
+ function onLoad(ui, event) {
1411
+ emit(ui, core.ImageEvent.LOAD, event);
1412
+ }
1413
+ function onLoadSuccess(ui, event) {
1414
+ emit(ui, core.ImageEvent.LOADED, event);
1415
+ }
1416
+ function onLoadError(ui, event, error) {
1417
+ event.error = error;
1418
+ ui.forceUpdate('surface');
1419
+ emit(ui, core.ImageEvent.ERROR, event);
1420
+ }
1421
+ function emit(ui, type, data) {
1422
+ if (ui.hasEvent(type))
1423
+ ui.emitEvent(new core.ImageEvent(type, data));
1424
+ }
1425
+ function ignoreRender(ui, value) {
1426
+ const { leafer } = ui;
1427
+ if (leafer && leafer.viewReady)
1428
+ leafer.renderer.ignore = value;
1429
+ }
1430
+
1431
+ const { get: get$2, scale, copy: copy$1 } = core.MatrixHelper;
1432
+ const { ceil, abs: abs$1 } = Math;
1433
+ function createPattern(ui, paint, pixelRatio) {
1434
+ let { scaleX, scaleY } = core.ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
1435
+ const id = scaleX + '-' + scaleY;
1436
+ if (paint.patternId !== id && !ui.destroyed) {
1437
+ scaleX = abs$1(scaleX);
1438
+ scaleY = abs$1(scaleY);
1439
+ const { image, data } = paint;
1440
+ let imageScale, imageMatrix, { width, height, scaleX: sx, scaleY: sy, opacity, transform, repeat } = data;
1441
+ if (sx) {
1442
+ imageMatrix = get$2();
1443
+ copy$1(imageMatrix, transform);
1444
+ scale(imageMatrix, 1 / sx, 1 / sy);
1445
+ scaleX *= sx;
1446
+ scaleY *= sy;
1447
+ }
1448
+ scaleX *= pixelRatio;
1449
+ scaleY *= pixelRatio;
1450
+ width *= scaleX;
1451
+ height *= scaleY;
1452
+ const size = width * height;
1453
+ if (!repeat) {
1454
+ if (size > core.Platform.image.maxCacheSize)
1455
+ return false;
1456
+ }
1457
+ let maxSize = core.Platform.image.maxPatternSize;
1458
+ if (!image.isSVG) {
1459
+ const imageSize = image.width * image.height;
1460
+ if (maxSize > imageSize)
1461
+ maxSize = imageSize;
1462
+ }
1463
+ if (size > maxSize)
1464
+ imageScale = Math.sqrt(size / maxSize);
1465
+ if (imageScale) {
1466
+ scaleX /= imageScale;
1467
+ scaleY /= imageScale;
1468
+ width /= imageScale;
1469
+ height /= imageScale;
1470
+ }
1471
+ if (sx) {
1472
+ scaleX /= sx;
1473
+ scaleY /= sy;
1474
+ }
1475
+ if (transform || scaleX !== 1 || scaleY !== 1) {
1476
+ if (!imageMatrix) {
1477
+ imageMatrix = get$2();
1478
+ if (transform)
1479
+ copy$1(imageMatrix, transform);
1480
+ }
1481
+ scale(imageMatrix, 1 / scaleX, 1 / scaleY);
1482
+ }
1483
+ const canvas = image.getCanvas(ceil(width) || 1, ceil(height) || 1, opacity);
1484
+ const pattern = image.getPattern(canvas, repeat || (core.Platform.origin.noRepeat || 'no-repeat'), imageMatrix, paint);
1485
+ paint.style = pattern;
1486
+ paint.patternId = id;
1487
+ return true;
1335
1488
  }
1336
1489
  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
- }
1490
+ return false;
1361
1491
  }
1362
1492
  }
1363
1493
 
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 });
1494
+ const { abs } = Math;
1495
+ function checkImage(ui, canvas, paint, allowPaint) {
1496
+ const { scaleX, scaleY } = core.ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
1497
+ if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
1498
+ return false;
1390
1499
  }
1391
1500
  else {
1392
- if (options.matrix) {
1393
- scaleX *= options.matrix.a;
1394
- scaleY *= options.matrix.d;
1395
- bounds = shapeBounds = getOuterOf(__world, options.matrix);
1501
+ const { data } = paint;
1502
+ if (allowPaint) {
1503
+ if (!data.repeat) {
1504
+ let { width, height } = data;
1505
+ width *= abs(scaleX) * canvas.pixelRatio;
1506
+ height *= abs(scaleY) * canvas.pixelRatio;
1507
+ if (data.scaleX) {
1508
+ width *= data.scaleX;
1509
+ height *= data.scaleY;
1510
+ }
1511
+ allowPaint = width * height > core.Platform.image.maxCacheSize;
1512
+ }
1513
+ else {
1514
+ allowPaint = false;
1515
+ }
1516
+ }
1517
+ if (allowPaint) {
1518
+ canvas.save();
1519
+ canvas.clip();
1520
+ if (paint.blendMode)
1521
+ canvas.blendMode = paint.blendMode;
1522
+ if (data.opacity)
1523
+ canvas.opacity *= data.opacity;
1524
+ if (data.transform)
1525
+ canvas.transform(data.transform);
1526
+ canvas.drawImage(paint.image.view, 0, 0, data.width, data.height);
1527
+ canvas.restore();
1528
+ return true;
1396
1529
  }
1397
1530
  else {
1398
- bounds = shapeBounds = __world;
1531
+ if (!paint.style || draw.Export.running) {
1532
+ createPattern(ui, paint, canvas.pixelRatio);
1533
+ }
1534
+ else {
1535
+ if (!paint.patternTask) {
1536
+ paint.patternTask = core.ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
1537
+ paint.patternTask = null;
1538
+ if (canvas.bounds.hit(ui.__nowWorld))
1539
+ createPattern(ui, paint, canvas.pixelRatio);
1540
+ ui.forceUpdate('surface');
1541
+ }), 300);
1542
+ }
1543
+ }
1544
+ return false;
1399
1545
  }
1400
- worldCanvas = canvas;
1401
1546
  }
1402
- ui.__renderShape(canvas, options);
1403
- return {
1404
- canvas, matrix, bounds,
1405
- worldCanvas, shapeBounds, scaleX, scaleY
1406
- };
1407
1547
  }
1408
1548
 
1549
+ function recycleImage(attrName, data) {
1550
+ const paints = data['_' + attrName];
1551
+ if (paints instanceof Array) {
1552
+ let image, recycleMap, input, url;
1553
+ for (let i = 0, len = paints.length; i < len; i++) {
1554
+ image = paints[i].image;
1555
+ url = image && image.url;
1556
+ if (url) {
1557
+ if (!recycleMap)
1558
+ recycleMap = {};
1559
+ recycleMap[url] = true;
1560
+ core.ImageManager.recycle(image);
1561
+ if (image.loading) {
1562
+ if (!input) {
1563
+ input = (data.__input && data.__input[attrName]) || [];
1564
+ if (!(input instanceof Array))
1565
+ input = [input];
1566
+ }
1567
+ image.unload(paints[i].loadId, !input.some((item) => item.url === url));
1568
+ }
1569
+ }
1570
+ }
1571
+ return recycleMap;
1572
+ }
1573
+ return null;
1574
+ }
1575
+
1576
+ const PaintImageModule = {
1577
+ image,
1578
+ createData,
1579
+ fillOrFitMode,
1580
+ clipMode,
1581
+ repeatMode,
1582
+ createPattern,
1583
+ checkImage,
1584
+ recycleImage
1585
+ };
1586
+
1409
1587
  const defaultFrom$2 = { x: 0.5, y: 0 };
1410
1588
  const defaultTo$2 = { x: 0.5, y: 1 };
1411
1589
  function linearGradient(paint, box) {
@@ -1423,7 +1601,7 @@ function applyStops(gradient, stops, opacity) {
1423
1601
  let stop;
1424
1602
  for (let i = 0, len = stops.length; i < len; i++) {
1425
1603
  stop = stops[i];
1426
- gradient.addColorStop(stop.offset, core$1.ColorConvert.string(stop.color, opacity));
1604
+ gradient.addColorStop(stop.offset, draw.ColorConvert.string(stop.color, opacity));
1427
1605
  }
1428
1606
  }
1429
1607
 
@@ -1485,62 +1663,18 @@ function conicGradient(paint, box) {
1485
1663
  return data;
1486
1664
  }
1487
1665
 
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
- });
1666
+ const PaintGradientModule = {
1667
+ linearGradient,
1668
+ radialGradient,
1669
+ conicGradient
1670
+ };
1537
1671
 
1538
1672
  const { copy, toOffsetOutBounds: toOffsetOutBounds$1 } = core.BoundsHelper;
1539
1673
  const tempBounds = {};
1540
1674
  const offsetOutBounds$1 = {};
1541
- function shadow(ui, current, shape, _options) {
1675
+ function shadow(ui, current, shape) {
1542
1676
  let copyBounds, spreadScale;
1543
- const { __world, __layout } = ui;
1677
+ const { __nowWorld: nowWorld, __layout } = ui;
1544
1678
  const { shadow } = ui.__;
1545
1679
  const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
1546
1680
  const other = current.getSameCanvas();
@@ -1555,21 +1689,21 @@ function shadow(ui, current, shape, _options) {
1555
1689
  other.restore();
1556
1690
  other.save();
1557
1691
  if (worldCanvas) {
1558
- other.copyWorld(other, bounds, __world, 'copy');
1559
- copyBounds = __world;
1692
+ other.copyWorld(other, bounds, nowWorld, 'copy');
1693
+ copyBounds = nowWorld;
1560
1694
  }
1561
- worldCanvas ? other.copyWorld(worldCanvas, __world, __world, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
1695
+ worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
1562
1696
  }
1563
- if (ui.__hasMirror) {
1564
- current.copyWorldByReset(other, copyBounds, __world, item.blendMode);
1697
+ if (ui.__worldFlipped) {
1698
+ current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1565
1699
  }
1566
1700
  else {
1567
1701
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1568
1702
  }
1569
1703
  if (end && index < end)
1570
- other.clear();
1704
+ other.clearWorld(copyBounds, true);
1571
1705
  });
1572
- other.recycle();
1706
+ other.recycle(copyBounds);
1573
1707
  }
1574
1708
  function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
1575
1709
  const { bounds, shapeBounds } = shape;
@@ -1600,9 +1734,9 @@ function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
1600
1734
 
1601
1735
  const { toOffsetOutBounds } = core.BoundsHelper;
1602
1736
  const offsetOutBounds = {};
1603
- function innerShadow(ui, current, shape, _options) {
1737
+ function innerShadow(ui, current, shape) {
1604
1738
  let copyBounds, spreadScale;
1605
- const { __world, __layout: __layout } = ui;
1739
+ const { __nowWorld: nowWorld, __layout: __layout } = ui;
1606
1740
  const { innerShadow } = ui.__;
1607
1741
  const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
1608
1742
  const other = current.getSameCanvas();
@@ -1615,40 +1749,115 @@ function innerShadow(ui, current, shape, _options) {
1615
1749
  drawWorldShadow(other, offsetOutBounds, spreadScale, shape);
1616
1750
  other.restore();
1617
1751
  if (worldCanvas) {
1618
- other.copyWorld(other, bounds, __world, 'copy');
1619
- other.copyWorld(worldCanvas, __world, __world, 'source-out');
1620
- copyBounds = __world;
1752
+ other.copyWorld(other, bounds, nowWorld, 'copy');
1753
+ other.copyWorld(worldCanvas, nowWorld, nowWorld, 'source-out');
1754
+ copyBounds = nowWorld;
1621
1755
  }
1622
1756
  else {
1623
1757
  other.copyWorld(shape.canvas, shapeBounds, bounds, 'source-out');
1624
1758
  copyBounds = bounds;
1625
1759
  }
1626
1760
  other.fillWorld(copyBounds, item.color, 'source-in');
1627
- if (ui.__hasMirror) {
1628
- current.copyWorldByReset(other, copyBounds, __world, item.blendMode);
1761
+ if (ui.__worldFlipped) {
1762
+ current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1629
1763
  }
1630
1764
  else {
1631
1765
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1632
1766
  }
1633
1767
  if (end && index < end)
1634
- other.clear();
1768
+ other.clearWorld(copyBounds, true);
1635
1769
  });
1636
- other.recycle();
1770
+ other.recycle(copyBounds);
1637
1771
  }
1638
1772
 
1639
1773
  function blur(ui, current, origin) {
1640
1774
  const { blur } = ui.__;
1641
- origin.setWorldBlur(blur * ui.__world.a);
1642
- origin.copyWorldToInner(current, ui.__world, ui.__layout.renderBounds);
1775
+ origin.setWorldBlur(blur * ui.__nowWorld.a);
1776
+ origin.copyWorldToInner(current, ui.__nowWorld, ui.__layout.renderBounds);
1643
1777
  origin.filter = 'none';
1644
1778
  }
1645
1779
 
1646
- var UIEffect = /*#__PURE__*/Object.freeze({
1647
- __proto__: null,
1648
- blur: blur,
1649
- innerShadow: innerShadow,
1650
- shadow: shadow
1651
- });
1780
+ function backgroundBlur(_ui, _current, _shape) {
1781
+ }
1782
+
1783
+ const EffectModule = {
1784
+ shadow,
1785
+ innerShadow,
1786
+ blur,
1787
+ backgroundBlur
1788
+ };
1789
+
1790
+ const { excludeRenderBounds } = core.LeafBoundsHelper;
1791
+ draw.Group.prototype.__renderMask = function (canvas, options) {
1792
+ let child, maskCanvas, contentCanvas, maskOpacity, currentMask;
1793
+ const { children } = this;
1794
+ for (let i = 0, len = children.length; i < len; i++) {
1795
+ child = children[i];
1796
+ if (child.__.mask) {
1797
+ if (currentMask) {
1798
+ maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
1799
+ maskCanvas = contentCanvas = null;
1800
+ }
1801
+ if (child.__.maskType === 'path') {
1802
+ if (child.opacity < 1) {
1803
+ currentMask = 'opacity-path';
1804
+ maskOpacity = child.opacity;
1805
+ if (!contentCanvas)
1806
+ contentCanvas = getCanvas(canvas);
1807
+ }
1808
+ else {
1809
+ currentMask = 'path';
1810
+ canvas.save();
1811
+ }
1812
+ child.__clip(contentCanvas || canvas, options);
1813
+ }
1814
+ else {
1815
+ currentMask = 'alpha';
1816
+ if (!maskCanvas)
1817
+ maskCanvas = getCanvas(canvas);
1818
+ if (!contentCanvas)
1819
+ contentCanvas = getCanvas(canvas);
1820
+ child.__render(maskCanvas, options);
1821
+ }
1822
+ if (child.__.maskType !== 'clipping')
1823
+ continue;
1824
+ }
1825
+ if (excludeRenderBounds(child, options))
1826
+ continue;
1827
+ child.__render(contentCanvas || canvas, options);
1828
+ }
1829
+ maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
1830
+ };
1831
+ function maskEnd(leaf, maskMode, canvas, contentCanvas, maskCanvas, maskOpacity) {
1832
+ switch (maskMode) {
1833
+ case 'alpha':
1834
+ usePixelMask(leaf, canvas, contentCanvas, maskCanvas);
1835
+ break;
1836
+ case 'opacity-path':
1837
+ copyContent(leaf, canvas, contentCanvas, maskOpacity);
1838
+ break;
1839
+ case 'path':
1840
+ canvas.restore();
1841
+ }
1842
+ }
1843
+ function getCanvas(canvas) {
1844
+ return canvas.getSameCanvas(false, true);
1845
+ }
1846
+ function usePixelMask(leaf, canvas, content, mask) {
1847
+ const realBounds = leaf.__nowWorld;
1848
+ content.resetTransform();
1849
+ content.opacity = 1;
1850
+ content.useMask(mask, realBounds);
1851
+ mask.recycle(realBounds);
1852
+ copyContent(leaf, canvas, content, 1);
1853
+ }
1854
+ function copyContent(leaf, canvas, content, maskOpacity) {
1855
+ const realBounds = leaf.__nowWorld;
1856
+ canvas.resetTransform();
1857
+ canvas.opacity = maskOpacity;
1858
+ canvas.copyWorld(content, realBounds);
1859
+ content.recycle(realBounds);
1860
+ }
1652
1861
 
1653
1862
  const money = '¥¥$€££¢¢';
1654
1863
  const letter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
@@ -1762,7 +1971,7 @@ function getTextCase(char, textCase, firstChar) {
1762
1971
  const { trimRight } = TextRowHelper;
1763
1972
  const { Letter, Single, Before, After, Symbol, Break } = CharType;
1764
1973
  let word, row, wordWidth, rowWidth, realWidth;
1765
- let char, charWidth, charType, lastCharType, langBreak, afterBreak, paraStart;
1974
+ let char, charWidth, startCharSize, charSize, charType, lastCharType, langBreak, afterBreak, paraStart;
1766
1975
  let textDrawData, rows = [], bounds;
1767
1976
  function createRows(drawData, content, style) {
1768
1977
  textDrawData = drawData;
@@ -1773,9 +1982,11 @@ function createRows(drawData, content, style) {
1773
1982
  const { width, height } = bounds;
1774
1983
  const charMode = width || height || __letterSpacing || (textCase !== 'none');
1775
1984
  if (charMode) {
1985
+ const wrap = style.textWrap !== 'none';
1986
+ const breakAll = style.textWrap === 'break';
1776
1987
  paraStart = true;
1777
1988
  lastCharType = null;
1778
- wordWidth = rowWidth = 0;
1989
+ startCharSize = charWidth = charSize = wordWidth = rowWidth = 0;
1779
1990
  word = { data: [] }, row = { words: [] };
1780
1991
  for (let i = 0, len = content.length; i < len; i++) {
1781
1992
  char = content[i];
@@ -1791,21 +2002,31 @@ function createRows(drawData, content, style) {
1791
2002
  if (charType === Letter && textCase !== 'none')
1792
2003
  char = getTextCase(char, textCase, !wordWidth);
1793
2004
  charWidth = canvas.measureText(char).width;
1794
- if (__letterSpacing)
2005
+ if (__letterSpacing) {
2006
+ if (__letterSpacing < 0)
2007
+ charSize = charWidth;
1795
2008
  charWidth += __letterSpacing;
2009
+ }
1796
2010
  langBreak = (charType === Single && (lastCharType === Single || lastCharType === Letter)) || (lastCharType === Single && charType !== After);
1797
2011
  afterBreak = ((charType === Before || charType === Single) && (lastCharType === Symbol || lastCharType === After));
1798
2012
  realWidth = paraStart && paraIndent ? width - paraIndent : width;
1799
- if (width && rowWidth + wordWidth + charWidth > realWidth) {
1800
- if (!afterBreak)
1801
- afterBreak = charType === Letter && lastCharType == After;
1802
- if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
2013
+ if (wrap && (width && rowWidth + wordWidth + charWidth > realWidth)) {
2014
+ if (breakAll) {
1803
2015
  if (wordWidth)
1804
2016
  addWord();
1805
2017
  addRow();
1806
2018
  }
1807
2019
  else {
1808
- addRow();
2020
+ if (!afterBreak)
2021
+ afterBreak = charType === Letter && lastCharType == After;
2022
+ if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
2023
+ if (wordWidth)
2024
+ addWord();
2025
+ addRow();
2026
+ }
2027
+ else {
2028
+ addRow();
2029
+ }
1809
2030
  }
1810
2031
  }
1811
2032
  if (char === ' ' && paraStart !== true && (rowWidth + wordWidth) === 0) ;
@@ -1842,6 +2063,8 @@ function createRows(drawData, content, style) {
1842
2063
  }
1843
2064
  }
1844
2065
  function addChar(char, width) {
2066
+ if (charSize && !startCharSize)
2067
+ startCharSize = charSize;
1845
2068
  word.data.push({ char, width });
1846
2069
  wordWidth += width;
1847
2070
  }
@@ -1858,6 +2081,11 @@ function addRow() {
1858
2081
  row.paraStart = true;
1859
2082
  paraStart = false;
1860
2083
  }
2084
+ if (charSize) {
2085
+ row.startCharSize = startCharSize;
2086
+ row.endCharSize = charSize;
2087
+ startCharSize = 0;
2088
+ }
1861
2089
  row.width = rowWidth;
1862
2090
  if (bounds.width)
1863
2091
  trimRight(row);
@@ -1868,7 +2096,7 @@ function addRow() {
1868
2096
 
1869
2097
  const CharMode = 0;
1870
2098
  const WordMode = 1;
1871
- const RowMode = 2;
2099
+ const TextMode = 2;
1872
2100
  function layoutChar(drawData, style, width, _height) {
1873
2101
  const { rows } = drawData;
1874
2102
  const { textAlign, paraIndent, letterSpacing } = style;
@@ -1877,15 +2105,12 @@ function layoutChar(drawData, style, width, _height) {
1877
2105
  if (row.words) {
1878
2106
  indentWidth = paraIndent && row.paraStart ? paraIndent : 0;
1879
2107
  addWordWidth = (width && textAlign === 'justify' && row.words.length > 1) ? (width - row.width - indentWidth) / (row.words.length - 1) : 0;
1880
- mode = (letterSpacing || row.isOverflow) ? CharMode : (addWordWidth > 0.01 ? WordMode : RowMode);
1881
- if (mode === RowMode) {
1882
- row.text = '';
2108
+ mode = (letterSpacing || row.isOverflow) ? CharMode : (addWordWidth > 0.01 ? WordMode : TextMode);
2109
+ if (row.isOverflow && !letterSpacing)
2110
+ row.textMode = true;
2111
+ if (mode === TextMode) {
1883
2112
  row.x += indentWidth;
1884
- row.words.forEach(word => {
1885
- word.data.forEach(char => {
1886
- row.text += char.char;
1887
- });
1888
- });
2113
+ toTextChar$1(row);
1889
2114
  }
1890
2115
  else {
1891
2116
  row.x += indentWidth;
@@ -1911,6 +2136,14 @@ function layoutChar(drawData, style, width, _height) {
1911
2136
  }
1912
2137
  });
1913
2138
  }
2139
+ function toTextChar$1(row) {
2140
+ row.text = '';
2141
+ row.words.forEach(word => {
2142
+ word.data.forEach(char => {
2143
+ row.text += char.char;
2144
+ });
2145
+ });
2146
+ }
1914
2147
  function toWordChar(data, charX, wordChar) {
1915
2148
  data.forEach(char => {
1916
2149
  wordChar.char += char.char;
@@ -1931,10 +2164,10 @@ function toChar(data, charX, rowData) {
1931
2164
 
1932
2165
  function layoutText(drawData, style) {
1933
2166
  const { rows, bounds } = drawData;
1934
- const { __lineHeight, __baseLine, textAlign, verticalAlign, paraSpacing, textOverflow } = style;
2167
+ const { __lineHeight, __baseLine, __letterSpacing, __clipText, textAlign, verticalAlign, paraSpacing } = style;
1935
2168
  let { x, y, width, height } = bounds, realHeight = __lineHeight * rows.length + (paraSpacing ? paraSpacing * (drawData.paraNumber - 1) : 0);
1936
2169
  let starY = __baseLine;
1937
- if (textOverflow !== 'show' && realHeight > height) {
2170
+ if (__clipText && realHeight > height) {
1938
2171
  realHeight = Math.max(height, __lineHeight);
1939
2172
  drawData.overflow = rows.length;
1940
2173
  }
@@ -1948,7 +2181,7 @@ function layoutText(drawData, style) {
1948
2181
  }
1949
2182
  }
1950
2183
  starY += y;
1951
- let row;
2184
+ let row, rowX, rowWidth;
1952
2185
  for (let i = 0, len = rows.length; i < len; i++) {
1953
2186
  row = rows[i];
1954
2187
  row.x = x;
@@ -1967,53 +2200,74 @@ function layoutText(drawData, style) {
1967
2200
  row.isOverflow = true;
1968
2201
  drawData.overflow = i + 1;
1969
2202
  }
1970
- if (row.width < 0) {
1971
- const charWidth = row.words[0].data[0].width;
1972
- const rowX = row.x + row.width;
1973
- if (rowX < bounds.x)
1974
- bounds.x = rowX - charWidth;
1975
- if (-row.width > bounds.width)
1976
- bounds.width = -row.width + style.fontSize + charWidth;
2203
+ rowX = row.x;
2204
+ rowWidth = row.width;
2205
+ if (__letterSpacing < 0) {
2206
+ if (row.width < 0) {
2207
+ rowWidth = -row.width + style.fontSize + __letterSpacing;
2208
+ rowX -= rowWidth;
2209
+ rowWidth += style.fontSize;
2210
+ }
2211
+ else {
2212
+ rowWidth -= __letterSpacing;
2213
+ }
1977
2214
  }
1978
- else {
1979
- if (row.x < bounds.x)
1980
- bounds.x = row.x;
1981
- if (row.width > bounds.width)
1982
- bounds.width = row.width;
2215
+ if (rowX < bounds.x)
2216
+ bounds.x = rowX;
2217
+ if (rowWidth > bounds.width)
2218
+ bounds.width = rowWidth;
2219
+ if (__clipText && width && width < rowWidth) {
2220
+ row.isOverflow = true;
2221
+ if (!drawData.overflow)
2222
+ drawData.overflow = rows.length;
1983
2223
  }
1984
2224
  }
1985
2225
  bounds.y = y;
1986
2226
  bounds.height = realHeight;
1987
2227
  }
1988
2228
 
1989
- function clipText(drawData, textOverflow) {
2229
+ function clipText(drawData, style) {
1990
2230
  const { rows, overflow } = drawData;
2231
+ let { textOverflow } = style;
1991
2232
  rows.splice(overflow);
1992
2233
  if (textOverflow !== 'hide') {
1993
2234
  if (textOverflow === 'ellipsis')
1994
2235
  textOverflow = '...';
2236
+ let char, charRight;
1995
2237
  const ellipsisWidth = core.Platform.canvas.measureText(textOverflow).width;
1996
- const row = rows[overflow - 1];
1997
- let char, end = row.data.length - 1, charRight;
1998
- const { x, width } = drawData.bounds;
1999
- const right = x + width - ellipsisWidth;
2000
- for (let i = end; i > -1; i--) {
2001
- char = row.data[i];
2002
- charRight = char.x + char.width;
2003
- if (i === end && charRight < right) {
2004
- break;
2005
- }
2006
- else if (charRight < right && char.char !== ' ') {
2007
- row.data.splice(i + 1);
2008
- row.width -= char.width;
2009
- break;
2238
+ const right = style.x + style.width - ellipsisWidth;
2239
+ const list = style.textWrap === 'none' ? rows : [rows[overflow - 1]];
2240
+ list.forEach(row => {
2241
+ if (row.isOverflow && row.data) {
2242
+ let end = row.data.length - 1;
2243
+ for (let i = end; i > -1; i--) {
2244
+ char = row.data[i];
2245
+ charRight = char.x + char.width;
2246
+ if (i === end && charRight < right) {
2247
+ break;
2248
+ }
2249
+ else if (charRight < right && char.char !== ' ') {
2250
+ row.data.splice(i + 1);
2251
+ row.width -= char.width;
2252
+ break;
2253
+ }
2254
+ row.width -= char.width;
2255
+ }
2256
+ row.width += ellipsisWidth;
2257
+ row.data.push({ char: textOverflow, x: charRight });
2258
+ if (row.textMode)
2259
+ toTextChar(row);
2010
2260
  }
2011
- row.width -= char.width;
2012
- }
2013
- row.width += ellipsisWidth;
2014
- row.data.push({ char: textOverflow, x: charRight });
2261
+ });
2015
2262
  }
2016
2263
  }
2264
+ function toTextChar(row) {
2265
+ row.text = '';
2266
+ row.data.forEach(char => {
2267
+ row.text += char.char;
2268
+ });
2269
+ row.data = null;
2270
+ }
2017
2271
 
2018
2272
  function decorationText(drawData, style) {
2019
2273
  const { fontSize } = style;
@@ -2027,101 +2281,190 @@ function decorationText(drawData, style) {
2027
2281
  }
2028
2282
  }
2029
2283
 
2030
- const TextConvert = {
2031
- getDrawData(content, style) {
2032
- if (typeof content !== 'string')
2033
- content = String(content);
2034
- let x = 0, y = 0;
2035
- let { width, height, padding } = style;
2036
- const { textDecoration, textOverflow, __font } = style;
2037
- if (!width)
2038
- width = 0;
2039
- if (padding) {
2040
- const [top, right, bottom, left] = core.MathHelper.fourNumber(padding);
2041
- if (width) {
2042
- x = left;
2043
- width -= (right + left);
2044
- }
2045
- if (height) {
2046
- y = top;
2047
- height -= (top + bottom);
2048
- }
2284
+ const { top, right, bottom, left } = core.Direction4;
2285
+ function getDrawData(content, style) {
2286
+ if (typeof content !== 'string')
2287
+ content = String(content);
2288
+ let x = 0, y = 0;
2289
+ let width = style.__getInput('width') || 0;
2290
+ let height = style.__getInput('height') || 0;
2291
+ const { textDecoration, __font, __padding: padding } = style;
2292
+ if (padding) {
2293
+ if (width) {
2294
+ x = padding[left];
2295
+ width -= (padding[right] + padding[left]);
2296
+ }
2297
+ if (height) {
2298
+ y = padding[top];
2299
+ height -= (padding[top] + padding[bottom]);
2300
+ }
2301
+ }
2302
+ const drawData = {
2303
+ bounds: { x, y, width, height },
2304
+ rows: [],
2305
+ paraNumber: 0,
2306
+ font: core.Platform.canvas.font = __font
2307
+ };
2308
+ createRows(drawData, content, style);
2309
+ if (padding)
2310
+ padAutoText(padding, drawData, style, width, height);
2311
+ layoutText(drawData, style);
2312
+ layoutChar(drawData, style, width);
2313
+ if (drawData.overflow)
2314
+ clipText(drawData, style);
2315
+ if (textDecoration !== 'none')
2316
+ decorationText(drawData, style);
2317
+ return drawData;
2318
+ }
2319
+ function padAutoText(padding, drawData, style, width, height) {
2320
+ if (!width) {
2321
+ switch (style.textAlign) {
2322
+ case 'left':
2323
+ offsetText(drawData, 'x', padding[left]);
2324
+ break;
2325
+ case 'right':
2326
+ offsetText(drawData, 'x', -padding[right]);
2327
+ }
2328
+ }
2329
+ if (!height) {
2330
+ switch (style.verticalAlign) {
2331
+ case 'top':
2332
+ offsetText(drawData, 'y', padding[top]);
2333
+ break;
2334
+ case 'bottom':
2335
+ offsetText(drawData, 'y', -padding[bottom]);
2049
2336
  }
2050
- const drawData = {
2051
- bounds: { x, y, width, height },
2052
- rows: [],
2053
- paraNumber: 0,
2054
- font: core.Platform.canvas.font = __font
2055
- };
2056
- createRows(drawData, content, style);
2057
- layoutText(drawData, style);
2058
- layoutChar(drawData, style, width);
2059
- if (drawData.overflow)
2060
- clipText(drawData, textOverflow);
2061
- if (textDecoration !== 'none')
2062
- decorationText(drawData, style);
2063
- return drawData;
2064
2337
  }
2338
+ }
2339
+ function offsetText(drawData, attrName, value) {
2340
+ const { bounds, rows } = drawData;
2341
+ bounds[attrName] += value;
2342
+ for (let i = 0; i < rows.length; i++)
2343
+ rows[i][attrName] += value;
2344
+ }
2345
+
2346
+ const TextConvertModule = {
2347
+ getDrawData
2065
2348
  };
2066
2349
 
2067
- const ColorConvert = {
2068
- string(color, opacity) {
2069
- if (typeof color === 'string')
2070
- return color;
2071
- let a = color.a === undefined ? 1 : color.a;
2072
- if (opacity)
2073
- a *= opacity;
2074
- const rgb = color.r + ',' + color.g + ',' + color.b;
2075
- return a === 1 ? 'rgb(' + rgb + ')' : 'rgba(' + rgb + ',' + a + ')';
2076
- }
2350
+ function string(color, opacity) {
2351
+ if (typeof color === 'string')
2352
+ return color;
2353
+ let a = color.a === undefined ? 1 : color.a;
2354
+ if (opacity)
2355
+ a *= opacity;
2356
+ const rgb = color.r + ',' + color.g + ',' + color.b;
2357
+ return a === 1 ? 'rgb(' + rgb + ')' : 'rgba(' + rgb + ',' + a + ')';
2358
+ }
2359
+
2360
+ const ColorConvertModule = {
2361
+ string
2077
2362
  };
2078
2363
 
2079
- const Export = {
2364
+ const { setPoint, addPoint, toBounds } = core.TwoPointBoundsHelper;
2365
+ function getTrimBounds(canvas) {
2366
+ const { width, height } = canvas.view;
2367
+ const { data } = canvas.context.getImageData(0, 0, width, height);
2368
+ let x, y, pointBounds, index = 0;
2369
+ for (let i = 0; i < data.length; i += 4) {
2370
+ if (data[i + 3] !== 0) {
2371
+ x = index % width;
2372
+ y = (index - x) / width;
2373
+ pointBounds ? addPoint(pointBounds, x, y) : setPoint(pointBounds = {}, x, y);
2374
+ }
2375
+ index++;
2376
+ }
2377
+ const bounds = new core.Bounds();
2378
+ toBounds(pointBounds, bounds);
2379
+ return bounds.scale(1 / canvas.pixelRatio).ceil();
2380
+ }
2381
+
2382
+ const ExportModule = {
2080
2383
  export(leaf, filename, options) {
2384
+ this.running = true;
2081
2385
  return addTask((success) => new Promise((resolve) => {
2386
+ const over = (result) => {
2387
+ success(result);
2388
+ resolve();
2389
+ this.running = false;
2390
+ };
2082
2391
  const { leafer } = leaf;
2083
2392
  if (leafer) {
2084
2393
  leafer.waitViewCompleted(() => __awaiter(this, void 0, void 0, function* () {
2085
- let quality, blob;
2086
- let { canvas } = leafer;
2087
- let { unreal } = canvas;
2088
- if (unreal) {
2089
- canvas = canvas.getSameCanvas();
2090
- canvas.backgroundColor = leafer.config.fill;
2091
- leafer.__render(canvas, {});
2394
+ options = core.FileHelper.getExportOptions(options);
2395
+ let renderBounds, trimBounds, scaleX = 1, scaleY = 1;
2396
+ const { worldTransform, isLeafer, isFrame } = leaf;
2397
+ const { slice, trim, onCanvas } = options;
2398
+ const scale = options.scale || 1;
2399
+ const pixelRatio = options.pixelRatio || 1;
2400
+ const screenshot = options.screenshot || leaf.isApp;
2401
+ const fill = (isLeafer && screenshot) ? (options.fill === undefined ? leaf.fill : options.fill) : options.fill;
2402
+ const needFill = core.FileHelper.isOpaqueImage(filename) || fill, matrix = new core.Matrix();
2403
+ if (screenshot) {
2404
+ renderBounds = screenshot === true ? (isLeafer ? leafer.canvas.bounds : leaf.worldRenderBounds) : screenshot;
2092
2405
  }
2093
- switch (typeof options) {
2094
- case 'object':
2095
- if (options.quality)
2096
- quality = options.quality;
2097
- if (options.blob)
2098
- blob = true;
2099
- break;
2100
- case 'number':
2101
- quality = options;
2102
- break;
2103
- case 'boolean':
2104
- blob = options;
2406
+ else {
2407
+ let relative = options.relative || (isLeafer ? 'inner' : 'local');
2408
+ scaleX = worldTransform.scaleX;
2409
+ scaleY = worldTransform.scaleY;
2410
+ switch (relative) {
2411
+ case 'inner':
2412
+ matrix.set(worldTransform);
2413
+ break;
2414
+ case 'local':
2415
+ matrix.set(worldTransform).divide(leaf.localTransform);
2416
+ scaleX /= leaf.scaleX;
2417
+ scaleY /= leaf.scaleY;
2418
+ break;
2419
+ case 'world':
2420
+ scaleX = 1;
2421
+ scaleY = 1;
2422
+ break;
2423
+ case 'page':
2424
+ relative = leaf.leafer;
2425
+ default:
2426
+ matrix.set(worldTransform).divide(leaf.getTransform(relative));
2427
+ const l = relative.worldTransform;
2428
+ scaleX /= scaleX / l.scaleX;
2429
+ scaleY /= scaleY / l.scaleY;
2430
+ }
2431
+ renderBounds = leaf.getBounds('render', relative);
2105
2432
  }
2106
- let data;
2107
- if (filename.includes('.')) {
2108
- data = yield canvas.saveAs(filename, quality);
2433
+ const { x, y, width, height } = new core.Bounds(renderBounds).scale(scale);
2434
+ let canvas = core.Creator.canvas({ width: Math.round(width), height: Math.round(height), pixelRatio });
2435
+ const renderOptions = { matrix: matrix.scale(1 / scale).invert().translate(-x, -y).withScale(1 / scaleX * scale, 1 / scaleY * scale) };
2436
+ if (slice) {
2437
+ leaf = leafer;
2438
+ renderOptions.bounds = canvas.bounds;
2109
2439
  }
2110
- else if (blob) {
2111
- data = yield canvas.toBlob(filename, quality);
2440
+ canvas.save();
2441
+ if (isFrame && fill !== undefined) {
2442
+ const oldFill = leaf.get('fill');
2443
+ leaf.fill = '';
2444
+ leaf.__render(canvas, renderOptions);
2445
+ leaf.fill = oldFill;
2112
2446
  }
2113
2447
  else {
2114
- data = yield canvas.toDataURL(filename, quality);
2448
+ leaf.__render(canvas, renderOptions);
2449
+ }
2450
+ canvas.restore();
2451
+ if (trim) {
2452
+ trimBounds = getTrimBounds(canvas);
2453
+ const old = canvas, { width, height } = trimBounds;
2454
+ const config = { x: 0, y: 0, width, height, pixelRatio };
2455
+ canvas = core.Creator.canvas(config);
2456
+ canvas.copyWorld(old, trimBounds, config);
2115
2457
  }
2116
- success({ data });
2117
- resolve();
2118
- if (unreal)
2119
- canvas.recycle();
2458
+ if (needFill)
2459
+ canvas.fillWorld(canvas.bounds, fill || '#FFFFFF', 'destination-over');
2460
+ if (onCanvas)
2461
+ onCanvas(canvas);
2462
+ const data = filename === 'canvas' ? canvas : yield canvas.export(filename, options);
2463
+ over({ data, width: canvas.pixelWidth, height: canvas.pixelHeight, renderBounds, trimBounds });
2120
2464
  }));
2121
2465
  }
2122
2466
  else {
2123
- success({ data: false });
2124
- resolve();
2467
+ over({ data: false });
2125
2468
  }
2126
2469
  }));
2127
2470
  }
@@ -2135,11 +2478,57 @@ function addTask(task) {
2135
2478
  });
2136
2479
  }
2137
2480
 
2138
- Object.assign(core$1.Paint, UIPaint);
2139
- Object.assign(core$1.Effect, UIEffect);
2140
- Object.assign(core$1.TextConvert, TextConvert);
2141
- Object.assign(core$1.ColorConvert, ColorConvert);
2142
- Object.assign(core$1.Export, Export);
2481
+ const canvas = core.LeaferCanvasBase.prototype;
2482
+ const debug = core.Debug.get('@leafer-ui/export');
2483
+ canvas.export = function (filename, options) {
2484
+ const { quality, blob } = core.FileHelper.getExportOptions(options);
2485
+ if (filename.includes('.')) {
2486
+ return this.saveAs(filename, quality);
2487
+ }
2488
+ else if (blob) {
2489
+ return this.toBlob(filename, quality);
2490
+ }
2491
+ else {
2492
+ return this.toDataURL(filename, quality);
2493
+ }
2494
+ };
2495
+ canvas.toBlob = function (type, quality) {
2496
+ return new Promise((resolve) => {
2497
+ core.Platform.origin.canvasToBolb(this.view, type, quality).then((blob) => {
2498
+ resolve(blob);
2499
+ }).catch((e) => {
2500
+ debug.error(e);
2501
+ resolve(null);
2502
+ });
2503
+ });
2504
+ };
2505
+ canvas.toDataURL = function (type, quality) {
2506
+ return core.Platform.origin.canvasToDataURL(this.view, type, quality);
2507
+ };
2508
+ canvas.saveAs = function (filename, quality) {
2509
+ return new Promise((resolve) => {
2510
+ core.Platform.origin.canvasSaveAs(this.view, filename, quality).then(() => {
2511
+ resolve(true);
2512
+ }).catch((e) => {
2513
+ debug.error(e);
2514
+ resolve(false);
2515
+ });
2516
+ });
2517
+ };
2518
+
2519
+ Object.assign(draw.TextConvert, TextConvertModule);
2520
+ Object.assign(draw.ColorConvert, ColorConvertModule);
2521
+ Object.assign(draw.Paint, PaintModule);
2522
+ Object.assign(draw.PaintImage, PaintImageModule);
2523
+ Object.assign(draw.PaintGradient, PaintGradientModule);
2524
+ Object.assign(draw.Effect, EffectModule);
2525
+ Object.assign(draw.Export, ExportModule);
2526
+
2527
+ Object.assign(core.Creator, {
2528
+ interaction: (target, canvas, selector, options) => { return new core$1.InteractionBase(target, canvas, selector, options); },
2529
+ hitCanvas: (options, manager) => new LeaferCanvas(options, manager),
2530
+ hitCanvasManager: () => new core$1.HitCanvasManager()
2531
+ });
2143
2532
 
2144
2533
  Object.defineProperty(exports, 'LeaferImage', {
2145
2534
  enumerable: true,