@leafer-ui/node 1.0.0-rc.3 → 1.0.0-rc.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/node.cjs +1396 -927
- package/dist/node.esm.js +1397 -928
- package/dist/node.esm.min.js +1 -1
- package/dist/node.min.cjs +1 -1
- package/package.json +12 -8
- package/src/index.ts +13 -0
- package/types/index.d.ts +1 -0
package/dist/node.esm.js
CHANGED
|
@@ -1,8 +1,109 @@
|
|
|
1
|
-
import { LeafList, DataHelper, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, Bounds, LeafBoundsHelper,
|
|
1
|
+
import { LeaferCanvasBase, Platform, canvasPatch, Creator, LeaferImage, FileHelper, LeafList, DataHelper, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, Bounds, LeafBoundsHelper, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, AnimateEvent, ResizeEvent, BoundsHelper, Answer, MatrixHelper, AlignHelper, ImageEvent, AroundHelper, PointHelper, Direction4, TwoPointBoundsHelper, TaskProcessor, Matrix } from '@leafer/core';
|
|
2
2
|
export * from '@leafer/core';
|
|
3
3
|
export { LeaferImage } from '@leafer/core';
|
|
4
|
-
import {
|
|
4
|
+
import { writeFileSync } from 'fs';
|
|
5
|
+
import { InteractionBase, HitCanvasManager } from '@leafer-ui/core';
|
|
5
6
|
export * from '@leafer-ui/core';
|
|
7
|
+
import { PaintImage, ColorConvert, PaintGradient, Export, Group, TextConvert, Paint, Effect } from '@leafer-ui/draw';
|
|
8
|
+
|
|
9
|
+
/******************************************************************************
|
|
10
|
+
Copyright (c) Microsoft Corporation.
|
|
11
|
+
|
|
12
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
13
|
+
purpose with or without fee is hereby granted.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
16
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
17
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
18
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
19
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
20
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
21
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
22
|
+
***************************************************************************** */
|
|
23
|
+
/* global Reflect, Promise, SuppressedError, Symbol */
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
27
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
28
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
29
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
30
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
31
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
32
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
37
|
+
var e = new Error(message);
|
|
38
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
class LeaferCanvas extends LeaferCanvasBase {
|
|
42
|
+
get allowBackgroundColor() { return true; }
|
|
43
|
+
init() {
|
|
44
|
+
this.__createView();
|
|
45
|
+
this.__createContext();
|
|
46
|
+
this.resize(this.config);
|
|
47
|
+
if (Platform.roundRectPatch) {
|
|
48
|
+
this.context.__proto__.roundRect = null;
|
|
49
|
+
canvasPatch(this.context.__proto__);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
__createView() {
|
|
53
|
+
this.view = Platform.origin.createCanvas(1, 1);
|
|
54
|
+
}
|
|
55
|
+
updateViewSize() {
|
|
56
|
+
const { width, height, pixelRatio } = this;
|
|
57
|
+
this.view.width = Math.ceil(width * pixelRatio);
|
|
58
|
+
this.view.height = Math.ceil(height * pixelRatio);
|
|
59
|
+
this.clientBounds = this.bounds;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const { mineType, fileType } = FileHelper;
|
|
64
|
+
Object.assign(Creator, {
|
|
65
|
+
canvas: (options, manager) => new LeaferCanvas(options, manager),
|
|
66
|
+
image: (options) => new LeaferImage(options)
|
|
67
|
+
});
|
|
68
|
+
function useCanvas(canvasType, power) {
|
|
69
|
+
Platform.canvasType = canvasType;
|
|
70
|
+
if (!Platform.origin) {
|
|
71
|
+
if (canvasType === 'skia') {
|
|
72
|
+
const { Canvas, loadImage } = power;
|
|
73
|
+
Platform.origin = {
|
|
74
|
+
createCanvas: (width, height, format) => new Canvas(width, height, format),
|
|
75
|
+
canvasToDataURL: (canvas, type, quality) => canvas.toDataURLSync(type, { quality }),
|
|
76
|
+
canvasToBolb: (canvas, type, quality) => canvas.toBuffer(type, { quality }),
|
|
77
|
+
canvasSaveAs: (canvas, filename, quality) => canvas.saveAs(filename, { quality }),
|
|
78
|
+
download(_url, _filename) { return undefined; },
|
|
79
|
+
loadImage(src) { return loadImage(Platform.image.getRealURL(src)); }
|
|
80
|
+
};
|
|
81
|
+
Platform.roundRectPatch = true;
|
|
82
|
+
}
|
|
83
|
+
else if (canvasType === 'napi') {
|
|
84
|
+
const { Canvas, loadImage } = power;
|
|
85
|
+
Platform.origin = {
|
|
86
|
+
createCanvas: (width, height, format) => new Canvas(width, height, format),
|
|
87
|
+
canvasToDataURL: (canvas, type, quality) => canvas.toDataURL(mineType(type), quality),
|
|
88
|
+
canvasToBolb: (canvas, type, quality) => __awaiter(this, void 0, void 0, function* () { return canvas.toBuffer(mineType(type), quality); }),
|
|
89
|
+
canvasSaveAs: (canvas, filename, quality) => __awaiter(this, void 0, void 0, function* () { return writeFileSync(filename, canvas.toBuffer(mineType(fileType(filename)), quality)); }),
|
|
90
|
+
download(_url, _filename) { return undefined; },
|
|
91
|
+
loadImage(src) { return loadImage(Platform.image.getRealURL(src)); }
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
Platform.ellipseToCurve = true;
|
|
95
|
+
Platform.event = {
|
|
96
|
+
stopDefault(_origin) { },
|
|
97
|
+
stopNow(_origin) { },
|
|
98
|
+
stop(_origin) { }
|
|
99
|
+
};
|
|
100
|
+
Platform.canvas = Creator.canvas();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
Platform.name = 'node';
|
|
104
|
+
Platform.requestRender = function (render) { setTimeout(render); };
|
|
105
|
+
Platform.devicePixelRatio = 1;
|
|
106
|
+
Platform.conicGradientSupport = true;
|
|
6
107
|
|
|
7
108
|
class Watcher {
|
|
8
109
|
get childrenChanged() { return this.hasAdd || this.hasRemove || this.hasVisible; }
|
|
@@ -10,7 +111,7 @@ class Watcher {
|
|
|
10
111
|
if (this.hasRemove) {
|
|
11
112
|
const updatedList = new LeafList();
|
|
12
113
|
this.__updatedList.list.forEach(item => { if (item.leafer)
|
|
13
|
-
updatedList.
|
|
114
|
+
updatedList.add(item); });
|
|
14
115
|
return updatedList;
|
|
15
116
|
}
|
|
16
117
|
else {
|
|
@@ -45,7 +146,7 @@ class Watcher {
|
|
|
45
146
|
this.target.emit(RenderEvent.REQUEST);
|
|
46
147
|
}
|
|
47
148
|
__onAttrChange(event) {
|
|
48
|
-
this.__updatedList.
|
|
149
|
+
this.__updatedList.add(event.target);
|
|
49
150
|
this.update();
|
|
50
151
|
}
|
|
51
152
|
__onChildEvent(event) {
|
|
@@ -55,12 +156,12 @@ class Watcher {
|
|
|
55
156
|
}
|
|
56
157
|
else {
|
|
57
158
|
this.hasRemove = true;
|
|
58
|
-
this.__updatedList.
|
|
159
|
+
this.__updatedList.add(event.parent);
|
|
59
160
|
}
|
|
60
161
|
this.update();
|
|
61
162
|
}
|
|
62
163
|
__pushChild(child) {
|
|
63
|
-
this.__updatedList.
|
|
164
|
+
this.__updatedList.add(child);
|
|
64
165
|
if (child.isBranch)
|
|
65
166
|
this.__loopChildren(child);
|
|
66
167
|
}
|
|
@@ -99,22 +200,22 @@ class Watcher {
|
|
|
99
200
|
}
|
|
100
201
|
}
|
|
101
202
|
|
|
102
|
-
const {
|
|
203
|
+
const { updateAllMatrix: updateAllMatrix$1, updateBounds: updateOneBounds, updateAllWorldOpacity } = LeafHelper;
|
|
103
204
|
const { pushAllChildBranch, pushAllParent } = BranchHelper;
|
|
104
205
|
function updateMatrix(updateList, levelList) {
|
|
105
206
|
let layout;
|
|
106
207
|
updateList.list.forEach(leaf => {
|
|
107
208
|
layout = leaf.__layout;
|
|
108
|
-
if (levelList.without(leaf) && !layout.
|
|
209
|
+
if (levelList.without(leaf) && !layout.proxyZoom) {
|
|
109
210
|
if (layout.matrixChanged) {
|
|
110
|
-
|
|
111
|
-
levelList.
|
|
211
|
+
updateAllMatrix$1(leaf, true);
|
|
212
|
+
levelList.add(leaf);
|
|
112
213
|
if (leaf.isBranch)
|
|
113
214
|
pushAllChildBranch(leaf, levelList);
|
|
114
215
|
pushAllParent(leaf, levelList);
|
|
115
216
|
}
|
|
116
217
|
else if (layout.boundsChanged) {
|
|
117
|
-
levelList.
|
|
218
|
+
levelList.add(leaf);
|
|
118
219
|
if (leaf.isBranch)
|
|
119
220
|
leaf.__tempNumber = 0;
|
|
120
221
|
pushAllParent(leaf, levelList);
|
|
@@ -123,20 +224,21 @@ function updateMatrix(updateList, levelList) {
|
|
|
123
224
|
});
|
|
124
225
|
}
|
|
125
226
|
function updateBounds(boundsList) {
|
|
126
|
-
let
|
|
227
|
+
let list, branch, children;
|
|
127
228
|
boundsList.sort(true);
|
|
128
229
|
boundsList.levels.forEach(level => {
|
|
129
|
-
|
|
130
|
-
for (let i = 0, len =
|
|
131
|
-
branch =
|
|
230
|
+
list = boundsList.levelMap[level];
|
|
231
|
+
for (let i = 0, len = list.length; i < len; i++) {
|
|
232
|
+
branch = list[i];
|
|
132
233
|
if (branch.isBranch && branch.__tempNumber) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
234
|
+
children = branch.children;
|
|
235
|
+
for (let j = 0, jLen = children.length; j < jLen; j++) {
|
|
236
|
+
if (!children[j].isBranch) {
|
|
237
|
+
updateOneBounds(children[j]);
|
|
136
238
|
}
|
|
137
239
|
}
|
|
138
240
|
}
|
|
139
|
-
branch
|
|
241
|
+
updateOneBounds(branch);
|
|
140
242
|
}
|
|
141
243
|
});
|
|
142
244
|
}
|
|
@@ -149,7 +251,7 @@ function updateChange(updateList) {
|
|
|
149
251
|
}
|
|
150
252
|
|
|
151
253
|
const { worldBounds } = LeafBoundsHelper;
|
|
152
|
-
const {
|
|
254
|
+
const bigBounds = { x: 0, y: 0, width: 100000, height: 100000 };
|
|
153
255
|
class LayoutBlockData {
|
|
154
256
|
constructor(list) {
|
|
155
257
|
this.updatedBounds = new Bounds();
|
|
@@ -160,14 +262,20 @@ class LayoutBlockData {
|
|
|
160
262
|
this.updatedList = list;
|
|
161
263
|
}
|
|
162
264
|
setBefore() {
|
|
163
|
-
|
|
265
|
+
this.beforeBounds.setListWithFn(this.updatedList.list, worldBounds);
|
|
164
266
|
}
|
|
165
267
|
setAfter() {
|
|
166
|
-
|
|
167
|
-
|
|
268
|
+
const { list } = this.updatedList;
|
|
269
|
+
if (list.some(leaf => leaf.noBounds)) {
|
|
270
|
+
this.afterBounds.set(bigBounds);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
this.afterBounds.setListWithFn(list, worldBounds);
|
|
274
|
+
}
|
|
275
|
+
this.updatedBounds.setList([this.beforeBounds, this.afterBounds]);
|
|
168
276
|
}
|
|
169
277
|
merge(data) {
|
|
170
|
-
this.updatedList.
|
|
278
|
+
this.updatedList.addList(data.updatedList.list);
|
|
171
279
|
this.beforeBounds.add(data.beforeBounds);
|
|
172
280
|
this.afterBounds.add(data.afterBounds);
|
|
173
281
|
this.updatedBounds.add(data.updatedBounds);
|
|
@@ -177,9 +285,8 @@ class LayoutBlockData {
|
|
|
177
285
|
}
|
|
178
286
|
}
|
|
179
287
|
|
|
180
|
-
const {
|
|
181
|
-
const
|
|
182
|
-
const debug$1 = Debug.get('Layouter');
|
|
288
|
+
const { updateAllMatrix, updateAllChange } = LeafHelper;
|
|
289
|
+
const debug$2 = Debug.get('Layouter');
|
|
183
290
|
class Layouter {
|
|
184
291
|
constructor(target, userConfig) {
|
|
185
292
|
this.totalTimes = 0;
|
|
@@ -214,7 +321,7 @@ class Layouter {
|
|
|
214
321
|
target.emitEvent(new LayoutEvent(LayoutEvent.END, this.layoutedBlocks, this.times));
|
|
215
322
|
}
|
|
216
323
|
catch (e) {
|
|
217
|
-
debug$
|
|
324
|
+
debug$2.error(e);
|
|
218
325
|
}
|
|
219
326
|
this.layoutedBlocks = null;
|
|
220
327
|
}
|
|
@@ -228,9 +335,9 @@ class Layouter {
|
|
|
228
335
|
}
|
|
229
336
|
layoutOnce() {
|
|
230
337
|
if (this.layouting)
|
|
231
|
-
return debug$
|
|
338
|
+
return debug$2.warn('layouting');
|
|
232
339
|
if (this.times > 3)
|
|
233
|
-
return debug$
|
|
340
|
+
return debug$2.warn('layout max times');
|
|
234
341
|
this.times++;
|
|
235
342
|
this.totalTimes++;
|
|
236
343
|
this.layouting = true;
|
|
@@ -255,12 +362,15 @@ class Layouter {
|
|
|
255
362
|
const { target, __updatedList: updateList } = this;
|
|
256
363
|
const { BEFORE, LAYOUT, AFTER } = LayoutEvent;
|
|
257
364
|
const blocks = this.getBlocks(updateList);
|
|
258
|
-
blocks.forEach(item =>
|
|
365
|
+
blocks.forEach(item => item.setBefore());
|
|
259
366
|
target.emitEvent(new LayoutEvent(BEFORE, blocks, this.times));
|
|
367
|
+
this.extraBlock = null;
|
|
260
368
|
updateList.sort();
|
|
261
369
|
updateMatrix(updateList, this.__levelList);
|
|
262
370
|
updateBounds(this.__levelList);
|
|
263
371
|
updateChange(updateList);
|
|
372
|
+
if (this.extraBlock)
|
|
373
|
+
blocks.push(this.extraBlock);
|
|
264
374
|
blocks.forEach(item => item.setAfter());
|
|
265
375
|
target.emitEvent(new LayoutEvent(LAYOUT, blocks, this.times));
|
|
266
376
|
target.emitEvent(new LayoutEvent(AFTER, blocks, this.times));
|
|
@@ -283,17 +393,22 @@ class Layouter {
|
|
|
283
393
|
Run.end(t);
|
|
284
394
|
}
|
|
285
395
|
static fullLayout(target) {
|
|
286
|
-
|
|
396
|
+
updateAllMatrix(target, true);
|
|
287
397
|
if (target.isBranch) {
|
|
288
|
-
|
|
289
|
-
pushAllBranchStack(target, branchStack);
|
|
290
|
-
updateWorldBoundsByBranchStack(branchStack);
|
|
398
|
+
BranchHelper.updateBounds(target);
|
|
291
399
|
}
|
|
292
400
|
else {
|
|
293
|
-
|
|
401
|
+
LeafHelper.updateBounds(target);
|
|
294
402
|
}
|
|
295
403
|
updateAllChange(target);
|
|
296
404
|
}
|
|
405
|
+
addExtra(leaf) {
|
|
406
|
+
if (!this.__updatedList.has(leaf)) {
|
|
407
|
+
const { updatedList, beforeBounds } = this.extraBlock || (this.extraBlock = new LayoutBlockData([]));
|
|
408
|
+
updatedList.length ? beforeBounds.add(leaf.__world) : beforeBounds.set(leaf.__world);
|
|
409
|
+
updatedList.add(leaf);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
297
412
|
createBlock(data) {
|
|
298
413
|
return new LayoutBlockData(data);
|
|
299
414
|
}
|
|
@@ -321,13 +436,12 @@ class Layouter {
|
|
|
321
436
|
if (this.target) {
|
|
322
437
|
this.stop();
|
|
323
438
|
this.__removeListenEvents();
|
|
324
|
-
this.target = null;
|
|
325
|
-
this.config = null;
|
|
439
|
+
this.target = this.config = null;
|
|
326
440
|
}
|
|
327
441
|
}
|
|
328
442
|
}
|
|
329
443
|
|
|
330
|
-
const debug = Debug.get('Renderer');
|
|
444
|
+
const debug$1 = Debug.get('Renderer');
|
|
331
445
|
class Renderer {
|
|
332
446
|
get needFill() { return !!(!this.canvas.allowBackgroundColor && this.config.fill); }
|
|
333
447
|
constructor(target, canvas, userConfig) {
|
|
@@ -365,7 +479,7 @@ class Renderer {
|
|
|
365
479
|
const { target } = this;
|
|
366
480
|
this.times = 0;
|
|
367
481
|
this.totalBounds = new Bounds();
|
|
368
|
-
debug.log(target.innerName, '--->');
|
|
482
|
+
debug$1.log(target.innerName, '--->');
|
|
369
483
|
try {
|
|
370
484
|
this.emitRender(RenderEvent.START);
|
|
371
485
|
this.renderOnce(callback);
|
|
@@ -374,9 +488,9 @@ class Renderer {
|
|
|
374
488
|
}
|
|
375
489
|
catch (e) {
|
|
376
490
|
this.rendering = false;
|
|
377
|
-
debug.error(e);
|
|
491
|
+
debug$1.error(e);
|
|
378
492
|
}
|
|
379
|
-
debug.log('-------------|');
|
|
493
|
+
debug$1.log('-------------|');
|
|
380
494
|
}
|
|
381
495
|
renderAgain() {
|
|
382
496
|
if (this.rendering) {
|
|
@@ -388,9 +502,9 @@ class Renderer {
|
|
|
388
502
|
}
|
|
389
503
|
renderOnce(callback) {
|
|
390
504
|
if (this.rendering)
|
|
391
|
-
return debug.warn('rendering');
|
|
505
|
+
return debug$1.warn('rendering');
|
|
392
506
|
if (this.times > 3)
|
|
393
|
-
return debug.warn('render max times');
|
|
507
|
+
return debug$1.warn('render max times');
|
|
394
508
|
this.times++;
|
|
395
509
|
this.totalTimes++;
|
|
396
510
|
this.rendering = true;
|
|
@@ -403,6 +517,10 @@ class Renderer {
|
|
|
403
517
|
}
|
|
404
518
|
else {
|
|
405
519
|
this.requestLayout();
|
|
520
|
+
if (this.ignore) {
|
|
521
|
+
this.ignore = this.rendering = false;
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
406
524
|
this.emitRender(RenderEvent.BEFORE);
|
|
407
525
|
if (this.config.usePartRender && this.totalTimes > 1) {
|
|
408
526
|
this.partRender();
|
|
@@ -423,9 +541,8 @@ class Renderer {
|
|
|
423
541
|
partRender() {
|
|
424
542
|
const { canvas, updateBlocks: list } = this;
|
|
425
543
|
if (!list)
|
|
426
|
-
return debug.warn('PartRender: need update attr');
|
|
427
|
-
|
|
428
|
-
this.mergeBlocks();
|
|
544
|
+
return debug$1.warn('PartRender: need update attr');
|
|
545
|
+
this.mergeBlocks();
|
|
429
546
|
list.forEach(block => { if (canvas.bounds.hit(block) && !block.isEmpty())
|
|
430
547
|
this.clipRender(block); });
|
|
431
548
|
}
|
|
@@ -434,17 +551,17 @@ class Renderer {
|
|
|
434
551
|
const { canvas } = this;
|
|
435
552
|
const bounds = block.getIntersect(canvas.bounds);
|
|
436
553
|
const includes = block.includes(this.target.__world);
|
|
437
|
-
const realBounds = new Bounds(
|
|
554
|
+
const realBounds = new Bounds(bounds);
|
|
438
555
|
canvas.save();
|
|
439
556
|
if (includes && !Debug.showRepaint) {
|
|
440
557
|
canvas.clear();
|
|
441
558
|
}
|
|
442
559
|
else {
|
|
443
|
-
bounds.spread(
|
|
560
|
+
bounds.spread(10 + 1 / this.canvas.pixelRatio).ceil();
|
|
444
561
|
canvas.clearWorld(bounds, true);
|
|
445
562
|
canvas.clipWorld(bounds, true);
|
|
446
563
|
}
|
|
447
|
-
this.__render(bounds, realBounds);
|
|
564
|
+
this.__render(bounds, includes, realBounds);
|
|
448
565
|
canvas.restore();
|
|
449
566
|
Run.end(t);
|
|
450
567
|
}
|
|
@@ -453,12 +570,12 @@ class Renderer {
|
|
|
453
570
|
const { canvas } = this;
|
|
454
571
|
canvas.save();
|
|
455
572
|
canvas.clear();
|
|
456
|
-
this.__render(canvas.bounds);
|
|
573
|
+
this.__render(canvas.bounds, true);
|
|
457
574
|
canvas.restore();
|
|
458
575
|
Run.end(t);
|
|
459
576
|
}
|
|
460
|
-
__render(bounds, realBounds) {
|
|
461
|
-
const options =
|
|
577
|
+
__render(bounds, includes, realBounds) {
|
|
578
|
+
const options = bounds.includes(this.target.__world) ? { includes } : { bounds, includes };
|
|
462
579
|
if (this.needFill)
|
|
463
580
|
this.canvas.fillWorld(bounds, this.config.fill);
|
|
464
581
|
if (Debug.showRepaint)
|
|
@@ -484,7 +601,7 @@ class Renderer {
|
|
|
484
601
|
const { updateBlocks: list } = this;
|
|
485
602
|
if (list) {
|
|
486
603
|
const bounds = new Bounds();
|
|
487
|
-
bounds.
|
|
604
|
+
bounds.setList(list);
|
|
488
605
|
list.length = 0;
|
|
489
606
|
list.push(bounds);
|
|
490
607
|
}
|
|
@@ -493,12 +610,12 @@ class Renderer {
|
|
|
493
610
|
const startTime = Date.now();
|
|
494
611
|
Platform.requestRender(() => {
|
|
495
612
|
this.FPS = Math.min(60, Math.ceil(1000 / (Date.now() - startTime)));
|
|
496
|
-
if (this.
|
|
497
|
-
|
|
613
|
+
if (this.running) {
|
|
614
|
+
this.target.emit(AnimateEvent.FRAME);
|
|
615
|
+
if (this.changed && this.canvas.view)
|
|
498
616
|
this.render();
|
|
617
|
+
this.target.emit(RenderEvent.NEXT);
|
|
499
618
|
}
|
|
500
|
-
if (this.running)
|
|
501
|
-
this.target.emit(AnimateEvent.FRAME);
|
|
502
619
|
if (this.target)
|
|
503
620
|
this.__requestRender();
|
|
504
621
|
});
|
|
@@ -511,9 +628,12 @@ class Renderer {
|
|
|
511
628
|
const bounds = new Bounds(0, 0, width, height);
|
|
512
629
|
if (!bounds.includes(this.target.__world) || this.needFill || !e.samePixelRatio) {
|
|
513
630
|
this.addBlock(this.canvas.bounds);
|
|
514
|
-
this.target.forceUpdate('
|
|
631
|
+
this.target.forceUpdate('surface');
|
|
632
|
+
return;
|
|
515
633
|
}
|
|
516
634
|
}
|
|
635
|
+
this.addBlock(new Bounds(0, 0, 1, 1));
|
|
636
|
+
this.changed = true;
|
|
517
637
|
}
|
|
518
638
|
__onLayoutEnd(event) {
|
|
519
639
|
if (event.data)
|
|
@@ -524,7 +644,7 @@ class Renderer {
|
|
|
524
644
|
empty = (!leaf.__world.width || !leaf.__world.height);
|
|
525
645
|
if (empty) {
|
|
526
646
|
if (!leaf.isLeafer)
|
|
527
|
-
debug.
|
|
647
|
+
debug$1.tip(leaf.innerName, ': empty');
|
|
528
648
|
empty = (!leaf.isBranch || leaf.isBranchLeaf);
|
|
529
649
|
}
|
|
530
650
|
return empty;
|
|
@@ -551,15 +671,13 @@ class Renderer {
|
|
|
551
671
|
if (this.target) {
|
|
552
672
|
this.stop();
|
|
553
673
|
this.__removeListenEvents();
|
|
554
|
-
this.target = null;
|
|
555
|
-
this.canvas = null;
|
|
556
|
-
this.config = null;
|
|
674
|
+
this.target = this.canvas = this.config = null;
|
|
557
675
|
}
|
|
558
676
|
}
|
|
559
677
|
}
|
|
560
678
|
|
|
561
679
|
const { hitRadiusPoint } = BoundsHelper;
|
|
562
|
-
class
|
|
680
|
+
class Picker {
|
|
563
681
|
constructor(target, selector) {
|
|
564
682
|
this.target = target;
|
|
565
683
|
this.selector = selector;
|
|
@@ -571,51 +689,59 @@ class FindPath {
|
|
|
571
689
|
options = {};
|
|
572
690
|
const through = options.through || false;
|
|
573
691
|
const ignoreHittable = options.ignoreHittable || false;
|
|
692
|
+
const target = options.target || this.target;
|
|
574
693
|
this.exclude = options.exclude || null;
|
|
575
694
|
this.point = { x: hitPoint.x, y: hitPoint.y, radiusX: hitRadius, radiusY: hitRadius };
|
|
576
|
-
this.findList =
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
const
|
|
695
|
+
this.findList = new LeafList(options.findList);
|
|
696
|
+
if (!options.findList)
|
|
697
|
+
this.hitBranch(target);
|
|
698
|
+
const { list } = this.findList;
|
|
699
|
+
const leaf = this.getBestMatchLeaf(list, options.bottomList, ignoreHittable);
|
|
580
700
|
const path = ignoreHittable ? this.getPath(leaf) : this.getHitablePath(leaf);
|
|
581
701
|
this.clear();
|
|
582
|
-
return through ? { path, leaf, throughPath: list.length ? this.getThroughPath(list) : path } : { path, leaf };
|
|
702
|
+
return through ? { path, target: leaf, throughPath: list.length ? this.getThroughPath(list) : path } : { path, target: leaf };
|
|
583
703
|
}
|
|
584
|
-
getBestMatchLeaf() {
|
|
585
|
-
|
|
586
|
-
if (targets.length > 1) {
|
|
704
|
+
getBestMatchLeaf(list, bottomList, ignoreHittable) {
|
|
705
|
+
if (list.length) {
|
|
587
706
|
let find;
|
|
588
|
-
this.findList =
|
|
707
|
+
this.findList = new LeafList();
|
|
589
708
|
const { x, y } = this.point;
|
|
590
709
|
const point = { x, y, radiusX: 0, radiusY: 0 };
|
|
591
|
-
for (let i = 0, len =
|
|
592
|
-
find =
|
|
593
|
-
if (LeafHelper.worldHittable(find)) {
|
|
710
|
+
for (let i = 0, len = list.length; i < len; i++) {
|
|
711
|
+
find = list[i];
|
|
712
|
+
if (ignoreHittable || LeafHelper.worldHittable(find)) {
|
|
594
713
|
this.hitChild(find, point);
|
|
595
714
|
if (this.findList.length)
|
|
596
|
-
return this.findList[0];
|
|
715
|
+
return this.findList.list[0];
|
|
597
716
|
}
|
|
598
717
|
}
|
|
599
718
|
}
|
|
600
|
-
|
|
719
|
+
if (bottomList) {
|
|
720
|
+
for (let i = 0, len = bottomList.length; i < len; i++) {
|
|
721
|
+
this.hitChild(bottomList[i].target, this.point, bottomList[i].proxy);
|
|
722
|
+
if (this.findList.length)
|
|
723
|
+
return this.findList.list[0];
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
return list[0];
|
|
601
727
|
}
|
|
602
728
|
getPath(leaf) {
|
|
603
729
|
const path = new LeafList();
|
|
604
730
|
while (leaf) {
|
|
605
|
-
path.
|
|
731
|
+
path.add(leaf);
|
|
606
732
|
leaf = leaf.parent;
|
|
607
733
|
}
|
|
608
|
-
path.
|
|
734
|
+
path.add(this.target);
|
|
609
735
|
return path;
|
|
610
736
|
}
|
|
611
737
|
getHitablePath(leaf) {
|
|
612
|
-
const path = this.getPath(leaf);
|
|
738
|
+
const path = this.getPath(leaf && leaf.hittable ? leaf : null);
|
|
613
739
|
let item, hittablePath = new LeafList();
|
|
614
740
|
for (let i = path.list.length - 1; i > -1; i--) {
|
|
615
741
|
item = path.list[i];
|
|
616
742
|
if (!item.__.hittable)
|
|
617
743
|
break;
|
|
618
|
-
hittablePath.
|
|
744
|
+
hittablePath.addAt(item, 0);
|
|
619
745
|
if (!item.__.hitChildren)
|
|
620
746
|
break;
|
|
621
747
|
}
|
|
@@ -634,17 +760,20 @@ class FindPath {
|
|
|
634
760
|
leaf = path.list[j];
|
|
635
761
|
if (nextPath && nextPath.has(leaf))
|
|
636
762
|
break;
|
|
637
|
-
throughPath.
|
|
763
|
+
throughPath.add(leaf);
|
|
638
764
|
}
|
|
639
765
|
}
|
|
640
766
|
return throughPath;
|
|
641
767
|
}
|
|
768
|
+
hitBranch(branch) {
|
|
769
|
+
this.eachFind(branch.children, branch.__onlyHitMask);
|
|
770
|
+
}
|
|
642
771
|
eachFind(children, hitMask) {
|
|
643
772
|
let child, hit;
|
|
644
773
|
const { point } = this, len = children.length;
|
|
645
774
|
for (let i = len - 1; i > -1; i--) {
|
|
646
775
|
child = children[i];
|
|
647
|
-
if (!child.__.visible || (hitMask && !child.__.
|
|
776
|
+
if (!child.__.visible || (hitMask && !child.__.mask))
|
|
648
777
|
continue;
|
|
649
778
|
hit = child.__.hitRadius ? true : hitRadiusPoint(child.__world, point);
|
|
650
779
|
if (child.isBranch) {
|
|
@@ -660,11 +789,15 @@ class FindPath {
|
|
|
660
789
|
}
|
|
661
790
|
}
|
|
662
791
|
}
|
|
663
|
-
hitChild(child, point) {
|
|
792
|
+
hitChild(child, point, proxy) {
|
|
664
793
|
if (this.exclude && this.exclude.has(child))
|
|
665
794
|
return;
|
|
666
|
-
if (child.__hitWorld(point))
|
|
667
|
-
|
|
795
|
+
if (child.__hitWorld(point)) {
|
|
796
|
+
const { parent } = child;
|
|
797
|
+
if (parent && parent.__hasMask && !child.__.mask && !parent.children.some(item => item.__.mask && item.__hitWorld(point)))
|
|
798
|
+
return;
|
|
799
|
+
this.findList.add(proxy || child);
|
|
800
|
+
}
|
|
668
801
|
}
|
|
669
802
|
clear() {
|
|
670
803
|
this.point = null;
|
|
@@ -676,120 +809,128 @@ class FindPath {
|
|
|
676
809
|
}
|
|
677
810
|
}
|
|
678
811
|
|
|
812
|
+
const { Yes, NoAndSkip, YesAndSkip } = Answer;
|
|
813
|
+
const idCondition = {}, classNameCondition = {}, tagCondition = {};
|
|
679
814
|
class Selector {
|
|
680
815
|
constructor(target, userConfig) {
|
|
681
816
|
this.config = {};
|
|
682
|
-
this.
|
|
683
|
-
this.
|
|
684
|
-
this.
|
|
685
|
-
|
|
817
|
+
this.innerIdMap = {};
|
|
818
|
+
this.idMap = {};
|
|
819
|
+
this.methods = {
|
|
820
|
+
id: (leaf, name) => leaf.id === name ? (this.idMap[name] = leaf, 1) : 0,
|
|
821
|
+
innerId: (leaf, innerId) => leaf.innerId === innerId ? (this.innerIdMap[innerId] = leaf, 1) : 0,
|
|
822
|
+
className: (leaf, name) => leaf.className === name ? 1 : 0,
|
|
823
|
+
tag: (leaf, name) => leaf.__tag === name ? 1 : 0,
|
|
824
|
+
tags: (leaf, nameMap) => nameMap[leaf.__tag] ? 1 : 0
|
|
825
|
+
};
|
|
686
826
|
this.target = target;
|
|
687
827
|
if (userConfig)
|
|
688
828
|
this.config = DataHelper.default(userConfig, this.config);
|
|
689
|
-
this.
|
|
829
|
+
this.picker = new Picker(target, this);
|
|
690
830
|
this.__listenEvents();
|
|
691
831
|
}
|
|
832
|
+
getBy(condition, branch, one, options) {
|
|
833
|
+
switch (typeof condition) {
|
|
834
|
+
case 'number':
|
|
835
|
+
const leaf = this.getByInnerId(condition, branch);
|
|
836
|
+
return one ? leaf : (leaf ? [leaf] : []);
|
|
837
|
+
case 'string':
|
|
838
|
+
switch (condition[0]) {
|
|
839
|
+
case '#':
|
|
840
|
+
idCondition.id = condition.substring(1), condition = idCondition;
|
|
841
|
+
break;
|
|
842
|
+
case '.':
|
|
843
|
+
classNameCondition.className = condition.substring(1), condition = classNameCondition;
|
|
844
|
+
break;
|
|
845
|
+
default:
|
|
846
|
+
tagCondition.tag = condition, condition = tagCondition;
|
|
847
|
+
}
|
|
848
|
+
case 'object':
|
|
849
|
+
if (condition.id !== undefined) {
|
|
850
|
+
const leaf = this.getById(condition.id, branch);
|
|
851
|
+
return one ? leaf : (leaf ? [leaf] : []);
|
|
852
|
+
}
|
|
853
|
+
else if (condition.tag) {
|
|
854
|
+
const { tag } = condition, isArray = tag instanceof Array;
|
|
855
|
+
return this.getByMethod(isArray ? this.methods.tags : this.methods.tag, branch, one, isArray ? DataHelper.toMap(tag) : tag);
|
|
856
|
+
}
|
|
857
|
+
else {
|
|
858
|
+
return this.getByMethod(this.methods.className, branch, one, condition.className);
|
|
859
|
+
}
|
|
860
|
+
case 'function':
|
|
861
|
+
return this.getByMethod(condition, branch, one, options);
|
|
862
|
+
}
|
|
863
|
+
}
|
|
692
864
|
getByPoint(hitPoint, hitRadius, options) {
|
|
693
865
|
if (Platform.name === 'node')
|
|
694
866
|
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
|
-
}
|
|
867
|
+
return this.picker.getByPoint(hitPoint, hitRadius, options);
|
|
710
868
|
}
|
|
711
|
-
getByInnerId(
|
|
712
|
-
|
|
869
|
+
getByInnerId(innerId, branch) {
|
|
870
|
+
const cache = this.innerIdMap[innerId];
|
|
713
871
|
if (cache)
|
|
714
872
|
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;
|
|
873
|
+
this.eachFind(this.toChildren(branch), this.methods.innerId, null, innerId);
|
|
874
|
+
return this.findLeaf;
|
|
729
875
|
}
|
|
730
|
-
getById(
|
|
731
|
-
|
|
732
|
-
if (cache)
|
|
876
|
+
getById(id, branch) {
|
|
877
|
+
const cache = this.idMap[id];
|
|
878
|
+
if (cache && LeafHelper.hasParent(cache, branch || this.target))
|
|
733
879
|
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;
|
|
880
|
+
this.eachFind(this.toChildren(branch), this.methods.id, null, id);
|
|
881
|
+
return this.findLeaf;
|
|
770
882
|
}
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
883
|
+
getByClassName(className, branch) {
|
|
884
|
+
return this.getByMethod(this.methods.className, branch, false, className);
|
|
885
|
+
}
|
|
886
|
+
getByTag(tag, branch) {
|
|
887
|
+
return this.getByMethod(this.methods.tag, branch, false, tag);
|
|
888
|
+
}
|
|
889
|
+
getByMethod(method, branch, one, options) {
|
|
890
|
+
const list = one ? null : [];
|
|
891
|
+
this.eachFind(this.toChildren(branch), method, list, options);
|
|
892
|
+
return list || this.findLeaf;
|
|
893
|
+
}
|
|
894
|
+
eachFind(children, method, list, options) {
|
|
895
|
+
let child, result;
|
|
775
896
|
for (let i = 0, len = children.length; i < len; i++) {
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
897
|
+
child = children[i];
|
|
898
|
+
result = method(child, options);
|
|
899
|
+
if (result === Yes || result === YesAndSkip) {
|
|
900
|
+
if (list) {
|
|
901
|
+
list.push(child);
|
|
902
|
+
}
|
|
903
|
+
else {
|
|
904
|
+
this.findLeaf = child;
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
if (child.isBranch && result < NoAndSkip)
|
|
909
|
+
this.eachFind(child.children, method, list, options);
|
|
781
910
|
}
|
|
782
911
|
}
|
|
912
|
+
toChildren(branch) {
|
|
913
|
+
this.findLeaf = null;
|
|
914
|
+
return [branch || this.target];
|
|
915
|
+
}
|
|
783
916
|
__onRemoveChild(event) {
|
|
784
|
-
const
|
|
785
|
-
if (this.
|
|
786
|
-
this.
|
|
787
|
-
if (this.
|
|
788
|
-
this.
|
|
917
|
+
const { id, innerId } = event.child;
|
|
918
|
+
if (this.idMap[id])
|
|
919
|
+
delete this.idMap[id];
|
|
920
|
+
if (this.innerIdMap[innerId])
|
|
921
|
+
delete this.innerIdMap[innerId];
|
|
922
|
+
}
|
|
923
|
+
__checkIdChange(event) {
|
|
924
|
+
if (event.attrName === 'id') {
|
|
925
|
+
const id = event.oldValue;
|
|
926
|
+
if (this.idMap[id])
|
|
927
|
+
delete this.idMap[id];
|
|
928
|
+
}
|
|
789
929
|
}
|
|
790
930
|
__listenEvents() {
|
|
791
931
|
this.__eventIds = [
|
|
792
|
-
this.target.on_(ChildEvent.REMOVE, this.__onRemoveChild, this)
|
|
932
|
+
this.target.on_(ChildEvent.REMOVE, this.__onRemoveChild, this),
|
|
933
|
+
this.target.on_(PropertyEvent.CHANGE, this.__checkIdChange, this)
|
|
793
934
|
];
|
|
794
935
|
}
|
|
795
936
|
__removeListenEvents() {
|
|
@@ -799,11 +940,10 @@ class Selector {
|
|
|
799
940
|
destroy() {
|
|
800
941
|
if (this.__eventIds.length) {
|
|
801
942
|
this.__removeListenEvents();
|
|
802
|
-
this.
|
|
803
|
-
this.
|
|
804
|
-
this.
|
|
805
|
-
this.
|
|
806
|
-
this.tagNameList = {};
|
|
943
|
+
this.picker.destroy();
|
|
944
|
+
this.findLeaf = null;
|
|
945
|
+
this.innerIdMap = {};
|
|
946
|
+
this.idMap = {};
|
|
807
947
|
}
|
|
808
948
|
}
|
|
809
949
|
}
|
|
@@ -816,444 +956,91 @@ Object.assign(Creator, {
|
|
|
816
956
|
});
|
|
817
957
|
Platform.layout = Layouter.fullLayout;
|
|
818
958
|
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
__createView() {
|
|
827
|
-
this.view = Platform.origin.createCanvas(1, 1);
|
|
828
|
-
}
|
|
829
|
-
updateViewSize() {
|
|
830
|
-
const { width, height, pixelRatio } = this;
|
|
831
|
-
this.view.width = width * pixelRatio;
|
|
832
|
-
this.view.height = height * pixelRatio;
|
|
833
|
-
this.clientBounds = this.bounds;
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
Object.assign(Creator, {
|
|
838
|
-
canvas: (options, manager) => new LeaferCanvas(options, manager),
|
|
839
|
-
image: (options) => new LeaferImage(options),
|
|
840
|
-
hitCanvas: (options, manager) => new LeaferCanvas(options, manager),
|
|
841
|
-
interaction: (target, canvas, selector, options) => { return new InteractionBase(target, canvas, selector, options); }
|
|
842
|
-
});
|
|
843
|
-
function useCanvas(canvasType, power) {
|
|
844
|
-
if (!Platform.origin) {
|
|
845
|
-
if (canvasType === 'skia') {
|
|
846
|
-
const { Canvas, loadImage } = power;
|
|
847
|
-
Platform.origin = {
|
|
848
|
-
createCanvas: (width, height, format) => new Canvas(width, height, format),
|
|
849
|
-
canvasToDataURL: (canvas, type, quality) => canvas.toDataURLSync(type, { quality }),
|
|
850
|
-
canvasToBolb: (canvas, type, quality) => canvas.toBuffer(type, { quality }),
|
|
851
|
-
canvasSaveAs: (canvas, filename, quality) => canvas.saveAs(filename, { quality }),
|
|
852
|
-
loadImage
|
|
853
|
-
};
|
|
959
|
+
function fillText(ui, canvas) {
|
|
960
|
+
let row;
|
|
961
|
+
const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
|
|
962
|
+
for (let i = 0, len = rows.length; i < len; i++) {
|
|
963
|
+
row = rows[i];
|
|
964
|
+
if (row.text) {
|
|
965
|
+
canvas.fillText(row.text, row.x, row.y);
|
|
854
966
|
}
|
|
855
|
-
|
|
967
|
+
else if (row.data) {
|
|
968
|
+
row.data.forEach(charData => {
|
|
969
|
+
canvas.fillText(charData.char, charData.x, row.y);
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
if (decorationY)
|
|
973
|
+
canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight);
|
|
856
974
|
}
|
|
857
975
|
}
|
|
858
|
-
Platform.name = 'node';
|
|
859
|
-
Platform.requestRender = function (render) { setTimeout(render); };
|
|
860
|
-
Platform.devicePixelRatio = 1;
|
|
861
|
-
Platform.conicGradientSupport = true;
|
|
862
|
-
Platform.realtimeLayout = true;
|
|
863
976
|
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
const swap = rotation && rotation !== 180;
|
|
868
|
-
const sw = box.width / (swap ? height : width);
|
|
869
|
-
const sh = box.height / (swap ? width : height);
|
|
870
|
-
const scale = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
|
|
871
|
-
const x = box.x + (box.width - width * scale) / 2;
|
|
872
|
-
const y = box.y + (box.height - height * scale) / 2;
|
|
873
|
-
translate$1(transform, x, y);
|
|
874
|
-
scaleHelper$1(transform, scale);
|
|
875
|
-
if (rotation)
|
|
876
|
-
rotateOfOuter$2(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
|
|
877
|
-
data.scaleX = data.scaleY = scale;
|
|
878
|
-
data.transform = transform;
|
|
879
|
-
}
|
|
880
|
-
function clipMode(data, box, offset, scale, rotation) {
|
|
881
|
-
const transform = get$4();
|
|
882
|
-
translate$1(transform, box.x, box.y);
|
|
883
|
-
if (offset)
|
|
884
|
-
translate$1(transform, offset.x, offset.y);
|
|
885
|
-
if (scale) {
|
|
886
|
-
typeof scale === 'number' ? scaleHelper$1(transform, scale) : scaleHelper$1(transform, scale.x, scale.y);
|
|
887
|
-
data.scaleX = transform.a;
|
|
888
|
-
data.scaleY = transform.d;
|
|
889
|
-
}
|
|
890
|
-
if (rotation)
|
|
891
|
-
rotate(transform, rotation);
|
|
892
|
-
data.transform = transform;
|
|
977
|
+
function fill(fill, ui, canvas) {
|
|
978
|
+
canvas.fillStyle = fill;
|
|
979
|
+
ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
|
|
893
980
|
}
|
|
894
|
-
function
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
981
|
+
function fills(fills, ui, canvas) {
|
|
982
|
+
let item;
|
|
983
|
+
const { windingRule, __font } = ui.__;
|
|
984
|
+
for (let i = 0, len = fills.length; i < len; i++) {
|
|
985
|
+
item = fills[i];
|
|
986
|
+
if (item.image && PaintImage.checkImage(ui, canvas, item, !__font))
|
|
987
|
+
continue;
|
|
988
|
+
if (item.style) {
|
|
989
|
+
canvas.fillStyle = item.style;
|
|
990
|
+
if (item.transform) {
|
|
991
|
+
canvas.save();
|
|
992
|
+
canvas.transform(item.transform);
|
|
993
|
+
if (item.blendMode)
|
|
994
|
+
canvas.blendMode = item.blendMode;
|
|
995
|
+
__font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
|
|
996
|
+
canvas.restore();
|
|
997
|
+
}
|
|
998
|
+
else {
|
|
999
|
+
if (item.blendMode) {
|
|
1000
|
+
canvas.saveBlendMode(item.blendMode);
|
|
1001
|
+
__font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
|
|
1002
|
+
canvas.restoreBlendMode();
|
|
1003
|
+
}
|
|
1004
|
+
else {
|
|
1005
|
+
__font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
908
1008
|
}
|
|
909
1009
|
}
|
|
910
|
-
translate$1(transform, box.x, box.y);
|
|
911
|
-
if (scale) {
|
|
912
|
-
scaleOfOuter$2(transform, box, scale);
|
|
913
|
-
data.scaleX = data.scaleY = scale;
|
|
914
|
-
}
|
|
915
|
-
data.transform = transform;
|
|
916
1010
|
}
|
|
917
1011
|
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
const data = leafPaint.data = { mode };
|
|
926
|
-
switch (mode) {
|
|
927
|
-
case 'strench':
|
|
928
|
-
if (!sameBox)
|
|
929
|
-
width = box.width, height = box.height;
|
|
930
|
-
if (box.x || box.y) {
|
|
931
|
-
data.transform = get$3();
|
|
932
|
-
translate(data.transform, box.x, box.y);
|
|
933
|
-
}
|
|
1012
|
+
function strokeText(stroke, ui, canvas) {
|
|
1013
|
+
const { strokeAlign } = ui.__;
|
|
1014
|
+
const isStrokes = typeof stroke !== 'string';
|
|
1015
|
+
switch (strokeAlign) {
|
|
1016
|
+
case 'center':
|
|
1017
|
+
canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
|
|
1018
|
+
isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
|
|
934
1019
|
break;
|
|
935
|
-
case '
|
|
936
|
-
|
|
937
|
-
clipMode(data, box, offset, scale, rotation);
|
|
1020
|
+
case 'inside':
|
|
1021
|
+
drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
|
|
938
1022
|
break;
|
|
939
|
-
case '
|
|
940
|
-
|
|
941
|
-
repeatMode(data, box, width, height, scale, rotation);
|
|
1023
|
+
case 'outside':
|
|
1024
|
+
drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
|
|
942
1025
|
break;
|
|
943
|
-
case 'fit':
|
|
944
|
-
case 'cover':
|
|
945
|
-
default:
|
|
946
|
-
if (!sameBox || rotation)
|
|
947
|
-
fillOrFitMode(data, mode, box, width, height, rotation);
|
|
948
1026
|
}
|
|
949
|
-
data.width = width;
|
|
950
|
-
data.height = height;
|
|
951
|
-
if (opacity)
|
|
952
|
-
data.opacity = opacity;
|
|
953
|
-
}
|
|
954
|
-
|
|
955
|
-
function image(ui, attrName, attrValue, box, firstUse) {
|
|
956
|
-
const leafPaint = { type: attrValue.type };
|
|
957
|
-
const image = leafPaint.image = ImageManager.get(attrValue);
|
|
958
|
-
const event = (firstUse || image.loading) && { target: ui, image, attrName, attrValue };
|
|
959
|
-
if (image.ready) {
|
|
960
|
-
if (hasNaturalSize(ui, attrName, image))
|
|
961
|
-
createData(leafPaint, image, attrValue, box);
|
|
962
|
-
if (firstUse) {
|
|
963
|
-
emit(ImageEvent.LOAD, event);
|
|
964
|
-
emit(ImageEvent.LOADED, event);
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
else if (image.error) {
|
|
968
|
-
if (firstUse) {
|
|
969
|
-
ui.forceUpdate('surface');
|
|
970
|
-
event.error = image.error;
|
|
971
|
-
emit(ImageEvent.ERROR, event);
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
else {
|
|
975
|
-
if (firstUse)
|
|
976
|
-
emit(ImageEvent.LOAD, event);
|
|
977
|
-
leafPaint.loadId = image.load(() => {
|
|
978
|
-
if (!ui.destroyed) {
|
|
979
|
-
if (hasNaturalSize(ui, attrName, image)) {
|
|
980
|
-
createData(leafPaint, image, attrValue, box);
|
|
981
|
-
ui.forceUpdate('surface');
|
|
982
|
-
}
|
|
983
|
-
emit(ImageEvent.LOADED, event);
|
|
984
|
-
}
|
|
985
|
-
}, (error) => {
|
|
986
|
-
ui.forceUpdate('surface');
|
|
987
|
-
event.error = error;
|
|
988
|
-
emit(ImageEvent.ERROR, event);
|
|
989
|
-
});
|
|
990
|
-
}
|
|
991
|
-
return leafPaint;
|
|
992
|
-
}
|
|
993
|
-
function hasNaturalSize(ui, attrName, image) {
|
|
994
|
-
if (attrName === 'fill' && !ui.__.__naturalWidth) {
|
|
995
|
-
const { __: d } = ui;
|
|
996
|
-
d.__naturalWidth = image.width;
|
|
997
|
-
d.__naturalHeight = image.height;
|
|
998
|
-
if (!d.__getInput('width') || !d.__getInput('height')) {
|
|
999
|
-
ui.forceUpdate('width');
|
|
1000
|
-
return false;
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
return true;
|
|
1004
|
-
}
|
|
1005
|
-
function emit(type, data) {
|
|
1006
|
-
if (data.target.hasEvent(type))
|
|
1007
|
-
data.target.emitEvent(new ImageEvent(type, data));
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
/******************************************************************************
|
|
1011
|
-
Copyright (c) Microsoft Corporation.
|
|
1012
|
-
|
|
1013
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
1014
|
-
purpose with or without fee is hereby granted.
|
|
1015
|
-
|
|
1016
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
1017
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
1018
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
1019
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
1020
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
1021
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
1022
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
1023
|
-
***************************************************************************** */
|
|
1024
|
-
/* global Reflect, Promise, SuppressedError, Symbol */
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
1028
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
1029
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
1030
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
1031
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
1032
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
1033
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
1034
|
-
});
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
1038
|
-
var e = new Error(message);
|
|
1039
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
1040
|
-
};
|
|
1041
|
-
|
|
1042
|
-
const { get: get$2, scale: scaleHelper, copy: copy$1 } = MatrixHelper;
|
|
1043
|
-
function createPattern(ui, paint, pixelRatio) {
|
|
1044
|
-
let { scaleX, scaleY } = ui.__world;
|
|
1045
|
-
const id = scaleX + '-' + scaleY;
|
|
1046
|
-
if (paint.patternId !== id && !ui.destroyed) {
|
|
1047
|
-
paint.patternId = id;
|
|
1048
|
-
scaleX = Math.abs(scaleX);
|
|
1049
|
-
scaleY = Math.abs(scaleY);
|
|
1050
|
-
const { image, data } = paint;
|
|
1051
|
-
const maxWidth = image.isSVG ? 4096 : Math.min(image.width, 4096);
|
|
1052
|
-
const maxHeight = image.isSVG ? 4096 : Math.min(image.height, 4096);
|
|
1053
|
-
let scale, matrix, { width, height, scaleX: sx, scaleY: sy, opacity, transform, mode } = data;
|
|
1054
|
-
if (sx) {
|
|
1055
|
-
matrix = get$2();
|
|
1056
|
-
copy$1(matrix, transform);
|
|
1057
|
-
scaleHelper(matrix, 1 / sx, 1 / sy);
|
|
1058
|
-
scaleX *= sx;
|
|
1059
|
-
scaleY *= sy;
|
|
1060
|
-
}
|
|
1061
|
-
scaleX *= pixelRatio;
|
|
1062
|
-
scaleY *= pixelRatio;
|
|
1063
|
-
width *= scaleX;
|
|
1064
|
-
height *= scaleY;
|
|
1065
|
-
if (width > maxWidth || height > maxHeight) {
|
|
1066
|
-
scale = Math.max(width / maxWidth, height / maxHeight);
|
|
1067
|
-
}
|
|
1068
|
-
if (scale) {
|
|
1069
|
-
scaleX /= scale;
|
|
1070
|
-
scaleY /= scale;
|
|
1071
|
-
width /= scale;
|
|
1072
|
-
height /= scale;
|
|
1073
|
-
}
|
|
1074
|
-
if (sx) {
|
|
1075
|
-
scaleX /= sx;
|
|
1076
|
-
scaleY /= sy;
|
|
1077
|
-
}
|
|
1078
|
-
if (transform || scaleX !== 1 || scaleY !== 1) {
|
|
1079
|
-
if (!matrix) {
|
|
1080
|
-
matrix = get$2();
|
|
1081
|
-
if (transform)
|
|
1082
|
-
copy$1(matrix, transform);
|
|
1083
|
-
}
|
|
1084
|
-
scaleHelper(matrix, 1 / scaleX, 1 / scaleY);
|
|
1085
|
-
}
|
|
1086
|
-
const style = Platform.canvas.createPattern(image.getCanvas(width < 1 ? 1 : width, height < 1 ? 1 : height, opacity), mode === 'repeat' ? 'repeat' : (Platform.origin.noRepeat || 'no-repeat'));
|
|
1087
|
-
try {
|
|
1088
|
-
if (paint.transform)
|
|
1089
|
-
paint.transform = null;
|
|
1090
|
-
if (matrix)
|
|
1091
|
-
style.setTransform ? style.setTransform(matrix) : paint.transform = matrix;
|
|
1092
|
-
}
|
|
1093
|
-
catch (_a) {
|
|
1094
|
-
paint.transform = matrix;
|
|
1095
|
-
}
|
|
1096
|
-
paint.style = style;
|
|
1097
|
-
return true;
|
|
1098
|
-
}
|
|
1099
|
-
else {
|
|
1100
|
-
return false;
|
|
1101
|
-
}
|
|
1102
|
-
}
|
|
1103
|
-
|
|
1104
|
-
function checkImage(ui, canvas, paint, allowPaint) {
|
|
1105
|
-
const { scaleX, scaleY } = ui.__world;
|
|
1106
|
-
if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
|
|
1107
|
-
return false;
|
|
1108
|
-
}
|
|
1109
|
-
else {
|
|
1110
|
-
if (allowPaint) {
|
|
1111
|
-
if (paint.image.isSVG && paint.data.mode !== 'repeat') {
|
|
1112
|
-
let { width, height } = paint.data;
|
|
1113
|
-
width *= scaleX * canvas.pixelRatio;
|
|
1114
|
-
height *= scaleY * canvas.pixelRatio;
|
|
1115
|
-
allowPaint = width > 4096 || height > 4096;
|
|
1116
|
-
}
|
|
1117
|
-
else {
|
|
1118
|
-
allowPaint = false;
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
1121
|
-
if (allowPaint) {
|
|
1122
|
-
canvas.save();
|
|
1123
|
-
canvas.clip();
|
|
1124
|
-
const { data } = paint;
|
|
1125
|
-
if (paint.blendMode)
|
|
1126
|
-
canvas.blendMode = paint.blendMode;
|
|
1127
|
-
if (data.opacity)
|
|
1128
|
-
canvas.opacity *= data.opacity;
|
|
1129
|
-
if (data.transform)
|
|
1130
|
-
canvas.transform(data.transform);
|
|
1131
|
-
canvas.drawImage(paint.image.view, 0, 0, data.width, data.height);
|
|
1132
|
-
canvas.restore();
|
|
1133
|
-
return true;
|
|
1134
|
-
}
|
|
1135
|
-
else {
|
|
1136
|
-
if (!paint.style) {
|
|
1137
|
-
createPattern(ui, paint, canvas.pixelRatio);
|
|
1138
|
-
}
|
|
1139
|
-
else {
|
|
1140
|
-
ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
|
|
1141
|
-
if (canvas.bounds.hit(ui.__world) && createPattern(ui, paint, canvas.pixelRatio))
|
|
1142
|
-
ui.forceUpdate('surface');
|
|
1143
|
-
}), 300);
|
|
1144
|
-
}
|
|
1145
|
-
return false;
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1148
|
-
}
|
|
1149
|
-
|
|
1150
|
-
function recycleImage(data, attrName) {
|
|
1151
|
-
const paints = (attrName === 'fill' ? data._fill : data._stroke);
|
|
1152
|
-
if (paints instanceof Array) {
|
|
1153
|
-
let image, recycleMap, input, url;
|
|
1154
|
-
for (let i = 0, len = paints.length; i < len; i++) {
|
|
1155
|
-
image = paints[i].image;
|
|
1156
|
-
url = image && image.url;
|
|
1157
|
-
if (url) {
|
|
1158
|
-
if (!recycleMap)
|
|
1159
|
-
recycleMap = {};
|
|
1160
|
-
recycleMap[url] = true;
|
|
1161
|
-
ImageManager.recycle(image);
|
|
1162
|
-
if (image.loading) {
|
|
1163
|
-
if (!input) {
|
|
1164
|
-
input = (data.__input && data.__input[attrName]) || [];
|
|
1165
|
-
if (!(input instanceof Array))
|
|
1166
|
-
input = [input];
|
|
1167
|
-
}
|
|
1168
|
-
image.unload(paints[i].loadId, !input.some((item) => item.url === url));
|
|
1169
|
-
}
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1172
|
-
return recycleMap;
|
|
1173
|
-
}
|
|
1174
|
-
return null;
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
|
-
function fillText(ui, canvas) {
|
|
1178
|
-
let row;
|
|
1179
|
-
const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
|
|
1180
|
-
for (let i = 0, len = rows.length; i < len; i++) {
|
|
1181
|
-
row = rows[i];
|
|
1182
|
-
if (row.text) {
|
|
1183
|
-
canvas.fillText(row.text, row.x, row.y);
|
|
1184
|
-
}
|
|
1185
|
-
else if (row.data) {
|
|
1186
|
-
row.data.forEach(charData => {
|
|
1187
|
-
canvas.fillText(charData.char, charData.x, row.y);
|
|
1188
|
-
});
|
|
1189
|
-
}
|
|
1190
|
-
if (decorationY)
|
|
1191
|
-
canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight);
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
|
|
1195
|
-
function fill(ui, canvas, fill) {
|
|
1196
|
-
canvas.fillStyle = fill;
|
|
1197
|
-
ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
|
|
1198
1027
|
}
|
|
1199
|
-
function
|
|
1200
|
-
|
|
1201
|
-
const
|
|
1202
|
-
|
|
1203
|
-
item = fills[i];
|
|
1204
|
-
if (item.image && checkImage(ui, canvas, item, !__font))
|
|
1205
|
-
continue;
|
|
1206
|
-
if (item.style) {
|
|
1207
|
-
canvas.fillStyle = item.style;
|
|
1208
|
-
if (item.transform) {
|
|
1209
|
-
canvas.save();
|
|
1210
|
-
canvas.transform(item.transform);
|
|
1211
|
-
if (item.blendMode)
|
|
1212
|
-
canvas.blendMode = item.blendMode;
|
|
1213
|
-
__font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
|
|
1214
|
-
canvas.restore();
|
|
1215
|
-
}
|
|
1216
|
-
else {
|
|
1217
|
-
if (item.blendMode) {
|
|
1218
|
-
canvas.saveBlendMode(item.blendMode);
|
|
1219
|
-
__font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
|
|
1220
|
-
canvas.restoreBlendMode();
|
|
1221
|
-
}
|
|
1222
|
-
else {
|
|
1223
|
-
__font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
}
|
|
1227
|
-
}
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
|
-
function strokeText(ui, canvas, stroke) {
|
|
1231
|
-
const { strokeAlign } = ui.__;
|
|
1232
|
-
const isStrokes = typeof stroke !== 'string';
|
|
1233
|
-
switch (strokeAlign) {
|
|
1234
|
-
case 'center':
|
|
1235
|
-
canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
|
|
1236
|
-
isStrokes ? drawStrokesStyle(ui, stroke, canvas, true) : drawTextStroke(ui, canvas);
|
|
1237
|
-
break;
|
|
1238
|
-
case 'inside':
|
|
1239
|
-
drawAlignStroke(ui, canvas, stroke, 'inside', isStrokes);
|
|
1240
|
-
break;
|
|
1241
|
-
case 'outside':
|
|
1242
|
-
drawAlignStroke(ui, canvas, stroke, 'outside', isStrokes);
|
|
1243
|
-
break;
|
|
1244
|
-
}
|
|
1245
|
-
}
|
|
1246
|
-
function drawAlignStroke(ui, canvas, stroke, align, isStrokes) {
|
|
1247
|
-
const { strokeWidth, __font } = ui.__;
|
|
1248
|
-
const out = canvas.getSameCanvas(true);
|
|
1249
|
-
out.setStroke(isStrokes ? undefined : stroke, strokeWidth * 2, ui.__);
|
|
1028
|
+
function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
|
|
1029
|
+
const { __strokeWidth, __font } = ui.__;
|
|
1030
|
+
const out = canvas.getSameCanvas(true, true);
|
|
1031
|
+
out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__);
|
|
1250
1032
|
out.font = __font;
|
|
1251
|
-
isStrokes ? drawStrokesStyle(
|
|
1033
|
+
isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
|
|
1252
1034
|
out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
|
|
1253
1035
|
fillText(ui, out);
|
|
1254
1036
|
out.blendMode = 'normal';
|
|
1255
|
-
|
|
1256
|
-
|
|
1037
|
+
if (ui.__worldFlipped) {
|
|
1038
|
+
canvas.copyWorldByReset(out, ui.__nowWorld);
|
|
1039
|
+
}
|
|
1040
|
+
else {
|
|
1041
|
+
canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
|
|
1042
|
+
}
|
|
1043
|
+
out.recycle(ui.__nowWorld);
|
|
1257
1044
|
}
|
|
1258
1045
|
function drawTextStroke(ui, canvas) {
|
|
1259
1046
|
let row;
|
|
@@ -1272,11 +1059,11 @@ function drawTextStroke(ui, canvas) {
|
|
|
1272
1059
|
canvas.strokeRect(row.x, row.y + decorationY, row.width, decorationHeight);
|
|
1273
1060
|
}
|
|
1274
1061
|
}
|
|
1275
|
-
function drawStrokesStyle(
|
|
1062
|
+
function drawStrokesStyle(strokes, isText, ui, canvas) {
|
|
1276
1063
|
let item;
|
|
1277
1064
|
for (let i = 0, len = strokes.length; i < len; i++) {
|
|
1278
1065
|
item = strokes[i];
|
|
1279
|
-
if (item.image && checkImage(ui, canvas, item, false))
|
|
1066
|
+
if (item.image && PaintImage.checkImage(ui, canvas, item, false))
|
|
1280
1067
|
continue;
|
|
1281
1068
|
if (item.style) {
|
|
1282
1069
|
canvas.strokeStyle = item.style;
|
|
@@ -1292,128 +1079,567 @@ function drawStrokesStyle(ui, strokes, canvas, isText) {
|
|
|
1292
1079
|
}
|
|
1293
1080
|
}
|
|
1294
1081
|
|
|
1295
|
-
function stroke(ui, canvas
|
|
1082
|
+
function stroke(stroke, ui, canvas) {
|
|
1296
1083
|
const options = ui.__;
|
|
1297
|
-
const {
|
|
1298
|
-
if (!
|
|
1084
|
+
const { __strokeWidth, strokeAlign, __font } = options;
|
|
1085
|
+
if (!__strokeWidth)
|
|
1299
1086
|
return;
|
|
1300
1087
|
if (__font) {
|
|
1301
|
-
strokeText(ui, canvas
|
|
1088
|
+
strokeText(stroke, ui, canvas);
|
|
1302
1089
|
}
|
|
1303
1090
|
else {
|
|
1304
1091
|
switch (strokeAlign) {
|
|
1305
1092
|
case 'center':
|
|
1306
|
-
canvas.setStroke(stroke,
|
|
1093
|
+
canvas.setStroke(stroke, __strokeWidth, options);
|
|
1307
1094
|
canvas.stroke();
|
|
1308
1095
|
break;
|
|
1309
1096
|
case 'inside':
|
|
1310
1097
|
canvas.save();
|
|
1311
|
-
canvas.setStroke(stroke,
|
|
1098
|
+
canvas.setStroke(stroke, __strokeWidth * 2, options);
|
|
1312
1099
|
options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
|
|
1313
1100
|
canvas.stroke();
|
|
1314
1101
|
canvas.restore();
|
|
1315
1102
|
break;
|
|
1316
1103
|
case 'outside':
|
|
1317
|
-
const out = canvas.getSameCanvas(true);
|
|
1318
|
-
out.setStroke(stroke,
|
|
1104
|
+
const out = canvas.getSameCanvas(true, true);
|
|
1105
|
+
out.setStroke(stroke, __strokeWidth * 2, options);
|
|
1319
1106
|
ui.__drawRenderPath(out);
|
|
1320
1107
|
out.stroke();
|
|
1321
1108
|
options.windingRule ? out.clip(options.windingRule) : out.clip();
|
|
1322
1109
|
out.clearWorld(ui.__layout.renderBounds);
|
|
1323
|
-
|
|
1324
|
-
|
|
1110
|
+
if (ui.__worldFlipped) {
|
|
1111
|
+
canvas.copyWorldByReset(out, ui.__nowWorld);
|
|
1112
|
+
}
|
|
1113
|
+
else {
|
|
1114
|
+
canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
|
|
1115
|
+
}
|
|
1116
|
+
out.recycle(ui.__nowWorld);
|
|
1117
|
+
break;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
function strokes(strokes, ui, canvas) {
|
|
1122
|
+
const options = ui.__;
|
|
1123
|
+
const { __strokeWidth, strokeAlign, __font } = options;
|
|
1124
|
+
if (!__strokeWidth)
|
|
1125
|
+
return;
|
|
1126
|
+
if (__font) {
|
|
1127
|
+
strokeText(strokes, ui, canvas);
|
|
1128
|
+
}
|
|
1129
|
+
else {
|
|
1130
|
+
switch (strokeAlign) {
|
|
1131
|
+
case 'center':
|
|
1132
|
+
canvas.setStroke(undefined, __strokeWidth, options);
|
|
1133
|
+
drawStrokesStyle(strokes, false, ui, canvas);
|
|
1325
1134
|
break;
|
|
1135
|
+
case 'inside':
|
|
1136
|
+
canvas.save();
|
|
1137
|
+
canvas.setStroke(undefined, __strokeWidth * 2, options);
|
|
1138
|
+
options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
|
|
1139
|
+
drawStrokesStyle(strokes, false, ui, canvas);
|
|
1140
|
+
canvas.restore();
|
|
1141
|
+
break;
|
|
1142
|
+
case 'outside':
|
|
1143
|
+
const { renderBounds } = ui.__layout;
|
|
1144
|
+
const out = canvas.getSameCanvas(true, true);
|
|
1145
|
+
ui.__drawRenderPath(out);
|
|
1146
|
+
out.setStroke(undefined, __strokeWidth * 2, options);
|
|
1147
|
+
drawStrokesStyle(strokes, false, ui, out);
|
|
1148
|
+
options.windingRule ? out.clip(options.windingRule) : out.clip();
|
|
1149
|
+
out.clearWorld(renderBounds);
|
|
1150
|
+
if (ui.__worldFlipped) {
|
|
1151
|
+
canvas.copyWorldByReset(out, ui.__nowWorld);
|
|
1152
|
+
}
|
|
1153
|
+
else {
|
|
1154
|
+
canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
|
|
1155
|
+
}
|
|
1156
|
+
out.recycle(ui.__nowWorld);
|
|
1157
|
+
break;
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
const { getSpread, getOuterOf, getByMove, getIntersectData } = BoundsHelper;
|
|
1163
|
+
function shape(ui, current, options) {
|
|
1164
|
+
const canvas = current.getSameCanvas();
|
|
1165
|
+
const nowWorld = ui.__nowWorld;
|
|
1166
|
+
let bounds, fitMatrix, shapeBounds, worldCanvas;
|
|
1167
|
+
let { scaleX, scaleY } = nowWorld;
|
|
1168
|
+
if (scaleX < 0)
|
|
1169
|
+
scaleX = -scaleX;
|
|
1170
|
+
if (scaleY < 0)
|
|
1171
|
+
scaleY = -scaleY;
|
|
1172
|
+
if (current.bounds.includes(nowWorld)) {
|
|
1173
|
+
worldCanvas = canvas;
|
|
1174
|
+
bounds = shapeBounds = nowWorld;
|
|
1175
|
+
}
|
|
1176
|
+
else {
|
|
1177
|
+
const { renderShapeSpread: spread } = ui.__layout;
|
|
1178
|
+
const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, scaleX === scaleY ? spread * scaleX : [spread * scaleY, spread * scaleX]) : current.bounds, nowWorld);
|
|
1179
|
+
fitMatrix = current.bounds.getFitMatrix(worldClipBounds);
|
|
1180
|
+
let { a: fitScaleX, d: fitScaleY } = fitMatrix;
|
|
1181
|
+
if (fitMatrix.a < 1) {
|
|
1182
|
+
worldCanvas = current.getSameCanvas();
|
|
1183
|
+
ui.__renderShape(worldCanvas, options);
|
|
1184
|
+
scaleX *= fitScaleX;
|
|
1185
|
+
scaleY *= fitScaleY;
|
|
1186
|
+
}
|
|
1187
|
+
shapeBounds = getOuterOf(nowWorld, fitMatrix);
|
|
1188
|
+
bounds = getByMove(shapeBounds, -fitMatrix.e, -fitMatrix.f);
|
|
1189
|
+
if (options.matrix) {
|
|
1190
|
+
const { matrix } = options;
|
|
1191
|
+
fitMatrix.multiply(matrix);
|
|
1192
|
+
fitScaleX *= matrix.scaleX;
|
|
1193
|
+
fitScaleY *= matrix.scaleY;
|
|
1194
|
+
}
|
|
1195
|
+
options = Object.assign(Object.assign({}, options), { matrix: fitMatrix.withScale(fitScaleX, fitScaleY) });
|
|
1196
|
+
}
|
|
1197
|
+
ui.__renderShape(canvas, options);
|
|
1198
|
+
return {
|
|
1199
|
+
canvas, matrix: fitMatrix, bounds,
|
|
1200
|
+
worldCanvas, shapeBounds, scaleX, scaleY
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
let recycleMap;
|
|
1205
|
+
function compute(attrName, ui) {
|
|
1206
|
+
const data = ui.__, leafPaints = [];
|
|
1207
|
+
let paints = data.__input[attrName], hasOpacityPixel;
|
|
1208
|
+
if (!(paints instanceof Array))
|
|
1209
|
+
paints = [paints];
|
|
1210
|
+
recycleMap = PaintImage.recycleImage(attrName, data);
|
|
1211
|
+
for (let i = 0, len = paints.length, item; i < len; i++) {
|
|
1212
|
+
item = getLeafPaint(attrName, paints[i], ui);
|
|
1213
|
+
if (item)
|
|
1214
|
+
leafPaints.push(item);
|
|
1215
|
+
}
|
|
1216
|
+
data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
|
|
1217
|
+
if (leafPaints.length && leafPaints[0].image)
|
|
1218
|
+
hasOpacityPixel = leafPaints[0].image.hasOpacityPixel;
|
|
1219
|
+
if (attrName === 'fill') {
|
|
1220
|
+
data.__pixelFill = hasOpacityPixel;
|
|
1221
|
+
}
|
|
1222
|
+
else {
|
|
1223
|
+
data.__pixelStroke = hasOpacityPixel;
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
function getLeafPaint(attrName, paint, ui) {
|
|
1227
|
+
if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
|
|
1228
|
+
return undefined;
|
|
1229
|
+
const { boxBounds } = ui.__layout;
|
|
1230
|
+
switch (paint.type) {
|
|
1231
|
+
case 'solid':
|
|
1232
|
+
let { type, blendMode, color, opacity } = paint;
|
|
1233
|
+
return { type, blendMode, style: ColorConvert.string(color, opacity) };
|
|
1234
|
+
case 'image':
|
|
1235
|
+
return PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
|
|
1236
|
+
case 'linear':
|
|
1237
|
+
return PaintGradient.linearGradient(paint, boxBounds);
|
|
1238
|
+
case 'radial':
|
|
1239
|
+
return PaintGradient.radialGradient(paint, boxBounds);
|
|
1240
|
+
case 'angular':
|
|
1241
|
+
return PaintGradient.conicGradient(paint, boxBounds);
|
|
1242
|
+
default:
|
|
1243
|
+
return paint.r !== undefined ? { type: 'solid', style: ColorConvert.string(paint) } : undefined;
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
const PaintModule = {
|
|
1248
|
+
compute,
|
|
1249
|
+
fill,
|
|
1250
|
+
fills,
|
|
1251
|
+
fillText,
|
|
1252
|
+
stroke,
|
|
1253
|
+
strokes,
|
|
1254
|
+
strokeText,
|
|
1255
|
+
drawTextStroke,
|
|
1256
|
+
shape
|
|
1257
|
+
};
|
|
1258
|
+
|
|
1259
|
+
let origin = {};
|
|
1260
|
+
const { get: get$3, rotateOfOuter: rotateOfOuter$1, translate: translate$1, scaleOfOuter: scaleOfOuter$1, scale: scaleHelper, rotate } = MatrixHelper;
|
|
1261
|
+
function fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation) {
|
|
1262
|
+
const transform = get$3();
|
|
1263
|
+
translate$1(transform, box.x + x, box.y + y);
|
|
1264
|
+
scaleHelper(transform, scaleX, scaleY);
|
|
1265
|
+
if (rotation)
|
|
1266
|
+
rotateOfOuter$1(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
|
|
1267
|
+
data.transform = transform;
|
|
1268
|
+
}
|
|
1269
|
+
function clipMode(data, box, x, y, scaleX, scaleY, rotation) {
|
|
1270
|
+
const transform = get$3();
|
|
1271
|
+
translate$1(transform, box.x + x, box.y + y);
|
|
1272
|
+
if (scaleX)
|
|
1273
|
+
scaleHelper(transform, scaleX, scaleY);
|
|
1274
|
+
if (rotation)
|
|
1275
|
+
rotate(transform, rotation);
|
|
1276
|
+
data.transform = transform;
|
|
1277
|
+
}
|
|
1278
|
+
function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align) {
|
|
1279
|
+
const transform = get$3();
|
|
1280
|
+
if (rotation) {
|
|
1281
|
+
if (align === 'center') {
|
|
1282
|
+
rotateOfOuter$1(transform, { x: width / 2, y: height / 2 }, rotation);
|
|
1283
|
+
}
|
|
1284
|
+
else {
|
|
1285
|
+
rotate(transform, rotation);
|
|
1286
|
+
switch (rotation) {
|
|
1287
|
+
case 90:
|
|
1288
|
+
translate$1(transform, height, 0);
|
|
1289
|
+
break;
|
|
1290
|
+
case 180:
|
|
1291
|
+
translate$1(transform, width, height);
|
|
1292
|
+
break;
|
|
1293
|
+
case 270:
|
|
1294
|
+
translate$1(transform, 0, width);
|
|
1295
|
+
break;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
origin.x = box.x + x;
|
|
1300
|
+
origin.y = box.y + y;
|
|
1301
|
+
translate$1(transform, origin.x, origin.y);
|
|
1302
|
+
if (scaleX)
|
|
1303
|
+
scaleOfOuter$1(transform, origin, scaleX, scaleY);
|
|
1304
|
+
data.transform = transform;
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
const { get: get$2, translate } = MatrixHelper;
|
|
1308
|
+
const tempBox = new Bounds();
|
|
1309
|
+
const tempPoint = {};
|
|
1310
|
+
function createData(leafPaint, image, paint, box) {
|
|
1311
|
+
const { blendMode } = paint;
|
|
1312
|
+
if (blendMode)
|
|
1313
|
+
leafPaint.blendMode = blendMode;
|
|
1314
|
+
leafPaint.data = getPatternData(paint, box, image);
|
|
1315
|
+
}
|
|
1316
|
+
function getPatternData(paint, box, image) {
|
|
1317
|
+
let { width, height } = image;
|
|
1318
|
+
if (paint.padding)
|
|
1319
|
+
box = tempBox.set(box).shrink(paint.padding);
|
|
1320
|
+
const { opacity, mode, align, offset, scale, size, rotation, repeat } = paint;
|
|
1321
|
+
const sameBox = box.width === width && box.height === height;
|
|
1322
|
+
const data = { mode };
|
|
1323
|
+
const swapSize = align !== 'center' && (rotation || 0) % 180 === 90;
|
|
1324
|
+
const swapWidth = swapSize ? height : width, swapHeight = swapSize ? width : height;
|
|
1325
|
+
let x = 0, y = 0, scaleX, scaleY;
|
|
1326
|
+
if (!mode || mode === 'cover' || mode === 'fit') {
|
|
1327
|
+
if (!sameBox || rotation) {
|
|
1328
|
+
const sw = box.width / swapWidth, sh = box.height / swapHeight;
|
|
1329
|
+
scaleX = scaleY = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
|
|
1330
|
+
x += (box.width - width * scaleX) / 2, y += (box.height - height * scaleY) / 2;
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
else if (size) {
|
|
1334
|
+
scaleX = (typeof size === 'number' ? size : size.width) / width;
|
|
1335
|
+
scaleY = (typeof size === 'number' ? size : size.height) / height;
|
|
1336
|
+
}
|
|
1337
|
+
else if (scale) {
|
|
1338
|
+
scaleX = typeof scale === 'number' ? scale : scale.x;
|
|
1339
|
+
scaleY = typeof scale === 'number' ? scale : scale.y;
|
|
1340
|
+
}
|
|
1341
|
+
if (align) {
|
|
1342
|
+
const imageBounds = { x, y, width: swapWidth, height: swapHeight };
|
|
1343
|
+
if (scaleX)
|
|
1344
|
+
imageBounds.width *= scaleX, imageBounds.height *= scaleY;
|
|
1345
|
+
AlignHelper.toPoint(align, imageBounds, box, tempPoint, true);
|
|
1346
|
+
x += tempPoint.x, y += tempPoint.y;
|
|
1347
|
+
}
|
|
1348
|
+
if (offset)
|
|
1349
|
+
x += offset.x, y += offset.y;
|
|
1350
|
+
switch (mode) {
|
|
1351
|
+
case 'strench':
|
|
1352
|
+
if (!sameBox)
|
|
1353
|
+
width = box.width, height = box.height;
|
|
1354
|
+
break;
|
|
1355
|
+
case 'normal':
|
|
1356
|
+
case 'clip':
|
|
1357
|
+
if (x || y || scaleX || rotation)
|
|
1358
|
+
clipMode(data, box, x, y, scaleX, scaleY, rotation);
|
|
1359
|
+
break;
|
|
1360
|
+
case 'repeat':
|
|
1361
|
+
if (!sameBox || scaleX || rotation)
|
|
1362
|
+
repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, align);
|
|
1363
|
+
if (!repeat)
|
|
1364
|
+
data.repeat = 'repeat';
|
|
1365
|
+
break;
|
|
1366
|
+
case 'fit':
|
|
1367
|
+
case 'cover':
|
|
1368
|
+
default:
|
|
1369
|
+
if (scaleX)
|
|
1370
|
+
fillOrFitMode(data, box, x, y, scaleX, scaleY, rotation);
|
|
1371
|
+
}
|
|
1372
|
+
if (!data.transform) {
|
|
1373
|
+
if (box.x || box.y) {
|
|
1374
|
+
data.transform = get$2();
|
|
1375
|
+
translate(data.transform, box.x, box.y);
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
if (scaleX && mode !== 'strench') {
|
|
1379
|
+
data.scaleX = scaleX;
|
|
1380
|
+
data.scaleY = scaleY;
|
|
1381
|
+
}
|
|
1382
|
+
data.width = width;
|
|
1383
|
+
data.height = height;
|
|
1384
|
+
if (opacity)
|
|
1385
|
+
data.opacity = opacity;
|
|
1386
|
+
if (repeat)
|
|
1387
|
+
data.repeat = typeof repeat === 'string' ? (repeat === 'x' ? 'repeat-x' : 'repeat-y') : 'repeat';
|
|
1388
|
+
return data;
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
let cache, box = new Bounds();
|
|
1392
|
+
const { isSame } = BoundsHelper;
|
|
1393
|
+
function image(ui, attrName, paint, boxBounds, firstUse) {
|
|
1394
|
+
let leafPaint, event;
|
|
1395
|
+
const image = ImageManager.get(paint);
|
|
1396
|
+
if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
|
|
1397
|
+
leafPaint = cache.leafPaint;
|
|
1398
|
+
}
|
|
1399
|
+
else {
|
|
1400
|
+
leafPaint = { type: paint.type, image };
|
|
1401
|
+
cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
|
|
1402
|
+
}
|
|
1403
|
+
if (firstUse || image.loading)
|
|
1404
|
+
event = { image, attrName, attrValue: paint };
|
|
1405
|
+
if (image.ready) {
|
|
1406
|
+
checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
|
|
1407
|
+
if (firstUse) {
|
|
1408
|
+
onLoad(ui, event);
|
|
1409
|
+
onLoadSuccess(ui, event);
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
else if (image.error) {
|
|
1413
|
+
if (firstUse)
|
|
1414
|
+
onLoadError(ui, event, image.error);
|
|
1415
|
+
}
|
|
1416
|
+
else {
|
|
1417
|
+
ignoreRender(ui, true);
|
|
1418
|
+
if (firstUse)
|
|
1419
|
+
onLoad(ui, event);
|
|
1420
|
+
leafPaint.loadId = image.load(() => {
|
|
1421
|
+
ignoreRender(ui, false);
|
|
1422
|
+
if (!ui.destroyed) {
|
|
1423
|
+
if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds)) {
|
|
1424
|
+
if (image.hasOpacityPixel)
|
|
1425
|
+
ui.__layout.hitCanvasChanged = true;
|
|
1426
|
+
ui.forceUpdate('surface');
|
|
1427
|
+
}
|
|
1428
|
+
onLoadSuccess(ui, event);
|
|
1429
|
+
}
|
|
1430
|
+
leafPaint.loadId = null;
|
|
1431
|
+
}, (error) => {
|
|
1432
|
+
ignoreRender(ui, false);
|
|
1433
|
+
onLoadError(ui, event, error);
|
|
1434
|
+
leafPaint.loadId = null;
|
|
1435
|
+
});
|
|
1436
|
+
}
|
|
1437
|
+
return leafPaint;
|
|
1438
|
+
}
|
|
1439
|
+
function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
|
|
1440
|
+
if (attrName === 'fill' && !ui.__.__naturalWidth) {
|
|
1441
|
+
const data = ui.__;
|
|
1442
|
+
data.__naturalWidth = image.width / data.pixelRatio;
|
|
1443
|
+
data.__naturalHeight = image.height / data.pixelRatio;
|
|
1444
|
+
if (data.__autoSide) {
|
|
1445
|
+
ui.forceUpdate('width');
|
|
1446
|
+
if (ui.__proxyData) {
|
|
1447
|
+
ui.setProxyAttr('width', data.width);
|
|
1448
|
+
ui.setProxyAttr('height', data.height);
|
|
1449
|
+
}
|
|
1450
|
+
return false;
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
if (!leafPaint.data)
|
|
1454
|
+
createData(leafPaint, image, paint, boxBounds);
|
|
1455
|
+
return true;
|
|
1456
|
+
}
|
|
1457
|
+
function onLoad(ui, event) {
|
|
1458
|
+
emit(ui, ImageEvent.LOAD, event);
|
|
1459
|
+
}
|
|
1460
|
+
function onLoadSuccess(ui, event) {
|
|
1461
|
+
emit(ui, ImageEvent.LOADED, event);
|
|
1462
|
+
}
|
|
1463
|
+
function onLoadError(ui, event, error) {
|
|
1464
|
+
event.error = error;
|
|
1465
|
+
ui.forceUpdate('surface');
|
|
1466
|
+
emit(ui, ImageEvent.ERROR, event);
|
|
1467
|
+
}
|
|
1468
|
+
function emit(ui, type, data) {
|
|
1469
|
+
if (ui.hasEvent(type))
|
|
1470
|
+
ui.emitEvent(new ImageEvent(type, data));
|
|
1471
|
+
}
|
|
1472
|
+
function ignoreRender(ui, value) {
|
|
1473
|
+
const { leafer } = ui;
|
|
1474
|
+
if (leafer && leafer.viewReady)
|
|
1475
|
+
leafer.renderer.ignore = value;
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
const { get: get$1, scale, copy: copy$1 } = MatrixHelper;
|
|
1479
|
+
const { ceil, abs: abs$1 } = Math;
|
|
1480
|
+
function createPattern(ui, paint, pixelRatio) {
|
|
1481
|
+
let { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
|
|
1482
|
+
const id = scaleX + '-' + scaleY;
|
|
1483
|
+
if (paint.patternId !== id && !ui.destroyed) {
|
|
1484
|
+
scaleX = abs$1(scaleX);
|
|
1485
|
+
scaleY = abs$1(scaleY);
|
|
1486
|
+
const { image, data } = paint;
|
|
1487
|
+
let imageScale, imageMatrix, { width, height, scaleX: sx, scaleY: sy, opacity, transform, repeat } = data;
|
|
1488
|
+
if (sx) {
|
|
1489
|
+
imageMatrix = get$1();
|
|
1490
|
+
copy$1(imageMatrix, transform);
|
|
1491
|
+
scale(imageMatrix, 1 / sx, 1 / sy);
|
|
1492
|
+
scaleX *= sx;
|
|
1493
|
+
scaleY *= sy;
|
|
1494
|
+
}
|
|
1495
|
+
scaleX *= pixelRatio;
|
|
1496
|
+
scaleY *= pixelRatio;
|
|
1497
|
+
width *= scaleX;
|
|
1498
|
+
height *= scaleY;
|
|
1499
|
+
const size = width * height;
|
|
1500
|
+
if (!repeat) {
|
|
1501
|
+
if (size > Platform.image.maxCacheSize)
|
|
1502
|
+
return false;
|
|
1326
1503
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1504
|
+
let maxSize = Platform.image.maxPatternSize;
|
|
1505
|
+
if (!image.isSVG) {
|
|
1506
|
+
const imageSize = image.width * image.height;
|
|
1507
|
+
if (maxSize > imageSize)
|
|
1508
|
+
maxSize = imageSize;
|
|
1509
|
+
}
|
|
1510
|
+
if (size > maxSize)
|
|
1511
|
+
imageScale = Math.sqrt(size / maxSize);
|
|
1512
|
+
if (imageScale) {
|
|
1513
|
+
scaleX /= imageScale;
|
|
1514
|
+
scaleY /= imageScale;
|
|
1515
|
+
width /= imageScale;
|
|
1516
|
+
height /= imageScale;
|
|
1517
|
+
}
|
|
1518
|
+
if (sx) {
|
|
1519
|
+
scaleX /= sx;
|
|
1520
|
+
scaleY /= sy;
|
|
1521
|
+
}
|
|
1522
|
+
if (transform || scaleX !== 1 || scaleY !== 1) {
|
|
1523
|
+
if (!imageMatrix) {
|
|
1524
|
+
imageMatrix = get$1();
|
|
1525
|
+
if (transform)
|
|
1526
|
+
copy$1(imageMatrix, transform);
|
|
1527
|
+
}
|
|
1528
|
+
scale(imageMatrix, 1 / scaleX, 1 / scaleY);
|
|
1529
|
+
}
|
|
1530
|
+
const canvas = image.getCanvas(ceil(width) || 1, ceil(height) || 1, opacity);
|
|
1531
|
+
const pattern = image.getPattern(canvas, repeat || (Platform.origin.noRepeat || 'no-repeat'), imageMatrix, paint);
|
|
1532
|
+
paint.style = pattern;
|
|
1533
|
+
paint.patternId = id;
|
|
1534
|
+
return true;
|
|
1336
1535
|
}
|
|
1337
1536
|
else {
|
|
1338
|
-
|
|
1339
|
-
case 'center':
|
|
1340
|
-
canvas.setStroke(undefined, strokeWidth, options);
|
|
1341
|
-
drawStrokesStyle(ui, strokes, canvas);
|
|
1342
|
-
break;
|
|
1343
|
-
case 'inside':
|
|
1344
|
-
canvas.save();
|
|
1345
|
-
canvas.setStroke(undefined, strokeWidth * 2, options);
|
|
1346
|
-
options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
|
|
1347
|
-
drawStrokesStyle(ui, strokes, canvas);
|
|
1348
|
-
canvas.restore();
|
|
1349
|
-
break;
|
|
1350
|
-
case 'outside':
|
|
1351
|
-
const { renderBounds } = ui.__layout;
|
|
1352
|
-
const out = canvas.getSameCanvas(true);
|
|
1353
|
-
ui.__drawRenderPath(out);
|
|
1354
|
-
out.setStroke(undefined, strokeWidth * 2, ui.__);
|
|
1355
|
-
drawStrokesStyle(ui, strokes, out);
|
|
1356
|
-
options.windingRule ? out.clip(options.windingRule) : out.clip();
|
|
1357
|
-
out.clearWorld(renderBounds);
|
|
1358
|
-
canvas.copyWorldToInner(out, ui.__world, renderBounds);
|
|
1359
|
-
out.recycle();
|
|
1360
|
-
break;
|
|
1361
|
-
}
|
|
1537
|
+
return false;
|
|
1362
1538
|
}
|
|
1363
1539
|
}
|
|
1364
1540
|
|
|
1365
|
-
const {
|
|
1366
|
-
function
|
|
1367
|
-
const
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
const { __world } = ui;
|
|
1371
|
-
let { scaleX, scaleY } = __world;
|
|
1372
|
-
if (scaleX < 0)
|
|
1373
|
-
scaleX = -scaleX;
|
|
1374
|
-
if (scaleY < 0)
|
|
1375
|
-
scaleY = -scaleY;
|
|
1376
|
-
if (!current.bounds.includes(__world, options.matrix)) {
|
|
1377
|
-
const { renderShapeSpread: spread } = ui.__layout;
|
|
1378
|
-
const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, spread * scaleX, spread * scaleY) : current.bounds, __world, options.matrix);
|
|
1379
|
-
matrix = current.bounds.getFitMatrix(worldClipBounds);
|
|
1380
|
-
if (matrix.a < 1) {
|
|
1381
|
-
worldCanvas = current.getSameCanvas();
|
|
1382
|
-
ui.__renderShape(worldCanvas, options);
|
|
1383
|
-
scaleX *= matrix.a;
|
|
1384
|
-
scaleY *= matrix.d;
|
|
1385
|
-
}
|
|
1386
|
-
shapeBounds = getOuterOf(__world, matrix);
|
|
1387
|
-
bounds = getByMove(shapeBounds, -matrix.e, -matrix.f);
|
|
1388
|
-
if (options.matrix)
|
|
1389
|
-
matrix.multiply(options.matrix);
|
|
1390
|
-
options = Object.assign(Object.assign({}, options), { matrix });
|
|
1541
|
+
const { abs } = Math;
|
|
1542
|
+
function checkImage(ui, canvas, paint, allowPaint) {
|
|
1543
|
+
const { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
|
|
1544
|
+
if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
|
|
1545
|
+
return false;
|
|
1391
1546
|
}
|
|
1392
1547
|
else {
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1548
|
+
const { data } = paint;
|
|
1549
|
+
if (allowPaint) {
|
|
1550
|
+
if (!data.repeat) {
|
|
1551
|
+
let { width, height } = data;
|
|
1552
|
+
width *= abs(scaleX) * canvas.pixelRatio;
|
|
1553
|
+
height *= abs(scaleY) * canvas.pixelRatio;
|
|
1554
|
+
if (data.scaleX) {
|
|
1555
|
+
width *= data.scaleX;
|
|
1556
|
+
height *= data.scaleY;
|
|
1557
|
+
}
|
|
1558
|
+
allowPaint = (width * height > Platform.image.maxCacheSize) || Export.running;
|
|
1559
|
+
}
|
|
1560
|
+
else {
|
|
1561
|
+
allowPaint = false;
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
if (allowPaint) {
|
|
1565
|
+
canvas.save();
|
|
1566
|
+
canvas.clip();
|
|
1567
|
+
if (paint.blendMode)
|
|
1568
|
+
canvas.blendMode = paint.blendMode;
|
|
1569
|
+
if (data.opacity)
|
|
1570
|
+
canvas.opacity *= data.opacity;
|
|
1571
|
+
if (data.transform)
|
|
1572
|
+
canvas.transform(data.transform);
|
|
1573
|
+
canvas.drawImage(paint.image.view, 0, 0, data.width, data.height);
|
|
1574
|
+
canvas.restore();
|
|
1575
|
+
return true;
|
|
1397
1576
|
}
|
|
1398
1577
|
else {
|
|
1399
|
-
|
|
1578
|
+
if (!paint.style || Export.running) {
|
|
1579
|
+
createPattern(ui, paint, canvas.pixelRatio);
|
|
1580
|
+
}
|
|
1581
|
+
else {
|
|
1582
|
+
if (!paint.patternTask) {
|
|
1583
|
+
paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
|
|
1584
|
+
paint.patternTask = null;
|
|
1585
|
+
if (canvas.bounds.hit(ui.__nowWorld))
|
|
1586
|
+
createPattern(ui, paint, canvas.pixelRatio);
|
|
1587
|
+
ui.forceUpdate('surface');
|
|
1588
|
+
}), 300);
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
return false;
|
|
1400
1592
|
}
|
|
1401
|
-
worldCanvas = canvas;
|
|
1402
1593
|
}
|
|
1403
|
-
ui.__renderShape(canvas, options);
|
|
1404
|
-
return {
|
|
1405
|
-
canvas, matrix, bounds,
|
|
1406
|
-
worldCanvas, shapeBounds, scaleX, scaleY
|
|
1407
|
-
};
|
|
1408
1594
|
}
|
|
1409
1595
|
|
|
1410
|
-
|
|
1411
|
-
const
|
|
1596
|
+
function recycleImage(attrName, data) {
|
|
1597
|
+
const paints = data['_' + attrName];
|
|
1598
|
+
if (paints instanceof Array) {
|
|
1599
|
+
let image, recycleMap, input, url;
|
|
1600
|
+
for (let i = 0, len = paints.length; i < len; i++) {
|
|
1601
|
+
image = paints[i].image;
|
|
1602
|
+
url = image && image.url;
|
|
1603
|
+
if (url) {
|
|
1604
|
+
if (!recycleMap)
|
|
1605
|
+
recycleMap = {};
|
|
1606
|
+
recycleMap[url] = true;
|
|
1607
|
+
ImageManager.recycle(image);
|
|
1608
|
+
if (image.loading) {
|
|
1609
|
+
if (!input) {
|
|
1610
|
+
input = (data.__input && data.__input[attrName]) || [];
|
|
1611
|
+
if (!(input instanceof Array))
|
|
1612
|
+
input = [input];
|
|
1613
|
+
}
|
|
1614
|
+
image.unload(paints[i].loadId, !input.some((item) => item.url === url));
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
return recycleMap;
|
|
1619
|
+
}
|
|
1620
|
+
return null;
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
const PaintImageModule = {
|
|
1624
|
+
image,
|
|
1625
|
+
checkImage,
|
|
1626
|
+
createPattern,
|
|
1627
|
+
recycleImage,
|
|
1628
|
+
createData,
|
|
1629
|
+
getPatternData,
|
|
1630
|
+
fillOrFitMode,
|
|
1631
|
+
clipMode,
|
|
1632
|
+
repeatMode
|
|
1633
|
+
};
|
|
1634
|
+
|
|
1635
|
+
const { toPoint: toPoint$2 } = AroundHelper;
|
|
1636
|
+
const realFrom$2 = {};
|
|
1637
|
+
const realTo$2 = {};
|
|
1412
1638
|
function linearGradient(paint, box) {
|
|
1413
1639
|
let { from, to, type, blendMode, opacity } = paint;
|
|
1414
|
-
from ||
|
|
1415
|
-
to ||
|
|
1416
|
-
const style = Platform.canvas.createLinearGradient(
|
|
1640
|
+
toPoint$2(from || 'top', box, realFrom$2);
|
|
1641
|
+
toPoint$2(to || 'bottom', box, realTo$2);
|
|
1642
|
+
const style = Platform.canvas.createLinearGradient(realFrom$2.x, realFrom$2.y, realTo$2.x, realTo$2.y);
|
|
1417
1643
|
applyStops(style, paint.stops, opacity);
|
|
1418
1644
|
const data = { type, style };
|
|
1419
1645
|
if (blendMode)
|
|
@@ -1424,124 +1650,84 @@ function applyStops(gradient, stops, opacity) {
|
|
|
1424
1650
|
let stop;
|
|
1425
1651
|
for (let i = 0, len = stops.length; i < len; i++) {
|
|
1426
1652
|
stop = stops[i];
|
|
1427
|
-
|
|
1653
|
+
if (typeof stop === 'string') {
|
|
1654
|
+
gradient.addColorStop(i / (len - 1), ColorConvert.string(stop, opacity));
|
|
1655
|
+
}
|
|
1656
|
+
else {
|
|
1657
|
+
gradient.addColorStop(stop.offset, ColorConvert.string(stop.color, opacity));
|
|
1658
|
+
}
|
|
1428
1659
|
}
|
|
1429
1660
|
}
|
|
1430
1661
|
|
|
1431
|
-
const {
|
|
1432
|
-
const { get
|
|
1433
|
-
const
|
|
1434
|
-
const defaultTo$1 = { x: 0.5, y: 1 };
|
|
1662
|
+
const { getAngle, getDistance: getDistance$1 } = PointHelper;
|
|
1663
|
+
const { get, rotateOfOuter, scaleOfOuter } = MatrixHelper;
|
|
1664
|
+
const { toPoint: toPoint$1 } = AroundHelper;
|
|
1435
1665
|
const realFrom$1 = {};
|
|
1436
1666
|
const realTo$1 = {};
|
|
1437
1667
|
function radialGradient(paint, box) {
|
|
1438
1668
|
let { from, to, type, opacity, blendMode, stretch } = paint;
|
|
1439
|
-
from ||
|
|
1440
|
-
to ||
|
|
1441
|
-
const { x, y, width, height } = box;
|
|
1442
|
-
set$1(realFrom$1, x + from.x * width, y + from.y * height);
|
|
1443
|
-
set$1(realTo$1, x + to.x * width, y + to.y * height);
|
|
1444
|
-
let transform;
|
|
1445
|
-
if (width !== height || stretch) {
|
|
1446
|
-
transform = get$1();
|
|
1447
|
-
scaleOfOuter$1(transform, realFrom$1, width / height * (stretch || 1), 1);
|
|
1448
|
-
rotateOfOuter$1(transform, realFrom$1, getAngle$1(realFrom$1, realTo$1) + 90);
|
|
1449
|
-
}
|
|
1669
|
+
toPoint$1(from || 'center', box, realFrom$1);
|
|
1670
|
+
toPoint$1(to || 'bottom', box, realTo$1);
|
|
1450
1671
|
const style = Platform.canvas.createRadialGradient(realFrom$1.x, realFrom$1.y, 0, realFrom$1.x, realFrom$1.y, getDistance$1(realFrom$1, realTo$1));
|
|
1451
1672
|
applyStops(style, paint.stops, opacity);
|
|
1452
|
-
const data = { type, style
|
|
1673
|
+
const data = { type, style };
|
|
1674
|
+
const transform = getTransform(box, realFrom$1, realTo$1, stretch, true);
|
|
1675
|
+
if (transform)
|
|
1676
|
+
data.transform = transform;
|
|
1453
1677
|
if (blendMode)
|
|
1454
1678
|
data.blendMode = blendMode;
|
|
1455
1679
|
return data;
|
|
1456
1680
|
}
|
|
1681
|
+
function getTransform(box, from, to, stretch, rotate90) {
|
|
1682
|
+
let transform;
|
|
1683
|
+
const { width, height } = box;
|
|
1684
|
+
if (width !== height || stretch) {
|
|
1685
|
+
const angle = getAngle(from, to);
|
|
1686
|
+
transform = get();
|
|
1687
|
+
if (rotate90) {
|
|
1688
|
+
scaleOfOuter(transform, from, width / height * (stretch || 1), 1);
|
|
1689
|
+
rotateOfOuter(transform, from, angle + 90);
|
|
1690
|
+
}
|
|
1691
|
+
else {
|
|
1692
|
+
scaleOfOuter(transform, from, 1, width / height * (stretch || 1));
|
|
1693
|
+
rotateOfOuter(transform, from, angle);
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
return transform;
|
|
1697
|
+
}
|
|
1457
1698
|
|
|
1458
|
-
const {
|
|
1459
|
-
const {
|
|
1460
|
-
const defaultFrom = { x: 0.5, y: 0.5 };
|
|
1461
|
-
const defaultTo = { x: 0.5, y: 1 };
|
|
1699
|
+
const { getDistance } = PointHelper;
|
|
1700
|
+
const { toPoint } = AroundHelper;
|
|
1462
1701
|
const realFrom = {};
|
|
1463
1702
|
const realTo = {};
|
|
1464
1703
|
function conicGradient(paint, box) {
|
|
1465
1704
|
let { from, to, type, opacity, blendMode, stretch } = paint;
|
|
1466
|
-
from ||
|
|
1467
|
-
to ||
|
|
1468
|
-
const { x, y, width, height } = box;
|
|
1469
|
-
set(realFrom, x + from.x * width, y + from.y * height);
|
|
1470
|
-
set(realTo, x + to.x * width, y + to.y * height);
|
|
1471
|
-
const transform = get();
|
|
1472
|
-
const angle = getAngle(realFrom, realTo);
|
|
1473
|
-
if (Platform.conicGradientRotate90) {
|
|
1474
|
-
scaleOfOuter(transform, realFrom, width / height * (stretch || 1), 1);
|
|
1475
|
-
rotateOfOuter(transform, realFrom, angle + 90);
|
|
1476
|
-
}
|
|
1477
|
-
else {
|
|
1478
|
-
scaleOfOuter(transform, realFrom, 1, width / height * (stretch || 1));
|
|
1479
|
-
rotateOfOuter(transform, realFrom, angle);
|
|
1480
|
-
}
|
|
1705
|
+
toPoint(from || 'center', box, realFrom);
|
|
1706
|
+
toPoint(to || 'bottom', box, realTo);
|
|
1481
1707
|
const style = Platform.conicGradientSupport ? Platform.canvas.createConicGradient(0, realFrom.x, realFrom.y) : Platform.canvas.createRadialGradient(realFrom.x, realFrom.y, 0, realFrom.x, realFrom.y, getDistance(realFrom, realTo));
|
|
1482
1708
|
applyStops(style, paint.stops, opacity);
|
|
1483
|
-
const data = { type, style
|
|
1709
|
+
const data = { type, style };
|
|
1710
|
+
const transform = getTransform(box, realFrom, realTo, stretch || 1, Platform.conicGradientRotate90);
|
|
1711
|
+
if (transform)
|
|
1712
|
+
data.transform = transform;
|
|
1484
1713
|
if (blendMode)
|
|
1485
1714
|
data.blendMode = blendMode;
|
|
1486
1715
|
return data;
|
|
1487
1716
|
}
|
|
1488
1717
|
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
paints = [paints];
|
|
1496
|
-
recycleMap = recycleImage(ui.__, attrName);
|
|
1497
|
-
for (let i = 0, len = paints.length; i < len; i++) {
|
|
1498
|
-
item = getLeafPaint(ui, paints[i], attrName);
|
|
1499
|
-
if (item)
|
|
1500
|
-
value.push(item);
|
|
1501
|
-
}
|
|
1502
|
-
ui.__['_' + attrName] = value.length ? value : undefined;
|
|
1503
|
-
}
|
|
1504
|
-
function getLeafPaint(ui, paint, attrName) {
|
|
1505
|
-
if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
|
|
1506
|
-
return undefined;
|
|
1507
|
-
const { boxBounds } = ui.__layout;
|
|
1508
|
-
switch (paint.type) {
|
|
1509
|
-
case 'solid':
|
|
1510
|
-
let { type, blendMode, color, opacity } = paint;
|
|
1511
|
-
return { type, blendMode, style: ColorConvert$1.string(color, opacity) };
|
|
1512
|
-
case 'image':
|
|
1513
|
-
return image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
|
|
1514
|
-
case 'linear':
|
|
1515
|
-
return linearGradient(paint, boxBounds);
|
|
1516
|
-
case 'radial':
|
|
1517
|
-
return radialGradient(paint, boxBounds);
|
|
1518
|
-
case 'angular':
|
|
1519
|
-
return conicGradient(paint, boxBounds);
|
|
1520
|
-
default:
|
|
1521
|
-
return paint.r ? { type: 'solid', style: ColorConvert$1.string(paint) } : undefined;
|
|
1522
|
-
}
|
|
1523
|
-
}
|
|
1524
|
-
|
|
1525
|
-
var UIPaint = /*#__PURE__*/Object.freeze({
|
|
1526
|
-
__proto__: null,
|
|
1527
|
-
compute: compute,
|
|
1528
|
-
drawTextStroke: drawTextStroke,
|
|
1529
|
-
fill: fill,
|
|
1530
|
-
fillText: fillText,
|
|
1531
|
-
fills: fills,
|
|
1532
|
-
recycleImage: recycleImage,
|
|
1533
|
-
shape: shape,
|
|
1534
|
-
stroke: stroke,
|
|
1535
|
-
strokeText: strokeText,
|
|
1536
|
-
strokes: strokes
|
|
1537
|
-
});
|
|
1718
|
+
const PaintGradientModule = {
|
|
1719
|
+
linearGradient,
|
|
1720
|
+
radialGradient,
|
|
1721
|
+
conicGradient,
|
|
1722
|
+
getTransform
|
|
1723
|
+
};
|
|
1538
1724
|
|
|
1539
1725
|
const { copy, toOffsetOutBounds: toOffsetOutBounds$1 } = BoundsHelper;
|
|
1540
1726
|
const tempBounds = {};
|
|
1541
1727
|
const offsetOutBounds$1 = {};
|
|
1542
|
-
function shadow(ui, current, shape
|
|
1728
|
+
function shadow(ui, current, shape) {
|
|
1543
1729
|
let copyBounds, spreadScale;
|
|
1544
|
-
const {
|
|
1730
|
+
const { __nowWorld: nowWorld, __layout } = ui;
|
|
1545
1731
|
const { shadow } = ui.__;
|
|
1546
1732
|
const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
|
|
1547
1733
|
const other = current.getSameCanvas();
|
|
@@ -1556,21 +1742,21 @@ function shadow(ui, current, shape, _options) {
|
|
|
1556
1742
|
other.restore();
|
|
1557
1743
|
other.save();
|
|
1558
1744
|
if (worldCanvas) {
|
|
1559
|
-
other.copyWorld(other, bounds,
|
|
1560
|
-
copyBounds =
|
|
1745
|
+
other.copyWorld(other, bounds, nowWorld, 'copy');
|
|
1746
|
+
copyBounds = nowWorld;
|
|
1561
1747
|
}
|
|
1562
|
-
worldCanvas ? other.copyWorld(worldCanvas,
|
|
1748
|
+
worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
|
|
1563
1749
|
}
|
|
1564
|
-
if (ui.
|
|
1565
|
-
current.copyWorldByReset(other, copyBounds,
|
|
1750
|
+
if (ui.__worldFlipped) {
|
|
1751
|
+
current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
|
|
1566
1752
|
}
|
|
1567
1753
|
else {
|
|
1568
1754
|
current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
|
|
1569
1755
|
}
|
|
1570
1756
|
if (end && index < end)
|
|
1571
|
-
other.
|
|
1757
|
+
other.clearWorld(copyBounds, true);
|
|
1572
1758
|
});
|
|
1573
|
-
other.recycle();
|
|
1759
|
+
other.recycle(copyBounds);
|
|
1574
1760
|
}
|
|
1575
1761
|
function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
|
|
1576
1762
|
const { bounds, shapeBounds } = shape;
|
|
@@ -1601,9 +1787,9 @@ function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
|
|
|
1601
1787
|
|
|
1602
1788
|
const { toOffsetOutBounds } = BoundsHelper;
|
|
1603
1789
|
const offsetOutBounds = {};
|
|
1604
|
-
function innerShadow(ui, current, shape
|
|
1790
|
+
function innerShadow(ui, current, shape) {
|
|
1605
1791
|
let copyBounds, spreadScale;
|
|
1606
|
-
const {
|
|
1792
|
+
const { __nowWorld: nowWorld, __layout: __layout } = ui;
|
|
1607
1793
|
const { innerShadow } = ui.__;
|
|
1608
1794
|
const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
|
|
1609
1795
|
const other = current.getSameCanvas();
|
|
@@ -1616,40 +1802,115 @@ function innerShadow(ui, current, shape, _options) {
|
|
|
1616
1802
|
drawWorldShadow(other, offsetOutBounds, spreadScale, shape);
|
|
1617
1803
|
other.restore();
|
|
1618
1804
|
if (worldCanvas) {
|
|
1619
|
-
other.copyWorld(other, bounds,
|
|
1620
|
-
other.copyWorld(worldCanvas,
|
|
1621
|
-
copyBounds =
|
|
1805
|
+
other.copyWorld(other, bounds, nowWorld, 'copy');
|
|
1806
|
+
other.copyWorld(worldCanvas, nowWorld, nowWorld, 'source-out');
|
|
1807
|
+
copyBounds = nowWorld;
|
|
1622
1808
|
}
|
|
1623
1809
|
else {
|
|
1624
1810
|
other.copyWorld(shape.canvas, shapeBounds, bounds, 'source-out');
|
|
1625
1811
|
copyBounds = bounds;
|
|
1626
1812
|
}
|
|
1627
1813
|
other.fillWorld(copyBounds, item.color, 'source-in');
|
|
1628
|
-
if (ui.
|
|
1629
|
-
current.copyWorldByReset(other, copyBounds,
|
|
1814
|
+
if (ui.__worldFlipped) {
|
|
1815
|
+
current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
|
|
1630
1816
|
}
|
|
1631
1817
|
else {
|
|
1632
1818
|
current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
|
|
1633
1819
|
}
|
|
1634
1820
|
if (end && index < end)
|
|
1635
|
-
other.
|
|
1821
|
+
other.clearWorld(copyBounds, true);
|
|
1636
1822
|
});
|
|
1637
|
-
other.recycle();
|
|
1823
|
+
other.recycle(copyBounds);
|
|
1638
1824
|
}
|
|
1639
1825
|
|
|
1640
1826
|
function blur(ui, current, origin) {
|
|
1641
1827
|
const { blur } = ui.__;
|
|
1642
|
-
origin.setWorldBlur(blur * ui.
|
|
1643
|
-
origin.copyWorldToInner(current, ui.
|
|
1828
|
+
origin.setWorldBlur(blur * ui.__nowWorld.a);
|
|
1829
|
+
origin.copyWorldToInner(current, ui.__nowWorld, ui.__layout.renderBounds);
|
|
1644
1830
|
origin.filter = 'none';
|
|
1645
1831
|
}
|
|
1646
1832
|
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
shadow
|
|
1652
|
-
|
|
1833
|
+
function backgroundBlur(_ui, _current, _shape) {
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
const EffectModule = {
|
|
1837
|
+
shadow,
|
|
1838
|
+
innerShadow,
|
|
1839
|
+
blur,
|
|
1840
|
+
backgroundBlur
|
|
1841
|
+
};
|
|
1842
|
+
|
|
1843
|
+
const { excludeRenderBounds } = LeafBoundsHelper;
|
|
1844
|
+
Group.prototype.__renderMask = function (canvas, options) {
|
|
1845
|
+
let child, maskCanvas, contentCanvas, maskOpacity, currentMask;
|
|
1846
|
+
const { children } = this;
|
|
1847
|
+
for (let i = 0, len = children.length; i < len; i++) {
|
|
1848
|
+
child = children[i];
|
|
1849
|
+
if (child.__.mask) {
|
|
1850
|
+
if (currentMask) {
|
|
1851
|
+
maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
|
|
1852
|
+
maskCanvas = contentCanvas = null;
|
|
1853
|
+
}
|
|
1854
|
+
if (child.__.mask === 'path') {
|
|
1855
|
+
if (child.opacity < 1) {
|
|
1856
|
+
currentMask = 'opacity-path';
|
|
1857
|
+
maskOpacity = child.opacity;
|
|
1858
|
+
if (!contentCanvas)
|
|
1859
|
+
contentCanvas = getCanvas(canvas);
|
|
1860
|
+
}
|
|
1861
|
+
else {
|
|
1862
|
+
currentMask = 'path';
|
|
1863
|
+
canvas.save();
|
|
1864
|
+
}
|
|
1865
|
+
child.__clip(contentCanvas || canvas, options);
|
|
1866
|
+
}
|
|
1867
|
+
else {
|
|
1868
|
+
currentMask = 'alpha';
|
|
1869
|
+
if (!maskCanvas)
|
|
1870
|
+
maskCanvas = getCanvas(canvas);
|
|
1871
|
+
if (!contentCanvas)
|
|
1872
|
+
contentCanvas = getCanvas(canvas);
|
|
1873
|
+
child.__render(maskCanvas, options);
|
|
1874
|
+
}
|
|
1875
|
+
if (child.__.mask !== 'clipping')
|
|
1876
|
+
continue;
|
|
1877
|
+
}
|
|
1878
|
+
if (excludeRenderBounds(child, options))
|
|
1879
|
+
continue;
|
|
1880
|
+
child.__render(contentCanvas || canvas, options);
|
|
1881
|
+
}
|
|
1882
|
+
maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
|
|
1883
|
+
};
|
|
1884
|
+
function maskEnd(leaf, maskMode, canvas, contentCanvas, maskCanvas, maskOpacity) {
|
|
1885
|
+
switch (maskMode) {
|
|
1886
|
+
case 'alpha':
|
|
1887
|
+
usePixelMask(leaf, canvas, contentCanvas, maskCanvas);
|
|
1888
|
+
break;
|
|
1889
|
+
case 'opacity-path':
|
|
1890
|
+
copyContent(leaf, canvas, contentCanvas, maskOpacity);
|
|
1891
|
+
break;
|
|
1892
|
+
case 'path':
|
|
1893
|
+
canvas.restore();
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
function getCanvas(canvas) {
|
|
1897
|
+
return canvas.getSameCanvas(false, true);
|
|
1898
|
+
}
|
|
1899
|
+
function usePixelMask(leaf, canvas, content, mask) {
|
|
1900
|
+
const realBounds = leaf.__nowWorld;
|
|
1901
|
+
content.resetTransform();
|
|
1902
|
+
content.opacity = 1;
|
|
1903
|
+
content.useMask(mask, realBounds);
|
|
1904
|
+
mask.recycle(realBounds);
|
|
1905
|
+
copyContent(leaf, canvas, content, 1);
|
|
1906
|
+
}
|
|
1907
|
+
function copyContent(leaf, canvas, content, maskOpacity) {
|
|
1908
|
+
const realBounds = leaf.__nowWorld;
|
|
1909
|
+
canvas.resetTransform();
|
|
1910
|
+
canvas.opacity = maskOpacity;
|
|
1911
|
+
canvas.copyWorld(content, realBounds);
|
|
1912
|
+
content.recycle(realBounds);
|
|
1913
|
+
}
|
|
1653
1914
|
|
|
1654
1915
|
const money = '¥¥$€££¢¢';
|
|
1655
1916
|
const letter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
|
|
@@ -1774,6 +2035,8 @@ function createRows(drawData, content, style) {
|
|
|
1774
2035
|
const { width, height } = bounds;
|
|
1775
2036
|
const charMode = width || height || __letterSpacing || (textCase !== 'none');
|
|
1776
2037
|
if (charMode) {
|
|
2038
|
+
const wrap = style.textWrap !== 'none';
|
|
2039
|
+
const breakAll = style.textWrap === 'break';
|
|
1777
2040
|
paraStart = true;
|
|
1778
2041
|
lastCharType = null;
|
|
1779
2042
|
startCharSize = charWidth = charSize = wordWidth = rowWidth = 0;
|
|
@@ -1800,16 +2063,26 @@ function createRows(drawData, content, style) {
|
|
|
1800
2063
|
langBreak = (charType === Single && (lastCharType === Single || lastCharType === Letter)) || (lastCharType === Single && charType !== After);
|
|
1801
2064
|
afterBreak = ((charType === Before || charType === Single) && (lastCharType === Symbol || lastCharType === After));
|
|
1802
2065
|
realWidth = paraStart && paraIndent ? width - paraIndent : width;
|
|
1803
|
-
if (width && rowWidth + wordWidth + charWidth > realWidth) {
|
|
1804
|
-
if (
|
|
1805
|
-
afterBreak = charType === Letter && lastCharType == After;
|
|
1806
|
-
if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
|
|
2066
|
+
if (wrap && (width && rowWidth + wordWidth + charWidth > realWidth)) {
|
|
2067
|
+
if (breakAll) {
|
|
1807
2068
|
if (wordWidth)
|
|
1808
2069
|
addWord();
|
|
1809
|
-
|
|
2070
|
+
if (rowWidth)
|
|
2071
|
+
addRow();
|
|
1810
2072
|
}
|
|
1811
2073
|
else {
|
|
1812
|
-
|
|
2074
|
+
if (!afterBreak)
|
|
2075
|
+
afterBreak = charType === Letter && lastCharType == After;
|
|
2076
|
+
if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
|
|
2077
|
+
if (wordWidth)
|
|
2078
|
+
addWord();
|
|
2079
|
+
if (rowWidth)
|
|
2080
|
+
addRow();
|
|
2081
|
+
}
|
|
2082
|
+
else {
|
|
2083
|
+
if (rowWidth)
|
|
2084
|
+
addRow();
|
|
2085
|
+
}
|
|
1813
2086
|
}
|
|
1814
2087
|
}
|
|
1815
2088
|
if (char === ' ' && paraStart !== true && (rowWidth + wordWidth) === 0) ;
|
|
@@ -1879,7 +2152,7 @@ function addRow() {
|
|
|
1879
2152
|
|
|
1880
2153
|
const CharMode = 0;
|
|
1881
2154
|
const WordMode = 1;
|
|
1882
|
-
const
|
|
2155
|
+
const TextMode = 2;
|
|
1883
2156
|
function layoutChar(drawData, style, width, _height) {
|
|
1884
2157
|
const { rows } = drawData;
|
|
1885
2158
|
const { textAlign, paraIndent, letterSpacing } = style;
|
|
@@ -1888,15 +2161,12 @@ function layoutChar(drawData, style, width, _height) {
|
|
|
1888
2161
|
if (row.words) {
|
|
1889
2162
|
indentWidth = paraIndent && row.paraStart ? paraIndent : 0;
|
|
1890
2163
|
addWordWidth = (width && textAlign === 'justify' && row.words.length > 1) ? (width - row.width - indentWidth) / (row.words.length - 1) : 0;
|
|
1891
|
-
mode = (letterSpacing || row.isOverflow) ? CharMode : (addWordWidth > 0.01 ? WordMode :
|
|
1892
|
-
if (
|
|
1893
|
-
row.
|
|
2164
|
+
mode = (letterSpacing || row.isOverflow) ? CharMode : (addWordWidth > 0.01 ? WordMode : TextMode);
|
|
2165
|
+
if (row.isOverflow && !letterSpacing)
|
|
2166
|
+
row.textMode = true;
|
|
2167
|
+
if (mode === TextMode) {
|
|
1894
2168
|
row.x += indentWidth;
|
|
1895
|
-
row
|
|
1896
|
-
word.data.forEach(char => {
|
|
1897
|
-
row.text += char.char;
|
|
1898
|
-
});
|
|
1899
|
-
});
|
|
2169
|
+
toTextChar$1(row);
|
|
1900
2170
|
}
|
|
1901
2171
|
else {
|
|
1902
2172
|
row.x += indentWidth;
|
|
@@ -1906,11 +2176,11 @@ function layoutChar(drawData, style, width, _height) {
|
|
|
1906
2176
|
if (mode === WordMode) {
|
|
1907
2177
|
wordChar = { char: '', x: charX };
|
|
1908
2178
|
charX = toWordChar(word.data, charX, wordChar);
|
|
1909
|
-
if (wordChar.char !== ' ')
|
|
2179
|
+
if (row.isOverflow || wordChar.char !== ' ')
|
|
1910
2180
|
row.data.push(wordChar);
|
|
1911
2181
|
}
|
|
1912
2182
|
else {
|
|
1913
|
-
charX = toChar(word.data, charX, row.data);
|
|
2183
|
+
charX = toChar(word.data, charX, row.data, row.isOverflow);
|
|
1914
2184
|
}
|
|
1915
2185
|
if (!row.paraEnd && addWordWidth) {
|
|
1916
2186
|
charX += addWordWidth;
|
|
@@ -1922,6 +2192,14 @@ function layoutChar(drawData, style, width, _height) {
|
|
|
1922
2192
|
}
|
|
1923
2193
|
});
|
|
1924
2194
|
}
|
|
2195
|
+
function toTextChar$1(row) {
|
|
2196
|
+
row.text = '';
|
|
2197
|
+
row.words.forEach(word => {
|
|
2198
|
+
word.data.forEach(char => {
|
|
2199
|
+
row.text += char.char;
|
|
2200
|
+
});
|
|
2201
|
+
});
|
|
2202
|
+
}
|
|
1925
2203
|
function toWordChar(data, charX, wordChar) {
|
|
1926
2204
|
data.forEach(char => {
|
|
1927
2205
|
wordChar.char += char.char;
|
|
@@ -1929,9 +2207,9 @@ function toWordChar(data, charX, wordChar) {
|
|
|
1929
2207
|
});
|
|
1930
2208
|
return charX;
|
|
1931
2209
|
}
|
|
1932
|
-
function toChar(data, charX, rowData) {
|
|
2210
|
+
function toChar(data, charX, rowData, isOverflow) {
|
|
1933
2211
|
data.forEach(char => {
|
|
1934
|
-
if (char.char !== ' ') {
|
|
2212
|
+
if (isOverflow || char.char !== ' ') {
|
|
1935
2213
|
char.x = charX;
|
|
1936
2214
|
rowData.push(char);
|
|
1937
2215
|
}
|
|
@@ -1942,10 +2220,10 @@ function toChar(data, charX, rowData) {
|
|
|
1942
2220
|
|
|
1943
2221
|
function layoutText(drawData, style) {
|
|
1944
2222
|
const { rows, bounds } = drawData;
|
|
1945
|
-
const { __lineHeight, __baseLine, __letterSpacing, textAlign, verticalAlign, paraSpacing
|
|
2223
|
+
const { __lineHeight, __baseLine, __letterSpacing, __clipText, textAlign, verticalAlign, paraSpacing } = style;
|
|
1946
2224
|
let { x, y, width, height } = bounds, realHeight = __lineHeight * rows.length + (paraSpacing ? paraSpacing * (drawData.paraNumber - 1) : 0);
|
|
1947
2225
|
let starY = __baseLine;
|
|
1948
|
-
if (
|
|
2226
|
+
if (__clipText && realHeight > height) {
|
|
1949
2227
|
realHeight = Math.max(height, __lineHeight);
|
|
1950
2228
|
drawData.overflow = rows.length;
|
|
1951
2229
|
}
|
|
@@ -1963,12 +2241,14 @@ function layoutText(drawData, style) {
|
|
|
1963
2241
|
for (let i = 0, len = rows.length; i < len; i++) {
|
|
1964
2242
|
row = rows[i];
|
|
1965
2243
|
row.x = x;
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
2244
|
+
if (row.width < width || (row.width > width && !__clipText)) {
|
|
2245
|
+
switch (textAlign) {
|
|
2246
|
+
case 'center':
|
|
2247
|
+
row.x += (width - row.width) / 2;
|
|
2248
|
+
break;
|
|
2249
|
+
case 'right':
|
|
2250
|
+
row.x += width - row.width;
|
|
2251
|
+
}
|
|
1972
2252
|
}
|
|
1973
2253
|
if (row.paraStart && paraSpacing && i > 0)
|
|
1974
2254
|
starY += paraSpacing;
|
|
@@ -1994,39 +2274,62 @@ function layoutText(drawData, style) {
|
|
|
1994
2274
|
bounds.x = rowX;
|
|
1995
2275
|
if (rowWidth > bounds.width)
|
|
1996
2276
|
bounds.width = rowWidth;
|
|
2277
|
+
if (__clipText && width && width < rowWidth) {
|
|
2278
|
+
row.isOverflow = true;
|
|
2279
|
+
if (!drawData.overflow)
|
|
2280
|
+
drawData.overflow = rows.length;
|
|
2281
|
+
}
|
|
1997
2282
|
}
|
|
1998
2283
|
bounds.y = y;
|
|
1999
2284
|
bounds.height = realHeight;
|
|
2000
2285
|
}
|
|
2001
2286
|
|
|
2002
|
-
function clipText(drawData,
|
|
2287
|
+
function clipText(drawData, style, x, width) {
|
|
2288
|
+
if (!width)
|
|
2289
|
+
return;
|
|
2003
2290
|
const { rows, overflow } = drawData;
|
|
2291
|
+
let { textOverflow } = style;
|
|
2004
2292
|
rows.splice(overflow);
|
|
2005
|
-
if (textOverflow !== '
|
|
2006
|
-
if (textOverflow === '
|
|
2293
|
+
if (textOverflow && textOverflow !== 'show') {
|
|
2294
|
+
if (textOverflow === 'hide')
|
|
2295
|
+
textOverflow = '';
|
|
2296
|
+
else if (textOverflow === 'ellipsis')
|
|
2007
2297
|
textOverflow = '...';
|
|
2008
|
-
|
|
2009
|
-
const
|
|
2010
|
-
let char, end = row.data.length - 1, charRight;
|
|
2011
|
-
const { x, width } = drawData.bounds;
|
|
2298
|
+
let char, charRight;
|
|
2299
|
+
const ellipsisWidth = textOverflow ? Platform.canvas.measureText(textOverflow).width : 0;
|
|
2012
2300
|
const right = x + width - ellipsisWidth;
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2301
|
+
const list = style.textWrap === 'none' ? rows : [rows[overflow - 1]];
|
|
2302
|
+
list.forEach(row => {
|
|
2303
|
+
if (row.isOverflow && row.data) {
|
|
2304
|
+
let end = row.data.length - 1;
|
|
2305
|
+
for (let i = end; i > -1; i--) {
|
|
2306
|
+
char = row.data[i];
|
|
2307
|
+
charRight = char.x + char.width;
|
|
2308
|
+
if (i === end && charRight < right) {
|
|
2309
|
+
break;
|
|
2310
|
+
}
|
|
2311
|
+
else if (charRight < right && char.char !== ' ') {
|
|
2312
|
+
row.data.splice(i + 1);
|
|
2313
|
+
row.width -= char.width;
|
|
2314
|
+
break;
|
|
2315
|
+
}
|
|
2316
|
+
row.width -= char.width;
|
|
2317
|
+
}
|
|
2318
|
+
row.width += ellipsisWidth;
|
|
2319
|
+
row.data.push({ char: textOverflow, x: charRight });
|
|
2320
|
+
if (row.textMode)
|
|
2321
|
+
toTextChar(row);
|
|
2023
2322
|
}
|
|
2024
|
-
|
|
2025
|
-
}
|
|
2026
|
-
row.width += ellipsisWidth;
|
|
2027
|
-
row.data.push({ char: textOverflow, x: charRight });
|
|
2323
|
+
});
|
|
2028
2324
|
}
|
|
2029
2325
|
}
|
|
2326
|
+
function toTextChar(row) {
|
|
2327
|
+
row.text = '';
|
|
2328
|
+
row.data.forEach(char => {
|
|
2329
|
+
row.text += char.char;
|
|
2330
|
+
});
|
|
2331
|
+
row.data = null;
|
|
2332
|
+
}
|
|
2030
2333
|
|
|
2031
2334
|
function decorationText(drawData, style) {
|
|
2032
2335
|
const { fontSize } = style;
|
|
@@ -2040,100 +2343,214 @@ function decorationText(drawData, style) {
|
|
|
2040
2343
|
}
|
|
2041
2344
|
}
|
|
2042
2345
|
|
|
2043
|
-
const
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2346
|
+
const { top, right, bottom, left } = Direction4;
|
|
2347
|
+
function getDrawData(content, style) {
|
|
2348
|
+
if (typeof content !== 'string')
|
|
2349
|
+
content = String(content);
|
|
2350
|
+
let x = 0, y = 0;
|
|
2351
|
+
let width = style.__getInput('width') || 0;
|
|
2352
|
+
let height = style.__getInput('height') || 0;
|
|
2353
|
+
const { textDecoration, __font, __padding: padding } = style;
|
|
2354
|
+
if (padding) {
|
|
2355
|
+
if (width) {
|
|
2356
|
+
x = padding[left];
|
|
2357
|
+
width -= (padding[right] + padding[left]);
|
|
2358
|
+
}
|
|
2359
|
+
if (height) {
|
|
2360
|
+
y = padding[top];
|
|
2361
|
+
height -= (padding[top] + padding[bottom]);
|
|
2362
|
+
}
|
|
2363
|
+
}
|
|
2364
|
+
const drawData = {
|
|
2365
|
+
bounds: { x, y, width, height },
|
|
2366
|
+
rows: [],
|
|
2367
|
+
paraNumber: 0,
|
|
2368
|
+
font: Platform.canvas.font = __font
|
|
2369
|
+
};
|
|
2370
|
+
createRows(drawData, content, style);
|
|
2371
|
+
if (padding)
|
|
2372
|
+
padAutoText(padding, drawData, style, width, height);
|
|
2373
|
+
layoutText(drawData, style);
|
|
2374
|
+
layoutChar(drawData, style, width);
|
|
2375
|
+
if (drawData.overflow)
|
|
2376
|
+
clipText(drawData, style, x, width);
|
|
2377
|
+
if (textDecoration !== 'none')
|
|
2378
|
+
decorationText(drawData, style);
|
|
2379
|
+
return drawData;
|
|
2380
|
+
}
|
|
2381
|
+
function padAutoText(padding, drawData, style, width, height) {
|
|
2382
|
+
if (!width) {
|
|
2383
|
+
switch (style.textAlign) {
|
|
2384
|
+
case 'left':
|
|
2385
|
+
offsetText(drawData, 'x', padding[left]);
|
|
2386
|
+
break;
|
|
2387
|
+
case 'right':
|
|
2388
|
+
offsetText(drawData, 'x', -padding[right]);
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
2391
|
+
if (!height) {
|
|
2392
|
+
switch (style.verticalAlign) {
|
|
2393
|
+
case 'top':
|
|
2394
|
+
offsetText(drawData, 'y', padding[top]);
|
|
2395
|
+
break;
|
|
2396
|
+
case 'bottom':
|
|
2397
|
+
offsetText(drawData, 'y', -padding[bottom]);
|
|
2061
2398
|
}
|
|
2062
|
-
const drawData = {
|
|
2063
|
-
bounds: { x, y, width, height },
|
|
2064
|
-
rows: [],
|
|
2065
|
-
paraNumber: 0,
|
|
2066
|
-
font: Platform.canvas.font = __font
|
|
2067
|
-
};
|
|
2068
|
-
createRows(drawData, content, style);
|
|
2069
|
-
layoutText(drawData, style);
|
|
2070
|
-
layoutChar(drawData, style, width);
|
|
2071
|
-
if (drawData.overflow)
|
|
2072
|
-
clipText(drawData, textOverflow);
|
|
2073
|
-
if (textDecoration !== 'none')
|
|
2074
|
-
decorationText(drawData, style);
|
|
2075
|
-
return drawData;
|
|
2076
2399
|
}
|
|
2400
|
+
}
|
|
2401
|
+
function offsetText(drawData, attrName, value) {
|
|
2402
|
+
const { bounds, rows } = drawData;
|
|
2403
|
+
bounds[attrName] += value;
|
|
2404
|
+
for (let i = 0; i < rows.length; i++)
|
|
2405
|
+
rows[i][attrName] += value;
|
|
2406
|
+
}
|
|
2407
|
+
|
|
2408
|
+
const TextConvertModule = {
|
|
2409
|
+
getDrawData
|
|
2077
2410
|
};
|
|
2078
2411
|
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2412
|
+
function string(color, opacity) {
|
|
2413
|
+
if (typeof color === 'string')
|
|
2414
|
+
return color;
|
|
2415
|
+
let a = color.a === undefined ? 1 : color.a;
|
|
2416
|
+
if (opacity)
|
|
2417
|
+
a *= opacity;
|
|
2418
|
+
const rgb = color.r + ',' + color.g + ',' + color.b;
|
|
2419
|
+
return a === 1 ? 'rgb(' + rgb + ')' : 'rgba(' + rgb + ',' + a + ')';
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
const ColorConvertModule = {
|
|
2423
|
+
string
|
|
2089
2424
|
};
|
|
2090
2425
|
|
|
2091
|
-
const
|
|
2426
|
+
const { setPoint, addPoint, toBounds } = TwoPointBoundsHelper;
|
|
2427
|
+
function getTrimBounds(canvas) {
|
|
2428
|
+
const { width, height } = canvas.view;
|
|
2429
|
+
const { data } = canvas.context.getImageData(0, 0, width, height);
|
|
2430
|
+
let x, y, pointBounds, index = 0;
|
|
2431
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
2432
|
+
if (data[i + 3] !== 0) {
|
|
2433
|
+
x = index % width;
|
|
2434
|
+
y = (index - x) / width;
|
|
2435
|
+
pointBounds ? addPoint(pointBounds, x, y) : setPoint(pointBounds = {}, x, y);
|
|
2436
|
+
}
|
|
2437
|
+
index++;
|
|
2438
|
+
}
|
|
2439
|
+
const bounds = new Bounds();
|
|
2440
|
+
toBounds(pointBounds, bounds);
|
|
2441
|
+
return bounds.scale(1 / canvas.pixelRatio).ceil();
|
|
2442
|
+
}
|
|
2443
|
+
|
|
2444
|
+
const ExportModule = {
|
|
2092
2445
|
export(leaf, filename, options) {
|
|
2446
|
+
this.running = true;
|
|
2447
|
+
const fileType = FileHelper.fileType(filename);
|
|
2448
|
+
options = FileHelper.getExportOptions(options);
|
|
2093
2449
|
return addTask((success) => new Promise((resolve) => {
|
|
2450
|
+
const over = (result) => {
|
|
2451
|
+
success(result);
|
|
2452
|
+
resolve();
|
|
2453
|
+
this.running = false;
|
|
2454
|
+
};
|
|
2455
|
+
const { toURL } = Platform;
|
|
2456
|
+
const { download } = Platform.origin;
|
|
2457
|
+
if (filename === 'json') {
|
|
2458
|
+
return over({ data: leaf.toJSON(options.json) });
|
|
2459
|
+
}
|
|
2460
|
+
else if (fileType === 'json') {
|
|
2461
|
+
download(toURL(JSON.stringify(leaf.toJSON(options.json)), 'text'), filename);
|
|
2462
|
+
return over({ data: true });
|
|
2463
|
+
}
|
|
2464
|
+
if (filename === 'svg') {
|
|
2465
|
+
return over({ data: leaf.toSVG() });
|
|
2466
|
+
}
|
|
2467
|
+
else if (fileType === 'svg') {
|
|
2468
|
+
download(toURL(leaf.toSVG(), 'svg'), filename);
|
|
2469
|
+
return over({ data: true });
|
|
2470
|
+
}
|
|
2094
2471
|
const { leafer } = leaf;
|
|
2095
2472
|
if (leafer) {
|
|
2473
|
+
checkLazy(leaf);
|
|
2096
2474
|
leafer.waitViewCompleted(() => __awaiter(this, void 0, void 0, function* () {
|
|
2097
|
-
let
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2475
|
+
let renderBounds, trimBounds, scaleX = 1, scaleY = 1;
|
|
2476
|
+
const { worldTransform, isLeafer, isFrame } = leaf;
|
|
2477
|
+
const { slice, trim, onCanvas } = options;
|
|
2478
|
+
let scale = options.scale || 1;
|
|
2479
|
+
let pixelRatio = options.pixelRatio || 1;
|
|
2480
|
+
const smooth = options.smooth === undefined ? leafer.config.smooth : options.smooth;
|
|
2481
|
+
const contextSettings = options.contextSettings || leafer.config.contextSettings;
|
|
2482
|
+
if (leaf.isApp) {
|
|
2483
|
+
scale *= pixelRatio;
|
|
2484
|
+
pixelRatio = leaf.app.pixelRatio;
|
|
2485
|
+
}
|
|
2486
|
+
const screenshot = options.screenshot || leaf.isApp;
|
|
2487
|
+
const fill = (isLeafer && screenshot) ? (options.fill === undefined ? leaf.fill : options.fill) : options.fill;
|
|
2488
|
+
const needFill = FileHelper.isOpaqueImage(filename) || fill, matrix = new Matrix();
|
|
2489
|
+
if (screenshot) {
|
|
2490
|
+
renderBounds = screenshot === true ? (isLeafer ? leafer.canvas.bounds : leaf.worldRenderBounds) : screenshot;
|
|
2104
2491
|
}
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2492
|
+
else {
|
|
2493
|
+
let relative = options.relative || (isLeafer ? 'inner' : 'local');
|
|
2494
|
+
scaleX = worldTransform.scaleX;
|
|
2495
|
+
scaleY = worldTransform.scaleY;
|
|
2496
|
+
switch (relative) {
|
|
2497
|
+
case 'inner':
|
|
2498
|
+
matrix.set(worldTransform);
|
|
2499
|
+
break;
|
|
2500
|
+
case 'local':
|
|
2501
|
+
matrix.set(worldTransform).divide(leaf.localTransform);
|
|
2502
|
+
scaleX /= leaf.scaleX;
|
|
2503
|
+
scaleY /= leaf.scaleY;
|
|
2504
|
+
break;
|
|
2505
|
+
case 'world':
|
|
2506
|
+
scaleX = 1;
|
|
2507
|
+
scaleY = 1;
|
|
2508
|
+
break;
|
|
2509
|
+
case 'page':
|
|
2510
|
+
relative = leaf.leafer;
|
|
2511
|
+
default:
|
|
2512
|
+
matrix.set(worldTransform).divide(leaf.getTransform(relative));
|
|
2513
|
+
const l = relative.worldTransform;
|
|
2514
|
+
scaleX /= scaleX / l.scaleX;
|
|
2515
|
+
scaleY /= scaleY / l.scaleY;
|
|
2516
|
+
}
|
|
2517
|
+
renderBounds = leaf.getBounds('render', relative);
|
|
2117
2518
|
}
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2519
|
+
const { x, y, width, height } = new Bounds(renderBounds).scale(scale);
|
|
2520
|
+
let canvas = Creator.canvas({ width: Math.round(width), height: Math.round(height), pixelRatio, smooth, contextSettings });
|
|
2521
|
+
const renderOptions = { matrix: matrix.scale(1 / scale).invert().translate(-x, -y).withScale(1 / scaleX * scale, 1 / scaleY * scale) };
|
|
2522
|
+
if (slice) {
|
|
2523
|
+
leaf = leafer;
|
|
2524
|
+
renderOptions.bounds = canvas.bounds;
|
|
2121
2525
|
}
|
|
2122
|
-
|
|
2123
|
-
|
|
2526
|
+
canvas.save();
|
|
2527
|
+
if (isFrame && fill !== undefined) {
|
|
2528
|
+
const oldFill = leaf.get('fill');
|
|
2529
|
+
leaf.fill = '';
|
|
2530
|
+
leaf.__render(canvas, renderOptions);
|
|
2531
|
+
leaf.fill = oldFill;
|
|
2124
2532
|
}
|
|
2125
2533
|
else {
|
|
2126
|
-
|
|
2534
|
+
leaf.__render(canvas, renderOptions);
|
|
2127
2535
|
}
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
canvas
|
|
2536
|
+
canvas.restore();
|
|
2537
|
+
if (trim) {
|
|
2538
|
+
trimBounds = getTrimBounds(canvas);
|
|
2539
|
+
const old = canvas, { width, height } = trimBounds;
|
|
2540
|
+
const config = { x: 0, y: 0, width, height, pixelRatio };
|
|
2541
|
+
canvas = Creator.canvas(config);
|
|
2542
|
+
canvas.copyWorld(old, trimBounds, config);
|
|
2543
|
+
}
|
|
2544
|
+
if (needFill)
|
|
2545
|
+
canvas.fillWorld(canvas.bounds, fill || '#FFFFFF', 'destination-over');
|
|
2546
|
+
if (onCanvas)
|
|
2547
|
+
onCanvas(canvas);
|
|
2548
|
+
const data = filename === 'canvas' ? canvas : yield canvas.export(filename, options);
|
|
2549
|
+
over({ data, width: canvas.pixelWidth, height: canvas.pixelHeight, renderBounds, trimBounds });
|
|
2132
2550
|
}));
|
|
2133
2551
|
}
|
|
2134
2552
|
else {
|
|
2135
|
-
|
|
2136
|
-
resolve();
|
|
2553
|
+
over({ data: false });
|
|
2137
2554
|
}
|
|
2138
2555
|
}));
|
|
2139
2556
|
}
|
|
@@ -2146,11 +2563,63 @@ function addTask(task) {
|
|
|
2146
2563
|
tasker.add(() => __awaiter(this, void 0, void 0, function* () { return yield task(resolve); }), { parallel: false });
|
|
2147
2564
|
});
|
|
2148
2565
|
}
|
|
2566
|
+
function checkLazy(leaf) {
|
|
2567
|
+
if (leaf.__.__needComputePaint)
|
|
2568
|
+
leaf.__.__computePaint();
|
|
2569
|
+
if (leaf.isBranch)
|
|
2570
|
+
leaf.children.forEach(child => checkLazy(child));
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
const canvas = LeaferCanvasBase.prototype;
|
|
2574
|
+
const debug = Debug.get('@leafer-ui/export');
|
|
2575
|
+
canvas.export = function (filename, options) {
|
|
2576
|
+
const { quality, blob } = FileHelper.getExportOptions(options);
|
|
2577
|
+
if (filename.includes('.')) {
|
|
2578
|
+
return this.saveAs(filename, quality);
|
|
2579
|
+
}
|
|
2580
|
+
else if (blob) {
|
|
2581
|
+
return this.toBlob(filename, quality);
|
|
2582
|
+
}
|
|
2583
|
+
else {
|
|
2584
|
+
return this.toDataURL(filename, quality);
|
|
2585
|
+
}
|
|
2586
|
+
};
|
|
2587
|
+
canvas.toBlob = function (type, quality) {
|
|
2588
|
+
return new Promise((resolve) => {
|
|
2589
|
+
Platform.origin.canvasToBolb(this.view, type, quality).then((blob) => {
|
|
2590
|
+
resolve(blob);
|
|
2591
|
+
}).catch((e) => {
|
|
2592
|
+
debug.error(e);
|
|
2593
|
+
resolve(null);
|
|
2594
|
+
});
|
|
2595
|
+
});
|
|
2596
|
+
};
|
|
2597
|
+
canvas.toDataURL = function (type, quality) {
|
|
2598
|
+
return Platform.origin.canvasToDataURL(this.view, type, quality);
|
|
2599
|
+
};
|
|
2600
|
+
canvas.saveAs = function (filename, quality) {
|
|
2601
|
+
return new Promise((resolve) => {
|
|
2602
|
+
Platform.origin.canvasSaveAs(this.view, filename, quality).then(() => {
|
|
2603
|
+
resolve(true);
|
|
2604
|
+
}).catch((e) => {
|
|
2605
|
+
debug.error(e);
|
|
2606
|
+
resolve(false);
|
|
2607
|
+
});
|
|
2608
|
+
});
|
|
2609
|
+
};
|
|
2149
2610
|
|
|
2150
|
-
Object.assign(
|
|
2151
|
-
Object.assign(
|
|
2152
|
-
Object.assign(
|
|
2153
|
-
Object.assign(
|
|
2154
|
-
Object.assign(
|
|
2611
|
+
Object.assign(TextConvert, TextConvertModule);
|
|
2612
|
+
Object.assign(ColorConvert, ColorConvertModule);
|
|
2613
|
+
Object.assign(Paint, PaintModule);
|
|
2614
|
+
Object.assign(PaintImage, PaintImageModule);
|
|
2615
|
+
Object.assign(PaintGradient, PaintGradientModule);
|
|
2616
|
+
Object.assign(Effect, EffectModule);
|
|
2617
|
+
Object.assign(Export, ExportModule);
|
|
2618
|
+
|
|
2619
|
+
Object.assign(Creator, {
|
|
2620
|
+
interaction: (target, canvas, selector, options) => { return new InteractionBase(target, canvas, selector, options); },
|
|
2621
|
+
hitCanvas: (options, manager) => new LeaferCanvas(options, manager),
|
|
2622
|
+
hitCanvasManager: () => new HitCanvasManager()
|
|
2623
|
+
});
|
|
2155
2624
|
|
|
2156
2625
|
export { Layouter, LeaferCanvas, Renderer, Selector, Watcher, useCanvas };
|