leafer-ui 1.0.0-rc.9 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/web.esm.js CHANGED
@@ -1,8 +1,269 @@
1
- import { LeafList, DataHelper, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, Bounds, LeafBoundsHelper, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, Platform, AnimateEvent, ResizeEvent, BoundsHelper, Creator, LeaferCanvasBase, Cursor, canvasSizeAttrs, canvasPatch, InteractionHelper, MathHelper, InteractionBase, LeaferImage, FileHelper, MatrixHelper, ImageEvent, PointHelper, Direction4, TaskProcessor } from '@leafer/core';
1
+ import { Debug, LeaferCanvasBase, Platform, DataHelper, canvasSizeAttrs, ResizeEvent, canvasPatch, Creator, LeaferImage, defineKey, FileHelper, LeafList, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, Bounds, LeafBoundsHelper, LeafLevelList, LayoutEvent, Run, ImageManager, AnimateEvent, BoundsHelper, Answer, MathHelper, 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 } from '@leafer-ui/core';
4
+ import { InteractionHelper, InteractionBase, Cursor, HitCanvasManager } 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
+ const debug$3 = Debug.get('LeaferCanvas');
9
+ class LeaferCanvas extends LeaferCanvasBase {
10
+ set zIndex(zIndex) {
11
+ const { style } = this.view;
12
+ style.zIndex = zIndex;
13
+ this.setAbsolute(this.view);
14
+ }
15
+ set childIndex(index) {
16
+ const { view, parentView } = this;
17
+ if (view && parentView) {
18
+ const beforeNode = parentView.children[index];
19
+ if (beforeNode) {
20
+ this.setAbsolute(beforeNode);
21
+ parentView.insertBefore(view, beforeNode);
22
+ }
23
+ else {
24
+ parentView.appendChild(beforeNode);
25
+ }
26
+ }
27
+ }
28
+ init() {
29
+ const { config } = this;
30
+ const view = config.view || config.canvas;
31
+ view ? this.__createViewFrom(view) : this.__createView();
32
+ const { style } = this.view;
33
+ style.display || (style.display = 'block');
34
+ this.parentView = this.view.parentElement;
35
+ if (this.parentView) {
36
+ const pStyle = this.parentView.style;
37
+ pStyle.webkitUserSelect = pStyle.userSelect = 'none';
38
+ }
39
+ if (Platform.syncDomFont && !this.parentView) {
40
+ style.display = 'none';
41
+ document.body.appendChild(this.view);
42
+ }
43
+ this.__createContext();
44
+ if (!this.autoLayout)
45
+ this.resize(config);
46
+ }
47
+ set backgroundColor(color) { this.view.style.backgroundColor = color; }
48
+ get backgroundColor() { return this.view.style.backgroundColor; }
49
+ set hittable(hittable) { this.view.style.pointerEvents = hittable ? 'auto' : 'none'; }
50
+ get hittable() { return this.view.style.pointerEvents !== 'none'; }
51
+ __createView() {
52
+ this.view = document.createElement('canvas');
53
+ }
54
+ __createViewFrom(inputView) {
55
+ let find = (typeof inputView === 'string') ? document.getElementById(inputView) : inputView;
56
+ if (find) {
57
+ if (find instanceof HTMLCanvasElement) {
58
+ this.view = find;
59
+ }
60
+ else {
61
+ let parent = find;
62
+ if (find === window || find === document) {
63
+ const div = document.createElement('div');
64
+ const { style } = div;
65
+ style.position = 'absolute';
66
+ style.top = style.bottom = style.left = style.right = '0px';
67
+ document.body.appendChild(div);
68
+ parent = div;
69
+ }
70
+ this.__createView();
71
+ const view = this.view;
72
+ if (parent.hasChildNodes()) {
73
+ this.setAbsolute(view);
74
+ parent.style.position || (parent.style.position = 'relative');
75
+ }
76
+ parent.appendChild(view);
77
+ }
78
+ }
79
+ else {
80
+ debug$3.error(`no id: ${inputView}`);
81
+ this.__createView();
82
+ }
83
+ }
84
+ setAbsolute(view) {
85
+ const { style } = view;
86
+ style.position = 'absolute';
87
+ style.top = style.left = '0px';
88
+ }
89
+ updateViewSize() {
90
+ const { width, height, pixelRatio } = this;
91
+ const { style } = this.view;
92
+ style.width = width + 'px';
93
+ style.height = height + 'px';
94
+ this.view.width = Math.ceil(width * pixelRatio);
95
+ this.view.height = Math.ceil(height * pixelRatio);
96
+ }
97
+ updateClientBounds() {
98
+ this.clientBounds = this.view.getBoundingClientRect();
99
+ }
100
+ startAutoLayout(autoBounds, listener) {
101
+ this.resizeListener = listener;
102
+ if (autoBounds) {
103
+ this.autoBounds = autoBounds;
104
+ try {
105
+ this.resizeObserver = new ResizeObserver((entries) => {
106
+ this.updateClientBounds();
107
+ for (const entry of entries)
108
+ this.checkAutoBounds(entry.contentRect);
109
+ });
110
+ const parent = this.parentView;
111
+ if (parent) {
112
+ this.resizeObserver.observe(parent);
113
+ this.checkAutoBounds(parent.getBoundingClientRect());
114
+ }
115
+ else {
116
+ this.checkAutoBounds(this.view);
117
+ debug$3.warn('no parent');
118
+ }
119
+ }
120
+ catch (_a) {
121
+ this.imitateResizeObserver();
122
+ }
123
+ }
124
+ else {
125
+ window.addEventListener('resize', () => {
126
+ const pixelRatio = Platform.devicePixelRatio;
127
+ if (this.pixelRatio !== pixelRatio) {
128
+ const { width, height } = this;
129
+ this.emitResize({ width, height, pixelRatio });
130
+ }
131
+ });
132
+ }
133
+ }
134
+ imitateResizeObserver() {
135
+ if (this.autoLayout) {
136
+ if (this.parentView)
137
+ this.checkAutoBounds(this.parentView.getBoundingClientRect());
138
+ Platform.requestRender(this.imitateResizeObserver.bind(this));
139
+ }
140
+ }
141
+ checkAutoBounds(parentSize) {
142
+ const view = this.view;
143
+ const { x, y, width, height } = this.autoBounds.getBoundsFrom(parentSize);
144
+ const size = { width, height, pixelRatio: Platform.devicePixelRatio };
145
+ if (!this.isSameSize(size)) {
146
+ const { style } = view;
147
+ style.marginLeft = x + 'px';
148
+ style.marginTop = y + 'px';
149
+ this.emitResize(size);
150
+ }
151
+ }
152
+ stopAutoLayout() {
153
+ this.autoLayout = false;
154
+ this.resizeListener = null;
155
+ if (this.resizeObserver) {
156
+ this.resizeObserver.disconnect();
157
+ this.resizeObserver = null;
158
+ }
159
+ }
160
+ emitResize(size) {
161
+ const oldSize = {};
162
+ DataHelper.copyAttrs(oldSize, this, canvasSizeAttrs);
163
+ this.resize(size);
164
+ if (this.width !== undefined)
165
+ this.resizeListener(new ResizeEvent(size, oldSize));
166
+ }
167
+ unrealCanvas() {
168
+ if (!this.unreal && this.parentView) {
169
+ const view = this.view;
170
+ if (view)
171
+ view.remove();
172
+ this.view = this.parentView;
173
+ this.unreal = true;
174
+ }
175
+ }
176
+ destroy() {
177
+ if (this.view) {
178
+ this.stopAutoLayout();
179
+ if (!this.unreal) {
180
+ const view = this.view;
181
+ if (view.parentElement)
182
+ view.remove();
183
+ }
184
+ super.destroy();
185
+ }
186
+ }
187
+ }
188
+
189
+ canvasPatch(CanvasRenderingContext2D.prototype);
190
+ canvasPatch(Path2D.prototype);
191
+
192
+ const { mineType, fileType } = FileHelper;
193
+ Object.assign(Creator, {
194
+ canvas: (options, manager) => new LeaferCanvas(options, manager),
195
+ image: (options) => new LeaferImage(options)
196
+ });
197
+ function useCanvas(_canvasType, _power) {
198
+ Platform.origin = {
199
+ createCanvas(width, height) {
200
+ const canvas = document.createElement('canvas');
201
+ canvas.width = width;
202
+ canvas.height = height;
203
+ return canvas;
204
+ },
205
+ canvasToDataURL: (canvas, type, quality) => canvas.toDataURL(mineType(type), quality),
206
+ canvasToBolb: (canvas, type, quality) => new Promise((resolve) => canvas.toBlob(resolve, mineType(type), quality)),
207
+ canvasSaveAs: (canvas, filename, quality) => {
208
+ const url = canvas.toDataURL(mineType(fileType(filename)), quality);
209
+ return Platform.origin.download(url, filename);
210
+ },
211
+ download(url, filename) {
212
+ return new Promise((resolve) => {
213
+ let el = document.createElement('a');
214
+ el.href = url;
215
+ el.download = filename;
216
+ document.body.appendChild(el);
217
+ el.click();
218
+ document.body.removeChild(el);
219
+ resolve();
220
+ });
221
+ },
222
+ loadImage(src) {
223
+ return new Promise((resolve, reject) => {
224
+ const img = new Image();
225
+ const { crossOrigin } = Platform.image;
226
+ if (crossOrigin) {
227
+ img.setAttribute('crossOrigin', crossOrigin);
228
+ img.crossOrigin = crossOrigin;
229
+ }
230
+ img.onload = () => { resolve(img); };
231
+ img.onerror = (e) => { reject(e); };
232
+ img.src = Platform.image.getRealURL(src);
233
+ });
234
+ }
235
+ };
236
+ Platform.event = {
237
+ stopDefault(origin) { origin.preventDefault(); },
238
+ stopNow(origin) { origin.stopImmediatePropagation(); },
239
+ stop(origin) { origin.stopPropagation(); }
240
+ };
241
+ Platform.canvas = Creator.canvas();
242
+ Platform.conicGradientSupport = !!Platform.canvas.context.createConicGradient;
243
+ }
244
+ Platform.name = 'web';
245
+ Platform.isMobile = 'ontouchstart' in window;
246
+ Platform.requestRender = function (render) { window.requestAnimationFrame(render); };
247
+ defineKey(Platform, 'devicePixelRatio', { get() { return Math.max(1, devicePixelRatio); } });
248
+ const { userAgent } = navigator;
249
+ if (userAgent.indexOf("Firefox") > -1) {
250
+ Platform.conicGradientRotate90 = true;
251
+ Platform.intWheelDeltaY = true;
252
+ Platform.syncDomFont = true;
253
+ }
254
+ else if (userAgent.indexOf("Safari") > -1 && userAgent.indexOf("Chrome") === -1) {
255
+ Platform.fullImageShadow = true;
256
+ }
257
+ if (userAgent.indexOf('Windows') > -1) {
258
+ Platform.os = 'Windows';
259
+ Platform.intWheelDeltaY = true;
260
+ }
261
+ else if (userAgent.indexOf('Mac') > -1) {
262
+ Platform.os = 'Mac';
263
+ }
264
+ else if (userAgent.indexOf('Linux') > -1) {
265
+ Platform.os = 'Linux';
266
+ }
6
267
 
