leafer-ui 1.0.0-rc.3 → 1.0.0-rc.30
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 +21 -5
- package/dist/web.esm.js +1556 -1066
- package/dist/web.esm.min.js +1 -1
- package/dist/web.js +7770 -5760
- package/dist/web.min.js +1 -1
- package/dist/web.module.js +7724 -5748
- package/dist/web.module.min.js +1 -1
- package/package.json +11 -4
- package/src/index.ts +1 -1
package/dist/web.esm.js
CHANGED
|
@@ -1,8 +1,255 @@
|
|
|
1
|
-
import {
|
|
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, 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 {
|
|
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 { view } = this.config;
|
|
30
|
+
view ? this.__createViewFrom(view) : this.__createView();
|
|
31
|
+
const { style } = this.view;
|
|
32
|
+
style.display || (style.display = 'block');
|
|
33
|
+
this.parentView = this.view.parentElement;
|
|
34
|
+
if (this.parentView) {
|
|
35
|
+
const pStyle = this.parentView.style;
|
|
36
|
+
pStyle.webkitUserSelect = pStyle.userSelect = 'none';
|
|
37
|
+
}
|
|
38
|
+
if (Platform.syncDomFont && !this.parentView) {
|
|
39
|
+
style.display = 'none';
|
|
40
|
+
document.body.appendChild(this.view);
|
|
41
|
+
}
|
|
42
|
+
this.__createContext();
|
|
43
|
+
if (!this.autoLayout)
|
|
44
|
+
this.resize(this.config);
|
|
45
|
+
}
|
|
46
|
+
set backgroundColor(color) { this.view.style.backgroundColor = color; }
|
|
47
|
+
get backgroundColor() { return this.view.style.backgroundColor; }
|
|
48
|
+
set hittable(hittable) { this.view.style.pointerEvents = hittable ? 'auto' : 'none'; }
|
|
49
|
+
get hittable() { return this.view.style.pointerEvents !== 'none'; }
|
|
50
|
+
__createView() {
|
|
51
|
+
this.view = document.createElement('canvas');
|
|
52
|
+
}
|
|
53
|
+
__createViewFrom(inputView) {
|
|
54
|
+
let find = (typeof inputView === 'string') ? document.getElementById(inputView) : inputView;
|
|
55
|
+
if (find) {
|
|
56
|
+
if (find instanceof HTMLCanvasElement) {
|
|
57
|
+
this.view = find;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
let parent = find;
|
|
61
|
+
if (find === window || find === document) {
|
|
62
|
+
const div = document.createElement('div');
|
|
63
|
+
const { style } = div;
|
|
64
|
+
style.position = 'absolute';
|
|
65
|
+
style.top = style.bottom = style.left = style.right = '0px';
|
|
66
|
+
document.body.appendChild(div);
|
|
67
|
+
parent = div;
|
|
68
|
+
}
|
|
69
|
+
this.__createView();
|
|
70
|
+
const view = this.view;
|
|
71
|
+
if (parent.hasChildNodes()) {
|
|
72
|
+
this.setAbsolute(view);
|
|
73
|
+
parent.style.position || (parent.style.position = 'relative');
|
|
74
|
+
}
|
|
75
|
+
parent.appendChild(view);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
debug$3.error(`no id: ${inputView}`);
|
|
80
|
+
this.__createView();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
setAbsolute(view) {
|
|
84
|
+
const { style } = view;
|
|
85
|
+
style.position = 'absolute';
|
|
86
|
+
style.top = style.left = '0px';
|
|
87
|
+
}
|
|
88
|
+
updateViewSize() {
|
|
89
|
+
const { width, height, pixelRatio } = this;
|
|
90
|
+
const { style } = this.view;
|
|
91
|
+
style.width = width + 'px';
|
|
92
|
+
style.height = height + 'px';
|
|
93
|
+
this.view.width = Math.ceil(width * pixelRatio);
|
|
94
|
+
this.view.height = Math.ceil(height * pixelRatio);
|
|
95
|
+
}
|
|
96
|
+
updateClientBounds() {
|
|
97
|
+
this.clientBounds = this.view.getBoundingClientRect();
|
|
98
|
+
}
|
|
99
|
+
startAutoLayout(autoBounds, listener) {
|
|
100
|
+
this.autoBounds = autoBounds;
|
|
101
|
+
this.resizeListener = listener;
|
|
102
|
+
try {
|
|
103
|
+
this.resizeObserver = new ResizeObserver((entries) => {
|
|
104
|
+
this.updateClientBounds();
|
|
105
|
+
for (const entry of entries)
|
|
106
|
+
this.checkAutoBounds(entry.contentRect);
|
|
107
|
+
});
|
|
108
|
+
const parent = this.parentView;
|
|
109
|
+
if (parent) {
|
|
110
|
+
this.resizeObserver.observe(parent);
|
|
111
|
+
this.checkAutoBounds(parent.getBoundingClientRect());
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
this.checkAutoBounds(this.view);
|
|
115
|
+
debug$3.warn('no parent');
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch (_a) {
|
|
119
|
+
this.imitateResizeObserver();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
imitateResizeObserver() {
|
|
123
|
+
if (this.autoLayout) {
|
|
124
|
+
if (this.parentView)
|
|
125
|
+
this.checkAutoBounds(this.parentView.getBoundingClientRect());
|
|
126
|
+
Platform.requestRender(this.imitateResizeObserver.bind(this));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
checkAutoBounds(parentSize) {
|
|
130
|
+
const view = this.view;
|
|
131
|
+
const { x, y, width, height } = this.autoBounds.getBoundsFrom(parentSize);
|
|
132
|
+
if (width !== this.width || height !== this.height) {
|
|
133
|
+
const { style } = view;
|
|
134
|
+
const { pixelRatio } = this;
|
|
135
|
+
style.marginLeft = x + 'px';
|
|
136
|
+
style.marginTop = y + 'px';
|
|
137
|
+
const size = { width, height, pixelRatio };
|
|
138
|
+
const oldSize = {};
|
|
139
|
+
DataHelper.copyAttrs(oldSize, this, canvasSizeAttrs);
|
|
140
|
+
this.resize(size);
|
|
141
|
+
if (this.width !== undefined)
|
|
142
|
+
this.resizeListener(new ResizeEvent(size, oldSize));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
stopAutoLayout() {
|
|
146
|
+
this.autoLayout = false;
|
|
147
|
+
this.resizeListener = null;
|
|
148
|
+
if (this.resizeObserver) {
|
|
149
|
+
this.resizeObserver.disconnect();
|
|
150
|
+
this.resizeObserver = null;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
unrealCanvas() {
|
|
154
|
+
if (!this.unreal && this.parentView) {
|
|
155
|
+
const view = this.view;
|
|
156
|
+
if (view)
|
|
157
|
+
view.remove();
|
|
158
|
+
this.view = this.parentView;
|
|
159
|
+
this.unreal = true;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
destroy() {
|
|
163
|
+
if (this.view) {
|
|
164
|
+
this.stopAutoLayout();
|
|
165
|
+
if (!this.unreal) {
|
|
166
|
+
const view = this.view;
|
|
167
|
+
if (view.parentElement)
|
|
168
|
+
view.remove();
|
|
169
|
+
}
|
|
170
|
+
super.destroy();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
canvasPatch(CanvasRenderingContext2D.prototype);
|
|
176
|
+
canvasPatch(Path2D.prototype);
|
|
177
|
+
|
|
178
|
+
const { mineType, fileType } = FileHelper;
|
|
179
|
+
Object.assign(Creator, {
|
|
180
|
+
canvas: (options, manager) => new LeaferCanvas(options, manager),
|
|
181
|
+
image: (options) => new LeaferImage(options)
|
|
182
|
+
});
|
|
183
|
+
function useCanvas(_canvasType, _power) {
|
|
184
|
+
Platform.origin = {
|
|
185
|
+
createCanvas(width, height) {
|
|
186
|
+
const canvas = document.createElement('canvas');
|
|
187
|
+
canvas.width = width;
|
|
188
|
+
canvas.height = height;
|
|
189
|
+
return canvas;
|
|
190
|
+
},
|
|
191
|
+
canvasToDataURL: (canvas, type, quality) => canvas.toDataURL(mineType(type), quality),
|
|
192
|
+
canvasToBolb: (canvas, type, quality) => new Promise((resolve) => canvas.toBlob(resolve, mineType(type), quality)),
|
|
193
|
+
canvasSaveAs: (canvas, filename, quality) => {
|
|
194
|
+
const url = canvas.toDataURL(mineType(fileType(filename)), quality);
|
|
195
|
+
return Platform.origin.download(url, filename);
|
|
196
|
+
},
|
|
197
|
+
download(url, filename) {
|
|
198
|
+
return new Promise((resolve) => {
|
|
199
|
+
let el = document.createElement('a');
|
|
200
|
+
el.href = url;
|
|
201
|
+
el.download = filename;
|
|
202
|
+
document.body.appendChild(el);
|
|
203
|
+
el.click();
|
|
204
|
+
document.body.removeChild(el);
|
|
205
|
+
resolve();
|
|
206
|
+
});
|
|
207
|
+
},
|
|
208
|
+
loadImage(src) {
|
|
209
|
+
return new Promise((resolve, reject) => {
|
|
210
|
+
const img = new Image();
|
|
211
|
+
const { crossOrigin } = Platform.image;
|
|
212
|
+
if (crossOrigin) {
|
|
213
|
+
img.setAttribute('crossOrigin', crossOrigin);
|
|
214
|
+
img.crossOrigin = crossOrigin;
|
|
215
|
+
}
|
|
216
|
+
img.onload = () => { resolve(img); };
|
|
217
|
+
img.onerror = (e) => { reject(e); };
|
|
218
|
+
img.src = Platform.image.getRealURL(src);
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
Platform.event = {
|
|
223
|
+
stopDefault(origin) { origin.preventDefault(); },
|
|
224
|
+
stopNow(origin) { origin.stopImmediatePropagation(); },
|
|
225
|
+
stop(origin) { origin.stopPropagation(); }
|
|
226
|
+
};
|
|
227
|
+
Platform.canvas = Creator.canvas();
|
|
228
|
+
Platform.conicGradientSupport = !!Platform.canvas.context.createConicGradient;
|
|
229
|
+
}
|
|
230
|
+
Platform.name = 'web';
|
|
231
|
+
Platform.isMobile = 'ontouchstart' in window;
|
|
232
|
+
Platform.requestRender = function (render) { window.requestAnimationFrame(render); };
|
|
233
|
+
Platform.devicePixelRatio = Math.max(1, devicePixelRatio);
|
|
234
|
+
const { userAgent } = navigator;
|
|
235
|
+
if (userAgent.indexOf("Firefox") > -1) {
|
|
236
|
+
Platform.conicGradientRotate90 = true;
|
|
237
|
+
Platform.intWheelDeltaY = true;
|
|
238
|
+
Platform.syncDomFont = true;
|
|
239
|
+
}
|
|
240
|
+
else if (userAgent.indexOf("Safari") > -1 && userAgent.indexOf("Chrome") === -1) {
|
|
241
|
+
Platform.fullImageShadow = true;
|
|
242
|
+
}
|
|
243
|
+
if (userAgent.indexOf('Windows') > -1) {
|
|
244
|
+
Platform.os = 'Windows';
|
|
245
|
+
Platform.intWheelDeltaY = true;
|
|
246
|
+
}
|
|
247
|
+
else if (userAgent.indexOf('Mac') > -1) {
|
|
248
|
+
Platform.os = 'Mac';
|
|
249
|
+
}
|
|
250
|
+
else if (userAgent.indexOf('Linux') > -1) {
|
|
251
|
+
Platform.os = 'Linux';
|
|
252
|
+
}
|
|
6
253
|
|
|
7
254
|
class Watcher {
|
|
8
255
|
get childrenChanged() { return this.hasAdd || this.hasRemove || this.hasVisible; }
|
|
@@ -10,7 +257,7 @@ class Watcher {
|
|
|
10
257
|
if (this.hasRemove) {
|
|
11
258
|
const updatedList = new LeafList();
|
|
12
259
|
this.__updatedList.list.forEach(item => { if (item.leafer)
|
|
13
|
-
updatedList.
|
|
260
|
+
updatedList.add(item); });
|
|
14
261
|
return updatedList;
|
|
15
262
|
}
|
|
16
263
|
else {
|
|
@@ -45,7 +292,7 @@ class Watcher {
|
|
|
45
292
|
this.target.emit(RenderEvent.REQUEST);
|
|
46
293
|
}
|
|
47
294
|
__onAttrChange(event) {
|
|
48
|
-
this.__updatedList.
|
|
295
|
+
this.__updatedList.add(event.target);
|
|
49
296
|
this.update();
|
|
50
297
|
}
|
|
51
298
|
__onChildEvent(event) {
|
|
@@ -55,12 +302,12 @@ class Watcher {
|
|
|
55
302
|
}
|
|
56
303
|
else {
|
|
57
304
|
this.hasRemove = true;
|
|
58
|
-
this.__updatedList.
|
|
305
|
+
this.__updatedList.add(event.parent);
|
|
59
306
|
}
|
|
60
307
|
this.update();
|
|
61
308
|
}
|
|
62
309
|
__pushChild(child) {
|
|
63
|
-
this.__updatedList.
|
|
310
|
+
this.__updatedList.add(child);
|
|
64
311
|
if (child.isBranch)
|
|
65
312
|
this.__loopChildren(child);
|
|
66
313
|
}
|
|
@@ -99,22 +346,22 @@ class Watcher {
|
|
|
99
346
|
}
|
|
100
347
|
}
|
|
101
348
|
|
|
102
|
-
const {
|
|
349
|
+
const { updateAllMatrix: updateAllMatrix$1, updateBounds: updateOneBounds, updateAllWorldOpacity } = LeafHelper;
|
|
103
350
|
const { pushAllChildBranch, pushAllParent } = BranchHelper;
|
|
104
351
|
function updateMatrix(updateList, levelList) {
|
|
105
352
|
let layout;
|
|
106
353
|
updateList.list.forEach(leaf => {
|
|
107
354
|
layout = leaf.__layout;
|
|
108
|
-
if (levelList.without(leaf) && !layout.
|
|
355
|
+
if (levelList.without(leaf) && !layout.proxyZoom) {
|
|
109
356
|
if (layout.matrixChanged) {
|
|
110
|
-
|
|
111
|
-
levelList.
|
|
357
|
+
updateAllMatrix$1(leaf, true);
|
|
358
|
+
levelList.add(leaf);
|
|
112
359
|
if (leaf.isBranch)
|
|
113
360
|
pushAllChildBranch(leaf, levelList);
|
|
114
361
|
pushAllParent(leaf, levelList);
|
|
115
362
|
}
|
|
116
363
|
else if (layout.boundsChanged) {
|
|
117
|
-
levelList.
|
|
364
|
+
levelList.add(leaf);
|
|
118
365
|
if (leaf.isBranch)
|
|
119
366
|
leaf.__tempNumber = 0;
|
|
120
367
|
pushAllParent(leaf, levelList);
|
|
@@ -123,20 +370,21 @@ function updateMatrix(updateList, levelList) {
|
|
|
123
370
|
});
|
|
124
371
|
}
|
|
125
372
|
function updateBounds(boundsList) {
|
|
126
|
-
let
|
|
373
|
+
let list, branch, children;
|
|
127
374
|
boundsList.sort(true);
|
|
128
375
|
boundsList.levels.forEach(level => {
|
|
129
|
-
|
|
130
|
-
for (let i = 0, len =
|
|
131
|
-
branch =
|
|
376
|
+
list = boundsList.levelMap[level];
|
|
377
|
+
for (let i = 0, len = list.length; i < len; i++) {
|
|
378
|
+
branch = list[i];
|
|
132
379
|
if (branch.isBranch && branch.__tempNumber) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
380
|
+
children = branch.children;
|
|
381
|
+
for (let j = 0, jLen = children.length; j < jLen; j++) {
|
|
382
|
+
if (!children[j].isBranch) {
|
|
383
|
+
updateOneBounds(children[j]);
|
|
136
384
|
}
|
|
137
385
|
}
|
|
138
386
|
}
|
|
139
|
-
branch
|
|
387
|
+
updateOneBounds(branch);
|
|
140
388
|
}
|
|
141
389
|
});
|
|
142
390
|
}
|
|
@@ -149,7 +397,7 @@ function updateChange(updateList) {
|
|
|
149
397
|
}
|
|
150
398
|
|
|
151
399
|
const { worldBounds } = LeafBoundsHelper;
|
|
152
|
-
const {
|
|
400
|
+
const bigBounds = { x: 0, y: 0, width: 100000, height: 100000 };
|
|
153
401
|
class LayoutBlockData {
|
|
154
402
|
constructor(list) {
|
|
155
403
|
this.updatedBounds = new Bounds();
|
|
@@ -160,14 +408,20 @@ class LayoutBlockData {
|
|
|
160
408
|
this.updatedList = list;
|
|
161
409
|
}
|
|
162
410
|
setBefore() {
|
|
163
|
-
|
|
411
|
+
this.beforeBounds.setListWithFn(this.updatedList.list, worldBounds);
|
|
164
412
|
}
|
|
165
413
|
setAfter() {
|
|
166
|
-
|
|
167
|
-
|
|
414
|
+
const { list } = this.updatedList;
|
|
415
|
+
if (list.some(leaf => leaf.noBounds)) {
|
|
416
|
+
this.afterBounds.set(bigBounds);
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
419
|
+
this.afterBounds.setListWithFn(list, worldBounds);
|
|
420
|
+
}
|
|
421
|
+
this.updatedBounds.setList([this.beforeBounds, this.afterBounds]);
|
|
168
422
|
}
|
|
169
423
|
merge(data) {
|
|
170
|
-
this.updatedList.
|
|
424
|
+
this.updatedList.addList(data.updatedList.list);
|
|
171
425
|
this.beforeBounds.add(data.beforeBounds);
|
|
172
426
|
this.afterBounds.add(data.afterBounds);
|
|
173
427
|
this.updatedBounds.add(data.updatedBounds);
|
|
@@ -177,8 +431,7 @@ class LayoutBlockData {
|
|
|
177
431
|
}
|
|
178
432
|
}
|
|
179
433
|
|
|
180
|
-
const {
|
|
181
|
-
const { pushAllBranchStack, updateWorldBoundsByBranchStack } = BranchHelper;
|
|
434
|
+
const { updateAllMatrix, updateAllChange } = LeafHelper;
|
|
182
435
|
const debug$2 = Debug.get('Layouter');
|
|
183
436
|
class Layouter {
|
|
184
437
|
constructor(target, userConfig) {
|
|
@@ -255,12 +508,15 @@ class Layouter {
|
|
|
255
508
|
const { target, __updatedList: updateList } = this;
|
|
256
509
|
const { BEFORE, LAYOUT, AFTER } = LayoutEvent;
|
|
257
510
|
const blocks = this.getBlocks(updateList);
|
|
258
|
-
blocks.forEach(item =>
|
|
511
|
+
blocks.forEach(item => item.setBefore());
|
|
259
512
|
target.emitEvent(new LayoutEvent(BEFORE, blocks, this.times));
|
|
513
|
+
this.extraBlock = null;
|
|
260
514
|
updateList.sort();
|
|
261
515
|
updateMatrix(updateList, this.__levelList);
|
|
262
516
|
updateBounds(this.__levelList);
|
|
263
517
|
updateChange(updateList);
|
|
518
|
+
if (this.extraBlock)
|
|
519
|
+
blocks.push(this.extraBlock);
|
|
264
520
|
blocks.forEach(item => item.setAfter());
|
|
265
521
|
target.emitEvent(new LayoutEvent(LAYOUT, blocks, this.times));
|
|
266
522
|
target.emitEvent(new LayoutEvent(AFTER, blocks, this.times));
|
|
@@ -283,17 +539,22 @@ class Layouter {
|
|
|
283
539
|
Run.end(t);
|
|
284
540
|
}
|
|
285
541
|
static fullLayout(target) {
|
|
286
|
-
|
|
542
|
+
updateAllMatrix(target, true);
|
|
287
543
|
if (target.isBranch) {
|
|
288
|
-
|
|
289
|
-
pushAllBranchStack(target, branchStack);
|
|
290
|
-
updateWorldBoundsByBranchStack(branchStack);
|
|
544
|
+
BranchHelper.updateBounds(target);
|
|
291
545
|
}
|
|
292
546
|
else {
|
|
293
|
-
|
|
547
|
+
LeafHelper.updateBounds(target);
|
|
294
548
|
}
|
|
295
549
|
updateAllChange(target);
|
|
296
550
|
}
|
|
551
|
+
addExtra(leaf) {
|
|
552
|
+
if (!this.__updatedList.has(leaf)) {
|
|
553
|
+
const { updatedList, beforeBounds } = this.extraBlock || (this.extraBlock = new LayoutBlockData([]));
|
|
554
|
+
updatedList.length ? beforeBounds.add(leaf.__world) : beforeBounds.set(leaf.__world);
|
|
555
|
+
updatedList.add(leaf);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
297
558
|
createBlock(data) {
|
|
298
559
|
return new LayoutBlockData(data);
|
|
299
560
|
}
|
|
@@ -321,8 +582,7 @@ class Layouter {
|
|
|
321
582
|
if (this.target) {
|
|
322
583
|
this.stop();
|
|
323
584
|
this.__removeListenEvents();
|
|
324
|
-
this.target = null;
|
|
325
|
-
this.config = null;
|
|
585
|
+
this.target = this.config = null;
|
|
326
586
|
}
|
|
327
587
|
}
|
|
328
588
|
}
|
|
@@ -403,6 +663,10 @@ class Renderer {
|
|
|
403
663
|
}
|
|
404
664
|
else {
|
|
405
665
|
this.requestLayout();
|
|
666
|
+
if (this.ignore) {
|
|
667
|
+
this.ignore = this.rendering = false;
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
406
670
|
this.emitRender(RenderEvent.BEFORE);
|
|
407
671
|
if (this.config.usePartRender && this.totalTimes > 1) {
|
|
408
672
|
this.partRender();
|
|
@@ -424,8 +688,7 @@ class Renderer {
|
|
|
424
688
|
const { canvas, updateBlocks: list } = this;
|
|
425
689
|
if (!list)
|
|
426
690
|
return debug$1.warn('PartRender: need update attr');
|
|
427
|
-
|
|
428
|
-
this.mergeBlocks();
|
|
691
|
+
this.mergeBlocks();
|
|
429
692
|
list.forEach(block => { if (canvas.bounds.hit(block) && !block.isEmpty())
|
|
430
693
|
this.clipRender(block); });
|
|
431
694
|
}
|
|
@@ -434,17 +697,17 @@ class Renderer {
|
|
|
434
697
|
const { canvas } = this;
|
|
435
698
|
const bounds = block.getIntersect(canvas.bounds);
|
|
436
699
|
const includes = block.includes(this.target.__world);
|
|
437
|
-
const realBounds = new Bounds(
|
|
700
|
+
const realBounds = new Bounds(bounds);
|
|
438
701
|
canvas.save();
|
|
439
702
|
if (includes && !Debug.showRepaint) {
|
|
440
703
|
canvas.clear();
|
|
441
704
|
}
|
|
442
705
|
else {
|
|
443
|
-
bounds.spread(
|
|
706
|
+
bounds.spread(10 + 1 / this.canvas.pixelRatio).ceil();
|
|
444
707
|
canvas.clearWorld(bounds, true);
|
|
445
708
|
canvas.clipWorld(bounds, true);
|
|
446
709
|
}
|
|
447
|
-
this.__render(bounds, realBounds);
|
|
710
|
+
this.__render(bounds, includes, realBounds);
|
|
448
711
|
canvas.restore();
|
|
449
712
|
Run.end(t);
|
|
450
713
|
}
|
|
@@ -453,12 +716,12 @@ class Renderer {
|
|
|
453
716
|
const { canvas } = this;
|
|
454
717
|
canvas.save();
|
|
455
718
|
canvas.clear();
|
|
456
|
-
this.__render(canvas.bounds);
|
|
719
|
+
this.__render(canvas.bounds, true);
|
|
457
720
|
canvas.restore();
|
|
458
721
|
Run.end(t);
|
|
459
722
|
}
|
|
460
|
-
__render(bounds, realBounds) {
|
|
461
|
-
const options =
|
|
723
|
+
__render(bounds, includes, realBounds) {
|
|
724
|
+
const options = bounds.includes(this.target.__world) ? { includes } : { bounds, includes };
|
|
462
725
|
if (this.needFill)
|
|
463
726
|
this.canvas.fillWorld(bounds, this.config.fill);
|
|
464
727
|
if (Debug.showRepaint)
|
|
@@ -484,7 +747,7 @@ class Renderer {
|
|
|
484
747
|
const { updateBlocks: list } = this;
|
|
485
748
|
if (list) {
|
|
486
749
|
const bounds = new Bounds();
|
|
487
|
-
bounds.
|
|
750
|
+
bounds.setList(list);
|
|
488
751
|
list.length = 0;
|
|
489
752
|
list.push(bounds);
|
|
490
753
|
}
|
|
@@ -493,12 +756,12 @@ class Renderer {
|
|
|
493
756
|
const startTime = Date.now();
|
|
494
757
|
Platform.requestRender(() => {
|
|
495
758
|
this.FPS = Math.min(60, Math.ceil(1000 / (Date.now() - startTime)));
|
|
496
|
-
if (this.
|
|
497
|
-
|
|
759
|
+
if (this.running) {
|
|
760
|
+
this.target.emit(AnimateEvent.FRAME);
|
|
761
|
+
if (this.changed && this.canvas.view)
|
|
498
762
|
this.render();
|
|
763
|
+
this.target.emit(RenderEvent.NEXT);
|
|
499
764
|
}
|
|
500
|
-
if (this.running)
|
|
501
|
-
this.target.emit(AnimateEvent.FRAME);
|
|
502
765
|
if (this.target)
|
|
503
766
|
this.__requestRender();
|
|
504
767
|
});
|
|
@@ -511,9 +774,12 @@ class Renderer {
|
|
|
511
774
|
const bounds = new Bounds(0, 0, width, height);
|
|
512
775
|
if (!bounds.includes(this.target.__world) || this.needFill || !e.samePixelRatio) {
|
|
513
776
|
this.addBlock(this.canvas.bounds);
|
|
514
|
-
this.target.forceUpdate('
|
|
777
|
+
this.target.forceUpdate('surface');
|
|
778
|
+
return;
|
|
515
779
|
}
|
|
516
780
|
}
|
|
781
|
+
this.addBlock(new Bounds(0, 0, 1, 1));
|
|
782
|
+
this.changed = true;
|
|
517
783
|
}
|
|
518
784
|
__onLayoutEnd(event) {
|
|
519
785
|
if (event.data)
|
|
@@ -524,7 +790,7 @@ class Renderer {
|
|
|
524
790
|
empty = (!leaf.__world.width || !leaf.__world.height);
|
|
525
791
|
if (empty) {
|
|
526
792
|
if (!leaf.isLeafer)
|
|
527
|
-
debug$1.
|
|
793
|
+
debug$1.tip(leaf.innerName, ': empty');
|
|
528
794
|
empty = (!leaf.isBranch || leaf.isBranchLeaf);
|
|
529
795
|
}
|
|
530
796
|
return empty;
|
|
@@ -551,15 +817,13 @@ class Renderer {
|
|
|
551
817
|
if (this.target) {
|
|
552
818
|
this.stop();
|
|
553
819
|
this.__removeListenEvents();
|
|
554
|
-
this.target = null;
|
|
555
|
-
this.canvas = null;
|
|
556
|
-
this.config = null;
|
|
820
|
+
this.target = this.canvas = this.config = null;
|
|
557
821
|
}
|
|
558
822
|
}
|
|
559
823
|
}
|
|
560
824
|
|
|
561
825
|
const { hitRadiusPoint } = BoundsHelper;
|
|
562
|
-
class
|
|
826
|
+
class Picker {
|
|
563
827
|
constructor(target, selector) {
|
|
564
828
|
this.target = target;
|
|
565
829
|
this.selector = selector;
|
|
@@ -571,51 +835,59 @@ class FindPath {
|
|
|
571
835
|
options = {};
|
|
572
836
|
const through = options.through || false;
|
|
573
837
|
const ignoreHittable = options.ignoreHittable || false;
|
|
838
|
+
const target = options.target || this.target;
|
|
574
839
|
this.exclude = options.exclude || null;
|
|
575
840
|
this.point = { x: hitPoint.x, y: hitPoint.y, radiusX: hitRadius, radiusY: hitRadius };
|
|
576
|
-
this.findList =
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
const
|
|
841
|
+
this.findList = new LeafList(options.findList);
|
|
842
|
+
if (!options.findList)
|
|
843
|
+
this.hitBranch(target);
|
|
844
|
+
const { list } = this.findList;
|
|
845
|
+
const leaf = this.getBestMatchLeaf(list, options.bottomList, ignoreHittable);
|
|
580
846
|
const path = ignoreHittable ? this.getPath(leaf) : this.getHitablePath(leaf);
|
|
581
847
|
this.clear();
|
|
582
|
-
return through ? { path, leaf, throughPath: list.length ? this.getThroughPath(list) : path } : { path, leaf };
|
|
848
|
+
return through ? { path, target: leaf, throughPath: list.length ? this.getThroughPath(list) : path } : { path, target: leaf };
|
|
583
849
|
}
|
|
584
|
-
getBestMatchLeaf() {
|
|
585
|
-
|
|
586
|
-
if (targets.length > 1) {
|
|
850
|
+
getBestMatchLeaf(list, bottomList, ignoreHittable) {
|
|
851
|
+
if (list.length) {
|
|
587
852
|
let find;
|
|
588
|
-
this.findList =
|
|
853
|
+
this.findList = new LeafList();
|
|
589
854
|
const { x, y } = this.point;
|
|
590
855
|
const point = { x, y, radiusX: 0, radiusY: 0 };
|
|
591
|
-
for (let i = 0, len =
|
|
592
|
-
find =
|
|
593
|
-
if (LeafHelper.worldHittable(find)) {
|
|
856
|
+
for (let i = 0, len = list.length; i < len; i++) {
|
|
857
|
+
find = list[i];
|
|
858
|
+
if (ignoreHittable || LeafHelper.worldHittable(find)) {
|
|
594
859
|
this.hitChild(find, point);
|
|
595
860
|
if (this.findList.length)
|
|
596
|
-
return this.findList[0];
|
|
861
|
+
return this.findList.list[0];
|
|
597
862
|
}
|
|
598
863
|
}
|
|
599
864
|
}
|
|
600
|
-
|
|
865
|
+
if (bottomList) {
|
|
866
|
+
for (let i = 0, len = bottomList.length; i < len; i++) {
|
|
867
|
+
this.hitChild(bottomList[i].target, this.point, bottomList[i].proxy);
|
|
868
|
+
if (this.findList.length)
|
|
869
|
+
return this.findList.list[0];
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
return list[0];
|
|
601
873
|
}
|
|
602
874
|
getPath(leaf) {
|
|
603
875
|
const path = new LeafList();
|
|
604
876
|
while (leaf) {
|
|
605
|
-
path.
|
|
877
|
+
path.add(leaf);
|
|
606
878
|
leaf = leaf.parent;
|
|
607
879
|
}
|
|
608
|
-
path.
|
|
880
|
+
path.add(this.target);
|
|
609
881
|
return path;
|
|
610
882
|
}
|
|
611
883
|
getHitablePath(leaf) {
|
|
612
|
-
const path = this.getPath(leaf);
|
|
884
|
+
const path = this.getPath(leaf && leaf.hittable ? leaf : null);
|
|
613
885
|
let item, hittablePath = new LeafList();
|
|
614
886
|
for (let i = path.list.length - 1; i > -1; i--) {
|
|
615
887
|
item = path.list[i];
|
|
616
888
|
if (!item.__.hittable)
|
|
617
889
|
break;
|
|
618
|
-
hittablePath.
|
|
890
|
+
hittablePath.addAt(item, 0);
|
|
619
891
|
if (!item.__.hitChildren)
|
|
620
892
|
break;
|
|
621
893
|
}
|
|
@@ -634,17 +906,20 @@ class FindPath {
|
|
|
634
906
|
leaf = path.list[j];
|
|
635
907
|
if (nextPath && nextPath.has(leaf))
|
|
636
908
|
break;
|
|
637
|
-
throughPath.
|
|
909
|
+
throughPath.add(leaf);
|
|
638
910
|
}
|
|
639
911
|
}
|
|
640
912
|
return throughPath;
|
|
641
913
|
}
|
|
914
|
+
hitBranch(branch) {
|
|
915
|
+
this.eachFind(branch.children, branch.__onlyHitMask);
|
|
916
|
+
}
|
|
642
917
|
eachFind(children, hitMask) {
|
|
643
918
|
let child, hit;
|
|
644
919
|
const { point } = this, len = children.length;
|
|
645
920
|
for (let i = len - 1; i > -1; i--) {
|
|
646
921
|
child = children[i];
|
|
647
|
-
if (!child.__.visible || (hitMask && !child.__.
|
|
922
|
+
if (!child.__.visible || (hitMask && !child.__.mask))
|
|
648
923
|
continue;
|
|
649
924
|
hit = child.__.hitRadius ? true : hitRadiusPoint(child.__world, point);
|
|
650
925
|
if (child.isBranch) {
|
|
@@ -660,11 +935,15 @@ class FindPath {
|
|
|
660
935
|
}
|
|
661
936
|
}
|
|
662
937
|
}
|
|
663
|
-
hitChild(child, point) {
|
|
938
|
+
hitChild(child, point, proxy) {
|
|
664
939
|
if (this.exclude && this.exclude.has(child))
|
|
665
940
|
return;
|
|
666
|
-
if (child.__hitWorld(point))
|
|
667
|
-
|
|
941
|
+
if (child.__hitWorld(point)) {
|
|
942
|
+
const { parent } = child;
|
|
943
|
+
if (parent && parent.__hasMask && !child.__.mask && !parent.children.some(item => item.__.mask && item.__hitWorld(point)))
|
|
944
|
+
return;
|
|
945
|
+
this.findList.add(proxy || child);
|
|
946
|
+
}
|
|
668
947
|
}
|
|
669
948
|
clear() {
|
|
670
949
|
this.point = null;
|
|
@@ -676,120 +955,128 @@ class FindPath {
|
|
|
676
955
|
}
|
|
677
956
|
}
|
|
678
957
|
|
|
958
|
+
const { Yes, NoAndSkip, YesAndSkip } = Answer;
|
|
959
|
+
const idCondition = {}, classNameCondition = {}, tagCondition = {};
|
|
679
960
|
class Selector {
|
|
680
961
|
constructor(target, userConfig) {
|
|
681
962
|
this.config = {};
|
|
682
|
-
this.
|
|
683
|
-
this.
|
|
684
|
-
this.
|
|
685
|
-
|
|
963
|
+
this.innerIdMap = {};
|
|
964
|
+
this.idMap = {};
|
|
965
|
+
this.methods = {
|
|
966
|
+
id: (leaf, name) => leaf.id === name ? (this.idMap[name] = leaf, 1) : 0,
|
|
967
|
+
innerId: (leaf, innerId) => leaf.innerId === innerId ? (this.innerIdMap[innerId] = leaf, 1) : 0,
|
|
968
|
+
className: (leaf, name) => leaf.className === name ? 1 : 0,
|
|
969
|
+
tag: (leaf, name) => leaf.__tag === name ? 1 : 0,
|
|
970
|
+
tags: (leaf, nameMap) => nameMap[leaf.__tag] ? 1 : 0
|
|
971
|
+
};
|
|
686
972
|
this.target = target;
|
|
687
973
|
if (userConfig)
|
|
688
974
|
this.config = DataHelper.default(userConfig, this.config);
|
|
689
|
-
this.
|
|
975
|
+
this.picker = new Picker(target, this);
|
|
690
976
|
this.__listenEvents();
|
|
691
977
|
}
|
|
978
|
+
getBy(condition, branch, one, options) {
|
|
979
|
+
switch (typeof condition) {
|
|
980
|
+
case 'number':
|
|
981
|
+
const leaf = this.getByInnerId(condition, branch);
|
|
982
|
+
return one ? leaf : (leaf ? [leaf] : []);
|
|
983
|
+
case 'string':
|
|
984
|
+
switch (condition[0]) {
|
|
985
|
+
case '#':
|
|
986
|
+
idCondition.id = condition.substring(1), condition = idCondition;
|
|
987
|
+
break;
|
|
988
|
+
case '.':
|
|
989
|
+
classNameCondition.className = condition.substring(1), condition = classNameCondition;
|
|
990
|
+
break;
|
|
991
|
+
default:
|
|
992
|
+
tagCondition.tag = condition, condition = tagCondition;
|
|
993
|
+
}
|
|
994
|
+
case 'object':
|
|
995
|
+
if (condition.id !== undefined) {
|
|
996
|
+
const leaf = this.getById(condition.id, branch);
|
|
997
|
+
return one ? leaf : (leaf ? [leaf] : []);
|
|
998
|
+
}
|
|
999
|
+
else if (condition.tag) {
|
|
1000
|
+
const { tag } = condition, isArray = tag instanceof Array;
|
|
1001
|
+
return this.getByMethod(isArray ? this.methods.tags : this.methods.tag, branch, one, isArray ? DataHelper.toMap(tag) : tag);
|
|
1002
|
+
}
|
|
1003
|
+
else {
|
|
1004
|
+
return this.getByMethod(this.methods.className, branch, one, condition.className);
|
|
1005
|
+
}
|
|
1006
|
+
case 'function':
|
|
1007
|
+
return this.getByMethod(condition, branch, one, options);
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
692
1010
|
getByPoint(hitPoint, hitRadius, options) {
|
|
693
1011
|
if (Platform.name === 'node')
|
|
694
1012
|
this.target.emit(LayoutEvent.CHECK_UPDATE);
|
|
695
|
-
return this.
|
|
696
|
-
}
|
|
697
|
-
find(name, branch) {
|
|
698
|
-
if (typeof name === 'number') {
|
|
699
|
-
return this.getByInnerId(name, branch);
|
|
700
|
-
}
|
|
701
|
-
else if (name.startsWith('#')) {
|
|
702
|
-
return this.getById(name.substring(1), branch);
|
|
703
|
-
}
|
|
704
|
-
else if (name.startsWith('.')) {
|
|
705
|
-
return this.getByClassName(name.substring(1), branch);
|
|
706
|
-
}
|
|
707
|
-
else {
|
|
708
|
-
return this.getByTagName(name, branch);
|
|
709
|
-
}
|
|
1013
|
+
return this.picker.getByPoint(hitPoint, hitRadius, options);
|
|
710
1014
|
}
|
|
711
|
-
getByInnerId(
|
|
712
|
-
|
|
1015
|
+
getByInnerId(innerId, branch) {
|
|
1016
|
+
const cache = this.innerIdMap[innerId];
|
|
713
1017
|
if (cache)
|
|
714
1018
|
return cache;
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
let find;
|
|
718
|
-
this.loopFind(branch, (leaf) => {
|
|
719
|
-
if (leaf.innerId === name) {
|
|
720
|
-
find = leaf;
|
|
721
|
-
this.innerIdList[name] = find;
|
|
722
|
-
return true;
|
|
723
|
-
}
|
|
724
|
-
else {
|
|
725
|
-
return false;
|
|
726
|
-
}
|
|
727
|
-
});
|
|
728
|
-
return find;
|
|
1019
|
+
this.eachFind(this.toChildren(branch), this.methods.innerId, null, innerId);
|
|
1020
|
+
return this.findLeaf;
|
|
729
1021
|
}
|
|
730
|
-
getById(
|
|
731
|
-
|
|
732
|
-
if (cache)
|
|
1022
|
+
getById(id, branch) {
|
|
1023
|
+
const cache = this.idMap[id];
|
|
1024
|
+
if (cache && LeafHelper.hasParent(cache, branch || this.target))
|
|
733
1025
|
return cache;
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
let find;
|
|
737
|
-
this.loopFind(branch, (leaf) => {
|
|
738
|
-
if (leaf.id === name) {
|
|
739
|
-
find = leaf;
|
|
740
|
-
this.idList[name] = find;
|
|
741
|
-
return true;
|
|
742
|
-
}
|
|
743
|
-
else {
|
|
744
|
-
return false;
|
|
745
|
-
}
|
|
746
|
-
});
|
|
747
|
-
return find;
|
|
748
|
-
}
|
|
749
|
-
getByClassName(name, branch) {
|
|
750
|
-
if (!branch)
|
|
751
|
-
branch = this.target;
|
|
752
|
-
let find = [];
|
|
753
|
-
this.loopFind(branch, (leaf) => {
|
|
754
|
-
if (leaf.className === name)
|
|
755
|
-
find.push(leaf);
|
|
756
|
-
return false;
|
|
757
|
-
});
|
|
758
|
-
return find;
|
|
759
|
-
}
|
|
760
|
-
getByTagName(name, branch) {
|
|
761
|
-
if (!branch)
|
|
762
|
-
branch = this.target;
|
|
763
|
-
let find = [];
|
|
764
|
-
this.loopFind(branch, (leaf) => {
|
|
765
|
-
if (leaf.__tag === name)
|
|
766
|
-
find.push(leaf);
|
|
767
|
-
return false;
|
|
768
|
-
});
|
|
769
|
-
return find;
|
|
1026
|
+
this.eachFind(this.toChildren(branch), this.methods.id, null, id);
|
|
1027
|
+
return this.findLeaf;
|
|
770
1028
|
}
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
return;
|
|
774
|
-
const { children } = branch;
|
|
775
|
-
for (let i = 0, len = children.length; i < len; i++) {
|
|
776
|
-
branch = children[i];
|
|
777
|
-
if (find(branch))
|
|
778
|
-
return;
|
|
779
|
-
if (branch.isBranch)
|
|
780
|
-
this.loopFind(branch, find);
|
|
781
|
-
}
|
|
1029
|
+
getByClassName(className, branch) {
|
|
1030
|
+
return this.getByMethod(this.methods.className, branch, false, className);
|
|
782
1031
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
1032
|
+
getByTag(tag, branch) {
|
|
1033
|
+
return this.getByMethod(this.methods.tag, branch, false, tag);
|
|
1034
|
+
}
|
|
1035
|
+
getByMethod(method, branch, one, options) {
|
|
1036
|
+
const list = one ? null : [];
|
|
1037
|
+
this.eachFind(this.toChildren(branch), method, list, options);
|
|
1038
|
+
return list || this.findLeaf;
|
|
1039
|
+
}
|
|
1040
|
+
eachFind(children, method, list, options) {
|
|
1041
|
+
let child, result;
|
|
1042
|
+
for (let i = 0, len = children.length; i < len; i++) {
|
|
1043
|
+
child = children[i];
|
|
1044
|
+
result = method(child, options);
|
|
1045
|
+
if (result === Yes || result === YesAndSkip) {
|
|
1046
|
+
if (list) {
|
|
1047
|
+
list.push(child);
|
|
1048
|
+
}
|
|
1049
|
+
else {
|
|
1050
|
+
this.findLeaf = child;
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
if (child.isBranch && result < NoAndSkip)
|
|
1055
|
+
this.eachFind(child.children, method, list, options);
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
toChildren(branch) {
|
|
1059
|
+
this.findLeaf = null;
|
|
1060
|
+
return [branch || this.target];
|
|
1061
|
+
}
|
|
1062
|
+
__onRemoveChild(event) {
|
|
1063
|
+
const { id, innerId } = event.child;
|
|
1064
|
+
if (this.idMap[id])
|
|
1065
|
+
delete this.idMap[id];
|
|
1066
|
+
if (this.innerIdMap[innerId])
|
|
1067
|
+
delete this.innerIdMap[innerId];
|
|
1068
|
+
}
|
|
1069
|
+
__checkIdChange(event) {
|
|
1070
|
+
if (event.attrName === 'id') {
|
|
1071
|
+
const id = event.oldValue;
|
|
1072
|
+
if (this.idMap[id])
|
|
1073
|
+
delete this.idMap[id];
|
|
1074
|
+
}
|
|
789
1075
|
}
|
|
790
1076
|
__listenEvents() {
|
|
791
1077
|
this.__eventIds = [
|
|
792
|
-
this.target.on_(ChildEvent.REMOVE, this.__onRemoveChild, this)
|
|
1078
|
+
this.target.on_(ChildEvent.REMOVE, this.__onRemoveChild, this),
|
|
1079
|
+
this.target.on_(PropertyEvent.CHANGE, this.__checkIdChange, this)
|
|
793
1080
|
];
|
|
794
1081
|
}
|
|
795
1082
|
__removeListenEvents() {
|
|
@@ -799,11 +1086,10 @@ class Selector {
|
|
|
799
1086
|
destroy() {
|
|
800
1087
|
if (this.__eventIds.length) {
|
|
801
1088
|
this.__removeListenEvents();
|
|
802
|
-
this.
|
|
803
|
-
this.
|
|
804
|
-
this.
|
|
805
|
-
this.
|
|
806
|
-
this.tagNameList = {};
|
|
1089
|
+
this.picker.destroy();
|
|
1090
|
+
this.findLeaf = null;
|
|
1091
|
+
this.innerIdMap = {};
|
|
1092
|
+
this.idMap = {};
|
|
807
1093
|
}
|
|
808
1094
|
}
|
|
809
1095
|
}
|
|
@@ -816,169 +1102,6 @@ Object.assign(Creator, {
|
|
|
816
1102
|
});
|
|
817
1103
|
Platform.layout = Layouter.fullLayout;
|
|
818
1104
|
|
|
819
|
-
const debug = Debug.get('LeaferCanvas');
|
|
820
|
-
class LeaferCanvas extends LeaferCanvasBase {
|
|
821
|
-
init() {
|
|
822
|
-
const { view } = this.config;
|
|
823
|
-
view ? this.__createViewFrom(view) : this.__createView();
|
|
824
|
-
const { style } = this.view;
|
|
825
|
-
style.display || (style.display = 'block');
|
|
826
|
-
this.parentView = this.view.parentElement;
|
|
827
|
-
if (Platform.syncDomFont && !this.parentView) {
|
|
828
|
-
this.view.style.display = 'none';
|
|
829
|
-
document.body.appendChild(this.view);
|
|
830
|
-
}
|
|
831
|
-
this.__createContext();
|
|
832
|
-
if (!this.autoLayout)
|
|
833
|
-
this.resize(this.config);
|
|
834
|
-
}
|
|
835
|
-
set backgroundColor(color) { this.view.style.backgroundColor = color; }
|
|
836
|
-
get backgroundColor() { return this.view.style.backgroundColor; }
|
|
837
|
-
set hittable(hittable) { this.view.style.pointerEvents = hittable ? 'auto' : 'none'; }
|
|
838
|
-
get hittable() { return this.view.style.pointerEvents !== 'none'; }
|
|
839
|
-
__createView() {
|
|
840
|
-
this.view = document.createElement('canvas');
|
|
841
|
-
}
|
|
842
|
-
setCursor(cursor) {
|
|
843
|
-
const list = [];
|
|
844
|
-
this.eachCursor(cursor, list);
|
|
845
|
-
if (typeof list[list.length - 1] === 'object')
|
|
846
|
-
list.push('default');
|
|
847
|
-
this.view.style.cursor = list.map(item => (typeof item === 'object') ? `url(${item.url}) ${item.x || 0} ${item.y || 0}` : item).join(',');
|
|
848
|
-
}
|
|
849
|
-
eachCursor(cursor, list, level = 0) {
|
|
850
|
-
level++;
|
|
851
|
-
if (cursor instanceof Array) {
|
|
852
|
-
cursor.forEach(item => this.eachCursor(item, list, level));
|
|
853
|
-
}
|
|
854
|
-
else {
|
|
855
|
-
const custom = typeof cursor === 'string' && Cursor.get(cursor);
|
|
856
|
-
if (custom && level < 2) {
|
|
857
|
-
this.eachCursor(custom, list, level);
|
|
858
|
-
}
|
|
859
|
-
else {
|
|
860
|
-
list.push(cursor);
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
__createViewFrom(inputView) {
|
|
865
|
-
let find = (typeof inputView === 'string') ? document.getElementById(inputView) : inputView;
|
|
866
|
-
if (find) {
|
|
867
|
-
if (find instanceof HTMLCanvasElement) {
|
|
868
|
-
this.view = find;
|
|
869
|
-
}
|
|
870
|
-
else {
|
|
871
|
-
let parent = find;
|
|
872
|
-
if (find === window || find === document) {
|
|
873
|
-
const div = document.createElement('div');
|
|
874
|
-
const { style } = div;
|
|
875
|
-
style.position = 'absolute';
|
|
876
|
-
style.top = style.bottom = style.left = style.right = '0px';
|
|
877
|
-
document.body.appendChild(div);
|
|
878
|
-
parent = div;
|
|
879
|
-
}
|
|
880
|
-
this.__createView();
|
|
881
|
-
const view = this.view;
|
|
882
|
-
if (parent.hasChildNodes()) {
|
|
883
|
-
const { style } = view;
|
|
884
|
-
style.position = 'absolute';
|
|
885
|
-
style.top = style.left = '0px';
|
|
886
|
-
parent.style.position || (parent.style.position = 'relative');
|
|
887
|
-
}
|
|
888
|
-
parent.appendChild(view);
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
else {
|
|
892
|
-
debug.error(`no id: ${inputView}`);
|
|
893
|
-
this.__createView();
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
updateViewSize() {
|
|
897
|
-
const { width, height, pixelRatio } = this;
|
|
898
|
-
const { style } = this.view;
|
|
899
|
-
style.width = width + 'px';
|
|
900
|
-
style.height = height + 'px';
|
|
901
|
-
this.view.width = width * pixelRatio;
|
|
902
|
-
this.view.height = height * pixelRatio;
|
|
903
|
-
}
|
|
904
|
-
updateClientBounds() {
|
|
905
|
-
this.clientBounds = this.view.getBoundingClientRect();
|
|
906
|
-
}
|
|
907
|
-
startAutoLayout(autoBounds, listener) {
|
|
908
|
-
this.autoBounds = autoBounds;
|
|
909
|
-
this.resizeListener = listener;
|
|
910
|
-
try {
|
|
911
|
-
this.resizeObserver = new ResizeObserver((entries) => {
|
|
912
|
-
this.updateClientBounds();
|
|
913
|
-
for (const entry of entries)
|
|
914
|
-
this.checkAutoBounds(entry.contentRect);
|
|
915
|
-
});
|
|
916
|
-
const parent = this.parentView;
|
|
917
|
-
if (parent) {
|
|
918
|
-
this.resizeObserver.observe(parent);
|
|
919
|
-
this.checkAutoBounds(parent.getBoundingClientRect());
|
|
920
|
-
}
|
|
921
|
-
}
|
|
922
|
-
catch (_a) {
|
|
923
|
-
this.imitateResizeObserver();
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
imitateResizeObserver() {
|
|
927
|
-
if (this.autoLayout) {
|
|
928
|
-
if (this.parentView)
|
|
929
|
-
this.checkAutoBounds(this.parentView.getBoundingClientRect());
|
|
930
|
-
Platform.requestRender(this.imitateResizeObserver.bind(this));
|
|
931
|
-
}
|
|
932
|
-
}
|
|
933
|
-
checkAutoBounds(parentSize) {
|
|
934
|
-
const view = this.view;
|
|
935
|
-
const { x, y, width, height } = this.autoBounds.getBoundsFrom(parentSize);
|
|
936
|
-
if (width !== this.width || height !== this.height) {
|
|
937
|
-
const { style } = view;
|
|
938
|
-
const { pixelRatio } = this;
|
|
939
|
-
style.marginLeft = x + 'px';
|
|
940
|
-
style.marginTop = y + 'px';
|
|
941
|
-
const size = { width, height, pixelRatio };
|
|
942
|
-
const oldSize = {};
|
|
943
|
-
DataHelper.copyAttrs(oldSize, this, canvasSizeAttrs);
|
|
944
|
-
this.resize(size);
|
|
945
|
-
if (this.width !== undefined)
|
|
946
|
-
this.resizeListener(new ResizeEvent(size, oldSize));
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
stopAutoLayout() {
|
|
950
|
-
this.autoLayout = false;
|
|
951
|
-
this.resizeListener = null;
|
|
952
|
-
if (this.resizeObserver) {
|
|
953
|
-
this.resizeObserver.disconnect();
|
|
954
|
-
this.resizeObserver = null;
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
unrealCanvas() {
|
|
958
|
-
if (!this.unreal && this.parentView) {
|
|
959
|
-
const view = this.view;
|
|
960
|
-
if (view)
|
|
961
|
-
view.remove();
|
|
962
|
-
this.view = this.parentView;
|
|
963
|
-
this.unreal = true;
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
destroy() {
|
|
967
|
-
if (this.view) {
|
|
968
|
-
this.stopAutoLayout();
|
|
969
|
-
if (!this.unreal) {
|
|
970
|
-
const view = this.view;
|
|
971
|
-
if (view.parentElement)
|
|
972
|
-
view.remove();
|
|
973
|
-
}
|
|
974
|
-
super.destroy();
|
|
975
|
-
}
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
canvasPatch(CanvasRenderingContext2D.prototype);
|
|
980
|
-
canvasPatch(Path2D.prototype);
|
|
981
|
-
|
|
982
1105
|
const PointerEventHelper = {
|
|
983
1106
|
convert(e, local) {
|
|
984
1107
|
const base = InteractionHelper.getBase(e);
|
|
@@ -1025,7 +1148,7 @@ const WheelEventHelper = {
|
|
|
1025
1148
|
let { zoomMode, zoomSpeed } = config;
|
|
1026
1149
|
const delta = e.deltaY || e.deltaX;
|
|
1027
1150
|
if (zoomMode) {
|
|
1028
|
-
zoom = !e.deltaX && (Platform.intWheelDeltaY ? Math.abs(delta) > 17 : Math.ceil(delta) !== delta);
|
|
1151
|
+
zoom = (zoomMode === 'mouse') ? true : (!e.deltaX && (Platform.intWheelDeltaY ? Math.abs(delta) > 17 : Math.ceil(delta) !== delta));
|
|
1029
1152
|
if (e.shiftKey || e.metaKey || e.ctrlKey)
|
|
1030
1153
|
zoom = true;
|
|
1031
1154
|
}
|
|
@@ -1035,7 +1158,7 @@ const WheelEventHelper = {
|
|
|
1035
1158
|
if (zoom) {
|
|
1036
1159
|
zoomSpeed = MathHelper.within(zoomSpeed, 0, 1);
|
|
1037
1160
|
const min = e.deltaY ? config.delta.y : config.delta.x;
|
|
1038
|
-
scale = 1 - delta / (min *
|
|
1161
|
+
scale = 1 - delta / (min * 4) * zoomSpeed;
|
|
1039
1162
|
if (scale < 0.5)
|
|
1040
1163
|
scale = 0.5;
|
|
1041
1164
|
if (scale >= 1.5)
|
|
@@ -1062,6 +1185,7 @@ class Interaction extends InteractionBase {
|
|
|
1062
1185
|
'pointerdown': this.onPointerDown,
|
|
1063
1186
|
'mousedown': this.onMouseDown,
|
|
1064
1187
|
'touchstart': this.onTouchStart,
|
|
1188
|
+
'contextmenu': this.onContextMenu,
|
|
1065
1189
|
'wheel': this.onWheel,
|
|
1066
1190
|
'gesturestart': this.onGesturestart,
|
|
1067
1191
|
'gesturechange': this.onGesturechange,
|
|
@@ -1102,12 +1226,6 @@ class Interaction extends InteractionBase {
|
|
|
1102
1226
|
this.windowEvents = {};
|
|
1103
1227
|
}
|
|
1104
1228
|
}
|
|
1105
|
-
getLocal(p, updateClient) {
|
|
1106
|
-
if (updateClient)
|
|
1107
|
-
this.canvas.updateClientBounds();
|
|
1108
|
-
const { clientBounds } = this.canvas;
|
|
1109
|
-
return { x: p.clientX - clientBounds.x, y: p.clientY - clientBounds.y };
|
|
1110
|
-
}
|
|
1111
1229
|
getTouches(touches) {
|
|
1112
1230
|
const list = [];
|
|
1113
1231
|
for (let i = 0, len = touches.length; i < len; i++) {
|
|
@@ -1134,6 +1252,11 @@ class Interaction extends InteractionBase {
|
|
|
1134
1252
|
onKeyUp(e) {
|
|
1135
1253
|
this.keyUp(KeyEventHelper.convert(e));
|
|
1136
1254
|
}
|
|
1255
|
+
onContextMenu(e) {
|
|
1256
|
+
if (this.config.pointer.preventDefaultMenu)
|
|
1257
|
+
e.preventDefault();
|
|
1258
|
+
this.menu(PointerEventHelper.convert(e, this.getLocal(e)));
|
|
1259
|
+
}
|
|
1137
1260
|
onScroll() {
|
|
1138
1261
|
this.canvas.updateClientBounds();
|
|
1139
1262
|
}
|
|
@@ -1261,17 +1384,23 @@ class Interaction extends InteractionBase {
|
|
|
1261
1384
|
onWheel(e) {
|
|
1262
1385
|
this.preventDefaultWheel(e);
|
|
1263
1386
|
const { wheel } = this.config;
|
|
1387
|
+
if (wheel.disabled)
|
|
1388
|
+
return;
|
|
1264
1389
|
const scale = wheel.getScale ? wheel.getScale(e, wheel) : WheelEventHelper.getScale(e, wheel);
|
|
1265
1390
|
const local = this.getLocal(e);
|
|
1266
1391
|
const eventBase = InteractionHelper.getBase(e);
|
|
1267
1392
|
scale !== 1 ? this.zoom(getZoomEventData(local, scale, eventBase)) : this.move(getMoveEventData(local, wheel.getMove ? wheel.getMove(e, wheel) : WheelEventHelper.getMove(e, wheel), eventBase));
|
|
1268
1393
|
}
|
|
1269
1394
|
onGesturestart(e) {
|
|
1395
|
+
if (this.useMultiTouch)
|
|
1396
|
+
return;
|
|
1270
1397
|
this.preventDefaultWheel(e);
|
|
1271
1398
|
this.lastGestureScale = 1;
|
|
1272
1399
|
this.lastGestureRotation = 0;
|
|
1273
1400
|
}
|
|
1274
1401
|
onGesturechange(e) {
|
|
1402
|
+
if (this.useMultiTouch)
|
|
1403
|
+
return;
|
|
1275
1404
|
this.preventDefaultWheel(e);
|
|
1276
1405
|
const local = this.getLocal(e);
|
|
1277
1406
|
const eventBase = InteractionHelper.getBase(e);
|
|
@@ -1285,9 +1414,34 @@ class Interaction extends InteractionBase {
|
|
|
1285
1414
|
this.lastGestureRotation = e.rotation;
|
|
1286
1415
|
}
|
|
1287
1416
|
onGestureend(e) {
|
|
1417
|
+
if (this.useMultiTouch)
|
|
1418
|
+
return;
|
|
1288
1419
|
this.preventDefaultWheel(e);
|
|
1289
1420
|
this.transformEnd();
|
|
1290
1421
|
}
|
|
1422
|
+
setCursor(cursor) {
|
|
1423
|
+
super.setCursor(cursor);
|
|
1424
|
+
const list = [];
|
|
1425
|
+
this.eachCursor(cursor, list);
|
|
1426
|
+
if (typeof list[list.length - 1] === 'object')
|
|
1427
|
+
list.push('default');
|
|
1428
|
+
this.canvas.view.style.cursor = list.map(item => (typeof item === 'object') ? `url(${item.url}) ${item.x || 0} ${item.y || 0}` : item).join(',');
|
|
1429
|
+
}
|
|
1430
|
+
eachCursor(cursor, list, level = 0) {
|
|
1431
|
+
level++;
|
|
1432
|
+
if (cursor instanceof Array) {
|
|
1433
|
+
cursor.forEach(item => this.eachCursor(item, list, level));
|
|
1434
|
+
}
|
|
1435
|
+
else {
|
|
1436
|
+
const custom = typeof cursor === 'string' && Cursor.get(cursor);
|
|
1437
|
+
if (custom && level < 2) {
|
|
1438
|
+
this.eachCursor(custom, list, level);
|
|
1439
|
+
}
|
|
1440
|
+
else {
|
|
1441
|
+
list.push(cursor);
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1291
1445
|
destroy() {
|
|
1292
1446
|
if (this.view) {
|
|
1293
1447
|
super.destroy();
|
|
@@ -1297,219 +1451,586 @@ class Interaction extends InteractionBase {
|
|
|
1297
1451
|
}
|
|
1298
1452
|
}
|
|
1299
1453
|
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
canvas.width = width;
|
|
1312
|
-
canvas.height = height;
|
|
1313
|
-
return canvas;
|
|
1314
|
-
},
|
|
1315
|
-
canvasToDataURL: (canvas, type, quality) => canvas.toDataURL(mineType(type), quality),
|
|
1316
|
-
canvasToBolb: (canvas, type, quality) => new Promise((resolve) => canvas.toBlob(resolve, mineType(type), quality)),
|
|
1317
|
-
canvasSaveAs: (canvas, filename, quality) => {
|
|
1318
|
-
return new Promise((resolve) => {
|
|
1319
|
-
let el = document.createElement('a');
|
|
1320
|
-
el.href = canvas.toDataURL(mineType(fileType(filename)), quality);
|
|
1321
|
-
el.download = filename;
|
|
1322
|
-
document.body.appendChild(el);
|
|
1323
|
-
el.click();
|
|
1324
|
-
document.body.removeChild(el);
|
|
1325
|
-
resolve();
|
|
1326
|
-
});
|
|
1327
|
-
},
|
|
1328
|
-
loadImage(src) {
|
|
1329
|
-
return new Promise((resolve, reject) => {
|
|
1330
|
-
const img = new Image();
|
|
1331
|
-
img.setAttribute('crossOrigin', 'anonymous');
|
|
1332
|
-
img.crossOrigin = 'anonymous';
|
|
1333
|
-
img.onload = () => { resolve(img); };
|
|
1334
|
-
img.onerror = (e) => { reject(e); };
|
|
1335
|
-
if (!src.startsWith('data:') && Platform.imageSuffix)
|
|
1336
|
-
src += (src.includes("?") ? "&" : "?") + Platform.imageSuffix;
|
|
1337
|
-
img.src = src;
|
|
1454
|
+
function fillText(ui, canvas) {
|
|
1455
|
+
let row;
|
|
1456
|
+
const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
|
|
1457
|
+
for (let i = 0, len = rows.length; i < len; i++) {
|
|
1458
|
+
row = rows[i];
|
|
1459
|
+
if (row.text) {
|
|
1460
|
+
canvas.fillText(row.text, row.x, row.y);
|
|
1461
|
+
}
|
|
1462
|
+
else if (row.data) {
|
|
1463
|
+
row.data.forEach(charData => {
|
|
1464
|
+
canvas.fillText(charData.char, charData.x, row.y);
|
|
1338
1465
|
});
|
|
1339
1466
|
}
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1467
|
+
if (decorationY)
|
|
1468
|
+
canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight);
|
|
1469
|
+
}
|
|
1343
1470
|
}
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
Platform.realtimeLayout = true;
|
|
1349
|
-
const { userAgent } = navigator;
|
|
1350
|
-
if (userAgent.indexOf("Firefox") > -1) {
|
|
1351
|
-
Platform.conicGradientRotate90 = true;
|
|
1352
|
-
Platform.intWheelDeltaY = true;
|
|
1353
|
-
Platform.syncDomFont = true;
|
|
1471
|
+
|
|
1472
|
+
function fill(fill, ui, canvas) {
|
|
1473
|
+
canvas.fillStyle = fill;
|
|
1474
|
+
ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
|
|
1354
1475
|
}
|
|
1355
|
-
|
|
1356
|
-
|
|
1476
|
+
function fills(fills, ui, canvas) {
|
|
1477
|
+
let item;
|
|
1478
|
+
const { windingRule, __font } = ui.__;
|
|
1479
|
+
for (let i = 0, len = fills.length; i < len; i++) {
|
|
1480
|
+
item = fills[i];
|
|
1481
|
+
if (item.image && PaintImage.checkImage(ui, canvas, item, !__font))
|
|
1482
|
+
continue;
|
|
1483
|
+
if (item.style) {
|
|
1484
|
+
canvas.fillStyle = item.style;
|
|
1485
|
+
if (item.transform) {
|
|
1486
|
+
canvas.save();
|
|
1487
|
+
canvas.transform(item.transform);
|
|
1488
|
+
if (item.blendMode)
|
|
1489
|
+
canvas.blendMode = item.blendMode;
|
|
1490
|
+
__font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
|
|
1491
|
+
canvas.restore();
|
|
1492
|
+
}
|
|
1493
|
+
else {
|
|
1494
|
+
if (item.blendMode) {
|
|
1495
|
+
canvas.saveBlendMode(item.blendMode);
|
|
1496
|
+
__font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
|
|
1497
|
+
canvas.restoreBlendMode();
|
|
1498
|
+
}
|
|
1499
|
+
else {
|
|
1500
|
+
__font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1357
1505
|
}
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1506
|
+
|
|
1507
|
+
function strokeText(stroke, ui, canvas) {
|
|
1508
|
+
const { strokeAlign } = ui.__;
|
|
1509
|
+
const isStrokes = typeof stroke !== 'string';
|
|
1510
|
+
switch (strokeAlign) {
|
|
1511
|
+
case 'center':
|
|
1512
|
+
canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
|
|
1513
|
+
isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
|
|
1514
|
+
break;
|
|
1515
|
+
case 'inside':
|
|
1516
|
+
drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
|
|
1517
|
+
break;
|
|
1518
|
+
case 'outside':
|
|
1519
|
+
drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
|
|
1520
|
+
break;
|
|
1521
|
+
}
|
|
1361
1522
|
}
|
|
1362
|
-
|
|
1363
|
-
|
|
1523
|
+
function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
|
|
1524
|
+
const { __strokeWidth, __font } = ui.__;
|
|
1525
|
+
const out = canvas.getSameCanvas(true, true);
|
|
1526
|
+
out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__);
|
|
1527
|
+
out.font = __font;
|
|
1528
|
+
isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
|
|
1529
|
+
out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
|
|
1530
|
+
fillText(ui, out);
|
|
1531
|
+
out.blendMode = 'normal';
|
|
1532
|
+
if (ui.__worldFlipped) {
|
|
1533
|
+
canvas.copyWorldByReset(out, ui.__nowWorld);
|
|
1534
|
+
}
|
|
1535
|
+
else {
|
|
1536
|
+
canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
|
|
1537
|
+
}
|
|
1538
|
+
out.recycle(ui.__nowWorld);
|
|
1364
1539
|
}
|
|
1365
|
-
|
|
1366
|
-
|
|
1540
|
+
function drawTextStroke(ui, canvas) {
|
|
1541
|
+
let row;
|
|
1542
|
+
const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
|
|
1543
|
+
for (let i = 0, len = rows.length; i < len; i++) {
|
|
1544
|
+
row = rows[i];
|
|
1545
|
+
if (row.text) {
|
|
1546
|
+
canvas.strokeText(row.text, row.x, row.y);
|
|
1547
|
+
}
|
|
1548
|
+
else if (row.data) {
|
|
1549
|
+
row.data.forEach(charData => {
|
|
1550
|
+
canvas.strokeText(charData.char, charData.x, row.y);
|
|
1551
|
+
});
|
|
1552
|
+
}
|
|
1553
|
+
if (decorationY)
|
|
1554
|
+
canvas.strokeRect(row.x, row.y + decorationY, row.width, decorationHeight);
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
function drawStrokesStyle(strokes, isText, ui, canvas) {
|
|
1558
|
+
let item;
|
|
1559
|
+
for (let i = 0, len = strokes.length; i < len; i++) {
|
|
1560
|
+
item = strokes[i];
|
|
1561
|
+
if (item.image && PaintImage.checkImage(ui, canvas, item, false))
|
|
1562
|
+
continue;
|
|
1563
|
+
if (item.style) {
|
|
1564
|
+
canvas.strokeStyle = item.style;
|
|
1565
|
+
if (item.blendMode) {
|
|
1566
|
+
canvas.saveBlendMode(item.blendMode);
|
|
1567
|
+
isText ? drawTextStroke(ui, canvas) : canvas.stroke();
|
|
1568
|
+
canvas.restoreBlendMode();
|
|
1569
|
+
}
|
|
1570
|
+
else {
|
|
1571
|
+
isText ? drawTextStroke(ui, canvas) : canvas.stroke();
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
function stroke(stroke, ui, canvas) {
|
|
1578
|
+
const options = ui.__;
|
|
1579
|
+
const { __strokeWidth, strokeAlign, __font } = options;
|
|
1580
|
+
if (!__strokeWidth)
|
|
1581
|
+
return;
|
|
1582
|
+
if (__font) {
|
|
1583
|
+
strokeText(stroke, ui, canvas);
|
|
1584
|
+
}
|
|
1585
|
+
else {
|
|
1586
|
+
switch (strokeAlign) {
|
|
1587
|
+
case 'center':
|
|
1588
|
+
canvas.setStroke(stroke, __strokeWidth, options);
|
|
1589
|
+
canvas.stroke();
|
|
1590
|
+
break;
|
|
1591
|
+
case 'inside':
|
|
1592
|
+
canvas.save();
|
|
1593
|
+
canvas.setStroke(stroke, __strokeWidth * 2, options);
|
|
1594
|
+
options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
|
|
1595
|
+
canvas.stroke();
|
|
1596
|
+
canvas.restore();
|
|
1597
|
+
break;
|
|
1598
|
+
case 'outside':
|
|
1599
|
+
const out = canvas.getSameCanvas(true, true);
|
|
1600
|
+
out.setStroke(stroke, __strokeWidth * 2, options);
|
|
1601
|
+
ui.__drawRenderPath(out);
|
|
1602
|
+
out.stroke();
|
|
1603
|
+
options.windingRule ? out.clip(options.windingRule) : out.clip();
|
|
1604
|
+
out.clearWorld(ui.__layout.renderBounds);
|
|
1605
|
+
if (ui.__worldFlipped) {
|
|
1606
|
+
canvas.copyWorldByReset(out, ui.__nowWorld);
|
|
1607
|
+
}
|
|
1608
|
+
else {
|
|
1609
|
+
canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
|
|
1610
|
+
}
|
|
1611
|
+
out.recycle(ui.__nowWorld);
|
|
1612
|
+
break;
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
function strokes(strokes, ui, canvas) {
|
|
1617
|
+
const options = ui.__;
|
|
1618
|
+
const { __strokeWidth, strokeAlign, __font } = options;
|
|
1619
|
+
if (!__strokeWidth)
|
|
1620
|
+
return;
|
|
1621
|
+
if (__font) {
|
|
1622
|
+
strokeText(strokes, ui, canvas);
|
|
1623
|
+
}
|
|
1624
|
+
else {
|
|
1625
|
+
switch (strokeAlign) {
|
|
1626
|
+
case 'center':
|
|
1627
|
+
canvas.setStroke(undefined, __strokeWidth, options);
|
|
1628
|
+
drawStrokesStyle(strokes, false, ui, canvas);
|
|
1629
|
+
break;
|
|
1630
|
+
case 'inside':
|
|
1631
|
+
canvas.save();
|
|
1632
|
+
canvas.setStroke(undefined, __strokeWidth * 2, options);
|
|
1633
|
+
options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
|
|
1634
|
+
drawStrokesStyle(strokes, false, ui, canvas);
|
|
1635
|
+
canvas.restore();
|
|
1636
|
+
break;
|
|
1637
|
+
case 'outside':
|
|
1638
|
+
const { renderBounds } = ui.__layout;
|
|
1639
|
+
const out = canvas.getSameCanvas(true, true);
|
|
1640
|
+
ui.__drawRenderPath(out);
|
|
1641
|
+
out.setStroke(undefined, __strokeWidth * 2, options);
|
|
1642
|
+
drawStrokesStyle(strokes, false, ui, out);
|
|
1643
|
+
options.windingRule ? out.clip(options.windingRule) : out.clip();
|
|
1644
|
+
out.clearWorld(renderBounds);
|
|
1645
|
+
if (ui.__worldFlipped) {
|
|
1646
|
+
canvas.copyWorldByReset(out, ui.__nowWorld);
|
|
1647
|
+
}
|
|
1648
|
+
else {
|
|
1649
|
+
canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
|
|
1650
|
+
}
|
|
1651
|
+
out.recycle(ui.__nowWorld);
|
|
1652
|
+
break;
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1367
1655
|
}
|
|
1368
1656
|
|
|
1369
|
-
const {
|
|
1370
|
-
function
|
|
1371
|
-
const
|
|
1372
|
-
const
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1657
|
+
const { getSpread, getOuterOf, getByMove, getIntersectData } = BoundsHelper;
|
|
1658
|
+
function shape(ui, current, options) {
|
|
1659
|
+
const canvas = current.getSameCanvas();
|
|
1660
|
+
const nowWorld = ui.__nowWorld;
|
|
1661
|
+
let bounds, fitMatrix, shapeBounds, worldCanvas;
|
|
1662
|
+
let { scaleX, scaleY } = nowWorld;
|
|
1663
|
+
if (scaleX < 0)
|
|
1664
|
+
scaleX = -scaleX;
|
|
1665
|
+
if (scaleY < 0)
|
|
1666
|
+
scaleY = -scaleY;
|
|
1667
|
+
if (current.bounds.includes(nowWorld)) {
|
|
1668
|
+
worldCanvas = canvas;
|
|
1669
|
+
bounds = shapeBounds = nowWorld;
|
|
1670
|
+
}
|
|
1671
|
+
else {
|
|
1672
|
+
const { renderShapeSpread: spread } = ui.__layout;
|
|
1673
|
+
const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, scaleX === scaleY ? spread * scaleX : [spread * scaleY, spread * scaleX]) : current.bounds, nowWorld);
|
|
1674
|
+
fitMatrix = current.bounds.getFitMatrix(worldClipBounds);
|
|
1675
|
+
let { a: fitScaleX, d: fitScaleY } = fitMatrix;
|
|
1676
|
+
if (fitMatrix.a < 1) {
|
|
1677
|
+
worldCanvas = current.getSameCanvas();
|
|
1678
|
+
ui.__renderShape(worldCanvas, options);
|
|
1679
|
+
scaleX *= fitScaleX;
|
|
1680
|
+
scaleY *= fitScaleY;
|
|
1681
|
+
}
|
|
1682
|
+
shapeBounds = getOuterOf(nowWorld, fitMatrix);
|
|
1683
|
+
bounds = getByMove(shapeBounds, -fitMatrix.e, -fitMatrix.f);
|
|
1684
|
+
if (options.matrix) {
|
|
1685
|
+
const { matrix } = options;
|
|
1686
|
+
fitMatrix.multiply(matrix);
|
|
1687
|
+
fitScaleX *= matrix.scaleX;
|
|
1688
|
+
fitScaleY *= matrix.scaleY;
|
|
1689
|
+
}
|
|
1690
|
+
options = Object.assign(Object.assign({}, options), { matrix: fitMatrix.withScale(fitScaleX, fitScaleY) });
|
|
1691
|
+
}
|
|
1692
|
+
ui.__renderShape(canvas, options);
|
|
1693
|
+
return {
|
|
1694
|
+
canvas, matrix: fitMatrix, bounds,
|
|
1695
|
+
worldCanvas, shapeBounds, scaleX, scaleY
|
|
1696
|
+
};
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
let recycleMap;
|
|
1700
|
+
function compute(attrName, ui) {
|
|
1701
|
+
const data = ui.__, leafPaints = [];
|
|
1702
|
+
let paints = data.__input[attrName], hasOpacityPixel;
|
|
1703
|
+
if (!(paints instanceof Array))
|
|
1704
|
+
paints = [paints];
|
|
1705
|
+
recycleMap = PaintImage.recycleImage(attrName, data);
|
|
1706
|
+
for (let i = 0, len = paints.length, item; i < len; i++) {
|
|
1707
|
+
item = getLeafPaint(attrName, paints[i], ui);
|
|
1708
|
+
if (item)
|
|
1709
|
+
leafPaints.push(item);
|
|
1710
|
+
}
|
|
1711
|
+
data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
|
|
1712
|
+
if (leafPaints.length && leafPaints[0].image)
|
|
1713
|
+
hasOpacityPixel = leafPaints[0].image.hasOpacityPixel;
|
|
1714
|
+
if (attrName === 'fill') {
|
|
1715
|
+
data.__pixelFill = hasOpacityPixel;
|
|
1716
|
+
}
|
|
1717
|
+
else {
|
|
1718
|
+
data.__pixelStroke = hasOpacityPixel;
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
function getLeafPaint(attrName, paint, ui) {
|
|
1722
|
+
if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
|
|
1723
|
+
return undefined;
|
|
1724
|
+
const { boxBounds } = ui.__layout;
|
|
1725
|
+
switch (paint.type) {
|
|
1726
|
+
case 'solid':
|
|
1727
|
+
let { type, blendMode, color, opacity } = paint;
|
|
1728
|
+
return { type, blendMode, style: ColorConvert.string(color, opacity) };
|
|
1729
|
+
case 'image':
|
|
1730
|
+
return PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
|
|
1731
|
+
case 'linear':
|
|
1732
|
+
return PaintGradient.linearGradient(paint, boxBounds);
|
|
1733
|
+
case 'radial':
|
|
1734
|
+
return PaintGradient.radialGradient(paint, boxBounds);
|
|
1735
|
+
case 'angular':
|
|
1736
|
+
return PaintGradient.conicGradient(paint, boxBounds);
|
|
1737
|
+
default:
|
|
1738
|
+
return paint.r !== undefined ? { type: 'solid', style: ColorConvert.string(paint) } : undefined;
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
const PaintModule = {
|
|
1743
|
+
compute,
|
|
1744
|
+
fill,
|
|
1745
|
+
fills,
|
|
1746
|
+
fillText,
|
|
1747
|
+
stroke,
|
|
1748
|
+
strokes,
|
|
1749
|
+
strokeText,
|
|
1750
|
+
drawTextStroke,
|
|
1751
|
+
shape
|
|
1752
|
+
};
|
|
1753
|
+
|
|
1754
|
+
let origin = {};
|
|
1755
|
+
const { get: get$3, rotateOfOuter: rotateOfOuter$1, translate: translate$1, scaleOfOuter: scaleOfOuter$1, scale: scaleHelper, rotate } = MatrixHelper;
|
|
1756
|
+
function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
|
|
1757
|
+
const transform = get$3();
|
|
1758
|
+
translate$1(transform, box.x + x, box.y + y);
|
|
1759
|
+
scaleHelper(transform, scaleX, scaleY);
|
|
1380
1760
|
if (rotation)
|
|
1381
|
-
rotateOfOuter$
|
|
1382
|
-
data.scaleX = data.scaleY = scale;
|
|
1761
|
+
rotateOfOuter$1(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
|
|
1383
1762
|
data.transform = transform;
|
|
1384
1763
|
}
|
|
1385
|
-
function clipMode(data, box,
|
|
1386
|
-
const transform = get$
|
|
1387
|
-
translate$1(transform, box.x, box.y);
|
|
1388
|
-
if (
|
|
1389
|
-
|
|
1390
|
-
if (scale) {
|
|
1391
|
-
typeof scale === 'number' ? scaleHelper$1(transform, scale) : scaleHelper$1(transform, scale.x, scale.y);
|
|
1392
|
-
data.scaleX = transform.a;
|
|
1393
|
-
data.scaleY = transform.d;
|
|
1394
|
-
}
|
|
1764
|
+
function clipMode(data, box, x, y, scaleX, scaleY, rotation) {
|
|
1765
|
+
const transform = get$3();
|
|
1766
|
+
translate$1(transform, box.x + x, box.y + y);
|
|
1767
|
+
if (scaleX)
|
|
1768
|
+
scaleHelper(transform, scaleX, scaleY);
|
|
1395
1769
|
if (rotation)
|
|
1396
1770
|
rotate(transform, rotation);
|
|
1397
1771
|
data.transform = transform;
|
|
1398
1772
|
}
|
|
1399
|
-
function repeatMode(data, box, width, height,
|
|
1400
|
-
const transform = get$
|
|
1773
|
+
function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align) {
|
|
1774
|
+
const transform = get$3();
|
|
1401
1775
|
if (rotation) {
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1776
|
+
if (align === 'center') {
|
|
1777
|
+
rotateOfOuter$1(transform, { x: width / 2, y: height / 2 }, rotation);
|
|
1778
|
+
}
|
|
1779
|
+
else {
|
|
1780
|
+
rotate(transform, rotation);
|
|
1781
|
+
switch (rotation) {
|
|
1782
|
+
case 90:
|
|
1783
|
+
translate$1(transform, height, 0);
|
|
1784
|
+
break;
|
|
1785
|
+
case 180:
|
|
1786
|
+
translate$1(transform, width, height);
|
|
1787
|
+
break;
|
|
1788
|
+
case 270:
|
|
1789
|
+
translate$1(transform, 0, width);
|
|
1790
|
+
break;
|
|
1791
|
+
}
|
|
1413
1792
|
}
|
|
1414
1793
|
}
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1794
|
+
origin.x = box.x + x;
|
|
1795
|
+
origin.y = box.y + y;
|
|
1796
|
+
translate$1(transform, origin.x, origin.y);
|
|
1797
|
+
if (scaleX)
|
|
1798
|
+
scaleOfOuter$1(transform, origin, scaleX, scaleY);
|
|
1420
1799
|
data.transform = transform;
|
|
1421
1800
|
}
|
|
1422
1801
|
|
|
1423
|
-
const { get: get$
|
|
1802
|
+
const { get: get$2, translate } = MatrixHelper;
|
|
1803
|
+
const tempBox = new Bounds();
|
|
1804
|
+
const tempPoint = {};
|
|
1424
1805
|
function createData(leafPaint, image, paint, box) {
|
|
1425
|
-
|
|
1426
|
-
const { opacity, mode, offset, scale, rotation, blendMode } = paint;
|
|
1427
|
-
const sameBox = box.width === width && box.height === height;
|
|
1806
|
+
const { blendMode } = paint;
|
|
1428
1807
|
if (blendMode)
|
|
1429
1808
|
leafPaint.blendMode = blendMode;
|
|
1430
|
-
|
|
1809
|
+
leafPaint.data = getPatternData(paint, box, image);
|
|
1810
|
+
}
|
|
1811
|
+
function getPatternData(paint, box, image) {
|
|
1812
|
+
let { width, height } = image;
|
|
1813
|
+
if (paint.padding)
|
|
1814
|
+
box = tempBox.set(box).shrink(paint.padding);
|
|
1815
|
+
const { opacity, mode, align, offset, scale, size, rotation, repeat } = paint;
|
|
1816
|
+
const sameBox = box.width === width && box.height === height;
|
|
1817
|
+
const data = { mode };
|
|
1818
|
+
const swapSize = align !== 'center' && (rotation || 0) % 180 === 90;
|
|
1819
|
+
const swapWidth = swapSize ? height : width, swapHeight = swapSize ? width : height;
|
|
1820
|
+
let x = 0, y = 0, scaleX, scaleY;
|
|
1821
|
+
if (!mode || mode === 'cover' || mode === 'fit') {
|
|
1822
|
+
if (!sameBox || rotation) {
|
|
1823
|
+
const sw = box.width / swapWidth, sh = box.height / swapHeight;
|
|
1824
|
+
scaleX = scaleY = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
|
|
1825
|
+
x += (box.width - width * scaleX) / 2, y += (box.height - height * scaleY) / 2;
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
else if (size) {
|
|
1829
|
+
scaleX = (typeof size === 'number' ? size : size.width) / width;
|
|
1830
|
+
scaleY = (typeof size === 'number' ? size : size.height) / height;
|
|
1831
|
+
}
|
|
1832
|
+
else if (scale) {
|
|
1833
|
+
scaleX = typeof scale === 'number' ? scale : scale.x;
|
|
1834
|
+
scaleY = typeof scale === 'number' ? scale : scale.y;
|
|
1835
|
+
}
|
|
1836
|
+
if (align) {
|
|
1837
|
+
const imageBounds = { x, y, width: swapWidth, height: swapHeight };
|
|
1838
|
+
if (scaleX)
|
|
1839
|
+
imageBounds.width *= scaleX, imageBounds.height *= scaleY;
|
|
1840
|
+
AlignHelper.toPoint(align, imageBounds, box, tempPoint, true);
|
|
1841
|
+
x += tempPoint.x, y += tempPoint.y;
|
|
1842
|
+
}
|
|
1843
|
+
if (offset)
|
|
1844
|
+
x += offset.x, y += offset.y;
|
|
1431
1845
|
switch (mode) {
|
|
1432
1846
|
case 'strench':
|
|
1433
1847
|
if (!sameBox)
|
|
1434
1848
|
width = box.width, height = box.height;
|
|
1435
|
-
if (box.x || box.y) {
|
|
1436
|
-
data.transform = get$3();
|
|
1437
|
-
translate(data.transform, box.x, box.y);
|
|
1438
|
-
}
|
|
1439
1849
|
break;
|
|
1850
|
+
case 'normal':
|
|
1440
1851
|
case 'clip':
|
|
1441
|
-
if (
|
|
1442
|
-
clipMode(data, box,
|
|
1852
|
+
if (x || y || scaleX || rotation)
|
|
1853
|
+
clipMode(data, box, x, y, scaleX, scaleY, rotation);
|
|
1443
1854
|
break;
|
|
1444
1855
|
case 'repeat':
|
|
1445
|
-
if (!sameBox ||
|
|
1446
|
-
repeatMode(data, box, width, height,
|
|
1856
|
+
if (!sameBox || scaleX || rotation)
|
|
1857
|
+
repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align);
|
|
1858
|
+
if (!repeat)
|
|
1859
|
+
data.repeat = 'repeat';
|
|
1447
1860
|
break;
|
|
1448
1861
|
case 'fit':
|
|
1449
1862
|
case 'cover':
|
|
1450
1863
|
default:
|
|
1451
|
-
if (
|
|
1452
|
-
fillOrFitMode(data,
|
|
1864
|
+
if (scaleX)
|
|
1865
|
+
fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation);
|
|
1866
|
+
}
|
|
1867
|
+
if (!data.transform) {
|
|
1868
|
+
if (box.x || box.y) {
|
|
1869
|
+
data.transform = get$2();
|
|
1870
|
+
translate(data.transform, box.x, box.y);
|
|
1871
|
+
}
|
|
1872
|
+
}
|
|
1873
|
+
if (scaleX && mode !== 'strench') {
|
|
1874
|
+
data.scaleX = scaleX;
|
|
1875
|
+
data.scaleY = scaleY;
|
|
1453
1876
|
}
|
|
1454
1877
|
data.width = width;
|
|
1455
1878
|
data.height = height;
|
|
1456
1879
|
if (opacity)
|
|
1457
1880
|
data.opacity = opacity;
|
|
1881
|
+
if (repeat)
|
|
1882
|
+
data.repeat = typeof repeat === 'string' ? (repeat === 'x' ? 'repeat-x' : 'repeat-y') : 'repeat';
|
|
1883
|
+
return data;
|
|
1458
1884
|
}
|
|
1459
1885
|
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1886
|
+
let cache, box = new Bounds();
|
|
1887
|
+
const { isSame } = BoundsHelper;
|
|
1888
|
+
function image(ui, attrName, paint, boxBounds, firstUse) {
|
|
1889
|
+
let leafPaint, event;
|
|
1890
|
+
const image = ImageManager.get(paint);
|
|
1891
|
+
if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
|
|
1892
|
+
leafPaint = cache.leafPaint;
|
|
1893
|
+
}
|
|
1894
|
+
else {
|
|
1895
|
+
leafPaint = { type: paint.type, image };
|
|
1896
|
+
cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
|
|
1897
|
+
}
|
|
1898
|
+
if (firstUse || image.loading)
|
|
1899
|
+
event = { image, attrName, attrValue: paint };
|
|
1464
1900
|
if (image.ready) {
|
|
1465
|
-
|
|
1466
|
-
createData(leafPaint, image, attrValue, box);
|
|
1901
|
+
checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
|
|
1467
1902
|
if (firstUse) {
|
|
1468
|
-
|
|
1469
|
-
|
|
1903
|
+
onLoad(ui, event);
|
|
1904
|
+
onLoadSuccess(ui, event);
|
|
1470
1905
|
}
|
|
1471
1906
|
}
|
|
1472
1907
|
else if (image.error) {
|
|
1473
|
-
if (firstUse)
|
|
1474
|
-
ui.
|
|
1475
|
-
event.error = image.error;
|
|
1476
|
-
emit(ImageEvent.ERROR, event);
|
|
1477
|
-
}
|
|
1908
|
+
if (firstUse)
|
|
1909
|
+
onLoadError(ui, event, image.error);
|
|
1478
1910
|
}
|
|
1479
1911
|
else {
|
|
1912
|
+
ignoreRender(ui, true);
|
|
1480
1913
|
if (firstUse)
|
|
1481
|
-
|
|
1914
|
+
onLoad(ui, event);
|
|
1482
1915
|
leafPaint.loadId = image.load(() => {
|
|
1916
|
+
ignoreRender(ui, false);
|
|
1483
1917
|
if (!ui.destroyed) {
|
|
1484
|
-
if (
|
|
1485
|
-
|
|
1918
|
+
if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
|
|
1919
|
+
if (image.hasOpacityPixel)
|
|
1920
|
+
ui.__layout.hitCanvasChanged = true;
|
|
1486
1921
|
ui.forceUpdate('surface');
|
|
1487
1922
|
}
|
|
1488
|
-
|
|
1923
|
+
onLoadSuccess(ui, event);
|
|
1489
1924
|
}
|
|
1925
|
+
leafPaint.loadId = null;
|
|
1490
1926
|
}, (error) => {
|
|
1491
|
-
ui
|
|
1492
|
-
event
|
|
1493
|
-
|
|
1927
|
+
ignoreRender(ui, false);
|
|
1928
|
+
onLoadError(ui, event, error);
|
|
1929
|
+
leafPaint.loadId = null;
|
|
1494
1930
|
});
|
|
1495
1931
|
}
|
|
1496
1932
|
return leafPaint;
|
|
1497
1933
|
}
|
|
1498
|
-
function
|
|
1934
|
+
function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
|
|
1499
1935
|
if (attrName === 'fill' && !ui.__.__naturalWidth) {
|
|
1500
|
-
const
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
if (
|
|
1936
|
+
const data = ui.__;
|
|
1937
|
+
data.__naturalWidth = image.width / data.pixelRatio;
|
|
1938
|
+
data.__naturalHeight = image.height / data.pixelRatio;
|
|
1939
|
+
if (data.__autoSide) {
|
|
1504
1940
|
ui.forceUpdate('width');
|
|
1941
|
+
if (ui.__proxyData) {
|
|
1942
|
+
ui.setProxyAttr('width', data.width);
|
|
1943
|
+
ui.setProxyAttr('height', data.height);
|
|
1944
|
+
}
|
|
1505
1945
|
return false;
|
|
1506
1946
|
}
|
|
1507
1947
|
}
|
|
1948
|
+
if (!leafPaint.data)
|
|
1949
|
+
createData(leafPaint, image, paint, boxBounds);
|
|
1508
1950
|
return true;
|
|
1509
1951
|
}
|
|
1510
|
-
function
|
|
1511
|
-
|
|
1512
|
-
|
|
1952
|
+
function onLoad(ui, event) {
|
|
1953
|
+
emit(ui, ImageEvent.LOAD, event);
|
|
1954
|
+
}
|
|
1955
|
+
function onLoadSuccess(ui, event) {
|
|
1956
|
+
emit(ui, ImageEvent.LOADED, event);
|
|
1957
|
+
}
|
|
1958
|
+
function onLoadError(ui, event, error) {
|
|
1959
|
+
event.error = error;
|
|
1960
|
+
ui.forceUpdate('surface');
|
|
1961
|
+
emit(ui, ImageEvent.ERROR, event);
|
|
1962
|
+
}
|
|
1963
|
+
function emit(ui, type, data) {
|
|
1964
|
+
if (ui.hasEvent(type))
|
|
1965
|
+
ui.emitEvent(new ImageEvent(type, data));
|
|
1966
|
+
}
|
|
1967
|
+
function ignoreRender(ui, value) {
|
|
1968
|
+
const { leafer } = ui;
|
|
1969
|
+
if (leafer && leafer.viewReady)
|
|
1970
|
+
leafer.renderer.ignore = value;
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1973
|
+
const { get: get$1, scale, copy: copy$1 } = MatrixHelper;
|
|
1974
|
+
const { ceil, abs: abs$1 } = Math;
|
|
1975
|
+
function createPattern(ui, paint, pixelRatio) {
|
|
1976
|
+
let { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
|
|
1977
|
+
const id = scaleX + '-' + scaleY;
|
|
1978
|
+
if (paint.patternId !== id && !ui.destroyed) {
|
|
1979
|
+
scaleX = abs$1(scaleX);
|
|
1980
|
+
scaleY = abs$1(scaleY);
|
|
1981
|
+
const { image, data } = paint;
|
|
1982
|
+
let imageScale, imageMatrix, { width, height, scaleX: sx, scaleY: sy, opacity, transform, repeat } = data;
|
|
1983
|
+
if (sx) {
|
|
1984
|
+
imageMatrix = get$1();
|
|
1985
|
+
copy$1(imageMatrix, transform);
|
|
1986
|
+
scale(imageMatrix, 1 / sx, 1 / sy);
|
|
1987
|
+
scaleX *= sx;
|
|
1988
|
+
scaleY *= sy;
|
|
1989
|
+
}
|
|
1990
|
+
scaleX *= pixelRatio;
|
|
1991
|
+
scaleY *= pixelRatio;
|
|
1992
|
+
width *= scaleX;
|
|
1993
|
+
height *= scaleY;
|
|
1994
|
+
const size = width * height;
|
|
1995
|
+
if (!repeat) {
|
|
1996
|
+
if (size > Platform.image.maxCacheSize)
|
|
1997
|
+
return false;
|
|
1998
|
+
}
|
|
1999
|
+
let maxSize = Platform.image.maxPatternSize;
|
|
2000
|
+
if (!image.isSVG) {
|
|
2001
|
+
const imageSize = image.width * image.height;
|
|
2002
|
+
if (maxSize > imageSize)
|
|
2003
|
+
maxSize = imageSize;
|
|
2004
|
+
}
|
|
2005
|
+
if (size > maxSize)
|
|
2006
|
+
imageScale = Math.sqrt(size / maxSize);
|
|
2007
|
+
if (imageScale) {
|
|
2008
|
+
scaleX /= imageScale;
|
|
2009
|
+
scaleY /= imageScale;
|
|
2010
|
+
width /= imageScale;
|
|
2011
|
+
height /= imageScale;
|
|
2012
|
+
}
|
|
2013
|
+
if (sx) {
|
|
2014
|
+
scaleX /= sx;
|
|
2015
|
+
scaleY /= sy;
|
|
2016
|
+
}
|
|
2017
|
+
if (transform || scaleX !== 1 || scaleY !== 1) {
|
|
2018
|
+
if (!imageMatrix) {
|
|
2019
|
+
imageMatrix = get$1();
|
|
2020
|
+
if (transform)
|
|
2021
|
+
copy$1(imageMatrix, transform);
|
|
2022
|
+
}
|
|
2023
|
+
scale(imageMatrix, 1 / scaleX, 1 / scaleY);
|
|
2024
|
+
}
|
|
2025
|
+
const canvas = image.getCanvas(ceil(width) || 1, ceil(height) || 1, opacity);
|
|
2026
|
+
const pattern = image.getPattern(canvas, repeat || (Platform.origin.noRepeat || 'no-repeat'), imageMatrix, paint);
|
|
2027
|
+
paint.style = pattern;
|
|
2028
|
+
paint.patternId = id;
|
|
2029
|
+
return true;
|
|
2030
|
+
}
|
|
2031
|
+
else {
|
|
2032
|
+
return false;
|
|
2033
|
+
}
|
|
1513
2034
|
}
|
|
1514
2035
|
|
|
1515
2036
|
/******************************************************************************
|
|
@@ -1544,80 +2065,24 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
1544
2065
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
1545
2066
|
};
|
|
1546
2067
|
|
|
1547
|
-
const {
|
|
1548
|
-
function createPattern(ui, paint, pixelRatio) {
|
|
1549
|
-
let { scaleX, scaleY } = ui.__world;
|
|
1550
|
-
const id = scaleX + '-' + scaleY;
|
|
1551
|
-
if (paint.patternId !== id && !ui.destroyed) {
|
|
1552
|
-
paint.patternId = id;
|
|
1553
|
-
scaleX = Math.abs(scaleX);
|
|
1554
|
-
scaleY = Math.abs(scaleY);
|
|
1555
|
-
const { image, data } = paint;
|
|
1556
|
-
const maxWidth = image.isSVG ? 4096 : Math.min(image.width, 4096);
|
|
1557
|
-
const maxHeight = image.isSVG ? 4096 : Math.min(image.height, 4096);
|
|
1558
|
-
let scale, matrix, { width, height, scaleX: sx, scaleY: sy, opacity, transform, mode } = data;
|
|
1559
|
-
if (sx) {
|
|
1560
|
-
matrix = get$2();
|
|
1561
|
-
copy$1(matrix, transform);
|
|
1562
|
-
scaleHelper(matrix, 1 / sx, 1 / sy);
|
|
1563
|
-
scaleX *= sx;
|
|
1564
|
-
scaleY *= sy;
|
|
1565
|
-
}
|
|
1566
|
-
scaleX *= pixelRatio;
|
|
1567
|
-
scaleY *= pixelRatio;
|
|
1568
|
-
width *= scaleX;
|
|
1569
|
-
height *= scaleY;
|
|
1570
|
-
if (width > maxWidth || height > maxHeight) {
|
|
1571
|
-
scale = Math.max(width / maxWidth, height / maxHeight);
|
|
1572
|
-
}
|
|
1573
|
-
if (scale) {
|
|
1574
|
-
scaleX /= scale;
|
|
1575
|
-
scaleY /= scale;
|
|
1576
|
-
width /= scale;
|
|
1577
|
-
height /= scale;
|
|
1578
|
-
}
|
|
1579
|
-
if (sx) {
|
|
1580
|
-
scaleX /= sx;
|
|
1581
|
-
scaleY /= sy;
|
|
1582
|
-
}
|
|
1583
|
-
if (transform || scaleX !== 1 || scaleY !== 1) {
|
|
1584
|
-
if (!matrix) {
|
|
1585
|
-
matrix = get$2();
|
|
1586
|
-
if (transform)
|
|
1587
|
-
copy$1(matrix, transform);
|
|
1588
|
-
}
|
|
1589
|
-
scaleHelper(matrix, 1 / scaleX, 1 / scaleY);
|
|
1590
|
-
}
|
|
1591
|
-
const style = Platform.canvas.createPattern(image.getCanvas(width < 1 ? 1 : width, height < 1 ? 1 : height, opacity), mode === 'repeat' ? 'repeat' : (Platform.origin.noRepeat || 'no-repeat'));
|
|
1592
|
-
try {
|
|
1593
|
-
if (paint.transform)
|
|
1594
|
-
paint.transform = null;
|
|
1595
|
-
if (matrix)
|
|
1596
|
-
style.setTransform ? style.setTransform(matrix) : paint.transform = matrix;
|
|
1597
|
-
}
|
|
1598
|
-
catch (_a) {
|
|
1599
|
-
paint.transform = matrix;
|
|
1600
|
-
}
|
|
1601
|
-
paint.style = style;
|
|
1602
|
-
return true;
|
|
1603
|
-
}
|
|
1604
|
-
else {
|
|
1605
|
-
return false;
|
|
1606
|
-
}
|
|
1607
|
-
}
|
|
1608
|
-
|
|
2068
|
+
const { abs } = Math;
|
|
1609
2069
|
function checkImage(ui, canvas, paint, allowPaint) {
|
|
1610
|
-
const { scaleX, scaleY } = ui.__world;
|
|
2070
|
+
const { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
|
|
1611
2071
|
if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
|
|
1612
2072
|
return false;
|
|
1613
2073
|
}
|
|
1614
2074
|
else {
|
|
2075
|
+
const { data } = paint;
|
|
1615
2076
|
if (allowPaint) {
|
|
1616
|
-
if (
|
|
1617
|
-
let { width, height } =
|
|
1618
|
-
width *= scaleX * canvas.pixelRatio;
|
|
1619
|
-
height *= scaleY * canvas.pixelRatio;
|
|
1620
|
-
|
|
2077
|
+
if (!data.repeat) {
|
|
2078
|
+
let { width, height } = data;
|
|
2079
|
+
width *= abs(scaleX) * canvas.pixelRatio;
|
|
2080
|
+
height *= abs(scaleY) * canvas.pixelRatio;
|
|
2081
|
+
if (data.scaleX) {
|
|
2082
|
+
width *= data.scaleX;
|
|
2083
|
+
height *= data.scaleY;
|
|
2084
|
+
}
|
|
2085
|
+
allowPaint = (width * height > Platform.image.maxCacheSize) || Export.running;
|
|
1621
2086
|
}
|
|
1622
2087
|
else {
|
|
1623
2088
|
allowPaint = false;
|
|
@@ -1626,7 +2091,6 @@ function checkImage(ui, canvas, paint, allowPaint) {
|
|
|
1626
2091
|
if (allowPaint) {
|
|
1627
2092
|
canvas.save();
|
|
1628
2093
|
canvas.clip();
|
|
1629
|
-
const { data } = paint;
|
|
1630
2094
|
if (paint.blendMode)
|
|
1631
2095
|
canvas.blendMode = paint.blendMode;
|
|
1632
2096
|
if (data.opacity)
|
|
@@ -1635,290 +2099,74 @@ function checkImage(ui, canvas, paint, allowPaint) {
|
|
|
1635
2099
|
canvas.transform(data.transform);
|
|
1636
2100
|
canvas.drawImage(paint.image.view, 0, 0, data.width, data.height);
|
|
1637
2101
|
canvas.restore();
|
|
1638
|
-
return true;
|
|
1639
|
-
}
|
|
1640
|
-
else {
|
|
1641
|
-
if (!paint.style) {
|
|
1642
|
-
createPattern(ui, paint, canvas.pixelRatio);
|
|
1643
|
-
}
|
|
1644
|
-
else {
|
|
1645
|
-
ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
|
|
1646
|
-
if (canvas.bounds.hit(ui.__world) && createPattern(ui, paint, canvas.pixelRatio))
|
|
1647
|
-
ui.forceUpdate('surface');
|
|
1648
|
-
}), 300);
|
|
1649
|
-
}
|
|
1650
|
-
return false;
|
|
1651
|
-
}
|
|
1652
|
-
}
|
|
1653
|
-
}
|
|
1654
|
-
|
|
1655
|
-
function recycleImage(data, attrName) {
|
|
1656
|
-
const paints = (attrName === 'fill' ? data._fill : data._stroke);
|
|
1657
|
-
if (paints instanceof Array) {
|
|
1658
|
-
let image, recycleMap, input, url;
|
|
1659
|
-
for (let i = 0, len = paints.length; i < len; i++) {
|
|
1660
|
-
image = paints[i].image;
|
|
1661
|
-
url = image && image.url;
|
|
1662
|
-
if (url) {
|
|
1663
|
-
if (!recycleMap)
|
|
1664
|
-
recycleMap = {};
|
|
1665
|
-
recycleMap[url] = true;
|
|
1666
|
-
ImageManager.recycle(image);
|
|
1667
|
-
if (image.loading) {
|
|
1668
|
-
if (!input) {
|
|
1669
|
-
input = (data.__input && data.__input[attrName]) || [];
|
|
1670
|
-
if (!(input instanceof Array))
|
|
1671
|
-
input = [input];
|
|
1672
|
-
}
|
|
1673
|
-
image.unload(paints[i].loadId, !input.some((item) => item.url === url));
|
|
1674
|
-
}
|
|
1675
|
-
}
|
|
1676
|
-
}
|
|
1677
|
-
return recycleMap;
|
|
1678
|
-
}
|
|
1679
|
-
return null;
|
|
1680
|
-
}
|
|
1681
|
-
|
|
1682
|
-
function fillText(ui, canvas) {
|
|
1683
|
-
let row;
|
|
1684
|
-
const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
|
|
1685
|
-
for (let i = 0, len = rows.length; i < len; i++) {
|
|
1686
|
-
row = rows[i];
|
|
1687
|
-
if (row.text) {
|
|
1688
|
-
canvas.fillText(row.text, row.x, row.y);
|
|
1689
|
-
}
|
|
1690
|
-
else if (row.data) {
|
|
1691
|
-
row.data.forEach(charData => {
|
|
1692
|
-
canvas.fillText(charData.char, charData.x, row.y);
|
|
1693
|
-
});
|
|
1694
|
-
}
|
|
1695
|
-
if (decorationY)
|
|
1696
|
-
canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight);
|
|
1697
|
-
}
|
|
1698
|
-
}
|
|
1699
|
-
|
|
1700
|
-
function fill(ui, canvas, fill) {
|
|
1701
|
-
canvas.fillStyle = fill;
|
|
1702
|
-
ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
|
|
1703
|
-
}
|
|
1704
|
-
function fills(ui, canvas, fills) {
|
|
1705
|
-
let item;
|
|
1706
|
-
const { windingRule, __font } = ui.__;
|
|
1707
|
-
for (let i = 0, len = fills.length; i < len; i++) {
|
|
1708
|
-
item = fills[i];
|
|
1709
|
-
if (item.image && checkImage(ui, canvas, item, !__font))
|
|
1710
|
-
continue;
|
|
1711
|
-
if (item.style) {
|
|
1712
|
-
canvas.fillStyle = item.style;
|
|
1713
|
-
if (item.transform) {
|
|
1714
|
-
canvas.save();
|
|
1715
|
-
canvas.transform(item.transform);
|
|
1716
|
-
if (item.blendMode)
|
|
1717
|
-
canvas.blendMode = item.blendMode;
|
|
1718
|
-
__font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
|
|
1719
|
-
canvas.restore();
|
|
1720
|
-
}
|
|
1721
|
-
else {
|
|
1722
|
-
if (item.blendMode) {
|
|
1723
|
-
canvas.saveBlendMode(item.blendMode);
|
|
1724
|
-
__font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
|
|
1725
|
-
canvas.restoreBlendMode();
|
|
1726
|
-
}
|
|
1727
|
-
else {
|
|
1728
|
-
__font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
|
|
1729
|
-
}
|
|
1730
|
-
}
|
|
1731
|
-
}
|
|
1732
|
-
}
|
|
1733
|
-
}
|
|
1734
|
-
|
|
1735
|
-
function strokeText(ui, canvas, stroke) {
|
|
1736
|
-
const { strokeAlign } = ui.__;
|
|
1737
|
-
const isStrokes = typeof stroke !== 'string';
|
|
1738
|
-
switch (strokeAlign) {
|
|
1739
|
-
case 'center':
|
|
1740
|
-
canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
|
|
1741
|
-
isStrokes ? drawStrokesStyle(ui, stroke, canvas, true) : drawTextStroke(ui, canvas);
|
|
1742
|
-
break;
|
|
1743
|
-
case 'inside':
|
|
1744
|
-
drawAlignStroke(ui, canvas, stroke, 'inside', isStrokes);
|
|
1745
|
-
break;
|
|
1746
|
-
case 'outside':
|
|
1747
|
-
drawAlignStroke(ui, canvas, stroke, 'outside', isStrokes);
|
|
1748
|
-
break;
|
|
1749
|
-
}
|
|
1750
|
-
}
|
|
1751
|
-
function drawAlignStroke(ui, canvas, stroke, align, isStrokes) {
|
|
1752
|
-
const { strokeWidth, __font } = ui.__;
|
|
1753
|
-
const out = canvas.getSameCanvas(true);
|
|
1754
|
-
out.setStroke(isStrokes ? undefined : stroke, strokeWidth * 2, ui.__);
|
|
1755
|
-
out.font = __font;
|
|
1756
|
-
isStrokes ? drawStrokesStyle(ui, stroke, out, true) : drawTextStroke(ui, out);
|
|
1757
|
-
out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
|
|
1758
|
-
fillText(ui, out);
|
|
1759
|
-
out.blendMode = 'normal';
|
|
1760
|
-
canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds);
|
|
1761
|
-
out.recycle();
|
|
1762
|
-
}
|
|
1763
|
-
function drawTextStroke(ui, canvas) {
|
|
1764
|
-
let row;
|
|
1765
|
-
const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
|
|
1766
|
-
for (let i = 0, len = rows.length; i < len; i++) {
|
|
1767
|
-
row = rows[i];
|
|
1768
|
-
if (row.text) {
|
|
1769
|
-
canvas.strokeText(row.text, row.x, row.y);
|
|
1770
|
-
}
|
|
1771
|
-
else if (row.data) {
|
|
1772
|
-
row.data.forEach(charData => {
|
|
1773
|
-
canvas.strokeText(charData.char, charData.x, row.y);
|
|
1774
|
-
});
|
|
2102
|
+
return true;
|
|
1775
2103
|
}
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
}
|
|
1780
|
-
function drawStrokesStyle(ui, strokes, canvas, isText) {
|
|
1781
|
-
let item;
|
|
1782
|
-
for (let i = 0, len = strokes.length; i < len; i++) {
|
|
1783
|
-
item = strokes[i];
|
|
1784
|
-
if (item.image && checkImage(ui, canvas, item, false))
|
|
1785
|
-
continue;
|
|
1786
|
-
if (item.style) {
|
|
1787
|
-
canvas.strokeStyle = item.style;
|
|
1788
|
-
if (item.blendMode) {
|
|
1789
|
-
canvas.saveBlendMode(item.blendMode);
|
|
1790
|
-
isText ? drawTextStroke(ui, canvas) : canvas.stroke();
|
|
1791
|
-
canvas.restoreBlendMode();
|
|
2104
|
+
else {
|
|
2105
|
+
if (!paint.style || Export.running) {
|
|
2106
|
+
createPattern(ui, paint, canvas.pixelRatio);
|
|
1792
2107
|
}
|
|
1793
2108
|
else {
|
|
1794
|
-
|
|
2109
|
+
if (!paint.patternTask) {
|
|
2110
|
+
paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
|
|
2111
|
+
paint.patternTask = null;
|
|
2112
|
+
if (canvas.bounds.hit(ui.__nowWorld))
|
|
2113
|
+
createPattern(ui, paint, canvas.pixelRatio);
|
|
2114
|
+
ui.forceUpdate('surface');
|
|
2115
|
+
}), 300);
|
|
2116
|
+
}
|
|
1795
2117
|
}
|
|
2118
|
+
return false;
|
|
1796
2119
|
}
|
|
1797
2120
|
}
|
|
1798
2121
|
}
|
|
1799
2122
|
|
|
1800
|
-
function
|
|
1801
|
-
const
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
case 'outside':
|
|
1822
|
-
const out = canvas.getSameCanvas(true);
|
|
1823
|
-
out.setStroke(stroke, strokeWidth * 2, ui.__);
|
|
1824
|
-
ui.__drawRenderPath(out);
|
|
1825
|
-
out.stroke();
|
|
1826
|
-
options.windingRule ? out.clip(options.windingRule) : out.clip();
|
|
1827
|
-
out.clearWorld(ui.__layout.renderBounds);
|
|
1828
|
-
canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds);
|
|
1829
|
-
out.recycle();
|
|
1830
|
-
break;
|
|
1831
|
-
}
|
|
1832
|
-
}
|
|
1833
|
-
}
|
|
1834
|
-
function strokes(ui, canvas, strokes) {
|
|
1835
|
-
const options = ui.__;
|
|
1836
|
-
const { strokeWidth, strokeAlign, __font } = options;
|
|
1837
|
-
if (!strokeWidth)
|
|
1838
|
-
return;
|
|
1839
|
-
if (__font) {
|
|
1840
|
-
strokeText(ui, canvas, strokes);
|
|
1841
|
-
}
|
|
1842
|
-
else {
|
|
1843
|
-
switch (strokeAlign) {
|
|
1844
|
-
case 'center':
|
|
1845
|
-
canvas.setStroke(undefined, strokeWidth, options);
|
|
1846
|
-
drawStrokesStyle(ui, strokes, canvas);
|
|
1847
|
-
break;
|
|
1848
|
-
case 'inside':
|
|
1849
|
-
canvas.save();
|
|
1850
|
-
canvas.setStroke(undefined, strokeWidth * 2, options);
|
|
1851
|
-
options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
|
|
1852
|
-
drawStrokesStyle(ui, strokes, canvas);
|
|
1853
|
-
canvas.restore();
|
|
1854
|
-
break;
|
|
1855
|
-
case 'outside':
|
|
1856
|
-
const { renderBounds } = ui.__layout;
|
|
1857
|
-
const out = canvas.getSameCanvas(true);
|
|
1858
|
-
ui.__drawRenderPath(out);
|
|
1859
|
-
out.setStroke(undefined, strokeWidth * 2, ui.__);
|
|
1860
|
-
drawStrokesStyle(ui, strokes, out);
|
|
1861
|
-
options.windingRule ? out.clip(options.windingRule) : out.clip();
|
|
1862
|
-
out.clearWorld(renderBounds);
|
|
1863
|
-
canvas.copyWorldToInner(out, ui.__world, renderBounds);
|
|
1864
|
-
out.recycle();
|
|
1865
|
-
break;
|
|
2123
|
+
function recycleImage(attrName, data) {
|
|
2124
|
+
const paints = data['_' + attrName];
|
|
2125
|
+
if (paints instanceof Array) {
|
|
2126
|
+
let image, recycleMap, input, url;
|
|
2127
|
+
for (let i = 0, len = paints.length; i < len; i++) {
|
|
2128
|
+
image = paints[i].image;
|
|
2129
|
+
url = image && image.url;
|
|
2130
|
+
if (url) {
|
|
2131
|
+
if (!recycleMap)
|
|
2132
|
+
recycleMap = {};
|
|
2133
|
+
recycleMap[url] = true;
|
|
2134
|
+
ImageManager.recycle(image);
|
|
2135
|
+
if (image.loading) {
|
|
2136
|
+
if (!input) {
|
|
2137
|
+
input = (data.__input && data.__input[attrName]) || [];
|
|
2138
|
+
if (!(input instanceof Array))
|
|
2139
|
+
input = [input];
|
|
2140
|
+
}
|
|
2141
|
+
image.unload(paints[i].loadId, !input.some((item) => item.url === url));
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
1866
2144
|
}
|
|
2145
|
+
return recycleMap;
|
|
1867
2146
|
}
|
|
2147
|
+
return null;
|
|
1868
2148
|
}
|
|
1869
2149
|
|
|
1870
|
-
const
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
if (!current.bounds.includes(__world, options.matrix)) {
|
|
1882
|
-
const { renderShapeSpread: spread } = ui.__layout;
|
|
1883
|
-
const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, spread * scaleX, spread * scaleY) : current.bounds, __world, options.matrix);
|
|
1884
|
-
matrix = current.bounds.getFitMatrix(worldClipBounds);
|
|
1885
|
-
if (matrix.a < 1) {
|
|
1886
|
-
worldCanvas = current.getSameCanvas();
|
|
1887
|
-
ui.__renderShape(worldCanvas, options);
|
|
1888
|
-
scaleX *= matrix.a;
|
|
1889
|
-
scaleY *= matrix.d;
|
|
1890
|
-
}
|
|
1891
|
-
shapeBounds = getOuterOf(__world, matrix);
|
|
1892
|
-
bounds = getByMove(shapeBounds, -matrix.e, -matrix.f);
|
|
1893
|
-
if (options.matrix)
|
|
1894
|
-
matrix.multiply(options.matrix);
|
|
1895
|
-
options = Object.assign(Object.assign({}, options), { matrix });
|
|
1896
|
-
}
|
|
1897
|
-
else {
|
|
1898
|
-
if (options.matrix) {
|
|
1899
|
-
scaleX *= options.matrix.a;
|
|
1900
|
-
scaleY *= options.matrix.d;
|
|
1901
|
-
bounds = shapeBounds = getOuterOf(__world, options.matrix);
|
|
1902
|
-
}
|
|
1903
|
-
else {
|
|
1904
|
-
bounds = shapeBounds = __world;
|
|
1905
|
-
}
|
|
1906
|
-
worldCanvas = canvas;
|
|
1907
|
-
}
|
|
1908
|
-
ui.__renderShape(canvas, options);
|
|
1909
|
-
return {
|
|
1910
|
-
canvas, matrix, bounds,
|
|
1911
|
-
worldCanvas, shapeBounds, scaleX, scaleY
|
|
1912
|
-
};
|
|
1913
|
-
}
|
|
2150
|
+
const PaintImageModule = {
|
|
2151
|
+
image,
|
|
2152
|
+
checkImage,
|
|
2153
|
+
createPattern,
|
|
2154
|
+
recycleImage,
|
|
2155
|
+
createData,
|
|
2156
|
+
getPatternData,
|
|
2157
|
+
fillOrFitMode,
|
|
2158
|
+
clipMode,
|
|
2159
|
+
repeatMode
|
|
2160
|
+
};
|
|
1914
2161
|
|
|
1915
|
-
const
|
|
1916
|
-
const
|
|
2162
|
+
const { toPoint: toPoint$2 } = AroundHelper;
|
|
2163
|
+
const realFrom$2 = {};
|
|
2164
|
+
const realTo$2 = {};
|
|
1917
2165
|
function linearGradient(paint, box) {
|
|
1918
2166
|
let { from, to, type, blendMode, opacity } = paint;
|
|
1919
|
-
from ||
|
|
1920
|
-
to ||
|
|
1921
|
-
const style = Platform.canvas.createLinearGradient(
|
|
2167
|
+
toPoint$2(from || 'top', box, realFrom$2);
|
|
2168
|
+
toPoint$2(to || 'bottom', box, realTo$2);
|
|
2169
|
+
const style = Platform.canvas.createLinearGradient(realFrom$2.x, realFrom$2.y, realTo$2.x, realTo$2.y);
|
|
1922
2170
|
applyStops(style, paint.stops, opacity);
|
|
1923
2171
|
const data = { type, style };
|
|
1924
2172
|
if (blendMode)
|
|
@@ -1929,124 +2177,84 @@ function applyStops(gradient, stops, opacity) {
|
|
|
1929
2177
|
let stop;
|
|
1930
2178
|
for (let i = 0, len = stops.length; i < len; i++) {
|
|
1931
2179
|
stop = stops[i];
|
|
1932
|
-
|
|
2180
|
+
if (typeof stop === 'string') {
|
|
2181
|
+
gradient.addColorStop(i / (len - 1), ColorConvert.string(stop, opacity));
|
|
2182
|
+
}
|
|
2183
|
+
else {
|
|
2184
|
+
gradient.addColorStop(stop.offset, ColorConvert.string(stop.color, opacity));
|
|
2185
|
+
}
|
|
1933
2186
|
}
|
|
1934
2187
|
}
|
|
1935
2188
|
|
|
1936
|
-
const {
|
|
1937
|
-
const { get
|
|
1938
|
-
const
|
|
1939
|
-
const defaultTo$1 = { x: 0.5, y: 1 };
|
|
2189
|
+
const { getAngle, getDistance: getDistance$1 } = PointHelper;
|
|
2190
|
+
const { get, rotateOfOuter, scaleOfOuter } = MatrixHelper;
|
|
2191
|
+
const { toPoint: toPoint$1 } = AroundHelper;
|
|
1940
2192
|
const realFrom$1 = {};
|
|
1941
2193
|
const realTo$1 = {};
|
|
1942
2194
|
function radialGradient(paint, box) {
|
|
1943
2195
|
let { from, to, type, opacity, blendMode, stretch } = paint;
|
|
1944
|
-
from ||
|
|
1945
|
-
to ||
|
|
1946
|
-
const { x, y, width, height } = box;
|
|
1947
|
-
set$1(realFrom$1, x + from.x * width, y + from.y * height);
|
|
1948
|
-
set$1(realTo$1, x + to.x * width, y + to.y * height);
|
|
1949
|
-
let transform;
|
|
1950
|
-
if (width !== height || stretch) {
|
|
1951
|
-
transform = get$1();
|
|
1952
|
-
scaleOfOuter$1(transform, realFrom$1, width / height * (stretch || 1), 1);
|
|
1953
|
-
rotateOfOuter$1(transform, realFrom$1, getAngle$1(realFrom$1, realTo$1) + 90);
|
|
1954
|
-
}
|
|
2196
|
+
toPoint$1(from || 'center', box, realFrom$1);
|
|
2197
|
+
toPoint$1(to || 'bottom', box, realTo$1);
|
|
1955
2198
|
const style = Platform.canvas.createRadialGradient(realFrom$1.x, realFrom$1.y, 0, realFrom$1.x, realFrom$1.y, getDistance$1(realFrom$1, realTo$1));
|
|
1956
2199
|
applyStops(style, paint.stops, opacity);
|
|
1957
|
-
const data = { type, style
|
|
2200
|
+
const data = { type, style };
|
|
2201
|
+
const transform = getTransform(box, realFrom$1, realTo$1, stretch, true);
|
|
2202
|
+
if (transform)
|
|
2203
|
+
data.transform = transform;
|
|
1958
2204
|
if (blendMode)
|
|
1959
2205
|
data.blendMode = blendMode;
|
|
1960
2206
|
return data;
|
|
1961
2207
|
}
|
|
2208
|
+
function getTransform(box, from, to, stretch, rotate90) {
|
|
2209
|
+
let transform;
|
|
2210
|
+
const { width, height } = box;
|
|
2211
|
+
if (width !== height || stretch) {
|
|
2212
|
+
const angle = getAngle(from, to);
|
|
2213
|
+
transform = get();
|
|
2214
|
+
if (rotate90) {
|
|
2215
|
+
scaleOfOuter(transform, from, width / height * (stretch || 1), 1);
|
|
2216
|
+
rotateOfOuter(transform, from, angle + 90);
|
|
2217
|
+
}
|
|
2218
|
+
else {
|
|
2219
|
+
scaleOfOuter(transform, from, 1, width / height * (stretch || 1));
|
|
2220
|
+
rotateOfOuter(transform, from, angle);
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
return transform;
|
|
2224
|
+
}
|
|
1962
2225
|
|
|
1963
|
-
const {
|
|
1964
|
-
const {
|
|
1965
|
-
const defaultFrom = { x: 0.5, y: 0.5 };
|
|
1966
|
-
const defaultTo = { x: 0.5, y: 1 };
|
|
2226
|
+
const { getDistance } = PointHelper;
|
|
2227
|
+
const { toPoint } = AroundHelper;
|
|
1967
2228
|
const realFrom = {};
|
|
1968
2229
|
const realTo = {};
|
|
1969
2230
|
function conicGradient(paint, box) {
|
|
1970
2231
|
let { from, to, type, opacity, blendMode, stretch } = paint;
|
|
1971
|
-
from ||
|
|
1972
|
-
to ||
|
|
1973
|
-
const { x, y, width, height } = box;
|
|
1974
|
-
set(realFrom, x + from.x * width, y + from.y * height);
|
|
1975
|
-
set(realTo, x + to.x * width, y + to.y * height);
|
|
1976
|
-
const transform = get();
|
|
1977
|
-
const angle = getAngle(realFrom, realTo);
|
|
1978
|
-
if (Platform.conicGradientRotate90) {
|
|
1979
|
-
scaleOfOuter(transform, realFrom, width / height * (stretch || 1), 1);
|
|
1980
|
-
rotateOfOuter(transform, realFrom, angle + 90);
|
|
1981
|
-
}
|
|
1982
|
-
else {
|
|
1983
|
-
scaleOfOuter(transform, realFrom, 1, width / height * (stretch || 1));
|
|
1984
|
-
rotateOfOuter(transform, realFrom, angle);
|
|
1985
|
-
}
|
|
2232
|
+
toPoint(from || 'center', box, realFrom);
|
|
2233
|
+
toPoint(to || 'bottom', box, realTo);
|
|
1986
2234
|
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));
|
|
1987
2235
|
applyStops(style, paint.stops, opacity);
|
|
1988
|
-
const data = { type, style
|
|
2236
|
+
const data = { type, style };
|
|
2237
|
+
const transform = getTransform(box, realFrom, realTo, stretch || 1, Platform.conicGradientRotate90);
|
|
2238
|
+
if (transform)
|
|
2239
|
+
data.transform = transform;
|
|
1989
2240
|
if (blendMode)
|
|
1990
2241
|
data.blendMode = blendMode;
|
|
1991
2242
|
return data;
|
|
1992
2243
|
}
|
|
1993
2244
|
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
paints = [paints];
|
|
2001
|
-
recycleMap = recycleImage(ui.__, attrName);
|
|
2002
|
-
for (let i = 0, len = paints.length; i < len; i++) {
|
|
2003
|
-
item = getLeafPaint(ui, paints[i], attrName);
|
|
2004
|
-
if (item)
|
|
2005
|
-
value.push(item);
|
|
2006
|
-
}
|
|
2007
|
-
ui.__['_' + attrName] = value.length ? value : undefined;
|
|
2008
|
-
}
|
|
2009
|
-
function getLeafPaint(ui, paint, attrName) {
|
|
2010
|
-
if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
|
|
2011
|
-
return undefined;
|
|
2012
|
-
const { boxBounds } = ui.__layout;
|
|
2013
|
-
switch (paint.type) {
|
|
2014
|
-
case 'solid':
|
|
2015
|
-
let { type, blendMode, color, opacity } = paint;
|
|
2016
|
-
return { type, blendMode, style: ColorConvert$1.string(color, opacity) };
|
|
2017
|
-
case 'image':
|
|
2018
|
-
return image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
|
|
2019
|
-
case 'linear':
|
|
2020
|
-
return linearGradient(paint, boxBounds);
|
|
2021
|
-
case 'radial':
|
|
2022
|
-
return radialGradient(paint, boxBounds);
|
|
2023
|
-
case 'angular':
|
|
2024
|
-
return conicGradient(paint, boxBounds);
|
|
2025
|
-
default:
|
|
2026
|
-
return paint.r ? { type: 'solid', style: ColorConvert$1.string(paint) } : undefined;
|
|
2027
|
-
}
|
|
2028
|
-
}
|
|
2029
|
-
|
|
2030
|
-
var UIPaint = /*#__PURE__*/Object.freeze({
|
|
2031
|
-
__proto__: null,
|
|
2032
|
-
compute: compute,
|
|
2033
|
-
drawTextStroke: drawTextStroke,
|
|
2034
|
-
fill: fill,
|
|
2035
|
-
fillText: fillText,
|
|
2036
|
-
fills: fills,
|
|
2037
|
-
recycleImage: recycleImage,
|
|
2038
|
-
shape: shape,
|
|
2039
|
-
stroke: stroke,
|
|
2040
|
-
strokeText: strokeText,
|
|
2041
|
-
strokes: strokes
|
|
2042
|
-
});
|
|
2245
|
+
const PaintGradientModule = {
|
|
2246
|
+
linearGradient,
|
|
2247
|
+
radialGradient,
|
|
2248
|
+
conicGradient,
|
|
2249
|
+
getTransform
|
|
2250
|
+
};
|
|
2043
2251
|
|
|
2044
2252
|
const { copy, toOffsetOutBounds: toOffsetOutBounds$1 } = BoundsHelper;
|
|
2045
2253
|
const tempBounds = {};
|
|
2046
2254
|
const offsetOutBounds$1 = {};
|
|
2047
|
-
function shadow(ui, current, shape
|
|
2255
|
+
function shadow(ui, current, shape) {
|
|
2048
2256
|
let copyBounds, spreadScale;
|
|
2049
|
-
const {
|
|
2257
|
+
const { __nowWorld: nowWorld, __layout } = ui;
|
|
2050
2258
|
const { shadow } = ui.__;
|
|
2051
2259
|
const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
|
|
2052
2260
|
const other = current.getSameCanvas();
|
|
@@ -2061,21 +2269,21 @@ function shadow(ui, current, shape, _options) {
|
|
|
2061
2269
|
other.restore();
|
|
2062
2270
|
other.save();
|
|
2063
2271
|
if (worldCanvas) {
|
|
2064
|
-
other.copyWorld(other, bounds,
|
|
2065
|
-
copyBounds =
|
|
2272
|
+
other.copyWorld(other, bounds, nowWorld, 'copy');
|
|
2273
|
+
copyBounds = nowWorld;
|
|
2066
2274
|
}
|
|
2067
|
-
worldCanvas ? other.copyWorld(worldCanvas,
|
|
2275
|
+
worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
|
|
2068
2276
|
}
|
|
2069
|
-
if (ui.
|
|
2070
|
-
current.copyWorldByReset(other, copyBounds,
|
|
2277
|
+
if (ui.__worldFlipped) {
|
|
2278
|
+
current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
|
|
2071
2279
|
}
|
|
2072
2280
|
else {
|
|
2073
2281
|
current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
|
|
2074
2282
|
}
|
|
2075
2283
|
if (end && index < end)
|
|
2076
|
-
other.
|
|
2284
|
+
other.clearWorld(copyBounds, true);
|
|
2077
2285
|
});
|
|
2078
|
-
other.recycle();
|
|
2286
|
+
other.recycle(copyBounds);
|
|
2079
2287
|
}
|
|
2080
2288
|
function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
|
|
2081
2289
|
const { bounds, shapeBounds } = shape;
|
|
@@ -2106,9 +2314,9 @@ function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
|
|
|
2106
2314
|
|
|
2107
2315
|
const { toOffsetOutBounds } = BoundsHelper;
|
|
2108
2316
|
const offsetOutBounds = {};
|
|
2109
|
-
function innerShadow(ui, current, shape
|
|
2317
|
+
function innerShadow(ui, current, shape) {
|
|
2110
2318
|
let copyBounds, spreadScale;
|
|
2111
|
-
const {
|
|
2319
|
+
const { __nowWorld: nowWorld, __layout: __layout } = ui;
|
|
2112
2320
|
const { innerShadow } = ui.__;
|
|
2113
2321
|
const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
|
|
2114
2322
|
const other = current.getSameCanvas();
|
|
@@ -2121,40 +2329,115 @@ function innerShadow(ui, current, shape, _options) {
|
|
|
2121
2329
|
drawWorldShadow(other, offsetOutBounds, spreadScale, shape);
|
|
2122
2330
|
other.restore();
|
|
2123
2331
|
if (worldCanvas) {
|
|
2124
|
-
other.copyWorld(other, bounds,
|
|
2125
|
-
other.copyWorld(worldCanvas,
|
|
2126
|
-
copyBounds =
|
|
2332
|
+
other.copyWorld(other, bounds, nowWorld, 'copy');
|
|
2333
|
+
other.copyWorld(worldCanvas, nowWorld, nowWorld, 'source-out');
|
|
2334
|
+
copyBounds = nowWorld;
|
|
2127
2335
|
}
|
|
2128
2336
|
else {
|
|
2129
2337
|
other.copyWorld(shape.canvas, shapeBounds, bounds, 'source-out');
|
|
2130
2338
|
copyBounds = bounds;
|
|
2131
2339
|
}
|
|
2132
2340
|
other.fillWorld(copyBounds, item.color, 'source-in');
|
|
2133
|
-
if (ui.
|
|
2134
|
-
current.copyWorldByReset(other, copyBounds,
|
|
2341
|
+
if (ui.__worldFlipped) {
|
|
2342
|
+
current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
|
|
2135
2343
|
}
|
|
2136
2344
|
else {
|
|
2137
2345
|
current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
|
|
2138
2346
|
}
|
|
2139
2347
|
if (end && index < end)
|
|
2140
|
-
other.
|
|
2348
|
+
other.clearWorld(copyBounds, true);
|
|
2141
2349
|
});
|
|
2142
|
-
other.recycle();
|
|
2350
|
+
other.recycle(copyBounds);
|
|
2143
2351
|
}
|
|
2144
2352
|
|
|
2145
2353
|
function blur(ui, current, origin) {
|
|
2146
2354
|
const { blur } = ui.__;
|
|
2147
|
-
origin.setWorldBlur(blur * ui.
|
|
2148
|
-
origin.copyWorldToInner(current, ui.
|
|
2355
|
+
origin.setWorldBlur(blur * ui.__nowWorld.a);
|
|
2356
|
+
origin.copyWorldToInner(current, ui.__nowWorld, ui.__layout.renderBounds);
|
|
2149
2357
|
origin.filter = 'none';
|
|
2150
2358
|
}
|
|
2151
2359
|
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
shadow
|
|
2157
|
-
|
|
2360
|
+
function backgroundBlur(_ui, _current, _shape) {
|
|
2361
|
+
}
|
|
2362
|
+
|
|
2363
|
+
const EffectModule = {
|
|
2364
|
+
shadow,
|
|
2365
|
+
innerShadow,
|
|
2366
|
+
blur,
|
|
2367
|
+
backgroundBlur
|
|
2368
|
+
};
|
|
2369
|
+
|
|
2370
|
+
const { excludeRenderBounds } = LeafBoundsHelper;
|
|
2371
|
+
Group.prototype.__renderMask = function (canvas, options) {
|
|
2372
|
+
let child, maskCanvas, contentCanvas, maskOpacity, currentMask;
|
|
2373
|
+
const { children } = this;
|
|
2374
|
+
for (let i = 0, len = children.length; i < len; i++) {
|
|
2375
|
+
child = children[i];
|
|
2376
|
+
if (child.__.mask) {
|
|
2377
|
+
if (currentMask) {
|
|
2378
|
+
maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
|
|
2379
|
+
maskCanvas = contentCanvas = null;
|
|
2380
|
+
}
|
|
2381
|
+
if (child.__.mask === 'path') {
|
|
2382
|
+
if (child.opacity < 1) {
|
|
2383
|
+
currentMask = 'opacity-path';
|
|
2384
|
+
maskOpacity = child.opacity;
|
|
2385
|
+
if (!contentCanvas)
|
|
2386
|
+
contentCanvas = getCanvas(canvas);
|
|
2387
|
+
}
|
|
2388
|
+
else {
|
|
2389
|
+
currentMask = 'path';
|
|
2390
|
+
canvas.save();
|
|
2391
|
+
}
|
|
2392
|
+
child.__clip(contentCanvas || canvas, options);
|
|
2393
|
+
}
|
|
2394
|
+
else {
|
|
2395
|
+
currentMask = 'alpha';
|
|
2396
|
+
if (!maskCanvas)
|
|
2397
|
+
maskCanvas = getCanvas(canvas);
|
|
2398
|
+
if (!contentCanvas)
|
|
2399
|
+
contentCanvas = getCanvas(canvas);
|
|
2400
|
+
child.__render(maskCanvas, options);
|
|
2401
|
+
}
|
|
2402
|
+
if (child.__.mask !== 'clipping')
|
|
2403
|
+
continue;
|
|
2404
|
+
}
|
|
2405
|
+
if (excludeRenderBounds(child, options))
|
|
2406
|
+
continue;
|
|
2407
|
+
child.__render(contentCanvas || canvas, options);
|
|
2408
|
+
}
|
|
2409
|
+
maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
|
|
2410
|
+
};
|
|
2411
|
+
function maskEnd(leaf, maskMode, canvas, contentCanvas, maskCanvas, maskOpacity) {
|
|
2412
|
+
switch (maskMode) {
|
|
2413
|
+
case 'alpha':
|
|
2414
|
+
usePixelMask(leaf, canvas, contentCanvas, maskCanvas);
|
|
2415
|
+
break;
|
|
2416
|
+
case 'opacity-path':
|
|
2417
|
+
copyContent(leaf, canvas, contentCanvas, maskOpacity);
|
|
2418
|
+
break;
|
|
2419
|
+
case 'path':
|
|
2420
|
+
canvas.restore();
|
|
2421
|
+
}
|
|
2422
|
+
}
|
|
2423
|
+
function getCanvas(canvas) {
|
|
2424
|
+
return canvas.getSameCanvas(false, true);
|
|
2425
|
+
}
|
|
2426
|
+
function usePixelMask(leaf, canvas, content, mask) {
|
|
2427
|
+
const realBounds = leaf.__nowWorld;
|
|
2428
|
+
content.resetTransform();
|
|
2429
|
+
content.opacity = 1;
|
|
2430
|
+
content.useMask(mask, realBounds);
|
|
2431
|
+
mask.recycle(realBounds);
|
|
2432
|
+
copyContent(leaf, canvas, content, 1);
|
|
2433
|
+
}
|
|
2434
|
+
function copyContent(leaf, canvas, content, maskOpacity) {
|
|
2435
|
+
const realBounds = leaf.__nowWorld;
|
|
2436
|
+
canvas.resetTransform();
|
|
2437
|
+
canvas.opacity = maskOpacity;
|
|
2438
|
+
canvas.copyWorld(content, realBounds);
|
|
2439
|
+
content.recycle(realBounds);
|
|
2440
|
+
}
|
|
2158
2441
|
|
|
2159
2442
|
const money = '¥¥$€££¢¢';
|
|
2160
2443
|
const letter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
|
|
@@ -2279,6 +2562,8 @@ function createRows(drawData, content, style) {
|
|
|
2279
2562
|
const { width, height } = bounds;
|
|
2280
2563
|
const charMode = width || height || __letterSpacing || (textCase !== 'none');
|
|
2281
2564
|
if (charMode) {
|
|
2565
|
+
const wrap = style.textWrap !== 'none';
|
|
2566
|
+
const breakAll = style.textWrap === 'break';
|
|
2282
2567
|
paraStart = true;
|
|
2283
2568
|
lastCharType = null;
|
|
2284
2569
|
startCharSize = charWidth = charSize = wordWidth = rowWidth = 0;
|
|
@@ -2305,16 +2590,26 @@ function createRows(drawData, content, style) {
|
|
|
2305
2590
|
langBreak = (charType === Single && (lastCharType === Single || lastCharType === Letter)) || (lastCharType === Single && charType !== After);
|
|
2306
2591
|
afterBreak = ((charType === Before || charType === Single) && (lastCharType === Symbol || lastCharType === After));
|
|
2307
2592
|
realWidth = paraStart && paraIndent ? width - paraIndent : width;
|
|
2308
|
-
if (width && rowWidth + wordWidth + charWidth > realWidth) {
|
|
2309
|
-
if (
|
|
2310
|
-
afterBreak = charType === Letter && lastCharType == After;
|
|
2311
|
-
if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
|
|
2593
|
+
if (wrap && (width && rowWidth + wordWidth + charWidth > realWidth)) {
|
|
2594
|
+
if (breakAll) {
|
|
2312
2595
|
if (wordWidth)
|
|
2313
2596
|
addWord();
|
|
2314
|
-
|
|
2597
|
+
if (rowWidth)
|
|
2598
|
+
addRow();
|
|
2315
2599
|
}
|
|
2316
2600
|
else {
|
|
2317
|
-
|
|
2601
|
+
if (!afterBreak)
|
|
2602
|
+
afterBreak = charType === Letter && lastCharType == After;
|
|
2603
|
+
if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
|
|
2604
|
+
if (wordWidth)
|
|
2605
|
+
addWord();
|
|
2606
|
+
if (rowWidth)
|
|
2607
|
+
addRow();
|
|
2608
|
+
}
|
|
2609
|
+
else {
|
|
2610
|
+
if (rowWidth)
|
|
2611
|
+
addRow();
|
|
2612
|
+
}
|
|
2318
2613
|
}
|
|
2319
2614
|
}
|
|
2320
2615
|
if (char === ' ' && paraStart !== true && (rowWidth + wordWidth) === 0) ;
|
|
@@ -2384,7 +2679,7 @@ function addRow() {
|
|
|
2384
2679
|
|
|
2385
2680
|
const CharMode = 0;
|
|
2386
2681
|
const WordMode = 1;
|
|
2387
|
-
const
|
|
2682
|
+
const TextMode = 2;
|
|
2388
2683
|
function layoutChar(drawData, style, width, _height) {
|
|
2389
2684
|
const { rows } = drawData;
|
|
2390
2685
|
const { textAlign, paraIndent, letterSpacing } = style;
|
|
@@ -2393,15 +2688,12 @@ function layoutChar(drawData, style, width, _height) {
|
|
|
2393
2688
|
if (row.words) {
|
|
2394
2689
|
indentWidth = paraIndent && row.paraStart ? paraIndent : 0;
|
|
2395
2690
|
addWordWidth = (width && textAlign === 'justify' && row.words.length > 1) ? (width - row.width - indentWidth) / (row.words.length - 1) : 0;
|
|
2396
|
-
mode = (letterSpacing || row.isOverflow) ? CharMode : (addWordWidth > 0.01 ? WordMode :
|
|
2397
|
-
if (
|
|
2398
|
-
row.
|
|
2691
|
+
mode = (letterSpacing || row.isOverflow) ? CharMode : (addWordWidth > 0.01 ? WordMode : TextMode);
|
|
2692
|
+
if (row.isOverflow && !letterSpacing)
|
|
2693
|
+
row.textMode = true;
|
|
2694
|
+
if (mode === TextMode) {
|
|
2399
2695
|
row.x += indentWidth;
|
|
2400
|
-
row
|
|
2401
|
-
word.data.forEach(char => {
|
|
2402
|
-
row.text += char.char;
|
|
2403
|
-
});
|
|
2404
|
-
});
|
|
2696
|
+
toTextChar$1(row);
|
|
2405
2697
|
}
|
|
2406
2698
|
else {
|
|
2407
2699
|
row.x += indentWidth;
|
|
@@ -2411,11 +2703,11 @@ function layoutChar(drawData, style, width, _height) {
|
|
|
2411
2703
|
if (mode === WordMode) {
|
|
2412
2704
|
wordChar = { char: '', x: charX };
|
|
2413
2705
|
charX = toWordChar(word.data, charX, wordChar);
|
|
2414
|
-
if (wordChar.char !== ' ')
|
|
2706
|
+
if (row.isOverflow || wordChar.char !== ' ')
|
|
2415
2707
|
row.data.push(wordChar);
|
|
2416
2708
|
}
|
|
2417
2709
|
else {
|
|
2418
|
-
charX = toChar(word.data, charX, row.data);
|
|
2710
|
+
charX = toChar(word.data, charX, row.data, row.isOverflow);
|
|
2419
2711
|
}
|
|
2420
2712
|
if (!row.paraEnd && addWordWidth) {
|
|
2421
2713
|
charX += addWordWidth;
|
|
@@ -2427,6 +2719,14 @@ function layoutChar(drawData, style, width, _height) {
|
|
|
2427
2719
|
}
|
|
2428
2720
|
});
|
|
2429
2721
|
}
|
|
2722
|
+
function toTextChar$1(row) {
|
|
2723
|
+
row.text = '';
|
|
2724
|
+
row.words.forEach(word => {
|
|
2725
|
+
word.data.forEach(char => {
|
|
2726
|
+
row.text += char.char;
|
|
2727
|
+
});
|
|
2728
|
+
});
|
|
2729
|
+
}
|
|
2430
2730
|
function toWordChar(data, charX, wordChar) {
|
|
2431
2731
|
data.forEach(char => {
|
|
2432
2732
|
wordChar.char += char.char;
|
|
@@ -2434,9 +2734,9 @@ function toWordChar(data, charX, wordChar) {
|
|
|
2434
2734
|
});
|
|
2435
2735
|
return charX;
|
|
2436
2736
|
}
|
|
2437
|
-
function toChar(data, charX, rowData) {
|
|
2737
|
+
function toChar(data, charX, rowData, isOverflow) {
|
|
2438
2738
|
data.forEach(char => {
|
|
2439
|
-
if (char.char !== ' ') {
|
|
2739
|
+
if (isOverflow || char.char !== ' ') {
|
|
2440
2740
|
char.x = charX;
|
|
2441
2741
|
rowData.push(char);
|
|
2442
2742
|
}
|
|
@@ -2447,10 +2747,10 @@ function toChar(data, charX, rowData) {
|
|
|
2447
2747
|
|
|
2448
2748
|
function layoutText(drawData, style) {
|
|
2449
2749
|
const { rows, bounds } = drawData;
|
|
2450
|
-
const { __lineHeight, __baseLine, __letterSpacing, textAlign, verticalAlign, paraSpacing
|
|
2750
|
+
const { __lineHeight, __baseLine, __letterSpacing, __clipText, textAlign, verticalAlign, paraSpacing } = style;
|
|
2451
2751
|
let { x, y, width, height } = bounds, realHeight = __lineHeight * rows.length + (paraSpacing ? paraSpacing * (drawData.paraNumber - 1) : 0);
|
|
2452
2752
|
let starY = __baseLine;
|
|
2453
|
-
if (
|
|
2753
|
+
if (__clipText && realHeight > height) {
|
|
2454
2754
|
realHeight = Math.max(height, __lineHeight);
|
|
2455
2755
|
drawData.overflow = rows.length;
|
|
2456
2756
|
}
|
|
@@ -2468,12 +2768,14 @@ function layoutText(drawData, style) {
|
|
|
2468
2768
|
for (let i = 0, len = rows.length; i < len; i++) {
|
|
2469
2769
|
row = rows[i];
|
|
2470
2770
|
row.x = x;
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2771
|
+
if (row.width < width || (row.width > width && !__clipText)) {
|
|
2772
|
+
switch (textAlign) {
|
|
2773
|
+
case 'center':
|
|
2774
|
+
row.x += (width - row.width) / 2;
|
|
2775
|
+
break;
|
|
2776
|
+
case 'right':
|
|
2777
|
+
row.x += width - row.width;
|
|
2778
|
+
}
|
|
2477
2779
|
}
|
|
2478
2780
|
if (row.paraStart && paraSpacing && i > 0)
|
|
2479
2781
|
starY += paraSpacing;
|
|
@@ -2499,39 +2801,62 @@ function layoutText(drawData, style) {
|
|
|
2499
2801
|
bounds.x = rowX;
|
|
2500
2802
|
if (rowWidth > bounds.width)
|
|
2501
2803
|
bounds.width = rowWidth;
|
|
2804
|
+
if (__clipText && width && width < rowWidth) {
|
|
2805
|
+
row.isOverflow = true;
|
|
2806
|
+
if (!drawData.overflow)
|
|
2807
|
+
drawData.overflow = rows.length;
|
|
2808
|
+
}
|
|
2502
2809
|
}
|
|
2503
2810
|
bounds.y = y;
|
|
2504
2811
|
bounds.height = realHeight;
|
|
2505
2812
|
}
|
|
2506
2813
|
|
|
2507
|
-
function clipText(drawData,
|
|
2814
|
+
function clipText(drawData, style, x, width) {
|
|
2815
|
+
if (!width)
|
|
2816
|
+
return;
|
|
2508
2817
|
const { rows, overflow } = drawData;
|
|
2818
|
+
let { textOverflow } = style;
|
|
2509
2819
|
rows.splice(overflow);
|
|
2510
|
-
if (textOverflow !== '
|
|
2511
|
-
if (textOverflow === '
|
|
2820
|
+
if (textOverflow && textOverflow !== 'show') {
|
|
2821
|
+
if (textOverflow === 'hide')
|
|
2822
|
+
textOverflow = '';
|
|
2823
|
+
else if (textOverflow === 'ellipsis')
|
|
2512
2824
|
textOverflow = '...';
|
|
2513
|
-
|
|
2514
|
-
const
|
|
2515
|
-
let char, end = row.data.length - 1, charRight;
|
|
2516
|
-
const { x, width } = drawData.bounds;
|
|
2825
|
+
let char, charRight;
|
|
2826
|
+
const ellipsisWidth = textOverflow ? Platform.canvas.measureText(textOverflow).width : 0;
|
|
2517
2827
|
const right = x + width - ellipsisWidth;
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2828
|
+
const list = style.textWrap === 'none' ? rows : [rows[overflow - 1]];
|
|
2829
|
+
list.forEach(row => {
|
|
2830
|
+
if (row.isOverflow && row.data) {
|
|
2831
|
+
let end = row.data.length - 1;
|
|
2832
|
+
for (let i = end; i > -1; i--) {
|
|
2833
|
+
char = row.data[i];
|
|
2834
|
+
charRight = char.x + char.width;
|
|
2835
|
+
if (i === end && charRight < right) {
|
|
2836
|
+
break;
|
|
2837
|
+
}
|
|
2838
|
+
else if (charRight < right && char.char !== ' ') {
|
|
2839
|
+
row.data.splice(i + 1);
|
|
2840
|
+
row.width -= char.width;
|
|
2841
|
+
break;
|
|
2842
|
+
}
|
|
2843
|
+
row.width -= char.width;
|
|
2844
|
+
}
|
|
2845
|
+
row.width += ellipsisWidth;
|
|
2846
|
+
row.data.push({ char: textOverflow, x: charRight });
|
|
2847
|
+
if (row.textMode)
|
|
2848
|
+
toTextChar(row);
|
|
2528
2849
|
}
|
|
2529
|
-
|
|
2530
|
-
}
|
|
2531
|
-
row.width += ellipsisWidth;
|
|
2532
|
-
row.data.push({ char: textOverflow, x: charRight });
|
|
2850
|
+
});
|
|
2533
2851
|
}
|
|
2534
2852
|
}
|
|
2853
|
+
function toTextChar(row) {
|
|
2854
|
+
row.text = '';
|
|
2855
|
+
row.data.forEach(char => {
|
|
2856
|
+
row.text += char.char;
|
|
2857
|
+
});
|
|
2858
|
+
row.data = null;
|
|
2859
|
+
}
|
|
2535
2860
|
|
|
2536
2861
|
function decorationText(drawData, style) {
|
|
2537
2862
|
const { fontSize } = style;
|
|
@@ -2545,100 +2870,214 @@ function decorationText(drawData, style) {
|
|
|
2545
2870
|
}
|
|
2546
2871
|
}
|
|
2547
2872
|
|
|
2548
|
-
const
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2873
|
+
const { top, right, bottom, left } = Direction4;
|
|
2874
|
+
function getDrawData(content, style) {
|
|
2875
|
+
if (typeof content !== 'string')
|
|
2876
|
+
content = String(content);
|
|
2877
|
+
let x = 0, y = 0;
|
|
2878
|
+
let width = style.__getInput('width') || 0;
|
|
2879
|
+
let height = style.__getInput('height') || 0;
|
|
2880
|
+
const { textDecoration, __font, __padding: padding } = style;
|
|
2881
|
+
if (padding) {
|
|
2882
|
+
if (width) {
|
|
2883
|
+
x = padding[left];
|
|
2884
|
+
width -= (padding[right] + padding[left]);
|
|
2885
|
+
}
|
|
2886
|
+
if (height) {
|
|
2887
|
+
y = padding[top];
|
|
2888
|
+
height -= (padding[top] + padding[bottom]);
|
|
2889
|
+
}
|
|
2890
|
+
}
|
|
2891
|
+
const drawData = {
|
|
2892
|
+
bounds: { x, y, width, height },
|
|
2893
|
+
rows: [],
|
|
2894
|
+
paraNumber: 0,
|
|
2895
|
+
font: Platform.canvas.font = __font
|
|
2896
|
+
};
|
|
2897
|
+
createRows(drawData, content, style);
|
|
2898
|
+
if (padding)
|
|
2899
|
+
padAutoText(padding, drawData, style, width, height);
|
|
2900
|
+
layoutText(drawData, style);
|
|
2901
|
+
layoutChar(drawData, style, width);
|
|
2902
|
+
if (drawData.overflow)
|
|
2903
|
+
clipText(drawData, style, x, width);
|
|
2904
|
+
if (textDecoration !== 'none')
|
|
2905
|
+
decorationText(drawData, style);
|
|
2906
|
+
return drawData;
|
|
2907
|
+
}
|
|
2908
|
+
function padAutoText(padding, drawData, style, width, height) {
|
|
2909
|
+
if (!width) {
|
|
2910
|
+
switch (style.textAlign) {
|
|
2911
|
+
case 'left':
|
|
2912
|
+
offsetText(drawData, 'x', padding[left]);
|
|
2913
|
+
break;
|
|
2914
|
+
case 'right':
|
|
2915
|
+
offsetText(drawData, 'x', -padding[right]);
|
|
2916
|
+
}
|
|
2917
|
+
}
|
|
2918
|
+
if (!height) {
|
|
2919
|
+
switch (style.verticalAlign) {
|
|
2920
|
+
case 'top':
|
|
2921
|
+
offsetText(drawData, 'y', padding[top]);
|
|
2922
|
+
break;
|
|
2923
|
+
case 'bottom':
|
|
2924
|
+
offsetText(drawData, 'y', -padding[bottom]);
|
|
2566
2925
|
}
|
|
2567
|
-
const drawData = {
|
|
2568
|
-
bounds: { x, y, width, height },
|
|
2569
|
-
rows: [],
|
|
2570
|
-
paraNumber: 0,
|
|
2571
|
-
font: Platform.canvas.font = __font
|
|
2572
|
-
};
|
|
2573
|
-
createRows(drawData, content, style);
|
|
2574
|
-
layoutText(drawData, style);
|
|
2575
|
-
layoutChar(drawData, style, width);
|
|
2576
|
-
if (drawData.overflow)
|
|
2577
|
-
clipText(drawData, textOverflow);
|
|
2578
|
-
if (textDecoration !== 'none')
|
|
2579
|
-
decorationText(drawData, style);
|
|
2580
|
-
return drawData;
|
|
2581
2926
|
}
|
|
2927
|
+
}
|
|
2928
|
+
function offsetText(drawData, attrName, value) {
|
|
2929
|
+
const { bounds, rows } = drawData;
|
|
2930
|
+
bounds[attrName] += value;
|
|
2931
|
+
for (let i = 0; i < rows.length; i++)
|
|
2932
|
+
rows[i][attrName] += value;
|
|
2933
|
+
}
|
|
2934
|
+
|
|
2935
|
+
const TextConvertModule = {
|
|
2936
|
+
getDrawData
|
|
2582
2937
|
};
|
|
2583
2938
|
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2939
|
+
function string(color, opacity) {
|
|
2940
|
+
if (typeof color === 'string')
|
|
2941
|
+
return color;
|
|
2942
|
+
let a = color.a === undefined ? 1 : color.a;
|
|
2943
|
+
if (opacity)
|
|
2944
|
+
a *= opacity;
|
|
2945
|
+
const rgb = color.r + ',' + color.g + ',' + color.b;
|
|
2946
|
+
return a === 1 ? 'rgb(' + rgb + ')' : 'rgba(' + rgb + ',' + a + ')';
|
|
2947
|
+
}
|
|
2948
|
+
|
|
2949
|
+
const ColorConvertModule = {
|
|
2950
|
+
string
|
|
2594
2951
|
};
|
|
2595
2952
|
|
|
2596
|
-
const
|
|
2953
|
+
const { setPoint, addPoint, toBounds } = TwoPointBoundsHelper;
|
|
2954
|
+
function getTrimBounds(canvas) {
|
|
2955
|
+
const { width, height } = canvas.view;
|
|
2956
|
+
const { data } = canvas.context.getImageData(0, 0, width, height);
|
|
2957
|
+
let x, y, pointBounds, index = 0;
|
|
2958
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
2959
|
+
if (data[i + 3] !== 0) {
|
|
2960
|
+
x = index % width;
|
|
2961
|
+
y = (index - x) / width;
|
|
2962
|
+
pointBounds ? addPoint(pointBounds, x, y) : setPoint(pointBounds = {}, x, y);
|
|
2963
|
+
}
|
|
2964
|
+
index++;
|
|
2965
|
+
}
|
|
2966
|
+
const bounds = new Bounds();
|
|
2967
|
+
toBounds(pointBounds, bounds);
|
|
2968
|
+
return bounds.scale(1 / canvas.pixelRatio).ceil();
|
|
2969
|
+
}
|
|
2970
|
+
|
|
2971
|
+
const ExportModule = {
|
|
2597
2972
|
export(leaf, filename, options) {
|
|
2973
|
+
this.running = true;
|
|
2974
|
+
const fileType = FileHelper.fileType(filename);
|
|
2975
|
+
options = FileHelper.getExportOptions(options);
|
|
2598
2976
|
return addTask((success) => new Promise((resolve) => {
|
|
2977
|
+
const over = (result) => {
|
|
2978
|
+
success(result);
|
|
2979
|
+
resolve();
|
|
2980
|
+
this.running = false;
|
|
2981
|
+
};
|
|
2982
|
+
const { toURL } = Platform;
|
|
2983
|
+
const { download } = Platform.origin;
|
|
2984
|
+
if (filename === 'json') {
|
|
2985
|
+
return over({ data: leaf.toJSON(options.json) });
|
|
2986
|
+
}
|
|
2987
|
+
else if (fileType === 'json') {
|
|
2988
|
+
download(toURL(JSON.stringify(leaf.toJSON(options.json)), 'text'), filename);
|
|
2989
|
+
return over({ data: true });
|
|
2990
|
+
}
|
|
2991
|
+
if (filename === 'svg') {
|
|
2992
|
+
return over({ data: leaf.toSVG() });
|
|
2993
|
+
}
|
|
2994
|
+
else if (fileType === 'svg') {
|
|
2995
|
+
download(toURL(leaf.toSVG(), 'svg'), filename);
|
|
2996
|
+
return over({ data: true });
|
|
2997
|
+
}
|
|
2599
2998
|
const { leafer } = leaf;
|
|
2600
2999
|
if (leafer) {
|
|
3000
|
+
checkLazy(leaf);
|
|
2601
3001
|
leafer.waitViewCompleted(() => __awaiter(this, void 0, void 0, function* () {
|
|
2602
|
-
let
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
3002
|
+
let renderBounds, trimBounds, scaleX = 1, scaleY = 1;
|
|
3003
|
+
const { worldTransform, isLeafer, isFrame } = leaf;
|
|
3004
|
+
const { slice, trim, onCanvas } = options;
|
|
3005
|
+
let scale = options.scale || 1;
|
|
3006
|
+
let pixelRatio = options.pixelRatio || 1;
|
|
3007
|
+
const smooth = options.smooth === undefined ? leafer.config.smooth : options.smooth;
|
|
3008
|
+
const contextSettings = options.contextSettings || leafer.config.contextSettings;
|
|
3009
|
+
if (leaf.isApp) {
|
|
3010
|
+
scale *= pixelRatio;
|
|
3011
|
+
pixelRatio = leaf.app.pixelRatio;
|
|
3012
|
+
}
|
|
3013
|
+
const screenshot = options.screenshot || leaf.isApp;
|
|
3014
|
+
const fill = (isLeafer && screenshot) ? (options.fill === undefined ? leaf.fill : options.fill) : options.fill;
|
|
3015
|
+
const needFill = FileHelper.isOpaqueImage(filename) || fill, matrix = new Matrix();
|
|
3016
|
+
if (screenshot) {
|
|
3017
|
+
renderBounds = screenshot === true ? (isLeafer ? leafer.canvas.bounds : leaf.worldRenderBounds) : screenshot;
|
|
2609
3018
|
}
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
3019
|
+
else {
|
|
3020
|
+
let relative = options.relative || (isLeafer ? 'inner' : 'local');
|
|
3021
|
+
scaleX = worldTransform.scaleX;
|
|
3022
|
+
scaleY = worldTransform.scaleY;
|
|
3023
|
+
switch (relative) {
|
|
3024
|
+
case 'inner':
|
|
3025
|
+
matrix.set(worldTransform);
|
|
3026
|
+
break;
|
|
3027
|
+
case 'local':
|
|
3028
|
+
matrix.set(worldTransform).divide(leaf.localTransform);
|
|
3029
|
+
scaleX /= leaf.scaleX;
|
|
3030
|
+
scaleY /= leaf.scaleY;
|
|
3031
|
+
break;
|
|
3032
|
+
case 'world':
|
|
3033
|
+
scaleX = 1;
|
|
3034
|
+
scaleY = 1;
|
|
3035
|
+
break;
|
|
3036
|
+
case 'page':
|
|
3037
|
+
relative = leaf.leafer;
|
|
3038
|
+
default:
|
|
3039
|
+
matrix.set(worldTransform).divide(leaf.getTransform(relative));
|
|
3040
|
+
const l = relative.worldTransform;
|
|
3041
|
+
scaleX /= scaleX / l.scaleX;
|
|
3042
|
+
scaleY /= scaleY / l.scaleY;
|
|
3043
|
+
}
|
|
3044
|
+
renderBounds = leaf.getBounds('render', relative);
|
|
2622
3045
|
}
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
3046
|
+
const { x, y, width, height } = new Bounds(renderBounds).scale(scale);
|
|
3047
|
+
let canvas = Creator.canvas({ width: Math.round(width), height: Math.round(height), pixelRatio, smooth, contextSettings });
|
|
3048
|
+
const renderOptions = { matrix: matrix.scale(1 / scale).invert().translate(-x, -y).withScale(1 / scaleX * scale, 1 / scaleY * scale) };
|
|
3049
|
+
if (slice) {
|
|
3050
|
+
leaf = leafer;
|
|
3051
|
+
renderOptions.bounds = canvas.bounds;
|
|
2626
3052
|
}
|
|
2627
|
-
|
|
2628
|
-
|
|
3053
|
+
canvas.save();
|
|
3054
|
+
if (isFrame && fill !== undefined) {
|
|
3055
|
+
const oldFill = leaf.get('fill');
|
|
3056
|
+
leaf.fill = '';
|
|
3057
|
+
leaf.__render(canvas, renderOptions);
|
|
3058
|
+
leaf.fill = oldFill;
|
|
2629
3059
|
}
|
|
2630
3060
|
else {
|
|
2631
|
-
|
|
3061
|
+
leaf.__render(canvas, renderOptions);
|
|
2632
3062
|
}
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
canvas
|
|
3063
|
+
canvas.restore();
|
|
3064
|
+
if (trim) {
|
|
3065
|
+
trimBounds = getTrimBounds(canvas);
|
|
3066
|
+
const old = canvas, { width, height } = trimBounds;
|
|
3067
|
+
const config = { x: 0, y: 0, width, height, pixelRatio };
|
|
3068
|
+
canvas = Creator.canvas(config);
|
|
3069
|
+
canvas.copyWorld(old, trimBounds, config);
|
|
3070
|
+
}
|
|
3071
|
+
if (needFill)
|
|
3072
|
+
canvas.fillWorld(canvas.bounds, fill || '#FFFFFF', 'destination-over');
|
|
3073
|
+
if (onCanvas)
|
|
3074
|
+
onCanvas(canvas);
|
|
3075
|
+
const data = filename === 'canvas' ? canvas : yield canvas.export(filename, options);
|
|
3076
|
+
over({ data, width: canvas.pixelWidth, height: canvas.pixelHeight, renderBounds, trimBounds });
|
|
2637
3077
|
}));
|
|
2638
3078
|
}
|
|
2639
3079
|
else {
|
|
2640
|
-
|
|
2641
|
-
resolve();
|
|
3080
|
+
over({ data: false });
|
|
2642
3081
|
}
|
|
2643
3082
|
}));
|
|
2644
3083
|
}
|
|
@@ -2651,13 +3090,64 @@ function addTask(task) {
|
|
|
2651
3090
|
tasker.add(() => __awaiter(this, void 0, void 0, function* () { return yield task(resolve); }), { parallel: false });
|
|
2652
3091
|
});
|
|
2653
3092
|
}
|
|
3093
|
+
function checkLazy(leaf) {
|
|
3094
|
+
if (leaf.__.__needComputePaint)
|
|
3095
|
+
leaf.__.__computePaint();
|
|
3096
|
+
if (leaf.isBranch)
|
|
3097
|
+
leaf.children.forEach(child => checkLazy(child));
|
|
3098
|
+
}
|
|
3099
|
+
|
|
3100
|
+
const canvas = LeaferCanvasBase.prototype;
|
|
3101
|
+
const debug = Debug.get('@leafer-ui/export');
|
|
3102
|
+
canvas.export = function (filename, options) {
|
|
3103
|
+
const { quality, blob } = FileHelper.getExportOptions(options);
|
|
3104
|
+
if (filename.includes('.')) {
|
|
3105
|
+
return this.saveAs(filename, quality);
|
|
3106
|
+
}
|
|
3107
|
+
else if (blob) {
|
|
3108
|
+
return this.toBlob(filename, quality);
|
|
3109
|
+
}
|
|
3110
|
+
else {
|
|
3111
|
+
return this.toDataURL(filename, quality);
|
|
3112
|
+
}
|
|
3113
|
+
};
|
|
3114
|
+
canvas.toBlob = function (type, quality) {
|
|
3115
|
+
return new Promise((resolve) => {
|
|
3116
|
+
Platform.origin.canvasToBolb(this.view, type, quality).then((blob) => {
|
|
3117
|
+
resolve(blob);
|
|
3118
|
+
}).catch((e) => {
|
|
3119
|
+
debug.error(e);
|
|
3120
|
+
resolve(null);
|
|
3121
|
+
});
|
|
3122
|
+
});
|
|
3123
|
+
};
|
|
3124
|
+
canvas.toDataURL = function (type, quality) {
|
|
3125
|
+
return Platform.origin.canvasToDataURL(this.view, type, quality);
|
|
3126
|
+
};
|
|
3127
|
+
canvas.saveAs = function (filename, quality) {
|
|
3128
|
+
return new Promise((resolve) => {
|
|
3129
|
+
Platform.origin.canvasSaveAs(this.view, filename, quality).then(() => {
|
|
3130
|
+
resolve(true);
|
|
3131
|
+
}).catch((e) => {
|
|
3132
|
+
debug.error(e);
|
|
3133
|
+
resolve(false);
|
|
3134
|
+
});
|
|
3135
|
+
});
|
|
3136
|
+
};
|
|
2654
3137
|
|
|
2655
|
-
Object.assign(
|
|
2656
|
-
Object.assign(
|
|
2657
|
-
Object.assign(
|
|
2658
|
-
Object.assign(
|
|
2659
|
-
Object.assign(
|
|
3138
|
+
Object.assign(TextConvert, TextConvertModule);
|
|
3139
|
+
Object.assign(ColorConvert, ColorConvertModule);
|
|
3140
|
+
Object.assign(Paint, PaintModule);
|
|
3141
|
+
Object.assign(PaintImage, PaintImageModule);
|
|
3142
|
+
Object.assign(PaintGradient, PaintGradientModule);
|
|
3143
|
+
Object.assign(Effect, EffectModule);
|
|
3144
|
+
Object.assign(Export, ExportModule);
|
|
2660
3145
|
|
|
3146
|
+
Object.assign(Creator, {
|
|
3147
|
+
interaction: (target, canvas, selector, options) => new Interaction(target, canvas, selector, options),
|
|
3148
|
+
hitCanvas: (options, manager) => new LeaferCanvas(options, manager),
|
|
3149
|
+
hitCanvasManager: () => new HitCanvasManager()
|
|
3150
|
+
});
|
|
2661
3151
|
useCanvas();
|
|
2662
3152
|
|
|
2663
3153
|
export { Interaction, Layouter, LeaferCanvas, Renderer, Selector, Watcher, useCanvas };
|