@leafer-ui/node 1.0.0-rc.8 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/node.esm.js CHANGED
@@ -1,9 +1,10 @@
1
- import { LeafList, DataHelper, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, Bounds, LeafBoundsHelper, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, Platform, AnimateEvent, ResizeEvent, BoundsHelper, Creator, LeaferCanvasBase, canvasPatch, LeaferImage, InteractionBase, FileHelper, MatrixHelper, ImageEvent, PointHelper, Direction4, TaskProcessor } from '@leafer/core';
1
+ import { LeaferCanvasBase, Platform, canvasPatch, Creator, LeaferImage, FileHelper, LeafList, DataHelper, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, Bounds, LeafBoundsHelper, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, AnimateEvent, ResizeEvent, BoundsHelper, Answer, MatrixHelper, AlignHelper, ImageEvent, AroundHelper, PointHelper, Direction4, TwoPointBoundsHelper, TaskProcessor, Matrix } from '@leafer/core';
2
2
  export * from '@leafer/core';
3
3
  export { LeaferImage } from '@leafer/core';
4
4
  import { writeFileSync } from 'fs';
5
- import { ColorConvert as ColorConvert$1, ImageManager as ImageManager$1, Paint, Effect, TextConvert as TextConvert$1, Export as Export$2 } from '@leafer-ui/core';
5
+ import { InteractionBase, HitCanvasManager } from '@leafer-ui/core';
6
6
  export * from '@leafer-ui/core';
7
+ import { PaintImage, ColorConvert, PaintGradient, Export, Group, TextConvert, Paint, Effect } from '@leafer-ui/draw';
7
8
 
