@leafer-ui/miniapp 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.
@@ -1,8 +1,220 @@
1
- import { LeafList, DataHelper, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, Bounds, LeafBoundsHelper, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, Platform, AnimateEvent, ResizeEvent, BoundsHelper, Creator, LeaferCanvasBase, canvasPatch, canvasSizeAttrs, InteractionHelper, InteractionBase, LeaferImage, FileHelper, MatrixHelper, ImageEvent, PointHelper, Direction4, TaskProcessor } from '@leafer/core';
1
+ import { LeaferCanvasBase, Platform, canvasPatch, DataHelper, canvasSizeAttrs, ResizeEvent, Creator, LeaferImage, FileHelper, LeafList, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, Bounds, LeafBoundsHelper, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, AnimateEvent, BoundsHelper, Answer, MatrixHelper, AlignHelper, ImageEvent, AroundHelper, PointHelper, Direction4, TwoPointBoundsHelper, TaskProcessor, Matrix } from '@leafer/core';
2
2
  export * from '@leafer/core';
3
3
  export { LeaferImage } from '@leafer/core';
4
- import { ColorConvert as ColorConvert$1, ImageManager as ImageManager$1, Paint, Effect, TextConvert as TextConvert$1, Export as Export$2, Platform as Platform$1 } from '@leafer-ui/core';
4
+ import { InteractionHelper, InteractionBase, HitCanvasManager, Platform as Platform$1 } from '@leafer-ui/core';
5
5
  export * from '@leafer-ui/core';
6
+ import { PaintImage, ColorConvert, PaintGradient, Export, Group, TextConvert, Paint, Effect } from '@leafer-ui/draw';
7
+
8
+ class LeaferCanvas extends LeaferCanvasBase {
9
+ get allowBackgroundColor() { return false; }
10
+ init() {
11
+ let { view } = this.config;
12
+ if (view) {
13
+ if (typeof view === 'string') {
14
+ if (view[0] !== '#')
15
+ view = '#' + view;
16
+ this.viewSelect = Platform.miniapp.select(view);
17
+ }
18
+ else if (view.fields) {
19
+ this.viewSelect = view;
20
+ }
21
+ else {
22
+ this.initView(view);
23
+ }
24
+ if (this.viewSelect)
25
+ Platform.miniapp.getSizeView(this.viewSelect).then(sizeView => {
26
+ this.initView(sizeView);
27
+ });
28
+ }
29
+ else {
30
+ this.initView();
31
+ }
32
+ }
33
+ initView(view) {
34
+ if (!view) {
35
+ view = {};
36
+ this.__createView();
37
+ }
38
+ else {
39
+ this.view = view.view || view;
40
+ }
41
+ this.__createContext();
42
+ const { width, height, pixelRatio } = this.config;
43
+ const size = { width: width || view.width, height: height || view.height, pixelRatio };
44
+ this.resize(size);
45
+ if (this.context.roundRect) {
46
+ this.roundRect = function (x, y, width, height, radius) {
47
+ this.context.roundRect(x, y, width, height, typeof radius === 'number' ? [radius] : radius);
48
+ };
49
+ }
50
+ canvasPatch(this.context.__proto__);
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
+ }
60
+ updateClientBounds(callback) {
61
+ if (this.viewSelect)
62
+ Platform.miniapp.getBounds(this.viewSelect).then(bounds => {
63
+ this.clientBounds = bounds;
64
+ if (callback)
65
+ callback();
66
+ });
67
+ }
68
+ startAutoLayout(_autoBounds, listener) {
69
+ this.resizeListener = listener;
70
+ this.checkSize = this.checkSize.bind(this);
71
+ Platform.miniapp.onWindowResize(this.checkSize);
72
+ }
73
+ checkSize() {
74
+ if (this.viewSelect) {
75
+ setTimeout(() => {
76
+ this.updateClientBounds(() => {
77
+ const { width, height } = this.clientBounds;
78
+ const { pixelRatio } = this;
79
+ const size = { width, height, pixelRatio };
80
+ if (!this.isSameSize(size)) {
81
+ const oldSize = {};
82
+ DataHelper.copyAttrs(oldSize, this, canvasSizeAttrs);
83
+ this.resize(size);
84
+ if (this.width !== undefined)
85
+ this.resizeListener(new ResizeEvent(size, oldSize));
86
+ }
87
+ });
88
+ }, 500);
89
+ }
90
+ }
91
+ stopAutoLayout() {
92
+ this.autoLayout = false;
93
+ this.resizeListener = null;
94
+ Platform.miniapp.offWindowResize(this.checkSize);
95
+ }
96
+ }
97
+
98
+ const { mineType, fileType } = FileHelper;
99
+ Object.assign(Creator, {
100
+ canvas: (options, manager) => new LeaferCanvas(options, manager),
101
+ image: (options) => new LeaferImage(options)
102
+ });
103
+ function useCanvas(_canvasType, app) {
104
+ if (!Platform.origin) {
105
+ Platform.origin = {
106
+ createCanvas: (width, height, _format) => app.createOffscreenCanvas({ type: '2d', width, height }),
107
+ canvasToDataURL: (canvas, type, quality) => canvas.toDataURL(mineType(type), quality),
108
+ canvasToBolb: (canvas, type, quality) => canvas.toBuffer(type, { quality }),
109
+ canvasSaveAs: (canvas, filePath, quality) => {
110
+ let data = canvas.toDataURL(mineType(fileType(filePath)), quality);
111
+ data = data.substring(data.indexOf('64,') + 3);
112
+ return Platform.origin.download(data, filePath);
113
+ },
114
+ download(data, filePath) {
115
+ return new Promise((resolve, reject) => {
116
+ let toAlbum;
117
+ if (!filePath.includes('/')) {
118
+ filePath = `${app.env.USER_DATA_PATH}/` + filePath;
119
+ toAlbum = true;
120
+ }
121
+ const fs = app.getFileSystemManager();
122
+ fs.writeFile({
123
+ filePath,
124
+ data,
125
+ encoding: 'base64',
126
+ success() {
127
+ if (toAlbum) {
128
+ Platform.miniapp.saveToAlbum(filePath).then(() => {
129
+ fs.unlink({ filePath });
130
+ resolve();
131
+ });
132
+ }
133
+ else {
134
+ resolve();
135
+ }
136
+ },
137
+ fail(error) {
138
+ reject(error);
139
+ }
140
+ });
141
+ });
142
+ },
143
+ loadImage(src) {
144
+ return new Promise((resolve, reject) => {
145
+ const img = Platform.canvas.view.createImage();
146
+ img.onload = () => { resolve(img); };
147
+ img.onerror = (error) => { reject(error); };
148
+ img.src = Platform.image.getRealURL(src);
149
+ });
150
+ },
151
+ noRepeat: 'repeat-x'
152
+ };
153
+ Platform.miniapp = {
154
+ select(name) {
155
+ return app.createSelectorQuery().select(name);
156
+ },
157
+ getBounds(select) {
158
+ return new Promise((resolve) => {
159
+ select.boundingClientRect().exec((res) => {
160
+ const rect = res[1];
161
+ resolve({ x: rect.top, y: rect.left, width: rect.width, height: rect.height });
162
+ });
163
+ });
164
+ },
165
+ getSizeView(select) {
166
+ return new Promise((resolve) => {
167
+ select.fields({ node: true, size: true }).exec((res) => {
168
+ const data = res[0];
169
+ resolve({ view: data.node, width: data.width, height: data.height });
170
+ });
171
+ });
172
+ },
173
+ saveToAlbum(path) {
174
+ return new Promise((resolve) => {
175
+ app.getSetting({
176
+ success: (res) => {
177
+ if (res.authSetting['scope.writePhotosAlbum']) {
178
+ app.saveImageToPhotosAlbum({
179
+ filePath: path,
180
+ success() { resolve(true); }
181
+ });
182
+ }
183
+ else {
184
+ app.authorize({
185
+ scope: 'scope.writePhotosAlbum',
186
+ success: () => {
187
+ app.saveImageToPhotosAlbum({
188
+ filePath: path,
189
+ success() { resolve(true); }
190
+ });
191
+ },
192
+ fail: () => { }
193
+ });
194
+ }
195
+ }
196
+ });
197
+ });
198
+ },
199
+ onWindowResize(fun) {
200
+ app.onWindowResize(fun);
201
+ },
202
+ offWindowResize(fun) {
203
+ app.offWindowResize(fun);
204
+ }
205
+ };
206
+ Platform.event = {
207
+ stopDefault(_origin) { },
208
+ stopNow(_origin) { },
209
+ stop(_origin) { }
210
+ };
211
+ Platform.canvas = Creator.canvas();
212
+ Platform.conicGradientSupport = !!Platform.canvas.context.createConicGradient;
213
+ }
214
+ }
215
+ Platform.name = 'miniapp';
216
+ Platform.requestRender = function (render) { Platform.canvas.view.requestAnimationFrame(render); };
217
+ Platform.devicePixelRatio = wx.getSystemInfoSync().pixelRatio;
6
218
 
