leafer-ui 1.0.0-rc.2 → 1.0.0-rc.21
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 +11 -3
- package/dist/web.esm.js +1409 -1020
- package/dist/web.esm.min.js +1 -1
- package/dist/web.js +7466 -5878
- package/dist/web.min.js +1 -1
- package/dist/web.module.js +7424 -5866
- package/dist/web.module.min.js +1 -1
- package/package.json +11 -4
- package/types/index.d.ts +1 -1
package/dist/web.esm.js
CHANGED
|
@@ -1,8 +1,230 @@
|
|
|
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, ImageEvent, 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, Leafer } 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
|
+
init() {
|
|
11
|
+
const { view } = this.config;
|
|
12
|
+
view ? this.__createViewFrom(view) : this.__createView();
|
|
13
|
+
const { style } = this.view;
|
|
14
|
+
style.display || (style.display = 'block');
|
|
15
|
+
this.parentView = this.view.parentElement;
|
|
16
|
+
if (this.parentView)
|
|
17
|
+
this.parentView.style.userSelect = 'none';
|
|
18
|
+
if (Platform.syncDomFont && !this.parentView) {
|
|
19
|
+
this.view.style.display = 'none';
|
|
20
|
+
document.body.appendChild(this.view);
|
|
21
|
+
}
|
|
22
|
+
this.__createContext();
|
|
23
|
+
if (!this.autoLayout)
|
|
24
|
+
this.resize(this.config);
|
|
25
|
+
}
|
|
26
|
+
set backgroundColor(color) { this.view.style.backgroundColor = color; }
|
|
27
|
+
get backgroundColor() { return this.view.style.backgroundColor; }
|
|
28
|
+
set hittable(hittable) { this.view.style.pointerEvents = hittable ? 'auto' : 'none'; }
|
|
29
|
+
get hittable() { return this.view.style.pointerEvents !== 'none'; }
|
|
30
|
+
__createView() {
|
|
31
|
+
this.view = document.createElement('canvas');
|
|
32
|
+
}
|
|
33
|
+
__createViewFrom(inputView) {
|
|
34
|
+
let find = (typeof inputView === 'string') ? document.getElementById(inputView) : inputView;
|
|
35
|
+
if (find) {
|
|
36
|
+
if (find instanceof HTMLCanvasElement) {
|
|
37
|
+
this.view = find;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
let parent = find;
|
|
41
|
+
if (find === window || find === document) {
|
|
42
|
+
const div = document.createElement('div');
|
|
43
|
+
const { style } = div;
|
|
44
|
+
style.position = 'absolute';
|
|
45
|
+
style.top = style.bottom = style.left = style.right = '0px';
|
|
46
|
+
document.body.appendChild(div);
|
|
47
|
+
parent = div;
|
|
48
|
+
}
|
|
49
|
+
this.__createView();
|
|
50
|
+
const view = this.view;
|
|
51
|
+
if (parent.hasChildNodes()) {
|
|
52
|
+
const { style } = view;
|
|
53
|
+
style.position = 'absolute';
|
|
54
|
+
style.top = style.left = '0px';
|
|
55
|
+
parent.style.position || (parent.style.position = 'relative');
|
|
56
|
+
}
|
|
57
|
+
parent.appendChild(view);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
debug$3.error(`no id: ${inputView}`);
|
|
62
|
+
this.__createView();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
updateViewSize() {
|
|
66
|
+
const { width, height, pixelRatio } = this;
|
|
67
|
+
const { style } = this.view;
|
|
68
|
+
style.width = width + 'px';
|
|
69
|
+
style.height = height + 'px';
|
|
70
|
+
this.view.width = Math.ceil(width * pixelRatio);
|
|
71
|
+
this.view.height = Math.ceil(height * pixelRatio);
|
|
72
|
+
}
|
|
73
|
+
updateClientBounds() {
|
|
74
|
+
this.clientBounds = this.view.getBoundingClientRect();
|
|
75
|
+
}
|
|
76
|
+
startAutoLayout(autoBounds, listener) {
|
|
77
|
+
this.autoBounds = autoBounds;
|
|
78
|
+
this.resizeListener = listener;
|
|
79
|
+
try {
|
|
80
|
+
this.resizeObserver = new ResizeObserver((entries) => {
|
|
81
|
+
this.updateClientBounds();
|
|
82
|
+
for (const entry of entries)
|
|
83
|
+
this.checkAutoBounds(entry.contentRect);
|
|
84
|
+
});
|
|
85
|
+
const parent = this.parentView;
|
|
86
|
+
if (parent) {
|
|
87
|
+
this.resizeObserver.observe(parent);
|
|
88
|
+
this.checkAutoBounds(parent.getBoundingClientRect());
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (_a) {
|
|
92
|
+
this.imitateResizeObserver();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
imitateResizeObserver() {
|
|
96
|
+
if (this.autoLayout) {
|
|
97
|
+
if (this.parentView)
|
|
98
|
+
this.checkAutoBounds(this.parentView.getBoundingClientRect());
|
|
99
|
+
Platform.requestRender(this.imitateResizeObserver.bind(this));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
checkAutoBounds(parentSize) {
|
|
103
|
+
const view = this.view;
|
|
104
|
+
const { x, y, width, height } = this.autoBounds.getBoundsFrom(parentSize);
|
|
105
|
+
if (width !== this.width || height !== this.height) {
|
|
106
|
+
const { style } = view;
|
|
107
|
+
const { pixelRatio } = this;
|
|
108
|
+
style.marginLeft = x + 'px';
|
|
109
|
+
style.marginTop = y + 'px';
|
|
110
|
+
const size = { width, height, pixelRatio };
|
|
111
|
+
const oldSize = {};
|
|
112
|
+
DataHelper.copyAttrs(oldSize, this, canvasSizeAttrs);
|
|
113
|
+
this.resize(size);
|
|
114
|
+
if (this.width !== undefined)
|
|
115
|
+
this.resizeListener(new ResizeEvent(size, oldSize));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
stopAutoLayout() {
|
|
119
|
+
this.autoLayout = false;
|
|
120
|
+
this.resizeListener = null;
|
|
121
|
+
if (this.resizeObserver) {
|
|
122
|
+
this.resizeObserver.disconnect();
|
|
123
|
+
this.resizeObserver = null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
unrealCanvas() {
|
|
127
|
+
if (!this.unreal && this.parentView) {
|
|
128
|
+
const view = this.view;
|
|
129
|
+
if (view)
|
|
130
|
+
view.remove();
|
|
131
|
+
this.view = this.parentView;
|
|
132
|
+
this.unreal = true;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
destroy() {
|
|
136
|
+
if (this.view) {
|
|
137
|
+
this.stopAutoLayout();
|
|
138
|
+
if (!this.unreal) {
|
|
139
|
+
const view = this.view;
|
|
140
|
+
if (view.parentElement)
|
|
141
|
+
view.remove();
|
|
142
|
+
}
|
|
143
|
+
super.destroy();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
canvasPatch(CanvasRenderingContext2D.prototype);
|
|
149
|
+
canvasPatch(Path2D.prototype);
|
|
150
|
+
|
|
151
|
+
const { mineType, fileType } = FileHelper;
|
|
152
|
+
Object.assign(Creator, {
|
|
153
|
+
canvas: (options, manager) => new LeaferCanvas(options, manager),
|
|
154
|
+
image: (options) => new LeaferImage(options)
|
|
155
|
+
});
|
|
156
|
+
function useCanvas(_canvasType, _power) {
|
|
157
|
+
Platform.origin = {
|
|
158
|
+
createCanvas(width, height) {
|
|
159
|
+
const canvas = document.createElement('canvas');
|
|
160
|
+
canvas.width = width;
|
|
161
|
+
canvas.height = height;
|
|
162
|
+
return canvas;
|
|
163
|
+
},
|
|
164
|
+
canvasToDataURL: (canvas, type, quality) => canvas.toDataURL(mineType(type), quality),
|
|
165
|
+
canvasToBolb: (canvas, type, quality) => new Promise((resolve) => canvas.toBlob(resolve, mineType(type), quality)),
|
|
166
|
+
canvasSaveAs: (canvas, filename, quality) => {
|
|
167
|
+
const url = canvas.toDataURL(mineType(fileType(filename)), quality);
|
|
168
|
+
return Platform.origin.download(url, filename);
|
|
169
|
+
},
|
|
170
|
+
download(url, filename) {
|
|
171
|
+
return new Promise((resolve) => {
|
|
172
|
+
let el = document.createElement('a');
|
|
173
|
+
el.href = url;
|
|
174
|
+
el.download = filename;
|
|
175
|
+
document.body.appendChild(el);
|
|
176
|
+
el.click();
|
|
177
|
+
document.body.removeChild(el);
|
|
178
|
+
resolve();
|
|
179
|
+
});
|
|
180
|
+
},
|
|
181
|
+
loadImage(src) {
|
|
182
|
+
return new Promise((resolve, reject) => {
|
|
183
|
+
const img = new Image();
|
|
184
|
+
const { suffix, crossOrigin } = Platform.image;
|
|
185
|
+
if (crossOrigin) {
|
|
186
|
+
img.setAttribute('crossOrigin', crossOrigin);
|
|
187
|
+
img.crossOrigin = crossOrigin;
|
|
188
|
+
}
|
|
189
|
+
img.onload = () => { resolve(img); };
|
|
190
|
+
img.onerror = (e) => { reject(e); };
|
|
191
|
+
if (!src.startsWith('data:') && !src.startsWith('blob:') && suffix)
|
|
192
|
+
src += (src.includes("?") ? "&" : "?") + suffix;
|
|
193
|
+
img.src = src;
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
Platform.event = {
|
|
198
|
+
stopDefault(origin) { origin.preventDefault(); },
|
|
199
|
+
stopNow(origin) { origin.stopImmediatePropagation(); },
|
|
200
|
+
stop(origin) { origin.stopPropagation(); }
|
|
201
|
+
};
|
|
202
|
+
Platform.canvas = Creator.canvas();
|
|
203
|
+
Platform.conicGradientSupport = !!Platform.canvas.context.createConicGradient;
|
|
204
|
+
}
|
|
205
|
+
Platform.name = 'web';
|
|
206
|
+
Platform.isMobile = 'ontouchstart' in window;
|
|
207
|
+
Platform.requestRender = function (render) { window.requestAnimationFrame(render); };
|
|
208
|
+
Platform.devicePixelRatio = Math.max(1, devicePixelRatio);
|
|
209
|
+
const { userAgent } = navigator;
|
|
210
|
+
if (userAgent.indexOf("Firefox") > -1) {
|
|
211
|
+
Platform.conicGradientRotate90 = true;
|
|
212
|
+
Platform.intWheelDeltaY = true;
|
|
213
|
+
Platform.syncDomFont = true;
|
|
214
|
+
}
|
|
215
|
+
else if (userAgent.indexOf("Safari") > -1 && userAgent.indexOf("Chrome") === -1) {
|
|
216
|
+
Platform.fullImageShadow = true;
|
|
217
|
+
}
|
|
218
|
+
if (userAgent.indexOf('Windows') > -1) {
|
|
219
|
+
Platform.os = 'Windows';
|
|
220
|
+
Platform.intWheelDeltaY = true;
|
|
221
|
+
}
|
|
222
|
+
else if (userAgent.indexOf('Mac') > -1) {
|
|
223
|
+
Platform.os = 'Mac';
|
|
224
|
+
}
|
|
225
|
+
else if (userAgent.indexOf('Linux') > -1) {
|
|
226
|
+
Platform.os = 'Linux';
|
|
227
|
+
}
|
|
6
228
|
|
|
7
229
|
class Watcher {
|
|
8
230
|
get childrenChanged() { return this.hasAdd || this.hasRemove || this.hasVisible; }
|
|
@@ -10,7 +232,7 @@ class Watcher {
|
|
|
10
232
|
if (this.hasRemove) {
|
|
11
233
|
const updatedList = new LeafList();
|
|
12
234
|
this.__updatedList.list.forEach(item => { if (item.leafer)
|
|
13
|
-
updatedList.
|
|
235
|
+
updatedList.add(item); });
|
|
14
236
|
return updatedList;
|
|
15
237
|
}
|
|
16
238
|
else {
|
|
@@ -45,7 +267,7 @@ class Watcher {
|
|
|
45
267
|
this.target.emit(RenderEvent.REQUEST);
|
|
46
268
|
}
|
|
47
269
|
__onAttrChange(event) {
|
|
48
|
-
this.__updatedList.
|
|
270
|
+
this.__updatedList.add(event.target);
|
|
49
271
|
this.update();
|
|
50
272
|
}
|
|
51
273
|
__onChildEvent(event) {
|
|
@@ -55,12 +277,12 @@ class Watcher {
|
|
|
55
277
|
}
|
|
56
278
|
else {
|
|
57
279
|
this.hasRemove = true;
|
|
58
|
-
this.__updatedList.
|
|
280
|
+
this.__updatedList.add(event.parent);
|
|
59
281
|
}
|
|
60
282
|
this.update();
|
|
61
283
|
}
|
|
62
284
|
__pushChild(child) {
|
|
63
|
-
this.__updatedList.
|
|
285
|
+
this.__updatedList.add(child);
|
|
64
286
|
if (child.isBranch)
|
|
65
287
|
this.__loopChildren(child);
|
|
66
288
|
}
|
|
@@ -99,22 +321,22 @@ class Watcher {
|
|
|
99
321
|
}
|
|
100
322
|
}
|
|
101
323
|
|
|
102
|
-
const {
|
|
324
|
+
const { updateAllMatrix: updateAllMatrix$1, updateBounds: updateOneBounds, updateAllWorldOpacity } = LeafHelper;
|
|
103
325
|
const { pushAllChildBranch, pushAllParent } = BranchHelper;
|
|
104
326
|
function updateMatrix(updateList, levelList) {
|
|
105
327
|
let layout;
|
|
106
328
|
updateList.list.forEach(leaf => {
|
|
107
329
|
layout = leaf.__layout;
|
|
108
|
-
if (levelList.without(leaf) && !layout.
|
|
330
|
+
if (levelList.without(leaf) && !layout.proxyZoom) {
|
|
109
331
|
if (layout.matrixChanged) {
|
|
110
|
-
|
|
111
|
-
levelList.
|
|
332
|
+
updateAllMatrix$1(leaf, true);
|
|
333
|
+
levelList.add(leaf);
|
|
112
334
|
if (leaf.isBranch)
|
|
113
335
|
pushAllChildBranch(leaf, levelList);
|
|
114
336
|
pushAllParent(leaf, levelList);
|
|
115
337
|
}
|
|
116
338
|
else if (layout.boundsChanged) {
|
|
117
|
-
levelList.
|
|
339
|
+
levelList.add(leaf);
|
|
118
340
|
if (leaf.isBranch)
|
|
119
341
|
leaf.__tempNumber = 0;
|
|
120
342
|
pushAllParent(leaf, levelList);
|
|
@@ -123,20 +345,21 @@ function updateMatrix(updateList, levelList) {
|
|
|
123
345
|
});
|
|
124
346
|
}
|
|
125
347
|
function updateBounds(boundsList) {
|
|
126
|
-
let
|
|
348
|
+
let list, branch, children;
|
|
127
349
|
boundsList.sort(true);
|
|
128
350
|
boundsList.levels.forEach(level => {
|
|
129
|
-
|
|
130
|
-
for (let i = 0, len =
|
|
131
|
-
branch =
|
|
351
|
+
list = boundsList.levelMap[level];
|
|
352
|
+
for (let i = 0, len = list.length; i < len; i++) {
|
|
353
|
+
branch = list[i];
|
|
132
354
|
if (branch.isBranch && branch.__tempNumber) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
355
|
+
children = branch.children;
|
|
356
|
+
for (let j = 0, jLen = children.length; j < jLen; j++) {
|
|
357
|
+
if (!children[j].isBranch) {
|
|
358
|
+
updateOneBounds(children[j]);
|
|
136
359
|
}
|
|
137
360
|
}
|
|
138
361
|
}
|
|
139
|
-
branch
|
|
362
|
+
updateOneBounds(branch);
|
|
140
363
|
}
|
|
141
364
|
});
|
|
142
365
|
}
|
|
@@ -149,7 +372,7 @@ function updateChange(updateList) {
|
|
|
149
372
|
}
|
|
150
373
|
|
|
151
374
|
const { worldBounds } = LeafBoundsHelper;
|
|
152
|
-
const {
|
|
375
|
+
const bigBounds = { x: 0, y: 0, width: 100000, height: 100000 };
|
|
153
376
|
class LayoutBlockData {
|
|
154
377
|
constructor(list) {
|
|
155
378
|
this.updatedBounds = new Bounds();
|
|
@@ -160,14 +383,20 @@ class LayoutBlockData {
|
|
|
160
383
|
this.updatedList = list;
|
|
161
384
|
}
|
|
162
385
|
setBefore() {
|
|
163
|
-
|
|
386
|
+
this.beforeBounds.setListWithFn(this.updatedList.list, worldBounds);
|
|
164
387
|
}
|
|
165
388
|
setAfter() {
|
|
166
|
-
|
|
167
|
-
|
|
389
|
+
const { list } = this.updatedList;
|
|
390
|
+
if (list.some(leaf => leaf.noBounds)) {
|
|
391
|
+
this.afterBounds.set(bigBounds);
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
this.afterBounds.setListWithFn(list, worldBounds);
|
|
395
|
+
}
|
|
396
|
+
this.updatedBounds.setList([this.beforeBounds, this.afterBounds]);
|
|
168
397
|
}
|
|
169
398
|
merge(data) {
|
|
170
|
-
this.updatedList.
|
|
399
|
+
this.updatedList.addList(data.updatedList.list);
|
|
171
400
|
this.beforeBounds.add(data.beforeBounds);
|
|
172
401
|
this.afterBounds.add(data.afterBounds);
|
|
173
402
|
this.updatedBounds.add(data.updatedBounds);
|
|
@@ -177,8 +406,7 @@ class LayoutBlockData {
|
|
|
177
406
|
}
|
|
178
407
|
}
|
|
179
408
|
|
|
180
|
-
const {
|
|
181
|
-
const { pushAllBranchStack, updateWorldBoundsByBranchStack } = BranchHelper;
|
|
409
|
+
const { updateAllMatrix, updateAllChange } = LeafHelper;
|
|
182
410
|
const debug$2 = Debug.get('Layouter');
|
|
183
411
|
class Layouter {
|
|
184
412
|
constructor(target, userConfig) {
|
|
@@ -255,12 +483,15 @@ class Layouter {
|
|
|
255
483
|
const { target, __updatedList: updateList } = this;
|
|
256
484
|
const { BEFORE, LAYOUT, AFTER } = LayoutEvent;
|
|
257
485
|
const blocks = this.getBlocks(updateList);
|
|
258
|
-
blocks.forEach(item =>
|
|
486
|
+
blocks.forEach(item => item.setBefore());
|
|
259
487
|
target.emitEvent(new LayoutEvent(BEFORE, blocks, this.times));
|
|
488
|
+
this.extraBlock = null;
|
|
260
489
|
updateList.sort();
|
|
261
490
|
updateMatrix(updateList, this.__levelList);
|
|
262
491
|
updateBounds(this.__levelList);
|
|
263
492
|
updateChange(updateList);
|
|
493
|
+
if (this.extraBlock)
|
|
494
|
+
blocks.push(this.extraBlock);
|
|
264
495
|
blocks.forEach(item => item.setAfter());
|
|
265
496
|
target.emitEvent(new LayoutEvent(LAYOUT, blocks, this.times));
|
|
266
497
|
target.emitEvent(new LayoutEvent(AFTER, blocks, this.times));
|
|
@@ -283,17 +514,22 @@ class Layouter {
|
|
|
283
514
|
Run.end(t);
|
|
284
515
|
}
|
|
285
516
|
static fullLayout(target) {
|
|
286
|
-
|
|
517
|
+
updateAllMatrix(target, true);
|
|
287
518
|
if (target.isBranch) {
|
|
288
|
-
|
|
289
|
-
pushAllBranchStack(target, branchStack);
|
|
290
|
-
updateWorldBoundsByBranchStack(branchStack);
|
|
519
|
+
BranchHelper.updateBounds(target);
|
|
291
520
|
}
|
|
292
521
|
else {
|
|
293
|
-
|
|
522
|
+
LeafHelper.updateBounds(target);
|
|
294
523
|
}
|
|
295
524
|
updateAllChange(target);
|
|
296
525
|
}
|
|
526
|
+
addExtra(leaf) {
|
|
527
|
+
if (!this.__updatedList.has(leaf)) {
|
|
528
|
+
const { updatedList, beforeBounds } = this.extraBlock || (this.extraBlock = new LayoutBlockData([]));
|
|
529
|
+
updatedList.length ? beforeBounds.add(leaf.__world) : beforeBounds.set(leaf.__world);
|
|
530
|
+
updatedList.add(leaf);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
297
533
|
createBlock(data) {
|
|
298
534
|
return new LayoutBlockData(data);
|
|
299
535
|
}
|
|
@@ -321,8 +557,7 @@ class Layouter {
|
|
|
321
557
|
if (this.target) {
|
|
322
558
|
this.stop();
|
|
323
559
|
this.__removeListenEvents();
|
|
324
|
-
this.target = null;
|
|
325
|
-
this.config = null;
|
|
560
|
+
this.target = this.config = null;
|
|
326
561
|
}
|
|
327
562
|
}
|
|
328
563
|
}
|
|
@@ -403,6 +638,10 @@ class Renderer {
|
|
|
403
638
|
}
|
|
404
639
|
else {
|
|
405
640
|
this.requestLayout();
|
|
641
|
+
if (this.ignore) {
|
|
642
|
+
this.ignore = this.rendering = false;
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
406
645
|
this.emitRender(RenderEvent.BEFORE);
|
|
407
646
|
if (this.config.usePartRender && this.totalTimes > 1) {
|
|
408
647
|
this.partRender();
|
|
@@ -424,8 +663,7 @@ class Renderer {
|
|
|
424
663
|
const { canvas, updateBlocks: list } = this;
|
|
425
664
|
if (!list)
|
|
426
665
|
return debug$1.warn('PartRender: need update attr');
|
|
427
|
-
|
|
428
|
-
this.mergeBlocks();
|
|
666
|
+
this.mergeBlocks();
|
|
429
667
|
list.forEach(block => { if (canvas.bounds.hit(block) && !block.isEmpty())
|
|
430
668
|
this.clipRender(block); });
|
|
431
669
|
}
|
|
@@ -434,7 +672,7 @@ class Renderer {
|
|
|
434
672
|
const { canvas } = this;
|
|
435
673
|
const bounds = block.getIntersect(canvas.bounds);
|
|
436
674
|
const includes = block.includes(this.target.__world);
|
|
437
|
-
const realBounds = new Bounds(
|
|
675
|
+
const realBounds = new Bounds(bounds);
|
|
438
676
|
canvas.save();
|
|
439
677
|
if (includes && !Debug.showRepaint) {
|
|
440
678
|
canvas.clear();
|
|
@@ -444,7 +682,7 @@ class Renderer {
|
|
|
444
682
|
canvas.clearWorld(bounds, true);
|
|
445
683
|
canvas.clipWorld(bounds, true);
|
|
446
684
|
}
|
|
447
|
-
this.__render(bounds, realBounds);
|
|
685
|
+
this.__render(bounds, includes, realBounds);
|
|
448
686
|
canvas.restore();
|
|
449
687
|
Run.end(t);
|
|
450
688
|
}
|
|
@@ -453,12 +691,12 @@ class Renderer {
|
|
|
453
691
|
const { canvas } = this;
|
|
454
692
|
canvas.save();
|
|
455
693
|
canvas.clear();
|
|
456
|
-
this.__render(canvas.bounds);
|
|
694
|
+
this.__render(canvas.bounds, true);
|
|
457
695
|
canvas.restore();
|
|
458
696
|
Run.end(t);
|
|
459
697
|
}
|
|
460
|
-
__render(bounds, realBounds) {
|
|
461
|
-
const options =
|
|
698
|
+
__render(bounds, includes, realBounds) {
|
|
699
|
+
const options = bounds.includes(this.target.__world) ? { includes } : { bounds, includes };
|
|
462
700
|
if (this.needFill)
|
|
463
701
|
this.canvas.fillWorld(bounds, this.config.fill);
|
|
464
702
|
if (Debug.showRepaint)
|
|
@@ -484,7 +722,7 @@ class Renderer {
|
|
|
484
722
|
const { updateBlocks: list } = this;
|
|
485
723
|
if (list) {
|
|
486
724
|
const bounds = new Bounds();
|
|
487
|
-
bounds.
|
|
725
|
+
bounds.setList(list);
|
|
488
726
|
list.length = 0;
|
|
489
727
|
list.push(bounds);
|
|
490
728
|
}
|
|
@@ -493,12 +731,12 @@ class Renderer {
|
|
|
493
731
|
const startTime = Date.now();
|
|
494
732
|
Platform.requestRender(() => {
|
|
495
733
|
this.FPS = Math.min(60, Math.ceil(1000 / (Date.now() - startTime)));
|
|
496
|
-
if (this.
|
|
497
|
-
|
|
734
|
+
if (this.running) {
|
|
735
|
+
this.target.emit(AnimateEvent.FRAME);
|
|
736
|
+
if (this.changed && this.canvas.view)
|
|
498
737
|
this.render();
|
|
738
|
+
this.target.emit(RenderEvent.NEXT);
|
|
499
739
|
}
|
|
500
|
-
if (this.running)
|
|
501
|
-
this.target.emit(AnimateEvent.FRAME);
|
|
502
740
|
if (this.target)
|
|
503
741
|
this.__requestRender();
|
|
504
742
|
});
|
|
@@ -511,7 +749,7 @@ class Renderer {
|
|
|
511
749
|
const bounds = new Bounds(0, 0, width, height);
|
|
512
750
|
if (!bounds.includes(this.target.__world) || this.needFill || !e.samePixelRatio) {
|
|
513
751
|
this.addBlock(this.canvas.bounds);
|
|
514
|
-
this.target.forceUpdate('
|
|
752
|
+
this.target.forceUpdate('surface');
|
|
515
753
|
}
|
|
516
754
|
}
|
|
517
755
|
}
|
|
@@ -524,7 +762,7 @@ class Renderer {
|
|
|
524
762
|
empty = (!leaf.__world.width || !leaf.__world.height);
|
|
525
763
|
if (empty) {
|
|
526
764
|
if (!leaf.isLeafer)
|
|
527
|
-
debug$1.
|
|
765
|
+
debug$1.tip(leaf.innerName, ': empty');
|
|
528
766
|
empty = (!leaf.isBranch || leaf.isBranchLeaf);
|
|
529
767
|
}
|
|
530
768
|
return empty;
|
|
@@ -551,15 +789,13 @@ class Renderer {
|
|
|
551
789
|
if (this.target) {
|
|
552
790
|
this.stop();
|
|
553
791
|
this.__removeListenEvents();
|
|
554
|
-
this.target = null;
|
|
555
|
-
this.canvas = null;
|
|
556
|
-
this.config = null;
|
|
792
|
+
this.target = this.canvas = this.config = null;
|
|
557
793
|
}
|
|
558
794
|
}
|
|
559
795
|
}
|
|
560
796
|
|
|
561
797
|
const { hitRadiusPoint } = BoundsHelper;
|
|
562
|
-
class
|
|
798
|
+
class Picker {
|
|
563
799
|
constructor(target, selector) {
|
|
564
800
|
this.target = target;
|
|
565
801
|
this.selector = selector;
|
|
@@ -571,15 +807,17 @@ class FindPath {
|
|
|
571
807
|
options = {};
|
|
572
808
|
const through = options.through || false;
|
|
573
809
|
const ignoreHittable = options.ignoreHittable || false;
|
|
810
|
+
const target = options.target || this.target;
|
|
574
811
|
this.exclude = options.exclude || null;
|
|
575
812
|
this.point = { x: hitPoint.x, y: hitPoint.y, radiusX: hitRadius, radiusY: hitRadius };
|
|
576
|
-
this.findList = [];
|
|
577
|
-
|
|
813
|
+
this.findList = options.findList || [];
|
|
814
|
+
if (!options.findList)
|
|
815
|
+
this.eachFind(target.children, target.__onlyHitMask);
|
|
578
816
|
const list = this.findList;
|
|
579
817
|
const leaf = this.getBestMatchLeaf();
|
|
580
818
|
const path = ignoreHittable ? this.getPath(leaf) : this.getHitablePath(leaf);
|
|
581
819
|
this.clear();
|
|
582
|
-
return through ? { path, leaf, throughPath: list.length ? this.getThroughPath(list) : path } : { path, leaf };
|
|
820
|
+
return through ? { path, target: leaf, throughPath: list.length ? this.getThroughPath(list) : path } : { path, target: leaf };
|
|
583
821
|
}
|
|
584
822
|
getBestMatchLeaf() {
|
|
585
823
|
const { findList: targets } = this;
|
|
@@ -602,20 +840,20 @@ class FindPath {
|
|
|
602
840
|
getPath(leaf) {
|
|
603
841
|
const path = new LeafList();
|
|
604
842
|
while (leaf) {
|
|
605
|
-
path.
|
|
843
|
+
path.add(leaf);
|
|
606
844
|
leaf = leaf.parent;
|
|
607
845
|
}
|
|
608
|
-
path.
|
|
846
|
+
path.add(this.target);
|
|
609
847
|
return path;
|
|
610
848
|
}
|
|
611
849
|
getHitablePath(leaf) {
|
|
612
|
-
const path = this.getPath(leaf);
|
|
850
|
+
const path = this.getPath(leaf && leaf.hittable ? leaf : null);
|
|
613
851
|
let item, hittablePath = new LeafList();
|
|
614
852
|
for (let i = path.list.length - 1; i > -1; i--) {
|
|
615
853
|
item = path.list[i];
|
|
616
854
|
if (!item.__.hittable)
|
|
617
855
|
break;
|
|
618
|
-
hittablePath.
|
|
856
|
+
hittablePath.addAt(item, 0);
|
|
619
857
|
if (!item.__.hitChildren)
|
|
620
858
|
break;
|
|
621
859
|
}
|
|
@@ -634,7 +872,7 @@ class FindPath {
|
|
|
634
872
|
leaf = path.list[j];
|
|
635
873
|
if (nextPath && nextPath.has(leaf))
|
|
636
874
|
break;
|
|
637
|
-
throughPath.
|
|
875
|
+
throughPath.add(leaf);
|
|
638
876
|
}
|
|
639
877
|
}
|
|
640
878
|
return throughPath;
|
|
@@ -644,7 +882,7 @@ class FindPath {
|
|
|
644
882
|
const { point } = this, len = children.length;
|
|
645
883
|
for (let i = len - 1; i > -1; i--) {
|
|
646
884
|
child = children[i];
|
|
647
|
-
if (!child.__.visible || (hitMask && !child.__.
|
|
885
|
+
if (!child.__.visible || (hitMask && !child.__.mask))
|
|
648
886
|
continue;
|
|
649
887
|
hit = child.__.hitRadius ? true : hitRadiusPoint(child.__world, point);
|
|
650
888
|
if (child.isBranch) {
|
|
@@ -676,120 +914,113 @@ class FindPath {
|
|
|
676
914
|
}
|
|
677
915
|
}
|
|
678
916
|
|
|
917
|
+
const { Yes, NoAndSkip, YesAndSkip } = Answer;
|
|
679
918
|
class Selector {
|
|
680
919
|
constructor(target, userConfig) {
|
|
681
920
|
this.config = {};
|
|
682
|
-
this.
|
|
683
|
-
this.
|
|
684
|
-
this.
|
|
685
|
-
|
|
921
|
+
this.innerIdMap = {};
|
|
922
|
+
this.idMap = {};
|
|
923
|
+
this.methods = {
|
|
924
|
+
id: (leaf, name) => leaf.id === name ? (this.idMap[name] = leaf, 1) : 0,
|
|
925
|
+
innerId: (leaf, innerId) => leaf.innerId === innerId ? (this.innerIdMap[innerId] = leaf, 1) : 0,
|
|
926
|
+
className: (leaf, name) => leaf.className === name ? 1 : 0,
|
|
927
|
+
tag: (leaf, name) => leaf.__tag === name ? 1 : 0
|
|
928
|
+
};
|
|
686
929
|
this.target = target;
|
|
687
930
|
if (userConfig)
|
|
688
931
|
this.config = DataHelper.default(userConfig, this.config);
|
|
689
|
-
this.
|
|
932
|
+
this.picker = new Picker(target, this);
|
|
690
933
|
this.__listenEvents();
|
|
691
934
|
}
|
|
935
|
+
getBy(condition, branch, one, options) {
|
|
936
|
+
switch (typeof condition) {
|
|
937
|
+
case 'number':
|
|
938
|
+
const leaf = this.getByInnerId(condition, branch);
|
|
939
|
+
return one ? leaf : (leaf ? [leaf] : []);
|
|
940
|
+
case 'string':
|
|
941
|
+
switch (condition[0]) {
|
|
942
|
+
case '#':
|
|
943
|
+
const leaf = this.getById(condition.substring(1), branch);
|
|
944
|
+
return one ? leaf : (leaf ? [leaf] : []);
|
|
945
|
+
case '.':
|
|
946
|
+
return this.getByMethod(this.methods.className, branch, one, condition.substring(1));
|
|
947
|
+
default:
|
|
948
|
+
return this.getByMethod(this.methods.tag, branch, one, condition);
|
|
949
|
+
}
|
|
950
|
+
case 'function':
|
|
951
|
+
return this.getByMethod(condition, branch, one, options);
|
|
952
|
+
}
|
|
953
|
+
}
|
|
692
954
|
getByPoint(hitPoint, hitRadius, options) {
|
|
693
955
|
if (Platform.name === 'node')
|
|
694
956
|
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
|
-
}
|
|
957
|
+
return this.picker.getByPoint(hitPoint, hitRadius, options);
|
|
710
958
|
}
|
|
711
|
-
getByInnerId(
|
|
712
|
-
|
|
959
|
+
getByInnerId(innerId, branch) {
|
|
960
|
+
const cache = this.innerIdMap[innerId];
|
|
713
961
|
if (cache)
|
|
714
962
|
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;
|
|
963
|
+
this.eachFind(this.toChildren(branch), this.methods.innerId, null, innerId);
|
|
964
|
+
return this.findLeaf;
|
|
729
965
|
}
|
|
730
|
-
getById(
|
|
731
|
-
|
|
732
|
-
if (cache)
|
|
966
|
+
getById(id, branch) {
|
|
967
|
+
const cache = this.idMap[id];
|
|
968
|
+
if (cache && LeafHelper.hasParent(cache, branch || this.target))
|
|
733
969
|
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;
|
|
970
|
+
this.eachFind(this.toChildren(branch), this.methods.id, null, id);
|
|
971
|
+
return this.findLeaf;
|
|
770
972
|
}
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
973
|
+
getByClassName(className, branch) {
|
|
974
|
+
return this.getByMethod(this.methods.className, branch, false, className);
|
|
975
|
+
}
|
|
976
|
+
getByTag(tag, branch) {
|
|
977
|
+
return this.getByMethod(this.methods.tag, branch, false, tag);
|
|
978
|
+
}
|
|
979
|
+
getByMethod(method, branch, one, options) {
|
|
980
|
+
const list = one ? null : [];
|
|
981
|
+
this.eachFind(this.toChildren(branch), method, list, options);
|
|
982
|
+
return list || this.findLeaf;
|
|
983
|
+
}
|
|
984
|
+
eachFind(children, method, list, options) {
|
|
985
|
+
let child, result;
|
|
775
986
|
for (let i = 0, len = children.length; i < len; i++) {
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
987
|
+
child = children[i];
|
|
988
|
+
result = method(child, options);
|
|
989
|
+
if (result === Yes || result === YesAndSkip) {
|
|
990
|
+
if (list) {
|
|
991
|
+
list.push(child);
|
|
992
|
+
}
|
|
993
|
+
else {
|
|
994
|
+
this.findLeaf = child;
|
|
995
|
+
return;
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
if (child.isBranch && result < NoAndSkip)
|
|
999
|
+
this.eachFind(child.children, method, list, options);
|
|
781
1000
|
}
|
|
782
1001
|
}
|
|
1002
|
+
toChildren(branch) {
|
|
1003
|
+
this.findLeaf = null;
|
|
1004
|
+
return [branch || this.target];
|
|
1005
|
+
}
|
|
783
1006
|
__onRemoveChild(event) {
|
|
784
|
-
const
|
|
785
|
-
if (this.
|
|
786
|
-
this.
|
|
787
|
-
if (this.
|
|
788
|
-
this.
|
|
1007
|
+
const { id, innerId } = event.child;
|
|
1008
|
+
if (this.idMap[id])
|
|
1009
|
+
delete this.idMap[id];
|
|
1010
|
+
if (this.innerIdMap[innerId])
|
|
1011
|
+
delete this.innerIdMap[innerId];
|
|
1012
|
+
}
|
|
1013
|
+
__checkIdChange(event) {
|
|
1014
|
+
if (event.attrName === 'id') {
|
|
1015
|
+
const id = event.oldValue;
|
|
1016
|
+
if (this.idMap[id])
|
|
1017
|
+
delete this.idMap[id];
|
|
1018
|
+
}
|
|
789
1019
|
}
|
|
790
1020
|
__listenEvents() {
|
|
791
1021
|
this.__eventIds = [
|
|
792
|
-
this.target.on_(ChildEvent.REMOVE, this.__onRemoveChild, this)
|
|
1022
|
+
this.target.on_(ChildEvent.REMOVE, this.__onRemoveChild, this),
|
|
1023
|
+
this.target.on_(PropertyEvent.CHANGE, this.__checkIdChange, this)
|
|
793
1024
|
];
|
|
794
1025
|
}
|
|
795
1026
|
__removeListenEvents() {
|
|
@@ -799,11 +1030,10 @@ class Selector {
|
|
|
799
1030
|
destroy() {
|
|
800
1031
|
if (this.__eventIds.length) {
|
|
801
1032
|
this.__removeListenEvents();
|
|
802
|
-
this.
|
|
803
|
-
this.
|
|
804
|
-
this.
|
|
805
|
-
this.
|
|
806
|
-
this.tagNameList = {};
|
|
1033
|
+
this.picker.destroy();
|
|
1034
|
+
this.findLeaf = null;
|
|
1035
|
+
this.innerIdMap = {};
|
|
1036
|
+
this.idMap = {};
|
|
807
1037
|
}
|
|
808
1038
|
}
|
|
809
1039
|
}
|
|
@@ -816,169 +1046,6 @@ Object.assign(Creator, {
|
|
|
816
1046
|
});
|
|
817
1047
|
Platform.layout = Layouter.fullLayout;
|
|
818
1048
|
|
|
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
1049
|
const PointerEventHelper = {
|
|
983
1050
|
convert(e, local) {
|
|
984
1051
|
const base = InteractionHelper.getBase(e);
|
|
@@ -1025,7 +1092,7 @@ const WheelEventHelper = {
|
|
|
1025
1092
|
let { zoomMode, zoomSpeed } = config;
|
|
1026
1093
|
const delta = e.deltaY || e.deltaX;
|
|
1027
1094
|
if (zoomMode) {
|
|
1028
|
-
zoom = !e.deltaX && (Platform.intWheelDeltaY ? Math.abs(delta) > 17 : Math.ceil(delta) !== delta);
|
|
1095
|
+
zoom = (zoomMode === 'mouse') ? true : (!e.deltaX && (Platform.intWheelDeltaY ? Math.abs(delta) > 17 : Math.ceil(delta) !== delta));
|
|
1029
1096
|
if (e.shiftKey || e.metaKey || e.ctrlKey)
|
|
1030
1097
|
zoom = true;
|
|
1031
1098
|
}
|
|
@@ -1035,7 +1102,7 @@ const WheelEventHelper = {
|
|
|
1035
1102
|
if (zoom) {
|
|
1036
1103
|
zoomSpeed = MathHelper.within(zoomSpeed, 0, 1);
|
|
1037
1104
|
const min = e.deltaY ? config.delta.y : config.delta.x;
|
|
1038
|
-
scale = 1 - delta / (min *
|
|
1105
|
+
scale = 1 - delta / (min * 4) * zoomSpeed;
|
|
1039
1106
|
if (scale < 0.5)
|
|
1040
1107
|
scale = 0.5;
|
|
1041
1108
|
if (scale >= 1.5)
|
|
@@ -1062,6 +1129,7 @@ class Interaction extends InteractionBase {
|
|
|
1062
1129
|
'pointerdown': this.onPointerDown,
|
|
1063
1130
|
'mousedown': this.onMouseDown,
|
|
1064
1131
|
'touchstart': this.onTouchStart,
|
|
1132
|
+
'contextmenu': this.onContextMenu,
|
|
1065
1133
|
'wheel': this.onWheel,
|
|
1066
1134
|
'gesturestart': this.onGesturestart,
|
|
1067
1135
|
'gesturechange': this.onGesturechange,
|
|
@@ -1134,6 +1202,11 @@ class Interaction extends InteractionBase {
|
|
|
1134
1202
|
onKeyUp(e) {
|
|
1135
1203
|
this.keyUp(KeyEventHelper.convert(e));
|
|
1136
1204
|
}
|
|
1205
|
+
onContextMenu(e) {
|
|
1206
|
+
if (this.config.pointer.preventDefaultMenu)
|
|
1207
|
+
e.preventDefault();
|
|
1208
|
+
this.menu(PointerEventHelper.convert(e, this.getLocal(e)));
|
|
1209
|
+
}
|
|
1137
1210
|
onScroll() {
|
|
1138
1211
|
this.canvas.updateClientBounds();
|
|
1139
1212
|
}
|
|
@@ -1288,6 +1361,29 @@ class Interaction extends InteractionBase {
|
|
|
1288
1361
|
this.preventDefaultWheel(e);
|
|
1289
1362
|
this.transformEnd();
|
|
1290
1363
|
}
|
|
1364
|
+
setCursor(cursor) {
|
|
1365
|
+
super.setCursor(cursor);
|
|
1366
|
+
const list = [];
|
|
1367
|
+
this.eachCursor(cursor, list);
|
|
1368
|
+
if (typeof list[list.length - 1] === 'object')
|
|
1369
|
+
list.push('default');
|
|
1370
|
+
this.canvas.view.style.cursor = list.map(item => (typeof item === 'object') ? `url(${item.url}) ${item.x || 0} ${item.y || 0}` : item).join(',');
|
|
1371
|
+
}
|
|
1372
|
+
eachCursor(cursor, list, level = 0) {
|
|
1373
|
+
level++;
|
|
1374
|
+
if (cursor instanceof Array) {
|
|
1375
|
+
cursor.forEach(item => this.eachCursor(item, list, level));
|
|
1376
|
+
}
|
|
1377
|
+
else {
|
|
1378
|
+
const custom = typeof cursor === 'string' && Cursor.get(cursor);
|
|
1379
|
+
if (custom && level < 2) {
|
|
1380
|
+
this.eachCursor(custom, list, level);
|
|
1381
|
+
}
|
|
1382
|
+
else {
|
|
1383
|
+
list.push(cursor);
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1291
1387
|
destroy() {
|
|
1292
1388
|
if (this.view) {
|
|
1293
1389
|
super.destroy();
|
|
@@ -1297,416 +1393,34 @@ class Interaction extends InteractionBase {
|
|
|
1297
1393
|
}
|
|
1298
1394
|
}
|
|
1299
1395
|
|
|
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;
|
|
1396
|
+
function fillText(ui, canvas) {
|
|
1397
|
+
let row;
|
|
1398
|
+
const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
|
|
1399
|
+
for (let i = 0, len = rows.length; i < len; i++) {
|
|
1400
|
+
row = rows[i];
|
|
1401
|
+
if (row.text) {
|
|
1402
|
+
canvas.fillText(row.text, row.x, row.y);
|
|
1403
|
+
}
|
|
1404
|
+
else if (row.data) {
|
|
1405
|
+
row.data.forEach(charData => {
|
|
1406
|
+
canvas.fillText(charData.char, charData.x, row.y);
|
|
1338
1407
|
});
|
|
1339
1408
|
}
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
}
|
|
1344
|
-
Platform.name = 'web';
|
|
1345
|
-
Platform.isMobile = 'ontouchstart' in window;
|
|
1346
|
-
Platform.requestRender = function (render) { window.requestAnimationFrame(render); };
|
|
1347
|
-
Platform.devicePixelRatio = devicePixelRatio;
|
|
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;
|
|
1354
|
-
}
|
|
1355
|
-
else if (userAgent.indexOf("Safari") > -1 && userAgent.indexOf("Chrome") === -1) {
|
|
1356
|
-
Platform.fullImageShadow = true;
|
|
1357
|
-
}
|
|
1358
|
-
if (userAgent.indexOf('Windows') > -1) {
|
|
1359
|
-
Platform.os = 'Windows';
|
|
1360
|
-
Platform.intWheelDeltaY = true;
|
|
1361
|
-
}
|
|
1362
|
-
else if (userAgent.indexOf('Mac') > -1) {
|
|
1363
|
-
Platform.os = 'Mac';
|
|
1364
|
-
}
|
|
1365
|
-
else if (userAgent.indexOf('Linux') > -1) {
|
|
1366
|
-
Platform.os = 'Linux';
|
|
1409
|
+
if (decorationY)
|
|
1410
|
+
canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight);
|
|
1411
|
+
}
|
|
1367
1412
|
}
|
|
1368
1413
|
|
|
1369
|
-
|
|
1370
|
-
function fillOrFitMode(data, mode, box, width, height, rotation) {
|
|
1371
|
-
const transform = get$4();
|
|
1372
|
-
const swap = rotation && rotation !== 180;
|
|
1373
|
-
const sw = box.width / (swap ? height : width);
|
|
1374
|
-
const sh = box.height / (swap ? width : height);
|
|
1375
|
-
const scale = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
|
|
1376
|
-
const x = box.x + (box.width - width * scale) / 2;
|
|
1377
|
-
const y = box.y + (box.height - height * scale) / 2;
|
|
1378
|
-
translate$1(transform, x, y);
|
|
1379
|
-
scaleHelper$1(transform, scale);
|
|
1380
|
-
if (rotation)
|
|
1381
|
-
rotateOfOuter$2(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
|
|
1382
|
-
data.scaleX = data.scaleY = scale;
|
|
1383
|
-
data.transform = transform;
|
|
1384
|
-
}
|
|
1385
|
-
function clipMode(data, box, offset, scale, rotation) {
|
|
1386
|
-
const transform = get$4();
|
|
1387
|
-
translate$1(transform, box.x, box.y);
|
|
1388
|
-
if (offset)
|
|
1389
|
-
translate$1(transform, offset.x, offset.y);
|
|
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
|
-
}
|
|
1395
|
-
if (rotation)
|
|
1396
|
-
rotate(transform, rotation);
|
|
1397
|
-
data.transform = transform;
|
|
1398
|
-
}
|
|
1399
|
-
function repeatMode(data, box, width, height, scale, rotation) {
|
|
1400
|
-
const transform = get$4();
|
|
1401
|
-
if (rotation) {
|
|
1402
|
-
rotate(transform, rotation);
|
|
1403
|
-
switch (rotation) {
|
|
1404
|
-
case 90:
|
|
1405
|
-
translate$1(transform, height, 0);
|
|
1406
|
-
break;
|
|
1407
|
-
case 180:
|
|
1408
|
-
translate$1(transform, width, height);
|
|
1409
|
-
break;
|
|
1410
|
-
case 270:
|
|
1411
|
-
translate$1(transform, 0, width);
|
|
1412
|
-
break;
|
|
1413
|
-
}
|
|
1414
|
-
}
|
|
1415
|
-
translate$1(transform, box.x, box.y);
|
|
1416
|
-
if (scale) {
|
|
1417
|
-
scaleOfOuter$2(transform, box, scale);
|
|
1418
|
-
data.scaleX = data.scaleY = scale;
|
|
1419
|
-
}
|
|
1420
|
-
data.transform = transform;
|
|
1421
|
-
}
|
|
1422
|
-
|
|
1423
|
-
const { get: get$3, translate } = MatrixHelper;
|
|
1424
|
-
function createData(leafPaint, image, paint, box) {
|
|
1425
|
-
let { width, height } = image;
|
|
1426
|
-
const { opacity, mode, offset, scale, rotation, blendMode } = paint;
|
|
1427
|
-
const sameBox = box.width === width && box.height === height;
|
|
1428
|
-
if (blendMode)
|
|
1429
|
-
leafPaint.blendMode = blendMode;
|
|
1430
|
-
const data = leafPaint.data = { mode };
|
|
1431
|
-
switch (mode) {
|
|
1432
|
-
case 'strench':
|
|
1433
|
-
if (!sameBox)
|
|
1434
|
-
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
|
-
break;
|
|
1440
|
-
case 'clip':
|
|
1441
|
-
if (offset || scale || rotation)
|
|
1442
|
-
clipMode(data, box, offset, scale, rotation);
|
|
1443
|
-
break;
|
|
1444
|
-
case 'repeat':
|
|
1445
|
-
if (!sameBox || scale || rotation)
|
|
1446
|
-
repeatMode(data, box, width, height, scale, rotation);
|
|
1447
|
-
break;
|
|
1448
|
-
case 'fit':
|
|
1449
|
-
case 'cover':
|
|
1450
|
-
default:
|
|
1451
|
-
if (!sameBox || rotation)
|
|
1452
|
-
fillOrFitMode(data, mode, box, width, height, rotation);
|
|
1453
|
-
}
|
|
1454
|
-
data.width = width;
|
|
1455
|
-
data.height = height;
|
|
1456
|
-
if (opacity)
|
|
1457
|
-
data.opacity = opacity;
|
|
1458
|
-
}
|
|
1459
|
-
|
|
1460
|
-
function image(ui, attrName, attrValue, box, firstUse) {
|
|
1461
|
-
const leafPaint = { type: attrValue.type };
|
|
1462
|
-
const image = leafPaint.image = ImageManager.get(attrValue);
|
|
1463
|
-
const event = (firstUse || image.loading) && { target: ui, image, attrName, attrValue };
|
|
1464
|
-
if (image.ready) {
|
|
1465
|
-
if (hasNaturalSize(ui, attrName, image))
|
|
1466
|
-
createData(leafPaint, image, attrValue, box);
|
|
1467
|
-
if (firstUse) {
|
|
1468
|
-
emit(ImageEvent.LOAD, event);
|
|
1469
|
-
emit(ImageEvent.LOADED, event);
|
|
1470
|
-
}
|
|
1471
|
-
}
|
|
1472
|
-
else if (image.error) {
|
|
1473
|
-
if (firstUse) {
|
|
1474
|
-
ui.forceUpdate('surface');
|
|
1475
|
-
event.error = image.error;
|
|
1476
|
-
emit(ImageEvent.ERROR, event);
|
|
1477
|
-
}
|
|
1478
|
-
}
|
|
1479
|
-
else {
|
|
1480
|
-
if (firstUse)
|
|
1481
|
-
emit(ImageEvent.LOAD, event);
|
|
1482
|
-
leafPaint.loadId = image.load(() => {
|
|
1483
|
-
if (!ui.destroyed) {
|
|
1484
|
-
if (hasNaturalSize(ui, attrName, image)) {
|
|
1485
|
-
createData(leafPaint, image, attrValue, box);
|
|
1486
|
-
ui.forceUpdate('surface');
|
|
1487
|
-
}
|
|
1488
|
-
emit(ImageEvent.LOADED, event);
|
|
1489
|
-
}
|
|
1490
|
-
}, (error) => {
|
|
1491
|
-
ui.forceUpdate('surface');
|
|
1492
|
-
event.error = error;
|
|
1493
|
-
emit(ImageEvent.ERROR, event);
|
|
1494
|
-
});
|
|
1495
|
-
}
|
|
1496
|
-
return leafPaint;
|
|
1497
|
-
}
|
|
1498
|
-
function hasNaturalSize(ui, attrName, image) {
|
|
1499
|
-
if (attrName === 'fill' && !ui.__.__naturalWidth) {
|
|
1500
|
-
const { __: d } = ui;
|
|
1501
|
-
d.__naturalWidth = image.width;
|
|
1502
|
-
d.__naturalHeight = image.height;
|
|
1503
|
-
if (!d.__getInput('width') || !d.__getInput('height')) {
|
|
1504
|
-
ui.forceUpdate('width');
|
|
1505
|
-
return false;
|
|
1506
|
-
}
|
|
1507
|
-
}
|
|
1508
|
-
return true;
|
|
1509
|
-
}
|
|
1510
|
-
function emit(type, data) {
|
|
1511
|
-
if (data.target.hasEvent(type))
|
|
1512
|
-
data.target.emitEvent(new ImageEvent(type, data));
|
|
1513
|
-
}
|
|
1514
|
-
|
|
1515
|
-
/******************************************************************************
|
|
1516
|
-
Copyright (c) Microsoft Corporation.
|
|
1517
|
-
|
|
1518
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
1519
|
-
purpose with or without fee is hereby granted.
|
|
1520
|
-
|
|
1521
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
1522
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
1523
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
1524
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
1525
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
1526
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
1527
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
1528
|
-
***************************************************************************** */
|
|
1529
|
-
/* global Reflect, Promise, SuppressedError, Symbol */
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
1533
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
1534
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
1535
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
1536
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
1537
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
1538
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
1539
|
-
});
|
|
1540
|
-
}
|
|
1541
|
-
|
|
1542
|
-
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
1543
|
-
var e = new Error(message);
|
|
1544
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
1545
|
-
};
|
|
1546
|
-
|
|
1547
|
-
const { get: get$2, scale: scaleHelper, copy: copy$1 } = MatrixHelper;
|
|
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
|
-
|
|
1609
|
-
function checkImage(ui, canvas, paint, allowPaint) {
|
|
1610
|
-
const { scaleX, scaleY } = ui.__world;
|
|
1611
|
-
if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
|
|
1612
|
-
return false;
|
|
1613
|
-
}
|
|
1614
|
-
else {
|
|
1615
|
-
if (allowPaint) {
|
|
1616
|
-
if (paint.image.isSVG && paint.data.mode !== 'repeat') {
|
|
1617
|
-
let { width, height } = paint.data;
|
|
1618
|
-
width *= scaleX * canvas.pixelRatio;
|
|
1619
|
-
height *= scaleY * canvas.pixelRatio;
|
|
1620
|
-
allowPaint = width > 4096 || height > 4096;
|
|
1621
|
-
}
|
|
1622
|
-
else {
|
|
1623
|
-
allowPaint = false;
|
|
1624
|
-
}
|
|
1625
|
-
}
|
|
1626
|
-
if (allowPaint) {
|
|
1627
|
-
canvas.save();
|
|
1628
|
-
canvas.clip();
|
|
1629
|
-
const { data } = paint;
|
|
1630
|
-
if (paint.blendMode)
|
|
1631
|
-
canvas.blendMode = paint.blendMode;
|
|
1632
|
-
if (data.opacity)
|
|
1633
|
-
canvas.opacity *= data.opacity;
|
|
1634
|
-
if (data.transform)
|
|
1635
|
-
canvas.transform(data.transform);
|
|
1636
|
-
canvas.drawImage(paint.image.view, 0, 0, data.width, data.height);
|
|
1637
|
-
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) {
|
|
1414
|
+
function fill(fill, ui, canvas) {
|
|
1701
1415
|
canvas.fillStyle = fill;
|
|
1702
1416
|
ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
|
|
1703
1417
|
}
|
|
1704
|
-
function fills(ui, canvas
|
|
1418
|
+
function fills(fills, ui, canvas) {
|
|
1705
1419
|
let item;
|
|
1706
1420
|
const { windingRule, __font } = ui.__;
|
|
1707
1421
|
for (let i = 0, len = fills.length; i < len; i++) {
|
|
1708
1422
|
item = fills[i];
|
|
1709
|
-
if (item.image && checkImage(ui, canvas, item, !__font))
|
|
1423
|
+
if (item.image && PaintImage.checkImage(ui, canvas, item, !__font))
|
|
1710
1424
|
continue;
|
|
1711
1425
|
if (item.style) {
|
|
1712
1426
|
canvas.fillStyle = item.style;
|
|
@@ -1732,33 +1446,38 @@ function fills(ui, canvas, fills) {
|
|
|
1732
1446
|
}
|
|
1733
1447
|
}
|
|
1734
1448
|
|
|
1735
|
-
function strokeText(ui, canvas
|
|
1449
|
+
function strokeText(stroke, ui, canvas) {
|
|
1736
1450
|
const { strokeAlign } = ui.__;
|
|
1737
1451
|
const isStrokes = typeof stroke !== 'string';
|
|
1738
1452
|
switch (strokeAlign) {
|
|
1739
1453
|
case 'center':
|
|
1740
1454
|
canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
|
|
1741
|
-
isStrokes ? drawStrokesStyle(
|
|
1455
|
+
isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
|
|
1742
1456
|
break;
|
|
1743
1457
|
case 'inside':
|
|
1744
|
-
drawAlignStroke(
|
|
1458
|
+
drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
|
|
1745
1459
|
break;
|
|
1746
1460
|
case 'outside':
|
|
1747
|
-
drawAlignStroke(
|
|
1461
|
+
drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
|
|
1748
1462
|
break;
|
|
1749
1463
|
}
|
|
1750
1464
|
}
|
|
1751
|
-
function drawAlignStroke(
|
|
1752
|
-
const {
|
|
1753
|
-
const out = canvas.getSameCanvas(true);
|
|
1754
|
-
out.setStroke(isStrokes ? undefined : stroke,
|
|
1465
|
+
function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
|
|
1466
|
+
const { __strokeWidth, __font } = ui.__;
|
|
1467
|
+
const out = canvas.getSameCanvas(true, true);
|
|
1468
|
+
out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__);
|
|
1755
1469
|
out.font = __font;
|
|
1756
|
-
isStrokes ? drawStrokesStyle(
|
|
1470
|
+
isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
|
|
1757
1471
|
out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
|
|
1758
1472
|
fillText(ui, out);
|
|
1759
1473
|
out.blendMode = 'normal';
|
|
1760
|
-
|
|
1761
|
-
|
|
1474
|
+
if (ui.__worldFlipped) {
|
|
1475
|
+
canvas.copyWorldByReset(out, ui.__nowWorld);
|
|
1476
|
+
}
|
|
1477
|
+
else {
|
|
1478
|
+
canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
|
|
1479
|
+
}
|
|
1480
|
+
out.recycle(ui.__nowWorld);
|
|
1762
1481
|
}
|
|
1763
1482
|
function drawTextStroke(ui, canvas) {
|
|
1764
1483
|
let row;
|
|
@@ -1777,11 +1496,11 @@ function drawTextStroke(ui, canvas) {
|
|
|
1777
1496
|
canvas.strokeRect(row.x, row.y + decorationY, row.width, decorationHeight);
|
|
1778
1497
|
}
|
|
1779
1498
|
}
|
|
1780
|
-
function drawStrokesStyle(
|
|
1499
|
+
function drawStrokesStyle(strokes, isText, ui, canvas) {
|
|
1781
1500
|
let item;
|
|
1782
1501
|
for (let i = 0, len = strokes.length; i < len; i++) {
|
|
1783
1502
|
item = strokes[i];
|
|
1784
|
-
if (item.image && checkImage(ui, canvas, item, false))
|
|
1503
|
+
if (item.image && PaintImage.checkImage(ui, canvas, item, false))
|
|
1785
1504
|
continue;
|
|
1786
1505
|
if (item.style) {
|
|
1787
1506
|
canvas.strokeStyle = item.style;
|
|
@@ -1797,121 +1516,575 @@ function drawStrokesStyle(ui, strokes, canvas, isText) {
|
|
|
1797
1516
|
}
|
|
1798
1517
|
}
|
|
1799
1518
|
|
|
1800
|
-
function stroke(ui, canvas
|
|
1519
|
+
function stroke(stroke, ui, canvas) {
|
|
1801
1520
|
const options = ui.__;
|
|
1802
|
-
const {
|
|
1803
|
-
if (!
|
|
1521
|
+
const { __strokeWidth, strokeAlign, __font } = options;
|
|
1522
|
+
if (!__strokeWidth)
|
|
1804
1523
|
return;
|
|
1805
1524
|
if (__font) {
|
|
1806
|
-
strokeText(ui, canvas
|
|
1525
|
+
strokeText(stroke, ui, canvas);
|
|
1807
1526
|
}
|
|
1808
1527
|
else {
|
|
1809
1528
|
switch (strokeAlign) {
|
|
1810
1529
|
case 'center':
|
|
1811
|
-
canvas.setStroke(stroke,
|
|
1530
|
+
canvas.setStroke(stroke, __strokeWidth, options);
|
|
1812
1531
|
canvas.stroke();
|
|
1813
1532
|
break;
|
|
1814
1533
|
case 'inside':
|
|
1815
1534
|
canvas.save();
|
|
1816
|
-
canvas.setStroke(stroke,
|
|
1535
|
+
canvas.setStroke(stroke, __strokeWidth * 2, options);
|
|
1817
1536
|
options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
|
|
1818
1537
|
canvas.stroke();
|
|
1819
1538
|
canvas.restore();
|
|
1820
1539
|
break;
|
|
1821
1540
|
case 'outside':
|
|
1822
|
-
const out = canvas.getSameCanvas(true);
|
|
1823
|
-
out.setStroke(stroke,
|
|
1541
|
+
const out = canvas.getSameCanvas(true, true);
|
|
1542
|
+
out.setStroke(stroke, __strokeWidth * 2, options);
|
|
1824
1543
|
ui.__drawRenderPath(out);
|
|
1825
1544
|
out.stroke();
|
|
1826
1545
|
options.windingRule ? out.clip(options.windingRule) : out.clip();
|
|
1827
1546
|
out.clearWorld(ui.__layout.renderBounds);
|
|
1828
|
-
|
|
1829
|
-
|
|
1547
|
+
if (ui.__worldFlipped) {
|
|
1548
|
+
canvas.copyWorldByReset(out, ui.__nowWorld);
|
|
1549
|
+
}
|
|
1550
|
+
else {
|
|
1551
|
+
canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
|
|
1552
|
+
}
|
|
1553
|
+
out.recycle(ui.__nowWorld);
|
|
1554
|
+
break;
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
function strokes(strokes, ui, canvas) {
|
|
1559
|
+
const options = ui.__;
|
|
1560
|
+
const { __strokeWidth, strokeAlign, __font } = options;
|
|
1561
|
+
if (!__strokeWidth)
|
|
1562
|
+
return;
|
|
1563
|
+
if (__font) {
|
|
1564
|
+
strokeText(strokes, ui, canvas);
|
|
1565
|
+
}
|
|
1566
|
+
else {
|
|
1567
|
+
switch (strokeAlign) {
|
|
1568
|
+
case 'center':
|
|
1569
|
+
canvas.setStroke(undefined, __strokeWidth, options);
|
|
1570
|
+
drawStrokesStyle(strokes, false, ui, canvas);
|
|
1571
|
+
break;
|
|
1572
|
+
case 'inside':
|
|
1573
|
+
canvas.save();
|
|
1574
|
+
canvas.setStroke(undefined, __strokeWidth * 2, options);
|
|
1575
|
+
options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
|
|
1576
|
+
drawStrokesStyle(strokes, false, ui, canvas);
|
|
1577
|
+
canvas.restore();
|
|
1578
|
+
break;
|
|
1579
|
+
case 'outside':
|
|
1580
|
+
const { renderBounds } = ui.__layout;
|
|
1581
|
+
const out = canvas.getSameCanvas(true, true);
|
|
1582
|
+
ui.__drawRenderPath(out);
|
|
1583
|
+
out.setStroke(undefined, __strokeWidth * 2, options);
|
|
1584
|
+
drawStrokesStyle(strokes, false, ui, out);
|
|
1585
|
+
options.windingRule ? out.clip(options.windingRule) : out.clip();
|
|
1586
|
+
out.clearWorld(renderBounds);
|
|
1587
|
+
if (ui.__worldFlipped) {
|
|
1588
|
+
canvas.copyWorldByReset(out, ui.__nowWorld);
|
|
1589
|
+
}
|
|
1590
|
+
else {
|
|
1591
|
+
canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
|
|
1592
|
+
}
|
|
1593
|
+
out.recycle(ui.__nowWorld);
|
|
1594
|
+
break;
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
const { getSpread, getOuterOf, getByMove, getIntersectData } = BoundsHelper;
|
|
1600
|
+
function shape(ui, current, options) {
|
|
1601
|
+
const canvas = current.getSameCanvas();
|
|
1602
|
+
const nowWorld = ui.__nowWorld;
|
|
1603
|
+
let bounds, fitMatrix, shapeBounds, worldCanvas;
|
|
1604
|
+
let { scaleX, scaleY } = nowWorld;
|
|
1605
|
+
if (scaleX < 0)
|
|
1606
|
+
scaleX = -scaleX;
|
|
1607
|
+
if (scaleY < 0)
|
|
1608
|
+
scaleY = -scaleY;
|
|
1609
|
+
if (current.bounds.includes(nowWorld)) {
|
|
1610
|
+
worldCanvas = canvas;
|
|
1611
|
+
bounds = shapeBounds = nowWorld;
|
|
1612
|
+
}
|
|
1613
|
+
else {
|
|
1614
|
+
const { renderShapeSpread: spread } = ui.__layout;
|
|
1615
|
+
const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, spread * scaleX, spread * scaleY) : current.bounds, nowWorld);
|
|
1616
|
+
fitMatrix = current.bounds.getFitMatrix(worldClipBounds);
|
|
1617
|
+
let { a: fitScaleX, d: fitScaleY } = fitMatrix;
|
|
1618
|
+
if (fitMatrix.a < 1) {
|
|
1619
|
+
worldCanvas = current.getSameCanvas();
|
|
1620
|
+
ui.__renderShape(worldCanvas, options);
|
|
1621
|
+
scaleX *= fitScaleX;
|
|
1622
|
+
scaleY *= fitScaleY;
|
|
1623
|
+
}
|
|
1624
|
+
shapeBounds = getOuterOf(nowWorld, fitMatrix);
|
|
1625
|
+
bounds = getByMove(shapeBounds, -fitMatrix.e, -fitMatrix.f);
|
|
1626
|
+
if (options.matrix) {
|
|
1627
|
+
const { matrix } = options;
|
|
1628
|
+
fitMatrix.multiply(matrix);
|
|
1629
|
+
fitScaleX *= matrix.scaleX;
|
|
1630
|
+
fitScaleY *= matrix.scaleY;
|
|
1631
|
+
}
|
|
1632
|
+
options = Object.assign(Object.assign({}, options), { matrix: fitMatrix.withScale(fitScaleX, fitScaleY) });
|
|
1633
|
+
}
|
|
1634
|
+
ui.__renderShape(canvas, options);
|
|
1635
|
+
return {
|
|
1636
|
+
canvas, matrix: fitMatrix, bounds,
|
|
1637
|
+
worldCanvas, shapeBounds, scaleX, scaleY
|
|
1638
|
+
};
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
let recycleMap;
|
|
1642
|
+
function compute(attrName, ui) {
|
|
1643
|
+
const data = ui.__, leafPaints = [];
|
|
1644
|
+
let paints = data.__input[attrName], hasOpacityPixel;
|
|
1645
|
+
if (!(paints instanceof Array))
|
|
1646
|
+
paints = [paints];
|
|
1647
|
+
recycleMap = PaintImage.recycleImage(attrName, data);
|
|
1648
|
+
for (let i = 0, len = paints.length, item; i < len; i++) {
|
|
1649
|
+
item = getLeafPaint(attrName, paints[i], ui);
|
|
1650
|
+
if (item)
|
|
1651
|
+
leafPaints.push(item);
|
|
1652
|
+
}
|
|
1653
|
+
data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
|
|
1654
|
+
if (leafPaints.length && leafPaints[0].image)
|
|
1655
|
+
hasOpacityPixel = leafPaints[0].image.hasOpacityPixel;
|
|
1656
|
+
if (attrName === 'fill') {
|
|
1657
|
+
data.__pixelFill = hasOpacityPixel;
|
|
1658
|
+
}
|
|
1659
|
+
else {
|
|
1660
|
+
data.__pixelStroke = hasOpacityPixel;
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
function getLeafPaint(attrName, paint, ui) {
|
|
1664
|
+
if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
|
|
1665
|
+
return undefined;
|
|
1666
|
+
const { boxBounds } = ui.__layout;
|
|
1667
|
+
switch (paint.type) {
|
|
1668
|
+
case 'solid':
|
|
1669
|
+
let { type, blendMode, color, opacity } = paint;
|
|
1670
|
+
return { type, blendMode, style: ColorConvert.string(color, opacity) };
|
|
1671
|
+
case 'image':
|
|
1672
|
+
return PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
|
|
1673
|
+
case 'linear':
|
|
1674
|
+
return PaintGradient.linearGradient(paint, boxBounds);
|
|
1675
|
+
case 'radial':
|
|
1676
|
+
return PaintGradient.radialGradient(paint, boxBounds);
|
|
1677
|
+
case 'angular':
|
|
1678
|
+
return PaintGradient.conicGradient(paint, boxBounds);
|
|
1679
|
+
default:
|
|
1680
|
+
return paint.r ? { type: 'solid', style: ColorConvert.string(paint) } : undefined;
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
const PaintModule = {
|
|
1685
|
+
compute,
|
|
1686
|
+
fill,
|
|
1687
|
+
fills,
|
|
1688
|
+
fillText,
|
|
1689
|
+
stroke,
|
|
1690
|
+
strokes,
|
|
1691
|
+
strokeText,
|
|
1692
|
+
drawTextStroke,
|
|
1693
|
+
shape
|
|
1694
|
+
};
|
|
1695
|
+
|
|
1696
|
+
let origin = {};
|
|
1697
|
+
const { get: get$4, rotateOfOuter: rotateOfOuter$2, translate: translate$1, scaleOfOuter: scaleOfOuter$2, scale: scaleHelper, rotate } = MatrixHelper;
|
|
1698
|
+
function fillOrFitMode(data, mode, box, width, height, rotation) {
|
|
1699
|
+
const transform = get$4();
|
|
1700
|
+
const swap = rotation && rotation !== 180;
|
|
1701
|
+
const sw = box.width / (swap ? height : width);
|
|
1702
|
+
const sh = box.height / (swap ? width : height);
|
|
1703
|
+
const scale = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
|
|
1704
|
+
const x = box.x + (box.width - width * scale) / 2;
|
|
1705
|
+
const y = box.y + (box.height - height * scale) / 2;
|
|
1706
|
+
translate$1(transform, x, y);
|
|
1707
|
+
scaleHelper(transform, scale);
|
|
1708
|
+
if (rotation)
|
|
1709
|
+
rotateOfOuter$2(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
|
|
1710
|
+
data.scaleX = data.scaleY = scale;
|
|
1711
|
+
data.transform = transform;
|
|
1712
|
+
}
|
|
1713
|
+
function clipMode(data, box, x, y, scaleX, scaleY, rotation) {
|
|
1714
|
+
const transform = get$4();
|
|
1715
|
+
translate$1(transform, box.x, box.y);
|
|
1716
|
+
if (x || y)
|
|
1717
|
+
translate$1(transform, x, y);
|
|
1718
|
+
if (scaleX) {
|
|
1719
|
+
scaleHelper(transform, scaleX, scaleY);
|
|
1720
|
+
data.scaleX = transform.a;
|
|
1721
|
+
data.scaleY = transform.d;
|
|
1722
|
+
}
|
|
1723
|
+
if (rotation)
|
|
1724
|
+
rotate(transform, rotation);
|
|
1725
|
+
data.transform = transform;
|
|
1726
|
+
}
|
|
1727
|
+
function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation) {
|
|
1728
|
+
const transform = get$4();
|
|
1729
|
+
if (rotation) {
|
|
1730
|
+
rotate(transform, rotation);
|
|
1731
|
+
switch (rotation) {
|
|
1732
|
+
case 90:
|
|
1733
|
+
translate$1(transform, height, 0);
|
|
1734
|
+
break;
|
|
1735
|
+
case 180:
|
|
1736
|
+
translate$1(transform, width, height);
|
|
1830
1737
|
break;
|
|
1738
|
+
case 270:
|
|
1739
|
+
translate$1(transform, 0, width);
|
|
1740
|
+
break;
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
origin.x = box.x;
|
|
1744
|
+
origin.y = box.y;
|
|
1745
|
+
if (x || y)
|
|
1746
|
+
origin.x += x, origin.y += y;
|
|
1747
|
+
translate$1(transform, origin.x, origin.y);
|
|
1748
|
+
if (scaleX) {
|
|
1749
|
+
scaleOfOuter$2(transform, origin, scaleX, scaleY);
|
|
1750
|
+
data.scaleX = scaleX;
|
|
1751
|
+
data.scaleY = scaleY;
|
|
1752
|
+
}
|
|
1753
|
+
data.transform = transform;
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
const { get: get$3, translate } = MatrixHelper;
|
|
1757
|
+
const tempBox = new Bounds();
|
|
1758
|
+
function createData(leafPaint, image, paint, box) {
|
|
1759
|
+
let { width, height } = image;
|
|
1760
|
+
if (paint.padding)
|
|
1761
|
+
box = tempBox.set(box).shrink(paint.padding);
|
|
1762
|
+
const { opacity, mode, offset, scale, size, rotation, blendMode, repeat } = paint;
|
|
1763
|
+
const sameBox = box.width === width && box.height === height;
|
|
1764
|
+
if (blendMode)
|
|
1765
|
+
leafPaint.blendMode = blendMode;
|
|
1766
|
+
const data = leafPaint.data = { mode };
|
|
1767
|
+
let x, y, scaleX, scaleY;
|
|
1768
|
+
if (offset)
|
|
1769
|
+
x = offset.x, y = offset.y;
|
|
1770
|
+
if (size) {
|
|
1771
|
+
scaleX = (typeof size === 'number' ? size : size.width) / width;
|
|
1772
|
+
scaleY = (typeof size === 'number' ? size : size.height) / height;
|
|
1773
|
+
}
|
|
1774
|
+
else if (scale) {
|
|
1775
|
+
scaleX = typeof scale === 'number' ? scale : scale.x;
|
|
1776
|
+
scaleY = typeof scale === 'number' ? scale : scale.y;
|
|
1777
|
+
}
|
|
1778
|
+
switch (mode) {
|
|
1779
|
+
case 'strench':
|
|
1780
|
+
if (!sameBox)
|
|
1781
|
+
width = box.width, height = box.height;
|
|
1782
|
+
break;
|
|
1783
|
+
case 'clip':
|
|
1784
|
+
if (offset || scaleX || rotation)
|
|
1785
|
+
clipMode(data, box, x, y, scaleX, scaleY, rotation);
|
|
1786
|
+
break;
|
|
1787
|
+
case 'repeat':
|
|
1788
|
+
if (!sameBox || scaleX || rotation)
|
|
1789
|
+
repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation);
|
|
1790
|
+
if (!repeat)
|
|
1791
|
+
data.repeat = 'repeat';
|
|
1792
|
+
break;
|
|
1793
|
+
case 'fit':
|
|
1794
|
+
case 'cover':
|
|
1795
|
+
default:
|
|
1796
|
+
if (!sameBox || rotation)
|
|
1797
|
+
fillOrFitMode(data, mode, box, width, height, rotation);
|
|
1798
|
+
}
|
|
1799
|
+
if (!data.transform) {
|
|
1800
|
+
if (box.x || box.y) {
|
|
1801
|
+
data.transform = get$3();
|
|
1802
|
+
translate(data.transform, box.x, box.y);
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
data.width = width;
|
|
1806
|
+
data.height = height;
|
|
1807
|
+
if (opacity)
|
|
1808
|
+
data.opacity = opacity;
|
|
1809
|
+
if (repeat)
|
|
1810
|
+
data.repeat = typeof repeat === 'string' ? (repeat === 'x' ? 'repeat-x' : 'repeat-y') : 'repeat';
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
let cache, box = new Bounds();
|
|
1814
|
+
const { isSame } = BoundsHelper;
|
|
1815
|
+
function image(ui, attrName, paint, boxBounds, firstUse) {
|
|
1816
|
+
let leafPaint, event;
|
|
1817
|
+
const image = ImageManager.get(paint);
|
|
1818
|
+
if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
|
|
1819
|
+
leafPaint = cache.leafPaint;
|
|
1820
|
+
}
|
|
1821
|
+
else {
|
|
1822
|
+
leafPaint = { type: paint.type, image };
|
|
1823
|
+
cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
|
|
1824
|
+
}
|
|
1825
|
+
if (firstUse || image.loading)
|
|
1826
|
+
event = { image, attrName, attrValue: paint };
|
|
1827
|
+
if (image.ready) {
|
|
1828
|
+
checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
|
|
1829
|
+
if (firstUse) {
|
|
1830
|
+
onLoad(ui, event);
|
|
1831
|
+
onLoadSuccess(ui, event);
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
else if (image.error) {
|
|
1835
|
+
if (firstUse)
|
|
1836
|
+
onLoadError(ui, event, image.error);
|
|
1837
|
+
}
|
|
1838
|
+
else {
|
|
1839
|
+
ignoreRender(ui, true);
|
|
1840
|
+
if (firstUse)
|
|
1841
|
+
onLoad(ui, event);
|
|
1842
|
+
leafPaint.loadId = image.load(() => {
|
|
1843
|
+
ignoreRender(ui, false);
|
|
1844
|
+
if (!ui.destroyed) {
|
|
1845
|
+
if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
|
|
1846
|
+
if (image.hasOpacityPixel)
|
|
1847
|
+
ui.__layout.hitCanvasChanged = true;
|
|
1848
|
+
ui.forceUpdate('surface');
|
|
1849
|
+
}
|
|
1850
|
+
onLoadSuccess(ui, event);
|
|
1851
|
+
}
|
|
1852
|
+
leafPaint.loadId = null;
|
|
1853
|
+
}, (error) => {
|
|
1854
|
+
ignoreRender(ui, false);
|
|
1855
|
+
onLoadError(ui, event, error);
|
|
1856
|
+
leafPaint.loadId = null;
|
|
1857
|
+
});
|
|
1858
|
+
}
|
|
1859
|
+
return leafPaint;
|
|
1860
|
+
}
|
|
1861
|
+
function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
|
|
1862
|
+
if (attrName === 'fill' && !ui.__.__naturalWidth) {
|
|
1863
|
+
const data = ui.__;
|
|
1864
|
+
data.__naturalWidth = image.width / data.pixelRatio;
|
|
1865
|
+
data.__naturalHeight = image.height / data.pixelRatio;
|
|
1866
|
+
if (data.__autoSide) {
|
|
1867
|
+
ui.forceUpdate('width');
|
|
1868
|
+
if (ui.__proxyData) {
|
|
1869
|
+
ui.setProxyAttr('width', data.width);
|
|
1870
|
+
ui.setProxyAttr('height', data.height);
|
|
1871
|
+
}
|
|
1872
|
+
return false;
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
if (!leafPaint.data)
|
|
1876
|
+
createData(leafPaint, image, paint, boxBounds);
|
|
1877
|
+
return true;
|
|
1878
|
+
}
|
|
1879
|
+
function onLoad(ui, event) {
|
|
1880
|
+
emit(ui, ImageEvent.LOAD, event);
|
|
1881
|
+
}
|
|
1882
|
+
function onLoadSuccess(ui, event) {
|
|
1883
|
+
emit(ui, ImageEvent.LOADED, event);
|
|
1884
|
+
}
|
|
1885
|
+
function onLoadError(ui, event, error) {
|
|
1886
|
+
event.error = error;
|
|
1887
|
+
ui.forceUpdate('surface');
|
|
1888
|
+
emit(ui, ImageEvent.ERROR, event);
|
|
1889
|
+
}
|
|
1890
|
+
function emit(ui, type, data) {
|
|
1891
|
+
if (ui.hasEvent(type))
|
|
1892
|
+
ui.emitEvent(new ImageEvent(type, data));
|
|
1893
|
+
}
|
|
1894
|
+
function ignoreRender(ui, value) {
|
|
1895
|
+
const { leafer } = ui;
|
|
1896
|
+
if (leafer && leafer.viewReady)
|
|
1897
|
+
leafer.renderer.ignore = value;
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1900
|
+
const { get: get$2, scale, copy: copy$1 } = MatrixHelper;
|
|
1901
|
+
const { ceil, abs: abs$1 } = Math;
|
|
1902
|
+
function createPattern(ui, paint, pixelRatio) {
|
|
1903
|
+
let { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
|
|
1904
|
+
const id = scaleX + '-' + scaleY;
|
|
1905
|
+
if (paint.patternId !== id && !ui.destroyed) {
|
|
1906
|
+
scaleX = abs$1(scaleX);
|
|
1907
|
+
scaleY = abs$1(scaleY);
|
|
1908
|
+
const { image, data } = paint;
|
|
1909
|
+
let imageScale, imageMatrix, { width, height, scaleX: sx, scaleY: sy, opacity, transform, repeat } = data;
|
|
1910
|
+
if (sx) {
|
|
1911
|
+
imageMatrix = get$2();
|
|
1912
|
+
copy$1(imageMatrix, transform);
|
|
1913
|
+
scale(imageMatrix, 1 / sx, 1 / sy);
|
|
1914
|
+
scaleX *= sx;
|
|
1915
|
+
scaleY *= sy;
|
|
1916
|
+
}
|
|
1917
|
+
scaleX *= pixelRatio;
|
|
1918
|
+
scaleY *= pixelRatio;
|
|
1919
|
+
width *= scaleX;
|
|
1920
|
+
height *= scaleY;
|
|
1921
|
+
const size = width * height;
|
|
1922
|
+
if (!repeat) {
|
|
1923
|
+
if (size > Platform.image.maxCacheSize)
|
|
1924
|
+
return false;
|
|
1925
|
+
}
|
|
1926
|
+
let maxSize = Platform.image.maxPatternSize;
|
|
1927
|
+
if (!image.isSVG) {
|
|
1928
|
+
const imageSize = image.width * image.height;
|
|
1929
|
+
if (maxSize > imageSize)
|
|
1930
|
+
maxSize = imageSize;
|
|
1931
|
+
}
|
|
1932
|
+
if (size > maxSize)
|
|
1933
|
+
imageScale = Math.sqrt(size / maxSize);
|
|
1934
|
+
if (imageScale) {
|
|
1935
|
+
scaleX /= imageScale;
|
|
1936
|
+
scaleY /= imageScale;
|
|
1937
|
+
width /= imageScale;
|
|
1938
|
+
height /= imageScale;
|
|
1939
|
+
}
|
|
1940
|
+
if (sx) {
|
|
1941
|
+
scaleX /= sx;
|
|
1942
|
+
scaleY /= sy;
|
|
1831
1943
|
}
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1944
|
+
if (transform || scaleX !== 1 || scaleY !== 1) {
|
|
1945
|
+
if (!imageMatrix) {
|
|
1946
|
+
imageMatrix = get$2();
|
|
1947
|
+
if (transform)
|
|
1948
|
+
copy$1(imageMatrix, transform);
|
|
1949
|
+
}
|
|
1950
|
+
scale(imageMatrix, 1 / scaleX, 1 / scaleY);
|
|
1951
|
+
}
|
|
1952
|
+
const canvas = image.getCanvas(ceil(width) || 1, ceil(height) || 1, opacity);
|
|
1953
|
+
const pattern = image.getPattern(canvas, repeat || (Platform.origin.noRepeat || 'no-repeat'), imageMatrix, paint);
|
|
1954
|
+
paint.style = pattern;
|
|
1955
|
+
paint.patternId = id;
|
|
1956
|
+
return true;
|
|
1841
1957
|
}
|
|
1842
1958
|
else {
|
|
1843
|
-
|
|
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;
|
|
1866
|
-
}
|
|
1959
|
+
return false;
|
|
1867
1960
|
}
|
|
1868
1961
|
}
|
|
1869
1962
|
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
}
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1963
|
+
/******************************************************************************
|
|
1964
|
+
Copyright (c) Microsoft Corporation.
|
|
1965
|
+
|
|
1966
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
1967
|
+
purpose with or without fee is hereby granted.
|
|
1968
|
+
|
|
1969
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
1970
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
1971
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
1972
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
1973
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
1974
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
1975
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
1976
|
+
***************************************************************************** */
|
|
1977
|
+
/* global Reflect, Promise, SuppressedError, Symbol */
|
|
1978
|
+
|
|
1979
|
+
|
|
1980
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
1981
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
1982
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
1983
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
1984
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
1985
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
1986
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
1987
|
+
});
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
1991
|
+
var e = new Error(message);
|
|
1992
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
1993
|
+
};
|
|
1994
|
+
|
|
1995
|
+
const { abs } = Math;
|
|
1996
|
+
function checkImage(ui, canvas, paint, allowPaint) {
|
|
1997
|
+
const { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
|
|
1998
|
+
if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
|
|
1999
|
+
return false;
|
|
1896
2000
|
}
|
|
1897
2001
|
else {
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
2002
|
+
const { data } = paint;
|
|
2003
|
+
if (allowPaint) {
|
|
2004
|
+
if (!data.repeat) {
|
|
2005
|
+
let { width, height } = data;
|
|
2006
|
+
width *= abs(scaleX) * canvas.pixelRatio;
|
|
2007
|
+
height *= abs(scaleY) * canvas.pixelRatio;
|
|
2008
|
+
if (data.scaleX) {
|
|
2009
|
+
width *= data.scaleX;
|
|
2010
|
+
height *= data.scaleY;
|
|
2011
|
+
}
|
|
2012
|
+
allowPaint = width * height > Platform.image.maxCacheSize;
|
|
2013
|
+
}
|
|
2014
|
+
else {
|
|
2015
|
+
allowPaint = false;
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
if (allowPaint) {
|
|
2019
|
+
canvas.save();
|
|
2020
|
+
canvas.clip();
|
|
2021
|
+
if (paint.blendMode)
|
|
2022
|
+
canvas.blendMode = paint.blendMode;
|
|
2023
|
+
if (data.opacity)
|
|
2024
|
+
canvas.opacity *= data.opacity;
|
|
2025
|
+
if (data.transform)
|
|
2026
|
+
canvas.transform(data.transform);
|
|
2027
|
+
canvas.drawImage(paint.image.view, 0, 0, data.width, data.height);
|
|
2028
|
+
canvas.restore();
|
|
2029
|
+
return true;
|
|
1902
2030
|
}
|
|
1903
2031
|
else {
|
|
1904
|
-
|
|
2032
|
+
if (!paint.style || Export.running) {
|
|
2033
|
+
createPattern(ui, paint, canvas.pixelRatio);
|
|
2034
|
+
}
|
|
2035
|
+
else {
|
|
2036
|
+
if (!paint.patternTask) {
|
|
2037
|
+
paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
|
|
2038
|
+
paint.patternTask = null;
|
|
2039
|
+
if (canvas.bounds.hit(ui.__nowWorld))
|
|
2040
|
+
createPattern(ui, paint, canvas.pixelRatio);
|
|
2041
|
+
ui.forceUpdate('surface');
|
|
2042
|
+
}), 300);
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
return false;
|
|
1905
2046
|
}
|
|
1906
|
-
worldCanvas = canvas;
|
|
1907
2047
|
}
|
|
1908
|
-
ui.__renderShape(canvas, options);
|
|
1909
|
-
return {
|
|
1910
|
-
canvas, matrix, bounds,
|
|
1911
|
-
worldCanvas, shapeBounds, scaleX, scaleY
|
|
1912
|
-
};
|
|
1913
2048
|
}
|
|
1914
2049
|
|
|
2050
|
+
function recycleImage(attrName, data) {
|
|
2051
|
+
const paints = data['_' + attrName];
|
|
2052
|
+
if (paints instanceof Array) {
|
|
2053
|
+
let image, recycleMap, input, url;
|
|
2054
|
+
for (let i = 0, len = paints.length; i < len; i++) {
|
|
2055
|
+
image = paints[i].image;
|
|
2056
|
+
url = image && image.url;
|
|
2057
|
+
if (url) {
|
|
2058
|
+
if (!recycleMap)
|
|
2059
|
+
recycleMap = {};
|
|
2060
|
+
recycleMap[url] = true;
|
|
2061
|
+
ImageManager.recycle(image);
|
|
2062
|
+
if (image.loading) {
|
|
2063
|
+
if (!input) {
|
|
2064
|
+
input = (data.__input && data.__input[attrName]) || [];
|
|
2065
|
+
if (!(input instanceof Array))
|
|
2066
|
+
input = [input];
|
|
2067
|
+
}
|
|
2068
|
+
image.unload(paints[i].loadId, !input.some((item) => item.url === url));
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
return recycleMap;
|
|
2073
|
+
}
|
|
2074
|
+
return null;
|
|
2075
|
+
}
|
|
2076
|
+
|
|
2077
|
+
const PaintImageModule = {
|
|
2078
|
+
image,
|
|
2079
|
+
createData,
|
|
2080
|
+
fillOrFitMode,
|
|
2081
|
+
clipMode,
|
|
2082
|
+
repeatMode,
|
|
2083
|
+
createPattern,
|
|
2084
|
+
checkImage,
|
|
2085
|
+
recycleImage
|
|
2086
|
+
};
|
|
2087
|
+
|
|
1915
2088
|
const defaultFrom$2 = { x: 0.5, y: 0 };
|
|
1916
2089
|
const defaultTo$2 = { x: 0.5, y: 1 };
|
|
1917
2090
|
function linearGradient(paint, box) {
|
|
@@ -1929,7 +2102,7 @@ function applyStops(gradient, stops, opacity) {
|
|
|
1929
2102
|
let stop;
|
|
1930
2103
|
for (let i = 0, len = stops.length; i < len; i++) {
|
|
1931
2104
|
stop = stops[i];
|
|
1932
|
-
gradient.addColorStop(stop.offset, ColorConvert
|
|
2105
|
+
gradient.addColorStop(stop.offset, ColorConvert.string(stop.color, opacity));
|
|
1933
2106
|
}
|
|
1934
2107
|
}
|
|
1935
2108
|
|
|
@@ -1991,62 +2164,18 @@ function conicGradient(paint, box) {
|
|
|
1991
2164
|
return data;
|
|
1992
2165
|
}
|
|
1993
2166
|
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
if (!(paints instanceof Array))
|
|
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
|
-
});
|
|
2167
|
+
const PaintGradientModule = {
|
|
2168
|
+
linearGradient,
|
|
2169
|
+
radialGradient,
|
|
2170
|
+
conicGradient
|
|
2171
|
+
};
|
|
2043
2172
|
|
|
2044
2173
|
const { copy, toOffsetOutBounds: toOffsetOutBounds$1 } = BoundsHelper;
|
|
2045
2174
|
const tempBounds = {};
|
|
2046
2175
|
const offsetOutBounds$1 = {};
|
|
2047
|
-
function shadow(ui, current, shape
|
|
2176
|
+
function shadow(ui, current, shape) {
|
|
2048
2177
|
let copyBounds, spreadScale;
|
|
2049
|
-
const {
|
|
2178
|
+
const { __nowWorld: nowWorld, __layout } = ui;
|
|
2050
2179
|
const { shadow } = ui.__;
|
|
2051
2180
|
const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
|
|
2052
2181
|
const other = current.getSameCanvas();
|
|
@@ -2061,21 +2190,21 @@ function shadow(ui, current, shape, _options) {
|
|
|
2061
2190
|
other.restore();
|
|
2062
2191
|
other.save();
|
|
2063
2192
|
if (worldCanvas) {
|
|
2064
|
-
other.copyWorld(other, bounds,
|
|
2065
|
-
copyBounds =
|
|
2193
|
+
other.copyWorld(other, bounds, nowWorld, 'copy');
|
|
2194
|
+
copyBounds = nowWorld;
|
|
2066
2195
|
}
|
|
2067
|
-
worldCanvas ? other.copyWorld(worldCanvas,
|
|
2196
|
+
worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
|
|
2068
2197
|
}
|
|
2069
|
-
if (ui.
|
|
2070
|
-
current.copyWorldByReset(other, copyBounds,
|
|
2198
|
+
if (ui.__worldFlipped) {
|
|
2199
|
+
current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
|
|
2071
2200
|
}
|
|
2072
2201
|
else {
|
|
2073
2202
|
current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
|
|
2074
2203
|
}
|
|
2075
2204
|
if (end && index < end)
|
|
2076
|
-
other.
|
|
2205
|
+
other.clearWorld(copyBounds, true);
|
|
2077
2206
|
});
|
|
2078
|
-
other.recycle();
|
|
2207
|
+
other.recycle(copyBounds);
|
|
2079
2208
|
}
|
|
2080
2209
|
function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
|
|
2081
2210
|
const { bounds, shapeBounds } = shape;
|
|
@@ -2106,9 +2235,9 @@ function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
|
|
|
2106
2235
|
|
|
2107
2236
|
const { toOffsetOutBounds } = BoundsHelper;
|
|
2108
2237
|
const offsetOutBounds = {};
|
|
2109
|
-
function innerShadow(ui, current, shape
|
|
2238
|
+
function innerShadow(ui, current, shape) {
|
|
2110
2239
|
let copyBounds, spreadScale;
|
|
2111
|
-
const {
|
|
2240
|
+
const { __nowWorld: nowWorld, __layout: __layout } = ui;
|
|
2112
2241
|
const { innerShadow } = ui.__;
|
|
2113
2242
|
const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
|
|
2114
2243
|
const other = current.getSameCanvas();
|
|
@@ -2121,40 +2250,115 @@ function innerShadow(ui, current, shape, _options) {
|
|
|
2121
2250
|
drawWorldShadow(other, offsetOutBounds, spreadScale, shape);
|
|
2122
2251
|
other.restore();
|
|
2123
2252
|
if (worldCanvas) {
|
|
2124
|
-
other.copyWorld(other, bounds,
|
|
2125
|
-
other.copyWorld(worldCanvas,
|
|
2126
|
-
copyBounds =
|
|
2253
|
+
other.copyWorld(other, bounds, nowWorld, 'copy');
|
|
2254
|
+
other.copyWorld(worldCanvas, nowWorld, nowWorld, 'source-out');
|
|
2255
|
+
copyBounds = nowWorld;
|
|
2127
2256
|
}
|
|
2128
2257
|
else {
|
|
2129
2258
|
other.copyWorld(shape.canvas, shapeBounds, bounds, 'source-out');
|
|
2130
2259
|
copyBounds = bounds;
|
|
2131
2260
|
}
|
|
2132
2261
|
other.fillWorld(copyBounds, item.color, 'source-in');
|
|
2133
|
-
if (ui.
|
|
2134
|
-
current.copyWorldByReset(other, copyBounds,
|
|
2262
|
+
if (ui.__worldFlipped) {
|
|
2263
|
+
current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
|
|
2135
2264
|
}
|
|
2136
2265
|
else {
|
|
2137
2266
|
current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
|
|
2138
2267
|
}
|
|
2139
2268
|
if (end && index < end)
|
|
2140
|
-
other.
|
|
2269
|
+
other.clearWorld(copyBounds, true);
|
|
2141
2270
|
});
|
|
2142
|
-
other.recycle();
|
|
2271
|
+
other.recycle(copyBounds);
|
|
2143
2272
|
}
|
|
2144
2273
|
|
|
2145
2274
|
function blur(ui, current, origin) {
|
|
2146
2275
|
const { blur } = ui.__;
|
|
2147
|
-
origin.setWorldBlur(blur * ui.
|
|
2148
|
-
origin.copyWorldToInner(current, ui.
|
|
2276
|
+
origin.setWorldBlur(blur * ui.__nowWorld.a);
|
|
2277
|
+
origin.copyWorldToInner(current, ui.__nowWorld, ui.__layout.renderBounds);
|
|
2149
2278
|
origin.filter = 'none';
|
|
2150
2279
|
}
|
|
2151
2280
|
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
shadow
|
|
2157
|
-
|
|
2281
|
+
function backgroundBlur(_ui, _current, _shape) {
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
const EffectModule = {
|
|
2285
|
+
shadow,
|
|
2286
|
+
innerShadow,
|
|
2287
|
+
blur,
|
|
2288
|
+
backgroundBlur
|
|
2289
|
+
};
|
|
2290
|
+
|
|
2291
|
+
const { excludeRenderBounds } = LeafBoundsHelper;
|
|
2292
|
+
Group.prototype.__renderMask = function (canvas, options) {
|
|
2293
|
+
let child, maskCanvas, contentCanvas, maskOpacity, currentMask;
|
|
2294
|
+
const { children } = this;
|
|
2295
|
+
for (let i = 0, len = children.length; i < len; i++) {
|
|
2296
|
+
child = children[i];
|
|
2297
|
+
if (child.__.mask) {
|
|
2298
|
+
if (currentMask) {
|
|
2299
|
+
maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
|
|
2300
|
+
maskCanvas = contentCanvas = null;
|
|
2301
|
+
}
|
|
2302
|
+
if (child.__.maskType === 'path') {
|
|
2303
|
+
if (child.opacity < 1) {
|
|
2304
|
+
currentMask = 'opacity-path';
|
|
2305
|
+
maskOpacity = child.opacity;
|
|
2306
|
+
if (!contentCanvas)
|
|
2307
|
+
contentCanvas = getCanvas(canvas);
|
|
2308
|
+
}
|
|
2309
|
+
else {
|
|
2310
|
+
currentMask = 'path';
|
|
2311
|
+
canvas.save();
|
|
2312
|
+
}
|
|
2313
|
+
child.__clip(contentCanvas || canvas, options);
|
|
2314
|
+
}
|
|
2315
|
+
else {
|
|
2316
|
+
currentMask = 'alpha';
|
|
2317
|
+
if (!maskCanvas)
|
|
2318
|
+
maskCanvas = getCanvas(canvas);
|
|
2319
|
+
if (!contentCanvas)
|
|
2320
|
+
contentCanvas = getCanvas(canvas);
|
|
2321
|
+
child.__render(maskCanvas, options);
|
|
2322
|
+
}
|
|
2323
|
+
if (child.__.maskType !== 'clipping')
|
|
2324
|
+
continue;
|
|
2325
|
+
}
|
|
2326
|
+
if (excludeRenderBounds(child, options))
|
|
2327
|
+
continue;
|
|
2328
|
+
child.__render(contentCanvas || canvas, options);
|
|
2329
|
+
}
|
|
2330
|
+
maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
|
|
2331
|
+
};
|
|
2332
|
+
function maskEnd(leaf, maskMode, canvas, contentCanvas, maskCanvas, maskOpacity) {
|
|
2333
|
+
switch (maskMode) {
|
|
2334
|
+
case 'alpha':
|
|
2335
|
+
usePixelMask(leaf, canvas, contentCanvas, maskCanvas);
|
|
2336
|
+
break;
|
|
2337
|
+
case 'opacity-path':
|
|
2338
|
+
copyContent(leaf, canvas, contentCanvas, maskOpacity);
|
|
2339
|
+
break;
|
|
2340
|
+
case 'path':
|
|
2341
|
+
canvas.restore();
|
|
2342
|
+
}
|
|
2343
|
+
}
|
|
2344
|
+
function getCanvas(canvas) {
|
|
2345
|
+
return canvas.getSameCanvas(false, true);
|
|
2346
|
+
}
|
|
2347
|
+
function usePixelMask(leaf, canvas, content, mask) {
|
|
2348
|
+
const realBounds = leaf.__nowWorld;
|
|
2349
|
+
content.resetTransform();
|
|
2350
|
+
content.opacity = 1;
|
|
2351
|
+
content.useMask(mask, realBounds);
|
|
2352
|
+
mask.recycle(realBounds);
|
|
2353
|
+
copyContent(leaf, canvas, content, 1);
|
|
2354
|
+
}
|
|
2355
|
+
function copyContent(leaf, canvas, content, maskOpacity) {
|
|
2356
|
+
const realBounds = leaf.__nowWorld;
|
|
2357
|
+
canvas.resetTransform();
|
|
2358
|
+
canvas.opacity = maskOpacity;
|
|
2359
|
+
canvas.copyWorld(content, realBounds);
|
|
2360
|
+
content.recycle(realBounds);
|
|
2361
|
+
}
|
|
2158
2362
|
|
|
2159
2363
|
const money = '¥¥$€££¢¢';
|
|
2160
2364
|
const letter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
|
|
@@ -2268,7 +2472,7 @@ function getTextCase(char, textCase, firstChar) {
|
|
|
2268
2472
|
const { trimRight } = TextRowHelper;
|
|
2269
2473
|
const { Letter, Single, Before, After, Symbol, Break } = CharType;
|
|
2270
2474
|
let word, row, wordWidth, rowWidth, realWidth;
|
|
2271
|
-
let char, charWidth, charType, lastCharType, langBreak, afterBreak, paraStart;
|
|
2475
|
+
let char, charWidth, startCharSize, charSize, charType, lastCharType, langBreak, afterBreak, paraStart;
|
|
2272
2476
|
let textDrawData, rows = [], bounds;
|
|
2273
2477
|
function createRows(drawData, content, style) {
|
|
2274
2478
|
textDrawData = drawData;
|
|
@@ -2279,9 +2483,11 @@ function createRows(drawData, content, style) {
|
|
|
2279
2483
|
const { width, height } = bounds;
|
|
2280
2484
|
const charMode = width || height || __letterSpacing || (textCase !== 'none');
|
|
2281
2485
|
if (charMode) {
|
|
2486
|
+
const wrap = style.textWrap !== 'none';
|
|
2487
|
+
const breakAll = style.textWrap === 'break';
|
|
2282
2488
|
paraStart = true;
|
|
2283
2489
|
lastCharType = null;
|
|
2284
|
-
wordWidth = rowWidth = 0;
|
|
2490
|
+
startCharSize = charWidth = charSize = wordWidth = rowWidth = 0;
|
|
2285
2491
|
word = { data: [] }, row = { words: [] };
|
|
2286
2492
|
for (let i = 0, len = content.length; i < len; i++) {
|
|
2287
2493
|
char = content[i];
|
|
@@ -2297,21 +2503,31 @@ function createRows(drawData, content, style) {
|
|
|
2297
2503
|
if (charType === Letter && textCase !== 'none')
|
|
2298
2504
|
char = getTextCase(char, textCase, !wordWidth);
|
|
2299
2505
|
charWidth = canvas.measureText(char).width;
|
|
2300
|
-
if (__letterSpacing)
|
|
2506
|
+
if (__letterSpacing) {
|
|
2507
|
+
if (__letterSpacing < 0)
|
|
2508
|
+
charSize = charWidth;
|
|
2301
2509
|
charWidth += __letterSpacing;
|
|
2510
|
+
}
|
|
2302
2511
|
langBreak = (charType === Single && (lastCharType === Single || lastCharType === Letter)) || (lastCharType === Single && charType !== After);
|
|
2303
2512
|
afterBreak = ((charType === Before || charType === Single) && (lastCharType === Symbol || lastCharType === After));
|
|
2304
2513
|
realWidth = paraStart && paraIndent ? width - paraIndent : width;
|
|
2305
|
-
if (width && rowWidth + wordWidth + charWidth > realWidth) {
|
|
2306
|
-
if (
|
|
2307
|
-
afterBreak = charType === Letter && lastCharType == After;
|
|
2308
|
-
if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
|
|
2514
|
+
if (wrap && (width && rowWidth + wordWidth + charWidth > realWidth)) {
|
|
2515
|
+
if (breakAll) {
|
|
2309
2516
|
if (wordWidth)
|
|
2310
2517
|
addWord();
|
|
2311
2518
|
addRow();
|
|
2312
2519
|
}
|
|
2313
2520
|
else {
|
|
2314
|
-
|
|
2521
|
+
if (!afterBreak)
|
|
2522
|
+
afterBreak = charType === Letter && lastCharType == After;
|
|
2523
|
+
if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
|
|
2524
|
+
if (wordWidth)
|
|
2525
|
+
addWord();
|
|
2526
|
+
addRow();
|
|
2527
|
+
}
|
|
2528
|
+
else {
|
|
2529
|
+
addRow();
|
|
2530
|
+
}
|
|
2315
2531
|
}
|
|
2316
2532
|
}
|
|
2317
2533
|
if (char === ' ' && paraStart !== true && (rowWidth + wordWidth) === 0) ;
|
|
@@ -2348,6 +2564,8 @@ function createRows(drawData, content, style) {
|
|
|
2348
2564
|
}
|
|
2349
2565
|
}
|
|
2350
2566
|
function addChar(char, width) {
|
|
2567
|
+
if (charSize && !startCharSize)
|
|
2568
|
+
startCharSize = charSize;
|
|
2351
2569
|
word.data.push({ char, width });
|
|
2352
2570
|
wordWidth += width;
|
|
2353
2571
|
}
|
|
@@ -2364,6 +2582,11 @@ function addRow() {
|
|
|
2364
2582
|
row.paraStart = true;
|
|
2365
2583
|
paraStart = false;
|
|
2366
2584
|
}
|
|
2585
|
+
if (charSize) {
|
|
2586
|
+
row.startCharSize = startCharSize;
|
|
2587
|
+
row.endCharSize = charSize;
|
|
2588
|
+
startCharSize = 0;
|
|
2589
|
+
}
|
|
2367
2590
|
row.width = rowWidth;
|
|
2368
2591
|
if (bounds.width)
|
|
2369
2592
|
trimRight(row);
|
|
@@ -2374,7 +2597,7 @@ function addRow() {
|
|
|
2374
2597
|
|
|
2375
2598
|
const CharMode = 0;
|
|
2376
2599
|
const WordMode = 1;
|
|
2377
|
-
const
|
|
2600
|
+
const TextMode = 2;
|
|
2378
2601
|
function layoutChar(drawData, style, width, _height) {
|
|
2379
2602
|
const { rows } = drawData;
|
|
2380
2603
|
const { textAlign, paraIndent, letterSpacing } = style;
|
|
@@ -2383,15 +2606,12 @@ function layoutChar(drawData, style, width, _height) {
|
|
|
2383
2606
|
if (row.words) {
|
|
2384
2607
|
indentWidth = paraIndent && row.paraStart ? paraIndent : 0;
|
|
2385
2608
|
addWordWidth = (width && textAlign === 'justify' && row.words.length > 1) ? (width - row.width - indentWidth) / (row.words.length - 1) : 0;
|
|
2386
|
-
mode = (letterSpacing || row.isOverflow) ? CharMode : (addWordWidth > 0.01 ? WordMode :
|
|
2387
|
-
if (
|
|
2388
|
-
row.
|
|
2609
|
+
mode = (letterSpacing || row.isOverflow) ? CharMode : (addWordWidth > 0.01 ? WordMode : TextMode);
|
|
2610
|
+
if (row.isOverflow && !letterSpacing)
|
|
2611
|
+
row.textMode = true;
|
|
2612
|
+
if (mode === TextMode) {
|
|
2389
2613
|
row.x += indentWidth;
|
|
2390
|
-
row
|
|
2391
|
-
word.data.forEach(char => {
|
|
2392
|
-
row.text += char.char;
|
|
2393
|
-
});
|
|
2394
|
-
});
|
|
2614
|
+
toTextChar$1(row);
|
|
2395
2615
|
}
|
|
2396
2616
|
else {
|
|
2397
2617
|
row.x += indentWidth;
|
|
@@ -2417,6 +2637,14 @@ function layoutChar(drawData, style, width, _height) {
|
|
|
2417
2637
|
}
|
|
2418
2638
|
});
|
|
2419
2639
|
}
|
|
2640
|
+
function toTextChar$1(row) {
|
|
2641
|
+
row.text = '';
|
|
2642
|
+
row.words.forEach(word => {
|
|
2643
|
+
word.data.forEach(char => {
|
|
2644
|
+
row.text += char.char;
|
|
2645
|
+
});
|
|
2646
|
+
});
|
|
2647
|
+
}
|
|
2420
2648
|
function toWordChar(data, charX, wordChar) {
|
|
2421
2649
|
data.forEach(char => {
|
|
2422
2650
|
wordChar.char += char.char;
|
|
@@ -2437,10 +2665,10 @@ function toChar(data, charX, rowData) {
|
|
|
2437
2665
|
|
|
2438
2666
|
function layoutText(drawData, style) {
|
|
2439
2667
|
const { rows, bounds } = drawData;
|
|
2440
|
-
const { __lineHeight, __baseLine, textAlign, verticalAlign, paraSpacing
|
|
2668
|
+
const { __lineHeight, __baseLine, __letterSpacing, __clipText, textAlign, verticalAlign, paraSpacing } = style;
|
|
2441
2669
|
let { x, y, width, height } = bounds, realHeight = __lineHeight * rows.length + (paraSpacing ? paraSpacing * (drawData.paraNumber - 1) : 0);
|
|
2442
2670
|
let starY = __baseLine;
|
|
2443
|
-
if (
|
|
2671
|
+
if (__clipText && realHeight > height) {
|
|
2444
2672
|
realHeight = Math.max(height, __lineHeight);
|
|
2445
2673
|
drawData.overflow = rows.length;
|
|
2446
2674
|
}
|
|
@@ -2454,7 +2682,7 @@ function layoutText(drawData, style) {
|
|
|
2454
2682
|
}
|
|
2455
2683
|
}
|
|
2456
2684
|
starY += y;
|
|
2457
|
-
let row;
|
|
2685
|
+
let row, rowX, rowWidth;
|
|
2458
2686
|
for (let i = 0, len = rows.length; i < len; i++) {
|
|
2459
2687
|
row = rows[i];
|
|
2460
2688
|
row.x = x;
|
|
@@ -2473,53 +2701,74 @@ function layoutText(drawData, style) {
|
|
|
2473
2701
|
row.isOverflow = true;
|
|
2474
2702
|
drawData.overflow = i + 1;
|
|
2475
2703
|
}
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
if (
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2704
|
+
rowX = row.x;
|
|
2705
|
+
rowWidth = row.width;
|
|
2706
|
+
if (__letterSpacing < 0) {
|
|
2707
|
+
if (row.width < 0) {
|
|
2708
|
+
rowWidth = -row.width + style.fontSize + __letterSpacing;
|
|
2709
|
+
rowX -= rowWidth;
|
|
2710
|
+
rowWidth += style.fontSize;
|
|
2711
|
+
}
|
|
2712
|
+
else {
|
|
2713
|
+
rowWidth -= __letterSpacing;
|
|
2714
|
+
}
|
|
2483
2715
|
}
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2716
|
+
if (rowX < bounds.x)
|
|
2717
|
+
bounds.x = rowX;
|
|
2718
|
+
if (rowWidth > bounds.width)
|
|
2719
|
+
bounds.width = rowWidth;
|
|
2720
|
+
if (__clipText && width && width < rowWidth) {
|
|
2721
|
+
row.isOverflow = true;
|
|
2722
|
+
if (!drawData.overflow)
|
|
2723
|
+
drawData.overflow = rows.length;
|
|
2489
2724
|
}
|
|
2490
2725
|
}
|
|
2491
2726
|
bounds.y = y;
|
|
2492
2727
|
bounds.height = realHeight;
|
|
2493
2728
|
}
|
|
2494
2729
|
|
|
2495
|
-
function clipText(drawData,
|
|
2730
|
+
function clipText(drawData, style) {
|
|
2496
2731
|
const { rows, overflow } = drawData;
|
|
2732
|
+
let { textOverflow } = style;
|
|
2497
2733
|
rows.splice(overflow);
|
|
2498
2734
|
if (textOverflow !== 'hide') {
|
|
2499
2735
|
if (textOverflow === 'ellipsis')
|
|
2500
2736
|
textOverflow = '...';
|
|
2737
|
+
let char, charRight;
|
|
2501
2738
|
const ellipsisWidth = Platform.canvas.measureText(textOverflow).width;
|
|
2502
|
-
const
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2739
|
+
const right = style.x + style.width - ellipsisWidth;
|
|
2740
|
+
const list = style.textWrap === 'none' ? rows : [rows[overflow - 1]];
|
|
2741
|
+
list.forEach(row => {
|
|
2742
|
+
if (row.isOverflow && row.data) {
|
|
2743
|
+
let end = row.data.length - 1;
|
|
2744
|
+
for (let i = end; i > -1; i--) {
|
|
2745
|
+
char = row.data[i];
|
|
2746
|
+
charRight = char.x + char.width;
|
|
2747
|
+
if (i === end && charRight < right) {
|
|
2748
|
+
break;
|
|
2749
|
+
}
|
|
2750
|
+
else if (charRight < right && char.char !== ' ') {
|
|
2751
|
+
row.data.splice(i + 1);
|
|
2752
|
+
row.width -= char.width;
|
|
2753
|
+
break;
|
|
2754
|
+
}
|
|
2755
|
+
row.width -= char.width;
|
|
2756
|
+
}
|
|
2757
|
+
row.width += ellipsisWidth;
|
|
2758
|
+
row.data.push({ char: textOverflow, x: charRight });
|
|
2759
|
+
if (row.textMode)
|
|
2760
|
+
toTextChar(row);
|
|
2516
2761
|
}
|
|
2517
|
-
|
|
2518
|
-
}
|
|
2519
|
-
row.width += ellipsisWidth;
|
|
2520
|
-
row.data.push({ char: textOverflow, x: charRight });
|
|
2762
|
+
});
|
|
2521
2763
|
}
|
|
2522
2764
|
}
|
|
2765
|
+
function toTextChar(row) {
|
|
2766
|
+
row.text = '';
|
|
2767
|
+
row.data.forEach(char => {
|
|
2768
|
+
row.text += char.char;
|
|
2769
|
+
});
|
|
2770
|
+
row.data = null;
|
|
2771
|
+
}
|
|
2523
2772
|
|
|
2524
2773
|
function decorationText(drawData, style) {
|
|
2525
2774
|
const { fontSize } = style;
|
|
@@ -2533,101 +2782,190 @@ function decorationText(drawData, style) {
|
|
|
2533
2782
|
}
|
|
2534
2783
|
}
|
|
2535
2784
|
|
|
2536
|
-
const
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
if (
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2785
|
+
const { top, right, bottom, left } = Direction4;
|
|
2786
|
+
function getDrawData(content, style) {
|
|
2787
|
+
if (typeof content !== 'string')
|
|
2788
|
+
content = String(content);
|
|
2789
|
+
let x = 0, y = 0;
|
|
2790
|
+
let width = style.__getInput('width') || 0;
|
|
2791
|
+
let height = style.__getInput('height') || 0;
|
|
2792
|
+
const { textDecoration, __font, __padding: padding } = style;
|
|
2793
|
+
if (padding) {
|
|
2794
|
+
if (width) {
|
|
2795
|
+
x = padding[left];
|
|
2796
|
+
width -= (padding[right] + padding[left]);
|
|
2797
|
+
}
|
|
2798
|
+
if (height) {
|
|
2799
|
+
y = padding[top];
|
|
2800
|
+
height -= (padding[top] + padding[bottom]);
|
|
2801
|
+
}
|
|
2802
|
+
}
|
|
2803
|
+
const drawData = {
|
|
2804
|
+
bounds: { x, y, width, height },
|
|
2805
|
+
rows: [],
|
|
2806
|
+
paraNumber: 0,
|
|
2807
|
+
font: Platform.canvas.font = __font
|
|
2808
|
+
};
|
|
2809
|
+
createRows(drawData, content, style);
|
|
2810
|
+
if (padding)
|
|
2811
|
+
padAutoText(padding, drawData, style, width, height);
|
|
2812
|
+
layoutText(drawData, style);
|
|
2813
|
+
layoutChar(drawData, style, width);
|
|
2814
|
+
if (drawData.overflow)
|
|
2815
|
+
clipText(drawData, style);
|
|
2816
|
+
if (textDecoration !== 'none')
|
|
2817
|
+
decorationText(drawData, style);
|
|
2818
|
+
return drawData;
|
|
2819
|
+
}
|
|
2820
|
+
function padAutoText(padding, drawData, style, width, height) {
|
|
2821
|
+
if (!width) {
|
|
2822
|
+
switch (style.textAlign) {
|
|
2823
|
+
case 'left':
|
|
2824
|
+
offsetText(drawData, 'x', padding[left]);
|
|
2825
|
+
break;
|
|
2826
|
+
case 'right':
|
|
2827
|
+
offsetText(drawData, 'x', -padding[right]);
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
if (!height) {
|
|
2831
|
+
switch (style.verticalAlign) {
|
|
2832
|
+
case 'top':
|
|
2833
|
+
offsetText(drawData, 'y', padding[top]);
|
|
2834
|
+
break;
|
|
2835
|
+
case 'bottom':
|
|
2836
|
+
offsetText(drawData, 'y', -padding[bottom]);
|
|
2555
2837
|
}
|
|
2556
|
-
const drawData = {
|
|
2557
|
-
bounds: { x, y, width, height },
|
|
2558
|
-
rows: [],
|
|
2559
|
-
paraNumber: 0,
|
|
2560
|
-
font: Platform.canvas.font = __font
|
|
2561
|
-
};
|
|
2562
|
-
createRows(drawData, content, style);
|
|
2563
|
-
layoutText(drawData, style);
|
|
2564
|
-
layoutChar(drawData, style, width);
|
|
2565
|
-
if (drawData.overflow)
|
|
2566
|
-
clipText(drawData, textOverflow);
|
|
2567
|
-
if (textDecoration !== 'none')
|
|
2568
|
-
decorationText(drawData, style);
|
|
2569
|
-
return drawData;
|
|
2570
2838
|
}
|
|
2839
|
+
}
|
|
2840
|
+
function offsetText(drawData, attrName, value) {
|
|
2841
|
+
const { bounds, rows } = drawData;
|
|
2842
|
+
bounds[attrName] += value;
|
|
2843
|
+
for (let i = 0; i < rows.length; i++)
|
|
2844
|
+
rows[i][attrName] += value;
|
|
2845
|
+
}
|
|
2846
|
+
|
|
2847
|
+
const TextConvertModule = {
|
|
2848
|
+
getDrawData
|
|
2571
2849
|
};
|
|
2572
2850
|
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2851
|
+
function string(color, opacity) {
|
|
2852
|
+
if (typeof color === 'string')
|
|
2853
|
+
return color;
|
|
2854
|
+
let a = color.a === undefined ? 1 : color.a;
|
|
2855
|
+
if (opacity)
|
|
2856
|
+
a *= opacity;
|
|
2857
|
+
const rgb = color.r + ',' + color.g + ',' + color.b;
|
|
2858
|
+
return a === 1 ? 'rgb(' + rgb + ')' : 'rgba(' + rgb + ',' + a + ')';
|
|
2859
|
+
}
|
|
2860
|
+
|
|
2861
|
+
const ColorConvertModule = {
|
|
2862
|
+
string
|
|
2583
2863
|
};
|
|
2584
2864
|
|
|
2585
|
-
const
|
|
2865
|
+
const { setPoint, addPoint, toBounds } = TwoPointBoundsHelper;
|
|
2866
|
+
function getTrimBounds(canvas) {
|
|
2867
|
+
const { width, height } = canvas.view;
|
|
2868
|
+
const { data } = canvas.context.getImageData(0, 0, width, height);
|
|
2869
|
+
let x, y, pointBounds, index = 0;
|
|
2870
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
2871
|
+
if (data[i + 3] !== 0) {
|
|
2872
|
+
x = index % width;
|
|
2873
|
+
y = (index - x) / width;
|
|
2874
|
+
pointBounds ? addPoint(pointBounds, x, y) : setPoint(pointBounds = {}, x, y);
|
|
2875
|
+
}
|
|
2876
|
+
index++;
|
|
2877
|
+
}
|
|
2878
|
+
const bounds = new Bounds();
|
|
2879
|
+
toBounds(pointBounds, bounds);
|
|
2880
|
+
return bounds.scale(1 / canvas.pixelRatio).ceil();
|
|
2881
|
+
}
|
|
2882
|
+
|
|
2883
|
+
const ExportModule = {
|
|
2586
2884
|
export(leaf, filename, options) {
|
|
2885
|
+
this.running = true;
|
|
2587
2886
|
return addTask((success) => new Promise((resolve) => {
|
|
2887
|
+
const over = (result) => {
|
|
2888
|
+
success(result);
|
|
2889
|
+
resolve();
|
|
2890
|
+
this.running = false;
|
|
2891
|
+
};
|
|
2588
2892
|
const { leafer } = leaf;
|
|
2589
2893
|
if (leafer) {
|
|
2590
2894
|
leafer.waitViewCompleted(() => __awaiter(this, void 0, void 0, function* () {
|
|
2591
|
-
|
|
2592
|
-
let
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2895
|
+
options = FileHelper.getExportOptions(options);
|
|
2896
|
+
let renderBounds, trimBounds, scaleX = 1, scaleY = 1;
|
|
2897
|
+
const { worldTransform, isLeafer, isFrame } = leaf;
|
|
2898
|
+
const { slice, trim, onCanvas } = options;
|
|
2899
|
+
const scale = options.scale || 1;
|
|
2900
|
+
const pixelRatio = options.pixelRatio || 1;
|
|
2901
|
+
const screenshot = options.screenshot || leaf.isApp;
|
|
2902
|
+
const fill = (isLeafer && screenshot) ? (options.fill === undefined ? leaf.fill : options.fill) : options.fill;
|
|
2903
|
+
const needFill = FileHelper.isOpaqueImage(filename) || fill, matrix = new Matrix();
|
|
2904
|
+
if (screenshot) {
|
|
2905
|
+
renderBounds = screenshot === true ? (isLeafer ? leafer.canvas.bounds : leaf.worldRenderBounds) : screenshot;
|
|
2598
2906
|
}
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2907
|
+
else {
|
|
2908
|
+
let relative = options.relative || (isLeafer ? 'inner' : 'local');
|
|
2909
|
+
scaleX = worldTransform.scaleX;
|
|
2910
|
+
scaleY = worldTransform.scaleY;
|
|
2911
|
+
switch (relative) {
|
|
2912
|
+
case 'inner':
|
|
2913
|
+
matrix.set(worldTransform);
|
|
2914
|
+
break;
|
|
2915
|
+
case 'local':
|
|
2916
|
+
matrix.set(worldTransform).divide(leaf.localTransform);
|
|
2917
|
+
scaleX /= leaf.scaleX;
|
|
2918
|
+
scaleY /= leaf.scaleY;
|
|
2919
|
+
break;
|
|
2920
|
+
case 'world':
|
|
2921
|
+
scaleX = 1;
|
|
2922
|
+
scaleY = 1;
|
|
2923
|
+
break;
|
|
2924
|
+
case 'page':
|
|
2925
|
+
relative = leaf.leafer;
|
|
2926
|
+
default:
|
|
2927
|
+
matrix.set(worldTransform).divide(leaf.getTransform(relative));
|
|
2928
|
+
const l = relative.worldTransform;
|
|
2929
|
+
scaleX /= scaleX / l.scaleX;
|
|
2930
|
+
scaleY /= scaleY / l.scaleY;
|
|
2931
|
+
}
|
|
2932
|
+
renderBounds = leaf.getBounds('render', relative);
|
|
2611
2933
|
}
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2934
|
+
const { x, y, width, height } = new Bounds(renderBounds).scale(scale);
|
|
2935
|
+
let canvas = Creator.canvas({ width: Math.round(width), height: Math.round(height), pixelRatio });
|
|
2936
|
+
const renderOptions = { matrix: matrix.scale(1 / scale).invert().translate(-x, -y).withScale(1 / scaleX * scale, 1 / scaleY * scale) };
|
|
2937
|
+
if (slice) {
|
|
2938
|
+
leaf = leafer;
|
|
2939
|
+
renderOptions.bounds = canvas.bounds;
|
|
2615
2940
|
}
|
|
2616
|
-
|
|
2617
|
-
|
|
2941
|
+
canvas.save();
|
|
2942
|
+
if (isFrame && fill !== undefined) {
|
|
2943
|
+
const oldFill = leaf.get('fill');
|
|
2944
|
+
leaf.fill = '';
|
|
2945
|
+
leaf.__render(canvas, renderOptions);
|
|
2946
|
+
leaf.fill = oldFill;
|
|
2618
2947
|
}
|
|
2619
2948
|
else {
|
|
2620
|
-
|
|
2949
|
+
leaf.__render(canvas, renderOptions);
|
|
2621
2950
|
}
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
canvas
|
|
2951
|
+
canvas.restore();
|
|
2952
|
+
if (trim) {
|
|
2953
|
+
trimBounds = getTrimBounds(canvas);
|
|
2954
|
+
const old = canvas, { width, height } = trimBounds;
|
|
2955
|
+
const config = { x: 0, y: 0, width, height, pixelRatio };
|
|
2956
|
+
canvas = Creator.canvas(config);
|
|
2957
|
+
canvas.copyWorld(old, trimBounds, config);
|
|
2958
|
+
}
|
|
2959
|
+
if (needFill)
|
|
2960
|
+
canvas.fillWorld(canvas.bounds, fill || '#FFFFFF', 'destination-over');
|
|
2961
|
+
if (onCanvas)
|
|
2962
|
+
onCanvas(canvas);
|
|
2963
|
+
const data = filename === 'canvas' ? canvas : yield canvas.export(filename, options);
|
|
2964
|
+
over({ data, width: canvas.pixelWidth, height: canvas.pixelHeight, renderBounds, trimBounds });
|
|
2626
2965
|
}));
|
|
2627
2966
|
}
|
|
2628
2967
|
else {
|
|
2629
|
-
|
|
2630
|
-
resolve();
|
|
2968
|
+
over({ data: false });
|
|
2631
2969
|
}
|
|
2632
2970
|
}));
|
|
2633
2971
|
}
|
|
@@ -2641,12 +2979,63 @@ function addTask(task) {
|
|
|
2641
2979
|
});
|
|
2642
2980
|
}
|
|
2643
2981
|
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2982
|
+
const canvas = LeaferCanvasBase.prototype;
|
|
2983
|
+
const debug = Debug.get('@leafer-ui/export');
|
|
2984
|
+
canvas.export = function (filename, options) {
|
|
2985
|
+
const { quality, blob } = FileHelper.getExportOptions(options);
|
|
2986
|
+
if (filename.includes('.')) {
|
|
2987
|
+
return this.saveAs(filename, quality);
|
|
2988
|
+
}
|
|
2989
|
+
else if (blob) {
|
|
2990
|
+
return this.toBlob(filename, quality);
|
|
2991
|
+
}
|
|
2992
|
+
else {
|
|
2993
|
+
return this.toDataURL(filename, quality);
|
|
2994
|
+
}
|
|
2995
|
+
};
|
|
2996
|
+
canvas.toBlob = function (type, quality) {
|
|
2997
|
+
return new Promise((resolve) => {
|
|
2998
|
+
Platform.origin.canvasToBolb(this.view, type, quality).then((blob) => {
|
|
2999
|
+
resolve(blob);
|
|
3000
|
+
}).catch((e) => {
|
|
3001
|
+
debug.error(e);
|
|
3002
|
+
resolve(null);
|
|
3003
|
+
});
|
|
3004
|
+
});
|
|
3005
|
+
};
|
|
3006
|
+
canvas.toDataURL = function (type, quality) {
|
|
3007
|
+
return Platform.origin.canvasToDataURL(this.view, type, quality);
|
|
3008
|
+
};
|
|
3009
|
+
canvas.saveAs = function (filename, quality) {
|
|
3010
|
+
return new Promise((resolve) => {
|
|
3011
|
+
Platform.origin.canvasSaveAs(this.view, filename, quality).then(() => {
|
|
3012
|
+
resolve(true);
|
|
3013
|
+
}).catch((e) => {
|
|
3014
|
+
debug.error(e);
|
|
3015
|
+
resolve(false);
|
|
3016
|
+
});
|
|
3017
|
+
});
|
|
3018
|
+
};
|
|
3019
|
+
|
|
3020
|
+
Object.assign(TextConvert, TextConvertModule);
|
|
3021
|
+
Object.assign(ColorConvert, ColorConvertModule);
|
|
3022
|
+
Object.assign(Paint, PaintModule);
|
|
3023
|
+
Object.assign(PaintImage, PaintImageModule);
|
|
3024
|
+
Object.assign(PaintGradient, PaintGradientModule);
|
|
3025
|
+
Object.assign(Effect, EffectModule);
|
|
3026
|
+
Object.assign(Export, ExportModule);
|
|
2649
3027
|
|
|
3028
|
+
Object.assign(Creator, {
|
|
3029
|
+
interaction: (target, canvas, selector, options) => new Interaction(target, canvas, selector, options),
|
|
3030
|
+
hitCanvas: (options, manager) => new LeaferCanvas(options, manager),
|
|
3031
|
+
hitCanvasManager: () => new HitCanvasManager()
|
|
3032
|
+
});
|
|
2650
3033
|
useCanvas();
|
|
3034
|
+
window.addEventListener('unload', () => {
|
|
3035
|
+
const { list } = Leafer;
|
|
3036
|
+
list.forEach(leafer => leafer.destroy(true));
|
|
3037
|
+
list.destroy();
|
|
3038
|
+
ImageManager.destroy();
|
|
3039
|
+
});
|
|
2651
3040
|
|
|
2652
3041
|
export { Interaction, Layouter, LeaferCanvas, Renderer, Selector, Watcher, useCanvas };
|