leafer-ui 1.0.0-rc.6 → 1.0.0-rc.7

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/README.md CHANGED
@@ -4,7 +4,7 @@ Leafer UI 是基于 Leafer 开发的一套绚丽多彩的 UI 绘图框架,可
4
4
 
5
5
  提供了常用的 UI 绘图组件,和开箱即用的功能,方便与 Figma、Sketch 等产品进行数据交换,并为跨平台开发提供了统一、丰富的交互事件,如拖拽、旋转、缩放手势等。
6
6
 
7
- 1.0.0-rc.6 已发布 🎉🎉🎉,查看 [更新日志](https://leaferjs.com/ui/update/)。
7
+ 1.0.0-rc.7 已发布 🎉🎉🎉,查看 [更新日志](https://leaferjs.com/ui/update/)。
8
8
 
9
9
  目前产品已经逐步稳定,正式版即将到来,感谢所有参与的朋友们~
10
10
 
package/dist/web.esm.js CHANGED
@@ -1,7 +1,7 @@
1
- import { LeafList, DataHelper, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, Bounds, LeafBoundsHelper, BoundsHelper, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, Platform, AnimateEvent, ResizeEvent, Creator, LeaferCanvasBase, Cursor, canvasSizeAttrs, canvasPatch, InteractionHelper, MathHelper, InteractionBase, LeaferImage, FileHelper, MatrixHelper, ImageEvent, PointHelper, TaskProcessor } from '@leafer/core';
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, TaskProcessor } 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$1 } from '@leafer-ui/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';
5
5
  export * from '@leafer-ui/core';
6
6
 
7
7
  class Watcher {
@@ -10,7 +10,7 @@ class Watcher {
10
10
  if (this.hasRemove) {
11
11
  const updatedList = new LeafList();
12
12
  this.__updatedList.list.forEach(item => { if (item.leafer)
13
- updatedList.push(item); });
13
+ updatedList.add(item); });
14
14
  return updatedList;
15
15
  }
16
16
  else {
@@ -45,7 +45,7 @@ class Watcher {
45
45
  this.target.emit(RenderEvent.REQUEST);
46
46
  }
47
47
  __onAttrChange(event) {
48
- this.__updatedList.push(event.target);
48
+ this.__updatedList.add(event.target);
49
49
  this.update();
50
50
  }
51
51
  __onChildEvent(event) {
@@ -55,12 +55,12 @@ class Watcher {
55
55
  }
56
56
  else {
57
57
  this.hasRemove = true;
58
- this.__updatedList.push(event.parent);
58
+ this.__updatedList.add(event.parent);
59
59
  }
60
60
  this.update();
61
61
  }
62
62
  __pushChild(child) {
63
- this.__updatedList.push(child);
63
+ this.__updatedList.add(child);
64
64
  if (child.isBranch)
65
65
  this.__loopChildren(child);
66
66
  }
@@ -99,7 +99,7 @@ class Watcher {
99
99
  }
100
100
  }
101
101
 
102
- const { updateAllWorldMatrix: updateAllWorldMatrix$1, updateAllWorldOpacity } = LeafHelper;
102
+ const { updateAllMatrix: updateAllMatrix$1, updateBounds: updateOneBounds, updateAllWorldOpacity } = LeafHelper;
103
103
  const { pushAllChildBranch, pushAllParent } = BranchHelper;