8
9
  /******************************************************************************
9
10
  Copyright (c) Microsoft Corporation.
@@ -37,6 +38,73 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
37
38
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
38
39
  };
39
40
 
41
+ class LeaferCanvas extends LeaferCanvasBase {
42
+ get allowBackgroundColor() { return true; }
43
+ init() {
44
+ this.__createView();
45
+ this.__createContext();
46
+ this.resize(this.config);
47
+ if (Platform.roundRectPatch) {
48
+ this.context.__proto__.roundRect = null;
49
+ canvasPatch(this.context.__proto__);
50
+ }
51
+ }
52
+ __createView() {
53
+ this.view = Platform.origin.createCanvas(1, 1);
54
+ }
55
+ updateViewSize() {
56
+ const { width, height, pixelRatio } = this;
57
+ this.view.width = Math.ceil(width * pixelRatio);
58
+ this.view.height = Math.ceil(height * pixelRatio);
59
+ this.clientBounds = this.bounds;
60
+ }
61
+ }
62
+
63
+ const { mineType, fileType } = FileHelper;
64
+ Object.assign(Creator, {
65
+ canvas: (options, manager) => new LeaferCanvas(options, manager),
66
+ image: (options) => new LeaferImage(options)
67
+ });
68
+ function useCanvas(canvasType, power) {
69
+ Platform.canvasType = canvasType;
70
+ if (!Platform.origin) {
71
+ if (canvasType === 'skia') {
72
+ const { Canvas, loadImage } = power;
73
+ Platform.origin = {
74
+ createCanvas: (width, height, format) => new Canvas(width, height, format),
75
+ canvasToDataURL: (canvas, type, quality) => canvas.toDataURLSync(type, { quality }),
76
+ canvasToBolb: (canvas, type, quality) => canvas.toBuffer(type, { quality }),
77
+ canvasSaveAs: (canvas, filename, quality) => canvas.saveAs(filename, { quality }),
78
+ download(_url, _filename) { return undefined; },
79
+ loadImage(src) { return loadImage(Platform.image.getRealURL(src)); }
80
+ };
81
+ Platform.roundRectPatch = true;
82
+ }
83
+ else if (canvasType === 'napi') {
84
+ const { Canvas, loadImage } = power;
85
+ Platform.origin = {
86
+ createCanvas: (width, height, format) => new Canvas(width, height, format),
87
+ canvasToDataURL: (canvas, type, quality) => canvas.toDataURL(mineType(type), quality),
88
+ canvasToBolb: (canvas, type, quality) => __awaiter(this, void 0, void 0, function* () { return canvas.toBuffer(mineType(type), quality); }),
89
+ canvasSaveAs: (canvas, filename, quality) => __awaiter(this, void 0, void 0, function* () { return writeFileSync(filename, canvas.toBuffer(mineType(fileType(filename)), quality)); }),
90
+ download(_url, _filename) { return undefined; },
91
+ loadImage(src) { return loadImage(Platform.image.getRealURL(src)); }
92
+ };
93
+ }
94
+ Platform.ellipseToCurve = true;
95
+ Platform.event = {
96
+ stopDefault(_origin) { },
97
+ stopNow(_origin) { },
98
+ stop(_origin) { }
99
+ };
100
+ Platform.canvas = Creator.canvas();
101
+ }
102
+ }
103
+ Platform.name = 'node';
104
+ Platform.requestRender = function (render) { setTimeout(render); };
105
+ Platform.devicePixelRatio = 1;
106
+ Platform.conicGradientSupport = true;
107
+
40
108
  class Watcher {
41
109
  get childrenChanged() { return this.hasAdd || this.hasRemove || this.hasVisible; }
42
110
  get updatedList() {
@@ -218,7 +286,7 @@ class LayoutBlockData {
218
286
  }
219
287
 
220
288
  const { updateAllMatrix, updateAllChange } = LeafHelper;
221
- const debug$1 = Debug.get('Layouter');
289
+ const debug$2 = Debug.get('Layouter');
222
290
  class Layouter {
223
291
  constructor(target, userConfig) {
224
292
  this.totalTimes = 0;
@@ -253,7 +321,7 @@ class Layouter {
253
321
  target.emitEvent(new LayoutEvent(LayoutEvent.END, this.layoutedBlocks, this.times));
254
322
  }
255
323
  catch (e) {
256
- debug$1.error(e);
324
+ debug$2.error(e);
257
325
  }
258
326
  this.layoutedBlocks = null;
259
327
  }
@@ -267,9 +335,9 @@ class Layouter {
267
335
  }
268
336
  layoutOnce() {
269
337
  if (this.layouting)
270
- return debug$1.warn('layouting');
338
+ return debug$2.warn('layouting');
271
339
  if (this.times > 3)
272
- return debug$1.warn('layout max times');
340
+ return debug$2.warn('layout max times');
273
341
  this.times++;
274
342
  this.totalTimes++;
275
343
  this.layouting = true;
@@ -335,9 +403,11 @@ class Layouter {
335
403
  updateAllChange(target);
336
404
  }
337
405
  addExtra(leaf) {
338
- const block = this.extraBlock || (this.extraBlock = new LayoutBlockData([]));
339
- block.updatedList.add(leaf);
340
- block.beforeBounds.add(leaf.__world);
406
+ if (!this.__updatedList.has(leaf)) {
407
+ const { updatedList, beforeBounds } = this.extraBlock || (this.extraBlock = new LayoutBlockData([]));
408
+ updatedList.length ? beforeBounds.add(leaf.__world) : beforeBounds.set(leaf.__world);
409
+ updatedList.add(leaf);
410
+ }
341
411
  }
342
412
  createBlock(data) {
343
413
  return new LayoutBlockData(data);
@@ -371,7 +441,7 @@ class Layouter {
371
441
  }
372
442
  }
373
443
 
374
- const debug = Debug.get('Renderer');
444
+ const debug$1 = Debug.get('Renderer');
375
445
  class Renderer {
376
446
  get needFill() { return !!(!this.canvas.allowBackgroundColor && this.config.fill); }
377
447
  constructor(target, canvas, userConfig) {
@@ -409,7 +479,7 @@ class Renderer {
409
479
  const { target } = this;
410
480
  this.times = 0;
411
481
  this.totalBounds = new Bounds();
412
- debug.log(target.innerName, '--->');
482
+ debug$1.log(target.innerName, '--->');
413
483
  try {
414
484
  this.emitRender(RenderEvent.START);
415
485
  this.renderOnce(callback);
@@ -418,9 +488,9 @@ class Renderer {
418
488
  }
419
489
  catch (e) {
420
490
  this.rendering = false;
421
- debug.error(e);
491
+ debug$1.error(e);
422
492
  }
423
- debug.log('-------------|');
493
+ debug$1.log('-------------|');
424
494
  }
425
495
  renderAgain() {
426
496
  if (this.rendering) {
@@ -432,9 +502,9 @@ class Renderer {
432
502
  }
433
503
  renderOnce(callback) {
434
504
  if (this.rendering)
435
- return debug.warn('rendering');
505
+ return debug$1.warn('rendering');
436
506
  if (this.times > 3)
437
- return debug.warn('render max times');
507
+ return debug$1.warn('render max times');
438
508
  this.times++;
439
509
  this.totalTimes++;
440
510
  this.rendering = true;
@@ -447,6 +517,10 @@ class Renderer {
447
517
  }
448
518
  else {
449
519
  this.requestLayout();
520
+ if (this.ignore) {
521
+ this.ignore = this.rendering = false;
522
+ return;
523
+ }
450
524
  this.emitRender(RenderEvent.BEFORE);
451
525
  if (this.config.usePartRender && this.totalTimes > 1) {
452
526
  this.partRender();
@@ -467,7 +541,7 @@ class Renderer {
467
541
  partRender() {
468
542
  const { canvas, updateBlocks: list } = this;
469
543
  if (!list)
470
- return debug.warn('PartRender: need update attr');
544
+ return debug$1.warn('PartRender: need update attr');
471
545
  this.mergeBlocks();
472
546
  list.forEach(block => { if (canvas.bounds.hit(block) && !block.isEmpty())
473
547
  this.clipRender(block); });
@@ -483,7 +557,7 @@ class Renderer {
483
557
  canvas.clear();
484
558
  }
485
559
  else {
486
- bounds.spread(1 + 1 / this.canvas.pixelRatio).ceil();
560
+ bounds.spread(10 + 1 / this.canvas.pixelRatio).ceil();
487
561
  canvas.clearWorld(bounds, true);
488
562
  canvas.clipWorld(bounds, true);
489
563
  }
@@ -536,12 +610,12 @@ class Renderer {
536
610
  const startTime = Date.now();
537
611
  Platform.requestRender(() => {
538
612
  this.FPS = Math.min(60, Math.ceil(1000 / (Date.now() - startTime)));
539
- if (this.changed) {
540
- if (this.running && this.canvas.view)
613
+ if (this.running) {
614
+ this.target.emit(AnimateEvent.FRAME);
615
+ if (this.changed && this.canvas.view)
541
616
  this.render();
617
+ this.target.emit(RenderEvent.NEXT);
542
618
  }
543
- if (this.running)
544
- this.target.emit(AnimateEvent.FRAME);
545
619
  if (this.target)
546
620
  this.__requestRender();
547
621
  });
@@ -554,9 +628,12 @@ class Renderer {
554
628
  const bounds = new Bounds(0, 0, width, height);
555
629
  if (!bounds.includes(this.target.__world) || this.needFill || !e.samePixelRatio) {
556
630
  this.addBlock(this.canvas.bounds);
557
- this.target.forceUpdate('blendMode');
631
+ this.target.forceUpdate('surface');
632
+ return;
558
633
  }
559
634
  }
635
+ this.addBlock(new Bounds(0, 0, 1, 1));
636
+ this.changed = true;
560
637
  }
561
638
  __onLayoutEnd(event) {
562
639
  if (event.data)
@@ -567,7 +644,7 @@ class Renderer {
567
644
  empty = (!leaf.__world.width || !leaf.__world.height);
568
645
  if (empty) {
569
646
  if (!leaf.isLeafer)
570
- debug.tip(leaf.innerName, ': empty');
647
+ debug$1.tip(leaf.innerName, ': empty');
571
648
  empty = (!leaf.isBranch || leaf.isBranchLeaf);
572
649
  }
573
650
  return empty;
@@ -594,23 +671,13 @@ class Renderer {
594
671
  if (this.target) {
595
672
  this.stop();
596
673
  this.__removeListenEvents();
597
- this.target = null;
598
- this.canvas = null;
599
- this.config = null;
674
+ this.target = this.canvas = this.config = null;
600
675
  }
601
676
  }
602
677
  }
603
678
 
604
- var AnswerType;
605
- (function (AnswerType) {
606
- AnswerType[AnswerType["No"] = 0] = "No";
607
- AnswerType[AnswerType["Yes"] = 1] = "Yes";
608
- AnswerType[AnswerType["NoAndSkip"] = 2] = "NoAndSkip";
609
- AnswerType[AnswerType["YesAndSkip"] = 3] = "YesAndSkip";
610
- })(AnswerType || (AnswerType = {}));
611
-
612
679
  const { hitRadiusPoint } = BoundsHelper;
613
- class Pather {
680
+ class Picker {
614
681
  constructor(target, selector) {
615
682
  this.target = target;
616
683
  this.selector = selector;
@@ -622,33 +689,41 @@ class Pather {
622
689
  options = {};
623
690
  const through = options.through || false;
624
691
  const ignoreHittable = options.ignoreHittable || false;
692
+ const target = options.target || this.target;
625
693
  this.exclude = options.exclude || null;
626
694
  this.point = { x: hitPoint.x, y: hitPoint.y, radiusX: hitRadius, radiusY: hitRadius };
627
- this.findList = [];
628
- this.eachFind(this.target.children, this.target.__onlyHitMask);
629
- const list = this.findList;
630
- const leaf = this.getBestMatchLeaf();
695
+ this.findList = new LeafList(options.findList);
696
+ if (!options.findList)
697
+ this.hitBranch(target);
698
+ const { list } = this.findList;
699
+ const leaf = this.getBestMatchLeaf(list, options.bottomList, ignoreHittable);
631
700
  const path = ignoreHittable ? this.getPath(leaf) : this.getHitablePath(leaf);
632
701
  this.clear();
633
- return through ? { path, leaf, throughPath: list.length ? this.getThroughPath(list) : path } : { path, leaf };
702
+ return through ? { path, target: leaf, throughPath: list.length ? this.getThroughPath(list) : path } : { path, target: leaf };
634
703
  }
635
- getBestMatchLeaf() {
636
- const { findList: targets } = this;
637
- if (targets.length > 1) {
704
+ getBestMatchLeaf(list, bottomList, ignoreHittable) {
705
+ if (list.length) {
638
706
  let find;
639
- this.findList = [];
707
+ this.findList = new LeafList();
640
708
  const { x, y } = this.point;
641
709
  const point = { x, y, radiusX: 0, radiusY: 0 };
642
- for (let i = 0, len = targets.length; i < len; i++) {
643
- find = targets[i];
644
- if (LeafHelper.worldHittable(find)) {
710
+ for (let i = 0, len = list.length; i < len; i++) {
711
+ find = list[i];
712
+ if (ignoreHittable || LeafHelper.worldHittable(find)) {
645
713
  this.hitChild(find, point);
646
714
  if (this.findList.length)
647
- return this.findList[0];
715
+ return this.findList.list[0];
648
716
  }
649
717
  }
650
718
  }
651
- return targets[0];
719
+ if (bottomList) {
720
+ for (let i = 0, len = bottomList.length; i < len; i++) {
721
+ this.hitChild(bottomList[i].target, this.point, bottomList[i].proxy);
722
+ if (this.findList.length)
723
+ return this.findList.list[0];
724
+ }
725
+ }
726
+ return list[0];
652
727
  }
653
728
  getPath(leaf) {
654
729
  const path = new LeafList();
@@ -660,7 +735,7 @@ class Pather {
660
735
  return path;
661
736
  }
662
737
  getHitablePath(leaf) {
663
- const path = this.getPath(leaf);
738
+ const path = this.getPath(leaf && leaf.hittable ? leaf : null);
664
739
  let item, hittablePath = new LeafList();
665
740
  for (let i = path.list.length - 1; i > -1; i--) {
666
741
  item = path.list[i];
@@ -690,12 +765,15 @@ class Pather {
690
765
  }
691
766
  return throughPath;
692
767
  }
768
+ hitBranch(branch) {
769
+ this.eachFind(branch.children, branch.__onlyHitMask);
770
+ }
693
771
  eachFind(children, hitMask) {
694
772
  let child, hit;
695
773
  const { point } = this, len = children.length;
696
774
  for (let i = len - 1; i > -1; i--) {
697
775
  child = children[i];
698
- if (!child.__.visible || (hitMask && !child.__.isMask))
776
+ if (!child.__.visible || (hitMask && !child.__.mask))
699
777
  continue;
700
778
  hit = child.__.hitRadius ? true : hitRadiusPoint(child.__world, point);
701
779
  if (child.isBranch) {
@@ -711,11 +789,15 @@ class Pather {
711
789
  }
712
790
  }
713
791
  }
714
- hitChild(child, point) {
792
+ hitChild(child, point, proxy) {
715
793
  if (this.exclude && this.exclude.has(child))
716
794
  return;
717
- if (child.__hitWorld(point))
718
- this.findList.push(child);
795
+ if (child.__hitWorld(point)) {
796
+ const { parent } = child;
797
+ if (parent && parent.__hasMask && !child.__.mask && !parent.children.some(item => item.__.mask && item.__hitWorld(point)))
798
+ return;
799
+ this.findList.add(proxy || child);
800
+ }
719
801
  }
720
802
  clear() {
721
803
  this.point = null;
@@ -727,7 +809,8 @@ class Pather {
727
809
  }
728
810
  }
729
811
 
730
- const { Yes, NoAndSkip, YesAndSkip } = AnswerType;
812
+ const { Yes, NoAndSkip, YesAndSkip } = Answer;
813
+ const idCondition = {}, classNameCondition = {}, tagCondition = {};
731
814
  class Selector {
732
815
  constructor(target, userConfig) {
733
816
  this.config = {};
@@ -737,12 +820,13 @@ class Selector {
737
820
  id: (leaf, name) => leaf.id === name ? (this.idMap[name] = leaf, 1) : 0,
738
821
  innerId: (leaf, innerId) => leaf.innerId === innerId ? (this.innerIdMap[innerId] = leaf, 1) : 0,
739
822
  className: (leaf, name) => leaf.className === name ? 1 : 0,
740
- tag: (leaf, name) => leaf.__tag === name ? 1 : 0
823
+ tag: (leaf, name) => leaf.__tag === name ? 1 : 0,
824
+ tags: (leaf, nameMap) => nameMap[leaf.__tag] ? 1 : 0
741
825
  };
742
826
  this.target = target;
743
827
  if (userConfig)
744
828
  this.config = DataHelper.default(userConfig, this.config);
745
- this.pather = new Pather(target, this);
829
+ this.picker = new Picker(target, this);
746
830
  this.__listenEvents();
747
831
  }
748
832
  getBy(condition, branch, one, options) {
@@ -753,12 +837,25 @@ class Selector {
753
837
  case 'string':
754
838
  switch (condition[0]) {
755
839
  case '#':
756
- const leaf = this.getById(condition.substring(1), branch);
757
- return one ? leaf : (leaf ? [leaf] : []);
840
+ idCondition.id = condition.substring(1), condition = idCondition;
841
+ break;
758
842
  case '.':
759
- return this.getByMethod(this.methods.className, branch, one, condition.substring(1));
843
+ classNameCondition.className = condition.substring(1), condition = classNameCondition;
844
+ break;
760
845
  default:
761
- return this.getByMethod(this.methods.tag, branch, one, condition);
846
+ tagCondition.tag = condition, condition = tagCondition;
847
+ }
848
+ case 'object':
849
+ if (condition.id !== undefined) {
850
+ const leaf = this.getById(condition.id, branch);
851
+ return one ? leaf : (leaf ? [leaf] : []);
852
+ }
853
+ else if (condition.tag) {
854
+ const { tag } = condition, isArray = tag instanceof Array;
855
+ return this.getByMethod(isArray ? this.methods.tags : this.methods.tag, branch, one, isArray ? DataHelper.toMap(tag) : tag);
856
+ }
857
+ else {
858
+ return this.getByMethod(this.methods.className, branch, one, condition.className);
762
859
  }
763
860
  case 'function':
764
861
  return this.getByMethod(condition, branch, one, options);
@@ -767,7 +864,7 @@ class Selector {
767
864
  getByPoint(hitPoint, hitRadius, options) {
768
865
  if (Platform.name === 'node')
769
866
  this.target.emit(LayoutEvent.CHECK_UPDATE);
770
- return this.pather.getByPoint(hitPoint, hitRadius, options);
867
+ return this.picker.getByPoint(hitPoint, hitRadius, options);
771
868
  }
772
869
  getByInnerId(innerId, branch) {
773
870
  const cache = this.innerIdMap[innerId];
@@ -843,7 +940,7 @@ class Selector {
843
940
  destroy() {
844
941
  if (this.__eventIds.length) {
845
942
  this.__removeListenEvents();
846
- this.pather.destroy();
943
+ this.picker.destroy();
847
944
  this.findLeaf = null;
848
945
  this.innerIdMap = {};
849
946
  this.idMap = {};
@@ -859,466 +956,91 @@ Object.assign(Creator, {
859
956
  });
860
957
  Platform.layout = Layouter.fullLayout;
861
958
 
862
- class LeaferCanvas extends LeaferCanvasBase {
863
- get allowBackgroundColor() { return true; }
864
- init() {
865
- this.__createView();
866
- this.__createContext();
867
- this.resize(this.config);
868
- if (Platform.roundRectPatch) {
869
- this.context.__proto__.roundRect = null;
870
- canvasPatch(this.context.__proto__);
871
- }
872
- }
873
- __createView() {
874
- this.view = Platform.origin.createCanvas(1, 1);
875
- }
876
- updateViewSize() {
877
- const { width, height, pixelRatio } = this;
878
- this.view.width = width * pixelRatio;
879
- this.view.height = height * pixelRatio;
880
- this.clientBounds = this.bounds;
881
- }
882
- }
883
-
884
- const { mineType, fileType } = FileHelper;
885
- Object.assign(Creator, {
886
- canvas: (options, manager) => new LeaferCanvas(options, manager),
887
- image: (options) => new LeaferImage(options),
888
- hitCanvas: (options, manager) => new LeaferCanvas(options, manager),
889
- interaction: (target, canvas, selector, options) => { return new InteractionBase(target, canvas, selector, options); }
890
- });
891
- function useCanvas(canvasType, power) {
892
- Platform.canvasType = canvasType;
893
- if (!Platform.origin) {
894
- if (canvasType === 'skia') {
895
- const { Canvas, loadImage } = power;
896
- Platform.origin = {
897
- createCanvas: (width, height, format) => new Canvas(width, height, format),
898
- canvasToDataURL: (canvas, type, quality) => canvas.toDataURLSync(type, { quality }),
899
- canvasToBolb: (canvas, type, quality) => canvas.toBuffer(type, { quality }),
900
- canvasSaveAs: (canvas, filename, quality) => canvas.saveAs(filename, { quality }),
901
- loadImage
902
- };
903
- Platform.roundRectPatch = true;
959
+ function fillText(ui, canvas) {
960
+ let row;
961
+ const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
962
+ for (let i = 0, len = rows.length; i < len; i++) {
963
+ row = rows[i];
964
+ if (row.text) {
965
+ canvas.fillText(row.text, row.x, row.y);
904
966
  }
905
- else if (canvasType === 'napi') {
906
- const { Canvas, loadImage } = power;
907
- Platform.origin = {
908
- createCanvas: (width, height, format) => new Canvas(width, height, format),
909
- canvasToDataURL: (canvas, type, quality) => canvas.toDataURL(mineType(type), quality),
910
- canvasToBolb: (canvas, type, quality) => __awaiter(this, void 0, void 0, function* () { return canvas.toBuffer(mineType(type), quality); }),
911
- canvasSaveAs: (canvas, filename, quality) => __awaiter(this, void 0, void 0, function* () { return writeFileSync(filename, canvas.toBuffer(mineType(fileType(filename)), quality)); }),
912
- loadImage
913
- };
967
+ else if (row.data) {
968
+ row.data.forEach(charData => {
969
+ canvas.fillText(charData.char, charData.x, row.y);
970
+ });
914
971
  }
915
- Platform.ellipseToCurve = true;
916
- Platform.event = {
917
- stopDefault(_origin) { },
918
- stopNow(_origin) { },
919
- stop(_origin) { }
920
- };
921
- Platform.canvas = Creator.canvas();
972
+ if (decorationY)
973
+ canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight);
922
974
  }
923
975
  }
924
- Platform.name = 'node';
925
- Platform.requestRender = function (render) { setTimeout(render); };
926
- Platform.devicePixelRatio = 1;
927
- Platform.conicGradientSupport = true;
928
976
 
929
- const { get: get$4, rotateOfOuter: rotateOfOuter$2, translate: translate$1, scaleOfOuter: scaleOfOuter$2, scale: scaleHelper, rotate } = MatrixHelper;
930
- function fillOrFitMode(data, mode, box, width, height, rotation) {
931
- const transform = get$4();
932
- const swap = rotation && rotation !== 180;
933
- const sw = box.width / (swap ? height : width);
934
- const sh = box.height / (swap ? width : height);
935
- const scale = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
936
- const x = box.x + (box.width - width * scale) / 2;
937
- const y = box.y + (box.height - height * scale) / 2;
938
- translate$1(transform, x, y);
939
- scaleHelper(transform, scale);
940
- if (rotation)
941
- rotateOfOuter$2(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
942
- data.scaleX = data.scaleY = scale;
943
- data.transform = transform;
944
- }
945
- function clipMode(data, box, offset, scale, rotation) {
946
- const transform = get$4();
947
- translate$1(transform, box.x, box.y);
948
- if (offset)
949
- translate$1(transform, offset.x, offset.y);
950
- if (scale) {
951
- typeof scale === 'number' ? scaleHelper(transform, scale) : scaleHelper(transform, scale.x, scale.y);
952
- data.scaleX = transform.a;
953
- data.scaleY = transform.d;
954
- }
955
- if (rotation)
956
- rotate(transform, rotation);
957
- data.transform = transform;
977
+ function fill(fill, ui, canvas) {
978
+ canvas.fillStyle = fill;
979
+ ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
958
980
  }
959
- function repeatMode(data, box, width, height, scale, rotation) {
960
- const transform = get$4();
961
- if (rotation) {
962
- rotate(transform, rotation);
963
- switch (rotation) {
964
- case 90:
965
- translate$1(transform, height, 0);
966
- break;
967
- case 180:
968
- translate$1(transform, width, height);
969
- break;
970
- case 270:
971
- translate$1(transform, 0, width);
972
- break;
981
+ function fills(fills, ui, canvas) {
982
+ let item;
983
+ const { windingRule, __font } = ui.__;
984
+ for (let i = 0, len = fills.length; i < len; i++) {
985
+ item = fills[i];
986
+ if (item.image && PaintImage.checkImage(ui, canvas, item, !__font))
987
+ continue;
988
+ if (item.style) {
989
+ canvas.fillStyle = item.style;
990
+ if (item.transform) {
991
+ canvas.save();
992
+ canvas.transform(item.transform);
993
+ if (item.blendMode)
994
+ canvas.blendMode = item.blendMode;
995
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
996
+ canvas.restore();
997
+ }
998
+ else {
999
+ if (item.blendMode) {
1000
+ canvas.saveBlendMode(item.blendMode);
1001
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1002
+ canvas.restoreBlendMode();
1003
+ }
1004
+ else {
1005
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1006
+ }
1007
+ }
973
1008
  }
974
1009
  }
975
- translate$1(transform, box.x, box.y);
976
- if (scale) {
977
- scaleOfOuter$2(transform, box, scale);
978
- data.scaleX = data.scaleY = scale;
979
- }
980
- data.transform = transform;
981
1010
  }
982
1011
 
983
- const { get: get$3, translate } = MatrixHelper;
984
- function createData(leafPaint, image, paint, box) {
985
- let { width, height } = image;
986
- const { opacity, mode, offset, scale, rotation, blendMode, repeat } = paint;
987
- const sameBox = box.width === width && box.height === height;
988
- if (blendMode)
989
- leafPaint.blendMode = blendMode;
990
- const data = leafPaint.data = { mode };
991
- switch (mode) {
992
- case 'strench':
993
- if (!sameBox)
994
- width = box.width, height = box.height;
995
- if (box.x || box.y) {
996
- data.transform = get$3();
997
- translate(data.transform, box.x, box.y);
998
- }
1012
+ function strokeText(stroke, ui, canvas) {
1013
+ const { strokeAlign } = ui.__;
1014
+ const isStrokes = typeof stroke !== 'string';
1015
+ switch (strokeAlign) {
1016
+ case 'center':
1017
+ canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
1018
+ isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
999
1019
  break;
1000
- case 'clip':
1001
- if (offset || scale || rotation)
1002
- clipMode(data, box, offset, scale, rotation);
1020
+ case 'inside':
1021
+ drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
1003
1022
  break;
1004
- case 'repeat':
1005
- if (!sameBox || scale || rotation)
1006
- repeatMode(data, box, width, height, scale, rotation);
1007
- if (!repeat)
1008
- data.repeat = 'repeat';
1023
+ case 'outside':
1024
+ drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
1009
1025
  break;
1010
- case 'fit':
1011
- case 'cover':
1012
- default:
1013
- if (!sameBox || rotation)
1014
- fillOrFitMode(data, mode, box, width, height, rotation);
1015
1026
  }
1016
- data.width = width;
1017
- data.height = height;
1018
- if (opacity)
1019
- data.opacity = opacity;
1020
- if (repeat)
1021
- data.repeat = typeof repeat === 'string' ? (repeat === 'x' ? 'repeat-x' : 'repeat-y') : 'repeat';
1022
1027
  }
1023
-
1024
- function image(ui, attrName, attrValue, box, firstUse) {
1025
- const leafPaint = { type: attrValue.type };
1026
- const image = leafPaint.image = ImageManager.get(attrValue);
1027
- const event = (firstUse || image.loading) && { target: ui, image, attrName, attrValue };
1028
- if (image.ready) {
1029
- if (hasNaturalSize(ui, attrName, image))
1030
- createData(leafPaint, image, attrValue, box);
1031
- if (firstUse) {
1032
- emit(ImageEvent.LOAD, event);
1033
- emit(ImageEvent.LOADED, event);
1034
- }
1035
- }
1036
- else if (image.error) {
1037
- if (firstUse) {
1038
- ui.forceUpdate('surface');
1039
- event.error = image.error;
1040
- emit(ImageEvent.ERROR, event);
1041
- }
1028
+ function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
1029
+ const { __strokeWidth, __font } = ui.__;
1030
+ const out = canvas.getSameCanvas(true, true);
1031
+ out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__);
1032
+ out.font = __font;
1033
+ isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
1034
+ out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
1035
+ fillText(ui, out);
1036
+ out.blendMode = 'normal';
1037
+ if (ui.__worldFlipped) {
1038
+ canvas.copyWorldByReset(out, ui.__nowWorld);
1042
1039
  }
1043
1040
  else {
1044
- if (firstUse)
1045
- emit(ImageEvent.LOAD, event);
1046
- leafPaint.loadId = image.load(() => {
1047
- if (!ui.destroyed) {
1048
- if (hasNaturalSize(ui, attrName, image)) {
1049
- createData(leafPaint, image, attrValue, box);
1050
- ui.forceUpdate('surface');
1051
- }
1052
- emit(ImageEvent.LOADED, event);
1053
- }
1054
- }, (error) => {
1055
- ui.forceUpdate('surface');
1056
- event.error = error;
1057
- emit(ImageEvent.ERROR, event);
1058
- });
1059
- }
1060
- return leafPaint;
1061
- }
1062
- function hasNaturalSize(ui, attrName, image) {
1063
- if (attrName === 'fill' && !ui.__.__naturalWidth) {
1064
- const { __: d } = ui;
1065
- d.__naturalWidth = image.width;
1066
- d.__naturalHeight = image.height;
1067
- if (!d.__getInput('width') || !d.__getInput('height')) {
1068
- ui.forceUpdate('width');
1069
- if (ui.__proxyData) {
1070
- ui.setProxyAttr('width', ui.__.width);
1071
- ui.setProxyAttr('height', ui.__.height);
1072
- }
1073
- return false;
1074
- }
1041
+ canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
1075
1042
  }
1076
- return true;
1077
- }
1078
- function emit(type, data) {
1079
- if (data.target.hasEvent(type))
1080
- data.target.emitEvent(new ImageEvent(type, data));
1081
- }
1082
-
1083
- const Export$1 = {};
1084
-
1085
- const { get: get$2, scale, copy: copy$1 } = MatrixHelper;
1086
- function createPattern(ui, paint, pixelRatio) {
1087
- let { scaleX, scaleY } = ui.__world;
1088
- const id = scaleX + '-' + scaleY;
1089
- if (paint.patternId !== id && !ui.destroyed) {
1090
- scaleX = Math.abs(scaleX);
1091
- scaleY = Math.abs(scaleY);
1092
- const { image, data } = paint;
1093
- let imageScale, imageMatrix, { width, height, scaleX: sx, scaleY: sy, opacity, transform, repeat } = data;
1094
- if (sx) {
1095
- imageMatrix = get$2();
1096
- copy$1(imageMatrix, transform);
1097
- scale(imageMatrix, 1 / sx, 1 / sy);
1098
- scaleX *= sx;
1099
- scaleY *= sy;
1100
- }
1101
- scaleX *= pixelRatio;
1102
- scaleY *= pixelRatio;
1103
- width *= scaleX;
1104
- height *= scaleY;
1105
- const size = width * height;
1106
- if (!repeat) {
1107
- if (size > Platform.image.maxCacheSize)
1108
- return false;
1109
- }
1110
- let maxSize = Platform.image.maxPatternSize;
1111
- if (!image.isSVG) {
1112
- const imageSize = image.width * image.height;
1113
- if (maxSize > imageSize)
1114
- maxSize = imageSize;
1115
- }
1116
- if (size > maxSize)
1117
- imageScale = Math.sqrt(size / maxSize);
1118
- if (imageScale) {
1119
- scaleX /= imageScale;
1120
- scaleY /= imageScale;
1121
- width /= imageScale;
1122
- height /= imageScale;
1123
- }
1124
- if (sx) {
1125
- scaleX /= sx;
1126
- scaleY /= sy;
1127
- }
1128
- if (transform || scaleX !== 1 || scaleY !== 1) {
1129
- if (!imageMatrix) {
1130
- imageMatrix = get$2();
1131
- if (transform)
1132
- copy$1(imageMatrix, transform);
1133
- }
1134
- scale(imageMatrix, 1 / scaleX, 1 / scaleY);
1135
- }
1136
- const pattern = Platform.canvas.createPattern(image.getCanvas(width < 1 ? 1 : width, height < 1 ? 1 : height, opacity), repeat || (Platform.origin.noRepeat || 'no-repeat'));
1137
- try {
1138
- if (paint.transform)
1139
- paint.transform = null;
1140
- if (imageMatrix)
1141
- pattern.setTransform ? pattern.setTransform(imageMatrix) : paint.transform = imageMatrix;
1142
- }
1143
- catch (_a) {
1144
- paint.transform = imageMatrix;
1145
- }
1146
- paint.style = pattern;
1147
- paint.patternId = id;
1148
- return true;
1149
- }
1150
- else {
1151
- return false;
1152
- }
1153
- }
1154
-
1155
- const { abs } = Math;
1156
- function checkImage(ui, canvas, paint, allowPaint) {
1157
- const { scaleX, scaleY } = ui.__world;
1158
- if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
1159
- return false;
1160
- }
1161
- else {
1162
- const { data } = paint;
1163
- if (allowPaint) {
1164
- if (!data.repeat) {
1165
- let { width, height } = data;
1166
- width *= abs(scaleX) * canvas.pixelRatio;
1167
- height *= abs(scaleY) * canvas.pixelRatio;
1168
- if (data.scaleX) {
1169
- width *= data.scaleX;
1170
- height *= data.scaleY;
1171
- }
1172
- allowPaint = width * height > Platform.image.maxCacheSize;
1173
- }
1174
- else {
1175
- allowPaint = false;
1176
- }
1177
- }
1178
- if (allowPaint) {
1179
- canvas.save();
1180
- canvas.clip();
1181
- if (paint.blendMode)
1182
- canvas.blendMode = paint.blendMode;
1183
- if (data.opacity)
1184
- canvas.opacity *= data.opacity;
1185
- if (data.transform)
1186
- canvas.transform(data.transform);
1187
- canvas.drawImage(paint.image.view, 0, 0, data.width, data.height);
1188
- canvas.restore();
1189
- return true;
1190
- }
1191
- else {
1192
- if (!paint.style || Export$1.running) {
1193
- createPattern(ui, paint, canvas.pixelRatio);
1194
- }
1195
- else {
1196
- if (!paint.patternTask) {
1197
- paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
1198
- paint.patternTask = null;
1199
- if (canvas.bounds.hit(ui.__world))
1200
- createPattern(ui, paint, canvas.pixelRatio);
1201
- ui.forceUpdate('surface');
1202
- }), 300);
1203
- }
1204
- }
1205
- return false;
1206
- }
1207
- }
1208
- }
1209
-
1210
- function recycleImage(attrName, data) {
1211
- const paints = data['_' + attrName];
1212
- if (paints instanceof Array) {
1213
- let image, recycleMap, input, url;
1214
- for (let i = 0, len = paints.length; i < len; i++) {
1215
- image = paints[i].image;
1216
- url = image && image.url;
1217
- if (url) {
1218
- if (!recycleMap)
1219
- recycleMap = {};
1220
- recycleMap[url] = true;
1221
- ImageManager.recycle(image);
1222
- if (image.loading) {
1223
- if (!input) {
1224
- input = (data.__input && data.__input[attrName]) || [];
1225
- if (!(input instanceof Array))
1226
- input = [input];
1227
- }
1228
- image.unload(paints[i].loadId, !input.some((item) => item.url === url));
1229
- }
1230
- }
1231
- }
1232
- return recycleMap;
1233
- }
1234
- return null;
1235
- }
1236
-
1237
- function fillText(ui, canvas) {
1238
- let row;
1239
- const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
1240
- for (let i = 0, len = rows.length; i < len; i++) {
1241
- row = rows[i];
1242
- if (row.text) {
1243
- canvas.fillText(row.text, row.x, row.y);
1244
- }
1245
- else if (row.data) {
1246
- row.data.forEach(charData => {
1247
- canvas.fillText(charData.char, charData.x, row.y);
1248
- });
1249
- }
1250
- if (decorationY)
1251
- canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight);
1252
- }
1253
- }
1254
-
1255
- function fill(fill, ui, canvas) {
1256
- canvas.fillStyle = fill;
1257
- ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
1258
- }
1259
- function fills(fills, ui, canvas) {
1260
- let item;
1261
- const { windingRule, __font } = ui.__;
1262
- for (let i = 0, len = fills.length; i < len; i++) {
1263
- item = fills[i];
1264
- if (item.image && checkImage(ui, canvas, item, !__font))
1265
- continue;
1266
- if (item.style) {
1267
- canvas.fillStyle = item.style;
1268
- if (item.transform) {
1269
- canvas.save();
1270
- canvas.transform(item.transform);
1271
- if (item.blendMode)
1272
- canvas.blendMode = item.blendMode;
1273
- __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1274
- canvas.restore();
1275
- }
1276
- else {
1277
- if (item.blendMode) {
1278
- canvas.saveBlendMode(item.blendMode);
1279
- __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1280
- canvas.restoreBlendMode();
1281
- }
1282
- else {
1283
- __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1284
- }
1285
- }
1286
- }
1287
- }
1288
- }
1289
-
1290
- function strokeText(stroke, ui, canvas, renderOptions) {
1291
- const { strokeAlign } = ui.__;
1292
- const isStrokes = typeof stroke !== 'string';
1293
- switch (strokeAlign) {
1294
- case 'center':
1295
- canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
1296
- isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
1297
- break;
1298
- case 'inside':
1299
- drawAlignStroke('inside', stroke, isStrokes, ui, canvas, renderOptions);
1300
- break;
1301
- case 'outside':
1302
- drawAlignStroke('outside', stroke, isStrokes, ui, canvas, renderOptions);
1303
- break;
1304
- }
1305
- }
1306
- function drawAlignStroke(align, stroke, isStrokes, ui, canvas, renderOptions) {
1307
- const { strokeWidth, __font } = ui.__;
1308
- const out = canvas.getSameCanvas(true);
1309
- out.setStroke(isStrokes ? undefined : stroke, strokeWidth * 2, ui.__);
1310
- out.font = __font;
1311
- isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
1312
- out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
1313
- fillText(ui, out);
1314
- out.blendMode = 'normal';
1315
- if (ui.__worldFlipped || renderOptions.matrix) {
1316
- canvas.copyWorldByReset(out);
1317
- }
1318
- else {
1319
- canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds);
1320
- }
1321
- out.recycle();
1043
+ out.recycle(ui.__nowWorld);
1322
1044
  }
1323
1045
  function drawTextStroke(ui, canvas) {
1324
1046
  let row;
@@ -1341,7 +1063,7 @@ function drawStrokesStyle(strokes, isText, ui, canvas) {
1341
1063
  let item;
1342
1064
  for (let i = 0, len = strokes.length; i < len; i++) {
1343
1065
  item = strokes[i];
1344
- if (item.image && checkImage(ui, canvas, item, false))
1066
+ if (item.image && PaintImage.checkImage(ui, canvas, item, false))
1345
1067
  continue;
1346
1068
  if (item.style) {
1347
1069
  canvas.strokeStyle = item.style;
@@ -1357,138 +1079,567 @@ function drawStrokesStyle(strokes, isText, ui, canvas) {
1357
1079
  }
1358
1080
  }
1359
1081
 
1360
- function stroke(stroke, ui, canvas, renderOptions) {
1082
+ function stroke(stroke, ui, canvas) {
1361
1083
  const options = ui.__;
1362
- const { strokeWidth, strokeAlign, __font } = options;
1363
- if (!strokeWidth)
1084
+ const { __strokeWidth, strokeAlign, __font } = options;
1085
+ if (!__strokeWidth)
1364
1086
  return;
1365
1087
  if (__font) {
1366
- strokeText(stroke, ui, canvas, renderOptions);
1088
+ strokeText(stroke, ui, canvas);
1367
1089
  }
1368
1090
  else {
1369
1091
  switch (strokeAlign) {
1370
1092
  case 'center':
1371
- canvas.setStroke(stroke, strokeWidth, options);
1093
+ canvas.setStroke(stroke, __strokeWidth, options);
1372
1094
  canvas.stroke();
1373
1095
  break;
1374
1096
  case 'inside':
1375
1097
  canvas.save();
1376
- canvas.setStroke(stroke, strokeWidth * 2, options);
1098
+ canvas.setStroke(stroke, __strokeWidth * 2, options);
1377
1099
  options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1378
1100
  canvas.stroke();
1379
1101
  canvas.restore();
1380
1102
  break;
1381
1103
  case 'outside':
1382
- const out = canvas.getSameCanvas(true);
1383
- out.setStroke(stroke, strokeWidth * 2, ui.__);
1104
+ const out = canvas.getSameCanvas(true, true);
1105
+ out.setStroke(stroke, __strokeWidth * 2, options);
1384
1106
  ui.__drawRenderPath(out);
1385
1107
  out.stroke();
1386
1108
  options.windingRule ? out.clip(options.windingRule) : out.clip();
1387
1109
  out.clearWorld(ui.__layout.renderBounds);
1388
- if (ui.__worldFlipped || renderOptions.matrix) {
1389
- canvas.copyWorldByReset(out);
1110
+ if (ui.__worldFlipped) {
1111
+ canvas.copyWorldByReset(out, ui.__nowWorld);
1112
+ }
1113
+ else {
1114
+ canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
1115
+ }
1116
+ out.recycle(ui.__nowWorld);
1117
+ break;
1118
+ }
1119
+ }
1120
+ }
1121
+ function strokes(strokes, ui, canvas) {
1122
+ const options = ui.__;
1123
+ const { __strokeWidth, strokeAlign, __font } = options;
1124
+ if (!__strokeWidth)
1125
+ return;
1126
+ if (__font) {
1127
+ strokeText(strokes, ui, canvas);
1128
+ }
1129
+ else {
1130
+ switch (strokeAlign) {
1131
+ case 'center':
1132
+ canvas.setStroke(undefined, __strokeWidth, options);
1133
+ drawStrokesStyle(strokes, false, ui, canvas);
1134
+ break;
1135
+ case 'inside':
1136
+ canvas.save();
1137
+ canvas.setStroke(undefined, __strokeWidth * 2, options);
1138
+ options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1139
+ drawStrokesStyle(strokes, false, ui, canvas);
1140
+ canvas.restore();
1141
+ break;
1142
+ case 'outside':
1143
+ const { renderBounds } = ui.__layout;
1144
+ const out = canvas.getSameCanvas(true, true);
1145
+ ui.__drawRenderPath(out);
1146
+ out.setStroke(undefined, __strokeWidth * 2, options);
1147
+ drawStrokesStyle(strokes, false, ui, out);
1148
+ options.windingRule ? out.clip(options.windingRule) : out.clip();
1149
+ out.clearWorld(renderBounds);
1150
+ if (ui.__worldFlipped) {
1151
+ canvas.copyWorldByReset(out, ui.__nowWorld);
1390
1152
  }
1391
1153
  else {
1392
- canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds);
1154
+ canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
1393
1155
  }
1394
- out.recycle();
1156
+ out.recycle(ui.__nowWorld);
1395
1157
  break;
1396
1158
  }
1397
1159
  }
1398
1160
  }
1399
- function strokes(strokes, ui, canvas, renderOptions) {
1400
- const options = ui.__;
1401
- const { strokeWidth, strokeAlign, __font } = options;
1402
- if (!strokeWidth)
1403
- return;
1404
- if (__font) {
1405
- strokeText(strokes, ui, canvas, renderOptions);
1161
+
1162
+ const { getSpread, getOuterOf, getByMove, getIntersectData } = BoundsHelper;
1163
+ function shape(ui, current, options) {
1164
+ const canvas = current.getSameCanvas();
1165
+ const nowWorld = ui.__nowWorld;
1166
+ let bounds, fitMatrix, shapeBounds, worldCanvas;
1167
+ let { scaleX, scaleY } = nowWorld;
1168
+ if (scaleX < 0)
1169
+ scaleX = -scaleX;
1170
+ if (scaleY < 0)
1171
+ scaleY = -scaleY;
1172
+ if (current.bounds.includes(nowWorld)) {
1173
+ worldCanvas = canvas;
1174
+ bounds = shapeBounds = nowWorld;
1175
+ }
1176
+ else {
1177
+ const { renderShapeSpread: spread } = ui.__layout;
1178
+ const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, scaleX === scaleY ? spread * scaleX : [spread * scaleY, spread * scaleX]) : current.bounds, nowWorld);
1179
+ fitMatrix = current.bounds.getFitMatrix(worldClipBounds);
1180
+ let { a: fitScaleX, d: fitScaleY } = fitMatrix;
1181
+ if (fitMatrix.a < 1) {
1182
+ worldCanvas = current.getSameCanvas();
1183
+ ui.__renderShape(worldCanvas, options);
1184
+ scaleX *= fitScaleX;
1185
+ scaleY *= fitScaleY;
1186
+ }
1187
+ shapeBounds = getOuterOf(nowWorld, fitMatrix);
1188
+ bounds = getByMove(shapeBounds, -fitMatrix.e, -fitMatrix.f);
1189
+ if (options.matrix) {
1190
+ const { matrix } = options;
1191
+ fitMatrix.multiply(matrix);
1192
+ fitScaleX *= matrix.scaleX;
1193
+ fitScaleY *= matrix.scaleY;
1194
+ }
1195
+ options = Object.assign(Object.assign({}, options), { matrix: fitMatrix.withScale(fitScaleX, fitScaleY) });
1196
+ }
1197
+ ui.__renderShape(canvas, options);
1198
+ return {
1199
+ canvas, matrix: fitMatrix, bounds,
1200
+ worldCanvas, shapeBounds, scaleX, scaleY
1201
+ };
1202
+ }
1203
+
1204
+ let recycleMap;
1205
+ function compute(attrName, ui) {
1206
+ const data = ui.__, leafPaints = [];
1207
+ let paints = data.__input[attrName], hasOpacityPixel;
1208
+ if (!(paints instanceof Array))
1209
+ paints = [paints];
1210
+ recycleMap = PaintImage.recycleImage(attrName, data);
1211
+ for (let i = 0, len = paints.length, item; i < len; i++) {
1212
+ item = getLeafPaint(attrName, paints[i], ui);
1213
+ if (item)
1214
+ leafPaints.push(item);
1215
+ }
1216
+ data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
1217
+ if (leafPaints.length && leafPaints[0].image)
1218
+ hasOpacityPixel = leafPaints[0].image.hasOpacityPixel;
1219
+ if (attrName === 'fill') {
1220
+ data.__pixelFill = hasOpacityPixel;
1221
+ }
1222
+ else {
1223
+ data.__pixelStroke = hasOpacityPixel;
1224
+ }
1225
+ }
1226
+ function getLeafPaint(attrName, paint, ui) {
1227
+ if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
1228
+ return undefined;
1229
+ const { boxBounds } = ui.__layout;
1230
+ switch (paint.type) {
1231
+ case 'solid':
1232
+ let { type, blendMode, color, opacity } = paint;
1233
+ return { type, blendMode, style: ColorConvert.string(color, opacity) };
1234
+ case 'image':
1235
+ return PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1236
+ case 'linear':
1237
+ return PaintGradient.linearGradient(paint, boxBounds);
1238
+ case 'radial':
1239
+ return PaintGradient.radialGradient(paint, boxBounds);
1240
+ case 'angular':
1241
+ return PaintGradient.conicGradient(paint, boxBounds);
1242
+ default:
1243
+ return paint.r !== undefined ? { type: 'solid', style: ColorConvert.string(paint) } : undefined;
1244
+ }
1245
+ }
1246
+
1247
+ const PaintModule = {
1248
+ compute,
1249
+ fill,
1250
+ fills,
1251
+ fillText,
1252
+ stroke,
1253
+ strokes,
1254
+ strokeText,
1255
+ drawTextStroke,
1256
+ shape
1257
+ };
1258
+
1259
+ let origin = {};
1260
+ const { get: get$3, rotateOfOuter: rotateOfOuter$1, translate: translate$1, scaleOfOuter: scaleOfOuter$1, scale: scaleHelper, rotate } = MatrixHelper;
1261
+ function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1262
+ const transform = get$3();
1263
+ translate$1(transform, box.x + x, box.y + y);
1264
+ scaleHelper(transform, scaleX, scaleY);
1265
+ if (rotation)
1266
+ rotateOfOuter$1(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
1267
+ data.transform = transform;
1268
+ }
1269
+ function clipMode(data, box, x, y, scaleX, scaleY, rotation) {
1270
+ const transform = get$3();
1271
+ translate$1(transform, box.x + x, box.y + y);
1272
+ if (scaleX)
1273
+ scaleHelper(transform, scaleX, scaleY);
1274
+ if (rotation)
1275
+ rotate(transform, rotation);
1276
+ data.transform = transform;
1277
+ }
1278
+ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align) {
1279
+ const transform = get$3();
1280
+ if (rotation) {
1281
+ if (align === 'center') {
1282
+ rotateOfOuter$1(transform, { x: width / 2, y: height / 2 }, rotation);
1283
+ }
1284
+ else {
1285
+ rotate(transform, rotation);
1286
+ switch (rotation) {
1287
+ case 90:
1288
+ translate$1(transform, height, 0);
1289
+ break;
1290
+ case 180:
1291
+ translate$1(transform, width, height);
1292
+ break;
1293
+ case 270:
1294
+ translate$1(transform, 0, width);
1295
+ break;
1296
+ }
1297
+ }
1298
+ }
1299
+ origin.x = box.x + x;
1300
+ origin.y = box.y + y;
1301
+ translate$1(transform, origin.x, origin.y);
1302
+ if (scaleX)
1303
+ scaleOfOuter$1(transform, origin, scaleX, scaleY);
1304
+ data.transform = transform;
1305
+ }
1306
+
1307
+ const { get: get$2, translate } = MatrixHelper;
1308
+ const tempBox = new Bounds();
1309
+ const tempPoint = {};
1310
+ function createData(leafPaint, image, paint, box) {
1311
+ const { blendMode } = paint;
1312
+ if (blendMode)
1313
+ leafPaint.blendMode = blendMode;
1314
+ leafPaint.data = getPatternData(paint, box, image);
1315
+ }
1316
+ function getPatternData(paint, box, image) {
1317
+ let { width, height } = image;
1318
+ if (paint.padding)
1319
+ box = tempBox.set(box).shrink(paint.padding);
1320
+ const { opacity, mode, align, offset, scale, size, rotation, repeat } = paint;
1321
+ const sameBox = box.width === width && box.height === height;
1322
+ const data = { mode };
1323
+ const swapSize = align !== 'center' && (rotation || 0) % 180 === 90;
1324
+ const swapWidth = swapSize ? height : width, swapHeight = swapSize ? width : height;
1325
+ let x = 0, y = 0, scaleX, scaleY;
1326
+ if (!mode || mode === 'cover' || mode === 'fit') {
1327
+ if (!sameBox || rotation) {
1328
+ const sw = box.width / swapWidth, sh = box.height / swapHeight;
1329
+ scaleX = scaleY = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
1330
+ x += (box.width - width * scaleX) / 2, y += (box.height - height * scaleY) / 2;
1331
+ }
1332
+ }
1333
+ else if (size) {
1334
+ scaleX = (typeof size === 'number' ? size : size.width) / width;
1335
+ scaleY = (typeof size === 'number' ? size : size.height) / height;
1336
+ }
1337
+ else if (scale) {
1338
+ scaleX = typeof scale === 'number' ? scale : scale.x;
1339
+ scaleY = typeof scale === 'number' ? scale : scale.y;
1340
+ }
1341
+ if (align) {
1342
+ const imageBounds = { x, y, width: swapWidth, height: swapHeight };
1343
+ if (scaleX)
1344
+ imageBounds.width *= scaleX, imageBounds.height *= scaleY;
1345
+ AlignHelper.toPoint(align, imageBounds, box, tempPoint, true);
1346
+ x += tempPoint.x, y += tempPoint.y;
1347
+ }
1348
+ if (offset)
1349
+ x += offset.x, y += offset.y;
1350
+ switch (mode) {
1351
+ case 'strench':
1352
+ if (!sameBox)
1353
+ width = box.width, height = box.height;
1354
+ break;
1355
+ case 'normal':
1356
+ case 'clip':
1357
+ if (x || y || scaleX || rotation)
1358
+ clipMode(data, box, x, y, scaleX, scaleY, rotation);
1359
+ break;
1360
+ case 'repeat':
1361
+ if (!sameBox || scaleX || rotation)
1362
+ repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align);
1363
+ if (!repeat)
1364
+ data.repeat = 'repeat';
1365
+ break;
1366
+ case 'fit':
1367
+ case 'cover':
1368
+ default:
1369
+ if (scaleX)
1370
+ fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation);
1371
+ }
1372
+ if (!data.transform) {
1373
+ if (box.x || box.y) {
1374
+ data.transform = get$2();
1375
+ translate(data.transform, box.x, box.y);
1376
+ }
1377
+ }
1378
+ if (scaleX && mode !== 'strench') {
1379
+ data.scaleX = scaleX;
1380
+ data.scaleY = scaleY;
1381
+ }
1382
+ data.width = width;
1383
+ data.height = height;
1384
+ if (opacity)
1385
+ data.opacity = opacity;
1386
+ if (repeat)
1387
+ data.repeat = typeof repeat === 'string' ? (repeat === 'x' ? 'repeat-x' : 'repeat-y') : 'repeat';
1388
+ return data;
1389
+ }
1390
+
1391
+ let cache, box = new Bounds();
1392
+ const { isSame } = BoundsHelper;
1393
+ function image(ui, attrName, paint, boxBounds, firstUse) {
1394
+ let leafPaint, event;
1395
+ const image = ImageManager.get(paint);
1396
+ if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
1397
+ leafPaint = cache.leafPaint;
1398
+ }
1399
+ else {
1400
+ leafPaint = { type: paint.type, image };
1401
+ cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
1402
+ }
1403
+ if (firstUse || image.loading)
1404
+ event = { image, attrName, attrValue: paint };
1405
+ if (image.ready) {
1406
+ checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
1407
+ if (firstUse) {
1408
+ onLoad(ui, event);
1409
+ onLoadSuccess(ui, event);
1410
+ }
1411
+ }
1412
+ else if (image.error) {
1413
+ if (firstUse)
1414
+ onLoadError(ui, event, image.error);
1415
+ }
1416
+ else {
1417
+ ignoreRender(ui, true);
1418
+ if (firstUse)
1419
+ onLoad(ui, event);
1420
+ leafPaint.loadId = image.load(() => {
1421
+ ignoreRender(ui, false);
1422
+ if (!ui.destroyed) {
1423
+ if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1424
+ if (image.hasOpacityPixel)
1425
+ ui.__layout.hitCanvasChanged = true;
1426
+ ui.forceUpdate('surface');
1427
+ }
1428
+ onLoadSuccess(ui, event);
1429
+ }
1430
+ leafPaint.loadId = null;
1431
+ }, (error) => {
1432
+ ignoreRender(ui, false);
1433
+ onLoadError(ui, event, error);
1434
+ leafPaint.loadId = null;
1435
+ });
1436
+ }
1437
+ return leafPaint;
1438
+ }
1439
+ function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
1440
+ if (attrName === 'fill' && !ui.__.__naturalWidth) {
1441
+ const data = ui.__;
1442
+ data.__naturalWidth = image.width / data.pixelRatio;
1443
+ data.__naturalHeight = image.height / data.pixelRatio;
1444
+ if (data.__autoSide) {
1445
+ ui.forceUpdate('width');
1446
+ if (ui.__proxyData) {
1447
+ ui.setProxyAttr('width', data.width);
1448
+ ui.setProxyAttr('height', data.height);
1449
+ }
1450
+ return false;
1451
+ }
1452
+ }
1453
+ if (!leafPaint.data)
1454
+ createData(leafPaint, image, paint, boxBounds);
1455
+ return true;
1456
+ }
1457
+ function onLoad(ui, event) {
1458
+ emit(ui, ImageEvent.LOAD, event);
1459
+ }
1460
+ function onLoadSuccess(ui, event) {
1461
+ emit(ui, ImageEvent.LOADED, event);
1462
+ }
1463
+ function onLoadError(ui, event, error) {
1464
+ event.error = error;
1465
+ ui.forceUpdate('surface');
1466
+ emit(ui, ImageEvent.ERROR, event);
1467
+ }
1468
+ function emit(ui, type, data) {
1469
+ if (ui.hasEvent(type))
1470
+ ui.emitEvent(new ImageEvent(type, data));
1471
+ }
1472
+ function ignoreRender(ui, value) {
1473
+ const { leafer } = ui;
1474
+ if (leafer && leafer.viewReady)
1475
+ leafer.renderer.ignore = value;
1476
+ }
1477
+
1478
+ const { get: get$1, scale, copy: copy$1 } = MatrixHelper;
1479
+ const { ceil, abs: abs$1 } = Math;
1480
+ function createPattern(ui, paint, pixelRatio) {
1481
+ let { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
1482
+ const id = scaleX + '-' + scaleY;
1483
+ if (paint.patternId !== id && !ui.destroyed) {
1484
+ scaleX = abs$1(scaleX);
1485
+ scaleY = abs$1(scaleY);
1486
+ const { image, data } = paint;
1487
+ let imageScale, imageMatrix, { width, height, scaleX: sx, scaleY: sy, opacity, transform, repeat } = data;
1488
+ if (sx) {
1489
+ imageMatrix = get$1();
1490
+ copy$1(imageMatrix, transform);
1491
+ scale(imageMatrix, 1 / sx, 1 / sy);
1492
+ scaleX *= sx;
1493
+ scaleY *= sy;
1494
+ }
1495
+ scaleX *= pixelRatio;
1496
+ scaleY *= pixelRatio;
1497
+ width *= scaleX;
1498
+ height *= scaleY;
1499
+ const size = width * height;
1500
+ if (!repeat) {
1501
+ if (size > Platform.image.maxCacheSize)
1502
+ return false;
1503
+ }
1504
+ let maxSize = Platform.image.maxPatternSize;
1505
+ if (!image.isSVG) {
1506
+ const imageSize = image.width * image.height;
1507
+ if (maxSize > imageSize)
1508
+ maxSize = imageSize;
1509
+ }
1510
+ if (size > maxSize)
1511
+ imageScale = Math.sqrt(size / maxSize);
1512
+ if (imageScale) {
1513
+ scaleX /= imageScale;
1514
+ scaleY /= imageScale;
1515
+ width /= imageScale;
1516
+ height /= imageScale;
1517
+ }
1518
+ if (sx) {
1519
+ scaleX /= sx;
1520
+ scaleY /= sy;
1521
+ }
1522
+ if (transform || scaleX !== 1 || scaleY !== 1) {
1523
+ if (!imageMatrix) {
1524
+ imageMatrix = get$1();
1525
+ if (transform)
1526
+ copy$1(imageMatrix, transform);
1527
+ }
1528
+ scale(imageMatrix, 1 / scaleX, 1 / scaleY);
1529
+ }
1530
+ const canvas = image.getCanvas(ceil(width) || 1, ceil(height) || 1, opacity);
1531
+ const pattern = image.getPattern(canvas, repeat || (Platform.origin.noRepeat || 'no-repeat'), imageMatrix, paint);
1532
+ paint.style = pattern;
1533
+ paint.patternId = id;
1534
+ return true;
1535
+ }
1536
+ else {
1537
+ return false;
1538
+ }
1539
+ }
1540
+
1541
+ const { abs } = Math;
1542
+ function checkImage(ui, canvas, paint, allowPaint) {
1543
+ const { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
1544
+ if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
1545
+ return false;
1406
1546
  }
1407
1547
  else {
1408
- switch (strokeAlign) {
1409
- case 'center':
1410
- canvas.setStroke(undefined, strokeWidth, options);
1411
- drawStrokesStyle(strokes, false, ui, canvas);
1412
- break;
1413
- case 'inside':
1414
- canvas.save();
1415
- canvas.setStroke(undefined, strokeWidth * 2, options);
1416
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1417
- drawStrokesStyle(strokes, false, ui, canvas);
1418
- canvas.restore();
1419
- break;
1420
- case 'outside':
1421
- const { renderBounds } = ui.__layout;
1422
- const out = canvas.getSameCanvas(true);
1423
- ui.__drawRenderPath(out);
1424
- out.setStroke(undefined, strokeWidth * 2, ui.__);
1425
- drawStrokesStyle(strokes, false, ui, out);
1426
- options.windingRule ? out.clip(options.windingRule) : out.clip();
1427
- out.clearWorld(renderBounds);
1428
- if (ui.__worldFlipped || renderOptions.matrix) {
1429
- canvas.copyWorldByReset(out);
1548
+ const { data } = paint;
1549
+ if (allowPaint) {
1550
+ if (!data.repeat) {
1551
+ let { width, height } = data;
1552
+ width *= abs(scaleX) * canvas.pixelRatio;
1553
+ height *= abs(scaleY) * canvas.pixelRatio;
1554
+ if (data.scaleX) {
1555
+ width *= data.scaleX;
1556
+ height *= data.scaleY;
1430
1557
  }
1431
- else {
1432
- canvas.copyWorldToInner(out, ui.__world, renderBounds);
1558
+ allowPaint = (width * height > Platform.image.maxCacheSize) || Export.running;
1559
+ }
1560
+ else {
1561
+ allowPaint = false;
1562
+ }
1563
+ }
1564
+ if (allowPaint) {
1565
+ canvas.save();
1566
+ canvas.clip();
1567
+ if (paint.blendMode)
1568
+ canvas.blendMode = paint.blendMode;
1569
+ if (data.opacity)
1570
+ canvas.opacity *= data.opacity;
1571
+ if (data.transform)
1572
+ canvas.transform(data.transform);
1573
+ canvas.drawImage(paint.image.view, 0, 0, data.width, data.height);
1574
+ canvas.restore();
1575
+ return true;
1576
+ }
1577
+ else {
1578
+ if (!paint.style || Export.running) {
1579
+ createPattern(ui, paint, canvas.pixelRatio);
1580
+ }
1581
+ else {
1582
+ if (!paint.patternTask) {
1583
+ paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
1584
+ paint.patternTask = null;
1585
+ if (canvas.bounds.hit(ui.__nowWorld))
1586
+ createPattern(ui, paint, canvas.pixelRatio);
1587
+ ui.forceUpdate('surface');
1588
+ }), 300);
1433
1589
  }
1434
- out.recycle();
1435
- break;
1590
+ }
1591
+ return false;
1436
1592
  }
1437
1593
  }
1438
1594
  }
1439
1595
 
1440
- const { getSpread, getOuterOf, getByMove, getIntersectData } = BoundsHelper;
1441
- function shape(ui, current, options) {
1442
- const canvas = current.getSameCanvas();
1443
- let bounds, matrix, shapeBounds;
1444
- let worldCanvas;
1445
- const { __world } = ui;
1446
- let { scaleX, scaleY } = __world;
1447
- if (scaleX < 0)
1448
- scaleX = -scaleX;
1449
- if (scaleY < 0)
1450
- scaleY = -scaleY;
1451
- if (!current.bounds.includes(__world, options.matrix)) {
1452
- const { renderShapeSpread: spread } = ui.__layout;
1453
- const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, spread * scaleX, spread * scaleY) : current.bounds, __world, options.matrix);
1454
- matrix = current.bounds.getFitMatrix(worldClipBounds);
1455
- if (matrix.a < 1) {
1456
- worldCanvas = current.getSameCanvas();
1457
- ui.__renderShape(worldCanvas, options);
1458
- scaleX *= matrix.a;
1459
- scaleY *= matrix.d;
1460
- }
1461
- shapeBounds = getOuterOf(__world, matrix);
1462
- bounds = getByMove(shapeBounds, -matrix.e, -matrix.f);
1463
- if (options.matrix)
1464
- matrix.multiply(options.matrix);
1465
- options = Object.assign(Object.assign({}, options), { matrix });
1466
- }
1467
- else {
1468
- if (options.matrix) {
1469
- scaleX *= options.matrix.a;
1470
- scaleY *= options.matrix.d;
1471
- bounds = shapeBounds = getOuterOf(__world, options.matrix);
1472
- }
1473
- else {
1474
- bounds = shapeBounds = __world;
1596
+ function recycleImage(attrName, data) {
1597
+ const paints = data['_' + attrName];
1598
+ if (paints instanceof Array) {
1599
+ let image, recycleMap, input, url;
1600
+ for (let i = 0, len = paints.length; i < len; i++) {
1601
+ image = paints[i].image;
1602
+ url = image && image.url;
1603
+ if (url) {
1604
+ if (!recycleMap)
1605
+ recycleMap = {};
1606
+ recycleMap[url] = true;
1607
+ ImageManager.recycle(image);
1608
+ if (image.loading) {
1609
+ if (!input) {
1610
+ input = (data.__input && data.__input[attrName]) || [];
1611
+ if (!(input instanceof Array))
1612
+ input = [input];
1613
+ }
1614
+ image.unload(paints[i].loadId, !input.some((item) => item.url === url));
1615
+ }
1616
+ }
1475
1617
  }
1476
- worldCanvas = canvas;
1618
+ return recycleMap;
1477
1619
  }
1478
- ui.__renderShape(canvas, options);
1479
- return {
1480
- canvas, matrix, bounds,
1481
- worldCanvas, shapeBounds, scaleX, scaleY
1482
- };
1620
+ return null;
1483
1621
  }
1484
1622
 
1485
- const defaultFrom$2 = { x: 0.5, y: 0 };
1486
- const defaultTo$2 = { x: 0.5, y: 1 };
1623
+ const PaintImageModule = {
1624
+ image,
1625
+ checkImage,
1626
+ createPattern,
1627
+ recycleImage,
1628
+ createData,
1629
+ getPatternData,
1630
+ fillOrFitMode,
1631
+ clipMode,
1632
+ repeatMode
1633
+ };
1634
+
1635
+ const { toPoint: toPoint$2 } = AroundHelper;
1636
+ const realFrom$2 = {};
1637
+ const realTo$2 = {};
1487
1638
  function linearGradient(paint, box) {
1488
1639
  let { from, to, type, blendMode, opacity } = paint;
1489
- from || (from = defaultFrom$2);
1490
- to || (to = defaultTo$2);
1491
- const style = Platform.canvas.createLinearGradient(box.x + from.x * box.width, box.y + from.y * box.height, box.x + to.x * box.width, box.y + to.y * box.height);
1640
+ toPoint$2(from || 'top', box, realFrom$2);
1641
+ toPoint$2(to || 'bottom', box, realTo$2);
1642
+ const style = Platform.canvas.createLinearGradient(realFrom$2.x, realFrom$2.y, realTo$2.x, realTo$2.y);
1492
1643
  applyStops(style, paint.stops, opacity);
1493
1644
  const data = { type, style };
1494
1645
  if (blendMode)
@@ -1499,137 +1650,84 @@ function applyStops(gradient, stops, opacity) {
1499
1650
  let stop;
1500
1651
  for (let i = 0, len = stops.length; i < len; i++) {
1501
1652
  stop = stops[i];
1502
- gradient.addColorStop(stop.offset, ColorConvert$1.string(stop.color, opacity));
1653
+ if (typeof stop === 'string') {
1654
+ gradient.addColorStop(i / (len - 1), ColorConvert.string(stop, opacity));
1655
+ }
1656
+ else {
1657
+ gradient.addColorStop(stop.offset, ColorConvert.string(stop.color, opacity));
1658
+ }
1503
1659
  }
1504
1660
  }
1505
1661
 
1506
- const { set: set$1, getAngle: getAngle$1, getDistance: getDistance$1 } = PointHelper;
1507
- const { get: get$1, rotateOfOuter: rotateOfOuter$1, scaleOfOuter: scaleOfOuter$1 } = MatrixHelper;
1508
- const defaultFrom$1 = { x: 0.5, y: 0.5 };
1509
- const defaultTo$1 = { x: 0.5, y: 1 };
1662
+ const { getAngle, getDistance: getDistance$1 } = PointHelper;
1663
+ const { get, rotateOfOuter, scaleOfOuter } = MatrixHelper;
1664
+ const { toPoint: toPoint$1 } = AroundHelper;
1510
1665
  const realFrom$1 = {};
1511
1666
  const realTo$1 = {};
1512
1667
  function radialGradient(paint, box) {
1513
1668
  let { from, to, type, opacity, blendMode, stretch } = paint;
1514
- from || (from = defaultFrom$1);
1515
- to || (to = defaultTo$1);
1516
- const { x, y, width, height } = box;
1517
- set$1(realFrom$1, x + from.x * width, y + from.y * height);
1518
- set$1(realTo$1, x + to.x * width, y + to.y * height);
1519
- let transform;
1520
- if (width !== height || stretch) {
1521
- transform = get$1();
1522
- scaleOfOuter$1(transform, realFrom$1, width / height * (stretch || 1), 1);
1523
- rotateOfOuter$1(transform, realFrom$1, getAngle$1(realFrom$1, realTo$1) + 90);
1524
- }
1669
+ toPoint$1(from || 'center', box, realFrom$1);
1670
+ toPoint$1(to || 'bottom', box, realTo$1);
1525
1671
  const style = Platform.canvas.createRadialGradient(realFrom$1.x, realFrom$1.y, 0, realFrom$1.x, realFrom$1.y, getDistance$1(realFrom$1, realTo$1));
1526
1672
  applyStops(style, paint.stops, opacity);
1527
- const data = { type, style, transform };
1673
+ const data = { type, style };
1674
+ const transform = getTransform(box, realFrom$1, realTo$1, stretch, true);
1675
+ if (transform)
1676
+ data.transform = transform;
1528
1677
  if (blendMode)
1529
1678
  data.blendMode = blendMode;
1530
1679
  return data;
1531
1680
  }
1681
+ function getTransform(box, from, to, stretch, rotate90) {
1682
+ let transform;
1683
+ const { width, height } = box;
1684
+ if (width !== height || stretch) {
1685
+ const angle = getAngle(from, to);
1686
+ transform = get();
1687
+ if (rotate90) {
1688
+ scaleOfOuter(transform, from, width / height * (stretch || 1), 1);
1689
+ rotateOfOuter(transform, from, angle + 90);
1690
+ }
1691
+ else {
1692
+ scaleOfOuter(transform, from, 1, width / height * (stretch || 1));
1693
+ rotateOfOuter(transform, from, angle);
1694
+ }
1695
+ }
1696
+ return transform;
1697
+ }
1532
1698
 
1533
- const { set, getAngle, getDistance } = PointHelper;
1534
- const { get, rotateOfOuter, scaleOfOuter } = MatrixHelper;
1535
- const defaultFrom = { x: 0.5, y: 0.5 };
1536
- const defaultTo = { x: 0.5, y: 1 };
1699
+ const { getDistance } = PointHelper;
1700
+ const { toPoint } = AroundHelper;
1537
1701
  const realFrom = {};
1538
1702
  const realTo = {};
1539
1703
  function conicGradient(paint, box) {
1540
1704
  let { from, to, type, opacity, blendMode, stretch } = paint;
1541
- from || (from = defaultFrom);
1542
- to || (to = defaultTo);
1543
- const { x, y, width, height } = box;
1544
- set(realFrom, x + from.x * width, y + from.y * height);
1545
- set(realTo, x + to.x * width, y + to.y * height);
1546
- const transform = get();
1547
- const angle = getAngle(realFrom, realTo);
1548
- if (Platform.conicGradientRotate90) {
1549
- scaleOfOuter(transform, realFrom, width / height * (stretch || 1), 1);
1550
- rotateOfOuter(transform, realFrom, angle + 90);
1551
- }
1552
- else {
1553
- scaleOfOuter(transform, realFrom, 1, width / height * (stretch || 1));
1554
- rotateOfOuter(transform, realFrom, angle);
1555
- }
1705
+ toPoint(from || 'center', box, realFrom);
1706
+ toPoint(to || 'bottom', box, realTo);
1556
1707
  const style = Platform.conicGradientSupport ? Platform.canvas.createConicGradient(0, realFrom.x, realFrom.y) : Platform.canvas.createRadialGradient(realFrom.x, realFrom.y, 0, realFrom.x, realFrom.y, getDistance(realFrom, realTo));
1557
1708
  applyStops(style, paint.stops, opacity);
1558
- const data = { type, style, transform };
1709
+ const data = { type, style };
1710
+ const transform = getTransform(box, realFrom, realTo, stretch || 1, Platform.conicGradientRotate90);
1711
+ if (transform)
1712
+ data.transform = transform;
1559
1713
  if (blendMode)
1560
1714
  data.blendMode = blendMode;
1561
1715
  return data;
1562
1716
  }
1563
1717
 
1564
- let recycleMap;
1565
- function compute(attrName, ui) {
1566
- const value = [];
1567
- const data = ui.__;
1568
- let item;
1569
- let paints = data.__input[attrName];
1570
- if (!(paints instanceof Array))
1571
- paints = [paints];
1572
- recycleMap = recycleImage(attrName, data);
1573
- for (let i = 0, len = paints.length; i < len; i++) {
1574
- item = getLeafPaint(attrName, paints[i], ui);
1575
- if (item)
1576
- value.push(item);
1577
- }
1578
- data['_' + attrName] = value.length ? value : undefined;
1579
- let isPixel;
1580
- if (paints.length === 1) {
1581
- const paint = paints[0];
1582
- if (paint.type === 'image')
1583
- isPixel = ImageManager$1.isPixel(paint);
1584
- }
1585
- if (attrName === 'fill') {
1586
- data.__pixelFill = isPixel;
1587
- }
1588
- else {
1589
- data.__pixelStroke = isPixel;
1590
- }
1591
- }
1592
- function getLeafPaint(attrName, paint, ui) {
1593
- if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
1594
- return undefined;
1595
- const { boxBounds } = ui.__layout;
1596
- switch (paint.type) {
1597
- case 'solid':
1598
- let { type, blendMode, color, opacity } = paint;
1599
- return { type, blendMode, style: ColorConvert$1.string(color, opacity) };
1600
- case 'image':
1601
- return image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1602
- case 'linear':
1603
- return linearGradient(paint, boxBounds);
1604
- case 'radial':
1605
- return radialGradient(paint, boxBounds);
1606
- case 'angular':
1607
- return conicGradient(paint, boxBounds);
1608
- default:
1609
- return paint.r ? { type: 'solid', style: ColorConvert$1.string(paint) } : undefined;
1610
- }
1611
- }
1612
-
1613
- var UIPaint = /*#__PURE__*/Object.freeze({
1614
- __proto__: null,
1615
- compute: compute,
1616
- drawTextStroke: drawTextStroke,
1617
- fill: fill,
1618
- fillText: fillText,
1619
- fills: fills,
1620
- recycleImage: recycleImage,
1621
- shape: shape,
1622
- stroke: stroke,
1623
- strokeText: strokeText,
1624
- strokes: strokes
1625
- });
1718
+ const PaintGradientModule = {
1719
+ linearGradient,
1720
+ radialGradient,
1721
+ conicGradient,
1722
+ getTransform
1723
+ };
1626
1724
 
