@leafer-ui/node 1.0.0-rc.8 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/node.cjs +1142 -825
- package/dist/node.esm.js +1143 -826
- package/dist/node.esm.min.js +1 -1
- package/dist/node.min.cjs +1 -1
- package/package.json +10 -7
- package/src/index.ts +13 -0
- package/types/index.d.ts +1 -0
package/dist/node.esm.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { LeafList, DataHelper, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, Bounds, LeafBoundsHelper, Debug, LeafLevelList, LayoutEvent, Run, ImageManager,
|
|
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
4
|
import { writeFileSync } from 'fs';
|
|
5
|
-
import {
|
|
5
|
+
import { InteractionBase, HitCanvasManager } from '@leafer-ui/core';
|
|
6
6
|
export * from '@leafer-ui/core';
|
|
7
|
+
import { PaintImage, ColorConvert, PaintGradient, Export, Group, TextConvert, Paint, Effect } from '@leafer-ui/draw';
|
|
7
8
|
|
|
8
9
|
/******************************************************************************
|
|
9
10
|
Copyright (c) Microsoft Corporation.
|
|
@@ -37,6 +38,73 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
37
38
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
38
39
|
};
|
|
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;
|
|
107
|
+
|
|
40
108
|
class Watcher {
|
|
41
109
|
get childrenChanged() { return this.hasAdd || this.hasRemove || this.hasVisible; }
|
|
42
110
|
get updatedList() {
|
|
@@ -218,7 +286,7 @@ class LayoutBlockData {
|
|
|
218
286
|
}
|
|
219
287
|
|
|
220
288
|
const { updateAllMatrix, updateAllChange } = LeafHelper;
|
|
221
|
-
const debug$
|
|
289
|
+
const debug$2 = Debug.get('Layouter');
|
|
222
290
|
class Layouter {
|
|
223
291
|
constructor(target, userConfig) {
|
|
224
292
|
this.totalTimes = 0;
|
|
@@ -253,7 +321,7 @@ class Layouter {
|
|
|
253
321
|
target.emitEvent(new LayoutEvent(LayoutEvent.END, this.layoutedBlocks, this.times));
|
|
254
322
|
}
|
|
255
323
|
catch (e) {
|
|
256
|
-
debug$
|
|
324
|
+
debug$2.error(e);
|
|
257
325
|
}
|
|
258
326
|
this.layoutedBlocks = null;
|
|
259
327
|
}
|
|
@@ -267,9 +335,9 @@ class Layouter {
|
|
|
267
335
|
}
|
|
268
336
|
layoutOnce() {
|
|
269
337
|
if (this.layouting)
|
|
270
|
-
return debug$
|
|
338
|
+
return debug$2.warn('layouting');
|
|
271
339
|
if (this.times > 3)
|
|
272
|
-
return debug$
|
|
340
|
+
return debug$2.warn('layout max times');
|
|
273
341
|
this.times++;
|
|
274
342
|
this.totalTimes++;
|
|
275
343
|
this.layouting = true;
|
|
@@ -335,9 +403,11 @@ class Layouter {
|
|
|
335
403
|
updateAllChange(target);
|
|
336
404
|
}
|
|
337
405
|
addExtra(leaf) {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
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
|
+
}
|
|
341
411
|
}
|
|
342
412
|
createBlock(data) {
|
|
343
413
|
return new LayoutBlockData(data);
|
|
@@ -371,7 +441,7 @@ class Layouter {
|
|
|
371
441
|
}
|
|
372
442
|
}
|
|
373
443
|
|
|
374
|
-
const debug = Debug.get('Renderer');
|
|
444
|
+
const debug$1 = Debug.get('Renderer');
|
|
375
445
|
class Renderer {
|
|
376
446
|
get needFill() { return !!(!this.canvas.allowBackgroundColor && this.config.fill); }
|
|
377
447
|
constructor(target, canvas, userConfig) {
|
|
@@ -409,7 +479,7 @@ class Renderer {
|
|
|
409
479
|
const { target } = this;
|
|
410
480
|
this.times = 0;
|
|
411
481
|
this.totalBounds = new Bounds();
|
|
412
|
-
debug.log(target.innerName, '--->');
|
|
482
|
+
debug$1.log(target.innerName, '--->');
|
|
413
483
|
try {
|
|
414
484
|
this.emitRender(RenderEvent.START);
|
|
415
485
|
this.renderOnce(callback);
|
|
@@ -418,9 +488,9 @@ class Renderer {
|
|
|
418
488
|
}
|
|
419
489
|
catch (e) {
|
|
420
490
|
this.rendering = false;
|
|
421
|
-
debug.error(e);
|
|
491
|
+
debug$1.error(e);
|
|
422
492
|
}
|
|
423
|
-
debug.log('-------------|');
|
|
493
|
+
debug$1.log('-------------|');
|
|
424
494
|
}
|
|
425
495
|
renderAgain() {
|
|
426
496
|
if (this.rendering) {
|
|
@@ -432,9 +502,9 @@ class Renderer {
|
|
|
432
502
|
}
|
|
433
503
|
renderOnce(callback) {
|
|
434
504
|
if (this.rendering)
|
|
435
|
-
return debug.warn('rendering');
|
|
505
|
+
return debug$1.warn('rendering');
|
|
436
506
|
if (this.times > 3)
|
|
437
|
-
return debug.warn('render max times');
|
|
507
|
+
return debug$1.warn('render max times');
|
|
438
508
|
this.times++;
|
|
439
509
|
this.totalTimes++;
|
|
440
510
|
this.rendering = true;
|
|
@@ -447,6 +517,10 @@ class Renderer {
|
|
|
447
517
|
}
|
|
448
518
|
else {
|
|
449
519
|
this.requestLayout();
|
|
520
|
+
if (this.ignore) {
|
|
521
|
+
this.ignore = this.rendering = false;
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
450
524
|
this.emitRender(RenderEvent.BEFORE);
|
|
451
525
|
if (this.config.usePartRender && this.totalTimes > 1) {
|
|
452
526
|
this.partRender();
|
|
@@ -467,7 +541,7 @@ class Renderer {
|
|
|
467
541
|
partRender() {
|
|
468
542
|
const { canvas, updateBlocks: list } = this;
|
|
469
543
|
if (!list)
|
|
470
|
-
return debug.warn('PartRender: need update attr');
|
|
544
|
+
return debug$1.warn('PartRender: need update attr');
|
|
471
545
|
this.mergeBlocks();
|
|
472
546
|
list.forEach(block => { if (canvas.bounds.hit(block) && !block.isEmpty())
|
|
473
547
|
this.clipRender(block); });
|
|
@@ -483,7 +557,7 @@ class Renderer {
|
|
|
483
557
|
canvas.clear();
|
|
484
558
|
}
|
|
485
559
|
else {
|
|
486
|
-
bounds.spread(
|
|
560
|
+
bounds.spread(10 + 1 / this.canvas.pixelRatio).ceil();
|
|
487
561
|
canvas.clearWorld(bounds, true);
|
|
488
562
|
canvas.clipWorld(bounds, true);
|
|
489
563
|
}
|
|
@@ -536,12 +610,12 @@ class Renderer {
|
|
|
536
610
|
const startTime = Date.now();
|
|
537
611
|
Platform.requestRender(() => {
|
|
538
612
|
this.FPS = Math.min(60, Math.ceil(1000 / (Date.now() - startTime)));
|
|
539
|
-
if (this.
|
|
540
|
-
|
|
613
|
+
if (this.running) {
|
|
614
|
+
this.target.emit(AnimateEvent.FRAME);
|
|
615
|
+
if (this.changed && this.canvas.view)
|
|
541
616
|
this.render();
|
|
617
|
+
this.target.emit(RenderEvent.NEXT);
|
|
542
618
|
}
|
|
543
|
-
if (this.running)
|
|
544
|
-
this.target.emit(AnimateEvent.FRAME);
|
|
545
619
|
if (this.target)
|
|
546
620
|
this.__requestRender();
|
|
547
621
|
});
|
|
@@ -554,9 +628,12 @@ class Renderer {
|
|
|
554
628
|
const bounds = new Bounds(0, 0, width, height);
|
|
555
629
|
if (!bounds.includes(this.target.__world) || this.needFill || !e.samePixelRatio) {
|
|
556
630
|
this.addBlock(this.canvas.bounds);
|
|
557
|
-
this.target.forceUpdate('
|
|
631
|
+
this.target.forceUpdate('surface');
|
|
632
|
+
return;
|
|
558
633
|
}
|
|
559
634
|
}
|
|
635
|
+
this.addBlock(new Bounds(0, 0, 1, 1));
|
|
636
|
+
this.changed = true;
|
|
560
637
|
}
|
|
561
638
|
__onLayoutEnd(event) {
|
|
562
639
|
if (event.data)
|
|
@@ -567,7 +644,7 @@ class Renderer {
|
|
|
567
644
|
empty = (!leaf.__world.width || !leaf.__world.height);
|
|
568
645
|
if (empty) {
|
|
569
646
|
if (!leaf.isLeafer)
|
|
570
|
-
debug.tip(leaf.innerName, ': empty');
|
|
647
|
+
debug$1.tip(leaf.innerName, ': empty');
|
|
571
648
|
empty = (!leaf.isBranch || leaf.isBranchLeaf);
|
|
572
649
|
}
|
|
573
650
|
return empty;
|
|
@@ -594,23 +671,13 @@ class Renderer {
|
|
|
594
671
|
if (this.target) {
|
|
595
672
|
this.stop();
|
|
596
673
|
this.__removeListenEvents();
|
|
597
|
-
this.target = null;
|
|
598
|
-
this.canvas = null;
|
|
599
|
-
this.config = null;
|
|
674
|
+
this.target = this.canvas = this.config = null;
|
|
600
675
|
}
|
|
601
676
|
}
|
|
602
677
|
}
|
|
603
678
|
|
|
604
|
-
var AnswerType;
|
|
605
|
-
(function (AnswerType) {
|
|
606
|
-
AnswerType[AnswerType["No"] = 0] = "No";
|
|
607
|
-
AnswerType[AnswerType["Yes"] = 1] = "Yes";
|
|
608
|
-
AnswerType[AnswerType["NoAndSkip"] = 2] = "NoAndSkip";
|
|
609
|
-
AnswerType[AnswerType["YesAndSkip"] = 3] = "YesAndSkip";
|
|
610
|
-
})(AnswerType || (AnswerType = {}));
|
|
611
|
-
|
|
612
679
|
const { hitRadiusPoint } = BoundsHelper;
|
|
613
|
-
class
|
|
680
|
+
class Picker {
|
|
614
681
|
constructor(target, selector) {
|
|
615
682
|
this.target = target;
|
|
616
683
|
this.selector = selector;
|
|
@@ -622,33 +689,41 @@ class Pather {
|
|
|
622
689
|
options = {};
|
|
623
690
|
const through = options.through || false;
|
|
624
691
|
const ignoreHittable = options.ignoreHittable || false;
|
|
692
|
+
const target = options.target || this.target;
|
|
625
693
|
this.exclude = options.exclude || null;
|
|
626
694
|
this.point = { x: hitPoint.x, y: hitPoint.y, radiusX: hitRadius, radiusY: hitRadius };
|
|
627
|
-
this.findList =
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
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);
|
|
631
700
|
const path = ignoreHittable ? this.getPath(leaf) : this.getHitablePath(leaf);
|
|
632
701
|
this.clear();
|
|
633
|
-
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 };
|
|
634
703
|
}
|
|
635
|
-
getBestMatchLeaf() {
|
|
636
|
-
|
|
637
|
-
if (targets.length > 1) {
|
|
704
|
+
getBestMatchLeaf(list, bottomList, ignoreHittable) {
|
|
705
|
+
if (list.length) {
|
|
638
706
|
let find;
|
|
639
|
-
this.findList =
|
|
707
|
+
this.findList = new LeafList();
|
|
640
708
|
const { x, y } = this.point;
|
|
641
709
|
const point = { x, y, radiusX: 0, radiusY: 0 };
|
|
642
|
-
for (let i = 0, len =
|
|
643
|
-
find =
|
|
644
|
-
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)) {
|
|
645
713
|
this.hitChild(find, point);
|
|
646
714
|
if (this.findList.length)
|
|
647
|
-
return this.findList[0];
|
|
715
|
+
return this.findList.list[0];
|
|
648
716
|
}
|
|
649
717
|
}
|
|
650
718
|
}
|
|
651
|
-
|
|
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];
|
|
652
727
|
}
|
|
653
728
|
getPath(leaf) {
|
|
654
729
|
const path = new LeafList();
|
|
@@ -660,7 +735,7 @@ class Pather {
|
|
|
660
735
|
return path;
|
|
661
736
|
}
|
|
662
737
|
getHitablePath(leaf) {
|
|
663
|
-
const path = this.getPath(leaf);
|
|
738
|
+
const path = this.getPath(leaf && leaf.hittable ? leaf : null);
|
|
664
739
|
let item, hittablePath = new LeafList();
|
|
665
740
|
for (let i = path.list.length - 1; i > -1; i--) {
|
|
666
741
|
item = path.list[i];
|
|
@@ -690,12 +765,15 @@ class Pather {
|
|
|
690
765
|
}
|
|
691
766
|
return throughPath;
|
|
692
767
|
}
|
|
768
|
+
hitBranch(branch) {
|
|
769
|
+
this.eachFind(branch.children, branch.__onlyHitMask);
|
|
770
|
+
}
|
|
693
771
|
eachFind(children, hitMask) {
|
|
694
772
|
let child, hit;
|
|
695
773
|
const { point } = this, len = children.length;
|
|
696
774
|
for (let i = len - 1; i > -1; i--) {
|
|
697
775
|
child = children[i];
|
|
698
|
-
if (!child.__.visible || (hitMask && !child.__.
|
|
776
|
+
if (!child.__.visible || (hitMask && !child.__.mask))
|
|
699
777
|
continue;
|
|
700
778
|
hit = child.__.hitRadius ? true : hitRadiusPoint(child.__world, point);
|
|
701
779
|
if (child.isBranch) {
|
|
@@ -711,11 +789,15 @@ class Pather {
|
|
|
711
789
|
}
|
|
712
790
|
}
|
|
713
791
|
}
|
|
714
|
-
hitChild(child, point) {
|
|
792
|
+
hitChild(child, point, proxy) {
|
|
715
793
|
if (this.exclude && this.exclude.has(child))
|
|
716
794
|
return;
|
|
717
|
-
if (child.__hitWorld(point))
|
|
718
|
-
|
|
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
|
+
}
|
|
719
801
|
}
|
|
720
802
|
clear() {
|
|
721
803
|
this.point = null;
|
|
@@ -727,7 +809,8 @@ class Pather {
|
|
|
727
809
|
}
|
|
728
810
|
}
|
|
729
811
|
|
|
730
|
-
const { Yes, NoAndSkip, YesAndSkip } =
|
|
812
|
+
const { Yes, NoAndSkip, YesAndSkip } = Answer;
|
|
813
|
+
const idCondition = {}, classNameCondition = {}, tagCondition = {};
|
|
731
814
|
class Selector {
|
|
732
815
|
constructor(target, userConfig) {
|
|
733
816
|
this.config = {};
|
|
@@ -737,12 +820,13 @@ class Selector {
|
|
|
737
820
|
id: (leaf, name) => leaf.id === name ? (this.idMap[name] = leaf, 1) : 0,
|
|
738
821
|
innerId: (leaf, innerId) => leaf.innerId === innerId ? (this.innerIdMap[innerId] = leaf, 1) : 0,
|
|
739
822
|
className: (leaf, name) => leaf.className === name ? 1 : 0,
|
|
740
|
-
tag: (leaf, name) => leaf.__tag === name ? 1 : 0
|
|
823
|
+
tag: (leaf, name) => leaf.__tag === name ? 1 : 0,
|
|
824
|
+
tags: (leaf, nameMap) => nameMap[leaf.__tag] ? 1 : 0
|
|
741
825
|
};
|
|
742
826
|
this.target = target;
|
|
743
827
|
if (userConfig)
|
|
744
828
|
this.config = DataHelper.default(userConfig, this.config);
|
|
745
|
-
this.
|
|
829
|
+
this.picker = new Picker(target, this);
|
|
746
830
|
this.__listenEvents();
|
|
747
831
|
}
|
|
748
832
|
getBy(condition, branch, one, options) {
|
|
@@ -753,12 +837,25 @@ class Selector {
|
|
|
753
837
|
case 'string':
|
|
754
838
|
switch (condition[0]) {
|
|
755
839
|
case '#':
|
|
756
|
-
|
|
757
|
-
|
|
840
|
+
idCondition.id = condition.substring(1), condition = idCondition;
|
|
841
|
+
break;
|
|
758
842
|
case '.':
|
|
759
|
-
|
|
843
|
+
classNameCondition.className = condition.substring(1), condition = classNameCondition;
|
|
844
|
+
break;
|
|
760
845
|
default:
|
|
761
|
-
|
|
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);
|
|
762
859
|
}
|
|
763
860
|
case 'function':
|
|
764
861
|
return this.getByMethod(condition, branch, one, options);
|
|
@@ -767,7 +864,7 @@ class Selector {
|
|
|
767
864
|
getByPoint(hitPoint, hitRadius, options) {
|
|
768
865
|
if (Platform.name === 'node')
|
|
769
866
|
this.target.emit(LayoutEvent.CHECK_UPDATE);
|
|
770
|
-
return this.
|
|
867
|
+
return this.picker.getByPoint(hitPoint, hitRadius, options);
|
|
771
868
|
}
|
|
772
869
|
getByInnerId(innerId, branch) {
|
|
773
870
|
const cache = this.innerIdMap[innerId];
|
|
@@ -843,7 +940,7 @@ class Selector {
|
|
|
843
940
|
destroy() {
|
|
844
941
|
if (this.__eventIds.length) {
|
|
845
942
|
this.__removeListenEvents();
|
|
846
|
-
this.
|
|
943
|
+
this.picker.destroy();
|
|
847
944
|
this.findLeaf = null;
|
|
848
945
|
this.innerIdMap = {};
|
|
849
946
|
this.idMap = {};
|
|
@@ -859,466 +956,91 @@ Object.assign(Creator, {
|
|
|
859
956
|
});
|
|
860
957
|
Platform.layout = Layouter.fullLayout;
|
|
861
958
|
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
this.context.__proto__.roundRect = null;
|
|
870
|
-
canvasPatch(this.context.__proto__);
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
__createView() {
|
|
874
|
-
this.view = Platform.origin.createCanvas(1, 1);
|
|
875
|
-
}
|
|
876
|
-
updateViewSize() {
|
|
877
|
-
const { width, height, pixelRatio } = this;
|
|
878
|
-
this.view.width = width * pixelRatio;
|
|
879
|
-
this.view.height = height * pixelRatio;
|
|
880
|
-
this.clientBounds = this.bounds;
|
|
881
|
-
}
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
const { mineType, fileType } = FileHelper;
|
|
885
|
-
Object.assign(Creator, {
|
|
886
|
-
canvas: (options, manager) => new LeaferCanvas(options, manager),
|
|
887
|
-
image: (options) => new LeaferImage(options),
|
|
888
|
-
hitCanvas: (options, manager) => new LeaferCanvas(options, manager),
|
|
889
|
-
interaction: (target, canvas, selector, options) => { return new InteractionBase(target, canvas, selector, options); }
|
|
890
|
-
});
|
|
891
|
-
function useCanvas(canvasType, power) {
|
|
892
|
-
Platform.canvasType = canvasType;
|
|
893
|
-
if (!Platform.origin) {
|
|
894
|
-
if (canvasType === 'skia') {
|
|
895
|
-
const { Canvas, loadImage } = power;
|
|
896
|
-
Platform.origin = {
|
|
897
|
-
createCanvas: (width, height, format) => new Canvas(width, height, format),
|
|
898
|
-
canvasToDataURL: (canvas, type, quality) => canvas.toDataURLSync(type, { quality }),
|
|
899
|
-
canvasToBolb: (canvas, type, quality) => canvas.toBuffer(type, { quality }),
|
|
900
|
-
canvasSaveAs: (canvas, filename, quality) => canvas.saveAs(filename, { quality }),
|
|
901
|
-
loadImage
|
|
902
|
-
};
|
|
903
|
-
Platform.roundRectPatch = true;
|
|
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);
|
|
904
966
|
}
|
|
905
|
-
else if (
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
canvasToDataURL: (canvas, type, quality) => canvas.toDataURL(mineType(type), quality),
|
|
910
|
-
canvasToBolb: (canvas, type, quality) => __awaiter(this, void 0, void 0, function* () { return canvas.toBuffer(mineType(type), quality); }),
|
|
911
|
-
canvasSaveAs: (canvas, filename, quality) => __awaiter(this, void 0, void 0, function* () { return writeFileSync(filename, canvas.toBuffer(mineType(fileType(filename)), quality)); }),
|
|
912
|
-
loadImage
|
|
913
|
-
};
|
|
967
|
+
else if (row.data) {
|
|
968
|
+
row.data.forEach(charData => {
|
|
969
|
+
canvas.fillText(charData.char, charData.x, row.y);
|
|
970
|
+
});
|
|
914
971
|
}
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
stopDefault(_origin) { },
|
|
918
|
-
stopNow(_origin) { },
|
|
919
|
-
stop(_origin) { }
|
|
920
|
-
};
|
|
921
|
-
Platform.canvas = Creator.canvas();
|
|
972
|
+
if (decorationY)
|
|
973
|
+
canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight);
|
|
922
974
|
}
|
|
923
975
|
}
|
|
924
|
-
Platform.name = 'node';
|
|
925
|
-
Platform.requestRender = function (render) { setTimeout(render); };
|
|
926
|
-
Platform.devicePixelRatio = 1;
|
|
927
|
-
Platform.conicGradientSupport = true;
|
|
928
976
|
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
const swap = rotation && rotation !== 180;
|
|
933
|
-
const sw = box.width / (swap ? height : width);
|
|
934
|
-
const sh = box.height / (swap ? width : height);
|
|
935
|
-
const scale = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
|
|
936
|
-
const x = box.x + (box.width - width * scale) / 2;
|
|
937
|
-
const y = box.y + (box.height - height * scale) / 2;
|
|
938
|
-
translate$1(transform, x, y);
|
|
939
|
-
scaleHelper(transform, scale);
|
|
940
|
-
if (rotation)
|
|
941
|
-
rotateOfOuter$2(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
|
|
942
|
-
data.scaleX = data.scaleY = scale;
|
|
943
|
-
data.transform = transform;
|
|
944
|
-
}
|
|
945
|
-
function clipMode(data, box, offset, scale, rotation) {
|
|
946
|
-
const transform = get$4();
|
|
947
|
-
translate$1(transform, box.x, box.y);
|
|
948
|
-
if (offset)
|
|
949
|
-
translate$1(transform, offset.x, offset.y);
|
|
950
|
-
if (scale) {
|
|
951
|
-
typeof scale === 'number' ? scaleHelper(transform, scale) : scaleHelper(transform, scale.x, scale.y);
|
|
952
|
-
data.scaleX = transform.a;
|
|
953
|
-
data.scaleY = transform.d;
|
|
954
|
-
}
|
|
955
|
-
if (rotation)
|
|
956
|
-
rotate(transform, rotation);
|
|
957
|
-
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());
|
|
958
980
|
}
|
|
959
|
-
function
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
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
|
+
}
|
|
973
1008
|
}
|
|
974
1009
|
}
|
|
975
|
-
translate$1(transform, box.x, box.y);
|
|
976
|
-
if (scale) {
|
|
977
|
-
scaleOfOuter$2(transform, box, scale);
|
|
978
|
-
data.scaleX = data.scaleY = scale;
|
|
979
|
-
}
|
|
980
|
-
data.transform = transform;
|
|
981
1010
|
}
|
|
982
1011
|
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
const data = leafPaint.data = { mode };
|
|
991
|
-
switch (mode) {
|
|
992
|
-
case 'strench':
|
|
993
|
-
if (!sameBox)
|
|
994
|
-
width = box.width, height = box.height;
|
|
995
|
-
if (box.x || box.y) {
|
|
996
|
-
data.transform = get$3();
|
|
997
|
-
translate(data.transform, box.x, box.y);
|
|
998
|
-
}
|
|
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);
|
|
999
1019
|
break;
|
|
1000
|
-
case '
|
|
1001
|
-
|
|
1002
|
-
clipMode(data, box, offset, scale, rotation);
|
|
1020
|
+
case 'inside':
|
|
1021
|
+
drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
|
|
1003
1022
|
break;
|
|
1004
|
-
case '
|
|
1005
|
-
|
|
1006
|
-
repeatMode(data, box, width, height, scale, rotation);
|
|
1007
|
-
if (!repeat)
|
|
1008
|
-
data.repeat = 'repeat';
|
|
1023
|
+
case 'outside':
|
|
1024
|
+
drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
|
|
1009
1025
|
break;
|
|
1010
|
-
case 'fit':
|
|
1011
|
-
case 'cover':
|
|
1012
|
-
default:
|
|
1013
|
-
if (!sameBox || rotation)
|
|
1014
|
-
fillOrFitMode(data, mode, box, width, height, rotation);
|
|
1015
1026
|
}
|
|
1016
|
-
data.width = width;
|
|
1017
|
-
data.height = height;
|
|
1018
|
-
if (opacity)
|
|
1019
|
-
data.opacity = opacity;
|
|
1020
|
-
if (repeat)
|
|
1021
|
-
data.repeat = typeof repeat === 'string' ? (repeat === 'x' ? 'repeat-x' : 'repeat-y') : 'repeat';
|
|
1022
1027
|
}
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
const
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
}
|
|
1035
|
-
}
|
|
1036
|
-
else if (image.error) {
|
|
1037
|
-
if (firstUse) {
|
|
1038
|
-
ui.forceUpdate('surface');
|
|
1039
|
-
event.error = image.error;
|
|
1040
|
-
emit(ImageEvent.ERROR, event);
|
|
1041
|
-
}
|
|
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.__);
|
|
1032
|
+
out.font = __font;
|
|
1033
|
+
isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
|
|
1034
|
+
out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
|
|
1035
|
+
fillText(ui, out);
|
|
1036
|
+
out.blendMode = 'normal';
|
|
1037
|
+
if (ui.__worldFlipped) {
|
|
1038
|
+
canvas.copyWorldByReset(out, ui.__nowWorld);
|
|
1042
1039
|
}
|
|
1043
1040
|
else {
|
|
1044
|
-
|
|
1045
|
-
emit(ImageEvent.LOAD, event);
|
|
1046
|
-
leafPaint.loadId = image.load(() => {
|
|
1047
|
-
if (!ui.destroyed) {
|
|
1048
|
-
if (hasNaturalSize(ui, attrName, image)) {
|
|
1049
|
-
createData(leafPaint, image, attrValue, box);
|
|
1050
|
-
ui.forceUpdate('surface');
|
|
1051
|
-
}
|
|
1052
|
-
emit(ImageEvent.LOADED, event);
|
|
1053
|
-
}
|
|
1054
|
-
}, (error) => {
|
|
1055
|
-
ui.forceUpdate('surface');
|
|
1056
|
-
event.error = error;
|
|
1057
|
-
emit(ImageEvent.ERROR, event);
|
|
1058
|
-
});
|
|
1059
|
-
}
|
|
1060
|
-
return leafPaint;
|
|
1061
|
-
}
|
|
1062
|
-
function hasNaturalSize(ui, attrName, image) {
|
|
1063
|
-
if (attrName === 'fill' && !ui.__.__naturalWidth) {
|
|
1064
|
-
const { __: d } = ui;
|
|
1065
|
-
d.__naturalWidth = image.width;
|
|
1066
|
-
d.__naturalHeight = image.height;
|
|
1067
|
-
if (!d.__getInput('width') || !d.__getInput('height')) {
|
|
1068
|
-
ui.forceUpdate('width');
|
|
1069
|
-
if (ui.__proxyData) {
|
|
1070
|
-
ui.setProxyAttr('width', ui.__.width);
|
|
1071
|
-
ui.setProxyAttr('height', ui.__.height);
|
|
1072
|
-
}
|
|
1073
|
-
return false;
|
|
1074
|
-
}
|
|
1041
|
+
canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
|
|
1075
1042
|
}
|
|
1076
|
-
|
|
1077
|
-
}
|
|
1078
|
-
function emit(type, data) {
|
|
1079
|
-
if (data.target.hasEvent(type))
|
|
1080
|
-
data.target.emitEvent(new ImageEvent(type, data));
|
|
1081
|
-
}
|
|
1082
|
-
|
|
1083
|
-
const Export$1 = {};
|
|
1084
|
-
|
|
1085
|
-
const { get: get$2, scale, copy: copy$1 } = MatrixHelper;
|
|
1086
|
-
function createPattern(ui, paint, pixelRatio) {
|
|
1087
|
-
let { scaleX, scaleY } = ui.__world;
|
|
1088
|
-
const id = scaleX + '-' + scaleY;
|
|
1089
|
-
if (paint.patternId !== id && !ui.destroyed) {
|
|
1090
|
-
scaleX = Math.abs(scaleX);
|
|
1091
|
-
scaleY = Math.abs(scaleY);
|
|
1092
|
-
const { image, data } = paint;
|
|
1093
|
-
let imageScale, imageMatrix, { width, height, scaleX: sx, scaleY: sy, opacity, transform, repeat } = data;
|
|
1094
|
-
if (sx) {
|
|
1095
|
-
imageMatrix = get$2();
|
|
1096
|
-
copy$1(imageMatrix, transform);
|
|
1097
|
-
scale(imageMatrix, 1 / sx, 1 / sy);
|
|
1098
|
-
scaleX *= sx;
|
|
1099
|
-
scaleY *= sy;
|
|
1100
|
-
}
|
|
1101
|
-
scaleX *= pixelRatio;
|
|
1102
|
-
scaleY *= pixelRatio;
|
|
1103
|
-
width *= scaleX;
|
|
1104
|
-
height *= scaleY;
|
|
1105
|
-
const size = width * height;
|
|
1106
|
-
if (!repeat) {
|
|
1107
|
-
if (size > Platform.image.maxCacheSize)
|
|
1108
|
-
return false;
|
|
1109
|
-
}
|
|
1110
|
-
let maxSize = Platform.image.maxPatternSize;
|
|
1111
|
-
if (!image.isSVG) {
|
|
1112
|
-
const imageSize = image.width * image.height;
|
|
1113
|
-
if (maxSize > imageSize)
|
|
1114
|
-
maxSize = imageSize;
|
|
1115
|
-
}
|
|
1116
|
-
if (size > maxSize)
|
|
1117
|
-
imageScale = Math.sqrt(size / maxSize);
|
|
1118
|
-
if (imageScale) {
|
|
1119
|
-
scaleX /= imageScale;
|
|
1120
|
-
scaleY /= imageScale;
|
|
1121
|
-
width /= imageScale;
|
|
1122
|
-
height /= imageScale;
|
|
1123
|
-
}
|
|
1124
|
-
if (sx) {
|
|
1125
|
-
scaleX /= sx;
|
|
1126
|
-
scaleY /= sy;
|
|
1127
|
-
}
|
|
1128
|
-
if (transform || scaleX !== 1 || scaleY !== 1) {
|
|
1129
|
-
if (!imageMatrix) {
|
|
1130
|
-
imageMatrix = get$2();
|
|
1131
|
-
if (transform)
|
|
1132
|
-
copy$1(imageMatrix, transform);
|
|
1133
|
-
}
|
|
1134
|
-
scale(imageMatrix, 1 / scaleX, 1 / scaleY);
|
|
1135
|
-
}
|
|
1136
|
-
const pattern = Platform.canvas.createPattern(image.getCanvas(width < 1 ? 1 : width, height < 1 ? 1 : height, opacity), repeat || (Platform.origin.noRepeat || 'no-repeat'));
|
|
1137
|
-
try {
|
|
1138
|
-
if (paint.transform)
|
|
1139
|
-
paint.transform = null;
|
|
1140
|
-
if (imageMatrix)
|
|
1141
|
-
pattern.setTransform ? pattern.setTransform(imageMatrix) : paint.transform = imageMatrix;
|
|
1142
|
-
}
|
|
1143
|
-
catch (_a) {
|
|
1144
|
-
paint.transform = imageMatrix;
|
|
1145
|
-
}
|
|
1146
|
-
paint.style = pattern;
|
|
1147
|
-
paint.patternId = id;
|
|
1148
|
-
return true;
|
|
1149
|
-
}
|
|
1150
|
-
else {
|
|
1151
|
-
return false;
|
|
1152
|
-
}
|
|
1153
|
-
}
|
|
1154
|
-
|
|
1155
|
-
const { abs } = Math;
|
|
1156
|
-
function checkImage(ui, canvas, paint, allowPaint) {
|
|
1157
|
-
const { scaleX, scaleY } = ui.__world;
|
|
1158
|
-
if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
|
|
1159
|
-
return false;
|
|
1160
|
-
}
|
|
1161
|
-
else {
|
|
1162
|
-
const { data } = paint;
|
|
1163
|
-
if (allowPaint) {
|
|
1164
|
-
if (!data.repeat) {
|
|
1165
|
-
let { width, height } = data;
|
|
1166
|
-
width *= abs(scaleX) * canvas.pixelRatio;
|
|
1167
|
-
height *= abs(scaleY) * canvas.pixelRatio;
|
|
1168
|
-
if (data.scaleX) {
|
|
1169
|
-
width *= data.scaleX;
|
|
1170
|
-
height *= data.scaleY;
|
|
1171
|
-
}
|
|
1172
|
-
allowPaint = width * height > Platform.image.maxCacheSize;
|
|
1173
|
-
}
|
|
1174
|
-
else {
|
|
1175
|
-
allowPaint = false;
|
|
1176
|
-
}
|
|
1177
|
-
}
|
|
1178
|
-
if (allowPaint) {
|
|
1179
|
-
canvas.save();
|
|
1180
|
-
canvas.clip();
|
|
1181
|
-
if (paint.blendMode)
|
|
1182
|
-
canvas.blendMode = paint.blendMode;
|
|
1183
|
-
if (data.opacity)
|
|
1184
|
-
canvas.opacity *= data.opacity;
|
|
1185
|
-
if (data.transform)
|
|
1186
|
-
canvas.transform(data.transform);
|
|
1187
|
-
canvas.drawImage(paint.image.view, 0, 0, data.width, data.height);
|
|
1188
|
-
canvas.restore();
|
|
1189
|
-
return true;
|
|
1190
|
-
}
|
|
1191
|
-
else {
|
|
1192
|
-
if (!paint.style || Export$1.running) {
|
|
1193
|
-
createPattern(ui, paint, canvas.pixelRatio);
|
|
1194
|
-
}
|
|
1195
|
-
else {
|
|
1196
|
-
if (!paint.patternTask) {
|
|
1197
|
-
paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
|
|
1198
|
-
paint.patternTask = null;
|
|
1199
|
-
if (canvas.bounds.hit(ui.__world))
|
|
1200
|
-
createPattern(ui, paint, canvas.pixelRatio);
|
|
1201
|
-
ui.forceUpdate('surface');
|
|
1202
|
-
}), 300);
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
1205
|
-
return false;
|
|
1206
|
-
}
|
|
1207
|
-
}
|
|
1208
|
-
}
|
|
1209
|
-
|
|
1210
|
-
function recycleImage(attrName, data) {
|
|
1211
|
-
const paints = data['_' + attrName];
|
|
1212
|
-
if (paints instanceof Array) {
|
|
1213
|
-
let image, recycleMap, input, url;
|
|
1214
|
-
for (let i = 0, len = paints.length; i < len; i++) {
|
|
1215
|
-
image = paints[i].image;
|
|
1216
|
-
url = image && image.url;
|
|
1217
|
-
if (url) {
|
|
1218
|
-
if (!recycleMap)
|
|
1219
|
-
recycleMap = {};
|
|
1220
|
-
recycleMap[url] = true;
|
|
1221
|
-
ImageManager.recycle(image);
|
|
1222
|
-
if (image.loading) {
|
|
1223
|
-
if (!input) {
|
|
1224
|
-
input = (data.__input && data.__input[attrName]) || [];
|
|
1225
|
-
if (!(input instanceof Array))
|
|
1226
|
-
input = [input];
|
|
1227
|
-
}
|
|
1228
|
-
image.unload(paints[i].loadId, !input.some((item) => item.url === url));
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
}
|
|
1232
|
-
return recycleMap;
|
|
1233
|
-
}
|
|
1234
|
-
return null;
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
function fillText(ui, canvas) {
|
|
1238
|
-
let row;
|
|
1239
|
-
const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
|
|
1240
|
-
for (let i = 0, len = rows.length; i < len; i++) {
|
|
1241
|
-
row = rows[i];
|
|
1242
|
-
if (row.text) {
|
|
1243
|
-
canvas.fillText(row.text, row.x, row.y);
|
|
1244
|
-
}
|
|
1245
|
-
else if (row.data) {
|
|
1246
|
-
row.data.forEach(charData => {
|
|
1247
|
-
canvas.fillText(charData.char, charData.x, row.y);
|
|
1248
|
-
});
|
|
1249
|
-
}
|
|
1250
|
-
if (decorationY)
|
|
1251
|
-
canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight);
|
|
1252
|
-
}
|
|
1253
|
-
}
|
|
1254
|
-
|
|
1255
|
-
function fill(fill, ui, canvas) {
|
|
1256
|
-
canvas.fillStyle = fill;
|
|
1257
|
-
ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
|
|
1258
|
-
}
|
|
1259
|
-
function fills(fills, ui, canvas) {
|
|
1260
|
-
let item;
|
|
1261
|
-
const { windingRule, __font } = ui.__;
|
|
1262
|
-
for (let i = 0, len = fills.length; i < len; i++) {
|
|
1263
|
-
item = fills[i];
|
|
1264
|
-
if (item.image && checkImage(ui, canvas, item, !__font))
|
|
1265
|
-
continue;
|
|
1266
|
-
if (item.style) {
|
|
1267
|
-
canvas.fillStyle = item.style;
|
|
1268
|
-
if (item.transform) {
|
|
1269
|
-
canvas.save();
|
|
1270
|
-
canvas.transform(item.transform);
|
|
1271
|
-
if (item.blendMode)
|
|
1272
|
-
canvas.blendMode = item.blendMode;
|
|
1273
|
-
__font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
|
|
1274
|
-
canvas.restore();
|
|
1275
|
-
}
|
|
1276
|
-
else {
|
|
1277
|
-
if (item.blendMode) {
|
|
1278
|
-
canvas.saveBlendMode(item.blendMode);
|
|
1279
|
-
__font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
|
|
1280
|
-
canvas.restoreBlendMode();
|
|
1281
|
-
}
|
|
1282
|
-
else {
|
|
1283
|
-
__font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
|
|
1284
|
-
}
|
|
1285
|
-
}
|
|
1286
|
-
}
|
|
1287
|
-
}
|
|
1288
|
-
}
|
|
1289
|
-
|
|
1290
|
-
function strokeText(stroke, ui, canvas, renderOptions) {
|
|
1291
|
-
const { strokeAlign } = ui.__;
|
|
1292
|
-
const isStrokes = typeof stroke !== 'string';
|
|
1293
|
-
switch (strokeAlign) {
|
|
1294
|
-
case 'center':
|
|
1295
|
-
canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
|
|
1296
|
-
isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
|
|
1297
|
-
break;
|
|
1298
|
-
case 'inside':
|
|
1299
|
-
drawAlignStroke('inside', stroke, isStrokes, ui, canvas, renderOptions);
|
|
1300
|
-
break;
|
|
1301
|
-
case 'outside':
|
|
1302
|
-
drawAlignStroke('outside', stroke, isStrokes, ui, canvas, renderOptions);
|
|
1303
|
-
break;
|
|
1304
|
-
}
|
|
1305
|
-
}
|
|
1306
|
-
function drawAlignStroke(align, stroke, isStrokes, ui, canvas, renderOptions) {
|
|
1307
|
-
const { strokeWidth, __font } = ui.__;
|
|
1308
|
-
const out = canvas.getSameCanvas(true);
|
|
1309
|
-
out.setStroke(isStrokes ? undefined : stroke, strokeWidth * 2, ui.__);
|
|
1310
|
-
out.font = __font;
|
|
1311
|
-
isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
|
|
1312
|
-
out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
|
|
1313
|
-
fillText(ui, out);
|
|
1314
|
-
out.blendMode = 'normal';
|
|
1315
|
-
if (ui.__worldFlipped || renderOptions.matrix) {
|
|
1316
|
-
canvas.copyWorldByReset(out);
|
|
1317
|
-
}
|
|
1318
|
-
else {
|
|
1319
|
-
canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds);
|
|
1320
|
-
}
|
|
1321
|
-
out.recycle();
|
|
1043
|
+
out.recycle(ui.__nowWorld);
|
|
1322
1044
|
}
|
|
1323
1045
|
function drawTextStroke(ui, canvas) {
|
|
1324
1046
|
let row;
|
|
@@ -1341,7 +1063,7 @@ function drawStrokesStyle(strokes, isText, ui, canvas) {
|
|
|
1341
1063
|
let item;
|
|
1342
1064
|
for (let i = 0, len = strokes.length; i < len; i++) {
|
|
1343
1065
|
item = strokes[i];
|
|
1344
|
-
if (item.image && checkImage(ui, canvas, item, false))
|
|
1066
|
+
if (item.image && PaintImage.checkImage(ui, canvas, item, false))
|
|
1345
1067
|
continue;
|
|
1346
1068
|
if (item.style) {
|
|
1347
1069
|
canvas.strokeStyle = item.style;
|
|
@@ -1357,138 +1079,567 @@ function drawStrokesStyle(strokes, isText, ui, canvas) {
|
|
|
1357
1079
|
}
|
|
1358
1080
|
}
|
|
1359
1081
|
|
|
1360
|
-
function stroke(stroke, ui, canvas
|
|
1082
|
+
function stroke(stroke, ui, canvas) {
|
|
1361
1083
|
const options = ui.__;
|
|
1362
|
-
const {
|
|
1363
|
-
if (!
|
|
1084
|
+
const { __strokeWidth, strokeAlign, __font } = options;
|
|
1085
|
+
if (!__strokeWidth)
|
|
1364
1086
|
return;
|
|
1365
1087
|
if (__font) {
|
|
1366
|
-
strokeText(stroke, ui, canvas
|
|
1088
|
+
strokeText(stroke, ui, canvas);
|
|
1367
1089
|
}
|
|
1368
1090
|
else {
|
|
1369
1091
|
switch (strokeAlign) {
|
|
1370
1092
|
case 'center':
|
|
1371
|
-
canvas.setStroke(stroke,
|
|
1093
|
+
canvas.setStroke(stroke, __strokeWidth, options);
|
|
1372
1094
|
canvas.stroke();
|
|
1373
1095
|
break;
|
|
1374
1096
|
case 'inside':
|
|
1375
1097
|
canvas.save();
|
|
1376
|
-
canvas.setStroke(stroke,
|
|
1098
|
+
canvas.setStroke(stroke, __strokeWidth * 2, options);
|
|
1377
1099
|
options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
|
|
1378
1100
|
canvas.stroke();
|
|
1379
1101
|
canvas.restore();
|
|
1380
1102
|
break;
|
|
1381
1103
|
case 'outside':
|
|
1382
|
-
const out = canvas.getSameCanvas(true);
|
|
1383
|
-
out.setStroke(stroke,
|
|
1104
|
+
const out = canvas.getSameCanvas(true, true);
|
|
1105
|
+
out.setStroke(stroke, __strokeWidth * 2, options);
|
|
1384
1106
|
ui.__drawRenderPath(out);
|
|
1385
1107
|
out.stroke();
|
|
1386
1108
|
options.windingRule ? out.clip(options.windingRule) : out.clip();
|
|
1387
1109
|
out.clearWorld(ui.__layout.renderBounds);
|
|
1388
|
-
if (ui.__worldFlipped
|
|
1389
|
-
canvas.copyWorldByReset(out);
|
|
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);
|
|
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);
|
|
1390
1152
|
}
|
|
1391
1153
|
else {
|
|
1392
|
-
canvas.copyWorldToInner(out, ui.
|
|
1154
|
+
canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
|
|
1393
1155
|
}
|
|
1394
|
-
out.recycle();
|
|
1156
|
+
out.recycle(ui.__nowWorld);
|
|
1395
1157
|
break;
|
|
1396
1158
|
}
|
|
1397
1159
|
}
|
|
1398
1160
|
}
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
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;
|
|
1503
|
+
}
|
|
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;
|
|
1535
|
+
}
|
|
1536
|
+
else {
|
|
1537
|
+
return false;
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
|
|
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;
|
|
1406
1546
|
}
|
|
1407
1547
|
else {
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
drawStrokesStyle(strokes, false, ui, canvas);
|
|
1418
|
-
canvas.restore();
|
|
1419
|
-
break;
|
|
1420
|
-
case 'outside':
|
|
1421
|
-
const { renderBounds } = ui.__layout;
|
|
1422
|
-
const out = canvas.getSameCanvas(true);
|
|
1423
|
-
ui.__drawRenderPath(out);
|
|
1424
|
-
out.setStroke(undefined, strokeWidth * 2, ui.__);
|
|
1425
|
-
drawStrokesStyle(strokes, false, ui, out);
|
|
1426
|
-
options.windingRule ? out.clip(options.windingRule) : out.clip();
|
|
1427
|
-
out.clearWorld(renderBounds);
|
|
1428
|
-
if (ui.__worldFlipped || renderOptions.matrix) {
|
|
1429
|
-
canvas.copyWorldByReset(out);
|
|
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;
|
|
1430
1557
|
}
|
|
1431
|
-
|
|
1432
|
-
|
|
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;
|
|
1576
|
+
}
|
|
1577
|
+
else {
|
|
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);
|
|
1433
1589
|
}
|
|
1434
|
-
|
|
1435
|
-
|
|
1590
|
+
}
|
|
1591
|
+
return false;
|
|
1436
1592
|
}
|
|
1437
1593
|
}
|
|
1438
1594
|
}
|
|
1439
1595
|
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
shapeBounds = getOuterOf(__world, matrix);
|
|
1462
|
-
bounds = getByMove(shapeBounds, -matrix.e, -matrix.f);
|
|
1463
|
-
if (options.matrix)
|
|
1464
|
-
matrix.multiply(options.matrix);
|
|
1465
|
-
options = Object.assign(Object.assign({}, options), { matrix });
|
|
1466
|
-
}
|
|
1467
|
-
else {
|
|
1468
|
-
if (options.matrix) {
|
|
1469
|
-
scaleX *= options.matrix.a;
|
|
1470
|
-
scaleY *= options.matrix.d;
|
|
1471
|
-
bounds = shapeBounds = getOuterOf(__world, options.matrix);
|
|
1472
|
-
}
|
|
1473
|
-
else {
|
|
1474
|
-
bounds = shapeBounds = __world;
|
|
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
|
+
}
|
|
1475
1617
|
}
|
|
1476
|
-
|
|
1618
|
+
return recycleMap;
|
|
1477
1619
|
}
|
|
1478
|
-
|
|
1479
|
-
return {
|
|
1480
|
-
canvas, matrix, bounds,
|
|
1481
|
-
worldCanvas, shapeBounds, scaleX, scaleY
|
|
1482
|
-
};
|
|
1620
|
+
return null;
|
|
1483
1621
|
}
|
|
1484
1622
|
|
|
1485
|
-
const
|
|
1486
|
-
|
|
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 = {};
|
|
1487
1638
|
function linearGradient(paint, box) {
|
|
1488
1639
|
let { from, to, type, blendMode, opacity } = paint;
|
|
1489
|
-
from ||
|
|
1490
|
-
to ||
|
|
1491
|
-
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);
|
|
1492
1643
|
applyStops(style, paint.stops, opacity);
|
|
1493
1644
|
const data = { type, style };
|
|
1494
1645
|
if (blendMode)
|
|
@@ -1499,137 +1650,84 @@ function applyStops(gradient, stops, opacity) {
|
|
|
1499
1650
|
let stop;
|
|
1500
1651
|
for (let i = 0, len = stops.length; i < len; i++) {
|
|
1501
1652
|
stop = stops[i];
|
|
1502
|
-
|
|
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
|
+
}
|
|
1503
1659
|
}
|
|
1504
1660
|
}
|
|
1505
1661
|
|
|
1506
|
-
const {
|
|
1507
|
-
const { get
|
|
1508
|
-
const
|
|
1509
|
-
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;
|
|
1510
1665
|
const realFrom$1 = {};
|
|
1511
1666
|
const realTo$1 = {};
|
|
1512
1667
|
function radialGradient(paint, box) {
|
|
1513
1668
|
let { from, to, type, opacity, blendMode, stretch } = paint;
|
|
1514
|
-
from ||
|
|
1515
|
-
to ||
|
|
1516
|
-
const { x, y, width, height } = box;
|
|
1517
|
-
set$1(realFrom$1, x + from.x * width, y + from.y * height);
|
|
1518
|
-
set$1(realTo$1, x + to.x * width, y + to.y * height);
|
|
1519
|
-
let transform;
|
|
1520
|
-
if (width !== height || stretch) {
|
|
1521
|
-
transform = get$1();
|
|
1522
|
-
scaleOfOuter$1(transform, realFrom$1, width / height * (stretch || 1), 1);
|
|
1523
|
-
rotateOfOuter$1(transform, realFrom$1, getAngle$1(realFrom$1, realTo$1) + 90);
|
|
1524
|
-
}
|
|
1669
|
+
toPoint$1(from || 'center', box, realFrom$1);
|
|
1670
|
+
toPoint$1(to || 'bottom', box, realTo$1);
|
|
1525
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));
|
|
1526
1672
|
applyStops(style, paint.stops, opacity);
|
|
1527
|
-
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;
|
|
1528
1677
|
if (blendMode)
|
|
1529
1678
|
data.blendMode = blendMode;
|
|
1530
1679
|
return data;
|
|
1531
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
|
+
}
|
|
1532
1698
|
|
|
1533
|
-
const {
|
|
1534
|
-
const {
|
|
1535
|
-
const defaultFrom = { x: 0.5, y: 0.5 };
|
|
1536
|
-
const defaultTo = { x: 0.5, y: 1 };
|
|
1699
|
+
const { getDistance } = PointHelper;
|
|
1700
|
+
const { toPoint } = AroundHelper;
|
|
1537
1701
|
const realFrom = {};
|
|
1538
1702
|
const realTo = {};
|
|
1539
1703
|
function conicGradient(paint, box) {
|
|
1540
1704
|
let { from, to, type, opacity, blendMode, stretch } = paint;
|
|
1541
|
-
from ||
|
|
1542
|
-
to ||
|
|
1543
|
-
const { x, y, width, height } = box;
|
|
1544
|
-
set(realFrom, x + from.x * width, y + from.y * height);
|
|
1545
|
-
set(realTo, x + to.x * width, y + to.y * height);
|
|
1546
|
-
const transform = get();
|
|
1547
|
-
const angle = getAngle(realFrom, realTo);
|
|
1548
|
-
if (Platform.conicGradientRotate90) {
|
|
1549
|
-
scaleOfOuter(transform, realFrom, width / height * (stretch || 1), 1);
|
|
1550
|
-
rotateOfOuter(transform, realFrom, angle + 90);
|
|
1551
|
-
}
|
|
1552
|
-
else {
|
|
1553
|
-
scaleOfOuter(transform, realFrom, 1, width / height * (stretch || 1));
|
|
1554
|
-
rotateOfOuter(transform, realFrom, angle);
|
|
1555
|
-
}
|
|
1705
|
+
toPoint(from || 'center', box, realFrom);
|
|
1706
|
+
toPoint(to || 'bottom', box, realTo);
|
|
1556
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));
|
|
1557
1708
|
applyStops(style, paint.stops, opacity);
|
|
1558
|
-
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;
|
|
1559
1713
|
if (blendMode)
|
|
1560
1714
|
data.blendMode = blendMode;
|
|
1561
1715
|
return data;
|
|
1562
1716
|
}
|
|
1563
1717
|
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
if (!(paints instanceof Array))
|
|
1571
|
-
paints = [paints];
|
|
1572
|
-
recycleMap = recycleImage(attrName, data);
|
|
1573
|
-
for (let i = 0, len = paints.length; i < len; i++) {
|
|
1574
|
-
item = getLeafPaint(attrName, paints[i], ui);
|
|
1575
|
-
if (item)
|
|
1576
|
-
value.push(item);
|
|
1577
|
-
}
|
|
1578
|
-
data['_' + attrName] = value.length ? value : undefined;
|
|
1579
|
-
let isPixel;
|
|
1580
|
-
if (paints.length === 1) {
|
|
1581
|
-
const paint = paints[0];
|
|
1582
|
-
if (paint.type === 'image')
|
|
1583
|
-
isPixel = ImageManager$1.isPixel(paint);
|
|
1584
|
-
}
|
|
1585
|
-
if (attrName === 'fill') {
|
|
1586
|
-
data.__pixelFill = isPixel;
|
|
1587
|
-
}
|
|
1588
|
-
else {
|
|
1589
|
-
data.__pixelStroke = isPixel;
|
|
1590
|
-
}
|
|
1591
|
-
}
|
|
1592
|
-
function getLeafPaint(attrName, paint, ui) {
|
|
1593
|
-
if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
|
|
1594
|
-
return undefined;
|
|
1595
|
-
const { boxBounds } = ui.__layout;
|
|
1596
|
-
switch (paint.type) {
|
|
1597
|
-
case 'solid':
|
|
1598
|
-
let { type, blendMode, color, opacity } = paint;
|
|
1599
|
-
return { type, blendMode, style: ColorConvert$1.string(color, opacity) };
|
|
1600
|
-
case 'image':
|
|
1601
|
-
return image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
|
|
1602
|
-
case 'linear':
|
|
1603
|
-
return linearGradient(paint, boxBounds);
|
|
1604
|
-
case 'radial':
|
|
1605
|
-
return radialGradient(paint, boxBounds);
|
|
1606
|
-
case 'angular':
|
|
1607
|
-
return conicGradient(paint, boxBounds);
|
|
1608
|
-
default:
|
|
1609
|
-
return paint.r ? { type: 'solid', style: ColorConvert$1.string(paint) } : undefined;
|
|
1610
|
-
}
|
|
1611
|
-
}
|
|
1612
|
-
|
|
1613
|
-
var UIPaint = /*#__PURE__*/Object.freeze({
|
|
1614
|
-
__proto__: null,
|
|
1615
|
-
compute: compute,
|
|
1616
|
-
drawTextStroke: drawTextStroke,
|
|
1617
|
-
fill: fill,
|
|
1618
|
-
fillText: fillText,
|
|
1619
|
-
fills: fills,
|
|
1620
|
-
recycleImage: recycleImage,
|
|
1621
|
-
shape: shape,
|
|
1622
|
-
stroke: stroke,
|
|
1623
|
-
strokeText: strokeText,
|
|
1624
|
-
strokes: strokes
|
|
1625
|
-
});
|
|
1718
|
+
const PaintGradientModule = {
|
|
1719
|
+
linearGradient,
|
|
1720
|
+
radialGradient,
|
|
1721
|
+
conicGradient,
|
|
1722
|
+
getTransform
|
|
1723
|
+
};
|
|
1626
1724
|
|
|
1627
1725
|
const { copy, toOffsetOutBounds: toOffsetOutBounds$1 } = BoundsHelper;
|
|
1628
1726
|
const tempBounds = {};
|
|
1629
1727
|
const offsetOutBounds$1 = {};
|
|
1630
|
-
function shadow(ui, current, shape
|
|
1728
|
+
function shadow(ui, current, shape) {
|
|
1631
1729
|
let copyBounds, spreadScale;
|
|
1632
|
-
const {
|
|
1730
|
+
const { __nowWorld: nowWorld, __layout } = ui;
|
|
1633
1731
|
const { shadow } = ui.__;
|
|
1634
1732
|
const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
|
|
1635
1733
|
const other = current.getSameCanvas();
|
|
@@ -1644,21 +1742,21 @@ function shadow(ui, current, shape, renderOptions) {
|
|
|
1644
1742
|
other.restore();
|
|
1645
1743
|
other.save();
|
|
1646
1744
|
if (worldCanvas) {
|
|
1647
|
-
other.copyWorld(other, bounds,
|
|
1648
|
-
copyBounds =
|
|
1745
|
+
other.copyWorld(other, bounds, nowWorld, 'copy');
|
|
1746
|
+
copyBounds = nowWorld;
|
|
1649
1747
|
}
|
|
1650
|
-
worldCanvas ? other.copyWorld(worldCanvas,
|
|
1748
|
+
worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
|
|
1651
1749
|
}
|
|
1652
|
-
if (ui.__worldFlipped
|
|
1653
|
-
current.copyWorldByReset(other, copyBounds,
|
|
1750
|
+
if (ui.__worldFlipped) {
|
|
1751
|
+
current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
|
|
1654
1752
|
}
|
|
1655
1753
|
else {
|
|
1656
1754
|
current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
|
|
1657
1755
|
}
|
|
1658
1756
|
if (end && index < end)
|
|
1659
|
-
other.
|
|
1757
|
+
other.clearWorld(copyBounds, true);
|
|
1660
1758
|
});
|
|
1661
|
-
other.recycle();
|
|
1759
|
+
other.recycle(copyBounds);
|
|
1662
1760
|
}
|
|
1663
1761
|
function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
|
|
1664
1762
|
const { bounds, shapeBounds } = shape;
|
|
@@ -1689,9 +1787,9 @@ function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
|
|
|
1689
1787
|
|
|
1690
1788
|
const { toOffsetOutBounds } = BoundsHelper;
|
|
1691
1789
|
const offsetOutBounds = {};
|
|
1692
|
-
function innerShadow(ui, current, shape
|
|
1790
|
+
function innerShadow(ui, current, shape) {
|
|
1693
1791
|
let copyBounds, spreadScale;
|
|
1694
|
-
const {
|
|
1792
|
+
const { __nowWorld: nowWorld, __layout: __layout } = ui;
|
|
1695
1793
|
const { innerShadow } = ui.__;
|
|
1696
1794
|
const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
|
|
1697
1795
|
const other = current.getSameCanvas();
|
|
@@ -1704,40 +1802,115 @@ function innerShadow(ui, current, shape, renderOptions) {
|
|
|
1704
1802
|
drawWorldShadow(other, offsetOutBounds, spreadScale, shape);
|
|
1705
1803
|
other.restore();
|
|
1706
1804
|
if (worldCanvas) {
|
|
1707
|
-
other.copyWorld(other, bounds,
|
|
1708
|
-
other.copyWorld(worldCanvas,
|
|
1709
|
-
copyBounds =
|
|
1805
|
+
other.copyWorld(other, bounds, nowWorld, 'copy');
|
|
1806
|
+
other.copyWorld(worldCanvas, nowWorld, nowWorld, 'source-out');
|
|
1807
|
+
copyBounds = nowWorld;
|
|
1710
1808
|
}
|
|
1711
1809
|
else {
|
|
1712
1810
|
other.copyWorld(shape.canvas, shapeBounds, bounds, 'source-out');
|
|
1713
1811
|
copyBounds = bounds;
|
|
1714
1812
|
}
|
|
1715
1813
|
other.fillWorld(copyBounds, item.color, 'source-in');
|
|
1716
|
-
if (ui.__worldFlipped
|
|
1717
|
-
current.copyWorldByReset(other, copyBounds,
|
|
1814
|
+
if (ui.__worldFlipped) {
|
|
1815
|
+
current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
|
|
1718
1816
|
}
|
|
1719
1817
|
else {
|
|
1720
1818
|
current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
|
|
1721
1819
|
}
|
|
1722
1820
|
if (end && index < end)
|
|
1723
|
-
other.
|
|
1821
|
+
other.clearWorld(copyBounds, true);
|
|
1724
1822
|
});
|
|
1725
|
-
other.recycle();
|
|
1823
|
+
other.recycle(copyBounds);
|
|
1726
1824
|
}
|
|
1727
1825
|
|
|
1728
1826
|
function blur(ui, current, origin) {
|
|
1729
1827
|
const { blur } = ui.__;
|
|
1730
|
-
origin.setWorldBlur(blur * ui.
|
|
1731
|
-
origin.copyWorldToInner(current, ui.
|
|
1828
|
+
origin.setWorldBlur(blur * ui.__nowWorld.a);
|
|
1829
|
+
origin.copyWorldToInner(current, ui.__nowWorld, ui.__layout.renderBounds);
|
|
1732
1830
|
origin.filter = 'none';
|
|
1733
1831
|
}
|
|
1734
1832
|
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
shadow
|
|
1740
|
-
|
|
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
|
+
}
|
|
1741
1914
|
|
|
1742
1915
|
const money = '¥¥$€££¢¢';
|
|
1743
1916
|
const letter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
|
|
@@ -1894,7 +2067,8 @@ function createRows(drawData, content, style) {
|
|
|
1894
2067
|
if (breakAll) {
|
|
1895
2068
|
if (wordWidth)
|
|
1896
2069
|
addWord();
|
|
1897
|
-
|
|
2070
|
+
if (rowWidth)
|
|
2071
|
+
addRow();
|
|
1898
2072
|
}
|
|
1899
2073
|
else {
|
|
1900
2074
|
if (!afterBreak)
|
|
@@ -1902,10 +2076,12 @@ function createRows(drawData, content, style) {
|
|
|
1902
2076
|
if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
|
|
1903
2077
|
if (wordWidth)
|
|
1904
2078
|
addWord();
|
|
1905
|
-
|
|
2079
|
+
if (rowWidth)
|
|
2080
|
+
addRow();
|
|
1906
2081
|
}
|
|
1907
2082
|
else {
|
|
1908
|
-
|
|
2083
|
+
if (rowWidth)
|
|
2084
|
+
addRow();
|
|
1909
2085
|
}
|
|
1910
2086
|
}
|
|
1911
2087
|
}
|
|
@@ -2000,11 +2176,11 @@ function layoutChar(drawData, style, width, _height) {
|
|
|
2000
2176
|
if (mode === WordMode) {
|
|
2001
2177
|
wordChar = { char: '', x: charX };
|
|
2002
2178
|
charX = toWordChar(word.data, charX, wordChar);
|
|
2003
|
-
if (wordChar.char !== ' ')
|
|
2179
|
+
if (row.isOverflow || wordChar.char !== ' ')
|
|
2004
2180
|
row.data.push(wordChar);
|
|
2005
2181
|
}
|
|
2006
2182
|
else {
|
|
2007
|
-
charX = toChar(word.data, charX, row.data);
|
|
2183
|
+
charX = toChar(word.data, charX, row.data, row.isOverflow);
|
|
2008
2184
|
}
|
|
2009
2185
|
if (!row.paraEnd && addWordWidth) {
|
|
2010
2186
|
charX += addWordWidth;
|
|
@@ -2031,9 +2207,9 @@ function toWordChar(data, charX, wordChar) {
|
|
|
2031
2207
|
});
|
|
2032
2208
|
return charX;
|
|
2033
2209
|
}
|
|
2034
|
-
function toChar(data, charX, rowData) {
|
|
2210
|
+
function toChar(data, charX, rowData, isOverflow) {
|
|
2035
2211
|
data.forEach(char => {
|
|
2036
|
-
if (char.char !== ' ') {
|
|
2212
|
+
if (isOverflow || char.char !== ' ') {
|
|
2037
2213
|
char.x = charX;
|
|
2038
2214
|
rowData.push(char);
|
|
2039
2215
|
}
|
|
@@ -2065,12 +2241,14 @@ function layoutText(drawData, style) {
|
|
|
2065
2241
|
for (let i = 0, len = rows.length; i < len; i++) {
|
|
2066
2242
|
row = rows[i];
|
|
2067
2243
|
row.x = x;
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
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
|
+
}
|
|
2074
2252
|
}
|
|
2075
2253
|
if (row.paraStart && paraSpacing && i > 0)
|
|
2076
2254
|
starY += paraSpacing;
|
|
@@ -2106,16 +2284,20 @@ function layoutText(drawData, style) {
|
|
|
2106
2284
|
bounds.height = realHeight;
|
|
2107
2285
|
}
|
|
2108
2286
|
|
|
2109
|
-
function clipText(drawData, style) {
|
|
2287
|
+
function clipText(drawData, style, x, width) {
|
|
2288
|
+
if (!width)
|
|
2289
|
+
return;
|
|
2110
2290
|
const { rows, overflow } = drawData;
|
|
2111
2291
|
let { textOverflow } = style;
|
|
2112
2292
|
rows.splice(overflow);
|
|
2113
|
-
if (textOverflow !== '
|
|
2114
|
-
if (textOverflow === '
|
|
2293
|
+
if (textOverflow && textOverflow !== 'show') {
|
|
2294
|
+
if (textOverflow === 'hide')
|
|
2295
|
+
textOverflow = '';
|
|
2296
|
+
else if (textOverflow === 'ellipsis')
|
|
2115
2297
|
textOverflow = '...';
|
|
2116
2298
|
let char, charRight;
|
|
2117
|
-
const ellipsisWidth = Platform.canvas.measureText(textOverflow).width;
|
|
2118
|
-
const right =
|
|
2299
|
+
const ellipsisWidth = textOverflow ? Platform.canvas.measureText(textOverflow).width : 0;
|
|
2300
|
+
const right = x + width - ellipsisWidth;
|
|
2119
2301
|
const list = style.textWrap === 'none' ? rows : [rows[overflow - 1]];
|
|
2120
2302
|
list.forEach(row => {
|
|
2121
2303
|
if (row.isOverflow && row.data) {
|
|
@@ -2162,42 +2344,40 @@ function decorationText(drawData, style) {
|
|
|
2162
2344
|
}
|
|
2163
2345
|
|
|
2164
2346
|
const { top, right, bottom, left } = Direction4;
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
if (
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
}
|
|
2200
|
-
};
|
|
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
|
+
}
|
|
2201
2381
|
function padAutoText(padding, drawData, style, width, height) {
|
|
2202
2382
|
if (!width) {
|
|
2203
2383
|
switch (style.textAlign) {
|
|
@@ -2225,67 +2405,152 @@ function offsetText(drawData, attrName, value) {
|
|
|
2225
2405
|
rows[i][attrName] += value;
|
|
2226
2406
|
}
|
|
2227
2407
|
|
|
2228
|
-
const
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2408
|
+
const TextConvertModule = {
|
|
2409
|
+
getDrawData
|
|
2410
|
+
};
|
|
2411
|
+
|
|
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
|
|
2238
2424
|
};
|
|
2239
2425
|
|
|
2240
|
-
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 = {
|
|
2241
2445
|
export(leaf, filename, options) {
|
|
2242
|
-
|
|
2446
|
+
this.running = true;
|
|
2447
|
+
const fileType = FileHelper.fileType(filename);
|
|
2448
|
+
options = FileHelper.getExportOptions(options);
|
|
2243
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
|
+
}
|
|
2244
2471
|
const { leafer } = leaf;
|
|
2245
2472
|
if (leafer) {
|
|
2473
|
+
checkLazy(leaf);
|
|
2246
2474
|
leafer.waitViewCompleted(() => __awaiter(this, void 0, void 0, function* () {
|
|
2247
|
-
let
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
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;
|
|
2254
2491
|
}
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
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);
|
|
2267
2518
|
}
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
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;
|
|
2271
2525
|
}
|
|
2272
|
-
|
|
2273
|
-
|
|
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;
|
|
2274
2532
|
}
|
|
2275
2533
|
else {
|
|
2276
|
-
|
|
2534
|
+
leaf.__render(canvas, renderOptions);
|
|
2277
2535
|
}
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
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 });
|
|
2283
2550
|
}));
|
|
2284
2551
|
}
|
|
2285
2552
|
else {
|
|
2286
|
-
|
|
2287
|
-
resolve();
|
|
2288
|
-
Export.running = false;
|
|
2553
|
+
over({ data: false });
|
|
2289
2554
|
}
|
|
2290
2555
|
}));
|
|
2291
2556
|
}
|
|
@@ -2298,11 +2563,63 @@ function addTask(task) {
|
|
|
2298
2563
|
tasker.add(() => __awaiter(this, void 0, void 0, function* () { return yield task(resolve); }), { parallel: false });
|
|
2299
2564
|
});
|
|
2300
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
|
+
};
|
|
2301
2610
|
|
|
2302
|
-
Object.assign(
|
|
2303
|
-
Object.assign(
|
|
2304
|
-
Object.assign(
|
|
2305
|
-
Object.assign(
|
|
2306
|
-
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
|
+
});
|
|
2307
2624
|
|
|
2308
2625
|
export { Layouter, LeaferCanvas, Renderer, Selector, Watcher, useCanvas };
|