104
104
  function updateMatrix(updateList, levelList) {
105
105
  let layout;
@@ -107,14 +107,14 @@ function updateMatrix(updateList, levelList) {
107
107
  layout = leaf.__layout;
108
108
  if (levelList.without(leaf) && !layout.proxyZoom) {
109
109
  if (layout.matrixChanged) {
110
- updateAllWorldMatrix$1(leaf);
111
- levelList.push(leaf);
110
+ updateAllMatrix$1(leaf, true);
111
+ levelList.add(leaf);
112
112
  if (leaf.isBranch)
113
113
  pushAllChildBranch(leaf, levelList);
114
114
  pushAllParent(leaf, levelList);
115
115
  }
116
116
  else if (layout.boundsChanged) {
117
- levelList.push(leaf);
117
+ levelList.add(leaf);
118
118
  if (leaf.isBranch)
119
119
  leaf.__tempNumber = 0;
120
120
  pushAllParent(leaf, levelList);
@@ -123,20 +123,21 @@ function updateMatrix(updateList, levelList) {
123
123
  });
124
124
  }
125
125
  function updateBounds(boundsList) {
126
- let itemList, branch;
126
+ let list, branch, children;
127
127
  boundsList.sort(true);
128
128
  boundsList.levels.forEach(level => {
129
- itemList = boundsList.levelMap[level];
130
- for (let i = 0, len = itemList.length; i < len; i++) {
131
- branch = itemList[i];
129
+ list = boundsList.levelMap[level];
130
+ for (let i = 0, len = list.length; i < len; i++) {
131
+ branch = list[i];
132
132
  if (branch.isBranch && branch.__tempNumber) {
133
- for (let j = 0, jLen = branch.children.length; j < jLen; j++) {
134
- if (!branch.children[j].isBranch) {
135
- branch.children[j].__updateWorldBounds();
133
+ children = branch.children;
134
+ for (let j = 0, jLen = children.length; j < jLen; j++) {
135
+ if (!children[j].isBranch) {
136
+ updateOneBounds(children[j]);
136
137
  }
137
138
  }
138
139
  }
139
- branch.__updateWorldBounds();
140
+ updateOneBounds(branch);
140
141
  }
141
142
  });
142
143
  }
@@ -149,7 +150,7 @@ function updateChange(updateList) {
149
150
  }
150
151
 
151
152
  const { worldBounds } = LeafBoundsHelper;
152
- const { setByListWithHandle } = BoundsHelper;
153
+ const bigBounds = { x: 0, y: 0, width: 100000, height: 100000 };
153
154
  class LayoutBlockData {
154
155
  constructor(list) {
155
156
  this.updatedBounds = new Bounds();
@@ -160,14 +161,20 @@ class LayoutBlockData {
160
161
  this.updatedList = list;
161
162
  }
162
163
  setBefore() {
163
- setByListWithHandle(this.beforeBounds, this.updatedList.list, worldBounds);
164
+ this.beforeBounds.setListWithFn(this.updatedList.list, worldBounds);
164
165
  }
165
166
  setAfter() {
166
- setByListWithHandle(this.afterBounds, this.updatedList.list, worldBounds);
167
- this.updatedBounds.setByList([this.beforeBounds, this.afterBounds]);
167
+ const { list } = this.updatedList;
168
+ if (list.some(leaf => leaf.noBounds)) {
169
+ this.afterBounds.set(bigBounds);
170
+ }
171
+ else {
172
+ this.afterBounds.setListWithFn(list, worldBounds);
173
+ }
174
+ this.updatedBounds.setList([this.beforeBounds, this.afterBounds]);
168
175
  }
169
176
  merge(data) {
170
- this.updatedList.pushList(data.updatedList.list);
177
+ this.updatedList.addList(data.updatedList.list);
171
178
  this.beforeBounds.add(data.beforeBounds);
172
179
  this.afterBounds.add(data.afterBounds);
173
180
  this.updatedBounds.add(data.updatedBounds);
@@ -177,8 +184,7 @@ class LayoutBlockData {
177
184
  }
178
185
  }
179
186
 
180
- const { updateAllWorldMatrix, updateAllChange } = LeafHelper;
181
- const { pushAllBranchStack, updateWorldBoundsByBranchStack } = BranchHelper;
187
+ const { updateAllMatrix, updateAllChange } = LeafHelper;
182
188
  const debug$2 = Debug.get('Layouter');
183
189
  class Layouter {
184
190
  constructor(target, userConfig) {
@@ -255,12 +261,15 @@ class Layouter {
255
261
  const { target, __updatedList: updateList } = this;
256
262
  const { BEFORE, LAYOUT, AFTER } = LayoutEvent;
257
263
  const blocks = this.getBlocks(updateList);
258
- blocks.forEach(item => { item.setBefore(); });
264
+ blocks.forEach(item => item.setBefore());
259
265
  target.emitEvent(new LayoutEvent(BEFORE, blocks, this.times));
266
+ this.extraBlock = null;
260
267
  updateList.sort();
261
268
  updateMatrix(updateList, this.__levelList);
262
269
  updateBounds(this.__levelList);
263
270
  updateChange(updateList);
271
+ if (this.extraBlock)
272
+ blocks.push(this.extraBlock);
264
273
  blocks.forEach(item => item.setAfter());
265
274
  target.emitEvent(new LayoutEvent(LAYOUT, blocks, this.times));
266
275
  target.emitEvent(new LayoutEvent(AFTER, blocks, this.times));
@@ -283,17 +292,20 @@ class Layouter {
283
292
  Run.end(t);
284
293
  }
285
294
  static fullLayout(target) {
286
- updateAllWorldMatrix(target);
295
+ updateAllMatrix(target, true);
287
296
  if (target.isBranch) {
288
- const branchStack = [target];
289
- pushAllBranchStack(target, branchStack);
290
- updateWorldBoundsByBranchStack(branchStack);
297
+ BranchHelper.updateBounds(target);
291
298
  }
292
299
  else {
293
- target.__updateWorldBounds();
300
+ LeafHelper.updateBounds(target);
294
301
  }
295
302
  updateAllChange(target);
296
303
  }
304
+ addExtra(leaf) {
305
+ const block = this.extraBlock || (this.extraBlock = new LayoutBlockData([]));
306
+ block.updatedList.add(leaf);
307
+ block.beforeBounds.add(leaf.__world);
308
+ }
297
309
  createBlock(data) {
298
310
  return new LayoutBlockData(data);
299
311
  }
@@ -321,8 +333,7 @@ class Layouter {
321
333
  if (this.target) {
322
334
  this.stop();
323
335
  this.__removeListenEvents();
324
- this.target = null;
325
- this.config = null;
336
+ this.target = this.config = null;
326
337
  }
327
338
  }
328
339
  }
@@ -433,7 +444,7 @@ class Renderer {
433
444
  const { canvas } = this;
434
445
  const bounds = block.getIntersect(canvas.bounds);
435
446
  const includes = block.includes(this.target.__world);
436
- const realBounds = new Bounds().copy(bounds);
447
+ const realBounds = new Bounds(bounds);
437
448
  canvas.save();
438
449
  if (includes && !Debug.showRepaint) {
439
450
  canvas.clear();
@@ -483,7 +494,7 @@ class Renderer {
483
494
  const { updateBlocks: list } = this;
484
495
  if (list) {
485
496
  const bounds = new Bounds();
486
- bounds.setByList(list);
497
+ bounds.setList(list);
487
498
  list.length = 0;
488
499
  list.push(bounds);
489
500
  }
@@ -523,7 +534,7 @@ class Renderer {
523
534
  empty = (!leaf.__world.width || !leaf.__world.height);
524
535
  if (empty) {
525
536
  if (!leaf.isLeafer)
526
- debug$1.warn(leaf.innerName, ': empty');
537
+ debug$1.tip(leaf.innerName, ': empty');
527
538
  empty = (!leaf.isBranch || leaf.isBranchLeaf);
528
539
  }
529
540
  return empty;
@@ -557,6 +568,14 @@ class Renderer {
557
568
  }
558
569
  }
559
570
 
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
+
560
579
  const { hitRadiusPoint } = BoundsHelper;
561
580
  class Pather {
562
581
  constructor(target, selector) {
@@ -601,10 +620,10 @@ class Pather {
601
620
  getPath(leaf) {
602
621
  const path = new LeafList();
603
622
  while (leaf) {
604
- path.push(leaf);
623
+ path.add(leaf);
605
624
  leaf = leaf.parent;
606
625
  }
607
- path.push(this.target);
626
+ path.add(this.target);
608
627
  return path;
609
628
  }
610
629
  getHitablePath(leaf) {
@@ -614,7 +633,7 @@ class Pather {
614
633
  item = path.list[i];
615
634
  if (!item.__.hittable)
616
635
  break;
617
- hittablePath.unshift(item);
636
+ hittablePath.addAt(item, 0);
618
637
  if (!item.__.hitChildren)
619
638
  break;
620
639
  }
@@ -633,7 +652,7 @@ class Pather {
633
652
  leaf = path.list[j];
634
653
  if (nextPath && nextPath.has(leaf))
635
654
  break;
636
- throughPath.push(leaf);
655
+ throughPath.add(leaf);
637
656
  }
638
657
  }
639
658
  return throughPath;
@@ -675,14 +694,15 @@ class Pather {
675
694
  }
676
695
  }
677
696
 
697
+ const { Yes, NoAndSkip, YesAndSkip } = AnswerType;
678
698
  class Selector {
679
699
  constructor(target, userConfig) {
680
700
  this.config = {};
681
701
  this.innerIdMap = {};
682
702
  this.idMap = {};
683
703
  this.methods = {
684
- id: (leaf, name) => leaf.id === name ? this.idMap[name] = leaf : 0,
685
- innerId: (leaf, innerId) => leaf.innerId === innerId ? this.innerIdMap[innerId] = leaf : 0,
704
+ id: (leaf, name) => leaf.id === name ? (this.idMap[name] = leaf, 1) : 0,
705
+ innerId: (leaf, innerId) => leaf.innerId === innerId ? (this.innerIdMap[innerId] = leaf, 1) : 0,
686
706
  className: (leaf, name) => leaf.className === name ? 1 : 0,
687
707
  tag: (leaf, name) => leaf.__tag === name ? 1 : 0
688
708
  };
@@ -692,11 +712,6 @@ class Selector {
692
712
  this.pather = new Pather(target, this);
693
713
  this.__listenEvents();
694
714
  }
695
- getByPoint(hitPoint, hitRadius, options) {
696
- if (Platform.name === 'node')
697
- this.target.emit(LayoutEvent.CHECK_UPDATE);
698
- return this.pather.getByPoint(hitPoint, hitRadius, options);
699
- }
700
715
  getBy(condition, branch, one, options) {
701
716
  switch (typeof condition) {
702
717
  case 'number':
@@ -716,6 +731,11 @@ class Selector {
716
731
  return this.getByMethod(condition, branch, one, options);
717
732
  }
718
733
  }
734
+ getByPoint(hitPoint, hitRadius, options) {
735
+ if (Platform.name === 'node')
736
+ this.target.emit(LayoutEvent.CHECK_UPDATE);
737
+ return this.pather.getByPoint(hitPoint, hitRadius, options);
738
+ }
719
739
  getByInnerId(innerId, branch) {
720
740
  const cache = this.innerIdMap[innerId];
721
741
  if (cache)
@@ -742,10 +762,11 @@ class Selector {
742
762
  return list || this.findLeaf;
743
763
  }
744
764
  eachFind(children, method, list, options) {
745
- let child;
765
+ let child, result;
746
766
  for (let i = 0, len = children.length; i < len; i++) {
747
767
  child = children[i];
748
- if (method(child, options)) {
768
+ result = method(child, options);
769
+ if (result === Yes || result === YesAndSkip) {
749
770
  if (list) {
750
771
  list.push(child);
751
772
  }
@@ -754,7 +775,7 @@ class Selector {
754
775
  return;
755
776
  }
756
777
  }
757
- if (child.isBranch)
778
+ if (child.isBranch && result < NoAndSkip)
758
779
  this.eachFind(child.children, method, list, options);
759
780
  }
760
781
  }
@@ -1325,8 +1346,8 @@ function useCanvas(_canvasType, _power) {
1325
1346
  img.crossOrigin = 'anonymous';
1326
1347
  img.onload = () => { resolve(img); };
1327
1348
  img.onerror = (e) => { reject(e); };
1328
- if (!src.startsWith('data:') && Platform.imageSuffix)
1329
- src += (src.includes("?") ? "&" : "?") + Platform.imageSuffix;
1349
+ if (!src.startsWith('data:') && Platform.image.suffix)
1350
+ src += (src.includes("?") ? "&" : "?") + Platform.image.suffix;
1330
1351
  img.src = src;
1331
1352
  });
1332
1353
  }
@@ -1342,8 +1363,7 @@ function useCanvas(_canvasType, _power) {
1342
1363
  Platform.name = 'web';
1343
1364
  Platform.isMobile = 'ontouchstart' in window;
1344
1365
  Platform.requestRender = function (render) { window.requestAnimationFrame(render); };
1345
- Platform.devicePixelRatio = devicePixelRatio;
1346
- Platform.realtimeLayout = true;
1366
+ Platform.devicePixelRatio = Math.max(1, devicePixelRatio);
1347
1367
  const { userAgent } = navigator;
1348
1368
  if (userAgent.indexOf("Firefox") > -1) {
1349
1369
  Platform.conicGradientRotate90 = true;
@@ -1364,7 +1384,7 @@ else if (userAgent.indexOf('Linux') > -1) {
1364
1384
  Platform.os = 'Linux';
1365
1385
  }
1366
1386
 
1367
- const { get: get$4, rotateOfOuter: rotateOfOuter$2, translate: translate$1, scaleOfOuter: scaleOfOuter$2, scale: scaleHelper$1, rotate } = MatrixHelper;
1387
+ const { get: get$4, rotateOfOuter: rotateOfOuter$2, translate: translate$1, scaleOfOuter: scaleOfOuter$2, scale: scaleHelper, rotate } = MatrixHelper;
1368
1388
  function fillOrFitMode(data, mode, box, width, height, rotation) {
1369
1389
  const transform = get$4();
1370
1390
  const swap = rotation && rotation !== 180;
@@ -1374,7 +1394,7 @@ function fillOrFitMode(data, mode, box, width, height, rotation) {
1374
1394
  const x = box.x + (box.width - width * scale) / 2;
1375
1395
  const y = box.y + (box.height - height * scale) / 2;
1376
1396
  translate$1(transform, x, y);
1377
- scaleHelper$1(transform, scale);
1397
+ scaleHelper(transform, scale);
1378
1398
  if (rotation)
1379
1399
  rotateOfOuter$2(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
1380
1400
  data.scaleX = data.scaleY = scale;
@@ -1386,7 +1406,7 @@ function clipMode(data, box, offset, scale, rotation) {
1386
1406
  if (offset)
1387
1407
  translate$1(transform, offset.x, offset.y);
1388
1408
  if (scale) {
1389
- typeof scale === 'number' ? scaleHelper$1(transform, scale) : scaleHelper$1(transform, scale.x, scale.y);
1409
+ typeof scale === 'number' ? scaleHelper(transform, scale) : scaleHelper(transform, scale.x, scale.y);
1390
1410
  data.scaleX = transform.a;
1391
1411
  data.scaleY = transform.d;
1392
1412
  }
@@ -1499,6 +1519,10 @@ function hasNaturalSize(ui, attrName, image) {
1499
1519
  d.__naturalWidth = image.width;
1500
1520
  d.__naturalHeight = image.height;
1501
1521
  if (!d.__getInput('width') || !d.__getInput('height')) {
1522
+ if (ui.__proxyData) {
1523
+ ui.setProxyAttr('width', ui.__.width);
1524
+ ui.setProxyAttr('height', ui.__.height);
1525
+ }
1502
1526
  ui.forceUpdate('width');
1503
1527
  return false;
1504
1528
  }
@@ -1542,22 +1566,21 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
1542
1566
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1543
1567
  };
1544
1568
 
1545
- const { get: get$2, scale: scaleHelper, copy: copy$1 } = MatrixHelper;
1569
+ const Export$1 = {};
1570
+
1571
+ const { get: get$2, scale, copy: copy$1 } = MatrixHelper;
1546
1572
  function createPattern(ui, paint, pixelRatio) {
1547
1573
  let { scaleX, scaleY } = ui.__world;
1548
1574
  const id = scaleX + '-' + scaleY;
1549
1575
  if (paint.patternId !== id && !ui.destroyed) {
1550
- paint.patternId = id;
1551
1576
  scaleX = Math.abs(scaleX);
1552
1577
  scaleY = Math.abs(scaleY);
1553
1578
  const { image, data } = paint;
1554
- const maxWidth = image.isSVG ? 4096 : Math.min(image.width, 4096);
1555
- const maxHeight = image.isSVG ? 4096 : Math.min(image.height, 4096);
1556
- let scale, matrix, { width, height, scaleX: sx, scaleY: sy, opacity, transform, mode } = data;
1579
+ let imageScale, imageMatrix, { width, height, scaleX: sx, scaleY: sy, opacity, transform, mode } = data;
1557
1580
  if (sx) {
1558
- matrix = get$2();
1559
- copy$1(matrix, transform);
1560
- scaleHelper(matrix, 1 / sx, 1 / sy);
1581
+ imageMatrix = get$2();
1582
+ copy$1(imageMatrix, transform);
1583
+ scale(imageMatrix, 1 / sx, 1 / sy);
1561
1584
  scaleX *= sx;
1562
1585
  scaleY *= sy;
1563
1586
  }
@@ -1565,38 +1588,49 @@ function createPattern(ui, paint, pixelRatio) {
1565
1588
  scaleY *= pixelRatio;
1566
1589
  width *= scaleX;
1567
1590
  height *= scaleY;
1568
- if (width > maxWidth || height > maxHeight) {
1569
- scale = Math.max(width / maxWidth, height / maxHeight);
1570
- }
1571
- if (scale) {
1572
- scaleX /= scale;
1573
- scaleY /= scale;
1574
- width /= scale;
1575
- height /= scale;
1591
+ const size = width * height;
1592
+ if (paint.data.mode !== 'repeat') {
1593
+ if (size > Platform.image.maxCacheSize)
1594
+ return false;
1595
+ }
1596
+ let maxSize = Platform.image.maxPatternSize;
1597
+ if (!image.isSVG) {
1598
+ const imageSize = image.width * image.height;
1599
+ if (maxSize > imageSize)
1600
+ maxSize = imageSize;
1601
+ }
1602
+ if (size > maxSize)
1603
+ imageScale = Math.sqrt(size / maxSize);
1604
+ if (imageScale) {
1605
+ scaleX /= imageScale;
1606
+ scaleY /= imageScale;
1607
+ width /= imageScale;
1608
+ height /= imageScale;
1576
1609
  }
1577
1610
  if (sx) {
1578
1611
  scaleX /= sx;
1579
1612
  scaleY /= sy;
1580
1613
  }
1581
1614
  if (transform || scaleX !== 1 || scaleY !== 1) {
1582
- if (!matrix) {
1583
- matrix = get$2();
1615
+ if (!imageMatrix) {
1616
+ imageMatrix = get$2();
1584
1617
  if (transform)
1585
- copy$1(matrix, transform);
1618
+ copy$1(imageMatrix, transform);
1586
1619
  }
1587
- scaleHelper(matrix, 1 / scaleX, 1 / scaleY);
1620
+ scale(imageMatrix, 1 / scaleX, 1 / scaleY);
1588
1621
  }
1589
- const style = Platform.canvas.createPattern(image.getCanvas(width < 1 ? 1 : width, height < 1 ? 1 : height, opacity), mode === 'repeat' ? 'repeat' : (Platform.origin.noRepeat || 'no-repeat'));
1622
+ const pattern = Platform.canvas.createPattern(image.getCanvas(width < 1 ? 1 : width, height < 1 ? 1 : height, opacity), mode === 'repeat' ? 'repeat' : (Platform.origin.noRepeat || 'no-repeat'));
1590
1623
  try {
1591
1624
  if (paint.transform)
1592
1625
  paint.transform = null;
1593
- if (matrix)
1594
- style.setTransform ? style.setTransform(matrix) : paint.transform = matrix;
1626
+ if (imageMatrix)
1627
+ pattern.setTransform ? pattern.setTransform(imageMatrix) : paint.transform = imageMatrix;
1595
1628
  }
1596
1629
  catch (_a) {
1597
- paint.transform = matrix;
1630
+ paint.transform = imageMatrix;
1598
1631
  }
1599
- paint.style = style;
1632
+ paint.style = pattern;
1633
+ paint.patternId = id;
1600
1634
  return true;
1601
1635
  }
1602
1636
  else {
@@ -1604,18 +1638,24 @@ function createPattern(ui, paint, pixelRatio) {
1604
1638
  }
1605
1639
  }
1606
1640
 
1641
+ const { abs } = Math;
1607
1642
  function checkImage(ui, canvas, paint, allowPaint) {
1608
1643
  const { scaleX, scaleY } = ui.__world;
1609
1644
  if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
1610
1645
  return false;
1611
1646
  }
1612
1647
  else {
1648
+ const { data } = paint;
1613
1649
  if (allowPaint) {
1614
- if (paint.image.isSVG && paint.data.mode !== 'repeat') {
1615
- let { width, height } = paint.data;
1616
- width *= scaleX * canvas.pixelRatio;
1617
- height *= scaleY * canvas.pixelRatio;
1618
- allowPaint = width > 4096 || height > 4096;
1650
+ if (data.mode !== 'repeat') {
1651
+ let { width, height } = data;
1652
+ width *= abs(scaleX) * canvas.pixelRatio;
1653
+ height *= abs(scaleY) * canvas.pixelRatio;
1654
+ if (data.scaleX) {
1655
+ width *= data.scaleX;
1656
+ height *= data.scaleY;
1657
+ }
1658
+ allowPaint = width * height > Platform.image.maxCacheSize;
1619
1659
  }
1620
1660
  else {
1621
1661
  allowPaint = false;
@@ -1624,7 +1664,6 @@ function checkImage(ui, canvas, paint, allowPaint) {
1624
1664
  if (allowPaint) {
1625
1665
  canvas.save();
1626
1666
  canvas.clip();
1627
- const { data } = paint;
1628
1667
  if (paint.blendMode)
1629
1668
  canvas.blendMode = paint.blendMode;
1630
1669
  if (data.opacity)
@@ -1636,7 +1675,7 @@ function checkImage(ui, canvas, paint, allowPaint) {
1636
1675
  return true;
1637
1676
  }
1638
1677
  else {
1639
- if (!paint.style) {
1678
+ if (!paint.style || Export$1.running) {
1640
1679
  createPattern(ui, paint, canvas.pixelRatio);
1641
1680
  }
1642
1681
  else {
@@ -1655,7 +1694,7 @@ function checkImage(ui, canvas, paint, allowPaint) {
1655
1694
  }
1656
1695
 
1657
1696
  function recycleImage(attrName, data) {
1658
- const paints = (attrName === 'fill' ? data._fill : data._stroke);
1697
+ const paints = data['_' + attrName];
1659
1698
  if (paints instanceof Array) {
1660
1699
  let image, recycleMap, input, url;
1661
1700
  for (let i = 0, len = paints.length; i < len; i++) {
@@ -1759,7 +1798,7 @@ function drawAlignStroke(align, stroke, isStrokes, ui, canvas, renderOptions) {
1759
1798
  out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
1760
1799
  fillText(ui, out);
1761
1800
  out.blendMode = 'normal';
1762
- if (ui.__hasMirror || renderOptions.matrix) {
1801
+ if (ui.__worldFlipped || renderOptions.matrix) {
1763
1802
  canvas.copyWorldByReset(out);
1764
1803
  }
1765
1804
  else {
@@ -1832,7 +1871,7 @@ function stroke(stroke, ui, canvas, renderOptions) {
1832
1871
  out.stroke();
1833
1872
  options.windingRule ? out.clip(options.windingRule) : out.clip();
1834
1873
  out.clearWorld(ui.__layout.renderBounds);
1835
- if (ui.__hasMirror || renderOptions.matrix) {
1874
+ if (ui.__worldFlipped || renderOptions.matrix) {
1836
1875
  canvas.copyWorldByReset(out);
1837
1876
  }
1838
1877
  else {
@@ -1872,7 +1911,7 @@ function strokes(strokes, ui, canvas, renderOptions) {
1872
1911
  drawStrokesStyle(strokes, false, ui, out);
1873
1912
  options.windingRule ? out.clip(options.windingRule) : out.clip();
1874
1913
  out.clearWorld(renderBounds);
1875
- if (ui.__hasMirror || renderOptions.matrix) {
1914
+ if (ui.__worldFlipped || renderOptions.matrix) {
1876
1915
  canvas.copyWorldByReset(out);
1877
1916
  }
1878
1917
  else {
@@ -2096,7 +2135,7 @@ function shadow(ui, current, shape, renderOptions) {
2096
2135
  }
2097
2136
  worldCanvas ? other.copyWorld(worldCanvas, __world, __world, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
2098
2137
  }
2099
- if (ui.__hasMirror || renderOptions.matrix) {
2138
+ if (ui.__worldFlipped || renderOptions.matrix) {
2100
2139
  current.copyWorldByReset(other, copyBounds, __world, item.blendMode);
2101
2140
  }
2102
2141
  else {
@@ -2160,7 +2199,7 @@ function innerShadow(ui, current, shape, renderOptions) {
2160
2199
  copyBounds = bounds;
2161
2200
  }
2162
2201
  other.fillWorld(copyBounds, item.color, 'source-in');
2163
- if (ui.__hasMirror || renderOptions.matrix) {
2202
+ if (ui.__worldFlipped || renderOptions.matrix) {
2164
2203
  current.copyWorldByReset(other, copyBounds, __world, item.blendMode);
2165
2204
  }
2166
2205
  else {
@@ -2658,6 +2697,7 @@ const ColorConvert = {
2658
2697
 
2659
2698
  const Export = {
2660
2699
  export(leaf, filename, options) {
2700
+ Export.running = true;
2661
2701
  return addTask((success) => new Promise((resolve) => {
2662
2702
  const { leafer } = leaf;
2663
2703
  if (leafer) {
@@ -2695,6 +2735,7 @@ const Export = {
2695
2735
  }
2696
2736
  success({ data });
2697
2737
  resolve();
2738
+ Export.running = false;
2698
2739
  if (unreal)
2699
2740
  canvas.recycle();
2700
2741
  }));
@@ -2702,6 +2743,7 @@ const Export = {
2702
2743
  else {
2703
2744
  success({ data: false });
2704
2745
  resolve();
2746
+ Export.running = false;
2705
2747
  }
2706
2748
  }));
2707
2749
  }
@@ -2719,7 +2761,7 @@ Object.assign(Paint, UIPaint);
2719
2761
  Object.assign(Effect, UIEffect);
2720
2762
  Object.assign(TextConvert$1, TextConvert);
2721
2763
  Object.assign(ColorConvert$1, ColorConvert);
2722
- Object.assign(Export$1, Export);
2764
+ Object.assign(Export$2, Export);
2723
2765
 
2724
2766
  useCanvas();
2725
2767