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