leafer-draw 1.0.0-rc.9 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/web.esm.js +379 -205
- package/dist/web.esm.min.js +1 -1
- package/dist/web.js +1957 -1260
- package/dist/web.min.js +1 -1
- package/dist/web.module.js +1938 -1260
- package/dist/web.module.min.js +1 -1
- package/package.json +8 -4
package/dist/web.esm.js
CHANGED
|
@@ -1,21 +1,41 @@
|
|
|
1
|
-
import { Debug, LeaferCanvasBase, Platform, DataHelper, canvasSizeAttrs, ResizeEvent, canvasPatch, Creator, LeaferImage, FileHelper, LeafList, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, Bounds, LeafBoundsHelper, LeafLevelList, LayoutEvent, Run, ImageManager, AnimateEvent, BoundsHelper, MatrixHelper, ImageEvent, PointHelper, Direction4, TwoPointBoundsHelper, TaskProcessor, Matrix } from '@leafer/core';
|
|
1
|
+
import { Debug, LeaferCanvasBase, Platform, DataHelper, canvasSizeAttrs, ResizeEvent, canvasPatch, Creator, LeaferImage, FileHelper, LeafList, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, Bounds, LeafBoundsHelper, LeafLevelList, LayoutEvent, Run, ImageManager, AnimateEvent, BoundsHelper, 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, Export, Group, TextConvert, Paint,
|
|
4
|
+
import { PaintImage, ColorConvert, PaintGradient, Export, Group, TextConvert, Paint, Effect } from '@leafer-ui/draw';
|
|
5
5
|
export * from '@leafer-ui/draw';
|
|
6
6
|
|
|
7
|
-
const debug$
|
|
7
|
+
const debug$3 = Debug.get('LeaferCanvas');
|
|
8
8
|
class LeaferCanvas extends LeaferCanvasBase {
|
|
9
|
+
set zIndex(zIndex) {
|
|
10
|
+
const { style } = this.view;
|
|
11
|
+
style.zIndex = zIndex;
|
|
12
|
+
this.setAbsolute(this.view);
|
|
13
|
+
}
|
|
14
|
+
set childIndex(index) {
|
|
15
|
+
const { view, parentView } = this;
|
|
16
|
+
if (view && parentView) {
|
|
17
|
+
const beforeNode = parentView.children[index];
|
|
18
|
+
if (beforeNode) {
|
|
19
|
+
this.setAbsolute(beforeNode);
|
|
20
|
+
parentView.insertBefore(view, beforeNode);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
parentView.appendChild(beforeNode);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
9
27
|
init() {
|
|
10
28
|
const { view } = this.config;
|
|
11
29
|
view ? this.__createViewFrom(view) : this.__createView();
|
|
12
30
|
const { style } = this.view;
|
|
13
31
|
style.display || (style.display = 'block');
|
|
14
32
|
this.parentView = this.view.parentElement;
|
|
15
|
-
if (this.parentView)
|
|
16
|
-
this.parentView.style
|
|
33
|
+
if (this.parentView) {
|
|
34
|
+
const pStyle = this.parentView.style;
|
|
35
|
+
pStyle.webkitUserSelect = pStyle.userSelect = 'none';
|
|
36
|
+
}
|
|
17
37
|
if (Platform.syncDomFont && !this.parentView) {
|
|
18
|
-
|
|
38
|
+
style.display = 'none';
|
|
19
39
|
document.body.appendChild(this.view);
|
|
20
40
|
}
|
|
21
41
|
this.__createContext();
|
|
@@ -48,19 +68,22 @@ class LeaferCanvas extends LeaferCanvasBase {
|
|
|
48
68
|
this.__createView();
|
|
49
69
|
const view = this.view;
|
|
50
70
|
if (parent.hasChildNodes()) {
|
|
51
|
-
|
|
52
|
-
style.position = 'absolute';
|
|
53
|
-
style.top = style.left = '0px';
|
|
71
|
+
this.setAbsolute(view);
|
|
54
72
|
parent.style.position || (parent.style.position = 'relative');
|
|
55
73
|
}
|
|
56
74
|
parent.appendChild(view);
|
|
57
75
|
}
|
|
58
76
|
}
|
|
59
77
|
else {
|
|
60
|
-
debug$
|
|
78
|
+
debug$3.error(`no id: ${inputView}`);
|
|
61
79
|
this.__createView();
|
|
62
80
|
}
|
|
63
81
|
}
|
|
82
|
+
setAbsolute(view) {
|
|
83
|
+
const { style } = view;
|
|
84
|
+
style.position = 'absolute';
|
|
85
|
+
style.top = style.left = '0px';
|
|
86
|
+
}
|
|
64
87
|
updateViewSize() {
|
|
65
88
|
const { width, height, pixelRatio } = this;
|
|
66
89
|
const { style } = this.view;
|
|
@@ -86,6 +109,10 @@ class LeaferCanvas extends LeaferCanvasBase {
|
|
|
86
109
|
this.resizeObserver.observe(parent);
|
|
87
110
|
this.checkAutoBounds(parent.getBoundingClientRect());
|
|
88
111
|
}
|
|
112
|
+
else {
|
|
113
|
+
this.checkAutoBounds(this.view);
|
|
114
|
+
debug$3.warn('no parent');
|
|
115
|
+
}
|
|
89
116
|
}
|
|
90
117
|
catch (_a) {
|
|
91
118
|
this.imitateResizeObserver();
|
|
@@ -163,9 +190,13 @@ function useCanvas(_canvasType, _power) {
|
|
|
163
190
|
canvasToDataURL: (canvas, type, quality) => canvas.toDataURL(mineType(type), quality),
|
|
164
191
|
canvasToBolb: (canvas, type, quality) => new Promise((resolve) => canvas.toBlob(resolve, mineType(type), quality)),
|
|
165
192
|
canvasSaveAs: (canvas, filename, quality) => {
|
|
193
|
+
const url = canvas.toDataURL(mineType(fileType(filename)), quality);
|
|
194
|
+
return Platform.origin.download(url, filename);
|
|
195
|
+
},
|
|
196
|
+
download(url, filename) {
|
|
166
197
|
return new Promise((resolve) => {
|
|
167
198
|
let el = document.createElement('a');
|
|
168
|
-
el.href =
|
|
199
|
+
el.href = url;
|
|
169
200
|
el.download = filename;
|
|
170
201
|
document.body.appendChild(el);
|
|
171
202
|
el.click();
|
|
@@ -176,16 +207,14 @@ function useCanvas(_canvasType, _power) {
|
|
|
176
207
|
loadImage(src) {
|
|
177
208
|
return new Promise((resolve, reject) => {
|
|
178
209
|
const img = new Image();
|
|
179
|
-
const {
|
|
210
|
+
const { crossOrigin } = Platform.image;
|
|
180
211
|
if (crossOrigin) {
|
|
181
212
|
img.setAttribute('crossOrigin', crossOrigin);
|
|
182
213
|
img.crossOrigin = crossOrigin;
|
|
183
214
|
}
|
|
184
215
|
img.onload = () => { resolve(img); };
|
|
185
216
|
img.onerror = (e) => { reject(e); };
|
|
186
|
-
|
|
187
|
-
src += (src.includes("?") ? "&" : "?") + suffix;
|
|
188
|
-
img.src = src;
|
|
217
|
+
img.src = Platform.image.getRealURL(src);
|
|
189
218
|
});
|
|
190
219
|
}
|
|
191
220
|
};
|
|
@@ -402,7 +431,7 @@ class LayoutBlockData {
|
|
|
402
431
|
}
|
|
403
432
|
|
|
404
433
|
const { updateAllMatrix, updateAllChange } = LeafHelper;
|
|
405
|
-
const debug$
|
|
434
|
+
const debug$2 = Debug.get('Layouter');
|
|
406
435
|
class Layouter {
|
|
407
436
|
constructor(target, userConfig) {
|
|
408
437
|
this.totalTimes = 0;
|
|
@@ -437,7 +466,7 @@ class Layouter {
|
|
|
437
466
|
target.emitEvent(new LayoutEvent(LayoutEvent.END, this.layoutedBlocks, this.times));
|
|
438
467
|
}
|
|
439
468
|
catch (e) {
|
|
440
|
-
debug$
|
|
469
|
+
debug$2.error(e);
|
|
441
470
|
}
|
|
442
471
|
this.layoutedBlocks = null;
|
|
443
472
|
}
|
|
@@ -451,9 +480,9 @@ class Layouter {
|
|
|
451
480
|
}
|
|
452
481
|
layoutOnce() {
|
|
453
482
|
if (this.layouting)
|
|
454
|
-
return debug$
|
|
483
|
+
return debug$2.warn('layouting');
|
|
455
484
|
if (this.times > 3)
|
|
456
|
-
return debug$
|
|
485
|
+
return debug$2.warn('layout max times');
|
|
457
486
|
this.times++;
|
|
458
487
|
this.totalTimes++;
|
|
459
488
|
this.layouting = true;
|
|
@@ -519,9 +548,11 @@ class Layouter {
|
|
|
519
548
|
updateAllChange(target);
|
|
520
549
|
}
|
|
521
550
|
addExtra(leaf) {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
551
|
+
if (!this.__updatedList.has(leaf)) {
|
|
552
|
+
const { updatedList, beforeBounds } = this.extraBlock || (this.extraBlock = new LayoutBlockData([]));
|
|
553
|
+
updatedList.length ? beforeBounds.add(leaf.__world) : beforeBounds.set(leaf.__world);
|
|
554
|
+
updatedList.add(leaf);
|
|
555
|
+
}
|
|
525
556
|
}
|
|
526
557
|
createBlock(data) {
|
|
527
558
|
return new LayoutBlockData(data);
|
|
@@ -555,7 +586,7 @@ class Layouter {
|
|
|
555
586
|
}
|
|
556
587
|
}
|
|
557
588
|
|
|
558
|
-
const debug = Debug.get('Renderer');
|
|
589
|
+
const debug$1 = Debug.get('Renderer');
|
|
559
590
|
class Renderer {
|
|
560
591
|
get needFill() { return !!(!this.canvas.allowBackgroundColor && this.config.fill); }
|
|
561
592
|
constructor(target, canvas, userConfig) {
|
|
@@ -593,7 +624,7 @@ class Renderer {
|
|
|
593
624
|
const { target } = this;
|
|
594
625
|
this.times = 0;
|
|
595
626
|
this.totalBounds = new Bounds();
|
|
596
|
-
debug.log(target.innerName, '--->');
|
|
627
|
+
debug$1.log(target.innerName, '--->');
|
|
597
628
|
try {
|
|
598
629
|
this.emitRender(RenderEvent.START);
|
|
599
630
|
this.renderOnce(callback);
|
|
@@ -602,9 +633,9 @@ class Renderer {
|
|
|
602
633
|
}
|
|
603
634
|
catch (e) {
|
|
604
635
|
this.rendering = false;
|
|
605
|
-
debug.error(e);
|
|
636
|
+
debug$1.error(e);
|
|
606
637
|
}
|
|
607
|
-
debug.log('-------------|');
|
|
638
|
+
debug$1.log('-------------|');
|
|
608
639
|
}
|
|
609
640
|
renderAgain() {
|
|
610
641
|
if (this.rendering) {
|
|
@@ -616,9 +647,9 @@ class Renderer {
|
|
|
616
647
|
}
|
|
617
648
|
renderOnce(callback) {
|
|
618
649
|
if (this.rendering)
|
|
619
|
-
return debug.warn('rendering');
|
|
650
|
+
return debug$1.warn('rendering');
|
|
620
651
|
if (this.times > 3)
|
|
621
|
-
return debug.warn('render max times');
|
|
652
|
+
return debug$1.warn('render max times');
|
|
622
653
|
this.times++;
|
|
623
654
|
this.totalTimes++;
|
|
624
655
|
this.rendering = true;
|
|
@@ -631,6 +662,10 @@ class Renderer {
|
|
|
631
662
|
}
|
|
632
663
|
else {
|
|
633
664
|
this.requestLayout();
|
|
665
|
+
if (this.ignore) {
|
|
666
|
+
this.ignore = this.rendering = false;
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
634
669
|
this.emitRender(RenderEvent.BEFORE);
|
|
635
670
|
if (this.config.usePartRender && this.totalTimes > 1) {
|
|
636
671
|
this.partRender();
|
|
@@ -651,7 +686,7 @@ class Renderer {
|
|
|
651
686
|
partRender() {
|
|
652
687
|
const { canvas, updateBlocks: list } = this;
|
|
653
688
|
if (!list)
|
|
654
|
-
return debug.warn('PartRender: need update attr');
|
|
689
|
+
return debug$1.warn('PartRender: need update attr');
|
|
655
690
|
this.mergeBlocks();
|
|
656
691
|
list.forEach(block => { if (canvas.bounds.hit(block) && !block.isEmpty())
|
|
657
692
|
this.clipRender(block); });
|
|
@@ -667,7 +702,7 @@ class Renderer {
|
|
|
667
702
|
canvas.clear();
|
|
668
703
|
}
|
|
669
704
|
else {
|
|
670
|
-
bounds.spread(
|
|
705
|
+
bounds.spread(10 + 1 / this.canvas.pixelRatio).ceil();
|
|
671
706
|
canvas.clearWorld(bounds, true);
|
|
672
707
|
canvas.clipWorld(bounds, true);
|
|
673
708
|
}
|
|
@@ -739,8 +774,11 @@ class Renderer {
|
|
|
739
774
|
if (!bounds.includes(this.target.__world) || this.needFill || !e.samePixelRatio) {
|
|
740
775
|
this.addBlock(this.canvas.bounds);
|
|
741
776
|
this.target.forceUpdate('surface');
|
|
777
|
+
return;
|
|
742
778
|
}
|
|
743
779
|
}
|
|
780
|
+
this.addBlock(new Bounds(0, 0, 1, 1));
|
|
781
|
+
this.changed = true;
|
|
744
782
|
}
|
|
745
783
|
__onLayoutEnd(event) {
|
|
746
784
|
if (event.data)
|
|
@@ -751,7 +789,7 @@ class Renderer {
|
|
|
751
789
|
empty = (!leaf.__world.width || !leaf.__world.height);
|
|
752
790
|
if (empty) {
|
|
753
791
|
if (!leaf.isLeafer)
|
|
754
|
-
debug.tip(leaf.innerName, ': empty');
|
|
792
|
+
debug$1.tip(leaf.innerName, ': empty');
|
|
755
793
|
empty = (!leaf.isBranch || leaf.isBranchLeaf);
|
|
756
794
|
}
|
|
757
795
|
return empty;
|
|
@@ -778,9 +816,7 @@ class Renderer {
|
|
|
778
816
|
if (this.target) {
|
|
779
817
|
this.stop();
|
|
780
818
|
this.__removeListenEvents();
|
|
781
|
-
this.target = null;
|
|
782
|
-
this.canvas = null;
|
|
783
|
-
this.config = null;
|
|
819
|
+
this.target = this.canvas = this.config = null;
|
|
784
820
|
}
|
|
785
821
|
}
|
|
786
822
|
}
|
|
@@ -794,9 +830,6 @@ Object.assign(Creator, {
|
|
|
794
830
|
});
|
|
795
831
|
Platform.layout = Layouter.fullLayout;
|
|
796
832
|
|
|
797
|
-
const PaintImage = {};
|
|
798
|
-
const PaintGradient = {};
|
|
799
|
-
|
|
800
833
|
function fillText(ui, canvas) {
|
|
801
834
|
let row;
|
|
802
835
|
const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
|
|
@@ -1016,7 +1049,7 @@ function shape(ui, current, options) {
|
|
|
1016
1049
|
}
|
|
1017
1050
|
else {
|
|
1018
1051
|
const { renderShapeSpread: spread } = ui.__layout;
|
|
1019
|
-
const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, spread * scaleX, spread *
|
|
1052
|
+
const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, scaleX === scaleY ? spread * scaleX : [spread * scaleY, spread * scaleX]) : current.bounds, nowWorld);
|
|
1020
1053
|
fitMatrix = current.bounds.getFitMatrix(worldClipBounds);
|
|
1021
1054
|
let { a: fitScaleX, d: fitScaleY } = fitMatrix;
|
|
1022
1055
|
if (fitMatrix.a < 1) {
|
|
@@ -1081,7 +1114,7 @@ function getLeafPaint(attrName, paint, ui) {
|
|
|
1081
1114
|
case 'angular':
|
|
1082
1115
|
return PaintGradient.conicGradient(paint, boxBounds);
|
|
1083
1116
|
default:
|
|
1084
|
-
return paint.r ? { type: 'solid', style: ColorConvert.string(paint) } : undefined;
|
|
1117
|
+
return paint.r !== undefined ? { type: 'solid', style: ColorConvert.string(paint) } : undefined;
|
|
1085
1118
|
}
|
|
1086
1119
|
}
|
|
1087
1120
|
|
|
@@ -1098,77 +1131,80 @@ const PaintModule = {
|
|
|
1098
1131
|
};
|
|
1099
1132
|
|
|
1100
1133
|
let origin = {};
|
|
1101
|
-
const { get: get$
|
|
1102
|
-
function fillOrFitMode(data,
|
|
1103
|
-
const transform = get$
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
const sh = box.height / (swap ? width : height);
|
|
1107
|
-
const scale = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
|
|
1108
|
-
const x = box.x + (box.width - width * scale) / 2;
|
|
1109
|
-
const y = box.y + (box.height - height * scale) / 2;
|
|
1110
|
-
translate$1(transform, x, y);
|
|
1111
|
-
scaleHelper(transform, scale);
|
|
1134
|
+
const { get: get$3, rotateOfOuter: rotateOfOuter$1, translate: translate$1, scaleOfOuter: scaleOfOuter$1, scale: scaleHelper, rotate } = MatrixHelper;
|
|
1135
|
+
function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
|
|
1136
|
+
const transform = get$3();
|
|
1137
|
+
translate$1(transform, box.x + x, box.y + y);
|
|
1138
|
+
scaleHelper(transform, scaleX, scaleY);
|
|
1112
1139
|
if (rotation)
|
|
1113
|
-
rotateOfOuter$
|
|
1114
|
-
data.scaleX = data.scaleY = scale;
|
|
1140
|
+
rotateOfOuter$1(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
|
|
1115
1141
|
data.transform = transform;
|
|
1116
1142
|
}
|
|
1117
1143
|
function clipMode(data, box, x, y, scaleX, scaleY, rotation) {
|
|
1118
|
-
const transform = get$
|
|
1119
|
-
translate$1(transform, box.x, box.y);
|
|
1120
|
-
if (
|
|
1121
|
-
translate$1(transform, x, y);
|
|
1122
|
-
if (scaleX) {
|
|
1144
|
+
const transform = get$3();
|
|
1145
|
+
translate$1(transform, box.x + x, box.y + y);
|
|
1146
|
+
if (scaleX)
|
|
1123
1147
|
scaleHelper(transform, scaleX, scaleY);
|
|
1124
|
-
data.scaleX = transform.a;
|
|
1125
|
-
data.scaleY = transform.d;
|
|
1126
|
-
}
|
|
1127
1148
|
if (rotation)
|
|
1128
1149
|
rotate(transform, rotation);
|
|
1129
1150
|
data.transform = transform;
|
|
1130
1151
|
}
|
|
1131
|
-
function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation) {
|
|
1132
|
-
const transform = get$
|
|
1152
|
+
function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align) {
|
|
1153
|
+
const transform = get$3();
|
|
1133
1154
|
if (rotation) {
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1155
|
+
if (align === 'center') {
|
|
1156
|
+
rotateOfOuter$1(transform, { x: width / 2, y: height / 2 }, rotation);
|
|
1157
|
+
}
|
|
1158
|
+
else {
|
|
1159
|
+
rotate(transform, rotation);
|
|
1160
|
+
switch (rotation) {
|
|
1161
|
+
case 90:
|
|
1162
|
+
translate$1(transform, height, 0);
|
|
1163
|
+
break;
|
|
1164
|
+
case 180:
|
|
1165
|
+
translate$1(transform, width, height);
|
|
1166
|
+
break;
|
|
1167
|
+
case 270:
|
|
1168
|
+
translate$1(transform, 0, width);
|
|
1169
|
+
break;
|
|
1170
|
+
}
|
|
1145
1171
|
}
|
|
1146
1172
|
}
|
|
1147
|
-
origin.x = box.x;
|
|
1148
|
-
origin.y = box.y;
|
|
1149
|
-
if (x || y)
|
|
1150
|
-
origin.x += x, origin.y += y;
|
|
1173
|
+
origin.x = box.x + x;
|
|
1174
|
+
origin.y = box.y + y;
|
|
1151
1175
|
translate$1(transform, origin.x, origin.y);
|
|
1152
|
-
if (scaleX)
|
|
1153
|
-
scaleOfOuter$
|
|
1154
|
-
data.scaleX = scaleX;
|
|
1155
|
-
data.scaleY = scaleY;
|
|
1156
|
-
}
|
|
1176
|
+
if (scaleX)
|
|
1177
|
+
scaleOfOuter$1(transform, origin, scaleX, scaleY);
|
|
1157
1178
|
data.transform = transform;
|
|
1158
1179
|
}
|
|
1159
1180
|
|
|
1160
|
-
const { get: get$
|
|
1181
|
+
const { get: get$2, translate } = MatrixHelper;
|
|
1182
|
+
const tempBox = new Bounds();
|
|
1183
|
+
const tempPoint = {};
|
|
1161
1184
|
function createData(leafPaint, image, paint, box) {
|
|
1162
|
-
|
|
1163
|
-
const { opacity, mode, offset, scale, size, rotation, blendMode, repeat } = paint;
|
|
1164
|
-
const sameBox = box.width === width && box.height === height;
|
|
1185
|
+
const { blendMode } = paint;
|
|
1165
1186
|
if (blendMode)
|
|
1166
1187
|
leafPaint.blendMode = blendMode;
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
if (
|
|
1188
|
+
leafPaint.data = getPatternData(paint, box, image);
|
|
1189
|
+
}
|
|
1190
|
+
function getPatternData(paint, box, image) {
|
|
1191
|
+
let { width, height } = image;
|
|
1192
|
+
if (paint.padding)
|
|
1193
|
+
box = tempBox.set(box).shrink(paint.padding);
|
|
1194
|
+
const { opacity, mode, align, offset, scale, size, rotation, repeat } = paint;
|
|
1195
|
+
const sameBox = box.width === width && box.height === height;
|
|
1196
|
+
const data = { mode };
|
|
1197
|
+
const swapSize = align !== 'center' && (rotation || 0) % 180 === 90;
|
|
1198
|
+
const swapWidth = swapSize ? height : width, swapHeight = swapSize ? width : height;
|
|
1199
|
+
let x = 0, y = 0, scaleX, scaleY;
|
|
1200
|
+
if (!mode || mode === 'cover' || mode === 'fit') {
|
|
1201
|
+
if (!sameBox || rotation) {
|
|
1202
|
+
const sw = box.width / swapWidth, sh = box.height / swapHeight;
|
|
1203
|
+
scaleX = scaleY = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
|
|
1204
|
+
x += (box.width - width * scaleX) / 2, y += (box.height - height * scaleY) / 2;
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
else if (size) {
|
|
1172
1208
|
scaleX = (typeof size === 'number' ? size : size.width) / width;
|
|
1173
1209
|
scaleY = (typeof size === 'number' ? size : size.height) / height;
|
|
1174
1210
|
}
|
|
@@ -1176,30 +1212,46 @@ function createData(leafPaint, image, paint, box) {
|
|
|
1176
1212
|
scaleX = typeof scale === 'number' ? scale : scale.x;
|
|
1177
1213
|
scaleY = typeof scale === 'number' ? scale : scale.y;
|
|
1178
1214
|
}
|
|
1215
|
+
if (align) {
|
|
1216
|
+
const imageBounds = { x, y, width: swapWidth, height: swapHeight };
|
|
1217
|
+
if (scaleX)
|
|
1218
|
+
imageBounds.width *= scaleX, imageBounds.height *= scaleY;
|
|
1219
|
+
AlignHelper.toPoint(align, imageBounds, box, tempPoint, true);
|
|
1220
|
+
x += tempPoint.x, y += tempPoint.y;
|
|
1221
|
+
}
|
|
1222
|
+
if (offset)
|
|
1223
|
+
x += offset.x, y += offset.y;
|
|
1179
1224
|
switch (mode) {
|
|
1180
1225
|
case 'strench':
|
|
1181
1226
|
if (!sameBox)
|
|
1182
1227
|
width = box.width, height = box.height;
|
|
1183
|
-
if (box.x || box.y) {
|
|
1184
|
-
data.transform = get$3();
|
|
1185
|
-
translate(data.transform, box.x, box.y);
|
|
1186
|
-
}
|
|
1187
1228
|
break;
|
|
1229
|
+
case 'normal':
|
|
1188
1230
|
case 'clip':
|
|
1189
|
-
if (
|
|
1231
|
+
if (x || y || scaleX || rotation)
|
|
1190
1232
|
clipMode(data, box, x, y, scaleX, scaleY, rotation);
|
|
1191
1233
|
break;
|
|
1192
1234
|
case 'repeat':
|
|
1193
1235
|
if (!sameBox || scaleX || rotation)
|
|
1194
|
-
repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation);
|
|
1236
|
+
repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align);
|
|
1195
1237
|
if (!repeat)
|
|
1196
1238
|
data.repeat = 'repeat';
|
|
1197
1239
|
break;
|
|
1198
1240
|
case 'fit':
|
|
1199
1241
|
case 'cover':
|
|
1200
1242
|
default:
|
|
1201
|
-
if (
|
|
1202
|
-
fillOrFitMode(data,
|
|
1243
|
+
if (scaleX)
|
|
1244
|
+
fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation);
|
|
1245
|
+
}
|
|
1246
|
+
if (!data.transform) {
|
|
1247
|
+
if (box.x || box.y) {
|
|
1248
|
+
data.transform = get$2();
|
|
1249
|
+
translate(data.transform, box.x, box.y);
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
if (scaleX && mode !== 'strench') {
|
|
1253
|
+
data.scaleX = scaleX;
|
|
1254
|
+
data.scaleY = scaleY;
|
|
1203
1255
|
}
|
|
1204
1256
|
data.width = width;
|
|
1205
1257
|
data.height = height;
|
|
@@ -1207,6 +1259,7 @@ function createData(leafPaint, image, paint, box) {
|
|
|
1207
1259
|
data.opacity = opacity;
|
|
1208
1260
|
if (repeat)
|
|
1209
1261
|
data.repeat = typeof repeat === 'string' ? (repeat === 'x' ? 'repeat-x' : 'repeat-y') : 'repeat';
|
|
1262
|
+
return data;
|
|
1210
1263
|
}
|
|
1211
1264
|
|
|
1212
1265
|
let cache, box = new Bounds();
|
|
@@ -1218,8 +1271,7 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
|
|
|
1218
1271
|
leafPaint = cache.leafPaint;
|
|
1219
1272
|
}
|
|
1220
1273
|
else {
|
|
1221
|
-
leafPaint = { type: paint.type };
|
|
1222
|
-
leafPaint.image = image;
|
|
1274
|
+
leafPaint = { type: paint.type, image };
|
|
1223
1275
|
cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
|
|
1224
1276
|
}
|
|
1225
1277
|
if (firstUse || image.loading)
|
|
@@ -1236,16 +1288,22 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
|
|
|
1236
1288
|
onLoadError(ui, event, image.error);
|
|
1237
1289
|
}
|
|
1238
1290
|
else {
|
|
1291
|
+
ignoreRender(ui, true);
|
|
1239
1292
|
if (firstUse)
|
|
1240
1293
|
onLoad(ui, event);
|
|
1241
1294
|
leafPaint.loadId = image.load(() => {
|
|
1295
|
+
ignoreRender(ui, false);
|
|
1242
1296
|
if (!ui.destroyed) {
|
|
1243
|
-
if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds))
|
|
1297
|
+
if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
|
|
1298
|
+
if (image.hasOpacityPixel)
|
|
1299
|
+
ui.__layout.hitCanvasChanged = true;
|
|
1244
1300
|
ui.forceUpdate('surface');
|
|
1301
|
+
}
|
|
1245
1302
|
onLoadSuccess(ui, event);
|
|
1246
1303
|
}
|
|
1247
1304
|
leafPaint.loadId = null;
|
|
1248
1305
|
}, (error) => {
|
|
1306
|
+
ignoreRender(ui, false);
|
|
1249
1307
|
onLoadError(ui, event, error);
|
|
1250
1308
|
leafPaint.loadId = null;
|
|
1251
1309
|
});
|
|
@@ -1255,9 +1313,9 @@ function image(ui, attrName, paint, boxBounds, firstUse) {
|
|
|
1255
1313
|
function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
|
|
1256
1314
|
if (attrName === 'fill' && !ui.__.__naturalWidth) {
|
|
1257
1315
|
const data = ui.__;
|
|
1258
|
-
data.__naturalWidth = image.width;
|
|
1259
|
-
data.__naturalHeight = image.height;
|
|
1260
|
-
if (data.
|
|
1316
|
+
data.__naturalWidth = image.width / data.pixelRatio;
|
|
1317
|
+
data.__naturalHeight = image.height / data.pixelRatio;
|
|
1318
|
+
if (data.__autoSide) {
|
|
1261
1319
|
ui.forceUpdate('width');
|
|
1262
1320
|
if (ui.__proxyData) {
|
|
1263
1321
|
ui.setProxyAttr('width', data.width);
|
|
@@ -1285,11 +1343,16 @@ function emit(ui, type, data) {
|
|
|
1285
1343
|
if (ui.hasEvent(type))
|
|
1286
1344
|
ui.emitEvent(new ImageEvent(type, data));
|
|
1287
1345
|
}
|
|
1346
|
+
function ignoreRender(ui, value) {
|
|
1347
|
+
const { leafer } = ui;
|
|
1348
|
+
if (leafer && leafer.viewReady)
|
|
1349
|
+
leafer.renderer.ignore = value;
|
|
1350
|
+
}
|
|
1288
1351
|
|
|
1289
|
-
const { get: get$
|
|
1290
|
-
const {
|
|
1352
|
+
const { get: get$1, scale, copy: copy$1 } = MatrixHelper;
|
|
1353
|
+
const { ceil, abs: abs$1 } = Math;
|
|
1291
1354
|
function createPattern(ui, paint, pixelRatio) {
|
|
1292
|
-
let { scaleX, scaleY } = ui.__world;
|
|
1355
|
+
let { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
|
|
1293
1356
|
const id = scaleX + '-' + scaleY;
|
|
1294
1357
|
if (paint.patternId !== id && !ui.destroyed) {
|
|
1295
1358
|
scaleX = abs$1(scaleX);
|
|
@@ -1297,7 +1360,7 @@ function createPattern(ui, paint, pixelRatio) {
|
|
|
1297
1360
|
const { image, data } = paint;
|
|
1298
1361
|
let imageScale, imageMatrix, { width, height, scaleX: sx, scaleY: sy, opacity, transform, repeat } = data;
|
|
1299
1362
|
if (sx) {
|
|
1300
|
-
imageMatrix = get$
|
|
1363
|
+
imageMatrix = get$1();
|
|
1301
1364
|
copy$1(imageMatrix, transform);
|
|
1302
1365
|
scale(imageMatrix, 1 / sx, 1 / sy);
|
|
1303
1366
|
scaleX *= sx;
|
|
@@ -1332,13 +1395,13 @@ function createPattern(ui, paint, pixelRatio) {
|
|
|
1332
1395
|
}
|
|
1333
1396
|
if (transform || scaleX !== 1 || scaleY !== 1) {
|
|
1334
1397
|
if (!imageMatrix) {
|
|
1335
|
-
imageMatrix = get$
|
|
1398
|
+
imageMatrix = get$1();
|
|
1336
1399
|
if (transform)
|
|
1337
1400
|
copy$1(imageMatrix, transform);
|
|
1338
1401
|
}
|
|
1339
1402
|
scale(imageMatrix, 1 / scaleX, 1 / scaleY);
|
|
1340
1403
|
}
|
|
1341
|
-
const canvas = image.getCanvas(width
|
|
1404
|
+
const canvas = image.getCanvas(ceil(width) || 1, ceil(height) || 1, opacity);
|
|
1342
1405
|
const pattern = image.getPattern(canvas, repeat || (Platform.origin.noRepeat || 'no-repeat'), imageMatrix, paint);
|
|
1343
1406
|
paint.style = pattern;
|
|
1344
1407
|
paint.patternId = id;
|
|
@@ -1383,7 +1446,7 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
1383
1446
|
|
|
1384
1447
|
const { abs } = Math;
|
|
1385
1448
|
function checkImage(ui, canvas, paint, allowPaint) {
|
|
1386
|
-
const { scaleX, scaleY } = ui.__world;
|
|
1449
|
+
const { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
|
|
1387
1450
|
if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
|
|
1388
1451
|
return false;
|
|
1389
1452
|
}
|
|
@@ -1398,7 +1461,7 @@ function checkImage(ui, canvas, paint, allowPaint) {
|
|
|
1398
1461
|
width *= data.scaleX;
|
|
1399
1462
|
height *= data.scaleY;
|
|
1400
1463
|
}
|
|
1401
|
-
allowPaint = width * height > Platform.image.maxCacheSize;
|
|
1464
|
+
allowPaint = (width * height > Platform.image.maxCacheSize) || Export.running;
|
|
1402
1465
|
}
|
|
1403
1466
|
else {
|
|
1404
1467
|
allowPaint = false;
|
|
@@ -1425,7 +1488,7 @@ function checkImage(ui, canvas, paint, allowPaint) {
|
|
|
1425
1488
|
if (!paint.patternTask) {
|
|
1426
1489
|
paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
|
|
1427
1490
|
paint.patternTask = null;
|
|
1428
|
-
if (canvas.bounds.hit(ui.
|
|
1491
|
+
if (canvas.bounds.hit(ui.__nowWorld))
|
|
1429
1492
|
createPattern(ui, paint, canvas.pixelRatio);
|
|
1430
1493
|
ui.forceUpdate('surface');
|
|
1431
1494
|
}), 300);
|
|
@@ -1465,22 +1528,24 @@ function recycleImage(attrName, data) {
|
|
|
1465
1528
|
|
|
1466
1529
|
const PaintImageModule = {
|
|
1467
1530
|
image,
|
|
1531
|
+
checkImage,
|
|
1532
|
+
createPattern,
|
|
1533
|
+
recycleImage,
|
|
1468
1534
|
createData,
|
|
1535
|
+
getPatternData,
|
|
1469
1536
|
fillOrFitMode,
|
|
1470
1537
|
clipMode,
|
|
1471
|
-
repeatMode
|
|
1472
|
-
createPattern,
|
|
1473
|
-
checkImage,
|
|
1474
|
-
recycleImage
|
|
1538
|
+
repeatMode
|
|
1475
1539
|
};
|
|
1476
1540
|
|
|
1477
|
-
const
|
|
1478
|
-
const
|
|
1541
|
+
const { toPoint: toPoint$2 } = AroundHelper;
|
|
1542
|
+
const realFrom$2 = {};
|
|
1543
|
+
const realTo$2 = {};
|
|
1479
1544
|
function linearGradient(paint, box) {
|
|
1480
1545
|
let { from, to, type, blendMode, opacity } = paint;
|
|
1481
|
-
from ||
|
|
1482
|
-
to ||
|
|
1483
|
-
const style = Platform.canvas.createLinearGradient(
|
|
1546
|
+
toPoint$2(from || 'top', box, realFrom$2);
|
|
1547
|
+
toPoint$2(to || 'bottom', box, realTo$2);
|
|
1548
|
+
const style = Platform.canvas.createLinearGradient(realFrom$2.x, realFrom$2.y, realTo$2.x, realTo$2.y);
|
|
1484
1549
|
applyStops(style, paint.stops, opacity);
|
|
1485
1550
|
const data = { type, style };
|
|
1486
1551
|
if (blendMode)
|
|
@@ -1491,63 +1556,66 @@ function applyStops(gradient, stops, opacity) {
|
|
|
1491
1556
|
let stop;
|
|
1492
1557
|
for (let i = 0, len = stops.length; i < len; i++) {
|
|
1493
1558
|
stop = stops[i];
|
|
1494
|
-
|
|
1559
|
+
if (typeof stop === 'string') {
|
|
1560
|
+
gradient.addColorStop(i / (len - 1), ColorConvert.string(stop, opacity));
|
|
1561
|
+
}
|
|
1562
|
+
else {
|
|
1563
|
+
gradient.addColorStop(stop.offset, ColorConvert.string(stop.color, opacity));
|
|
1564
|
+
}
|
|
1495
1565
|
}
|
|
1496
1566
|
}
|
|
1497
1567
|
|
|
1498
|
-
const {
|
|
1499
|
-
const { get
|
|
1500
|
-
const
|
|
1501
|
-
const defaultTo$1 = { x: 0.5, y: 1 };
|
|
1568
|
+
const { getAngle, getDistance: getDistance$1 } = PointHelper;
|
|
1569
|
+
const { get, rotateOfOuter, scaleOfOuter } = MatrixHelper;
|
|
1570
|
+
const { toPoint: toPoint$1 } = AroundHelper;
|
|
1502
1571
|
const realFrom$1 = {};
|
|
1503
1572
|
const realTo$1 = {};
|
|
1504
1573
|
function radialGradient(paint, box) {
|
|
1505
1574
|
let { from, to, type, opacity, blendMode, stretch } = paint;
|
|
1506
|
-
from ||
|
|
1507
|
-
to ||
|
|
1508
|
-
const { x, y, width, height } = box;
|
|
1509
|
-
set$1(realFrom$1, x + from.x * width, y + from.y * height);
|
|
1510
|
-
set$1(realTo$1, x + to.x * width, y + to.y * height);
|
|
1511
|
-
let transform;
|
|
1512
|
-
if (width !== height || stretch) {
|
|
1513
|
-
transform = get$1();
|
|
1514
|
-
scaleOfOuter$1(transform, realFrom$1, width / height * (stretch || 1), 1);
|
|
1515
|
-
rotateOfOuter$1(transform, realFrom$1, getAngle$1(realFrom$1, realTo$1) + 90);
|
|
1516
|
-
}
|
|
1575
|
+
toPoint$1(from || 'center', box, realFrom$1);
|
|
1576
|
+
toPoint$1(to || 'bottom', box, realTo$1);
|
|
1517
1577
|
const style = Platform.canvas.createRadialGradient(realFrom$1.x, realFrom$1.y, 0, realFrom$1.x, realFrom$1.y, getDistance$1(realFrom$1, realTo$1));
|
|
1518
1578
|
applyStops(style, paint.stops, opacity);
|
|
1519
|
-
const data = { type, style
|
|
1579
|
+
const data = { type, style };
|
|
1580
|
+
const transform = getTransform(box, realFrom$1, realTo$1, stretch, true);
|
|
1581
|
+
if (transform)
|
|
1582
|
+
data.transform = transform;
|
|
1520
1583
|
if (blendMode)
|
|
1521
1584
|
data.blendMode = blendMode;
|
|
1522
1585
|
return data;
|
|
1523
1586
|
}
|
|
1587
|
+
function getTransform(box, from, to, stretch, rotate90) {
|
|
1588
|
+
let transform;
|
|
1589
|
+
const { width, height } = box;
|
|
1590
|
+
if (width !== height || stretch) {
|
|
1591
|
+
const angle = getAngle(from, to);
|
|
1592
|
+
transform = get();
|
|
1593
|
+
if (rotate90) {
|
|
1594
|
+
scaleOfOuter(transform, from, width / height * (stretch || 1), 1);
|
|
1595
|
+
rotateOfOuter(transform, from, angle + 90);
|
|
1596
|
+
}
|
|
1597
|
+
else {
|
|
1598
|
+
scaleOfOuter(transform, from, 1, width / height * (stretch || 1));
|
|
1599
|
+
rotateOfOuter(transform, from, angle);
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
return transform;
|
|
1603
|
+
}
|
|
1524
1604
|
|
|
1525
|
-
const {
|
|
1526
|
-
const {
|
|
1527
|
-
const defaultFrom = { x: 0.5, y: 0.5 };
|
|
1528
|
-
const defaultTo = { x: 0.5, y: 1 };
|
|
1605
|
+
const { getDistance } = PointHelper;
|
|
1606
|
+
const { toPoint } = AroundHelper;
|
|
1529
1607
|
const realFrom = {};
|
|
1530
1608
|
const realTo = {};
|
|
1531
1609
|
function conicGradient(paint, box) {
|
|
1532
1610
|
let { from, to, type, opacity, blendMode, stretch } = paint;
|
|
1533
|
-
from ||
|
|
1534
|
-
to ||
|
|
1535
|
-
const { x, y, width, height } = box;
|
|
1536
|
-
set(realFrom, x + from.x * width, y + from.y * height);
|
|
1537
|
-
set(realTo, x + to.x * width, y + to.y * height);
|
|
1538
|
-
const transform = get();
|
|
1539
|
-
const angle = getAngle(realFrom, realTo);
|
|
1540
|
-
if (Platform.conicGradientRotate90) {
|
|
1541
|
-
scaleOfOuter(transform, realFrom, width / height * (stretch || 1), 1);
|
|
1542
|
-
rotateOfOuter(transform, realFrom, angle + 90);
|
|
1543
|
-
}
|
|
1544
|
-
else {
|
|
1545
|
-
scaleOfOuter(transform, realFrom, 1, width / height * (stretch || 1));
|
|
1546
|
-
rotateOfOuter(transform, realFrom, angle);
|
|
1547
|
-
}
|
|
1611
|
+
toPoint(from || 'center', box, realFrom);
|
|
1612
|
+
toPoint(to || 'bottom', box, realTo);
|
|
1548
1613
|
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));
|
|
1549
1614
|
applyStops(style, paint.stops, opacity);
|
|
1550
|
-
const data = { type, style
|
|
1615
|
+
const data = { type, style };
|
|
1616
|
+
const transform = getTransform(box, realFrom, realTo, stretch || 1, Platform.conicGradientRotate90);
|
|
1617
|
+
if (transform)
|
|
1618
|
+
data.transform = transform;
|
|
1551
1619
|
if (blendMode)
|
|
1552
1620
|
data.blendMode = blendMode;
|
|
1553
1621
|
return data;
|
|
@@ -1556,7 +1624,8 @@ function conicGradient(paint, box) {
|
|
|
1556
1624
|
const PaintGradientModule = {
|
|
1557
1625
|
linearGradient,
|
|
1558
1626
|
radialGradient,
|
|
1559
|
-
conicGradient
|
|
1627
|
+
conicGradient,
|
|
1628
|
+
getTransform
|
|
1560
1629
|
};
|
|
1561
1630
|
|
|
1562
1631
|
const { copy, toOffsetOutBounds: toOffsetOutBounds$1 } = BoundsHelper;
|
|
@@ -1662,8 +1731,8 @@ function innerShadow(ui, current, shape) {
|
|
|
1662
1731
|
|
|
1663
1732
|
function blur(ui, current, origin) {
|
|
1664
1733
|
const { blur } = ui.__;
|
|
1665
|
-
origin.setWorldBlur(blur * ui.
|
|
1666
|
-
origin.copyWorldToInner(current, ui.
|
|
1734
|
+
origin.setWorldBlur(blur * ui.__nowWorld.a);
|
|
1735
|
+
origin.copyWorldToInner(current, ui.__nowWorld, ui.__layout.renderBounds);
|
|
1667
1736
|
origin.filter = 'none';
|
|
1668
1737
|
}
|
|
1669
1738
|
|
|
@@ -1688,7 +1757,7 @@ Group.prototype.__renderMask = function (canvas, options) {
|
|
|
1688
1757
|
maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
|
|
1689
1758
|
maskCanvas = contentCanvas = null;
|
|
1690
1759
|
}
|
|
1691
|
-
if (child.__.
|
|
1760
|
+
if (child.__.mask === 'path') {
|
|
1692
1761
|
if (child.opacity < 1) {
|
|
1693
1762
|
currentMask = 'opacity-path';
|
|
1694
1763
|
maskOpacity = child.opacity;
|
|
@@ -1709,7 +1778,7 @@ Group.prototype.__renderMask = function (canvas, options) {
|
|
|
1709
1778
|
contentCanvas = getCanvas(canvas);
|
|
1710
1779
|
child.__render(maskCanvas, options);
|
|
1711
1780
|
}
|
|
1712
|
-
if (child.__.
|
|
1781
|
+
if (child.__.mask !== 'clipping')
|
|
1713
1782
|
continue;
|
|
1714
1783
|
}
|
|
1715
1784
|
if (excludeRenderBounds(child, options))
|
|
@@ -1904,7 +1973,8 @@ function createRows(drawData, content, style) {
|
|
|
1904
1973
|
if (breakAll) {
|
|
1905
1974
|
if (wordWidth)
|
|
1906
1975
|
addWord();
|
|
1907
|
-
|
|
1976
|
+
if (rowWidth)
|
|
1977
|
+
addRow();
|
|
1908
1978
|
}
|
|
1909
1979
|
else {
|
|
1910
1980
|
if (!afterBreak)
|
|
@@ -1912,10 +1982,12 @@ function createRows(drawData, content, style) {
|
|
|
1912
1982
|
if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
|
|
1913
1983
|
if (wordWidth)
|
|
1914
1984
|
addWord();
|
|
1915
|
-
|
|
1985
|
+
if (rowWidth)
|
|
1986
|
+
addRow();
|
|
1916
1987
|
}
|
|
1917
1988
|
else {
|
|
1918
|
-
|
|
1989
|
+
if (rowWidth)
|
|
1990
|
+
addRow();
|
|
1919
1991
|
}
|
|
1920
1992
|
}
|
|
1921
1993
|
}
|
|
@@ -2010,11 +2082,11 @@ function layoutChar(drawData, style, width, _height) {
|
|
|
2010
2082
|
if (mode === WordMode) {
|
|
2011
2083
|
wordChar = { char: '', x: charX };
|
|
2012
2084
|
charX = toWordChar(word.data, charX, wordChar);
|
|
2013
|
-
if (wordChar.char !== ' ')
|
|
2085
|
+
if (row.isOverflow || wordChar.char !== ' ')
|
|
2014
2086
|
row.data.push(wordChar);
|
|
2015
2087
|
}
|
|
2016
2088
|
else {
|
|
2017
|
-
charX = toChar(word.data, charX, row.data);
|
|
2089
|
+
charX = toChar(word.data, charX, row.data, row.isOverflow);
|
|
2018
2090
|
}
|
|
2019
2091
|
if (!row.paraEnd && addWordWidth) {
|
|
2020
2092
|
charX += addWordWidth;
|
|
@@ -2041,9 +2113,9 @@ function toWordChar(data, charX, wordChar) {
|
|
|
2041
2113
|
});
|
|
2042
2114
|
return charX;
|
|
2043
2115
|
}
|
|
2044
|
-
function toChar(data, charX, rowData) {
|
|
2116
|
+
function toChar(data, charX, rowData, isOverflow) {
|
|
2045
2117
|
data.forEach(char => {
|
|
2046
|
-
if (char.char !== ' ') {
|
|
2118
|
+
if (isOverflow || char.char !== ' ') {
|
|
2047
2119
|
char.x = charX;
|
|
2048
2120
|
rowData.push(char);
|
|
2049
2121
|
}
|
|
@@ -2075,12 +2147,14 @@ function layoutText(drawData, style) {
|
|
|
2075
2147
|
for (let i = 0, len = rows.length; i < len; i++) {
|
|
2076
2148
|
row = rows[i];
|
|
2077
2149
|
row.x = x;
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2150
|
+
if (row.width < width || (row.width > width && !__clipText)) {
|
|
2151
|
+
switch (textAlign) {
|
|
2152
|
+
case 'center':
|
|
2153
|
+
row.x += (width - row.width) / 2;
|
|
2154
|
+
break;
|
|
2155
|
+
case 'right':
|
|
2156
|
+
row.x += width - row.width;
|
|
2157
|
+
}
|
|
2084
2158
|
}
|
|
2085
2159
|
if (row.paraStart && paraSpacing && i > 0)
|
|
2086
2160
|
starY += paraSpacing;
|
|
@@ -2116,16 +2190,20 @@ function layoutText(drawData, style) {
|
|
|
2116
2190
|
bounds.height = realHeight;
|
|
2117
2191
|
}
|
|
2118
2192
|
|
|
2119
|
-
function clipText(drawData, style) {
|
|
2193
|
+
function clipText(drawData, style, x, width) {
|
|
2194
|
+
if (!width)
|
|
2195
|
+
return;
|
|
2120
2196
|
const { rows, overflow } = drawData;
|
|
2121
2197
|
let { textOverflow } = style;
|
|
2122
2198
|
rows.splice(overflow);
|
|
2123
|
-
if (textOverflow !== '
|
|
2124
|
-
if (textOverflow === '
|
|
2199
|
+
if (textOverflow && textOverflow !== 'show') {
|
|
2200
|
+
if (textOverflow === 'hide')
|
|
2201
|
+
textOverflow = '';
|
|
2202
|
+
else if (textOverflow === 'ellipsis')
|
|
2125
2203
|
textOverflow = '...';
|
|
2126
2204
|
let char, charRight;
|
|
2127
|
-
const ellipsisWidth = Platform.canvas.measureText(textOverflow).width;
|
|
2128
|
-
const right =
|
|
2205
|
+
const ellipsisWidth = textOverflow ? Platform.canvas.measureText(textOverflow).width : 0;
|
|
2206
|
+
const right = x + width - ellipsisWidth;
|
|
2129
2207
|
const list = style.textWrap === 'none' ? rows : [rows[overflow - 1]];
|
|
2130
2208
|
list.forEach(row => {
|
|
2131
2209
|
if (row.isOverflow && row.data) {
|
|
@@ -2201,7 +2279,7 @@ function getDrawData(content, style) {
|
|
|
2201
2279
|
layoutText(drawData, style);
|
|
2202
2280
|
layoutChar(drawData, style, width);
|
|
2203
2281
|
if (drawData.overflow)
|
|
2204
|
-
clipText(drawData, style);
|
|
2282
|
+
clipText(drawData, style, x, width);
|
|
2205
2283
|
if (textDecoration !== 'none')
|
|
2206
2284
|
decorationText(drawData, style);
|
|
2207
2285
|
return drawData;
|
|
@@ -2272,45 +2350,95 @@ function getTrimBounds(canvas) {
|
|
|
2272
2350
|
const ExportModule = {
|
|
2273
2351
|
export(leaf, filename, options) {
|
|
2274
2352
|
this.running = true;
|
|
2353
|
+
const fileType = FileHelper.fileType(filename);
|
|
2354
|
+
options = FileHelper.getExportOptions(options);
|
|
2275
2355
|
return addTask((success) => new Promise((resolve) => {
|
|
2276
2356
|
const over = (result) => {
|
|
2277
2357
|
success(result);
|
|
2278
2358
|
resolve();
|
|
2279
2359
|
this.running = false;
|
|
2280
2360
|
};
|
|
2361
|
+
const { toURL } = Platform;
|
|
2362
|
+
const { download } = Platform.origin;
|
|
2363
|
+
if (filename === 'json') {
|
|
2364
|
+
return over({ data: leaf.toJSON(options.json) });
|
|
2365
|
+
}
|
|
2366
|
+
else if (fileType === 'json') {
|
|
2367
|
+
download(toURL(JSON.stringify(leaf.toJSON(options.json)), 'text'), filename);
|
|
2368
|
+
return over({ data: true });
|
|
2369
|
+
}
|
|
2370
|
+
if (filename === 'svg') {
|
|
2371
|
+
return over({ data: leaf.toSVG() });
|
|
2372
|
+
}
|
|
2373
|
+
else if (fileType === 'svg') {
|
|
2374
|
+
download(toURL(leaf.toSVG(), 'svg'), filename);
|
|
2375
|
+
return over({ data: true });
|
|
2376
|
+
}
|
|
2281
2377
|
const { leafer } = leaf;
|
|
2282
2378
|
if (leafer) {
|
|
2379
|
+
checkLazy(leaf);
|
|
2283
2380
|
leafer.waitViewCompleted(() => __awaiter(this, void 0, void 0, function* () {
|
|
2284
2381
|
let renderBounds, trimBounds, scaleX = 1, scaleY = 1;
|
|
2285
|
-
|
|
2286
|
-
const {
|
|
2382
|
+
const { worldTransform, isLeafer, isFrame } = leaf;
|
|
2383
|
+
const { slice, trim, onCanvas } = options;
|
|
2384
|
+
let scale = options.scale || 1;
|
|
2385
|
+
let pixelRatio = options.pixelRatio || 1;
|
|
2386
|
+
const smooth = options.smooth === undefined ? leafer.config.smooth : options.smooth;
|
|
2387
|
+
const contextSettings = options.contextSettings || leafer.config.contextSettings;
|
|
2388
|
+
if (leaf.isApp) {
|
|
2389
|
+
scale *= pixelRatio;
|
|
2390
|
+
pixelRatio = leaf.app.pixelRatio;
|
|
2391
|
+
}
|
|
2287
2392
|
const screenshot = options.screenshot || leaf.isApp;
|
|
2288
|
-
const fill =
|
|
2393
|
+
const fill = (isLeafer && screenshot) ? (options.fill === undefined ? leaf.fill : options.fill) : options.fill;
|
|
2289
2394
|
const needFill = FileHelper.isOpaqueImage(filename) || fill, matrix = new Matrix();
|
|
2290
2395
|
if (screenshot) {
|
|
2291
|
-
renderBounds = screenshot === true ? (
|
|
2396
|
+
renderBounds = screenshot === true ? (isLeafer ? leafer.canvas.bounds : leaf.worldRenderBounds) : screenshot;
|
|
2292
2397
|
}
|
|
2293
2398
|
else {
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2399
|
+
let relative = options.relative || (isLeafer ? 'inner' : 'local');
|
|
2400
|
+
scaleX = worldTransform.scaleX;
|
|
2401
|
+
scaleY = worldTransform.scaleY;
|
|
2402
|
+
switch (relative) {
|
|
2403
|
+
case 'inner':
|
|
2404
|
+
matrix.set(worldTransform);
|
|
2405
|
+
break;
|
|
2406
|
+
case 'local':
|
|
2407
|
+
matrix.set(worldTransform).divide(leaf.localTransform);
|
|
2408
|
+
scaleX /= leaf.scaleX;
|
|
2409
|
+
scaleY /= leaf.scaleY;
|
|
2410
|
+
break;
|
|
2411
|
+
case 'world':
|
|
2412
|
+
scaleX = 1;
|
|
2413
|
+
scaleY = 1;
|
|
2414
|
+
break;
|
|
2415
|
+
case 'page':
|
|
2416
|
+
relative = leaf.leafer;
|
|
2417
|
+
default:
|
|
2418
|
+
matrix.set(worldTransform).divide(leaf.getTransform(relative));
|
|
2419
|
+
const l = relative.worldTransform;
|
|
2420
|
+
scaleX /= scaleX / l.scaleX;
|
|
2421
|
+
scaleY /= scaleY / l.scaleY;
|
|
2422
|
+
}
|
|
2423
|
+
renderBounds = leaf.getBounds('render', relative);
|
|
2305
2424
|
}
|
|
2306
|
-
|
|
2307
|
-
|
|
2425
|
+
const { x, y, width, height } = new Bounds(renderBounds).scale(scale);
|
|
2426
|
+
let canvas = Creator.canvas({ width: Math.round(width), height: Math.round(height), pixelRatio, smooth, contextSettings });
|
|
2427
|
+
const renderOptions = { matrix: matrix.scale(1 / scale).invert().translate(-x, -y).withScale(1 / scaleX * scale, 1 / scaleY * scale) };
|
|
2308
2428
|
if (slice) {
|
|
2309
2429
|
leaf = leafer;
|
|
2310
2430
|
renderOptions.bounds = canvas.bounds;
|
|
2311
2431
|
}
|
|
2312
2432
|
canvas.save();
|
|
2313
|
-
|
|
2433
|
+
if (isFrame && fill !== undefined) {
|
|
2434
|
+
const oldFill = leaf.get('fill');
|
|
2435
|
+
leaf.fill = '';
|
|
2436
|
+
leaf.__render(canvas, renderOptions);
|
|
2437
|
+
leaf.fill = oldFill;
|
|
2438
|
+
}
|
|
2439
|
+
else {
|
|
2440
|
+
leaf.__render(canvas, renderOptions);
|
|
2441
|
+
}
|
|
2314
2442
|
canvas.restore();
|
|
2315
2443
|
if (trim) {
|
|
2316
2444
|
trimBounds = getTrimBounds(canvas);
|
|
@@ -2321,8 +2449,10 @@ const ExportModule = {
|
|
|
2321
2449
|
}
|
|
2322
2450
|
if (needFill)
|
|
2323
2451
|
canvas.fillWorld(canvas.bounds, fill || '#FFFFFF', 'destination-over');
|
|
2452
|
+
if (onCanvas)
|
|
2453
|
+
onCanvas(canvas);
|
|
2324
2454
|
const data = filename === 'canvas' ? canvas : yield canvas.export(filename, options);
|
|
2325
|
-
over({ data, renderBounds, trimBounds });
|
|
2455
|
+
over({ data, width: canvas.pixelWidth, height: canvas.pixelHeight, renderBounds, trimBounds });
|
|
2326
2456
|
}));
|
|
2327
2457
|
}
|
|
2328
2458
|
else {
|
|
@@ -2339,12 +2469,56 @@ function addTask(task) {
|
|
|
2339
2469
|
tasker.add(() => __awaiter(this, void 0, void 0, function* () { return yield task(resolve); }), { parallel: false });
|
|
2340
2470
|
});
|
|
2341
2471
|
}
|
|
2472
|
+
function checkLazy(leaf) {
|
|
2473
|
+
if (leaf.__.__needComputePaint)
|
|
2474
|
+
leaf.__.__computePaint();
|
|
2475
|
+
if (leaf.isBranch)
|
|
2476
|
+
leaf.children.forEach(child => checkLazy(child));
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2479
|
+
const canvas = LeaferCanvasBase.prototype;
|
|
2480
|
+
const debug = Debug.get('@leafer-ui/export');
|
|
2481
|
+
canvas.export = function (filename, options) {
|
|
2482
|
+
const { quality, blob } = FileHelper.getExportOptions(options);
|
|
2483
|
+
if (filename.includes('.')) {
|
|
2484
|
+
return this.saveAs(filename, quality);
|
|
2485
|
+
}
|
|
2486
|
+
else if (blob) {
|
|
2487
|
+
return this.toBlob(filename, quality);
|
|
2488
|
+
}
|
|
2489
|
+
else {
|
|
2490
|
+
return this.toDataURL(filename, quality);
|
|
2491
|
+
}
|
|
2492
|
+
};
|
|
2493
|
+
canvas.toBlob = function (type, quality) {
|
|
2494
|
+
return new Promise((resolve) => {
|
|
2495
|
+
Platform.origin.canvasToBolb(this.view, type, quality).then((blob) => {
|
|
2496
|
+
resolve(blob);
|
|
2497
|
+
}).catch((e) => {
|
|
2498
|
+
debug.error(e);
|
|
2499
|
+
resolve(null);
|
|
2500
|
+
});
|
|
2501
|
+
});
|
|
2502
|
+
};
|
|
2503
|
+
canvas.toDataURL = function (type, quality) {
|
|
2504
|
+
return Platform.origin.canvasToDataURL(this.view, type, quality);
|
|
2505
|
+
};
|
|
2506
|
+
canvas.saveAs = function (filename, quality) {
|
|
2507
|
+
return new Promise((resolve) => {
|
|
2508
|
+
Platform.origin.canvasSaveAs(this.view, filename, quality).then(() => {
|
|
2509
|
+
resolve(true);
|
|
2510
|
+
}).catch((e) => {
|
|
2511
|
+
debug.error(e);
|
|
2512
|
+
resolve(false);
|
|
2513
|
+
});
|
|
2514
|
+
});
|
|
2515
|
+
};
|
|
2342
2516
|
|
|
2343
2517
|
Object.assign(TextConvert, TextConvertModule);
|
|
2344
2518
|
Object.assign(ColorConvert, ColorConvertModule);
|
|
2345
2519
|
Object.assign(Paint, PaintModule);
|
|
2346
|
-
Object.assign(PaintImage
|
|
2347
|
-
Object.assign(PaintGradient
|
|
2520
|
+
Object.assign(PaintImage, PaintImageModule);
|
|
2521
|
+
Object.assign(PaintGradient, PaintGradientModule);
|
|
2348
2522
|
Object.assign(Effect, EffectModule);
|
|
2349
2523
|
Object.assign(Export, ExportModule);
|
|
2350
2524
|
|