7
268
  class Watcher {
8
269
  get childrenChanged() { return this.hasAdd || this.hasRemove || this.hasVisible; }
@@ -302,9 +563,11 @@ class Layouter {
302
563
  updateAllChange(target);
303
564
  }
304
565
  addExtra(leaf) {
305
- const block = this.extraBlock || (this.extraBlock = new LayoutBlockData([]));
306
- block.updatedList.add(leaf);
307
- block.beforeBounds.add(leaf.__world);
566
+ if (!this.__updatedList.has(leaf)) {
567
+ const { updatedList, beforeBounds } = this.extraBlock || (this.extraBlock = new LayoutBlockData([]));
568
+ updatedList.length ? beforeBounds.add(leaf.__world) : beforeBounds.set(leaf.__world);
569
+ updatedList.add(leaf);
570
+ }
308
571
  }
309
572
  createBlock(data) {
310
573
  return new LayoutBlockData(data);
@@ -414,6 +677,10 @@ class Renderer {
414
677
  }
415
678
  else {
416
679
  this.requestLayout();
680
+ if (this.ignore) {
681
+ this.ignore = this.rendering = false;
682
+ return;
683
+ }
417
684
  this.emitRender(RenderEvent.BEFORE);
418
685
  if (this.config.usePartRender && this.totalTimes > 1) {
419
686
  this.partRender();
@@ -450,7 +717,7 @@ class Renderer {
450
717
  canvas.clear();
451
718
  }
452
719
  else {
453
- bounds.spread(1 + 1 / this.canvas.pixelRatio).ceil();
720
+ bounds.spread(10 + 1 / this.canvas.pixelRatio).ceil();
454
721
  canvas.clearWorld(bounds, true);
455
722
  canvas.clipWorld(bounds, true);
456
723
  }
@@ -474,14 +741,14 @@ class Renderer {
474
741
  if (Debug.showRepaint)
475
742
  this.canvas.strokeWorld(bounds, 'red');
476
743
  this.target.__render(this.canvas, options);
477
- this.renderBounds = realBounds || bounds;
744
+ this.renderBounds = realBounds = realBounds || bounds;
478
745
  this.renderOptions = options;
479
- this.totalBounds.isEmpty() ? this.totalBounds = this.renderBounds : this.totalBounds.add(this.renderBounds);
746
+ this.totalBounds.isEmpty() ? this.totalBounds = realBounds : this.totalBounds.add(realBounds);
480
747
  if (Debug.showHitView)
481
748
  this.renderHitView(options);
482
749
  if (Debug.showBoundsView)
483
750
  this.renderBoundsView(options);
484
- this.canvas.updateRender();
751
+ this.canvas.updateRender(realBounds);
485
752
  }
486
753
  renderHitView(_options) { }
487
754
  renderBoundsView(_options) { }
@@ -503,12 +770,12 @@ class Renderer {
503
770
  const startTime = Date.now();
504
771
  Platform.requestRender(() => {
505
772
  this.FPS = Math.min(60, Math.ceil(1000 / (Date.now() - startTime)));
506
- if (this.changed) {
507
- if (this.running && this.canvas.view)
773
+ if (this.running) {
774
+ this.target.emit(AnimateEvent.FRAME);
775
+ if (this.changed && this.canvas.view)
508
776
  this.render();
777
+ this.target.emit(RenderEvent.NEXT);
509
778
  }
510
- if (this.running)
511
- this.target.emit(AnimateEvent.FRAME);
512
779
  if (this.target)
513
780
  this.__requestRender();
514
781
  });
@@ -521,9 +788,12 @@ class Renderer {
521
788
  const bounds = new Bounds(0, 0, width, height);
522
789
  if (!bounds.includes(this.target.__world) || this.needFill || !e.samePixelRatio) {
523
790
  this.addBlock(this.canvas.bounds);
524
- this.target.forceUpdate('blendMode');
791
+ this.target.forceUpdate('surface');
792
+ return;
525
793
  }
526
794
  }
795
+ this.addBlock(new Bounds(0, 0, 1, 1));
796
+ this.changed = true;
527
797
  }
528
798
  __onLayoutEnd(event) {
529
799
  if (event.data)
@@ -561,23 +831,13 @@ class Renderer {
561
831
  if (this.target) {
562
832
  this.stop();
563
833
  this.__removeListenEvents();
564
- this.target = null;
565
- this.canvas = null;
566
- this.config = null;
834
+ this.target = this.canvas = this.config = null;
567
835
  }
568
836
  }
569
837
  }
570
838
 
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
839
  const { hitRadiusPoint } = BoundsHelper;
580
- class Pather {
840
+ class Picker {
581
841
  constructor(target, selector) {
582
842
  this.target = target;
583
843
  this.selector = selector;
@@ -589,33 +849,41 @@ class Pather {
589
849
  options = {};
590
850
  const through = options.through || false;
591
851
  const ignoreHittable = options.ignoreHittable || false;
852
+ const target = options.target || this.target;
592
853
  this.exclude = options.exclude || null;
593
854
  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();
855
+ this.findList = new LeafList(options.findList);
856
+ if (!options.findList)
857
+ this.hitBranch(target);
858
+ const { list } = this.findList;
859
+ const leaf = this.getBestMatchLeaf(list, options.bottomList, ignoreHittable);
598
860
  const path = ignoreHittable ? this.getPath(leaf) : this.getHitablePath(leaf);
599
861
  this.clear();
600
- return through ? { path, leaf, throughPath: list.length ? this.getThroughPath(list) : path } : { path, leaf };
862
+ return through ? { path, target: leaf, throughPath: list.length ? this.getThroughPath(list) : path } : { path, target: leaf };
601
863
  }
602
- getBestMatchLeaf() {
603
- const { findList: targets } = this;
604
- if (targets.length > 1) {
864
+ getBestMatchLeaf(list, bottomList, ignoreHittable) {
865
+ if (list.length) {
605
866
  let find;
606
- this.findList = [];
867
+ this.findList = new LeafList();
607
868
  const { x, y } = this.point;
608
869
  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)) {
870
+ for (let i = 0, len = list.length; i < len; i++) {
871
+ find = list[i];
872
+ if (ignoreHittable || LeafHelper.worldHittable(find)) {
612
873
  this.hitChild(find, point);
613
874
  if (this.findList.length)
614
- return this.findList[0];
875
+ return this.findList.list[0];
615
876
  }
616
877
  }
617
878
  }
618
- return targets[0];
879
+ if (bottomList) {
880
+ for (let i = 0, len = bottomList.length; i < len; i++) {
881
+ this.hitChild(bottomList[i].target, this.point, bottomList[i].proxy);
882
+ if (this.findList.length)
883
+ return this.findList.list[0];
884
+ }
885
+ }
886
+ return list[0];
619
887
  }
620
888
  getPath(leaf) {
621
889
  const path = new LeafList();
@@ -627,7 +895,7 @@ class Pather {
627
895
  return path;
628
896
  }
629
897
  getHitablePath(leaf) {
630
- const path = this.getPath(leaf);
898
+ const path = this.getPath(leaf && leaf.hittable ? leaf : null);
631
899
  let item, hittablePath = new LeafList();
632
900
  for (let i = path.list.length - 1; i > -1; i--) {
633
901
  item = path.list[i];
@@ -657,12 +925,15 @@ class Pather {
657
925
  }
658
926
  return throughPath;
659
927
  }
928
+ hitBranch(branch) {
929
+ this.eachFind(branch.children, branch.__onlyHitMask);
930
+ }
660
931
  eachFind(children, hitMask) {
661
932
  let child, hit;
662
933
  const { point } = this, len = children.length;
663
934
  for (let i = len - 1; i > -1; i--) {
664
935
  child = children[i];
665
- if (!child.__.visible || (hitMask && !child.__.isMask))
936
+ if (!child.__.visible || (hitMask && !child.__.mask))
666
937
  continue;
667
938
  hit = child.__.hitRadius ? true : hitRadiusPoint(child.__world, point);
668
939
  if (child.isBranch) {
@@ -678,11 +949,15 @@ class Pather {
678
949
  }
679
950
  }
680
951
  }
681
- hitChild(child, point) {
952
+ hitChild(child, point, proxy) {
682
953
  if (this.exclude && this.exclude.has(child))
683
954
  return;
684
- if (child.__hitWorld(point))
685
- this.findList.push(child);
955
+ if (child.__hitWorld(point)) {
956
+ const { parent } = child;
957
+ if (parent && parent.__hasMask && !child.__.mask && !parent.children.some(item => item.__.mask && item.__hitWorld(point)))
958
+ return;
959
+ this.findList.add(proxy || child);
960
+ }
686
961
  }
687
962
  clear() {
688
963
  this.point = null;
@@ -694,7 +969,8 @@ class Pather {
694
969
  }
695
970
  }
696
971
 
697
- const { Yes, NoAndSkip, YesAndSkip } = AnswerType;
972
+ const { Yes, NoAndSkip, YesAndSkip } = Answer;
973
+ const idCondition = {}, classNameCondition = {}, tagCondition = {};
698
974
  class Selector {
699
975
  constructor(target, userConfig) {
700
976
  this.config = {};
@@ -704,12 +980,13 @@ class Selector {
704
980
  id: (leaf, name) => leaf.id === name ? (this.idMap[name] = leaf, 1) : 0,
705
981
  innerId: (leaf, innerId) => leaf.innerId === innerId ? (this.innerIdMap[innerId] = leaf, 1) : 0,
706
982
  className: (leaf, name) => leaf.className === name ? 1 : 0,
707
- tag: (leaf, name) => leaf.__tag === name ? 1 : 0
983
+ tag: (leaf, name) => leaf.__tag === name ? 1 : 0,
984
+ tags: (leaf, nameMap) => nameMap[leaf.__tag] ? 1 : 0
708
985
  };
709
986
  this.target = target;
710
987
  if (userConfig)
711
988
  this.config = DataHelper.default(userConfig, this.config);
712
- this.pather = new Pather(target, this);
989
+ this.picker = new Picker(target, this);
713
990
  this.__listenEvents();
714
991
  }
715
992
  getBy(condition, branch, one, options) {
@@ -720,12 +997,25 @@ class Selector {
720
997
  case 'string':
721
998
  switch (condition[0]) {
722
999
  case '#':
723
- const leaf = this.getById(condition.substring(1), branch);
724
- return one ? leaf : (leaf ? [leaf] : []);
1000
+ idCondition.id = condition.substring(1), condition = idCondition;
1001
+ break;
725
1002
  case '.':
726
- return this.getByMethod(this.methods.className, branch, one, condition.substring(1));
1003
+ classNameCondition.className = condition.substring(1), condition = classNameCondition;
1004
+ break;
727
1005
  default:
728
- return this.getByMethod(this.methods.tag, branch, one, condition);
1006
+ tagCondition.tag = condition, condition = tagCondition;
1007
+ }
1008
+ case 'object':
1009
+ if (condition.id !== undefined) {
1010
+ const leaf = this.getById(condition.id, branch);
1011
+ return one ? leaf : (leaf ? [leaf] : []);
1012
+ }
1013
+ else if (condition.tag) {
1014
+ const { tag } = condition, isArray = tag instanceof Array;
1015
+ return this.getByMethod(isArray ? this.methods.tags : this.methods.tag, branch, one, isArray ? DataHelper.toMap(tag) : tag);
1016
+ }
1017
+ else {
1018
+ return this.getByMethod(this.methods.className, branch, one, condition.className);
729
1019
  }
730
1020
  case 'function':
731
1021
  return this.getByMethod(condition, branch, one, options);
@@ -734,7 +1024,7 @@ class Selector {
734
1024
  getByPoint(hitPoint, hitRadius, options) {
735
1025
  if (Platform.name === 'node')
736
1026
  this.target.emit(LayoutEvent.CHECK_UPDATE);
737
- return this.pather.getByPoint(hitPoint, hitRadius, options);
1027
+ return this.picker.getByPoint(hitPoint, hitRadius, options);
738
1028
  }
739
1029
  getByInnerId(innerId, branch) {
740
1030
  const cache = this.innerIdMap[innerId];
@@ -810,7 +1100,7 @@ class Selector {
810
1100
  destroy() {
811
1101
  if (this.__eventIds.length) {
812
1102
  this.__removeListenEvents();
813
- this.pather.destroy();
1103
+ this.picker.destroy();
814
1104
  this.findLeaf = null;
815
1105
  this.innerIdMap = {};
816
1106
  this.idMap = {};
@@ -826,194 +1116,29 @@ Object.assign(Creator, {
826
1116
  });
827
1117
  Platform.layout = Layouter.fullLayout;
828
1118
 
829
- const debug = Debug.get('LeaferCanvas');
830
- class LeaferCanvas extends LeaferCanvasBase {
831
- init() {
832
- const { view } = this.config;
833
- view ? this.__createViewFrom(view) : this.__createView();
834
- const { style } = this.view;
835
- style.display || (style.display = 'block');
836
- this.parentView = this.view.parentElement;
837
- if (this.parentView)
838
- this.parentView.style.userSelect = 'none';
839
- if (Platform.syncDomFont && !this.parentView) {
840
- this.view.style.display = 'none';
841
- document.body.appendChild(this.view);
1119
+ const PointerEventHelper = {
1120
+ convert(e, local) {
1121
+ const base = InteractionHelper.getBase(e);
1122
+ const data = Object.assign(Object.assign({}, base), { x: local.x, y: local.y, width: e.width, height: e.height, pointerType: e.pointerType, pressure: e.pressure });
1123
+ if (data.pointerType === 'pen') {
1124
+ data.tangentialPressure = e.tangentialPressure;
1125
+ data.tiltX = e.tiltX;
1126
+ data.tiltY = e.tiltY;
1127
+ data.twist = e.twist;
842
1128
  }
843
- this.__createContext();
844
- if (!this.autoLayout)
845
- this.resize(this.config);
846
- }
847
- set backgroundColor(color) { this.view.style.backgroundColor = color; }
848
- get backgroundColor() { return this.view.style.backgroundColor; }
849
- set hittable(hittable) { this.view.style.pointerEvents = hittable ? 'auto' : 'none'; }
850
- get hittable() { return this.view.style.pointerEvents !== 'none'; }
851
- __createView() {
852
- this.view = document.createElement('canvas');
853
- }
854
- setCursor(cursor) {
855
- const list = [];
856
- this.eachCursor(cursor, list);
857
- if (typeof list[list.length - 1] === 'object')
858
- list.push('default');
859
- this.view.style.cursor = list.map(item => (typeof item === 'object') ? `url(${item.url}) ${item.x || 0} ${item.y || 0}` : item).join(',');
860
- }
861
- eachCursor(cursor, list, level = 0) {
862
- level++;
863
- if (cursor instanceof Array) {
864
- cursor.forEach(item => this.eachCursor(item, list, level));
865
- }
866
- else {
867
- const custom = typeof cursor === 'string' && Cursor.get(cursor);
868
- if (custom && level < 2) {
869
- this.eachCursor(custom, list, level);
870
- }
871
- else {
872
- list.push(cursor);
873
- }
874
- }
875
- }
876
- __createViewFrom(inputView) {
877
- let find = (typeof inputView === 'string') ? document.getElementById(inputView) : inputView;
878
- if (find) {
879
- if (find instanceof HTMLCanvasElement) {
880
- this.view = find;
881
- }
882
- else {
883
- let parent = find;
884
- if (find === window || find === document) {
885
- const div = document.createElement('div');
886
- const { style } = div;
887
- style.position = 'absolute';
888
- style.top = style.bottom = style.left = style.right = '0px';
889
- document.body.appendChild(div);
890
- parent = div;
891
- }
892
- this.__createView();
893
- const view = this.view;
894
- if (parent.hasChildNodes()) {
895
- const { style } = view;
896
- style.position = 'absolute';
897
- style.top = style.left = '0px';
898
- parent.style.position || (parent.style.position = 'relative');
899
- }
900
- parent.appendChild(view);
901
- }
902
- }
903
- else {
904
- debug.error(`no id: ${inputView}`);
905
- this.__createView();
906
- }
907
- }
908
- updateViewSize() {
909
- const { width, height, pixelRatio } = this;
910
- const { style } = this.view;
911
- style.width = width + 'px';
912
- style.height = height + 'px';
913
- this.view.width = width * pixelRatio;
914
- this.view.height = height * pixelRatio;
915
- }
916
- updateClientBounds() {
917
- this.clientBounds = this.view.getBoundingClientRect();
918
- }
919
- startAutoLayout(autoBounds, listener) {
920
- this.autoBounds = autoBounds;
921
- this.resizeListener = listener;
922
- try {
923
- this.resizeObserver = new ResizeObserver((entries) => {
924
- this.updateClientBounds();
925
- for (const entry of entries)
926
- this.checkAutoBounds(entry.contentRect);
927
- });
928
- const parent = this.parentView;
929
- if (parent) {
930
- this.resizeObserver.observe(parent);
931
- this.checkAutoBounds(parent.getBoundingClientRect());
932
- }
933
- }
934
- catch (_a) {
935
- this.imitateResizeObserver();
936
- }
937
- }
938
- imitateResizeObserver() {
939
- if (this.autoLayout) {
940
- if (this.parentView)
941
- this.checkAutoBounds(this.parentView.getBoundingClientRect());
942
- Platform.requestRender(this.imitateResizeObserver.bind(this));
943
- }
944
- }
945
- checkAutoBounds(parentSize) {
946
- const view = this.view;
947
- const { x, y, width, height } = this.autoBounds.getBoundsFrom(parentSize);
948
- if (width !== this.width || height !== this.height) {
949
- const { style } = view;
950
- const { pixelRatio } = this;
951
- style.marginLeft = x + 'px';
952
- style.marginTop = y + 'px';
953
- const size = { width, height, pixelRatio };
954
- const oldSize = {};
955
- DataHelper.copyAttrs(oldSize, this, canvasSizeAttrs);
956
- this.resize(size);
957
- if (this.width !== undefined)
958
- this.resizeListener(new ResizeEvent(size, oldSize));
959
- }
960
- }
961
- stopAutoLayout() {
962
- this.autoLayout = false;
963
- this.resizeListener = null;
964
- if (this.resizeObserver) {
965
- this.resizeObserver.disconnect();
966
- this.resizeObserver = null;
967
- }
968
- }
969
- unrealCanvas() {
970
- if (!this.unreal && this.parentView) {
971
- const view = this.view;
972
- if (view)
973
- view.remove();
974
- this.view = this.parentView;
975
- this.unreal = true;
976
- }
977
- }
978
- destroy() {
979
- if (this.view) {
980
- this.stopAutoLayout();
981
- if (!this.unreal) {
982
- const view = this.view;
983
- if (view.parentElement)
984
- view.remove();
985
- }
986
- super.destroy();
987
- }
988
- }
989
- }
990
-
991
- canvasPatch(CanvasRenderingContext2D.prototype);
992
- canvasPatch(Path2D.prototype);
993
-
994
- const PointerEventHelper = {
995
- convert(e, local) {
996
- const base = InteractionHelper.getBase(e);
997
- const data = Object.assign(Object.assign({}, base), { x: local.x, y: local.y, width: e.width, height: e.height, pointerType: e.pointerType, pressure: e.pressure });
998
- if (data.pointerType === 'pen') {
999
- data.tangentialPressure = e.tangentialPressure;
1000
- data.tiltX = e.tiltX;
1001
- data.tiltY = e.tiltY;
1002
- data.twist = e.twist;
1003
- }
1004
- return data;
1005
- },
1006
- convertMouse(e, local) {
1007
- const base = InteractionHelper.getBase(e);
1008
- return Object.assign(Object.assign({}, base), { x: local.x, y: local.y, width: 1, height: 1, pointerType: 'mouse', pressure: 0.5 });
1009
- },
1010
- convertTouch(e, local) {
1011
- const touch = PointerEventHelper.getTouch(e);
1012
- const base = InteractionHelper.getBase(e);
1013
- return Object.assign(Object.assign({}, base), { x: local.x, y: local.y, width: 1, height: 1, pointerType: 'touch', pressure: touch.force });
1014
- },
1015
- getTouch(e) {
1016
- return e.targetTouches[0] || e.changedTouches[0];
1129
+ return data;
1130
+ },
1131
+ convertMouse(e, local) {
1132
+ const base = InteractionHelper.getBase(e);
1133
+ return Object.assign(Object.assign({}, base), { x: local.x, y: local.y, width: 1, height: 1, pointerType: 'mouse', pressure: 0.5 });
1134
+ },
1135
+ convertTouch(e, local) {
1136
+ const touch = PointerEventHelper.getTouch(e);
1137
+ const base = InteractionHelper.getBase(e);
1138
+ return Object.assign(Object.assign({}, base), { x: local.x, y: local.y, width: 1, height: 1, pointerType: 'touch', multiTouch: e.touches.length > 1, pressure: touch.force });
1139
+ },
1140
+ getTouch(e) {
1141
+ return e.targetTouches[0] || e.changedTouches[0];
1017
1142
  }
1018
1143
  };
1019
1144
 
@@ -1047,7 +1172,7 @@ const WheelEventHelper = {
1047
1172
  if (zoom) {
1048
1173
  zoomSpeed = MathHelper.within(zoomSpeed, 0, 1);
1049
1174
  const min = e.deltaY ? config.delta.y : config.delta.x;
1050
- scale = 1 - delta / (min * 25 * (1 - zoomSpeed) + 10);
1175
+ scale = 1 - delta / (min * 4) * zoomSpeed;
1051
1176
  if (scale < 0.5)
1052
1177
  scale = 0.5;
1053
1178
  if (scale >= 1.5)
@@ -1115,12 +1240,6 @@ class Interaction extends InteractionBase {
1115
1240
  this.windowEvents = {};
1116
1241
  }
1117
1242
  }
1118
- getLocal(p, updateClient) {
1119
- if (updateClient)
1120
- this.canvas.updateClientBounds();
1121
- const { clientBounds } = this.canvas;
1122
- return { x: p.clientX - clientBounds.x, y: p.clientY - clientBounds.y };
1123
- }
1124
1243
  getTouches(touches) {
1125
1244
  const list = [];
1126
1245
  for (let i = 0, len = touches.length; i < len; i++) {
@@ -1148,6 +1267,8 @@ class Interaction extends InteractionBase {
1148
1267
  this.keyUp(KeyEventHelper.convert(e));
1149
1268
  }
1150
1269
  onContextMenu(e) {
1270
+ if (this.config.pointer.preventDefaultMenu)
1271
+ e.preventDefault();
1151
1272
  this.menu(PointerEventHelper.convert(e, this.getLocal(e)));
1152
1273
  }
1153
1274
  onScroll() {
@@ -1155,21 +1276,21 @@ class Interaction extends InteractionBase {
1155
1276
  }
1156
1277
  onPointerDown(e) {
1157
1278
  this.preventDefaultPointer(e);
1158
- this.usePointer || (this.usePointer = true);
1159
- if (this.useMultiTouch)
1279
+ if (this.config.pointer.touch || this.useMultiTouch)
1160
1280
  return;
1281
+ this.usePointer || (this.usePointer = true);
1161
1282
  this.pointerDown(PointerEventHelper.convert(e, this.getLocal(e)));
1162
1283
  }
1163
1284
  onPointerMove(e) {
1164
- this.usePointer || (this.usePointer = true);
1165
- if (this.useMultiTouch || this.preventWindowPointer(e))
1285
+ if (this.config.pointer.touch || this.useMultiTouch || this.preventWindowPointer(e))
1166
1286
  return;
1287
+ this.usePointer || (this.usePointer = true);
1167
1288
  this.pointerMove(PointerEventHelper.convert(e, this.getLocal(e, true)));
1168
1289
  }
1169
1290
  onPointerUp(e) {
1170
1291
  if (this.downData)
1171
1292
  this.preventDefaultPointer(e);
1172
- if (this.useMultiTouch || this.preventWindowPointer(e))
1293
+ if (this.config.pointer.touch || this.useMultiTouch || this.preventWindowPointer(e))
1173
1294
  return;
1174
1295
  this.pointerUp(PointerEventHelper.convert(e, this.getLocal(e)));
1175
1296
  }
@@ -1239,7 +1360,7 @@ class Interaction extends InteractionBase {
1239
1360
  this.pointerCancel();
1240
1361
  }
1241
1362
  multiTouchStart(e) {
1242
- this.useMultiTouch = (e.touches.length >= 2);
1363
+ this.useMultiTouch = (e.touches.length > 1);
1243
1364
  this.touches = this.useMultiTouch ? this.getTouches(e.touches) : undefined;
1244
1365
  if (this.useMultiTouch)
1245
1366
  this.pointerCancel();
@@ -1277,17 +1398,23 @@ class Interaction extends InteractionBase {
1277
1398
  onWheel(e) {
1278
1399
  this.preventDefaultWheel(e);
1279
1400
  const { wheel } = this.config;
1401
+ if (wheel.disabled)
1402
+ return;
1280
1403
  const scale = wheel.getScale ? wheel.getScale(e, wheel) : WheelEventHelper.getScale(e, wheel);
1281
1404
  const local = this.getLocal(e);
1282
1405
  const eventBase = InteractionHelper.getBase(e);
1283
1406
  scale !== 1 ? this.zoom(getZoomEventData(local, scale, eventBase)) : this.move(getMoveEventData(local, wheel.getMove ? wheel.getMove(e, wheel) : WheelEventHelper.getMove(e, wheel), eventBase));
1284
1407
  }
1285
1408
  onGesturestart(e) {
1409
+ if (this.useMultiTouch)
1410
+ return;
1286
1411
  this.preventDefaultWheel(e);
1287
1412
  this.lastGestureScale = 1;
1288
1413
  this.lastGestureRotation = 0;
1289
1414
  }
1290
1415
  onGesturechange(e) {
1416
+ if (this.useMultiTouch)
1417
+ return;
1291
1418
  this.preventDefaultWheel(e);
1292
1419
  const local = this.getLocal(e);
1293
1420
  const eventBase = InteractionHelper.getBase(e);
@@ -1301,9 +1428,34 @@ class Interaction extends InteractionBase {
1301
1428
  this.lastGestureRotation = e.rotation;
1302
1429
  }
1303
1430
  onGestureend(e) {
1431
+ if (this.useMultiTouch)
1432
+ return;
1304
1433
  this.preventDefaultWheel(e);
1305
1434
  this.transformEnd();
1306
1435
  }
1436
+ setCursor(cursor) {
1437
+ super.setCursor(cursor);
1438
+ const list = [];
1439
+ this.eachCursor(cursor, list);
1440
+ if (typeof list[list.length - 1] === 'object')
1441
+ list.push('default');
1442
+ this.canvas.view.style.cursor = list.map(item => (typeof item === 'object') ? `url(${item.url}) ${item.x || 0} ${item.y || 0}` : item).join(',');
1443
+ }
1444
+ eachCursor(cursor, list, level = 0) {
1445
+ level++;
1446
+ if (cursor instanceof Array) {
1447
+ cursor.forEach(item => this.eachCursor(item, list, level));
1448
+ }
1449
+ else {
1450
+ const custom = typeof cursor === 'string' && Cursor.get(cursor);
1451
+ if (custom && level < 2) {
1452
+ this.eachCursor(custom, list, level);
1453
+ }
1454
+ else {
1455
+ list.push(cursor);
1456
+ }
1457
+ }
1458
+ }
1307
1459
  destroy() {
1308
1460
  if (this.view) {
1309
1461
  super.destroy();
@@ -1313,151 +1465,381 @@ class Interaction extends InteractionBase {
1313
1465
  }
1314
1466
  }
1315
1467
 
1316
- const { mineType, fileType } = FileHelper;
1317
- Object.assign(Creator, {
1318
- canvas: (options, manager) => new LeaferCanvas(options, manager),
1319
- image: (options) => new LeaferImage(options),
1320
- hitCanvas: (options, manager) => new LeaferCanvas(options, manager),
1321
- interaction: (target, canvas, selector, options) => new Interaction(target, canvas, selector, options),
1322
- });
1323
- function useCanvas(_canvasType, _power) {
1324
- Platform.origin = {
1325
- createCanvas(width, height) {
1326
- const canvas = document.createElement('canvas');
1327
- canvas.width = width;
1328
- canvas.height = height;
1329
- return canvas;
1330
- },
1331
- canvasToDataURL: (canvas, type, quality) => canvas.toDataURL(mineType(type), quality),
1332
- canvasToBolb: (canvas, type, quality) => new Promise((resolve) => canvas.toBlob(resolve, mineType(type), quality)),
1333
- canvasSaveAs: (canvas, filename, quality) => {
1334
- return new Promise((resolve) => {
1335
- let el = document.createElement('a');
1336
- el.href = canvas.toDataURL(mineType(fileType(filename)), quality);
1337
- el.download = filename;
1338
- document.body.appendChild(el);
1339
- el.click();
1340
- document.body.removeChild(el);
1341
- resolve();
1342
- });
1343
- },
1344
- loadImage(src) {
1345
- return new Promise((resolve, reject) => {
1346
- const img = new Image();
1347
- img.setAttribute('crossOrigin', 'anonymous');
1348
- img.crossOrigin = 'anonymous';
1349
- img.onload = () => { resolve(img); };
1350
- img.onerror = (e) => { reject(e); };
1351
- if (!src.startsWith('data:') && Platform.image.suffix)
1352
- src += (src.includes("?") ? "&" : "?") + Platform.image.suffix;
1353
- img.src = src;
1468
+ function fillText(ui, canvas) {
1469
+ let row;
1470
+ const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
1471
+ for (let i = 0, len = rows.length; i < len; i++) {
1472
+ row = rows[i];
1473
+ if (row.text) {
1474
+ canvas.fillText(row.text, row.x, row.y);
1475
+ }
1476
+ else if (row.data) {
1477
+ row.data.forEach(charData => {
1478
+ canvas.fillText(charData.char, charData.x, row.y);
1354
1479
  });
1355
1480
  }
1356
- };
1357
- Platform.event = {
1358
- stopDefault(origin) { origin.preventDefault(); },
1359
- stopNow(origin) { origin.stopImmediatePropagation(); },
1360
- stop(origin) { origin.stopPropagation(); }
1361
- };
1362
- Platform.canvas = Creator.canvas();
1363
- Platform.conicGradientSupport = !!Platform.canvas.context.createConicGradient;
1364
- }
1365
- Platform.name = 'web';
1366
- Platform.isMobile = 'ontouchstart' in window;
1367
- Platform.requestRender = function (render) { window.requestAnimationFrame(render); };
1368
- Platform.devicePixelRatio = Math.max(1, devicePixelRatio);
1369
- const { userAgent } = navigator;
1370
- if (userAgent.indexOf("Firefox") > -1) {
1371
- Platform.conicGradientRotate90 = true;
1372
- Platform.intWheelDeltaY = true;
1373
- Platform.syncDomFont = true;
1374
- }
1375
- else if (userAgent.indexOf("Safari") > -1 && userAgent.indexOf("Chrome") === -1) {
1376
- Platform.fullImageShadow = true;
1377
- }
1378
- if (userAgent.indexOf('Windows') > -1) {
1379
- Platform.os = 'Windows';
1380
- Platform.intWheelDeltaY = true;
1381
- }
1382
- else if (userAgent.indexOf('Mac') > -1) {
1383
- Platform.os = 'Mac';
1384
- }
1385
- else if (userAgent.indexOf('Linux') > -1) {
1386
- Platform.os = 'Linux';
1481
+ if (decorationY)
1482
+ canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight);
1483
+ }
1387
1484
  }
1388
1485
 
1389
- let origin = {};
1390
- const { get: get$4, rotateOfOuter: rotateOfOuter$2, translate: translate$1, scaleOfOuter: scaleOfOuter$2, scale: scaleHelper, rotate } = MatrixHelper;
1391
- function fillOrFitMode(data, mode, box, width, height, rotation) {
1392
- const transform = get$4();
1393
- const swap = rotation && rotation !== 180;
1394
- const sw = box.width / (swap ? height : width);
1395
- const sh = box.height / (swap ? width : height);
1396
- const scale = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
1397
- const x = box.x + (box.width - width * scale) / 2;
1398
- const y = box.y + (box.height - height * scale) / 2;
1399
- translate$1(transform, x, y);
1400
- scaleHelper(transform, scale);
1401
- if (rotation)
1402
- rotateOfOuter$2(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
1403
- data.scaleX = data.scaleY = scale;
1404
- data.transform = transform;
1405
- }
1406
- function clipMode(data, box, x, y, scaleX, scaleY, rotation) {
1407
- const transform = get$4();
1408
- translate$1(transform, box.x, box.y);
1409
- if (x || y)
1410
- translate$1(transform, x, y);
1411
- if (scaleX) {
1412
- scaleHelper(transform, scaleX, scaleY);
1413
- data.scaleX = transform.a;
1414
- data.scaleY = transform.d;
1415
- }
1416
- if (rotation)
1417
- rotate(transform, rotation);
1418
- data.transform = transform;
1486
+ function fill(fill, ui, canvas) {
1487
+ canvas.fillStyle = fill;
1488
+ ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
1419
1489
  }
1420
- function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation) {
1421
- const transform = get$4();
1422
- if (rotation) {
1423
- rotate(transform, rotation);
1424
- switch (rotation) {
1425
- case 90:
1426
- translate$1(transform, height, 0);
1427
- break;
1428
- case 180:
1429
- translate$1(transform, width, height);
1430
- break;
1431
- case 270:
1432
- translate$1(transform, 0, width);
1490
+ function fills(fills, ui, canvas) {
1491
+ let item;
1492
+ const { windingRule, __font } = ui.__;
1493
+ for (let i = 0, len = fills.length; i < len; i++) {
1494
+ item = fills[i];
1495
+ if (item.image && PaintImage.checkImage(ui, canvas, item, !__font))
1496
+ continue;
1497
+ if (item.style) {
1498
+ canvas.fillStyle = item.style;
1499
+ if (item.transform) {
1500
+ canvas.save();
1501
+ canvas.transform(item.transform);
1502
+ if (item.blendMode)
1503
+ canvas.blendMode = item.blendMode;
1504
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1505
+ canvas.restore();
1506
+ }
1507
+ else {
1508
+ if (item.blendMode) {
1509
+ canvas.saveBlendMode(item.blendMode);
1510
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1511
+ canvas.restoreBlendMode();
1512
+ }
1513
+ else {
1514
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1515
+ }
1516
+ }
1517
+ }
1518
+ }
1519
+ }
1520
+
1521
+ function strokeText(stroke, ui, canvas) {
1522
+ const { strokeAlign } = ui.__;
1523
+ const isStrokes = typeof stroke !== 'string';
1524
+ switch (strokeAlign) {
1525
+ case 'center':
1526
+ canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
1527
+ isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
1528
+ break;
1529
+ case 'inside':
1530
+ drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
1531
+ break;
1532
+ case 'outside':
1533
+ drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
1534
+ break;
1535
+ }
1536
+ }
1537
+ function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
1538
+ const { __strokeWidth, __font } = ui.__;
1539
+ const out = canvas.getSameCanvas(true, true);
1540
+ out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__);
1541
+ out.font = __font;
1542
+ isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
1543
+ out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
1544
+ fillText(ui, out);
1545
+ out.blendMode = 'normal';
1546
+ if (ui.__worldFlipped) {
1547
+ canvas.copyWorldByReset(out, ui.__nowWorld);
1548
+ }
1549
+ else {
1550
+ canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
1551
+ }
1552
+ out.recycle(ui.__nowWorld);
1553
+ }
1554
+ function drawTextStroke(ui, canvas) {
1555
+ let row;
1556
+ const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
1557
+ for (let i = 0, len = rows.length; i < len; i++) {
1558
+ row = rows[i];
1559
+ if (row.text) {
1560
+ canvas.strokeText(row.text, row.x, row.y);
1561
+ }
1562
+ else if (row.data) {
1563
+ row.data.forEach(charData => {
1564
+ canvas.strokeText(charData.char, charData.x, row.y);
1565
+ });
1566
+ }
1567
+ if (decorationY)
1568
+ canvas.strokeRect(row.x, row.y + decorationY, row.width, decorationHeight);
1569
+ }
1570
+ }
1571
+ function drawStrokesStyle(strokes, isText, ui, canvas) {
1572
+ let item;
1573
+ for (let i = 0, len = strokes.length; i < len; i++) {
1574
+ item = strokes[i];
1575
+ if (item.image && PaintImage.checkImage(ui, canvas, item, false))
1576
+ continue;
1577
+ if (item.style) {
1578
+ canvas.strokeStyle = item.style;
1579
+ if (item.blendMode) {
1580
+ canvas.saveBlendMode(item.blendMode);
1581
+ isText ? drawTextStroke(ui, canvas) : canvas.stroke();
1582
+ canvas.restoreBlendMode();
1583
+ }
1584
+ else {
1585
+ isText ? drawTextStroke(ui, canvas) : canvas.stroke();
1586
+ }
1587
+ }
1588
+ }
1589
+ }
1590
+
1591
+ function stroke(stroke, ui, canvas) {
1592
+ const options = ui.__;
1593
+ const { __strokeWidth, strokeAlign, __font } = options;
1594
+ if (!__strokeWidth)
1595
+ return;
1596
+ if (__font) {
1597
+ strokeText(stroke, ui, canvas);
1598
+ }
1599
+ else {
1600
+ switch (strokeAlign) {
1601
+ case 'center':
1602
+ canvas.setStroke(stroke, __strokeWidth, options);
1603
+ canvas.stroke();
1604
+ break;
1605
+ case 'inside':
1606
+ canvas.save();
1607
+ canvas.setStroke(stroke, __strokeWidth * 2, options);
1608
+ options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1609
+ canvas.stroke();
1610
+ canvas.restore();
1611
+ break;
1612
+ case 'outside':
1613
+ const out = canvas.getSameCanvas(true, true);
1614
+ out.setStroke(stroke, __strokeWidth * 2, options);
1615
+ ui.__drawRenderPath(out);
1616
+ out.stroke();
1617
+ options.windingRule ? out.clip(options.windingRule) : out.clip();
1618
+ out.clearWorld(ui.__layout.renderBounds);
1619
+ if (ui.__worldFlipped) {
1620
+ canvas.copyWorldByReset(out, ui.__nowWorld);
1621
+ }
1622
+ else {
1623
+ canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
1624
+ }
1625
+ out.recycle(ui.__nowWorld);
1433
1626
  break;
1434
1627
  }
1435
1628
  }
1436
- origin.x = box.x;
1437
- origin.y = box.y;
1438
- if (x || y)
1439
- origin.x += x, origin.y += y;
1440
- translate$1(transform, origin.x, origin.y);
1441
- if (scaleX) {
1442
- scaleOfOuter$2(transform, origin, scaleX, scaleY);
1443
- data.scaleX = scaleX;
1444
- data.scaleY = scaleY;
1629
+ }
1630
+ function strokes(strokes, ui, canvas) {
1631
+ const options = ui.__;
1632
+ const { __strokeWidth, strokeAlign, __font } = options;
1633
+ if (!__strokeWidth)
1634
+ return;
1635
+ if (__font) {
1636
+ strokeText(strokes, ui, canvas);
1637
+ }
1638
+ else {
1639
+ switch (strokeAlign) {
1640
+ case 'center':
1641
+ canvas.setStroke(undefined, __strokeWidth, options);
1642
+ drawStrokesStyle(strokes, false, ui, canvas);
1643
+ break;
1644
+ case 'inside':
1645
+ canvas.save();
1646
+ canvas.setStroke(undefined, __strokeWidth * 2, options);
1647
+ options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1648
+ drawStrokesStyle(strokes, false, ui, canvas);
1649
+ canvas.restore();
1650
+ break;
1651
+ case 'outside':
1652
+ const { renderBounds } = ui.__layout;
1653
+ const out = canvas.getSameCanvas(true, true);
1654
+ ui.__drawRenderPath(out);
1655
+ out.setStroke(undefined, __strokeWidth * 2, options);
1656
+ drawStrokesStyle(strokes, false, ui, out);
1657
+ options.windingRule ? out.clip(options.windingRule) : out.clip();
1658
+ out.clearWorld(renderBounds);
1659
+ if (ui.__worldFlipped) {
1660
+ canvas.copyWorldByReset(out, ui.__nowWorld);
1661
+ }
1662
+ else {
1663
+ canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
1664
+ }
1665
+ out.recycle(ui.__nowWorld);
1666
+ break;
1667
+ }
1668
+ }
1669
+ }
1670
+
1671
+ const { getSpread, getOuterOf, getByMove, getIntersectData } = BoundsHelper;
1672
+ function shape(ui, current, options) {
1673
+ const canvas = current.getSameCanvas();
1674
+ const nowWorld = ui.__nowWorld;
1675
+ let bounds, fitMatrix, shapeBounds, worldCanvas;
1676
+ let { scaleX, scaleY } = nowWorld;
1677
+ if (scaleX < 0)
1678
+ scaleX = -scaleX;
1679
+ if (scaleY < 0)
1680
+ scaleY = -scaleY;
1681
+ if (current.bounds.includes(nowWorld)) {
1682
+ worldCanvas = canvas;
1683
+ bounds = shapeBounds = nowWorld;
1684
+ }
1685
+ else {
1686
+ const { renderShapeSpread: spread } = ui.__layout;
1687
+ const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, scaleX === scaleY ? spread * scaleX : [spread * scaleY, spread * scaleX]) : current.bounds, nowWorld);
1688
+ fitMatrix = current.bounds.getFitMatrix(worldClipBounds);
1689
+ let { a: fitScaleX, d: fitScaleY } = fitMatrix;
1690
+ if (fitMatrix.a < 1) {
1691
+ worldCanvas = current.getSameCanvas();
1692
+ ui.__renderShape(worldCanvas, options);
1693
+ scaleX *= fitScaleX;
1694
+ scaleY *= fitScaleY;
1695
+ }
1696
+ shapeBounds = getOuterOf(nowWorld, fitMatrix);
1697
+ bounds = getByMove(shapeBounds, -fitMatrix.e, -fitMatrix.f);
1698
+ if (options.matrix) {
1699
+ const { matrix } = options;
1700
+ fitMatrix.multiply(matrix);
1701
+ fitScaleX *= matrix.scaleX;
1702
+ fitScaleY *= matrix.scaleY;
1703
+ }
1704
+ options = Object.assign(Object.assign({}, options), { matrix: fitMatrix.withScale(fitScaleX, fitScaleY) });
1705
+ }
1706
+ ui.__renderShape(canvas, options);
1707
+ return {
1708
+ canvas, matrix: fitMatrix, bounds,
1709
+ worldCanvas, shapeBounds, scaleX, scaleY
1710
+ };
1711
+ }
1712
+
1713
+ let recycleMap;
1714
+ function compute(attrName, ui) {
1715
+ const data = ui.__, leafPaints = [];
1716
+ let paints = data.__input[attrName], hasOpacityPixel;
1717
+ if (!(paints instanceof Array))
1718
+ paints = [paints];
1719
+ recycleMap = PaintImage.recycleImage(attrName, data);
1720
+ for (let i = 0, len = paints.length, item; i < len; i++) {
1721
+ item = getLeafPaint(attrName, paints[i], ui);
1722
+ if (item)
1723
+ leafPaints.push(item);
1724
+ }
1725
+ data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
1726
+ if (leafPaints.length && leafPaints[0].image)
1727
+ hasOpacityPixel = leafPaints[0].image.hasOpacityPixel;
1728
+ if (attrName === 'fill') {
1729
+ data.__pixelFill = hasOpacityPixel;
1730
+ }
1731
+ else {
1732
+ data.__pixelStroke = hasOpacityPixel;
1733
+ }
1734
+ }
1735
+ function getLeafPaint(attrName, paint, ui) {
1736
+ if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
1737
+ return undefined;
1738
+ const { boxBounds } = ui.__layout;
1739
+ switch (paint.type) {
1740
+ case 'solid':
1741
+ let { type, blendMode, color, opacity } = paint;
1742
+ return { type, blendMode, style: ColorConvert.string(color, opacity) };
1743
+ case 'image':
1744
+ return PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
1745
+ case 'linear':
1746
+ return PaintGradient.linearGradient(paint, boxBounds);
1747
+ case 'radial':
1748
+ return PaintGradient.radialGradient(paint, boxBounds);
1749
+ case 'angular':
1750
+ return PaintGradient.conicGradient(paint, boxBounds);
1751
+ default:
1752
+ return paint.r !== undefined ? { type: 'solid', style: ColorConvert.string(paint) } : undefined;
1445
1753
  }
1754
+ }
1755
+
1756
+ const PaintModule = {
1757
+ compute,
1758
+ fill,
1759
+ fills,
1760
+ fillText,
1761
+ stroke,
1762
+ strokes,
1763
+ strokeText,
1764
+ drawTextStroke,
1765
+ shape
1766
+ };
1767
+
1768
+ let origin = {};
1769
+ const { get: get$3, rotateOfOuter: rotateOfOuter$1, translate: translate$1, scaleOfOuter: scaleOfOuter$1, scale: scaleHelper, rotate } = MatrixHelper;
1770
+ function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
1771
+ const transform = get$3();
1772
+ translate$1(transform, box.x + x, box.y + y);
1773
+ scaleHelper(transform, scaleX, scaleY);
1774
+ if (rotation)
1775
+ rotateOfOuter$1(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
1776
+ data.transform = transform;
1777
+ }
1778
+ function clipMode(data, box, x, y, scaleX, scaleY, rotation) {
1779
+ const transform = get$3();
1780
+ translate$1(transform, box.x + x, box.y + y);
1781
+ if (scaleX)
1782
+ scaleHelper(transform, scaleX, scaleY);
1783
+ if (rotation)
1784
+ rotate(transform, rotation);
1785
+ data.transform = transform;
1786
+ }
1787
+ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align) {
1788
+ const transform = get$3();
1789
+ if (rotation) {
1790
+ if (align === 'center') {
1791
+ rotateOfOuter$1(transform, { x: width / 2, y: height / 2 }, rotation);
1792
+ }
1793
+ else {
1794
+ rotate(transform, rotation);
1795
+ switch (rotation) {
1796
+ case 90:
1797
+ translate$1(transform, height, 0);
1798
+ break;
1799
+ case 180:
1800
+ translate$1(transform, width, height);
1801
+ break;
1802
+ case 270:
1803
+ translate$1(transform, 0, width);
1804
+ break;
1805
+ }
1806
+ }
1807
+ }
1808
+ origin.x = box.x + x;
1809
+ origin.y = box.y + y;
1810
+ translate$1(transform, origin.x, origin.y);
1811
+ if (scaleX)
1812
+ scaleOfOuter$1(transform, origin, scaleX, scaleY);
1446
1813
  data.transform = transform;
1447
1814
  }
1448
1815
 
1449
- const { get: get$3, translate } = MatrixHelper;
1816
+ const { get: get$2, translate } = MatrixHelper;
1817
+ const tempBox = new Bounds();
1818
+ const tempPoint = {};
1450
1819
  function createData(leafPaint, image, paint, box) {
1451
- let { width, height } = image;
1452
- const { opacity, mode, offset, scale, size, rotation, blendMode, repeat } = paint;
1453
- const sameBox = box.width === width && box.height === height;
1820
+ const { blendMode } = paint;
1454
1821
  if (blendMode)
1455
1822
  leafPaint.blendMode = blendMode;
1456
- const data = leafPaint.data = { mode };
1457
- let x, y, scaleX, scaleY;
1458
- if (offset)
1459
- x = offset.x, y = offset.y;
1460
- if (size) {
1823
+ leafPaint.data = getPatternData(paint, box, image);
1824
+ }
1825
+ function getPatternData(paint, box, image) {
1826
+ let { width, height } = image;
1827
+ if (paint.padding)
1828
+ box = tempBox.set(box).shrink(paint.padding);
1829
+ const { opacity, mode, align, offset, scale, size, rotation, repeat } = paint;
1830
+ const sameBox = box.width === width && box.height === height;
1831
+ const data = { mode };
1832
+ const swapSize = align !== 'center' && (rotation || 0) % 180 === 90;
1833
+ const swapWidth = swapSize ? height : width, swapHeight = swapSize ? width : height;
1834
+ let x = 0, y = 0, scaleX, scaleY;
1835
+ if (!mode || mode === 'cover' || mode === 'fit') {
1836
+ if (!sameBox || rotation) {
1837
+ const sw = box.width / swapWidth, sh = box.height / swapHeight;
1838
+ scaleX = scaleY = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
1839
+ x += (box.width - width * scaleX) / 2, y += (box.height - height * scaleY) / 2;
1840
+ }
1841
+ }
1842
+ else if (size) {
1461
1843
  scaleX = (typeof size === 'number' ? size : size.width) / width;
1462
1844
  scaleY = (typeof size === 'number' ? size : size.height) / height;
1463
1845
  }
@@ -1465,30 +1847,46 @@ function createData(leafPaint, image, paint, box) {
1465
1847
  scaleX = typeof scale === 'number' ? scale : scale.x;
1466
1848
  scaleY = typeof scale === 'number' ? scale : scale.y;
1467
1849
  }
1850
+ if (align) {
1851
+ const imageBounds = { x, y, width: swapWidth, height: swapHeight };
1852
+ if (scaleX)
1853
+ imageBounds.width *= scaleX, imageBounds.height *= scaleY;
1854
+ AlignHelper.toPoint(align, imageBounds, box, tempPoint, true);
1855
+ x += tempPoint.x, y += tempPoint.y;
1856
+ }
1857
+ if (offset)
1858
+ x += offset.x, y += offset.y;
1468
1859
  switch (mode) {
1469
1860
  case 'strench':
1470
1861
  if (!sameBox)
1471
1862
  width = box.width, height = box.height;
1472
- if (box.x || box.y) {
1473
- data.transform = get$3();
1474
- translate(data.transform, box.x, box.y);
1475
- }
1476
1863
  break;
1864
+ case 'normal':
1477
1865
  case 'clip':
1478
- if (offset || scaleX || rotation)
1866
+ if (x || y || scaleX || rotation)
1479
1867
  clipMode(data, box, x, y, scaleX, scaleY, rotation);
1480
1868
  break;
1481
1869
  case 'repeat':
1482
1870
  if (!sameBox || scaleX || rotation)
1483
- repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation);
1871
+ repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align);
1484
1872
  if (!repeat)
1485
1873
  data.repeat = 'repeat';
1486
1874
  break;
1487
1875
  case 'fit':
1488
1876
  case 'cover':
1489
1877
  default:
1490
- if (!sameBox || rotation)
1491
- fillOrFitMode(data, mode, box, width, height, rotation);
1878
+ if (scaleX)
1879
+ fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation);
1880
+ }
1881
+ if (!data.transform) {
1882
+ if (box.x || box.y) {
1883
+ data.transform = get$2();
1884
+ translate(data.transform, box.x, box.y);
1885
+ }
1886
+ }
1887
+ if (scaleX && mode !== 'strench') {
1888
+ data.scaleX = scaleX;
1889
+ data.scaleY = scaleY;
1492
1890
  }
1493
1891
  data.width = width;
1494
1892
  data.height = height;
@@ -1496,112 +1894,108 @@ function createData(leafPaint, image, paint, box) {
1496
1894
  data.opacity = opacity;
1497
1895
  if (repeat)
1498
1896
  data.repeat = typeof repeat === 'string' ? (repeat === 'x' ? 'repeat-x' : 'repeat-y') : 'repeat';
1897
+ return data;
1499
1898
  }
1500
1899
 
1501
- function image(ui, attrName, attrValue, box, firstUse) {
1502
- const leafPaint = { type: attrValue.type };
1503
- const image = leafPaint.image = ImageManager.get(attrValue);
1504
- const event = (firstUse || image.loading) && { target: ui, image, attrName, attrValue };
1900
+ let cache, box = new Bounds();
1901
+ const { isSame } = BoundsHelper;
1902
+ function image(ui, attrName, paint, boxBounds, firstUse) {
1903
+ let leafPaint, event;
1904
+ const image = ImageManager.get(paint);
1905
+ if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
1906
+ leafPaint = cache.leafPaint;
1907
+ }
1908
+ else {
1909
+ leafPaint = { type: paint.type, image };
1910
+ cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
1911
+ }
1912
+ if (firstUse || image.loading)
1913
+ event = { image, attrName, attrValue: paint };
1505
1914
  if (image.ready) {
1506
- if (hasNaturalSize(ui, attrName, image))
1507
- createData(leafPaint, image, attrValue, box);
1915
+ checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
1508
1916
  if (firstUse) {
1509
- emit(ImageEvent.LOAD, event);
1510
- emit(ImageEvent.LOADED, event);
1917
+ onLoad(ui, event);
1918
+ onLoadSuccess(ui, event);
1511
1919
  }
1512
1920
  }
1513
1921
  else if (image.error) {
1514
- if (firstUse) {
1515
- ui.forceUpdate('surface');
1516
- event.error = image.error;
1517
- emit(ImageEvent.ERROR, event);
1518
- }
1922
+ if (firstUse)
1923
+ onLoadError(ui, event, image.error);
1519
1924
  }
1520
1925
  else {
1926
+ ignoreRender(ui, true);
1521
1927
  if (firstUse)
1522
- emit(ImageEvent.LOAD, event);
1928
+ onLoad(ui, event);
1523
1929
  leafPaint.loadId = image.load(() => {
1930
+ ignoreRender(ui, false);
1524
1931
  if (!ui.destroyed) {
1525
- if (hasNaturalSize(ui, attrName, image)) {
1526
- createData(leafPaint, image, attrValue, box);
1932
+ if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
1933
+ if (image.hasOpacityPixel)
1934
+ ui.__layout.hitCanvasChanged = true;
1527
1935
  ui.forceUpdate('surface');
1528
1936
  }
1529
- emit(ImageEvent.LOADED, event);
1937
+ onLoadSuccess(ui, event);
1530
1938
  }
1939
+ leafPaint.loadId = null;
1531
1940
  }, (error) => {
1532
- ui.forceUpdate('surface');
1533
- event.error = error;
1534
- emit(ImageEvent.ERROR, event);
1941
+ ignoreRender(ui, false);
1942
+ onLoadError(ui, event, error);
1943
+ leafPaint.loadId = null;
1535
1944
  });
1536
1945
  }
1537
1946
  return leafPaint;
1538
1947
  }
1539
- function hasNaturalSize(ui, attrName, image) {
1948
+ function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
1540
1949
  if (attrName === 'fill' && !ui.__.__naturalWidth) {
1541
- const { __: d } = ui;
1542
- d.__naturalWidth = image.width;
1543
- d.__naturalHeight = image.height;
1544
- if (!d.__getInput('width') || !d.__getInput('height')) {
1950
+ const data = ui.__;
1951
+ data.__naturalWidth = image.width / data.pixelRatio;
1952
+ data.__naturalHeight = image.height / data.pixelRatio;
1953
+ if (data.__autoSide) {
1545
1954
  ui.forceUpdate('width');
1546
1955
  if (ui.__proxyData) {
1547
- ui.setProxyAttr('width', ui.__.width);
1548
- ui.setProxyAttr('height', ui.__.height);
1956
+ ui.setProxyAttr('width', data.width);
1957
+ ui.setProxyAttr('height', data.height);
1549
1958
  }
1550
1959
  return false;
1551
1960
  }
1552
1961
  }
1962
+ if (!leafPaint.data)
1963
+ createData(leafPaint, image, paint, boxBounds);
1553
1964
  return true;
1554
1965
  }
1555
- function emit(type, data) {
1556
- if (data.target.hasEvent(type))
1557
- data.target.emitEvent(new ImageEvent(type, data));
1966
+ function onLoad(ui, event) {
1967
+ emit(ui, ImageEvent.LOAD, event);
1968
+ }
1969
+ function onLoadSuccess(ui, event) {
1970
+ emit(ui, ImageEvent.LOADED, event);
1971
+ }
1972
+ function onLoadError(ui, event, error) {
1973
+ event.error = error;
1974
+ ui.forceUpdate('surface');
1975
+ emit(ui, ImageEvent.ERROR, event);
1976
+ }
1977
+ function emit(ui, type, data) {
1978
+ if (ui.hasEvent(type))
1979
+ ui.emitEvent(new ImageEvent(type, data));
1980
+ }
1981
+ function ignoreRender(ui, value) {
1982
+ const { leafer } = ui;
1983
+ if (leafer && leafer.viewReady)
1984
+ leafer.renderer.ignore = value;
1558
1985
  }
1559
1986
 
1560
- /******************************************************************************
1561
- Copyright (c) Microsoft Corporation.
1562
-
1563
- Permission to use, copy, modify, and/or distribute this software for any
1564
- purpose with or without fee is hereby granted.
1565
-
1566
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
1567
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1568
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
1569
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1570
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
1571
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1572
- PERFORMANCE OF THIS SOFTWARE.
1573
- ***************************************************************************** */
1574
- /* global Reflect, Promise, SuppressedError, Symbol */
1575
-
1576
-
1577
- function __awaiter(thisArg, _arguments, P, generator) {
1578
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
1579
- return new (P || (P = Promise))(function (resolve, reject) {
1580
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
1581
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
1582
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
1583
- step((generator = generator.apply(thisArg, _arguments || [])).next());
1584
- });
1585
- }
1586
-
1587
- typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
1588
- var e = new Error(message);
1589
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1590
- };
1591
-
1592
- const Export$1 = {};
1593
-
1594
- const { get: get$2, scale, copy: copy$1 } = MatrixHelper;
1987
+ const { get: get$1, scale, copy: copy$1 } = MatrixHelper;
1988
+ const { ceil, abs: abs$1 } = Math;
1595
1989
  function createPattern(ui, paint, pixelRatio) {
1596
- let { scaleX, scaleY } = ui.__world;
1990
+ let { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
1597
1991
  const id = scaleX + '-' + scaleY;
1598
1992
  if (paint.patternId !== id && !ui.destroyed) {
1599
- scaleX = Math.abs(scaleX);
1600
- scaleY = Math.abs(scaleY);
1993
+ scaleX = abs$1(scaleX);
1994
+ scaleY = abs$1(scaleY);
1601
1995
  const { image, data } = paint;
1602
1996
  let imageScale, imageMatrix, { width, height, scaleX: sx, scaleY: sy, opacity, transform, repeat } = data;
1603
1997
  if (sx) {
1604
- imageMatrix = get$2();
1998
+ imageMatrix = get$1();
1605
1999
  copy$1(imageMatrix, transform);
1606
2000
  scale(imageMatrix, 1 / sx, 1 / sy);
1607
2001
  scaleX *= sx;
@@ -1636,22 +2030,14 @@ function createPattern(ui, paint, pixelRatio) {
1636
2030
  }
1637
2031
  if (transform || scaleX !== 1 || scaleY !== 1) {
1638
2032
  if (!imageMatrix) {
1639
- imageMatrix = get$2();
2033
+ imageMatrix = get$1();
1640
2034
  if (transform)
1641
2035
  copy$1(imageMatrix, transform);
1642
2036
  }
1643
2037
  scale(imageMatrix, 1 / scaleX, 1 / scaleY);
1644
2038
  }
1645
- const pattern = Platform.canvas.createPattern(image.getCanvas(width < 1 ? 1 : width, height < 1 ? 1 : height, opacity), repeat || (Platform.origin.noRepeat || 'no-repeat'));
1646
- try {
1647
- if (paint.transform)
1648
- paint.transform = null;
1649
- if (imageMatrix)
1650
- pattern.setTransform ? pattern.setTransform(imageMatrix) : paint.transform = imageMatrix;
1651
- }
1652
- catch (_a) {
1653
- paint.transform = imageMatrix;
1654
- }
2039
+ const canvas = image.getCanvas(ceil(width) || 1, ceil(height) || 1, opacity);
2040
+ const pattern = image.getPattern(canvas, repeat || (Platform.origin.noRepeat || 'no-repeat'), imageMatrix, paint);
1655
2041
  paint.style = pattern;
1656
2042
  paint.patternId = id;
1657
2043
  return true;
@@ -1661,10 +2047,42 @@ function createPattern(ui, paint, pixelRatio) {
1661
2047
  }
1662
2048
  }
1663
2049
 
2050
+ /******************************************************************************
2051
+ Copyright (c) Microsoft Corporation.
2052
+
2053
+ Permission to use, copy, modify, and/or distribute this software for any
2054
+ purpose with or without fee is hereby granted.
2055
+
2056
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
2057
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
2058
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
2059
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
2060
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
2061
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2062
+ PERFORMANCE OF THIS SOFTWARE.
2063
+ ***************************************************************************** */
2064
+ /* global Reflect, Promise, SuppressedError, Symbol */
2065
+
2066
+
2067
+ function __awaiter(thisArg, _arguments, P, generator) {
2068
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
2069
+ return new (P || (P = Promise))(function (resolve, reject) {
2070
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
2071
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
2072
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
2073
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
2074
+ });
2075
+ }
2076
+
2077
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
2078
+ var e = new Error(message);
2079
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
2080
+ };
2081
+
1664
2082
  const { abs } = Math;
1665
2083
  function checkImage(ui, canvas, paint, allowPaint) {
1666
- const { scaleX, scaleY } = ui.__world;
1667
- if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
2084
+ const { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
2085
+ if (!paint.data || (paint.patternId === scaleX + '-' + scaleY && !Export.running)) {
1668
2086
  return false;
1669
2087
  }
1670
2088
  else {
@@ -1678,7 +2096,7 @@ function checkImage(ui, canvas, paint, allowPaint) {
1678
2096
  width *= data.scaleX;
1679
2097
  height *= data.scaleY;
1680
2098
  }
1681
- allowPaint = width * height > Platform.image.maxCacheSize;
2099
+ allowPaint = (width * height > Platform.image.maxCacheSize) || Export.running;
1682
2100
  }
1683
2101
  else {
1684
2102
  allowPaint = false;
@@ -1697,307 +2115,72 @@ function checkImage(ui, canvas, paint, allowPaint) {
1697
2115
  canvas.restore();
1698
2116
  return true;
1699
2117
  }
1700
- else {
1701
- if (!paint.style || Export$1.running) {
1702
- createPattern(ui, paint, canvas.pixelRatio);
1703
- }
1704
- else {
1705
- if (!paint.patternTask) {
1706
- paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
1707
- paint.patternTask = null;
1708
- if (canvas.bounds.hit(ui.__world))
1709
- createPattern(ui, paint, canvas.pixelRatio);
1710
- ui.forceUpdate('surface');
1711
- }), 300);
1712
- }
1713
- }
1714
- return false;
1715
- }
1716
- }
1717
- }
1718
-
1719
- function recycleImage(attrName, data) {
1720
- const paints = data['_' + attrName];
1721
- if (paints instanceof Array) {
1722
- let image, recycleMap, input, url;
1723
- for (let i = 0, len = paints.length; i < len; i++) {
1724
- image = paints[i].image;
1725
- url = image && image.url;
1726
- if (url) {
1727
- if (!recycleMap)
1728
- recycleMap = {};
1729
- recycleMap[url] = true;
1730
- ImageManager.recycle(image);
1731
- if (image.loading) {
1732
- if (!input) {
1733
- input = (data.__input && data.__input[attrName]) || [];
1734
- if (!(input instanceof Array))
1735
- input = [input];
1736
- }
1737
- image.unload(paints[i].loadId, !input.some((item) => item.url === url));
1738
- }
1739
- }
1740
- }
1741
- return recycleMap;
1742
- }
1743
- return null;
1744
- }
1745
-
1746
- function fillText(ui, canvas) {
1747
- let row;
1748
- const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
1749
- for (let i = 0, len = rows.length; i < len; i++) {
1750
- row = rows[i];
1751
- if (row.text) {
1752
- canvas.fillText(row.text, row.x, row.y);
1753
- }
1754
- else if (row.data) {
1755
- row.data.forEach(charData => {
1756
- canvas.fillText(charData.char, charData.x, row.y);
1757
- });
1758
- }
1759
- if (decorationY)
1760
- canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight);
1761
- }
1762
- }
1763
-
1764
- function fill(fill, ui, canvas) {
1765
- canvas.fillStyle = fill;
1766
- ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
1767
- }
1768
- function fills(fills, ui, canvas) {
1769
- let item;
1770
- const { windingRule, __font } = ui.__;
1771
- for (let i = 0, len = fills.length; i < len; i++) {
1772
- item = fills[i];
1773
- if (item.image && checkImage(ui, canvas, item, !__font))
1774
- continue;
1775
- if (item.style) {
1776
- canvas.fillStyle = item.style;
1777
- if (item.transform) {
1778
- canvas.save();
1779
- canvas.transform(item.transform);
1780
- if (item.blendMode)
1781
- canvas.blendMode = item.blendMode;
1782
- __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1783
- canvas.restore();
1784
- }
1785
- else {
1786
- if (item.blendMode) {
1787
- canvas.saveBlendMode(item.blendMode);
1788
- __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1789
- canvas.restoreBlendMode();
1790
- }
1791
- else {
1792
- __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
1793
- }
1794
- }
1795
- }
1796
- }
1797
- }
1798
-
1799
- function strokeText(stroke, ui, canvas, renderOptions) {
1800
- const { strokeAlign } = ui.__;
1801
- const isStrokes = typeof stroke !== 'string';
1802
- switch (strokeAlign) {
1803
- case 'center':
1804
- canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
1805
- isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
1806
- break;
1807
- case 'inside':
1808
- drawAlignStroke('inside', stroke, isStrokes, ui, canvas, renderOptions);
1809
- break;
1810
- case 'outside':
1811
- drawAlignStroke('outside', stroke, isStrokes, ui, canvas, renderOptions);
1812
- break;
1813
- }
1814
- }
1815
- function drawAlignStroke(align, stroke, isStrokes, ui, canvas, renderOptions) {
1816
- const { strokeWidth, __font } = ui.__;
1817
- const out = canvas.getSameCanvas(true);
1818
- out.setStroke(isStrokes ? undefined : stroke, strokeWidth * 2, ui.__);
1819
- out.font = __font;
1820
- isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
1821
- out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
1822
- fillText(ui, out);
1823
- out.blendMode = 'normal';
1824
- if (ui.__worldFlipped || renderOptions.matrix) {
1825
- canvas.copyWorldByReset(out);
1826
- }
1827
- else {
1828
- canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds);
1829
- }
1830
- out.recycle();
1831
- }
1832
- function drawTextStroke(ui, canvas) {
1833
- let row;
1834
- const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
1835
- for (let i = 0, len = rows.length; i < len; i++) {
1836
- row = rows[i];
1837
- if (row.text) {
1838
- canvas.strokeText(row.text, row.x, row.y);
1839
- }
1840
- else if (row.data) {
1841
- row.data.forEach(charData => {
1842
- canvas.strokeText(charData.char, charData.x, row.y);
1843
- });
1844
- }
1845
- if (decorationY)
1846
- canvas.strokeRect(row.x, row.y + decorationY, row.width, decorationHeight);
1847
- }
1848
- }
1849
- function drawStrokesStyle(strokes, isText, ui, canvas) {
1850
- let item;
1851
- for (let i = 0, len = strokes.length; i < len; i++) {
1852
- item = strokes[i];
1853
- if (item.image && checkImage(ui, canvas, item, false))
1854
- continue;
1855
- if (item.style) {
1856
- canvas.strokeStyle = item.style;
1857
- if (item.blendMode) {
1858
- canvas.saveBlendMode(item.blendMode);
1859
- isText ? drawTextStroke(ui, canvas) : canvas.stroke();
1860
- canvas.restoreBlendMode();
2118
+ else {
2119
+ if (!paint.style || Export.running) {
2120
+ createPattern(ui, paint, canvas.pixelRatio);
1861
2121
  }
1862
2122
  else {
1863
- isText ? drawTextStroke(ui, canvas) : canvas.stroke();
2123
+ if (!paint.patternTask) {
2124
+ paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
2125
+ paint.patternTask = null;
2126
+ if (canvas.bounds.hit(ui.__nowWorld))
2127
+ createPattern(ui, paint, canvas.pixelRatio);
2128
+ ui.forceUpdate('surface');
2129
+ }), 300);
2130
+ }
1864
2131
  }
2132
+ return false;
1865
2133
  }
1866
2134
  }
1867
2135
  }
1868
2136
 
1869
- function stroke(stroke, ui, canvas, renderOptions) {
1870
- const options = ui.__;
1871
- const { strokeWidth, strokeAlign, __font } = options;
1872
- if (!strokeWidth)
1873
- return;
1874
- if (__font) {
1875
- strokeText(stroke, ui, canvas, renderOptions);
1876
- }
1877
- else {
1878
- switch (strokeAlign) {
1879
- case 'center':
1880
- canvas.setStroke(stroke, strokeWidth, options);
1881
- canvas.stroke();
1882
- break;
1883
- case 'inside':
1884
- canvas.save();
1885
- canvas.setStroke(stroke, strokeWidth * 2, options);
1886
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1887
- canvas.stroke();
1888
- canvas.restore();
1889
- break;
1890
- case 'outside':
1891
- const out = canvas.getSameCanvas(true);
1892
- out.setStroke(stroke, strokeWidth * 2, ui.__);
1893
- ui.__drawRenderPath(out);
1894
- out.stroke();
1895
- options.windingRule ? out.clip(options.windingRule) : out.clip();
1896
- out.clearWorld(ui.__layout.renderBounds);
1897
- if (ui.__worldFlipped || renderOptions.matrix) {
1898
- canvas.copyWorldByReset(out);
1899
- }
1900
- else {
1901
- canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds);
1902
- }
1903
- out.recycle();
1904
- break;
1905
- }
1906
- }
1907
- }
1908
- function strokes(strokes, ui, canvas, renderOptions) {
1909
- const options = ui.__;
1910
- const { strokeWidth, strokeAlign, __font } = options;
1911
- if (!strokeWidth)
1912
- return;
1913
- if (__font) {
1914
- strokeText(strokes, ui, canvas, renderOptions);
1915
- }
1916
- else {
1917
- switch (strokeAlign) {
1918
- case 'center':
1919
- canvas.setStroke(undefined, strokeWidth, options);
1920
- drawStrokesStyle(strokes, false, ui, canvas);
1921
- break;
1922
- case 'inside':
1923
- canvas.save();
1924
- canvas.setStroke(undefined, strokeWidth * 2, options);
1925
- options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
1926
- drawStrokesStyle(strokes, false, ui, canvas);
1927
- canvas.restore();
1928
- break;
1929
- case 'outside':
1930
- const { renderBounds } = ui.__layout;
1931
- const out = canvas.getSameCanvas(true);
1932
- ui.__drawRenderPath(out);
1933
- out.setStroke(undefined, strokeWidth * 2, ui.__);
1934
- drawStrokesStyle(strokes, false, ui, out);
1935
- options.windingRule ? out.clip(options.windingRule) : out.clip();
1936
- out.clearWorld(renderBounds);
1937
- if (ui.__worldFlipped || renderOptions.matrix) {
1938
- canvas.copyWorldByReset(out);
1939
- }
1940
- else {
1941
- canvas.copyWorldToInner(out, ui.__world, renderBounds);
2137
+ function recycleImage(attrName, data) {
2138
+ const paints = data['_' + attrName];
2139
+ if (paints instanceof Array) {
2140
+ let image, recycleMap, input, url;
2141
+ for (let i = 0, len = paints.length; i < len; i++) {
2142
+ image = paints[i].image;
2143
+ url = image && image.url;
2144
+ if (url) {
2145
+ if (!recycleMap)
2146
+ recycleMap = {};
2147
+ recycleMap[url] = true;
2148
+ ImageManager.recycle(image);
2149
+ if (image.loading) {
2150
+ if (!input) {
2151
+ input = (data.__input && data.__input[attrName]) || [];
2152
+ if (!(input instanceof Array))
2153
+ input = [input];
2154
+ }
2155
+ image.unload(paints[i].loadId, !input.some((item) => item.url === url));
1942
2156
  }
1943
- out.recycle();
1944
- break;
2157
+ }
1945
2158
  }
2159
+ return recycleMap;
1946
2160
  }
2161
+ return null;
1947
2162
  }
1948
2163
 
1949
- const { getSpread, getOuterOf, getByMove, getIntersectData } = BoundsHelper;
1950
- function shape(ui, current, options) {
1951
- const canvas = current.getSameCanvas();
1952
- let bounds, matrix, shapeBounds;
1953
- let worldCanvas;
1954
- const { __world } = ui;
1955
- let { scaleX, scaleY } = __world;
1956
- if (scaleX < 0)
1957
- scaleX = -scaleX;
1958
- if (scaleY < 0)
1959
- scaleY = -scaleY;
1960
- if (!current.bounds.includes(__world, options.matrix)) {
1961
- const { renderShapeSpread: spread } = ui.__layout;
1962
- const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, spread * scaleX, spread * scaleY) : current.bounds, __world, options.matrix);
1963
- matrix = current.bounds.getFitMatrix(worldClipBounds);
1964
- if (matrix.a < 1) {
1965
- worldCanvas = current.getSameCanvas();
1966
- ui.__renderShape(worldCanvas, options);
1967
- scaleX *= matrix.a;
1968
- scaleY *= matrix.d;
1969
- }
1970
- shapeBounds = getOuterOf(__world, matrix);
1971
- bounds = getByMove(shapeBounds, -matrix.e, -matrix.f);
1972
- if (options.matrix)
1973
- matrix.multiply(options.matrix);
1974
- options = Object.assign(Object.assign({}, options), { matrix });
1975
- }
1976
- else {
1977
- if (options.matrix) {
1978
- scaleX *= options.matrix.a;
1979
- scaleY *= options.matrix.d;
1980
- bounds = shapeBounds = getOuterOf(__world, options.matrix);
1981
- }
1982
- else {
1983
- bounds = shapeBounds = __world;
1984
- }
1985
- worldCanvas = canvas;
1986
- }
1987
- ui.__renderShape(canvas, options);
1988
- return {
1989
- canvas, matrix, bounds,
1990
- worldCanvas, shapeBounds, scaleX, scaleY
1991
- };
1992
- }
2164
+ const PaintImageModule = {
2165
+ image,
2166
+ checkImage,
2167
+ createPattern,
2168
+ recycleImage,
2169
+ createData,
2170
+ getPatternData,
2171
+ fillOrFitMode,
2172
+ clipMode,
2173
+ repeatMode
2174
+ };
1993
2175
 
1994
- const defaultFrom$2 = { x: 0.5, y: 0 };
1995
- const defaultTo$2 = { x: 0.5, y: 1 };
2176
+ const { toPoint: toPoint$2 } = AroundHelper;
2177
+ const realFrom$2 = {};
2178
+ const realTo$2 = {};
1996
2179
  function linearGradient(paint, box) {
1997
2180
  let { from, to, type, blendMode, opacity } = paint;
1998
- from || (from = defaultFrom$2);
1999
- to || (to = defaultTo$2);
2000
- 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);
2181
+ toPoint$2(from || 'top', box, realFrom$2);
2182
+ toPoint$2(to || 'bottom', box, realTo$2);
2183
+ const style = Platform.canvas.createLinearGradient(realFrom$2.x, realFrom$2.y, realTo$2.x, realTo$2.y);
2001
2184
  applyStops(style, paint.stops, opacity);
2002
2185
  const data = { type, style };
2003
2186
  if (blendMode)
@@ -2008,137 +2191,84 @@ function applyStops(gradient, stops, opacity) {
2008
2191
  let stop;
2009
2192
  for (let i = 0, len = stops.length; i < len; i++) {
2010
2193
  stop = stops[i];
2011
- gradient.addColorStop(stop.offset, ColorConvert$1.string(stop.color, opacity));
2194
+ if (typeof stop === 'string') {
2195
+ gradient.addColorStop(i / (len - 1), ColorConvert.string(stop, opacity));
2196
+ }
2197
+ else {
2198
+ gradient.addColorStop(stop.offset, ColorConvert.string(stop.color, opacity));
2199
+ }
2012
2200
  }
2013
2201
  }
2014
2202
 
2015
- const { set: set$1, getAngle: getAngle$1, getDistance: getDistance$1 } = PointHelper;
2016
- const { get: get$1, rotateOfOuter: rotateOfOuter$1, scaleOfOuter: scaleOfOuter$1 } = MatrixHelper;
2017
- const defaultFrom$1 = { x: 0.5, y: 0.5 };
2018
- const defaultTo$1 = { x: 0.5, y: 1 };
2203
+ const { getAngle, getDistance: getDistance$1 } = PointHelper;
2204
+ const { get, rotateOfOuter, scaleOfOuter } = MatrixHelper;
2205
+ const { toPoint: toPoint$1 } = AroundHelper;
2019
2206
  const realFrom$1 = {};
2020
2207
  const realTo$1 = {};
2021
2208
  function radialGradient(paint, box) {
2022
2209
  let { from, to, type, opacity, blendMode, stretch } = paint;
2023
- from || (from = defaultFrom$1);
2024
- to || (to = defaultTo$1);
2025
- const { x, y, width, height } = box;
2026
- set$1(realFrom$1, x + from.x * width, y + from.y * height);
2027
- set$1(realTo$1, x + to.x * width, y + to.y * height);
2028
- let transform;
2029
- if (width !== height || stretch) {
2030
- transform = get$1();
2031
- scaleOfOuter$1(transform, realFrom$1, width / height * (stretch || 1), 1);
2032
- rotateOfOuter$1(transform, realFrom$1, getAngle$1(realFrom$1, realTo$1) + 90);
2033
- }
2210
+ toPoint$1(from || 'center', box, realFrom$1);
2211
+ toPoint$1(to || 'bottom', box, realTo$1);
2034
2212
  const style = Platform.canvas.createRadialGradient(realFrom$1.x, realFrom$1.y, 0, realFrom$1.x, realFrom$1.y, getDistance$1(realFrom$1, realTo$1));
2035
2213
  applyStops(style, paint.stops, opacity);
2036
- const data = { type, style, transform };
2214
+ const data = { type, style };
2215
+ const transform = getTransform(box, realFrom$1, realTo$1, stretch, true);
2216
+ if (transform)
2217
+ data.transform = transform;
2037
2218
  if (blendMode)
2038
2219
  data.blendMode = blendMode;
2039
2220
  return data;
2040
2221
  }
2222
+ function getTransform(box, from, to, stretch, rotate90) {
2223
+ let transform;
2224
+ const { width, height } = box;
2225
+ if (width !== height || stretch) {
2226
+ const angle = getAngle(from, to);
2227
+ transform = get();
2228
+ if (rotate90) {
2229
+ scaleOfOuter(transform, from, width / height * (stretch || 1), 1);
2230
+ rotateOfOuter(transform, from, angle + 90);
2231
+ }
2232
+ else {
2233
+ scaleOfOuter(transform, from, 1, width / height * (stretch || 1));
2234
+ rotateOfOuter(transform, from, angle);
2235
+ }
2236
+ }
2237
+ return transform;
2238
+ }
2041
2239
 
2042
- const { set, getAngle, getDistance } = PointHelper;
2043
- const { get, rotateOfOuter, scaleOfOuter } = MatrixHelper;
2044
- const defaultFrom = { x: 0.5, y: 0.5 };
2045
- const defaultTo = { x: 0.5, y: 1 };
2240
+ const { getDistance } = PointHelper;
2241
+ const { toPoint } = AroundHelper;
2046
2242
  const realFrom = {};
2047
2243
  const realTo = {};
2048
2244
  function conicGradient(paint, box) {
2049
2245
  let { from, to, type, opacity, blendMode, stretch } = paint;
2050
- from || (from = defaultFrom);
2051
- to || (to = defaultTo);
2052
- const { x, y, width, height } = box;
2053
- set(realFrom, x + from.x * width, y + from.y * height);
2054
- set(realTo, x + to.x * width, y + to.y * height);
2055
- const transform = get();
2056
- const angle = getAngle(realFrom, realTo);
2057
- if (Platform.conicGradientRotate90) {
2058
- scaleOfOuter(transform, realFrom, width / height * (stretch || 1), 1);
2059
- rotateOfOuter(transform, realFrom, angle + 90);
2060
- }
2061
- else {
2062
- scaleOfOuter(transform, realFrom, 1, width / height * (stretch || 1));
2063
- rotateOfOuter(transform, realFrom, angle);
2064
- }
2246
+ toPoint(from || 'center', box, realFrom);
2247
+ toPoint(to || 'bottom', box, realTo);
2065
2248
  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));
2066
2249
  applyStops(style, paint.stops, opacity);
2067
- const data = { type, style, transform };
2250
+ const data = { type, style };
2251
+ const transform = getTransform(box, realFrom, realTo, stretch || 1, Platform.conicGradientRotate90);
2252
+ if (transform)
2253
+ data.transform = transform;
2068
2254
  if (blendMode)
2069
2255
  data.blendMode = blendMode;
2070
2256
  return data;
2071
2257
  }
2072
2258
 
2073
- let recycleMap;
2074
- function compute(attrName, ui) {
2075
- const value = [];
2076
- const data = ui.__;
2077
- let item;
2078
- let paints = data.__input[attrName];
2079
- if (!(paints instanceof Array))
2080
- paints = [paints];
2081
- recycleMap = recycleImage(attrName, data);
2082
- for (let i = 0, len = paints.length; i < len; i++) {
2083
- item = getLeafPaint(attrName, paints[i], ui);
2084
- if (item)
2085
- value.push(item);
2086
- }
2087
- data['_' + attrName] = value.length ? value : undefined;
2088
- let isPixel;
2089
- if (paints.length === 1) {
2090
- const paint = paints[0];
2091
- if (paint.type === 'image')
2092
- isPixel = ImageManager$1.isPixel(paint);
2093
- }
2094
- if (attrName === 'fill') {
2095
- data.__pixelFill = isPixel;
2096
- }
2097
- else {
2098
- data.__pixelStroke = isPixel;
2099
- }
2100
- }
2101
- function getLeafPaint(attrName, paint, ui) {
2102
- if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
2103
- return undefined;
2104
- const { boxBounds } = ui.__layout;
2105
- switch (paint.type) {
2106
- case 'solid':
2107
- let { type, blendMode, color, opacity } = paint;
2108
- return { type, blendMode, style: ColorConvert$1.string(color, opacity) };
2109
- case 'image':
2110
- return image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
2111
- case 'linear':
2112
- return linearGradient(paint, boxBounds);
2113
- case 'radial':
2114
- return radialGradient(paint, boxBounds);
2115
- case 'angular':
2116
- return conicGradient(paint, boxBounds);
2117
- default:
2118
- return paint.r ? { type: 'solid', style: ColorConvert$1.string(paint) } : undefined;
2119
- }
2120
- }
2121
-
2122
- var UIPaint = /*#__PURE__*/Object.freeze({
2123
- __proto__: null,
2124
- compute: compute,
2125
- drawTextStroke: drawTextStroke,
2126
- fill: fill,
2127
- fillText: fillText,
2128
- fills: fills,
2129
- recycleImage: recycleImage,
2130
- shape: shape,
2131
- stroke: stroke,
2132
- strokeText: strokeText,
2133
- strokes: strokes
2134
- });
2259
+ const PaintGradientModule = {
2260
+ linearGradient,
2261
+ radialGradient,
2262
+ conicGradient,
2263
+ getTransform
2264
+ };
2135
2265
 
2136
2266
  const { copy, toOffsetOutBounds: toOffsetOutBounds$1 } = BoundsHelper;
2137
2267
  const tempBounds = {};
2138
2268
  const offsetOutBounds$1 = {};
2139
- function shadow(ui, current, shape, renderOptions) {
2269
+ function shadow(ui, current, shape) {
2140
2270
  let copyBounds, spreadScale;
2141
- const { __world, __layout } = ui;
2271
+ const { __nowWorld: nowWorld, __layout } = ui;
2142
2272
  const { shadow } = ui.__;
2143
2273
  const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
2144
2274
  const other = current.getSameCanvas();
@@ -2153,21 +2283,21 @@ function shadow(ui, current, shape, renderOptions) {
2153
2283
  other.restore();
2154
2284
  other.save();
2155
2285
  if (worldCanvas) {
2156
- other.copyWorld(other, bounds, __world, 'copy');
2157
- copyBounds = __world;
2286
+ other.copyWorld(other, bounds, nowWorld, 'copy');
2287
+ copyBounds = nowWorld;
2158
2288
  }
2159
- worldCanvas ? other.copyWorld(worldCanvas, __world, __world, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
2289
+ worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
2160
2290
  }
2161
- if (ui.__worldFlipped || renderOptions.matrix) {
2162
- current.copyWorldByReset(other, copyBounds, __world, item.blendMode);
2291
+ if (ui.__worldFlipped) {
2292
+ current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
2163
2293
  }
2164
2294
  else {
2165
2295
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
2166
2296
  }
2167
2297
  if (end && index < end)
2168
- other.clear();
2298
+ other.clearWorld(copyBounds, true);
2169
2299
  });
2170
- other.recycle();
2300
+ other.recycle(copyBounds);
2171
2301
  }
2172
2302
  function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
2173
2303
  const { bounds, shapeBounds } = shape;
@@ -2198,9 +2328,9 @@ function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
2198
2328
 
2199
2329
  const { toOffsetOutBounds } = BoundsHelper;
2200
2330
  const offsetOutBounds = {};
2201
- function innerShadow(ui, current, shape, renderOptions) {
2331
+ function innerShadow(ui, current, shape) {
2202
2332
  let copyBounds, spreadScale;
2203
- const { __world, __layout: __layout } = ui;
2333
+ const { __nowWorld: nowWorld, __layout: __layout } = ui;
2204
2334
  const { innerShadow } = ui.__;
2205
2335
  const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
2206
2336
  const other = current.getSameCanvas();
@@ -2213,40 +2343,115 @@ function innerShadow(ui, current, shape, renderOptions) {
2213
2343
  drawWorldShadow(other, offsetOutBounds, spreadScale, shape);
2214
2344
  other.restore();
2215
2345
  if (worldCanvas) {
2216
- other.copyWorld(other, bounds, __world, 'copy');
2217
- other.copyWorld(worldCanvas, __world, __world, 'source-out');
2218
- copyBounds = __world;
2346
+ other.copyWorld(other, bounds, nowWorld, 'copy');
2347
+ other.copyWorld(worldCanvas, nowWorld, nowWorld, 'source-out');
2348
+ copyBounds = nowWorld;
2219
2349
  }
2220
2350
  else {
2221
2351
  other.copyWorld(shape.canvas, shapeBounds, bounds, 'source-out');
2222
2352
  copyBounds = bounds;
2223
2353
  }
2224
2354
  other.fillWorld(copyBounds, item.color, 'source-in');
2225
- if (ui.__worldFlipped || renderOptions.matrix) {
2226
- current.copyWorldByReset(other, copyBounds, __world, item.blendMode);
2355
+ if (ui.__worldFlipped) {
2356
+ current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
2227
2357
  }
2228
2358
  else {
2229
2359
  current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
2230
2360
  }
2231
2361
  if (end && index < end)
2232
- other.clear();
2362
+ other.clearWorld(copyBounds, true);
2233
2363
  });
2234
- other.recycle();
2364
+ other.recycle(copyBounds);
2235
2365
  }
2236
2366
 
2237
2367
  function blur(ui, current, origin) {
2238
2368
  const { blur } = ui.__;
2239
- origin.setWorldBlur(blur * ui.__world.a);
2240
- origin.copyWorldToInner(current, ui.__world, ui.__layout.renderBounds);
2369
+ origin.setWorldBlur(blur * ui.__nowWorld.a);
2370
+ origin.copyWorldToInner(current, ui.__nowWorld, ui.__layout.renderBounds);
2241
2371
  origin.filter = 'none';
2242
2372
  }
2243
2373
 
2244
- var UIEffect = /*#__PURE__*/Object.freeze({
2245
- __proto__: null,
2246
- blur: blur,
2247
- innerShadow: innerShadow,
2248
- shadow: shadow
2249
- });
2374
+ function backgroundBlur(_ui, _current, _shape) {
2375
+ }
2376
+
2377
+ const EffectModule = {
2378
+ shadow,
2379
+ innerShadow,
2380
+ blur,
2381
+ backgroundBlur
2382
+ };
2383
+
2384
+ const { excludeRenderBounds } = LeafBoundsHelper;
2385
+ Group.prototype.__renderMask = function (canvas, options) {
2386
+ let child, maskCanvas, contentCanvas, maskOpacity, currentMask;
2387
+ const { children } = this;
2388
+ for (let i = 0, len = children.length; i < len; i++) {
2389
+ child = children[i];
2390
+ if (child.__.mask) {
2391
+ if (currentMask) {
2392
+ maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
2393
+ maskCanvas = contentCanvas = null;
2394
+ }
2395
+ if (child.__.mask === 'path') {
2396
+ if (child.opacity < 1) {
2397
+ currentMask = 'opacity-path';
2398
+ maskOpacity = child.opacity;
2399
+ if (!contentCanvas)
2400
+ contentCanvas = getCanvas(canvas);
2401
+ }
2402
+ else {
2403
+ currentMask = 'path';
2404
+ canvas.save();
2405
+ }
2406
+ child.__clip(contentCanvas || canvas, options);
2407
+ }
2408
+ else {
2409
+ currentMask = 'alpha';
2410
+ if (!maskCanvas)
2411
+ maskCanvas = getCanvas(canvas);
2412
+ if (!contentCanvas)
2413
+ contentCanvas = getCanvas(canvas);
2414
+ child.__render(maskCanvas, options);
2415
+ }
2416
+ if (child.__.mask !== 'clipping')
2417
+ continue;
2418
+ }
2419
+ if (excludeRenderBounds(child, options))
2420
+ continue;
2421
+ child.__render(contentCanvas || canvas, options);
2422
+ }
2423
+ maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
2424
+ };
2425
+ function maskEnd(leaf, maskMode, canvas, contentCanvas, maskCanvas, maskOpacity) {
2426
+ switch (maskMode) {
2427
+ case 'alpha':
2428
+ usePixelMask(leaf, canvas, contentCanvas, maskCanvas);
2429
+ break;
2430
+ case 'opacity-path':
2431
+ copyContent(leaf, canvas, contentCanvas, maskOpacity);
2432
+ break;
2433
+ case 'path':
2434
+ canvas.restore();
2435
+ }
2436
+ }
2437
+ function getCanvas(canvas) {
2438
+ return canvas.getSameCanvas(false, true);
2439
+ }
2440
+ function usePixelMask(leaf, canvas, content, mask) {
2441
+ const realBounds = leaf.__nowWorld;
2442
+ content.resetTransform();
2443
+ content.opacity = 1;
2444
+ content.useMask(mask, realBounds);
2445
+ mask.recycle(realBounds);
2446
+ copyContent(leaf, canvas, content, 1);
2447
+ }
2448
+ function copyContent(leaf, canvas, content, maskOpacity) {
2449
+ const realBounds = leaf.__nowWorld;
2450
+ canvas.resetTransform();
2451
+ canvas.opacity = maskOpacity;
2452
+ canvas.copyWorld(content, realBounds);
2453
+ content.recycle(realBounds);
2454
+ }
2250
2455
 
2251
2456
  const money = '¥¥$€££¢¢';
2252
2457
  const letter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
@@ -2403,7 +2608,8 @@ function createRows(drawData, content, style) {
2403
2608
  if (breakAll) {
2404
2609
  if (wordWidth)
2405
2610
  addWord();
2406
- addRow();
2611
+ if (rowWidth)
2612
+ addRow();
2407
2613
  }
2408
2614
  else {
2409
2615
  if (!afterBreak)
@@ -2411,10 +2617,12 @@ function createRows(drawData, content, style) {
2411
2617
  if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
2412
2618
  if (wordWidth)
2413
2619
  addWord();
2414
- addRow();
2620
+ if (rowWidth)
2621
+ addRow();
2415
2622
  }
2416
2623
  else {
2417
- addRow();
2624
+ if (rowWidth)
2625
+ addRow();
2418
2626
  }
2419
2627
  }
2420
2628
  }
@@ -2509,11 +2717,11 @@ function layoutChar(drawData, style, width, _height) {
2509
2717
  if (mode === WordMode) {
2510
2718
  wordChar = { char: '', x: charX };
2511
2719
  charX = toWordChar(word.data, charX, wordChar);
2512
- if (wordChar.char !== ' ')
2720
+ if (row.isOverflow || wordChar.char !== ' ')
2513
2721
  row.data.push(wordChar);
2514
2722
  }
2515
2723
  else {
2516
- charX = toChar(word.data, charX, row.data);
2724
+ charX = toChar(word.data, charX, row.data, row.isOverflow);
2517
2725
  }
2518
2726
  if (!row.paraEnd && addWordWidth) {
2519
2727
  charX += addWordWidth;
@@ -2540,9 +2748,9 @@ function toWordChar(data, charX, wordChar) {
2540
2748
  });
2541
2749
  return charX;
2542
2750
  }
2543
- function toChar(data, charX, rowData) {
2751
+ function toChar(data, charX, rowData, isOverflow) {
2544
2752
  data.forEach(char => {
2545
- if (char.char !== ' ') {
2753
+ if (isOverflow || char.char !== ' ') {
2546
2754
  char.x = charX;
2547
2755
  rowData.push(char);
2548
2756
  }
@@ -2574,12 +2782,14 @@ function layoutText(drawData, style) {
2574
2782
  for (let i = 0, len = rows.length; i < len; i++) {
2575
2783
  row = rows[i];
2576
2784
  row.x = x;
2577
- switch (textAlign) {
2578
- case 'center':
2579
- row.x += (width - row.width) / 2;
2580
- break;
2581
- case 'right':
2582
- row.x += width - row.width;
2785
+ if (row.width < width || (row.width > width && !__clipText)) {
2786
+ switch (textAlign) {
2787
+ case 'center':
2788
+ row.x += (width - row.width) / 2;
2789
+ break;
2790
+ case 'right':
2791
+ row.x += width - row.width;
2792
+ }
2583
2793
  }
2584
2794
  if (row.paraStart && paraSpacing && i > 0)
2585
2795
  starY += paraSpacing;
@@ -2615,16 +2825,20 @@ function layoutText(drawData, style) {
2615
2825
  bounds.height = realHeight;
2616
2826
  }
2617
2827
 
2618
- function clipText(drawData, style) {
2828
+ function clipText(drawData, style, x, width) {
2829
+ if (!width)
2830
+ return;
2619
2831
  const { rows, overflow } = drawData;
2620
2832
  let { textOverflow } = style;
2621
2833
  rows.splice(overflow);
2622
- if (textOverflow !== 'hide') {
2623
- if (textOverflow === 'ellipsis')
2834
+ if (textOverflow && textOverflow !== 'show') {
2835
+ if (textOverflow === 'hide')
2836
+ textOverflow = '';
2837
+ else if (textOverflow === 'ellipsis')
2624
2838
  textOverflow = '...';
2625
2839
  let char, charRight;
2626
- const ellipsisWidth = Platform.canvas.measureText(textOverflow).width;
2627
- const right = style.x + style.width - ellipsisWidth;
2840
+ const ellipsisWidth = textOverflow ? Platform.canvas.measureText(textOverflow).width : 0;
2841
+ const right = x + width - ellipsisWidth;
2628
2842
  const list = style.textWrap === 'none' ? rows : [rows[overflow - 1]];
2629
2843
  list.forEach(row => {
2630
2844
  if (row.isOverflow && row.data) {
@@ -2671,42 +2885,40 @@ function decorationText(drawData, style) {
2671
2885
  }
2672
2886
 
2673
2887
  const { top, right, bottom, left } = Direction4;
2674
- const TextConvert = {
2675
- getDrawData(content, style) {
2676
- if (typeof content !== 'string')
2677
- content = String(content);
2678
- let x = 0, y = 0;
2679
- let width = style.__getInput('width') || 0;
2680
- let height = style.__getInput('height') || 0;
2681
- const { textDecoration, __font, __padding: padding } = style;
2682
- if (padding) {
2683
- if (width) {
2684
- x = padding[left];
2685
- width -= (padding[right] + padding[left]);
2686
- }
2687
- if (height) {
2688
- y = padding[top];
2689
- height -= (padding[top] + padding[bottom]);
2690
- }
2691
- }
2692
- const drawData = {
2693
- bounds: { x, y, width, height },
2694
- rows: [],
2695
- paraNumber: 0,
2696
- font: Platform.canvas.font = __font
2697
- };
2698
- createRows(drawData, content, style);
2699
- if (padding)
2700
- padAutoText(padding, drawData, style, width, height);
2701
- layoutText(drawData, style);
2702
- layoutChar(drawData, style, width);
2703
- if (drawData.overflow)
2704
- clipText(drawData, style);
2705
- if (textDecoration !== 'none')
2706
- decorationText(drawData, style);
2707
- return drawData;
2708
- }
2709
- };
2888
+ function getDrawData(content, style) {
2889
+ if (typeof content !== 'string')
2890
+ content = String(content);
2891
+ let x = 0, y = 0;
2892
+ let width = style.__getInput('width') || 0;
2893
+ let height = style.__getInput('height') || 0;
2894
+ const { textDecoration, __font, __padding: padding } = style;
2895
+ if (padding) {
2896
+ if (width) {
2897
+ x = padding[left];
2898
+ width -= (padding[right] + padding[left]);
2899
+ }
2900
+ if (height) {
2901
+ y = padding[top];
2902
+ height -= (padding[top] + padding[bottom]);
2903
+ }
2904
+ }
2905
+ const drawData = {
2906
+ bounds: { x, y, width, height },
2907
+ rows: [],
2908
+ paraNumber: 0,
2909
+ font: Platform.canvas.font = __font
2910
+ };
2911
+ createRows(drawData, content, style);
2912
+ if (padding)
2913
+ padAutoText(padding, drawData, style, width, height);
2914
+ layoutText(drawData, style);
2915
+ layoutChar(drawData, style, width);
2916
+ if (drawData.overflow)
2917
+ clipText(drawData, style, x, width);
2918
+ if (textDecoration !== 'none')
2919
+ decorationText(drawData, style);
2920
+ return drawData;
2921
+ }
2710
2922
  function padAutoText(padding, drawData, style, width, height) {
2711
2923
  if (!width) {
2712
2924
  switch (style.textAlign) {
@@ -2734,67 +2946,157 @@ function offsetText(drawData, attrName, value) {
2734
2946
  rows[i][attrName] += value;
2735
2947
  }
2736
2948
 
2737
- const ColorConvert = {
2738
- string(color, opacity) {
2739
- if (typeof color === 'string')
2740
- return color;
2741
- let a = color.a === undefined ? 1 : color.a;
2742
- if (opacity)
2743
- a *= opacity;
2744
- const rgb = color.r + ',' + color.g + ',' + color.b;
2745
- return a === 1 ? 'rgb(' + rgb + ')' : 'rgba(' + rgb + ',' + a + ')';
2746
- }
2949
+ const TextConvertModule = {
2950
+ getDrawData
2951
+ };
2952
+
2953
+ function string(color, opacity) {
2954
+ if (typeof color === 'string')
2955
+ return color;
2956
+ let a = color.a === undefined ? 1 : color.a;
2957
+ if (opacity)
2958
+ a *= opacity;
2959
+ const rgb = color.r + ',' + color.g + ',' + color.b;
2960
+ return a === 1 ? 'rgb(' + rgb + ')' : 'rgba(' + rgb + ',' + a + ')';
2961
+ }
2962
+
2963
+ const ColorConvertModule = {
2964
+ string
2747
2965
  };
2748
2966
 
2749
- const Export = {
2967
+ const { setPoint, addPoint, toBounds } = TwoPointBoundsHelper;
2968
+ function getTrimBounds(canvas) {
2969
+ const { width, height } = canvas.view;
2970
+ const { data } = canvas.context.getImageData(0, 0, width, height);
2971
+ let x, y, pointBounds, index = 0;
2972
+ for (let i = 0; i < data.length; i += 4) {
2973
+ if (data[i + 3] !== 0) {
2974
+ x = index % width;
2975
+ y = (index - x) / width;
2976
+ pointBounds ? addPoint(pointBounds, x, y) : setPoint(pointBounds = {}, x, y);
2977
+ }
2978
+ index++;
2979
+ }
2980
+ const bounds = new Bounds();
2981
+ toBounds(pointBounds, bounds);
2982
+ return bounds.scale(1 / canvas.pixelRatio).ceil();
2983
+ }
2984
+
2985
+ const ExportModule = {
2750
2986
  export(leaf, filename, options) {
2751
- Export.running = true;
2987
+ this.running = true;
2988
+ const fileType = FileHelper.fileType(filename);
2989
+ options = FileHelper.getExportOptions(options);
2752
2990
  return addTask((success) => new Promise((resolve) => {
2991
+ const over = (result) => {
2992
+ success(result);
2993
+ resolve();
2994
+ this.running = false;
2995
+ };
2996
+ const { toURL } = Platform;
2997
+ const { download } = Platform.origin;
2998
+ if (filename === 'json') {
2999
+ return over({ data: leaf.toJSON(options.json) });
3000
+ }
3001
+ else if (fileType === 'json') {
3002
+ download(toURL(JSON.stringify(leaf.toJSON(options.json)), 'text'), filename);
3003
+ return over({ data: true });
3004
+ }
3005
+ if (filename === 'svg') {
3006
+ return over({ data: leaf.toSVG() });
3007
+ }
3008
+ else if (fileType === 'svg') {
3009
+ download(toURL(leaf.toSVG(), 'svg'), filename);
3010
+ return over({ data: true });
3011
+ }
2753
3012
  const { leafer } = leaf;
2754
3013
  if (leafer) {
3014
+ checkLazy(leaf);
2755
3015
  leafer.waitViewCompleted(() => __awaiter(this, void 0, void 0, function* () {
2756
- let quality, blob;
2757
- let { canvas } = leafer;
2758
- let { unreal } = canvas;
2759
- if (unreal) {
2760
- canvas = canvas.getSameCanvas();
2761
- canvas.backgroundColor = leafer.config.fill;
2762
- leafer.__render(canvas, {});
3016
+ let renderBounds, trimBounds, scaleX = 1, scaleY = 1;
3017
+ const { worldTransform, isLeafer, isFrame } = leaf;
3018
+ const { slice, trim, onCanvas } = options;
3019
+ let scale = options.scale || 1;
3020
+ let pixelRatio = options.pixelRatio || 1;
3021
+ const smooth = options.smooth === undefined ? leafer.config.smooth : options.smooth;
3022
+ const contextSettings = options.contextSettings || leafer.config.contextSettings;
3023
+ if (leaf.isApp) {
3024
+ scale *= pixelRatio;
3025
+ pixelRatio = leaf.app.pixelRatio;
3026
+ }
3027
+ const screenshot = options.screenshot || leaf.isApp;
3028
+ const fill = (isLeafer && screenshot) ? (options.fill === undefined ? leaf.fill : options.fill) : options.fill;
3029
+ const needFill = FileHelper.isOpaqueImage(filename) || fill, matrix = new Matrix();
3030
+ if (screenshot) {
3031
+ renderBounds = screenshot === true ? (isLeafer ? leafer.canvas.bounds : leaf.worldRenderBounds) : screenshot;
2763
3032
  }
2764
- switch (typeof options) {
2765
- case 'object':
2766
- if (options.quality)
2767
- quality = options.quality;
2768
- if (options.blob)
2769
- blob = true;
2770
- break;
2771
- case 'number':
2772
- quality = options;
2773
- break;
2774
- case 'boolean':
2775
- blob = options;
3033
+ else {
3034
+ let relative = options.relative || (isLeafer ? 'inner' : 'local');
3035
+ scaleX = worldTransform.scaleX;
3036
+ scaleY = worldTransform.scaleY;
3037
+ switch (relative) {
3038
+ case 'inner':
3039
+ matrix.set(worldTransform);
3040
+ break;
3041
+ case 'local':
3042
+ matrix.set(worldTransform).divide(leaf.localTransform);
3043
+ scaleX /= leaf.scaleX;
3044
+ scaleY /= leaf.scaleY;
3045
+ break;
3046
+ case 'world':
3047
+ scaleX = 1;
3048
+ scaleY = 1;
3049
+ break;
3050
+ case 'page':
3051
+ relative = leaf.leafer;
3052
+ default:
3053
+ matrix.set(worldTransform).divide(leaf.getTransform(relative));
3054
+ const l = relative.worldTransform;
3055
+ scaleX /= scaleX / l.scaleX;
3056
+ scaleY /= scaleY / l.scaleY;
3057
+ }
3058
+ renderBounds = leaf.getBounds('render', relative);
2776
3059
  }
2777
- let data;
2778
- if (filename.includes('.')) {
2779
- data = yield canvas.saveAs(filename, quality);
3060
+ const { x, y, width, height } = new Bounds(renderBounds).scale(scale);
3061
+ let canvas = Creator.canvas({ width: Math.round(width), height: Math.round(height), pixelRatio, smooth, contextSettings });
3062
+ const renderOptions = { matrix: matrix.scale(1 / scale).invert().translate(-x, -y).withScale(1 / scaleX * scale, 1 / scaleY * scale) };
3063
+ let sliceLeaf;
3064
+ if (slice) {
3065
+ sliceLeaf = leaf;
3066
+ sliceLeaf.__worldOpacity = 0;
3067
+ leaf = leafer;
3068
+ renderOptions.bounds = canvas.bounds;
2780
3069
  }
2781
- else if (blob) {
2782
- data = yield canvas.toBlob(filename, quality);
3070
+ canvas.save();
3071
+ if (isFrame && fill !== undefined) {
3072
+ const oldFill = leaf.get('fill');
3073
+ leaf.fill = '';
3074
+ leaf.__render(canvas, renderOptions);
3075
+ leaf.fill = oldFill;
2783
3076
  }
2784
3077
  else {
2785
- data = yield canvas.toDataURL(filename, quality);
3078
+ leaf.__render(canvas, renderOptions);
2786
3079
  }
2787
- success({ data });
2788
- resolve();
2789
- Export.running = false;
2790
- if (unreal)
2791
- canvas.recycle();
3080
+ canvas.restore();
3081
+ if (sliceLeaf)
3082
+ sliceLeaf.__updateWorldOpacity();
3083
+ if (trim) {
3084
+ trimBounds = getTrimBounds(canvas);
3085
+ const old = canvas, { width, height } = trimBounds;
3086
+ const config = { x: 0, y: 0, width, height, pixelRatio };
3087
+ canvas = Creator.canvas(config);
3088
+ canvas.copyWorld(old, trimBounds, config);
3089
+ }
3090
+ if (needFill)
3091
+ canvas.fillWorld(canvas.bounds, fill || '#FFFFFF', 'destination-over');
3092
+ if (onCanvas)
3093
+ onCanvas(canvas);
3094
+ const data = filename === 'canvas' ? canvas : yield canvas.export(filename, options);
3095
+ over({ data, width: canvas.pixelWidth, height: canvas.pixelHeight, renderBounds, trimBounds });
2792
3096
  }));
2793
3097
  }
2794
3098
  else {
2795
- success({ data: false });
2796
- resolve();
2797
- Export.running = false;
3099
+ over({ data: false });
2798
3100
  }
2799
3101
  }));
2800
3102
  }
@@ -2807,13 +3109,64 @@ function addTask(task) {
2807
3109
  tasker.add(() => __awaiter(this, void 0, void 0, function* () { return yield task(resolve); }), { parallel: false });
2808
3110
  });
2809
3111
  }
3112
+ function checkLazy(leaf) {
3113
+ if (leaf.__.__needComputePaint)
3114
+ leaf.__.__computePaint();
3115
+ if (leaf.isBranch)
3116
+ leaf.children.forEach(child => checkLazy(child));
3117
+ }
3118
+
3119
+ const canvas = LeaferCanvasBase.prototype;
3120
+ const debug = Debug.get('@leafer-ui/export');
3121
+ canvas.export = function (filename, options) {
3122
+ const { quality, blob } = FileHelper.getExportOptions(options);
3123
+ if (filename.includes('.')) {
3124
+ return this.saveAs(filename, quality);
3125
+ }
3126
+ else if (blob) {
3127
+ return this.toBlob(filename, quality);
3128
+ }
3129
+ else {
3130
+ return this.toDataURL(filename, quality);
3131
+ }
3132
+ };
3133
+ canvas.toBlob = function (type, quality) {
3134
+ return new Promise((resolve) => {
3135
+ Platform.origin.canvasToBolb(this.view, type, quality).then((blob) => {
3136
+ resolve(blob);
3137
+ }).catch((e) => {
3138
+ debug.error(e);
3139
+ resolve(null);
3140
+ });
3141
+ });
3142
+ };
3143
+ canvas.toDataURL = function (type, quality) {
3144
+ return Platform.origin.canvasToDataURL(this.view, type, quality);
3145
+ };
3146
+ canvas.saveAs = function (filename, quality) {
3147
+ return new Promise((resolve) => {
3148
+ Platform.origin.canvasSaveAs(this.view, filename, quality).then(() => {
3149
+ resolve(true);
3150
+ }).catch((e) => {
3151
+ debug.error(e);
3152
+ resolve(false);
3153
+ });
3154
+ });
3155
+ };
2810
3156
 
2811
- Object.assign(Paint, UIPaint);
2812
- Object.assign(Effect, UIEffect);
2813
- Object.assign(TextConvert$1, TextConvert);
2814
- Object.assign(ColorConvert$1, ColorConvert);
2815
- Object.assign(Export$2, Export);
3157
+ Object.assign(TextConvert, TextConvertModule);
3158
+ Object.assign(ColorConvert, ColorConvertModule);
3159
+ Object.assign(Paint, PaintModule);
3160
+ Object.assign(PaintImage, PaintImageModule);
3161
+ Object.assign(PaintGradient, PaintGradientModule);
3162
+ Object.assign(Effect, EffectModule);
3163
+ Object.assign(Export, ExportModule);
2816
3164
 
3165
+ Object.assign(Creator, {
3166
+ interaction: (target, canvas, selector, options) => new Interaction(target, canvas, selector, options),
3167
+ hitCanvas: (options, manager) => new LeaferCanvas(options, manager),
3168
+ hitCanvasManager: () => new HitCanvasManager()
3169
+ });
2817
3170
  useCanvas();
2818
3171
 
2819
3172
  export { Interaction, Layouter, LeaferCanvas, Renderer, Selector, Watcher, useCanvas };