7
219
  class Watcher {
8
220
  get childrenChanged() { return this.hasAdd || this.hasRemove || this.hasVisible; }
@@ -185,7 +397,7 @@ class LayoutBlockData {
185
397
  }
186
398
 
187
399
  const { updateAllMatrix, updateAllChange } = LeafHelper;
188
- const debug$1 = Debug.get('Layouter');
400
+ const debug$2 = Debug.get('Layouter');
189
401
  class Layouter {
190
402
  constructor(target, userConfig) {
191
403
  this.totalTimes = 0;
@@ -220,7 +432,7 @@ class Layouter {
220
432
  target.emitEvent(new LayoutEvent(LayoutEvent.END, this.layoutedBlocks, this.times));
221
433
  }
222
434
  catch (e) {
223
- debug$1.error(e);
435
+ debug$2.error(e);
224
436
  }
225
437
  this.layoutedBlocks = null;
226
438
  }
@@ -234,9 +446,9 @@ class Layouter {
234
446
  }
235
447
  layoutOnce() {
236
448
  if (this.layouting)
237
- return debug$1.warn('layouting');
449
+ return debug$2.warn('layouting');
238
450
  if (this.times > 3)
239
- return debug$1.warn('layout max times');
451
+ return debug$2.warn('layout max times');
240
452
  this.times++;
241
453
  this.totalTimes++;
242
454
  this.layouting = true;
@@ -302,9 +514,11 @@ class Layouter {
302
514
  updateAllChange(target);
303
515
  }
304
516
  addExtra(leaf) {
305
- const block = this.extraBlock || (this.extraBlock = new LayoutBlockData([]));
306
- block.updatedList.add(leaf);
307
- block.beforeBounds.add(leaf.__world);
517
+ if (!this.__updatedList.has(leaf)) {
518
+ const { updatedList, beforeBounds } = this.extraBlock || (this.extraBlock = new LayoutBlockData([]));
519
+ updatedList.length ? beforeBounds.add(leaf.__world) : beforeBounds.set(leaf.__world);
520
+ updatedList.add(leaf);
521
+ }
308
522
  }
309
523
  createBlock(data) {
310
524
  return new LayoutBlockData(data);
@@ -338,7 +552,7 @@ class Layouter {
338
552
  }
339
553
  }
340
554
 
341
- const debug = Debug.get('Renderer');
555
+ const debug$1 = Debug.get('Renderer');
342
556
  class Renderer {
343
557
  get needFill() { return !!(!this.canvas.allowBackgroundColor && this.config.fill); }
344
558
  constructor(target, canvas, userConfig) {
@@ -376,7 +590,7 @@ class Renderer {
376
590
  const { target } = this;
377
591
  this.times = 0;
378
592
  this.totalBounds = new Bounds();
379
- debug.log(target.innerName, '--->');
593
+ debug$1.log(target.innerName, '--->');
380
594
  try {
381
595
  this.emitRender(RenderEvent.START);
382
596
  this.renderOnce(callback);
@@ -385,9 +599,9 @@ class Renderer {
385
599
  }
386
600
  catch (e) {
387
601
  this.rendering = false;
388
- debug.error(e);
602
+ debug$1.error(e);
389
603
  }
390
- debug.log('-------------|');
604
+ debug$1.log('-------------|');
391
605
  }
392
606
  renderAgain() {
393
607
  if (this.rendering) {
@@ -399,9 +613,9 @@ class Renderer {
399
613
  }
400
614
  renderOnce(callback) {
401
615
  if (this.rendering)
402
- return debug.warn('rendering');
616
+ return debug$1.warn('rendering');
403
617
  if (this.times > 3)
404
- return debug.warn('render max times');
618
+ return debug$1.warn('render max times');
405
619
  this.times++;
406
620
  this.totalTimes++;
407
621
  this.rendering = true;
@@ -414,6 +628,10 @@ class Renderer {
414
628
  }
415
629
  else {
416
630
  this.requestLayout();
631
+ if (this.ignore) {
632
+ this.ignore = this.rendering = false;
633
+ return;
634
+ }
417
635
  this.emitRender(RenderEvent.BEFORE);
418
636
  if (this.config.usePartRender && this.totalTimes > 1) {
419
637
  this.partRender();
@@ -434,7 +652,7 @@ class Renderer {
434
652
  partRender() {
435
653
  const { canvas, updateBlocks: list } = this;
436
654
  if (!list)
437
- return debug.warn('PartRender: need update attr');
655
+ return debug$1.warn('PartRender: need update attr');
438
656
  this.mergeBlocks();
439
657
  list.forEach(block => { if (canvas.bounds.hit(block) && !block.isEmpty())
440
658
  this.clipRender(block); });
@@ -450,7 +668,7 @@ class Renderer {
450
668
  canvas.clear();
451
669
  }
452
670
  else {
453
- bounds.spread(1 + 1 / this.canvas.pixelRatio).ceil();
671
+ bounds.spread(10 + 1 / this.canvas.pixelRatio).ceil();
454
672
  canvas.clearWorld(bounds, true);
455
673
  canvas.clipWorld(bounds, true);
456
674
  }
@@ -503,12 +721,12 @@ class Renderer {
503
721
  const startTime = Date.now();
504
722
  Platform.requestRender(() => {
505
723
  this.FPS = Math.min(60, Math.ceil(1000 / (Date.now() - startTime)));
506
- if (this.changed) {
507
- if (this.running && this.canvas.view)
724
+ if (this.running) {
725
+ this.target.emit(AnimateEvent.FRAME);
726
+ if (this.changed && this.canvas.view)
508
727
  this.render();
728
+ this.target.emit(RenderEvent.NEXT);
509
729
  }
510
- if (this.running)
511
- this.target.emit(AnimateEvent.FRAME);
512
730
  if (this.target)
513
731
  this.__requestRender();
514
732
  });
@@ -521,9 +739,12 @@ class Renderer {
521
739
  const bounds = new Bounds(0, 0, width, height);
522
740
  if (!bounds.includes(this.target.__world) || this.needFill || !e.samePixelRatio) {
523
741
  this.addBlock(this.canvas.bounds);
524
- this.target.forceUpdate('blendMode');
742
+ this.target.forceUpdate('surface');
743
+ return;
525
744
  }
526
745
  }
746
+ this.addBlock(new Bounds(0, 0, 1, 1));
747
+ this.changed = true;
527
748
  }
528
749
  __onLayoutEnd(event) {
529
750
  if (event.data)
@@ -534,7 +755,7 @@ class Renderer {
534
755
  empty = (!leaf.__world.width || !leaf.__world.height);
535
756
  if (empty) {
536
757
  if (!leaf.isLeafer)
537
- debug.tip(leaf.innerName, ': empty');
758
+ debug$1.tip(leaf.innerName, ': empty');
538
759
  empty = (!leaf.isBranch || leaf.isBranchLeaf);
539
760
  }
540
761
  return empty;
@@ -561,23 +782,13 @@ class Renderer {
561
782
  if (this.target) {
562
783
  this.stop();
563
784
  this.__removeListenEvents();
564
- this.target = null;
565
- this.canvas = null;
566
- this.config = null;
785
+ this.target = this.canvas = this.config = null;
567
786
  }
568
787
  }
569
788
  }
570
789
 
571
- var AnswerType;
572
- (function (AnswerType) {
573
- AnswerType[AnswerType["No"] = 0] = "No";
574
- AnswerType[AnswerType["Yes"] = 1] = "Yes";
575
- AnswerType[AnswerType["NoAndSkip"] = 2] = "NoAndSkip";
576
- AnswerType[AnswerType["YesAndSkip"] = 3] = "YesAndSkip";
577
- })(AnswerType || (AnswerType = {}));
578
-
579
790
  const { hitRadiusPoint } = BoundsHelper;
580
- class Pather {
791
+ class Picker {
581
792
  constructor(target, selector) {
582
793
  this.target = target;
583
794
  this.selector = selector;
@@ -589,33 +800,41 @@ class Pather {
589
800
  options = {};
590
801
  const through = options.through || false;
591
802
  const ignoreHittable = options.ignoreHittable || false;
803
+ const target = options.target || this.target;
592
804
  this.exclude = options.exclude || null;
593
805
  this.point = { x: hitPoint.x, y: hitPoint.y, radiusX: hitRadius, radiusY: hitRadius };
594
- this.findList = [];
595
- this.eachFind(this.target.children, this.target.__onlyHitMask);
596
- const list = this.findList;
597
- const leaf = this.getBestMatchLeaf();
806
+ this.findList = new LeafList(options.findList);
807
+ if (!options.findList)
808
+ this.hitBranch(target);
809
+ const { list } = this.findList;
810
+ const leaf = this.getBestMatchLeaf(list, options.bottomList, ignoreHittable);
598
811
  const path = ignoreHittable ? this.getPath(leaf) : this.getHitablePath(leaf);
599
812
  this.clear();
600
- return through ? { path, leaf, throughPath: list.length ? this.getThroughPath(list) : path } : { path, leaf };
813
+ return through ? { path, target: leaf, throughPath: list.length ? this.getThroughPath(list) : path } : { path, target: leaf };
601
814
  }
602
- getBestMatchLeaf() {
603
- const { findList: targets } = this;
604
- if (targets.length > 1) {
815
+ getBestMatchLeaf(list, bottomList, ignoreHittable) {
816
+ if (list.length) {
605
817
  let find;
606
- this.findList = [];
818
+ this.findList = new LeafList();
607
819
  const { x, y } = this.point;
608
820
  const point = { x, y, radiusX: 0, radiusY: 0 };
609
- for (let i = 0, len = targets.length; i < len; i++) {
610
- find = targets[i];
611
- if (LeafHelper.worldHittable(find)) {
821
+ for (let i = 0, len = list.length; i < len; i++) {
822
+ find = list[i];
823
+ if (ignoreHittable || LeafHelper.worldHittable(find)) {
612
824
  this.hitChild(find, point);
613
825
  if (this.findList.length)
614
- return this.findList[0];
826
+ return this.findList.list[0];
615
827
  }
616
828
  }
617
829
  }
618
- return targets[0];
830
+ if (bottomList) {
831
+ for (let i = 0, len = bottomList.length; i < len; i++) {
832
+ this.hitChild(bottomList[i].target, this.point, bottomList[i].proxy);
833
+ if (this.findList.length)
834
+ return this.findList.list[0];
835
+ }
836
+ }
837
+ return list[0];
619
838
  }
620
839
  getPath(leaf) {
621
840
  const path = new LeafList();
@@ -627,7 +846,7 @@ class Pather {
627
846
  return path;
628
847
  }
629
848
  getHitablePath(leaf) {
630
- const path = this.getPath(leaf);
849
+ const path = this.getPath(leaf && leaf.hittable ? leaf : null);
631
850
  let item, hittablePath = new LeafList();
632
851
  for (let i = path.list.length - 1; i > -1; i--) {
633
852
  item = path.list[i];
@@ -657,12 +876,15 @@ class Pather {
657
876
  }
658
877
  return throughPath;
659
878
  }
879
+ hitBranch(branch) {
880
+ this.eachFind(branch.children, branch.__onlyHitMask);
881
+ }
660
882
  eachFind(children, hitMask) {
661
883
  let child, hit;
662
884
  const { point } = this, len = children.length;
663
885
  for (let i = len - 1; i > -1; i--) {
664
886
  child = children[i];
665
- if (!child.__.visible || (hitMask && !child.__.isMask))
887
+ if (!child.__.visible || (hitMask && !child.__.mask))
666
888
  continue;
667
889
  hit = child.__.hitRadius ? true : hitRadiusPoint(child.__world, point);
668
890
  if (child.isBranch) {
@@ -678,11 +900,15 @@ class Pather {
678
900
  }
679
901
  }
680
902
  }
681
- hitChild(child, point) {
903
+ hitChild(child, point, proxy) {
682
904
  if (this.exclude && this.exclude.has(child))
683
905
  return;
684
- if (child.__hitWorld(point))
685
- this.findList.push(child);
906
+ if (child.__hitWorld(point)) {
907
+ const { parent } = child;
908
+ if (parent && parent.__hasMask && !child.__.mask && !parent.children.some(item => item.__.mask && item.__hitWorld(point)))
909
+ return;
910
+ this.findList.add(proxy || child);
911
+ }
686
912
  }
687
913
  clear() {
688
914
  this.point = null;
@@ -694,7 +920,8 @@ class Pather {
694
920
  }
695
921
  }
696
922
 
697
- const { Yes, NoAndSkip, YesAndSkip } = AnswerType;
923
+ const { Yes, NoAndSkip, YesAndSkip } = Answer;
924
+ const idCondition = {}, classNameCondition = {}, tagCondition = {};
698
925
  class Selector {
699
926
  constructor(target, userConfig) {
700
927
  this.config = {};
@@ -704,12 +931,13 @@ class Selector {
704
931
  id: (leaf, name) => leaf.id === name ? (this.idMap[name] = leaf, 1) : 0,
705
932
  innerId: (leaf, innerId) => leaf.innerId === innerId ? (this.innerIdMap[innerId] = leaf, 1) : 0,
706
933
  className: (leaf, name) => leaf.className === name ? 1 : 0,
707
- tag: (leaf, name) => leaf.__tag === name ? 1 : 0
934
+ tag: (leaf, name) => leaf.__tag === name ? 1 : 0,
935
+ tags: (leaf, nameMap) => nameMap[leaf.__tag] ? 1 : 0
708
936
  };
709
937
  this.target = target;
710
938
  if (userConfig)
711
939
  this.config = DataHelper.default(userConfig, this.config);
712
- this.pather = new Pather(target, this);
940
+ this.picker = new Picker(target, this);
713
941
  this.__listenEvents();
714
942
  }
715
943
  getBy(condition, branch, one, options) {
@@ -720,12 +948,25 @@ class Selector {
720
948
  case 'string':
721
949
  switch (condition[0]) {
722
950
  case '#':
723
- const leaf = this.getById(condition.substring(1), branch);
724
- return one ? leaf : (leaf ? [leaf] : []);
951
+ idCondition.id = condition.substring(1), condition = idCondition;
952
+ break;
725
953
  case '.':
726
- return this.getByMethod(this.methods.className, branch, one, condition.substring(1));
954
+ classNameCondition.className = condition.substring(1), condition = classNameCondition;
955
+ break;
727
956
  default:
728
- return this.getByMethod(this.methods.tag, branch, one, condition);
957
+ tagCondition.tag = condition, condition = tagCondition;
958
+ }
959
+ case 'object':
960
+ if (condition.id !== undefined) {
961
+ const leaf = this.getById(condition.id, branch);
962
+ return one ? leaf : (leaf ? [leaf] : []);
963
+ }
964
+ else if (condition.tag) {
965
+ const { tag } = condition, isArray = tag instanceof Array;
966
+ return this.getByMethod(isArray ? this.methods.tags : this.methods.tag, branch, one, isArray ? DataHelper.toMap(tag) : tag);
967
+ }
968
+ else {
969
+ return this.getByMethod(this.methods.className, branch, one, condition.className);
729
970
  }
730
971
  case 'function':
731
972
  return this.getByMethod(condition, branch, one, options);
@@ -734,7 +975,7 @@ class Selector {
734
975
  getByPoint(hitPoint, hitRadius, options) {
735
976
  if (Platform.name === 'node')
736
977
  this.target.emit(LayoutEvent.CHECK_UPDATE);
737
- return this.pather.getByPoint(hitPoint, hitRadius, options);
978
+ return this.picker.getByPoint(hitPoint, hitRadius, options);
738
979
  }
739
980
  getByInnerId(innerId, branch) {
740
981
  const cache = this.innerIdMap[innerId];
@@ -810,7 +1051,7 @@ class Selector {
810
1051
  destroy() {
811
1052
  if (this.__eventIds.length) {
812
1053
  this.__removeListenEvents();
813
- this.pather.destroy();
1054
+ this.picker.destroy();
814
1055
  this.findLeaf = null;
815
1056
  this.innerIdMap = {};
816
1057
  this.idMap = {};
@@ -826,104 +1067,14 @@ Object.assign(Creator, {
826
1067
  });
827
1068
  Platform.layout = Layouter.fullLayout;
828
1069
 
829
- class LeaferCanvas extends LeaferCanvasBase {
830
- get allowBackgroundColor() { return false; }
831
- init() {
832
- let { view } = this.config;
833
- if (view) {
834
- if (typeof view === 'string') {
835
- if (view[0] !== '#')
836
- view = '#' + view;
837
- this.viewSelect = Platform.miniapp.select(view);
838
- }
839
- else if (view.fields) {
840
- this.viewSelect = view;
841
- }
842
- else {
843
- this.initView(view);
844
- }
845
- if (this.viewSelect)
846
- Platform.miniapp.getSizeView(this.viewSelect).then(sizeView => {
847
- this.initView(sizeView);
848
- });
849
- }
850
- else {
851
- this.initView();
852
- }
853
- }
854
- initView(view) {
855
- if (!view) {
856
- view = {};
857
- this.__createView();
858
- }
859
- else {
860
- this.view = view.view || view;
861
- }
862
- this.__createContext();
863
- const { width, height, pixelRatio } = this.config;
864
- const size = { width: width || view.width, height: height || view.height, pixelRatio };
865
- this.resize(size);
866
- if (this.context.roundRect) {
867
- this.roundRect = function (x, y, width, height, radius) {
868
- this.context.roundRect(x, y, width, height, typeof radius === 'number' ? [radius] : radius);
869
- };
870
- }
871
- canvasPatch(this.context.__proto__);
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
- }
881
- updateClientBounds(callback) {
882
- if (this.viewSelect)
883
- Platform.miniapp.getBounds(this.viewSelect).then(bounds => {
884
- this.clientBounds = bounds;
885
- if (callback)
886
- callback();
887
- });
888
- }
889
- startAutoLayout(_autoBounds, listener) {
890
- this.resizeListener = listener;
891
- this.checkSize = this.checkSize.bind(this);
892
- Platform.miniapp.onWindowResize(this.checkSize);
893
- }
894
- checkSize() {
895
- if (this.viewSelect) {
896
- setTimeout(() => {
897
- this.updateClientBounds(() => {
898
- const { width, height } = this.clientBounds;
899
- const { pixelRatio } = this;
900
- const size = { width, height, pixelRatio };
901
- if (!this.isSameSize(size)) {
902
- const oldSize = {};
903
- DataHelper.copyAttrs(oldSize, this, canvasSizeAttrs);
904
- this.resize(size);
905
- if (this.width !== undefined)
906
- this.resizeListener(new ResizeEvent(size, oldSize));
907
- }
908
- });
909
- }, 500);
910
- }
911
- }
912
- stopAutoLayout() {
913
- this.autoLayout = false;
914
- this.resizeListener = null;
915
- Platform.miniapp.offWindowResize(this.checkSize);
916
- }
917
- }
918
-
919
- const PointerEventHelper = {
920
- convertTouch(e, local) {
921
- const touch = PointerEventHelper.getTouch(e);
922
- const base = InteractionHelper.getBase(e);
923
- return Object.assign(Object.assign({}, base), { x: local.x, y: local.y, width: 1, height: 1, pointerType: 'touch', pressure: touch.force || 1 });
924
- },
925
- getTouch(e) {
926
- return e.touches[0] || e.changedTouches[0];
1070
+ const PointerEventHelper = {
1071
+ convertTouch(e, local) {
1072
+ const touch = PointerEventHelper.getTouch(e);
1073
+ const base = InteractionHelper.getBase(e);
1074
+ return Object.assign(Object.assign({}, base), { x: local.x, y: local.y, width: 1, height: 1, pointerType: 'touch', pressure: touch.force || 1 });
1075
+ },
1076
+ getTouch(e) {
1077
+ return e.touches[0] || e.changedTouches[0];
927
1078
  }
928
1079
  };
929
1080
 
@@ -948,15 +1099,12 @@ class Interaction extends InteractionBase {
948
1099
  this.onTouchCancel();
949
1100
  }
950
1101
  }
951
- getLocal(p, updateClient) {
952
- if (updateClient)
953
- this.canvas.updateClientBounds();
954
- if (p.x !== undefined) {
955
- return { x: p.x, y: p.y };
1102
+ getLocal(clientPoint, updateClient) {
1103
+ if (clientPoint.x !== undefined) {
1104
+ return { x: clientPoint.x, y: clientPoint.y };
956
1105
  }
957
1106
  else {
958
- const { clientBounds } = this.canvas;
959
- return { x: p.clientX - clientBounds.x, y: p.clientY - clientBounds.y };
1107
+ return super.getLocal(clientPoint, updateClient);
960
1108
  }
961
1109
  }
962
1110
  getTouches(touches) {
@@ -1024,209 +1172,428 @@ class Interaction extends InteractionBase {
1024
1172
  }
1025
1173
  }
1026
1174
 
1027
- const { mineType, fileType } = FileHelper;
1028
- Object.assign(Creator, {
1029
- canvas: (options, manager) => new LeaferCanvas(options, manager),
1030
- image: (options) => new LeaferImage(options),
1031
- hitCanvas: (options, manager) => new LeaferCanvas(options, manager),
1032
- interaction: (target, canvas, selector, options) => { return new Interaction(target, canvas, selector, options); }
1033
- });
1034
- function useCanvas(_canvasType, app) {
1035
- if (!Platform.origin) {
1036
- Platform.origin = {
1037
- createCanvas: (width, height, _format) => app.createOffscreenCanvas({ type: '2d', width, height }),
1038
- canvasToDataURL: (canvas, type, quality) => canvas.toDataURL(mineType(type), quality),
1039
- canvasToBolb: (canvas, type, quality) => canvas.toBuffer(type, { quality }),
1040
- canvasSaveAs: (canvas, filePath, quality) => {
1041
- return new Promise((resolve, reject) => {
1042
- let data = canvas.toDataURL(mineType(fileType(filePath)), quality);
1043
- data = data.substring(data.indexOf('64,') + 3);
1044
- let toAlbum;
1045
- if (!filePath.includes('/')) {
1046
- filePath = `${app.env.USER_DATA_PATH}/` + filePath;
1047
- toAlbum = true;
1048
- }
1049
- const fs = app.getFileSystemManager();
1050
- fs.writeFile({
1051
- filePath,
1052
- data,
1053
- encoding: 'base64',
1054
- success() {
1055
- if (toAlbum) {
1056
- Platform.miniapp.saveToAlbum(filePath).then(() => {
1057
- fs.unlink({ filePath });
1058
- });
1059
- }
1060
- resolve();
1061
- },
1062
- fail(error) {
1063
- reject(error);
1064
- }
1065
- });
1066
- });
1067
- },
1068
- loadImage(url) {
1069
- return new Promise((resolve, reject) => {
1070
- const img = Platform.canvas.view.createImage();
1071
- img.onload = () => { resolve(img); };
1072
- img.onerror = (error) => { reject(error); };
1073
- img.src = url;
1074
- });
1075
- },
1076
- noRepeat: 'repeat-x'
1077
- };
1078
- Platform.miniapp = {
1079
- select(name) {
1080
- return app.createSelectorQuery().select(name);
1081
- },
1082
- getBounds(select) {
1083
- return new Promise((resolve) => {
1084
- select.boundingClientRect().exec((res) => {
1085
- const rect = res[1];
1086
- resolve({ x: rect.top, y: rect.left, width: rect.width, height: rect.height });
1087
- });
1088
- });
1089
- },
1090
- getSizeView(select) {
1091
- return new Promise((resolve) => {
1092
- select.fields({ node: true, size: true }).exec((res) => {
1093
- const data = res[0];
1094
- resolve({ view: data.node, width: data.width, height: data.height });
1095
- });
1096
- });
1097
- },
1098
- saveToAlbum(path) {
1099
- return new Promise((resolve) => {
1100
- app.getSetting({
1101
- success: (res) => {
1102
- if (res.authSetting['scope.writePhotosAlbum']) {
1103
- app.saveImageToPhotosAlbum({
1104
- filePath: path,
1105
- success() { resolve(true); }
1106
- });
1107
- }
1108
- else {
1109
- app.authorize({
1110
- scope: 'scope.writePhotosAlbum',
1111
- success: () => {
1112
- app.saveImageToPhotosAlbum({
1113
- filePath: path,
1114
- success() { resolve(true); }
1115
- });
1116
- },
1117
- fail: () => { }
1118
- });
1119
- }
1120
- }
1121
- });
1122
- });
1123
- },
1124
- onWindowResize(fun) {
1125
- app.onWindowResize(fun);
1126
- },
1127
- offWindowResize(fun) {
1128
- app.offWindowResize(fun);
1175
+ function fillText(ui, canvas) {
1176
+ let row;
1177
+ const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
1178
+ for (let i = 0, len = rows.length; i < len; i++) {
1179
+ row = rows[i];
1180
+ if (row.text) {
1181
+ canvas.fillText(row.text, row.x, row.y);
1182
+ }
1183
+ else if (row.data) {
1184
+ row.data.forEach(charData => {
1185
+ canvas.fillText(charData.char, charData.x, row.y);
1186
+ });
1187
+ }
1188
+ if (decorationY)
1189
+ canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight);
1190
+ }
1191
+ }
1192
+
1193
+ function fill(fill, ui, canvas) {
1194
+ canvas.fillStyle = fill;
1195
+ ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
1196
+ }
1197
+ function fills(fills, ui, canvas) {
1198
+ let item;
1199
+ const { windingRule, __font } = ui.__;
1200
+ for (let i = 0, len = fills.length; i < len; i++) {
1201
+ item = fills[i];
1202
+ if (item.image && PaintImage.checkImage(ui, canvas, item, !__font))
1203
+ continue;
1204
+ if (item.style) {
1205
+ canvas.fillStyle = item.style;
1206
+ if (item.transform) {
1207
+ canvas.save();
1208
+ canvas.transform(item.transform);
1209
+ if (item.blendMode)
1210
+ canvas.blendMode = item.blendMode;
1211
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1212
+ canvas.restore();
1129
1213
  }
1130
- };
1131
- Platform.event = {
1132
- stopDefault(_origin) { },
1133
- stopNow(_origin) { },
1134
- stop(_origin) { }
1135
- };
1136
- Platform.canvas = Creator.canvas();
1137
- Platform.conicGradientSupport = !!Platform.canvas.context.createConicGradient;
1214
+ else {
1215
+ if (item.blendMode) {
1216
+ canvas.saveBlendMode(item.blendMode);
1217
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1218
+ canvas.restoreBlendMode();
1219
+ }
1220
+ else {
1221
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1222
+ }
1223
+ }
1224
+ }
1138
1225
  }
1139
1226
  }
1140
- Platform.name = 'miniapp';
1141
- Platform.requestRender = function (render) { Platform.canvas.view.requestAnimationFrame(render); };
1142
- Platform.devicePixelRatio = wx.getSystemInfoSync().pixelRatio;
1143
1227
 
1144
- const { get: get$4, rotateOfOuter: rotateOfOuter$2, translate: translate$1, scaleOfOuter: scaleOfOuter$2, scale: scaleHelper, rotate } = MatrixHelper;
1145
- function fillOrFitMode(data, mode, box, width, height, rotation) {
1146
- const transform = get$4();
1147
- const swap = rotation && rotation !== 180;
1148
- const sw = box.width / (swap ? height : width);
1149
- const sh = box.height / (swap ? width : height);
1150
- const scale = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
1151
- const x = box.x + (box.width - width * scale) / 2;
1152
- const y = box.y + (box.height - height * scale) / 2;
1153
- translate$1(transform, x, y);
1154
- scaleHelper(transform, scale);
1228
+ function strokeText(stroke, ui, canvas) {
1229
+ const { strokeAlign } = ui.__;
1230
+ const isStrokes = typeof stroke !== 'string';
1231
+ switch (strokeAlign) {
1232
+ case 'center':
1233
+ canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
1234
+ isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
1235
+ break;
1236
+ case 'inside':
1237
+ drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
1238
+ break;
1239
+ case 'outside':
1240
+ drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
1241
+ break;
1242
+ }
1243
+ }
1244
+ function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
1245
+ const { __strokeWidth, __font } = ui.__;
1246
+ const out = canvas.getSameCanvas(true, true);
1247
+ out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__);
1248
+ out.font = __font;
1249
+ isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
1250
+ out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
1251
+ fillText(ui, out);
1252
+ out.blendMode = 'normal';
1253
+ if (ui.__worldFlipped) {
1254
+ canvas.copyWorldByReset(out, ui.__nowWorld);
1255
+ }
1256
+ else {
1257
+ canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
1258
+ }
1259
+ out.recycle(ui.__nowWorld);
1260
+ }
1261
+ function drawTextStroke(ui, canvas) {
1262
+ let row;
1263
+ const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
1264
+ for (let i = 0, len = rows.length; i < len; i++) {
1265
+ row = rows[i];
1266
+ if (row.text) {
1267
+ canvas.strokeText(row.text, row.x, row.y);
1268
+ }
1269
+ else if (row.data) {
1270
+ row.data.forEach(charData => {
1271
+ canvas.strokeText(charData.char, charData.x, row.y);
1272
+ });
1273
+ }
1274
+ if (decorationY)
1275
+ canvas.strokeRect(row.x, row.y + decorationY, row.width, decorationHeight);
1276
+ }
1277
+ }
1278
+ function drawStrokesStyle(strokes, isText, ui, canvas) {
1279
+ let item;
1280
+ for (let i = 0, len = strokes.length; i < len; i++) {
1281
+ item = strokes[i];
1282
+ if (item.image && PaintImage.checkImage(ui, canvas, item, false))
1283
+ continue;
1284
+ if (item.style) {
1285
+ canvas.strokeStyle = item.style;
1286
+ if (item.blendMode) {
1287
+ canvas.saveBlendMode(item.blendMode);
1288
+ isText ? drawTextStroke(ui, canvas) : canvas.stroke();
1289
+ canvas.restoreBlendMode();
1290
+ }
1291
+ else {
1292
+ isText ? drawTextStroke(ui, canvas) : canvas.stroke();
1293
+ }
1294
+ }
1295
+ }
1296
+ }
1297
+
1298
+ function stroke(stroke, ui, canvas) {
1299
+ const options = ui.__;
1300
+ const { __strokeWidth, strokeAlign, __font } = options;
1301
+ if (!__strokeWidth)
1302
+ return;
1303
+ if (__font) {
1304
+ strokeText(stroke, ui, canvas);
1305
+ }
1306
+ else {
1307
+ switch (strokeAlign) {
1308
+ case 'center':
1309
+ canvas.setStroke(stroke, __strokeWidth, options);
1310
+ canvas.stroke();
1311
+ break;
1312
+ case 'inside':
1313
+ canvas.save();
1314
+ canvas.setStroke(stroke, __strokeWidth * 2, options);
1315
+ options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1316
+ canvas.stroke();
1317
+ canvas.restore();
1318
+ break;
1319
+ case 'outside':
1320
+ const out = canvas.getSameCanvas(true, true);
1321
+ out.setStroke(stroke, __strokeWidth * 2, options);
1322
+ ui.__drawRenderPath(out);
1323
+ out.stroke();
1324
+ options.windingRule ? out.clip(options.windingRule) : out.clip();
1325
+ out.clearWorld(ui.__layout.renderBounds);
1326
+ if (ui.__worldFlipped) {
1327
+ canvas.copyWorldByReset(out, ui.__nowWorld);
1328
+ }
1329
+ else {
1330
+ canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
1331
+ }
1332
+ out.recycle(ui.__nowWorld);
1333
+ break;
1334
+ }
1335
+ }
1336
+ }
1337
+ function strokes(strokes, ui, canvas) {
1338
+ const options = ui.__;
1339
+ const { __strokeWidth, strokeAlign, __font } = options;
1340
+ if (!__strokeWidth)
1341
+ return;
1342
+ if (__font) {
1343
+ strokeText(strokes, ui, canvas);
1344
+ }
1345
+ else {
1346
+ switch (strokeAlign) {
1347
+ case 'center':
1348
+ canvas.setStroke(undefined, __strokeWidth, options);
1349
+ drawStrokesStyle(strokes, false, ui, canvas);
1350
+ break;
1351
+ case 'inside':
1352
+ canvas.save();
1353
+ canvas.setStroke(undefined, __strokeWidth * 2, options);
1354
+ options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1355
+ drawStrokesStyle(strokes, false, ui, canvas);
1356
+ canvas.restore();
1357
+ break;
1358
+ case 'outside':
1359
+ const { renderBounds } = ui.__layout;
1360
+ const out = canvas.getSameCanvas(true, true);
1361
+ ui.__drawRenderPath(out);
1362
+ out.setStroke(undefined, __strokeWidth * 2, options);
1363
+ drawStrokesStyle(strokes, false, ui, out);
1364
+ options.windingRule ? out.clip(options.windingRule) : out.clip();
1365
+ out.clearWorld(renderBounds);
1366
+ if (ui.__worldFlipped) {
1367
+ canvas.copyWorldByReset(out, ui.__nowWorld);
1368
+ }
1369
+ else {
1370
+ canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
1371
+ }
1372
+ out.recycle(ui.__nowWorld);
1373
+ break;
1374
+ }
1375
+ }
1376
+ }
1377
+
1378
+ const { getSpread, getOuterOf, getByMove, getIntersectData } = BoundsHelper;
1379
+ function shape(ui, current, options) {
1380
+ const canvas = current.getSameCanvas();
1381
+ const nowWorld = ui.__nowWorld;
1382
+ let bounds, fitMatrix, shapeBounds, worldCanvas;
1383
+ let { scaleX, scaleY } = nowWorld;
1384
+ if (scaleX < 0)
1385
+ scaleX = -scaleX;
1386
+ if (scaleY < 0)
1387
+ scaleY = -scaleY;
1388
+ if (current.bounds.includes(nowWorld)) {
1389
+ worldCanvas = canvas;
1390
+ bounds = shapeBounds = nowWorld;
1391
+ }
1392
+ else {
1393
+ const { renderShapeSpread: spread } = ui.__layout;
1394
+ const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, scaleX === scaleY ? spread * scaleX : [spread * scaleY, spread * scaleX]) : current.bounds, nowWorld);
1395
+ fitMatrix = current.bounds.getFitMatrix(worldClipBounds);
1396
+ let { a: fitScaleX, d: fitScaleY } = fitMatrix;
1397
+ if (fitMatrix.a < 1) {
1398
+ worldCanvas = current.getSameCanvas();
1399
+ ui.__renderShape(worldCanvas, options);
1400
+ scaleX *= fitScaleX;
1401
+ scaleY *= fitScaleY;
1402
+ }
1403
+ shapeBounds = getOuterOf(nowWorld, fitMatrix);
1404
+ bounds = getByMove(shapeBounds, -fitMatrix.e, -fitMatrix.f);
1405
+ if (options.matrix) {
1406
+ const { matrix } = options;
1407
+ fitMatrix.multiply(matrix);
1408
+ fitScaleX *= matrix.scaleX;
1409
+ fitScaleY *= matrix.scaleY;
1410
+ }
1411
+ options = Object.assign(Object.assign({}, options), { matrix: fitMatrix.withScale(fitScaleX, fitScaleY) });
1412
+ }
1413
+ ui.__renderShape(canvas, options);
1414
+ return {
1415
+ canvas, matrix: fitMatrix, bounds,
1416
+ worldCanvas, shapeBounds, scaleX, scaleY
1417
+ };
1418
+ }
1419
+
1420
+ let recycleMap;
1421
+ function compute(attrName, ui) {
1422
+ const data = ui.__, leafPaints = [];
1423
+ let paints = data.__input[attrName], hasOpacityPixel;
1424
+ if (!(paints instanceof Array))
1425
+ paints = [paints];
1426
+ recycleMap = PaintImage.recycleImage(attrName, data);
1427
+ for (let i = 0, len = paints.length, item; i < len; i++) {
1428
+ item = getLeafPaint(attrName, paints[i], ui);
1429
+ if (item)
1430
+ leafPaints.push(item);
1431
+ }
1432
+ data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
1433
+ if (leafPaints.length && leafPaints[0].image)
1434
+ hasOpacityPixel = leafPaints[0].image.hasOpacityPixel;
1435
+ if (attrName === 'fill') {
1436
+ data.__pixelFill = hasOpacityPixel;
1437
+ }
1438
+ else {
1439
+ data.__pixelStroke = hasOpacityPixel;
1440
+ }
1441
+ }
1442
+ function getLeafPaint(attrName, paint, ui) {
1443
+ if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
1444
+ return undefined;
1445
+ const { boxBounds } = ui.__layout;
1446
+ switch (paint.type) {
1447
+ case 'solid':
1448
+ let { type, blendMode, color, opacity } = paint;
1449
+ return { type, blendMode, style: ColorConvert.string(color, opacity) };
1450
+ case 'image':
1451
+ return PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1452
+ case 'linear':
1453
+ return PaintGradient.linearGradient(paint, boxBounds);
1454
+ case 'radial':
1455
+ return PaintGradient.radialGradient(paint, boxBounds);
1456
+ case 'angular':
1457
+ return PaintGradient.conicGradient(paint, boxBounds);
1458
+ default:
1459
+ return paint.r !== undefined ? { type: 'solid', style: ColorConvert.string(paint) } : undefined;
1460
+ }
1461
+ }
1462
+
1463
+ const PaintModule = {
1464
+ compute,
1465
+ fill,
1466
+ fills,
1467
+ fillText,
1468
+ stroke,
1469
+ strokes,
1470
+ strokeText,
1471
+ drawTextStroke,
1472
+ shape
1473
+ };
1474
+
1475
+ let origin = {};
1476
+ const { get: get$3, rotateOfOuter: rotateOfOuter$1, translate: translate$1, scaleOfOuter: scaleOfOuter$1, scale: scaleHelper, rotate } = MatrixHelper;
1477
+ function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1478
+ const transform = get$3();
1479
+ translate$1(transform, box.x + x, box.y + y);
1480
+ scaleHelper(transform, scaleX, scaleY);
1155
1481
  if (rotation)
1156
- rotateOfOuter$2(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
1157
- data.scaleX = data.scaleY = scale;
1482
+ rotateOfOuter$1(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
1158
1483
  data.transform = transform;
1159
1484
  }
1160
- function clipMode(data, box, offset, scale, rotation) {
1161
- const transform = get$4();
1162
- translate$1(transform, box.x, box.y);
1163
- if (offset)
1164
- translate$1(transform, offset.x, offset.y);
1165
- if (scale) {
1166
- typeof scale === 'number' ? scaleHelper(transform, scale) : scaleHelper(transform, scale.x, scale.y);
1167
- data.scaleX = transform.a;
1168
- data.scaleY = transform.d;
1169
- }
1485
+ function clipMode(data, box, x, y, scaleX, scaleY, rotation) {
1486
+ const transform = get$3();
1487
+ translate$1(transform, box.x + x, box.y + y);
1488
+ if (scaleX)
1489
+ scaleHelper(transform, scaleX, scaleY);
1170
1490
  if (rotation)
1171
1491
  rotate(transform, rotation);
1172
1492
  data.transform = transform;
1173
1493
  }
1174
- function repeatMode(data, box, width, height, scale, rotation) {
1175
- const transform = get$4();
1494
+ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align) {
1495
+ const transform = get$3();
1176
1496
  if (rotation) {
1177
- rotate(transform, rotation);
1178
- switch (rotation) {
1179
- case 90:
1180
- translate$1(transform, height, 0);
1181
- break;
1182
- case 180:
1183
- translate$1(transform, width, height);
1184
- break;
1185
- case 270:
1186
- translate$1(transform, 0, width);
1187
- break;
1497
+ if (align === 'center') {
1498
+ rotateOfOuter$1(transform, { x: width / 2, y: height / 2 }, rotation);
1499
+ }
1500
+ else {
1501
+ rotate(transform, rotation);
1502
+ switch (rotation) {
1503
+ case 90:
1504
+ translate$1(transform, height, 0);
1505
+ break;
1506
+ case 180:
1507
+ translate$1(transform, width, height);
1508
+ break;
1509
+ case 270:
1510
+ translate$1(transform, 0, width);
1511
+ break;
1512
+ }
1188
1513
  }
1189
1514
  }
1190
- translate$1(transform, box.x, box.y);
1191
- if (scale) {
1192
- scaleOfOuter$2(transform, box, scale);
1193
- data.scaleX = data.scaleY = scale;
1194
- }
1515
+ origin.x = box.x + x;
1516
+ origin.y = box.y + y;
1517
+ translate$1(transform, origin.x, origin.y);
1518
+ if (scaleX)
1519
+ scaleOfOuter$1(transform, origin, scaleX, scaleY);
1195
1520
  data.transform = transform;
1196
1521
  }
1197
1522
 
1198
- const { get: get$3, translate } = MatrixHelper;
1523
+ const { get: get$2, translate } = MatrixHelper;
1524
+ const tempBox = new Bounds();
1525
+ const tempPoint = {};
1199
1526
  function createData(leafPaint, image, paint, box) {
1200
- let { width, height } = image;
1201
- const { opacity, mode, offset, scale, rotation, blendMode, repeat } = paint;
1202
- const sameBox = box.width === width && box.height === height;
1527
+ const { blendMode } = paint;
1203
1528
  if (blendMode)
1204
1529
  leafPaint.blendMode = blendMode;
1205
- const data = leafPaint.data = { mode };
1530
+ leafPaint.data = getPatternData(paint, box, image);
1531
+ }
1532
+ function getPatternData(paint, box, image) {
1533
+ let { width, height } = image;
1534
+ if (paint.padding)
1535
+ box = tempBox.set(box).shrink(paint.padding);
1536
+ const { opacity, mode, align, offset, scale, size, rotation, repeat } = paint;
1537
+ const sameBox = box.width === width && box.height === height;
1538
+ const data = { mode };
1539
+ const swapSize = align !== 'center' && (rotation || 0) % 180 === 90;
1540
+ const swapWidth = swapSize ? height : width, swapHeight = swapSize ? width : height;
1541
+ let x = 0, y = 0, scaleX, scaleY;
1542
+ if (!mode || mode === 'cover' || mode === 'fit') {
1543
+ if (!sameBox || rotation) {
1544
+ const sw = box.width / swapWidth, sh = box.height / swapHeight;
1545
+ scaleX = scaleY = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
1546
+ x += (box.width - width * scaleX) / 2, y += (box.height - height * scaleY) / 2;
1547
+ }
1548
+ }
1549
+ else if (size) {
1550
+ scaleX = (typeof size === 'number' ? size : size.width) / width;
1551
+ scaleY = (typeof size === 'number' ? size : size.height) / height;
1552
+ }
1553
+ else if (scale) {
1554
+ scaleX = typeof scale === 'number' ? scale : scale.x;
1555
+ scaleY = typeof scale === 'number' ? scale : scale.y;
1556
+ }
1557
+ if (align) {
1558
+ const imageBounds = { x, y, width: swapWidth, height: swapHeight };
1559
+ if (scaleX)
1560
+ imageBounds.width *= scaleX, imageBounds.height *= scaleY;
1561
+ AlignHelper.toPoint(align, imageBounds, box, tempPoint, true);
1562
+ x += tempPoint.x, y += tempPoint.y;
1563
+ }
1564
+ if (offset)
1565
+ x += offset.x, y += offset.y;
1206
1566
  switch (mode) {
1207
1567
  case 'strench':
1208
1568
  if (!sameBox)
1209
1569
  width = box.width, height = box.height;
1210
- if (box.x || box.y) {
1211
- data.transform = get$3();
1212
- translate(data.transform, box.x, box.y);
1213
- }
1214
1570
  break;
1571
+ case 'normal':
1215
1572
  case 'clip':
1216
- if (offset || scale || rotation)
1217
- clipMode(data, box, offset, scale, rotation);
1573
+ if (x || y || scaleX || rotation)
1574
+ clipMode(data, box, x, y, scaleX, scaleY, rotation);
1218
1575
  break;
1219
1576
  case 'repeat':
1220
- if (!sameBox || scale || rotation)
1221
- repeatMode(data, box, width, height, scale, rotation);
1577
+ if (!sameBox || scaleX || rotation)
1578
+ repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align);
1222
1579
  if (!repeat)
1223
1580
  data.repeat = 'repeat';
1224
1581
  break;
1225
1582
  case 'fit':
1226
1583
  case 'cover':
1227
1584
  default:
1228
- if (!sameBox || rotation)
1229
- fillOrFitMode(data, mode, box, width, height, rotation);
1585
+ if (scaleX)
1586
+ fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation);
1587
+ }
1588
+ if (!data.transform) {
1589
+ if (box.x || box.y) {
1590
+ data.transform = get$2();
1591
+ translate(data.transform, box.x, box.y);
1592
+ }
1593
+ }
1594
+ if (scaleX && mode !== 'strench') {
1595
+ data.scaleX = scaleX;
1596
+ data.scaleY = scaleY;
1230
1597
  }
1231
1598
  data.width = width;
1232
1599
  data.height = height;
@@ -1234,112 +1601,108 @@ function createData(leafPaint, image, paint, box) {
1234
1601
  data.opacity = opacity;
1235
1602
  if (repeat)
1236
1603
  data.repeat = typeof repeat === 'string' ? (repeat === 'x' ? 'repeat-x' : 'repeat-y') : 'repeat';
1604
+ return data;
1237
1605
  }
1238
1606
 
1239
- function image(ui, attrName, attrValue, box, firstUse) {
1240
- const leafPaint = { type: attrValue.type };
1241
- const image = leafPaint.image = ImageManager.get(attrValue);
1242
- const event = (firstUse || image.loading) && { target: ui, image, attrName, attrValue };
1607
+ let cache, box = new Bounds();
1608
+ const { isSame } = BoundsHelper;
1609
+ function image(ui, attrName, paint, boxBounds, firstUse) {
1610
+ let leafPaint, event;
1611
+ const image = ImageManager.get(paint);
1612
+ if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
1613
+ leafPaint = cache.leafPaint;
1614
+ }
1615
+ else {
1616
+ leafPaint = { type: paint.type, image };
1617
+ cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
1618
+ }
1619
+ if (firstUse || image.loading)
1620
+ event = { image, attrName, attrValue: paint };
1243
1621
  if (image.ready) {
1244
- if (hasNaturalSize(ui, attrName, image))
1245
- createData(leafPaint, image, attrValue, box);
1622
+ checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
1246
1623
  if (firstUse) {
1247
- emit(ImageEvent.LOAD, event);
1248
- emit(ImageEvent.LOADED, event);
1624
+ onLoad(ui, event);
1625
+ onLoadSuccess(ui, event);
1249
1626
  }
1250
1627
  }
1251
1628
  else if (image.error) {
1252
- if (firstUse) {
1253
- ui.forceUpdate('surface');
1254
- event.error = image.error;
1255
- emit(ImageEvent.ERROR, event);
1256
- }
1629
+ if (firstUse)
1630
+ onLoadError(ui, event, image.error);
1257
1631
  }
1258
1632
  else {
1633
+ ignoreRender(ui, true);
1259
1634
  if (firstUse)
1260
- emit(ImageEvent.LOAD, event);
1635
+ onLoad(ui, event);
1261
1636
  leafPaint.loadId = image.load(() => {
1637
+ ignoreRender(ui, false);
1262
1638
  if (!ui.destroyed) {
1263
- if (hasNaturalSize(ui, attrName, image)) {
1264
- createData(leafPaint, image, attrValue, box);
1639
+ if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1640
+ if (image.hasOpacityPixel)
1641
+ ui.__layout.hitCanvasChanged = true;
1265
1642
  ui.forceUpdate('surface');
1266
1643
  }
1267
- emit(ImageEvent.LOADED, event);
1644
+ onLoadSuccess(ui, event);
1268
1645
  }
1646
+ leafPaint.loadId = null;
1269
1647
  }, (error) => {
1270
- ui.forceUpdate('surface');
1271
- event.error = error;
1272
- emit(ImageEvent.ERROR, event);
1648
+ ignoreRender(ui, false);
1649
+ onLoadError(ui, event, error);
1650
+ leafPaint.loadId = null;
1273
1651
  });
1274
1652
  }
1275
1653
  return leafPaint;
1276
1654
  }
1277
- function hasNaturalSize(ui, attrName, image) {
1655
+ function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
1278
1656
  if (attrName === 'fill' && !ui.__.__naturalWidth) {
1279
- const { __: d } = ui;
1280
- d.__naturalWidth = image.width;
1281
- d.__naturalHeight = image.height;
1282
- if (!d.__getInput('width') || !d.__getInput('height')) {
1657
+ const data = ui.__;
1658
+ data.__naturalWidth = image.width / data.pixelRatio;
1659
+ data.__naturalHeight = image.height / data.pixelRatio;
1660
+ if (data.__autoSide) {
1283
1661
  ui.forceUpdate('width');
1284
1662
  if (ui.__proxyData) {
1285
- ui.setProxyAttr('width', ui.__.width);
1286
- ui.setProxyAttr('height', ui.__.height);
1663
+ ui.setProxyAttr('width', data.width);
1664
+ ui.setProxyAttr('height', data.height);
1287
1665
  }
1288
1666
  return false;
1289
1667
  }
1290
1668
  }
1669
+ if (!leafPaint.data)
1670
+ createData(leafPaint, image, paint, boxBounds);
1291
1671
  return true;
1292
1672
  }
1293
- function emit(type, data) {
1294
- if (data.target.hasEvent(type))
1295
- data.target.emitEvent(new ImageEvent(type, data));
1673
+ function onLoad(ui, event) {
1674
+ emit(ui, ImageEvent.LOAD, event);
1675
+ }
1676
+ function onLoadSuccess(ui, event) {
1677
+ emit(ui, ImageEvent.LOADED, event);
1678
+ }
1679
+ function onLoadError(ui, event, error) {
1680
+ event.error = error;
1681
+ ui.forceUpdate('surface');
1682
+ emit(ui, ImageEvent.ERROR, event);
1683
+ }
1684
+ function emit(ui, type, data) {
1685
+ if (ui.hasEvent(type))
1686
+ ui.emitEvent(new ImageEvent(type, data));
1687
+ }
1688
+ function ignoreRender(ui, value) {
1689
+ const { leafer } = ui;
1690
+ if (leafer && leafer.viewReady)
1691
+ leafer.renderer.ignore = value;
1296
1692
  }
1297
1693
 
1298
- /******************************************************************************
1299
- Copyright (c) Microsoft Corporation.
1300
-
1301
- Permission to use, copy, modify, and/or distribute this software for any
1302
- purpose with or without fee is hereby granted.
1303
-
1304
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
1305
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1306
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
1307
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1308
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
1309
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1310
- PERFORMANCE OF THIS SOFTWARE.
1311
- ***************************************************************************** */
1312
- /* global Reflect, Promise, SuppressedError, Symbol */
1313
-
1314
-
1315
- function __awaiter(thisArg, _arguments, P, generator) {
1316
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
1317
- return new (P || (P = Promise))(function (resolve, reject) {
1318
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
1319
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
1320
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
1321
- step((generator = generator.apply(thisArg, _arguments || [])).next());
1322
- });
1323
- }
1324
-
1325
- typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
1326
- var e = new Error(message);
1327
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1328
- };
1329
-
1330
- const Export$1 = {};
1331
-
1332
- const { get: get$2, scale, copy: copy$1 } = MatrixHelper;
1694
+ const { get: get$1, scale, copy: copy$1 } = MatrixHelper;
1695
+ const { ceil, abs: abs$1 } = Math;
1333
1696
  function createPattern(ui, paint, pixelRatio) {
1334
- let { scaleX, scaleY } = ui.__world;
1697
+ let { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
1335
1698
  const id = scaleX + '-' + scaleY;
1336
1699
  if (paint.patternId !== id && !ui.destroyed) {
1337
- scaleX = Math.abs(scaleX);
1338
- scaleY = Math.abs(scaleY);
1700
+ scaleX = abs$1(scaleX);
1701
+ scaleY = abs$1(scaleY);
1339
1702
  const { image, data } = paint;
1340
1703
  let imageScale, imageMatrix, { width, height, scaleX: sx, scaleY: sy, opacity, transform, repeat } = data;
1341
1704
  if (sx) {
1342
- imageMatrix = get$2();
1705
+ imageMatrix = get$1();
1343
1706
  copy$1(imageMatrix, transform);
1344
1707
  scale(imageMatrix, 1 / sx, 1 / sy);
1345
1708
  scaleX *= sx;
@@ -1374,22 +1737,14 @@ function createPattern(ui, paint, pixelRatio) {
1374
1737
  }
1375
1738
  if (transform || scaleX !== 1 || scaleY !== 1) {
1376
1739
  if (!imageMatrix) {
1377
- imageMatrix = get$2();
1740
+ imageMatrix = get$1();
1378
1741
  if (transform)
1379
1742
  copy$1(imageMatrix, transform);
1380
1743
  }
1381
1744
  scale(imageMatrix, 1 / scaleX, 1 / scaleY);
1382
1745
  }
1383
- const pattern = Platform.canvas.createPattern(image.getCanvas(width < 1 ? 1 : width, height < 1 ? 1 : height, opacity), repeat || (Platform.origin.noRepeat || 'no-repeat'));
1384
- try {
1385
- if (paint.transform)
1386
- paint.transform = null;
1387
- if (imageMatrix)
1388
- pattern.setTransform ? pattern.setTransform(imageMatrix) : paint.transform = imageMatrix;
1389
- }
1390
- catch (_a) {
1391
- paint.transform = imageMatrix;
1392
- }
1746
+ const canvas = image.getCanvas(ceil(width) || 1, ceil(height) || 1, opacity);
1747
+ const pattern = image.getPattern(canvas, repeat || (Platform.origin.noRepeat || 'no-repeat'), imageMatrix, paint);
1393
1748
  paint.style = pattern;
1394
1749
  paint.patternId = id;
1395
1750
  return true;
@@ -1399,9 +1754,41 @@ function createPattern(ui, paint, pixelRatio) {
1399
1754
  }
1400
1755
  }
1401
1756
 
1757
+ /******************************************************************************
1758
+ Copyright (c) Microsoft Corporation.
1759
+
1760
+ Permission to use, copy, modify, and/or distribute this software for any
1761
+ purpose with or without fee is hereby granted.
1762
+
1763
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
1764
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1765
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
1766
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1767
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
1768
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1769
+ PERFORMANCE OF THIS SOFTWARE.
1770
+ ***************************************************************************** */
1771
+ /* global Reflect, Promise, SuppressedError, Symbol */
1772
+
1773
+
1774
+ function __awaiter(thisArg, _arguments, P, generator) {
1775
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
1776
+ return new (P || (P = Promise))(function (resolve, reject) {
1777
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
1778
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
1779
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
1780
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
1781
+ });
1782
+ }
1783
+
1784
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
1785
+ var e = new Error(message);
1786
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1787
+ };
1788
+
1402
1789
  const { abs } = Math;
1403
1790
  function checkImage(ui, canvas, paint, allowPaint) {
1404
- const { scaleX, scaleY } = ui.__world;
1791
+ const { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
1405
1792
  if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
1406
1793
  return false;
1407
1794
  }
@@ -1416,326 +1803,91 @@ function checkImage(ui, canvas, paint, allowPaint) {
1416
1803
  width *= data.scaleX;
1417
1804
  height *= data.scaleY;
1418
1805
  }
1419
- allowPaint = width * height > Platform.image.maxCacheSize;
1806
+ allowPaint = (width * height > Platform.image.maxCacheSize) || Export.running;
1420
1807
  }
1421
1808
  else {
1422
1809
  allowPaint = false;
1423
1810
  }
1424
1811
  }
1425
- if (allowPaint) {
1426
- canvas.save();
1427
- canvas.clip();
1428
- if (paint.blendMode)
1429
- canvas.blendMode = paint.blendMode;
1430
- if (data.opacity)
1431
- canvas.opacity *= data.opacity;
1432
- if (data.transform)
1433
- canvas.transform(data.transform);
1434
- canvas.drawImage(paint.image.view, 0, 0, data.width, data.height);
1435
- canvas.restore();
1436
- return true;
1437
- }
1438
- else {
1439
- if (!paint.style || Export$1.running) {
1440
- createPattern(ui, paint, canvas.pixelRatio);
1441
- }
1442
- else {
1443
- if (!paint.patternTask) {
1444
- paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
1445
- paint.patternTask = null;
1446
- if (canvas.bounds.hit(ui.__world))
1447
- createPattern(ui, paint, canvas.pixelRatio);
1448
- ui.forceUpdate('surface');
1449
- }), 300);
1450
- }
1451
- }
1452
- return false;
1453
- }
1454
- }
1455
- }
1456
-
1457
- function recycleImage(attrName, data) {
1458
- const paints = data['_' + attrName];
1459
- if (paints instanceof Array) {
1460
- let image, recycleMap, input, url;
1461
- for (let i = 0, len = paints.length; i < len; i++) {
1462
- image = paints[i].image;
1463
- url = image && image.url;
1464
- if (url) {
1465
- if (!recycleMap)
1466
- recycleMap = {};
1467
- recycleMap[url] = true;
1468
- ImageManager.recycle(image);
1469
- if (image.loading) {
1470
- if (!input) {
1471
- input = (data.__input && data.__input[attrName]) || [];
1472
- if (!(input instanceof Array))
1473
- input = [input];
1474
- }
1475
- image.unload(paints[i].loadId, !input.some((item) => item.url === url));
1476
- }
1477
- }
1478
- }
1479
- return recycleMap;
1480
- }
1481
- return null;
1482
- }
1483
-
1484
- function fillText(ui, canvas) {
1485
- let row;
1486
- const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
1487
- for (let i = 0, len = rows.length; i < len; i++) {
1488
- row = rows[i];
1489
- if (row.text) {
1490
- canvas.fillText(row.text, row.x, row.y);
1491
- }
1492
- else if (row.data) {
1493
- row.data.forEach(charData => {
1494
- canvas.fillText(charData.char, charData.x, row.y);
1495
- });
1496
- }
1497
- if (decorationY)
1498
- canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight);
1499
- }
1500
- }
1501
-
1502
- function fill(fill, ui, canvas) {
1503
- canvas.fillStyle = fill;
1504
- ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
1505
- }
1506
- function fills(fills, ui, canvas) {
1507
- let item;
1508
- const { windingRule, __font } = ui.__;
1509
- for (let i = 0, len = fills.length; i < len; i++) {
1510
- item = fills[i];
1511
- if (item.image && checkImage(ui, canvas, item, !__font))
1512
- continue;
1513
- if (item.style) {
1514
- canvas.fillStyle = item.style;
1515
- if (item.transform) {
1516
- canvas.save();
1517
- canvas.transform(item.transform);
1518
- if (item.blendMode)
1519
- canvas.blendMode = item.blendMode;
1520
- __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1521
- canvas.restore();
1522
- }
1523
- else {
1524
- if (item.blendMode) {
1525
- canvas.saveBlendMode(item.blendMode);
1526
- __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1527
- canvas.restoreBlendMode();
1528
- }
1529
- else {
1530
- __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1531
- }
1532
- }
1533
- }
1534
- }
1535
- }
1536
-
1537
- function strokeText(stroke, ui, canvas, renderOptions) {
1538
- const { strokeAlign } = ui.__;
1539
- const isStrokes = typeof stroke !== 'string';
1540
- switch (strokeAlign) {
1541
- case 'center':
1542
- canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
1543
- isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
1544
- break;
1545
- case 'inside':
1546
- drawAlignStroke('inside', stroke, isStrokes, ui, canvas, renderOptions);
1547
- break;
1548
- case 'outside':
1549
- drawAlignStroke('outside', stroke, isStrokes, ui, canvas, renderOptions);
1550
- break;
1551
- }
1552
- }
1553
- function drawAlignStroke(align, stroke, isStrokes, ui, canvas, renderOptions) {
1554
- const { strokeWidth, __font } = ui.__;
1555
- const out = canvas.getSameCanvas(true);
1556
- out.setStroke(isStrokes ? undefined : stroke, strokeWidth * 2, ui.__);
1557
- out.font = __font;
1558
- isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
1559
- out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
1560
- fillText(ui, out);
1561
- out.blendMode = 'normal';
1562
- if (ui.__worldFlipped || renderOptions.matrix) {
1563
- canvas.copyWorldByReset(out);
1564
- }
1565
- else {
1566
- canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds);
1567
- }
1568
- out.recycle();
1569
- }
1570
- function drawTextStroke(ui, canvas) {
1571
- let row;
1572
- const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
1573
- for (let i = 0, len = rows.length; i < len; i++) {
1574
- row = rows[i];
1575
- if (row.text) {
1576
- canvas.strokeText(row.text, row.x, row.y);
1577
- }
1578
- else if (row.data) {
1579
- row.data.forEach(charData => {
1580
- canvas.strokeText(charData.char, charData.x, row.y);
1581
- });
1582
- }
1583
- if (decorationY)
1584
- canvas.strokeRect(row.x, row.y + decorationY, row.width, decorationHeight);
1585
- }
1586
- }
1587
- function drawStrokesStyle(strokes, isText, ui, canvas) {
1588
- let item;
1589
- for (let i = 0, len = strokes.length; i < len; i++) {
1590
- item = strokes[i];
1591
- if (item.image && checkImage(ui, canvas, item, false))
1592
- continue;
1593
- if (item.style) {
1594
- canvas.strokeStyle = item.style;
1595
- if (item.blendMode) {
1596
- canvas.saveBlendMode(item.blendMode);
1597
- isText ? drawTextStroke(ui, canvas) : canvas.stroke();
1598
- canvas.restoreBlendMode();
1812
+ if (allowPaint) {
1813
+ canvas.save();
1814
+ canvas.clip();
1815
+ if (paint.blendMode)
1816
+ canvas.blendMode = paint.blendMode;
1817
+ if (data.opacity)
1818
+ canvas.opacity *= data.opacity;
1819
+ if (data.transform)
1820
+ canvas.transform(data.transform);
1821
+ canvas.drawImage(paint.image.view, 0, 0, data.width, data.height);
1822
+ canvas.restore();
1823
+ return true;
1824
+ }
1825
+ else {
1826
+ if (!paint.style || Export.running) {
1827
+ createPattern(ui, paint, canvas.pixelRatio);
1599
1828
  }
1600
1829
  else {
1601
- isText ? drawTextStroke(ui, canvas) : canvas.stroke();
1830
+ if (!paint.patternTask) {
1831
+ paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
1832
+ paint.patternTask = null;
1833
+ if (canvas.bounds.hit(ui.__nowWorld))
1834
+ createPattern(ui, paint, canvas.pixelRatio);
1835
+ ui.forceUpdate('surface');
1836
+ }), 300);
1837
+ }
1602
1838
  }
1839
+ return false;
1603
1840
  }
1604
1841
  }
1605
1842
  }
1606
1843
 
1607
- function stroke(stroke, ui, canvas, renderOptions) {
1608
- const options = ui.__;
1609
- const { strokeWidth, strokeAlign, __font } = options;
1610
- if (!strokeWidth)
1611
- return;
1612
- if (__font) {
1613
- strokeText(stroke, ui, canvas, renderOptions);
1614
- }
1615
- else {
1616
- switch (strokeAlign) {
1617
- case 'center':
1618
- canvas.setStroke(stroke, strokeWidth, options);
1619
- canvas.stroke();
1620
- break;
1621
- case 'inside':
1622
- canvas.save();
1623
- canvas.setStroke(stroke, strokeWidth * 2, options);
1624
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1625
- canvas.stroke();
1626
- canvas.restore();
1627
- break;
1628
- case 'outside':
1629
- const out = canvas.getSameCanvas(true);
1630
- out.setStroke(stroke, strokeWidth * 2, ui.__);
1631
- ui.__drawRenderPath(out);
1632
- out.stroke();
1633
- options.windingRule ? out.clip(options.windingRule) : out.clip();
1634
- out.clearWorld(ui.__layout.renderBounds);
1635
- if (ui.__worldFlipped || renderOptions.matrix) {
1636
- canvas.copyWorldByReset(out);
1637
- }
1638
- else {
1639
- canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds);
1640
- }
1641
- out.recycle();
1642
- break;
1643
- }
1644
- }
1645
- }
1646
- function strokes(strokes, ui, canvas, renderOptions) {
1647
- const options = ui.__;
1648
- const { strokeWidth, strokeAlign, __font } = options;
1649
- if (!strokeWidth)
1650
- return;
1651
- if (__font) {
1652
- strokeText(strokes, ui, canvas, renderOptions);
1653
- }
1654
- else {
1655
- switch (strokeAlign) {
1656
- case 'center':
1657
- canvas.setStroke(undefined, strokeWidth, options);
1658
- drawStrokesStyle(strokes, false, ui, canvas);
1659
- break;
1660
- case 'inside':
1661
- canvas.save();
1662
- canvas.setStroke(undefined, strokeWidth * 2, options);
1663
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1664
- drawStrokesStyle(strokes, false, ui, canvas);
1665
- canvas.restore();
1666
- break;
1667
- case 'outside':
1668
- const { renderBounds } = ui.__layout;
1669
- const out = canvas.getSameCanvas(true);
1670
- ui.__drawRenderPath(out);
1671
- out.setStroke(undefined, strokeWidth * 2, ui.__);
1672
- drawStrokesStyle(strokes, false, ui, out);
1673
- options.windingRule ? out.clip(options.windingRule) : out.clip();
1674
- out.clearWorld(renderBounds);
1675
- if (ui.__worldFlipped || renderOptions.matrix) {
1676
- canvas.copyWorldByReset(out);
1677
- }
1678
- else {
1679
- canvas.copyWorldToInner(out, ui.__world, renderBounds);
1844
+ function recycleImage(attrName, data) {
1845
+ const paints = data['_' + attrName];
1846
+ if (paints instanceof Array) {
1847
+ let image, recycleMap, input, url;
1848
+ for (let i = 0, len = paints.length; i < len; i++) {
1849
+ image = paints[i].image;
1850
+ url = image && image.url;
1851
+ if (url) {
1852
+ if (!recycleMap)
1853
+ recycleMap = {};
1854
+ recycleMap[url] = true;
1855
+ ImageManager.recycle(image);
1856
+ if (image.loading) {
1857
+ if (!input) {
1858
+ input = (data.__input && data.__input[attrName]) || [];
1859
+ if (!(input instanceof Array))
1860
+ input = [input];
1861
+ }
1862
+ image.unload(paints[i].loadId, !input.some((item) => item.url === url));
1680
1863
  }
1681
- out.recycle();
1682
- break;
1864
+ }
1683
1865
  }
1866
+ return recycleMap;
1684
1867
  }
1868
+ return null;
1685
1869
  }
1686
1870
 
1687
- const { getSpread, getOuterOf, getByMove, getIntersectData } = BoundsHelper;
1688
- function shape(ui, current, options) {
1689
- const canvas = current.getSameCanvas();
1690
- let bounds, matrix, shapeBounds;
1691
- let worldCanvas;
1692
- const { __world } = ui;
1693
- let { scaleX, scaleY } = __world;
1694
- if (scaleX < 0)
1695
- scaleX = -scaleX;
1696
- if (scaleY < 0)
1697
- scaleY = -scaleY;
1698
- if (!current.bounds.includes(__world, options.matrix)) {
1699
- const { renderShapeSpread: spread } = ui.__layout;
1700
- const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, spread * scaleX, spread * scaleY) : current.bounds, __world, options.matrix);
1701
- matrix = current.bounds.getFitMatrix(worldClipBounds);
1702
- if (matrix.a < 1) {
1703
- worldCanvas = current.getSameCanvas();
1704
- ui.__renderShape(worldCanvas, options);
1705
- scaleX *= matrix.a;
1706
- scaleY *= matrix.d;
1707
- }
1708
- shapeBounds = getOuterOf(__world, matrix);
1709
- bounds = getByMove(shapeBounds, -matrix.e, -matrix.f);
1710
- if (options.matrix)
1711
- matrix.multiply(options.matrix);
1712
- options = Object.assign(Object.assign({}, options), { matrix });
1713
- }
1714
- else {
1715
- if (options.matrix) {
1716
- scaleX *= options.matrix.a;
1717
- scaleY *= options.matrix.d;
1718
- bounds = shapeBounds = getOuterOf(__world, options.matrix);
1719
- }
1720
- else {
1721
- bounds = shapeBounds = __world;
1722
- }
1723
- worldCanvas = canvas;
1724
- }
1725
- ui.__renderShape(canvas, options);
1726
- return {
1727
- canvas, matrix, bounds,
1728
- worldCanvas, shapeBounds, scaleX, scaleY
1729
- };
1730
- }
1871
+ const PaintImageModule = {
1872
+ image,
1873
+ checkImage,
1874
+ createPattern,
1875
+ recycleImage,
1876
+ createData,
1877
+ getPatternData,
1878
+ fillOrFitMode,
1879
+ clipMode,
1880
+ repeatMode
1881
+ };
1731
1882
 
1732
- const defaultFrom$2 = { x: 0.5, y: 0 };
1733
- const defaultTo$2 = { x: 0.5, y: 1 };
1883
+ const { toPoint: toPoint$2 } = AroundHelper;
1884
+ const realFrom$2 = {};
1885
+ const realTo$2 = {};
1734
1886
  function linearGradient(paint, box) {
1735
1887
  let { from, to, type, blendMode, opacity } = paint;
1736
- from || (from = defaultFrom$2);
1737
- to || (to = defaultTo$2);
1738
- 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);
1888
+ toPoint$2(from || 'top', box, realFrom$2);
1889
+ toPoint$2(to || 'bottom', box, realTo$2);
1890
+ const style = Platform.canvas.createLinearGradient(realFrom$2.x, realFrom$2.y, realTo$2.x, realTo$2.y);
1739
1891
  applyStops(style, paint.stops, opacity);
1740
1892
  const data = { type, style };
1741
1893
  if (blendMode)
@@ -1746,137 +1898,84 @@ function applyStops(gradient, stops, opacity) {
1746
1898
  let stop;
1747
1899
  for (let i = 0, len = stops.length; i < len; i++) {
1748
1900
  stop = stops[i];
1749
- gradient.addColorStop(stop.offset, ColorConvert$1.string(stop.color, opacity));
1901
+ if (typeof stop === 'string') {
1902
+ gradient.addColorStop(i / (len - 1), ColorConvert.string(stop, opacity));
1903
+ }
1904
+ else {
1905
+ gradient.addColorStop(stop.offset, ColorConvert.string(stop.color, opacity));
1906
+ }
1750
1907
  }
1751
1908
  }
1752
1909
 
1753
- const { set: set$1, getAngle: getAngle$1, getDistance: getDistance$1 } = PointHelper;
1754
- const { get: get$1, rotateOfOuter: rotateOfOuter$1, scaleOfOuter: scaleOfOuter$1 } = MatrixHelper;
1755
- const defaultFrom$1 = { x: 0.5, y: 0.5 };
1756
- const defaultTo$1 = { x: 0.5, y: 1 };
1910
+ const { getAngle, getDistance: getDistance$1 } = PointHelper;
1911
+ const { get, rotateOfOuter, scaleOfOuter } = MatrixHelper;
1912
+ const { toPoint: toPoint$1 } = AroundHelper;
1757
1913
  const realFrom$1 = {};
1758
1914
  const realTo$1 = {};
1759
1915
  function radialGradient(paint, box) {
1760
1916
  let { from, to, type, opacity, blendMode, stretch } = paint;
1761
- from || (from = defaultFrom$1);
1762
- to || (to = defaultTo$1);
1763
- const { x, y, width, height } = box;
1764
- set$1(realFrom$1, x + from.x * width, y + from.y * height);
1765
- set$1(realTo$1, x + to.x * width, y + to.y * height);
1766
- let transform;
1767
- if (width !== height || stretch) {
1768
- transform = get$1();
1769
- scaleOfOuter$1(transform, realFrom$1, width / height * (stretch || 1), 1);
1770
- rotateOfOuter$1(transform, realFrom$1, getAngle$1(realFrom$1, realTo$1) + 90);
1771
- }
1917
+ toPoint$1(from || 'center', box, realFrom$1);
1918
+ toPoint$1(to || 'bottom', box, realTo$1);
1772
1919
  const style = Platform.canvas.createRadialGradient(realFrom$1.x, realFrom$1.y, 0, realFrom$1.x, realFrom$1.y, getDistance$1(realFrom$1, realTo$1));
1773
1920
  applyStops(style, paint.stops, opacity);
1774
- const data = { type, style, transform };
1921
+ const data = { type, style };
1922
+ const transform = getTransform(box, realFrom$1, realTo$1, stretch, true);
1923
+ if (transform)
1924
+ data.transform = transform;
1775
1925
  if (blendMode)
1776
1926
  data.blendMode = blendMode;
1777
1927
  return data;
1778
1928
  }
1929
+ function getTransform(box, from, to, stretch, rotate90) {
1930
+ let transform;
1931
+ const { width, height } = box;
1932
+ if (width !== height || stretch) {
1933
+ const angle = getAngle(from, to);
1934
+ transform = get();
1935
+ if (rotate90) {
1936
+ scaleOfOuter(transform, from, width / height * (stretch || 1), 1);
1937
+ rotateOfOuter(transform, from, angle + 90);
1938
+ }
1939
+ else {
1940
+ scaleOfOuter(transform, from, 1, width / height * (stretch || 1));
1941
+ rotateOfOuter(transform, from, angle);
1942
+ }
1943
+ }
1944
+ return transform;
1945
+ }
1779
1946
 
1780
- const { set, getAngle, getDistance } = PointHelper;
1781
- const { get, rotateOfOuter, scaleOfOuter } = MatrixHelper;
1782
- const defaultFrom = { x: 0.5, y: 0.5 };
1783
- const defaultTo = { x: 0.5, y: 1 };
1947
+ const { getDistance } = PointHelper;
1948
+ const { toPoint } = AroundHelper;
1784
1949
  const realFrom = {};
1785
1950
  const realTo = {};
1786
1951
  function conicGradient(paint, box) {
1787
1952
  let { from, to, type, opacity, blendMode, stretch } = paint;
1788
- from || (from = defaultFrom);
1789
- to || (to = defaultTo);
1790
- const { x, y, width, height } = box;
1791
- set(realFrom, x + from.x * width, y + from.y * height);
1792
- set(realTo, x + to.x * width, y + to.y * height);
1793
- const transform = get();
1794
- const angle = getAngle(realFrom, realTo);
1795
- if (Platform.conicGradientRotate90) {
1796
- scaleOfOuter(transform, realFrom, width / height * (stretch || 1), 1);
1797
- rotateOfOuter(transform, realFrom, angle + 90);
1798
- }
1799
- else {
1800
- scaleOfOuter(transform, realFrom, 1, width / height * (stretch || 1));
1801
- rotateOfOuter(transform, realFrom, angle);
1802
- }
1953
+ toPoint(from || 'center', box, realFrom);
1954
+ toPoint(to || 'bottom', box, realTo);
1803
1955
  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));
1804
1956
  applyStops(style, paint.stops, opacity);
1805
- const data = { type, style, transform };
1957
+ const data = { type, style };
1958
+ const transform = getTransform(box, realFrom, realTo, stretch || 1, Platform.conicGradientRotate90);
1959
+ if (transform)
1960
+ data.transform = transform;
1806
1961
  if (blendMode)
1807
1962
  data.blendMode = blendMode;
1808
1963
  return data;
1809
1964
  }
1810
1965
 
1811
- let recycleMap;
1812
- function compute(attrName, ui) {
1813
- const value = [];
1814
- const data = ui.__;
1815
- let item;
1816
- let paints = data.__input[attrName];
1817
- if (!(paints instanceof Array))
1818
- paints = [paints];
1819
- recycleMap = recycleImage(attrName, data);
1820
- for (let i = 0, len = paints.length; i < len; i++) {
1821
- item = getLeafPaint(attrName, paints[i], ui);
1822
- if (item)
1823
- value.push(item);
1824
- }
1825
- data['_' + attrName] = value.length ? value : undefined;
1826
- let isPixel;
1827
- if (paints.length === 1) {
1828
- const paint = paints[0];
1829
- if (paint.type === 'image')
1830
- isPixel = ImageManager$1.isPixel(paint);
1831
- }
1832
- if (attrName === 'fill') {
1833
- data.__pixelFill = isPixel;
1834
- }
1835
- else {
1836
- data.__pixelStroke = isPixel;
1837
- }
1838
- }
1839
- function getLeafPaint(attrName, paint, ui) {
1840
- if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
1841
- return undefined;
1842
- const { boxBounds } = ui.__layout;
1843
- switch (paint.type) {
1844
- case 'solid':
1845
- let { type, blendMode, color, opacity } = paint;
1846
- return { type, blendMode, style: ColorConvert$1.string(color, opacity) };
1847
- case 'image':
1848
- return image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1849
- case 'linear':
1850
- return linearGradient(paint, boxBounds);
1851
- case 'radial':
1852
- return radialGradient(paint, boxBounds);
1853
- case 'angular':
1854
- return conicGradient(paint, boxBounds);
1855
- default:
1856
- return paint.r ? { type: 'solid', style: ColorConvert$1.string(paint) } : undefined;
1857
- }
1858
- }
1859
-
1860
- var UIPaint = /*#__PURE__*/Object.freeze({
1861
- __proto__: null,
1862
- compute: compute,
1863
- drawTextStroke: drawTextStroke,
1864
- fill: fill,
1865
- fillText: fillText,
1866
- fills: fills,
1867
- recycleImage: recycleImage,
1868
- shape: shape,
1869
- stroke: stroke,
1870
- strokeText: strokeText,
1871
- strokes: strokes
1872
- });
1966
+ const PaintGradientModule = {
1967
+ linearGradient,
1968
+ radialGradient,
1969
+ conicGradient,
1970
+ getTransform
1971
+ };
1873
1972
 
1874
1973
  const { copy, toOffsetOutBounds: toOffsetOutBounds$1 } = BoundsHelper;
1875
1974
  const tempBounds = {};
1876
1975
  const offsetOutBounds$1 = {};
1877
- function shadow(ui, current, shape, renderOptions) {
1976
+ function shadow(ui, current, shape) {
1878
1977
  let copyBounds, spreadScale;
1879
- const { __world, __layout } = ui;
1978
+ const { __nowWorld: nowWorld, __layout } = ui;
1880
1979
  const { shadow } = ui.__;
1881
1980
  const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
1882
1981
  const other = current.getSameCanvas();
@@ -1891,21 +1990,21 @@ function shadow(ui, current, shape, renderOptions) {
1891
1990
  other.restore();
1892
1991
  other.save();
1893
1992
  if (worldCanvas) {
1894
- other.copyWorld(other, bounds, __world, 'copy');
1895
- copyBounds = __world;
1993
+ other.copyWorld(other, bounds, nowWorld, 'copy');
1994
+ copyBounds = nowWorld;
1896
1995
  }
1897
- worldCanvas ? other.copyWorld(worldCanvas, __world, __world, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
1996
+ worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
1898
1997
  }
1899
- if (ui.__worldFlipped || renderOptions.matrix) {
1900
- current.copyWorldByReset(other, copyBounds, __world, item.blendMode);
1998
+ if (ui.__worldFlipped) {
1999
+ current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1901
2000
  }
1902
2001
  else {
1903
2002
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1904
2003
  }
1905
2004
  if (end && index < end)
1906
- other.clear();
2005
+ other.clearWorld(copyBounds, true);
1907
2006
  });
1908
- other.recycle();
2007
+ other.recycle(copyBounds);
1909
2008
  }
1910
2009
  function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
1911
2010
  const { bounds, shapeBounds } = shape;
@@ -1936,9 +2035,9 @@ function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
1936
2035
 
1937
2036
  const { toOffsetOutBounds } = BoundsHelper;
1938
2037
  const offsetOutBounds = {};
1939
- function innerShadow(ui, current, shape, renderOptions) {
2038
+ function innerShadow(ui, current, shape) {
1940
2039
  let copyBounds, spreadScale;
1941
- const { __world, __layout: __layout } = ui;
2040
+ const { __nowWorld: nowWorld, __layout: __layout } = ui;
1942
2041
  const { innerShadow } = ui.__;
1943
2042
  const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
1944
2043
  const other = current.getSameCanvas();
@@ -1951,40 +2050,115 @@ function innerShadow(ui, current, shape, renderOptions) {
1951
2050
  drawWorldShadow(other, offsetOutBounds, spreadScale, shape);
1952
2051
  other.restore();
1953
2052
  if (worldCanvas) {
1954
- other.copyWorld(other, bounds, __world, 'copy');
1955
- other.copyWorld(worldCanvas, __world, __world, 'source-out');
1956
- copyBounds = __world;
2053
+ other.copyWorld(other, bounds, nowWorld, 'copy');
2054
+ other.copyWorld(worldCanvas, nowWorld, nowWorld, 'source-out');
2055
+ copyBounds = nowWorld;
1957
2056
  }
1958
2057
  else {
1959
2058
  other.copyWorld(shape.canvas, shapeBounds, bounds, 'source-out');
1960
2059
  copyBounds = bounds;
1961
2060
  }
1962
2061
  other.fillWorld(copyBounds, item.color, 'source-in');
1963
- if (ui.__worldFlipped || renderOptions.matrix) {
1964
- current.copyWorldByReset(other, copyBounds, __world, item.blendMode);
2062
+ if (ui.__worldFlipped) {
2063
+ current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1965
2064
  }
1966
2065
  else {
1967
2066
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1968
2067
  }
1969
2068
  if (end && index < end)
1970
- other.clear();
2069
+ other.clearWorld(copyBounds, true);
1971
2070
  });
1972
- other.recycle();
2071
+ other.recycle(copyBounds);
1973
2072
  }
1974
2073
 
1975
2074
  function blur(ui, current, origin) {
1976
2075
  const { blur } = ui.__;
1977
- origin.setWorldBlur(blur * ui.__world.a);
1978
- origin.copyWorldToInner(current, ui.__world, ui.__layout.renderBounds);
2076
+ origin.setWorldBlur(blur * ui.__nowWorld.a);
2077
+ origin.copyWorldToInner(current, ui.__nowWorld, ui.__layout.renderBounds);
1979
2078
  origin.filter = 'none';
1980
2079
  }
1981
2080
 
1982
- var UIEffect = /*#__PURE__*/Object.freeze({
1983
- __proto__: null,
1984
- blur: blur,
1985
- innerShadow: innerShadow,
1986
- shadow: shadow
1987
- });
2081
+ function backgroundBlur(_ui, _current, _shape) {
2082
+ }
2083
+
2084
+ const EffectModule = {
2085
+ shadow,
2086
+ innerShadow,
2087
+ blur,
2088
+ backgroundBlur
2089
+ };
2090
+
2091
+ const { excludeRenderBounds } = LeafBoundsHelper;
2092
+ Group.prototype.__renderMask = function (canvas, options) {
2093
+ let child, maskCanvas, contentCanvas, maskOpacity, currentMask;
2094
+ const { children } = this;
2095
+ for (let i = 0, len = children.length; i < len; i++) {
2096
+ child = children[i];
2097
+ if (child.__.mask) {
2098
+ if (currentMask) {
2099
+ maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
2100
+ maskCanvas = contentCanvas = null;
2101
+ }
2102
+ if (child.__.mask === 'path') {
2103
+ if (child.opacity < 1) {
2104
+ currentMask = 'opacity-path';
2105
+ maskOpacity = child.opacity;
2106
+ if (!contentCanvas)
2107
+ contentCanvas = getCanvas(canvas);
2108
+ }
2109
+ else {
2110
+ currentMask = 'path';
2111
+ canvas.save();
2112
+ }
2113
+ child.__clip(contentCanvas || canvas, options);
2114
+ }
2115
+ else {
2116
+ currentMask = 'alpha';
2117
+ if (!maskCanvas)
2118
+ maskCanvas = getCanvas(canvas);
2119
+ if (!contentCanvas)
2120
+ contentCanvas = getCanvas(canvas);
2121
+ child.__render(maskCanvas, options);
2122
+ }
2123
+ if (child.__.mask !== 'clipping')
2124
+ continue;
2125
+ }
2126
+ if (excludeRenderBounds(child, options))
2127
+ continue;
2128
+ child.__render(contentCanvas || canvas, options);
2129
+ }
2130
+ maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
2131
+ };
2132
+ function maskEnd(leaf, maskMode, canvas, contentCanvas, maskCanvas, maskOpacity) {
2133
+ switch (maskMode) {
2134
+ case 'alpha':
2135
+ usePixelMask(leaf, canvas, contentCanvas, maskCanvas);
2136
+ break;
2137
+ case 'opacity-path':
2138
+ copyContent(leaf, canvas, contentCanvas, maskOpacity);
2139
+ break;
2140
+ case 'path':
2141
+ canvas.restore();
2142
+ }
2143
+ }
2144
+ function getCanvas(canvas) {
2145
+ return canvas.getSameCanvas(false, true);
2146
+ }
2147
+ function usePixelMask(leaf, canvas, content, mask) {
2148
+ const realBounds = leaf.__nowWorld;
2149
+ content.resetTransform();
2150
+ content.opacity = 1;
2151
+ content.useMask(mask, realBounds);
2152
+ mask.recycle(realBounds);
2153
+ copyContent(leaf, canvas, content, 1);
2154
+ }
2155
+ function copyContent(leaf, canvas, content, maskOpacity) {
2156
+ const realBounds = leaf.__nowWorld;
2157
+ canvas.resetTransform();
2158
+ canvas.opacity = maskOpacity;
2159
+ canvas.copyWorld(content, realBounds);
2160
+ content.recycle(realBounds);
2161
+ }
1988
2162
 
1989
2163
  const money = '¥¥$€££¢¢';
1990
2164
  const letter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
@@ -2141,7 +2315,8 @@ function createRows(drawData, content, style) {
2141
2315
  if (breakAll) {
2142
2316
  if (wordWidth)
2143
2317
  addWord();
2144
- addRow();
2318
+ if (rowWidth)
2319
+ addRow();
2145
2320
  }
2146
2321
  else {
2147
2322
  if (!afterBreak)
@@ -2149,10 +2324,12 @@ function createRows(drawData, content, style) {
2149
2324
  if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
2150
2325
  if (wordWidth)
2151
2326
  addWord();
2152
- addRow();
2327
+ if (rowWidth)
2328
+ addRow();
2153
2329
  }
2154
2330
  else {
2155
- addRow();
2331
+ if (rowWidth)
2332
+ addRow();
2156
2333
  }
2157
2334
  }
2158
2335
  }
@@ -2247,11 +2424,11 @@ function layoutChar(drawData, style, width, _height) {
2247
2424
  if (mode === WordMode) {
2248
2425
  wordChar = { char: '', x: charX };
2249
2426
  charX = toWordChar(word.data, charX, wordChar);
2250
- if (wordChar.char !== ' ')
2427
+ if (row.isOverflow || wordChar.char !== ' ')
2251
2428
  row.data.push(wordChar);
2252
2429
  }
2253
2430
  else {
2254
- charX = toChar(word.data, charX, row.data);
2431
+ charX = toChar(word.data, charX, row.data, row.isOverflow);
2255
2432
  }
2256
2433
  if (!row.paraEnd && addWordWidth) {
2257
2434
  charX += addWordWidth;
@@ -2278,9 +2455,9 @@ function toWordChar(data, charX, wordChar) {
2278
2455
  });
2279
2456
  return charX;
2280
2457
  }
2281
- function toChar(data, charX, rowData) {
2458
+ function toChar(data, charX, rowData, isOverflow) {
2282
2459
  data.forEach(char => {
2283
- if (char.char !== ' ') {
2460
+ if (isOverflow || char.char !== ' ') {
2284
2461
  char.x = charX;
2285
2462
  rowData.push(char);
2286
2463
  }
@@ -2312,12 +2489,14 @@ function layoutText(drawData, style) {
2312
2489
  for (let i = 0, len = rows.length; i < len; i++) {
2313
2490
  row = rows[i];
2314
2491
  row.x = x;
2315
- switch (textAlign) {
2316
- case 'center':
2317
- row.x += (width - row.width) / 2;
2318
- break;
2319
- case 'right':
2320
- row.x += width - row.width;
2492
+ if (row.width < width || (row.width > width && !__clipText)) {
2493
+ switch (textAlign) {
2494
+ case 'center':
2495
+ row.x += (width - row.width) / 2;
2496
+ break;
2497
+ case 'right':
2498
+ row.x += width - row.width;
2499
+ }
2321
2500
  }
2322
2501
  if (row.paraStart && paraSpacing && i > 0)
2323
2502
  starY += paraSpacing;
@@ -2353,16 +2532,20 @@ function layoutText(drawData, style) {
2353
2532
  bounds.height = realHeight;
2354
2533
  }
2355
2534
 
2356
- function clipText(drawData, style) {
2535
+ function clipText(drawData, style, x, width) {
2536
+ if (!width)
2537
+ return;
2357
2538
  const { rows, overflow } = drawData;
2358
2539
  let { textOverflow } = style;
2359
2540
  rows.splice(overflow);
2360
- if (textOverflow !== 'hide') {
2361
- if (textOverflow === 'ellipsis')
2541
+ if (textOverflow && textOverflow !== 'show') {
2542
+ if (textOverflow === 'hide')
2543
+ textOverflow = '';
2544
+ else if (textOverflow === 'ellipsis')
2362
2545
  textOverflow = '...';
2363
2546
  let char, charRight;
2364
- const ellipsisWidth = Platform.canvas.measureText(textOverflow).width;
2365
- const right = style.x + style.width - ellipsisWidth;
2547
+ const ellipsisWidth = textOverflow ? Platform.canvas.measureText(textOverflow).width : 0;
2548
+ const right = x + width - ellipsisWidth;
2366
2549
  const list = style.textWrap === 'none' ? rows : [rows[overflow - 1]];
2367
2550
  list.forEach(row => {
2368
2551
  if (row.isOverflow && row.data) {
@@ -2409,42 +2592,40 @@ function decorationText(drawData, style) {
2409
2592
  }
2410
2593
 
2411
2594
  const { top, right, bottom, left } = Direction4;
2412
- const TextConvert = {
2413
- getDrawData(content, style) {
2414
- if (typeof content !== 'string')
2415
- content = String(content);
2416
- let x = 0, y = 0;
2417
- let width = style.__getInput('width') || 0;
2418
- let height = style.__getInput('height') || 0;
2419
- const { textDecoration, __font, __padding: padding } = style;
2420
- if (padding) {
2421
- if (width) {
2422
- x = padding[left];
2423
- width -= (padding[right] + padding[left]);
2424
- }
2425
- if (height) {
2426
- y = padding[top];
2427
- height -= (padding[top] + padding[bottom]);
2428
- }
2429
- }
2430
- const drawData = {
2431
- bounds: { x, y, width, height },
2432
- rows: [],
2433
- paraNumber: 0,
2434
- font: Platform.canvas.font = __font
2435
- };
2436
- createRows(drawData, content, style);
2437
- if (padding)
2438
- padAutoText(padding, drawData, style, width, height);
2439
- layoutText(drawData, style);
2440
- layoutChar(drawData, style, width);
2441
- if (drawData.overflow)
2442
- clipText(drawData, style);
2443
- if (textDecoration !== 'none')
2444
- decorationText(drawData, style);
2445
- return drawData;
2446
- }
2447
- };
2595
+ function getDrawData(content, style) {
2596
+ if (typeof content !== 'string')
2597
+ content = String(content);
2598
+ let x = 0, y = 0;
2599
+ let width = style.__getInput('width') || 0;
2600
+ let height = style.__getInput('height') || 0;
2601
+ const { textDecoration, __font, __padding: padding } = style;
2602
+ if (padding) {
2603
+ if (width) {
2604
+ x = padding[left];
2605
+ width -= (padding[right] + padding[left]);
2606
+ }
2607
+ if (height) {
2608
+ y = padding[top];
2609
+ height -= (padding[top] + padding[bottom]);
2610
+ }
2611
+ }
2612
+ const drawData = {
2613
+ bounds: { x, y, width, height },
2614
+ rows: [],
2615
+ paraNumber: 0,
2616
+ font: Platform.canvas.font = __font
2617
+ };
2618
+ createRows(drawData, content, style);
2619
+ if (padding)
2620
+ padAutoText(padding, drawData, style, width, height);
2621
+ layoutText(drawData, style);
2622
+ layoutChar(drawData, style, width);
2623
+ if (drawData.overflow)
2624
+ clipText(drawData, style, x, width);
2625
+ if (textDecoration !== 'none')
2626
+ decorationText(drawData, style);
2627
+ return drawData;
2628
+ }
2448
2629
  function padAutoText(padding, drawData, style, width, height) {
2449
2630
  if (!width) {
2450
2631
  switch (style.textAlign) {
@@ -2472,67 +2653,152 @@ function offsetText(drawData, attrName, value) {
2472
2653
  rows[i][attrName] += value;
2473
2654
  }
2474
2655
 
2475
- const ColorConvert = {
2476
- string(color, opacity) {
2477
- if (typeof color === 'string')
2478
- return color;
2479
- let a = color.a === undefined ? 1 : color.a;
2480
- if (opacity)
2481
- a *= opacity;
2482
- const rgb = color.r + ',' + color.g + ',' + color.b;
2483
- return a === 1 ? 'rgb(' + rgb + ')' : 'rgba(' + rgb + ',' + a + ')';
2484
- }
2656
+ const TextConvertModule = {
2657
+ getDrawData
2485
2658
  };
2486
2659
 
2487
- const Export = {
2660
+ function string(color, opacity) {
2661
+ if (typeof color === 'string')
2662
+ return color;
2663
+ let a = color.a === undefined ? 1 : color.a;
2664
+ if (opacity)
2665
+ a *= opacity;
2666
+ const rgb = color.r + ',' + color.g + ',' + color.b;
2667
+ return a === 1 ? 'rgb(' + rgb + ')' : 'rgba(' + rgb + ',' + a + ')';
2668
+ }
2669
+
2670
+ const ColorConvertModule = {
2671
+ string
2672
+ };
2673
+
2674
+ const { setPoint, addPoint, toBounds } = TwoPointBoundsHelper;
2675
+ function getTrimBounds(canvas) {
2676
+ const { width, height } = canvas.view;
2677
+ const { data } = canvas.context.getImageData(0, 0, width, height);
2678
+ let x, y, pointBounds, index = 0;
2679
+ for (let i = 0; i < data.length; i += 4) {
2680
+ if (data[i + 3] !== 0) {
2681
+ x = index % width;
2682
+ y = (index - x) / width;
2683
+ pointBounds ? addPoint(pointBounds, x, y) : setPoint(pointBounds = {}, x, y);
2684
+ }
2685
+ index++;
2686
+ }
2687
+ const bounds = new Bounds();
2688
+ toBounds(pointBounds, bounds);
2689
+ return bounds.scale(1 / canvas.pixelRatio).ceil();
2690
+ }
2691
+
2692
+ const ExportModule = {
2488
2693
  export(leaf, filename, options) {
2489
- Export.running = true;
2694
+ this.running = true;
2695
+ const fileType = FileHelper.fileType(filename);
2696
+ options = FileHelper.getExportOptions(options);
2490
2697
  return addTask((success) => new Promise((resolve) => {
2698
+ const over = (result) => {
2699
+ success(result);
2700
+ resolve();
2701
+ this.running = false;
2702
+ };
2703
+ const { toURL } = Platform;
2704
+ const { download } = Platform.origin;
2705
+ if (filename === 'json') {
2706
+ return over({ data: leaf.toJSON(options.json) });
2707
+ }
2708
+ else if (fileType === 'json') {
2709
+ download(toURL(JSON.stringify(leaf.toJSON(options.json)), 'text'), filename);
2710
+ return over({ data: true });
2711
+ }
2712
+ if (filename === 'svg') {
2713
+ return over({ data: leaf.toSVG() });
2714
+ }
2715
+ else if (fileType === 'svg') {
2716
+ download(toURL(leaf.toSVG(), 'svg'), filename);
2717
+ return over({ data: true });
2718
+ }
2491
2719
  const { leafer } = leaf;
2492
2720
  if (leafer) {
2721
+ checkLazy(leaf);
2493
2722
  leafer.waitViewCompleted(() => __awaiter(this, void 0, void 0, function* () {
2494
- let quality, blob;
2495
- let { canvas } = leafer;
2496
- let { unreal } = canvas;
2497
- if (unreal) {
2498
- canvas = canvas.getSameCanvas();
2499
- canvas.backgroundColor = leafer.config.fill;
2500
- leafer.__render(canvas, {});
2723
+ let renderBounds, trimBounds, scaleX = 1, scaleY = 1;
2724
+ const { worldTransform, isLeafer, isFrame } = leaf;
2725
+ const { slice, trim, onCanvas } = options;
2726
+ let scale = options.scale || 1;
2727
+ let pixelRatio = options.pixelRatio || 1;
2728
+ const smooth = options.smooth === undefined ? leafer.config.smooth : options.smooth;
2729
+ const contextSettings = options.contextSettings || leafer.config.contextSettings;
2730
+ if (leaf.isApp) {
2731
+ scale *= pixelRatio;
2732
+ pixelRatio = leaf.app.pixelRatio;
2501
2733
  }
2502
- switch (typeof options) {
2503
- case 'object':
2504
- if (options.quality)
2505
- quality = options.quality;
2506
- if (options.blob)
2507
- blob = true;
2508
- break;
2509
- case 'number':
2510
- quality = options;
2511
- break;
2512
- case 'boolean':
2513
- blob = options;
2734
+ const screenshot = options.screenshot || leaf.isApp;
2735
+ const fill = (isLeafer && screenshot) ? (options.fill === undefined ? leaf.fill : options.fill) : options.fill;
2736
+ const needFill = FileHelper.isOpaqueImage(filename) || fill, matrix = new Matrix();
2737
+ if (screenshot) {
2738
+ renderBounds = screenshot === true ? (isLeafer ? leafer.canvas.bounds : leaf.worldRenderBounds) : screenshot;
2739
+ }
2740
+ else {
2741
+ let relative = options.relative || (isLeafer ? 'inner' : 'local');
2742
+ scaleX = worldTransform.scaleX;
2743
+ scaleY = worldTransform.scaleY;
2744
+ switch (relative) {
2745
+ case 'inner':
2746
+ matrix.set(worldTransform);
2747
+ break;
2748
+ case 'local':
2749
+ matrix.set(worldTransform).divide(leaf.localTransform);
2750
+ scaleX /= leaf.scaleX;
2751
+ scaleY /= leaf.scaleY;
2752
+ break;
2753
+ case 'world':
2754
+ scaleX = 1;
2755
+ scaleY = 1;
2756
+ break;
2757
+ case 'page':
2758
+ relative = leaf.leafer;
2759
+ default:
2760
+ matrix.set(worldTransform).divide(leaf.getTransform(relative));
2761
+ const l = relative.worldTransform;
2762
+ scaleX /= scaleX / l.scaleX;
2763
+ scaleY /= scaleY / l.scaleY;
2764
+ }
2765
+ renderBounds = leaf.getBounds('render', relative);
2514
2766
  }
2515
- let data;
2516
- if (filename.includes('.')) {
2517
- data = yield canvas.saveAs(filename, quality);
2767
+ const { x, y, width, height } = new Bounds(renderBounds).scale(scale);
2768
+ let canvas = Creator.canvas({ width: Math.round(width), height: Math.round(height), pixelRatio, smooth, contextSettings });
2769
+ const renderOptions = { matrix: matrix.scale(1 / scale).invert().translate(-x, -y).withScale(1 / scaleX * scale, 1 / scaleY * scale) };
2770
+ if (slice) {
2771
+ leaf = leafer;
2772
+ renderOptions.bounds = canvas.bounds;
2518
2773
  }
2519
- else if (blob) {
2520
- data = yield canvas.toBlob(filename, quality);
2774
+ canvas.save();
2775
+ if (isFrame && fill !== undefined) {
2776
+ const oldFill = leaf.get('fill');
2777
+ leaf.fill = '';
2778
+ leaf.__render(canvas, renderOptions);
2779
+ leaf.fill = oldFill;
2521
2780
  }
2522
2781
  else {
2523
- data = yield canvas.toDataURL(filename, quality);
2782
+ leaf.__render(canvas, renderOptions);
2783
+ }
2784
+ canvas.restore();
2785
+ if (trim) {
2786
+ trimBounds = getTrimBounds(canvas);
2787
+ const old = canvas, { width, height } = trimBounds;
2788
+ const config = { x: 0, y: 0, width, height, pixelRatio };
2789
+ canvas = Creator.canvas(config);
2790
+ canvas.copyWorld(old, trimBounds, config);
2524
2791
  }
2525
- success({ data });
2526
- resolve();
2527
- Export.running = false;
2528
- if (unreal)
2529
- canvas.recycle();
2792
+ if (needFill)
2793
+ canvas.fillWorld(canvas.bounds, fill || '#FFFFFF', 'destination-over');
2794
+ if (onCanvas)
2795
+ onCanvas(canvas);
2796
+ const data = filename === 'canvas' ? canvas : yield canvas.export(filename, options);
2797
+ over({ data, width: canvas.pixelWidth, height: canvas.pixelHeight, renderBounds, trimBounds });
2530
2798
  }));
2531
2799
  }
2532
2800
  else {
2533
- success({ data: false });
2534
- resolve();
2535
- Export.running = false;
2801
+ over({ data: false });
2536
2802
  }
2537
2803
  }));
2538
2804
  }
@@ -2545,13 +2811,64 @@ function addTask(task) {
2545
2811
  tasker.add(() => __awaiter(this, void 0, void 0, function* () { return yield task(resolve); }), { parallel: false });
2546
2812
  });
2547
2813
  }
2814
+ function checkLazy(leaf) {
2815
+ if (leaf.__.__needComputePaint)
2816
+ leaf.__.__computePaint();
2817
+ if (leaf.isBranch)
2818
+ leaf.children.forEach(child => checkLazy(child));
2819
+ }
2820
+
2821
+ const canvas = LeaferCanvasBase.prototype;
2822
+ const debug = Debug.get('@leafer-ui/export');
2823
+ canvas.export = function (filename, options) {
2824
+ const { quality, blob } = FileHelper.getExportOptions(options);
2825
+ if (filename.includes('.')) {
2826
+ return this.saveAs(filename, quality);
2827
+ }
2828
+ else if (blob) {
2829
+ return this.toBlob(filename, quality);
2830
+ }
2831
+ else {
2832
+ return this.toDataURL(filename, quality);
2833
+ }
2834
+ };
2835
+ canvas.toBlob = function (type, quality) {
2836
+ return new Promise((resolve) => {
2837
+ Platform.origin.canvasToBolb(this.view, type, quality).then((blob) => {
2838
+ resolve(blob);
2839
+ }).catch((e) => {
2840
+ debug.error(e);
2841
+ resolve(null);
2842
+ });
2843
+ });
2844
+ };
2845
+ canvas.toDataURL = function (type, quality) {
2846
+ return Platform.origin.canvasToDataURL(this.view, type, quality);
2847
+ };
2848
+ canvas.saveAs = function (filename, quality) {
2849
+ return new Promise((resolve) => {
2850
+ Platform.origin.canvasSaveAs(this.view, filename, quality).then(() => {
2851
+ resolve(true);
2852
+ }).catch((e) => {
2853
+ debug.error(e);
2854
+ resolve(false);
2855
+ });
2856
+ });
2857
+ };
2548
2858
 
2549
- Object.assign(Paint, UIPaint);
2550
- Object.assign(Effect, UIEffect);
2551
- Object.assign(TextConvert$1, TextConvert);
2552
- Object.assign(ColorConvert$1, ColorConvert);
2553
- Object.assign(Export$2, Export);
2859
+ Object.assign(TextConvert, TextConvertModule);
2860
+ Object.assign(ColorConvert, ColorConvertModule);
2861
+ Object.assign(Paint, PaintModule);
2862
+ Object.assign(PaintImage, PaintImageModule);
2863
+ Object.assign(PaintGradient, PaintGradientModule);
2864
+ Object.assign(Effect, EffectModule);
2865
+ Object.assign(Export, ExportModule);
2554
2866
 
2867
+ Object.assign(Creator, {
2868
+ interaction: (target, canvas, selector, options) => new Interaction(target, canvas, selector, options),
2869
+ hitCanvas: (options, manager) => new LeaferCanvas(options, manager),
2870
+ hitCanvasManager: () => new HitCanvasManager()
2871
+ });
2555
2872
  try {
2556
2873
  useCanvas('wx', wx);
2557
2874
  }