1627
1725
  const { copy, toOffsetOutBounds: toOffsetOutBounds$1 } = BoundsHelper;
1628
1726
  const tempBounds = {};
1629
1727
  const offsetOutBounds$1 = {};
1630
- function shadow(ui, current, shape, renderOptions) {
1728
+ function shadow(ui, current, shape) {
1631
1729
  let copyBounds, spreadScale;
1632
- const { __world, __layout } = ui;
1730
+ const { __nowWorld: nowWorld, __layout } = ui;
1633
1731
  const { shadow } = ui.__;
1634
1732
  const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
1635
1733
  const other = current.getSameCanvas();
@@ -1644,21 +1742,21 @@ function shadow(ui, current, shape, renderOptions) {
1644
1742
  other.restore();
1645
1743
  other.save();
1646
1744
  if (worldCanvas) {
1647
- other.copyWorld(other, bounds, __world, 'copy');
1648
- copyBounds = __world;
1745
+ other.copyWorld(other, bounds, nowWorld, 'copy');
1746
+ copyBounds = nowWorld;
1649
1747
  }
1650
- worldCanvas ? other.copyWorld(worldCanvas, __world, __world, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
1748
+ worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
1651
1749
  }
1652
- if (ui.__worldFlipped || renderOptions.matrix) {
1653
- current.copyWorldByReset(other, copyBounds, __world, item.blendMode);
1750
+ if (ui.__worldFlipped) {
1751
+ current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1654
1752
  }
1655
1753
  else {
1656
1754
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1657
1755
  }
1658
1756
  if (end && index < end)
1659
- other.clear();
1757
+ other.clearWorld(copyBounds, true);
1660
1758
  });
1661
- other.recycle();
1759
+ other.recycle(copyBounds);
1662
1760
  }
1663
1761
  function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
1664
1762
  const { bounds, shapeBounds } = shape;
@@ -1689,9 +1787,9 @@ function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
1689
1787
 
1690
1788
  const { toOffsetOutBounds } = BoundsHelper;
1691
1789
  const offsetOutBounds = {};
1692
- function innerShadow(ui, current, shape, renderOptions) {
1790
+ function innerShadow(ui, current, shape) {
1693
1791
  let copyBounds, spreadScale;
1694
- const { __world, __layout: __layout } = ui;
1792
+ const { __nowWorld: nowWorld, __layout: __layout } = ui;
1695
1793
  const { innerShadow } = ui.__;
1696
1794
  const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
1697
1795
  const other = current.getSameCanvas();
@@ -1704,40 +1802,115 @@ function innerShadow(ui, current, shape, renderOptions) {
1704
1802
  drawWorldShadow(other, offsetOutBounds, spreadScale, shape);
1705
1803
  other.restore();
1706
1804
  if (worldCanvas) {
1707
- other.copyWorld(other, bounds, __world, 'copy');
1708
- other.copyWorld(worldCanvas, __world, __world, 'source-out');
1709
- copyBounds = __world;
1805
+ other.copyWorld(other, bounds, nowWorld, 'copy');
1806
+ other.copyWorld(worldCanvas, nowWorld, nowWorld, 'source-out');
1807
+ copyBounds = nowWorld;
1710
1808
  }
1711
1809
  else {
1712
1810
  other.copyWorld(shape.canvas, shapeBounds, bounds, 'source-out');
1713
1811
  copyBounds = bounds;
1714
1812
  }
1715
1813
  other.fillWorld(copyBounds, item.color, 'source-in');
1716
- if (ui.__worldFlipped || renderOptions.matrix) {
1717
- current.copyWorldByReset(other, copyBounds, __world, item.blendMode);
1814
+ if (ui.__worldFlipped) {
1815
+ current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1718
1816
  }
1719
1817
  else {
1720
1818
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1721
1819
  }
1722
1820
  if (end && index < end)
1723
- other.clear();
1821
+ other.clearWorld(copyBounds, true);
1724
1822
  });
1725
- other.recycle();
1823
+ other.recycle(copyBounds);
1726
1824
  }
1727
1825
 
1728
1826
  function blur(ui, current, origin) {
1729
1827
  const { blur } = ui.__;
1730
- origin.setWorldBlur(blur * ui.__world.a);
1731
- origin.copyWorldToInner(current, ui.__world, ui.__layout.renderBounds);
1828
+ origin.setWorldBlur(blur * ui.__nowWorld.a);
1829
+ origin.copyWorldToInner(current, ui.__nowWorld, ui.__layout.renderBounds);
1732
1830
  origin.filter = 'none';
1733
1831
  }
1734
1832
 
1735
- var UIEffect = /*#__PURE__*/Object.freeze({
1736
- __proto__: null,
1737
- blur: blur,
1738
- innerShadow: innerShadow,
1739
- shadow: shadow
1740
- });
1833
+ function backgroundBlur(_ui, _current, _shape) {
1834
+ }
1835
+
1836
+ const EffectModule = {
1837
+ shadow,
1838
+ innerShadow,
1839
+ blur,
1840
+ backgroundBlur
1841
+ };
1842
+
1843
+ const { excludeRenderBounds } = LeafBoundsHelper;
1844
+ Group.prototype.__renderMask = function (canvas, options) {
1845
+ let child, maskCanvas, contentCanvas, maskOpacity, currentMask;
1846
+ const { children } = this;
1847
+ for (let i = 0, len = children.length; i < len; i++) {
1848
+ child = children[i];
1849
+ if (child.__.mask) {
1850
+ if (currentMask) {
1851
+ maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
1852
+ maskCanvas = contentCanvas = null;
1853
+ }
1854
+ if (child.__.mask === 'path') {
1855
+ if (child.opacity < 1) {
1856
+ currentMask = 'opacity-path';
1857
+ maskOpacity = child.opacity;
1858
+ if (!contentCanvas)
1859
+ contentCanvas = getCanvas(canvas);
1860
+ }
1861
+ else {
1862
+ currentMask = 'path';
1863
+ canvas.save();
1864
+ }
1865
+ child.__clip(contentCanvas || canvas, options);
1866
+ }
1867
+ else {
1868
+ currentMask = 'alpha';
1869
+ if (!maskCanvas)
1870
+ maskCanvas = getCanvas(canvas);
1871
+ if (!contentCanvas)
1872
+ contentCanvas = getCanvas(canvas);
1873
+ child.__render(maskCanvas, options);
1874
+ }
1875
+ if (child.__.mask !== 'clipping')
1876
+ continue;
1877
+ }
1878
+ if (excludeRenderBounds(child, options))
1879
+ continue;
1880
+ child.__render(contentCanvas || canvas, options);
1881
+ }
1882
+ maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
1883
+ };
1884
+ function maskEnd(leaf, maskMode, canvas, contentCanvas, maskCanvas, maskOpacity) {
1885
+ switch (maskMode) {
1886
+ case 'alpha':
1887
+ usePixelMask(leaf, canvas, contentCanvas, maskCanvas);
1888
+ break;
1889
+ case 'opacity-path':
1890
+ copyContent(leaf, canvas, contentCanvas, maskOpacity);
1891
+ break;
1892
+ case 'path':
1893
+ canvas.restore();
1894
+ }
1895
+ }
1896
+ function getCanvas(canvas) {
1897
+ return canvas.getSameCanvas(false, true);
1898
+ }
1899
+ function usePixelMask(leaf, canvas, content, mask) {
1900
+ const realBounds = leaf.__nowWorld;
1901
+ content.resetTransform();
1902
+ content.opacity = 1;
1903
+ content.useMask(mask, realBounds);
1904
+ mask.recycle(realBounds);
1905
+ copyContent(leaf, canvas, content, 1);
1906
+ }
1907
+ function copyContent(leaf, canvas, content, maskOpacity) {
1908
+ const realBounds = leaf.__nowWorld;
1909
+ canvas.resetTransform();
1910
+ canvas.opacity = maskOpacity;
1911
+ canvas.copyWorld(content, realBounds);
1912
+ content.recycle(realBounds);
1913
+ }
1741
1914
 
1742
1915
  const money = '¥¥$€££¢¢';
1743
1916
  const letter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
@@ -1894,7 +2067,8 @@ function createRows(drawData, content, style) {
1894
2067
  if (breakAll) {
1895
2068
  if (wordWidth)
1896
2069
  addWord();
1897
- addRow();
2070
+ if (rowWidth)
2071
+ addRow();
1898
2072
  }
1899
2073
  else {
1900
2074
  if (!afterBreak)
@@ -1902,10 +2076,12 @@ function createRows(drawData, content, style) {
1902
2076
  if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
1903
2077
  if (wordWidth)
1904
2078
  addWord();
1905
- addRow();
2079
+ if (rowWidth)
2080
+ addRow();
1906
2081
  }
1907
2082
  else {
1908
- addRow();
2083
+ if (rowWidth)
2084
+ addRow();
1909
2085
  }
1910
2086
  }
1911
2087
  }
@@ -2000,11 +2176,11 @@ function layoutChar(drawData, style, width, _height) {
2000
2176
  if (mode === WordMode) {
2001
2177
  wordChar = { char: '', x: charX };
2002
2178
  charX = toWordChar(word.data, charX, wordChar);
2003
- if (wordChar.char !== ' ')
2179
+ if (row.isOverflow || wordChar.char !== ' ')
2004
2180
  row.data.push(wordChar);
2005
2181
  }
2006
2182
  else {
2007
- charX = toChar(word.data, charX, row.data);
2183
+ charX = toChar(word.data, charX, row.data, row.isOverflow);
2008
2184
  }
2009
2185
  if (!row.paraEnd && addWordWidth) {
2010
2186
  charX += addWordWidth;
@@ -2031,9 +2207,9 @@ function toWordChar(data, charX, wordChar) {
2031
2207
  });
2032
2208
  return charX;
2033
2209
  }
2034
- function toChar(data, charX, rowData) {
2210
+ function toChar(data, charX, rowData, isOverflow) {
2035
2211
  data.forEach(char => {
2036
- if (char.char !== ' ') {
2212
+ if (isOverflow || char.char !== ' ') {
2037
2213
  char.x = charX;
2038
2214
  rowData.push(char);
2039
2215
  }
@@ -2065,12 +2241,14 @@ function layoutText(drawData, style) {
2065
2241
  for (let i = 0, len = rows.length; i < len; i++) {
2066
2242
  row = rows[i];
2067
2243
  row.x = x;
2068
- switch (textAlign) {
2069
- case 'center':
2070
- row.x += (width - row.width) / 2;
2071
- break;
2072
- case 'right':
2073
- row.x += width - row.width;
2244
+ if (row.width < width || (row.width > width && !__clipText)) {
2245
+ switch (textAlign) {
2246
+ case 'center':
2247
+ row.x += (width - row.width) / 2;
2248
+ break;
2249
+ case 'right':
2250
+ row.x += width - row.width;
2251
+ }
2074
2252
  }
2075
2253
  if (row.paraStart && paraSpacing && i > 0)
2076
2254
  starY += paraSpacing;
@@ -2106,16 +2284,20 @@ function layoutText(drawData, style) {
2106
2284
  bounds.height = realHeight;
2107
2285
  }
2108
2286
 
2109
- function clipText(drawData, style) {
2287
+ function clipText(drawData, style, x, width) {
2288
+ if (!width)
2289
+ return;
2110
2290
  const { rows, overflow } = drawData;
2111
2291
  let { textOverflow } = style;
2112
2292
  rows.splice(overflow);
2113
- if (textOverflow !== 'hide') {
2114
- if (textOverflow === 'ellipsis')
2293
+ if (textOverflow && textOverflow !== 'show') {
2294
+ if (textOverflow === 'hide')
2295
+ textOverflow = '';
2296
+ else if (textOverflow === 'ellipsis')
2115
2297
  textOverflow = '...';
2116
2298
  let char, charRight;
2117
- const ellipsisWidth = Platform.canvas.measureText(textOverflow).width;
2118
- const right = style.x + style.width - ellipsisWidth;
2299
+ const ellipsisWidth = textOverflow ? Platform.canvas.measureText(textOverflow).width : 0;
2300
+ const right = x + width - ellipsisWidth;
2119
2301
  const list = style.textWrap === 'none' ? rows : [rows[overflow - 1]];
2120
2302
  list.forEach(row => {
2121
2303
  if (row.isOverflow && row.data) {
@@ -2162,42 +2344,40 @@ function decorationText(drawData, style) {
2162
2344
  }
2163
2345
 
2164
2346
  const { top, right, bottom, left } = Direction4;
2165
- const TextConvert = {
2166
- getDrawData(content, style) {
2167
- if (typeof content !== 'string')
2168
- content = String(content);
2169
- let x = 0, y = 0;
2170
- let width = style.__getInput('width') || 0;
2171
- let height = style.__getInput('height') || 0;
2172
- const { textDecoration, __font, __padding: padding } = style;
2173
- if (padding) {
2174
- if (width) {
2175
- x = padding[left];
2176
- width -= (padding[right] + padding[left]);
2177
- }
2178
- if (height) {
2179
- y = padding[top];
2180
- height -= (padding[top] + padding[bottom]);
2181
- }
2182
- }
2183
- const drawData = {
2184
- bounds: { x, y, width, height },
2185
- rows: [],
2186
- paraNumber: 0,
2187
- font: Platform.canvas.font = __font
2188
- };
2189
- createRows(drawData, content, style);
2190
- if (padding)
2191
- padAutoText(padding, drawData, style, width, height);
2192
- layoutText(drawData, style);
2193
- layoutChar(drawData, style, width);
2194
- if (drawData.overflow)
2195
- clipText(drawData, style);
2196
- if (textDecoration !== 'none')
2197
- decorationText(drawData, style);
2198
- return drawData;
2199
- }
2200
- };
2347
+ function getDrawData(content, style) {
2348
+ if (typeof content !== 'string')
2349
+ content = String(content);
2350
+ let x = 0, y = 0;
2351
+ let width = style.__getInput('width') || 0;
2352
+ let height = style.__getInput('height') || 0;
2353
+ const { textDecoration, __font, __padding: padding } = style;
2354
+ if (padding) {
2355
+ if (width) {
2356
+ x = padding[left];
2357
+ width -= (padding[right] + padding[left]);
2358
+ }
2359
+ if (height) {
2360
+ y = padding[top];
2361
+ height -= (padding[top] + padding[bottom]);
2362
+ }
2363
+ }
2364
+ const drawData = {
2365
+ bounds: { x, y, width, height },
2366
+ rows: [],
2367
+ paraNumber: 0,
2368
+ font: Platform.canvas.font = __font
2369
+ };
2370
+ createRows(drawData, content, style);
2371
+ if (padding)
2372
+ padAutoText(padding, drawData, style, width, height);
2373
+ layoutText(drawData, style);
2374
+ layoutChar(drawData, style, width);
2375
+ if (drawData.overflow)
2376
+ clipText(drawData, style, x, width);
2377
+ if (textDecoration !== 'none')
2378
+ decorationText(drawData, style);
2379
+ return drawData;
2380
+ }
2201
2381
  function padAutoText(padding, drawData, style, width, height) {
2202
2382
  if (!width) {
2203
2383
  switch (style.textAlign) {
@@ -2225,67 +2405,152 @@ function offsetText(drawData, attrName, value) {
2225
2405
  rows[i][attrName] += value;
2226
2406
  }
2227
2407
 
2228
- const ColorConvert = {
2229
- string(color, opacity) {
2230
- if (typeof color === 'string')
2231
- return color;
2232
- let a = color.a === undefined ? 1 : color.a;
2233
- if (opacity)
2234
- a *= opacity;
2235
- const rgb = color.r + ',' + color.g + ',' + color.b;
2236
- return a === 1 ? 'rgb(' + rgb + ')' : 'rgba(' + rgb + ',' + a + ')';
2237
- }
2408
+ const TextConvertModule = {
2409
+ getDrawData
2410
+ };
2411
+
2412
+ function string(color, opacity) {
2413
+ if (typeof color === 'string')
2414
+ return color;
2415
+ let a = color.a === undefined ? 1 : color.a;
2416
+ if (opacity)
2417
+ a *= opacity;
2418
+ const rgb = color.r + ',' + color.g + ',' + color.b;
2419
+ return a === 1 ? 'rgb(' + rgb + ')' : 'rgba(' + rgb + ',' + a + ')';
2420
+ }
2421
+
2422
+ const ColorConvertModule = {
2423
+ string
2238
2424
  };
2239
2425
 
2240
- const Export = {
2426
+ const { setPoint, addPoint, toBounds } = TwoPointBoundsHelper;
2427
+ function getTrimBounds(canvas) {
2428
+ const { width, height } = canvas.view;
2429
+ const { data } = canvas.context.getImageData(0, 0, width, height);
2430
+ let x, y, pointBounds, index = 0;
2431
+ for (let i = 0; i < data.length; i += 4) {
2432
+ if (data[i + 3] !== 0) {
2433
+ x = index % width;
2434
+ y = (index - x) / width;
2435
+ pointBounds ? addPoint(pointBounds, x, y) : setPoint(pointBounds = {}, x, y);
2436
+ }
2437
+ index++;
2438
+ }
2439
+ const bounds = new Bounds();
2440
+ toBounds(pointBounds, bounds);
2441
+ return bounds.scale(1 / canvas.pixelRatio).ceil();
2442
+ }
2443
+
2444
+ const ExportModule = {
2241
2445
  export(leaf, filename, options) {
2242
- Export.running = true;
2446
+ this.running = true;
2447
+ const fileType = FileHelper.fileType(filename);
2448
+ options = FileHelper.getExportOptions(options);
2243
2449
  return addTask((success) => new Promise((resolve) => {
2450
+ const over = (result) => {
2451
+ success(result);
2452
+ resolve();
2453
+ this.running = false;
2454
+ };
2455
+ const { toURL } = Platform;
2456
+ const { download } = Platform.origin;
2457
+ if (filename === 'json') {
2458
+ return over({ data: leaf.toJSON(options.json) });
2459
+ }
2460
+ else if (fileType === 'json') {
2461
+ download(toURL(JSON.stringify(leaf.toJSON(options.json)), 'text'), filename);
2462
+ return over({ data: true });
2463
+ }
2464
+ if (filename === 'svg') {
2465
+ return over({ data: leaf.toSVG() });
2466
+ }
2467
+ else if (fileType === 'svg') {
2468
+ download(toURL(leaf.toSVG(), 'svg'), filename);
2469
+ return over({ data: true });
2470
+ }
2244
2471
  const { leafer } = leaf;
2245
2472
  if (leafer) {
2473
+ checkLazy(leaf);
2246
2474
  leafer.waitViewCompleted(() => __awaiter(this, void 0, void 0, function* () {
2247
- let quality, blob;
2248
- let { canvas } = leafer;
2249
- let { unreal } = canvas;
2250
- if (unreal) {
2251
- canvas = canvas.getSameCanvas();
2252
- canvas.backgroundColor = leafer.config.fill;
2253
- leafer.__render(canvas, {});
2475
+ let renderBounds, trimBounds, scaleX = 1, scaleY = 1;
2476
+ const { worldTransform, isLeafer, isFrame } = leaf;
2477
+ const { slice, trim, onCanvas } = options;
2478
+ let scale = options.scale || 1;
2479
+ let pixelRatio = options.pixelRatio || 1;
2480
+ const smooth = options.smooth === undefined ? leafer.config.smooth : options.smooth;
2481
+ const contextSettings = options.contextSettings || leafer.config.contextSettings;
2482
+ if (leaf.isApp) {
2483
+ scale *= pixelRatio;
2484
+ pixelRatio = leaf.app.pixelRatio;
2485
+ }
2486
+ const screenshot = options.screenshot || leaf.isApp;
2487
+ const fill = (isLeafer && screenshot) ? (options.fill === undefined ? leaf.fill : options.fill) : options.fill;
2488
+ const needFill = FileHelper.isOpaqueImage(filename) || fill, matrix = new Matrix();
2489
+ if (screenshot) {
2490
+ renderBounds = screenshot === true ? (isLeafer ? leafer.canvas.bounds : leaf.worldRenderBounds) : screenshot;
2254
2491
  }
2255
- switch (typeof options) {
2256
- case 'object':
2257
- if (options.quality)
2258
- quality = options.quality;
2259
- if (options.blob)
2260
- blob = true;
2261
- break;
2262
- case 'number':
2263
- quality = options;
2264
- break;
2265
- case 'boolean':
2266
- blob = options;
2492
+ else {
2493
+ let relative = options.relative || (isLeafer ? 'inner' : 'local');
2494
+ scaleX = worldTransform.scaleX;
2495
+ scaleY = worldTransform.scaleY;
2496
+ switch (relative) {
2497
+ case 'inner':
2498
+ matrix.set(worldTransform);
2499
+ break;
2500
+ case 'local':
2501
+ matrix.set(worldTransform).divide(leaf.localTransform);
2502
+ scaleX /= leaf.scaleX;
2503
+ scaleY /= leaf.scaleY;
2504
+ break;
2505
+ case 'world':
2506
+ scaleX = 1;
2507
+ scaleY = 1;
2508
+ break;
2509
+ case 'page':
2510
+ relative = leaf.leafer;
2511
+ default:
2512
+ matrix.set(worldTransform).divide(leaf.getTransform(relative));
2513
+ const l = relative.worldTransform;
2514
+ scaleX /= scaleX / l.scaleX;
2515
+ scaleY /= scaleY / l.scaleY;
2516
+ }
2517
+ renderBounds = leaf.getBounds('render', relative);
2267
2518
  }
2268
- let data;
2269
- if (filename.includes('.')) {
2270
- data = yield canvas.saveAs(filename, quality);
2519
+ const { x, y, width, height } = new Bounds(renderBounds).scale(scale);
2520
+ let canvas = Creator.canvas({ width: Math.round(width), height: Math.round(height), pixelRatio, smooth, contextSettings });
2521
+ const renderOptions = { matrix: matrix.scale(1 / scale).invert().translate(-x, -y).withScale(1 / scaleX * scale, 1 / scaleY * scale) };
2522
+ if (slice) {
2523
+ leaf = leafer;
2524
+ renderOptions.bounds = canvas.bounds;
2271
2525
  }
2272
- else if (blob) {
2273
- data = yield canvas.toBlob(filename, quality);
2526
+ canvas.save();
2527
+ if (isFrame && fill !== undefined) {
2528
+ const oldFill = leaf.get('fill');
2529
+ leaf.fill = '';
2530
+ leaf.__render(canvas, renderOptions);
2531
+ leaf.fill = oldFill;
2274
2532
  }
2275
2533
  else {
2276
- data = yield canvas.toDataURL(filename, quality);
2534
+ leaf.__render(canvas, renderOptions);
2277
2535
  }
2278
- success({ data });
2279
- resolve();
2280
- Export.running = false;
2281
- if (unreal)
2282
- canvas.recycle();
2536
+ canvas.restore();
2537
+ if (trim) {
2538
+ trimBounds = getTrimBounds(canvas);
2539
+ const old = canvas, { width, height } = trimBounds;
2540
+ const config = { x: 0, y: 0, width, height, pixelRatio };
2541
+ canvas = Creator.canvas(config);
2542
+ canvas.copyWorld(old, trimBounds, config);
2543
+ }
2544
+ if (needFill)
2545
+ canvas.fillWorld(canvas.bounds, fill || '#FFFFFF', 'destination-over');
2546
+ if (onCanvas)
2547
+ onCanvas(canvas);
2548
+ const data = filename === 'canvas' ? canvas : yield canvas.export(filename, options);
2549
+ over({ data, width: canvas.pixelWidth, height: canvas.pixelHeight, renderBounds, trimBounds });
2283
2550
  }));
2284
2551
  }
2285
2552
  else {
2286
- success({ data: false });
2287
- resolve();
2288
- Export.running = false;
2553
+ over({ data: false });
2289
2554
  }
2290
2555
  }));
2291
2556
  }
@@ -2298,11 +2563,63 @@ function addTask(task) {
2298
2563
  tasker.add(() => __awaiter(this, void 0, void 0, function* () { return yield task(resolve); }), { parallel: false });
2299
2564
  });
2300
2565
  }
2566
+ function checkLazy(leaf) {
2567
+ if (leaf.__.__needComputePaint)
2568
+ leaf.__.__computePaint();
2569
+ if (leaf.isBranch)
2570
+ leaf.children.forEach(child => checkLazy(child));
2571
+ }
2572
+
2573
+ const canvas = LeaferCanvasBase.prototype;
2574
+ const debug = Debug.get('@leafer-ui/export');
2575
+ canvas.export = function (filename, options) {
2576
+ const { quality, blob } = FileHelper.getExportOptions(options);
2577
+ if (filename.includes('.')) {
2578
+ return this.saveAs(filename, quality);
2579
+ }
2580
+ else if (blob) {
2581
+ return this.toBlob(filename, quality);
2582
+ }
2583
+ else {
2584
+ return this.toDataURL(filename, quality);
2585
+ }
2586
+ };
2587
+ canvas.toBlob = function (type, quality) {
2588
+ return new Promise((resolve) => {
2589
+ Platform.origin.canvasToBolb(this.view, type, quality).then((blob) => {
2590
+ resolve(blob);
2591
+ }).catch((e) => {
2592
+ debug.error(e);
2593
+ resolve(null);
2594
+ });
2595
+ });
2596
+ };
2597
+ canvas.toDataURL = function (type, quality) {
2598
+ return Platform.origin.canvasToDataURL(this.view, type, quality);
2599
+ };
2600
+ canvas.saveAs = function (filename, quality) {
2601
+ return new Promise((resolve) => {
2602
+ Platform.origin.canvasSaveAs(this.view, filename, quality).then(() => {
2603
+ resolve(true);
2604
+ }).catch((e) => {
2605
+ debug.error(e);
2606
+ resolve(false);
2607
+ });
2608
+ });
2609
+ };
2301
2610
 
2302
- Object.assign(Paint, UIPaint);
2303
- Object.assign(Effect, UIEffect);
2304
- Object.assign(TextConvert$1, TextConvert);
2305
- Object.assign(ColorConvert$1, ColorConvert);
2306
- Object.assign(Export$2, Export);
2611
+ Object.assign(TextConvert, TextConvertModule);
2612
+ Object.assign(ColorConvert, ColorConvertModule);
2613
+ Object.assign(Paint, PaintModule);
2614
+ Object.assign(PaintImage, PaintImageModule);
2615
+ Object.assign(PaintGradient, PaintGradientModule);
2616
+ Object.assign(Effect, EffectModule);
2617
+ Object.assign(Export, ExportModule);
2618
+
2619
+ Object.assign(Creator, {
2620
+ interaction: (target, canvas, selector, options) => { return new InteractionBase(target, canvas, selector, options); },
2621
+ hitCanvas: (options, manager) => new LeaferCanvas(options, manager),
2622
+ hitCanvasManager: () => new HitCanvasManager()
2623
+ });
2307
2624
 
2308
2625
  export { Layouter, LeaferCanvas, Renderer, Selector, Watcher, useCanvas };