@leafer-ui/node 1.0.0-rc.9 → 1.0.1
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 +1150 -845
- package/dist/node.esm.js +1151 -846
- 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, defineKey, 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
|
+
defineKey(Platform, 'devicePixelRatio', { get() { return 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
|
}
|
|
@@ -507,14 +581,14 @@ class Renderer {
|
|
|
507
581
|
if (Debug.showRepaint)
|
|
508
582
|
this.canvas.strokeWorld(bounds, 'red');
|
|
509
583
|
this.target.__render(this.canvas, options);
|
|
510
|
-
this.renderBounds = realBounds || bounds;
|
|
584
|
+
this.renderBounds = realBounds = realBounds || bounds;
|
|
511
585
|
this.renderOptions = options;
|
|
512
|
-
this.totalBounds.isEmpty() ? this.totalBounds =
|
|
586
|
+
this.totalBounds.isEmpty() ? this.totalBounds = realBounds : this.totalBounds.add(realBounds);
|
|
513
587
|
if (Debug.showHitView)
|
|
514
588
|
this.renderHitView(options);
|
|
515
589
|
if (Debug.showBoundsView)
|
|
516
590
|
this.renderBoundsView(options);
|
|
517
|
-
this.canvas.updateRender();
|
|
591
|
+
this.canvas.updateRender(realBounds);
|
|
518
592
|
}
|
|
519
593
|
renderHitView(_options) { }
|
|
520
594
|
renderBoundsView(_options) { }
|
|
@@ -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,483 +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 transform = get$4();
|
|
933
|
-
const swap = rotation && rotation !== 180;
|
|
934
|
-
const sw = box.width / (swap ? height : width);
|
|
935
|
-
const sh = box.height / (swap ? width : height);
|
|
936
|
-
const scale = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
|
|
937
|
-
const x = box.x + (box.width - width * scale) / 2;
|
|
938
|
-
const y = box.y + (box.height - height * scale) / 2;
|
|
939
|
-
translate$1(transform, x, y);
|
|
940
|
-
scaleHelper(transform, scale);
|
|
941
|
-
if (rotation)
|
|
942
|
-
rotateOfOuter$2(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
|
|
943
|
-
data.scaleX = data.scaleY = scale;
|
|
944
|
-
data.transform = transform;
|
|
945
|
-
}
|
|
946
|
-
function clipMode(data, box, x, y, scaleX, scaleY, rotation) {
|
|
947
|
-
const transform = get$4();
|
|
948
|
-
translate$1(transform, box.x, box.y);
|
|
949
|
-
if (x || y)
|
|
950
|
-
translate$1(transform, x, y);
|
|
951
|
-
if (scaleX) {
|
|
952
|
-
scaleHelper(transform, scaleX, scaleY);
|
|
953
|
-
data.scaleX = transform.a;
|
|
954
|
-
data.scaleY = transform.d;
|
|
955
|
-
}
|
|
956
|
-
if (rotation)
|
|
957
|
-
rotate(transform, rotation);
|
|
958
|
-
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());
|
|
959
980
|
}
|
|
960
|
-
function
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
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
|
+
}
|
|
974
1008
|
}
|
|
975
1009
|
}
|
|
976
|
-
origin.x = box.x;
|
|
977
|
-
origin.y = box.y;
|
|
978
|
-
if (x || y)
|
|
979
|
-
origin.x += x, origin.y += y;
|
|
980
|
-
translate$1(transform, origin.x, origin.y);
|
|
981
|
-
if (scaleX) {
|
|
982
|
-
scaleOfOuter$2(transform, origin, scaleX, scaleY);
|
|
983
|
-
data.scaleX = scaleX;
|
|
984
|
-
data.scaleY = scaleY;
|
|
985
|
-
}
|
|
986
|
-
data.transform = transform;
|
|
987
1010
|
}
|
|
988
1011
|
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
const data = leafPaint.data = { mode };
|
|
997
|
-
let x, y, scaleX, scaleY;
|
|
998
|
-
if (offset)
|
|
999
|
-
x = offset.x, y = offset.y;
|
|
1000
|
-
if (size) {
|
|
1001
|
-
scaleX = (typeof size === 'number' ? size : size.width) / width;
|
|
1002
|
-
scaleY = (typeof size === 'number' ? size : size.height) / height;
|
|
1003
|
-
}
|
|
1004
|
-
else if (scale) {
|
|
1005
|
-
scaleX = typeof scale === 'number' ? scale : scale.x;
|
|
1006
|
-
scaleY = typeof scale === 'number' ? scale : scale.y;
|
|
1007
|
-
}
|
|
1008
|
-
switch (mode) {
|
|
1009
|
-
case 'strench':
|
|
1010
|
-
if (!sameBox)
|
|
1011
|
-
width = box.width, height = box.height;
|
|
1012
|
-
if (box.x || box.y) {
|
|
1013
|
-
data.transform = get$3();
|
|
1014
|
-
translate(data.transform, box.x, box.y);
|
|
1015
|
-
}
|
|
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);
|
|
1016
1019
|
break;
|
|
1017
|
-
case '
|
|
1018
|
-
|
|
1019
|
-
clipMode(data, box, x, y, scaleX, scaleY, rotation);
|
|
1020
|
+
case 'inside':
|
|
1021
|
+
drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
|
|
1020
1022
|
break;
|
|
1021
|
-
case '
|
|
1022
|
-
|
|
1023
|
-
repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation);
|
|
1024
|
-
if (!repeat)
|
|
1025
|
-
data.repeat = 'repeat';
|
|
1023
|
+
case 'outside':
|
|
1024
|
+
drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
|
|
1026
1025
|
break;
|
|
1027
|
-
case 'fit':
|
|
1028
|
-
case 'cover':
|
|
1029
|
-
default:
|
|
1030
|
-
if (!sameBox || rotation)
|
|
1031
|
-
fillOrFitMode(data, mode, box, width, height, rotation);
|
|
1032
1026
|
}
|
|
1033
|
-
data.width = width;
|
|
1034
|
-
data.height = height;
|
|
1035
|
-
if (opacity)
|
|
1036
|
-
data.opacity = opacity;
|
|
1037
|
-
if (repeat)
|
|
1038
|
-
data.repeat = typeof repeat === 'string' ? (repeat === 'x' ? 'repeat-x' : 'repeat-y') : 'repeat';
|
|
1039
1027
|
}
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
const
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
else if (image.error) {
|
|
1054
|
-
if (firstUse) {
|
|
1055
|
-
ui.forceUpdate('surface');
|
|
1056
|
-
event.error = image.error;
|
|
1057
|
-
emit(ImageEvent.ERROR, event);
|
|
1058
|
-
}
|
|
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);
|
|
1059
1039
|
}
|
|
1060
1040
|
else {
|
|
1061
|
-
|
|
1062
|
-
emit(ImageEvent.LOAD, event);
|
|
1063
|
-
leafPaint.loadId = image.load(() => {
|
|
1064
|
-
if (!ui.destroyed) {
|
|
1065
|
-
if (hasNaturalSize(ui, attrName, image)) {
|
|
1066
|
-
createData(leafPaint, image, attrValue, box);
|
|
1067
|
-
ui.forceUpdate('surface');
|
|
1068
|
-
}
|
|
1069
|
-
emit(ImageEvent.LOADED, event);
|
|
1070
|
-
}
|
|
1071
|
-
}, (error) => {
|
|
1072
|
-
ui.forceUpdate('surface');
|
|
1073
|
-
event.error = error;
|
|
1074
|
-
emit(ImageEvent.ERROR, event);
|
|
1075
|
-
});
|
|
1076
|
-
}
|
|
1077
|
-
return leafPaint;
|
|
1078
|
-
}
|
|
1079
|
-
function hasNaturalSize(ui, attrName, image) {
|
|
1080
|
-
if (attrName === 'fill' && !ui.__.__naturalWidth) {
|
|
1081
|
-
const { __: d } = ui;
|
|
1082
|
-
d.__naturalWidth = image.width;
|
|
1083
|
-
d.__naturalHeight = image.height;
|
|
1084
|
-
if (!d.__getInput('width') || !d.__getInput('height')) {
|
|
1085
|
-
ui.forceUpdate('width');
|
|
1086
|
-
if (ui.__proxyData) {
|
|
1087
|
-
ui.setProxyAttr('width', ui.__.width);
|
|
1088
|
-
ui.setProxyAttr('height', ui.__.height);
|
|
1089
|
-
}
|
|
1090
|
-
return false;
|
|
1091
|
-
}
|
|
1092
|
-
}
|
|
1093
|
-
return true;
|
|
1094
|
-
}
|
|
1095
|
-
function emit(type, data) {
|
|
1096
|
-
if (data.target.hasEvent(type))
|
|
1097
|
-
data.target.emitEvent(new ImageEvent(type, data));
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
const Export$1 = {};
|
|
1101
|
-
|
|
1102
|
-
const { get: get$2, scale, copy: copy$1 } = MatrixHelper;
|
|
1103
|
-
function createPattern(ui, paint, pixelRatio) {
|
|
1104
|
-
let { scaleX, scaleY } = ui.__world;
|
|
1105
|
-
const id = scaleX + '-' + scaleY;
|
|
1106
|
-
if (paint.patternId !== id && !ui.destroyed) {
|
|
1107
|
-
scaleX = Math.abs(scaleX);
|
|
1108
|
-
scaleY = Math.abs(scaleY);
|
|
1109
|
-
const { image, data } = paint;
|
|
1110
|
-
let imageScale, imageMatrix, { width, height, scaleX: sx, scaleY: sy, opacity, transform, repeat } = data;
|
|
1111
|
-
if (sx) {
|
|
1112
|
-
imageMatrix = get$2();
|
|
1113
|
-
copy$1(imageMatrix, transform);
|
|
1114
|
-
scale(imageMatrix, 1 / sx, 1 / sy);
|
|
1115
|
-
scaleX *= sx;
|
|
1116
|
-
scaleY *= sy;
|
|
1117
|
-
}
|
|
1118
|
-
scaleX *= pixelRatio;
|
|
1119
|
-
scaleY *= pixelRatio;
|
|
1120
|
-
width *= scaleX;
|
|
1121
|
-
height *= scaleY;
|
|
1122
|
-
const size = width * height;
|
|
1123
|
-
if (!repeat) {
|
|
1124
|
-
if (size > Platform.image.maxCacheSize)
|
|
1125
|
-
return false;
|
|
1126
|
-
}
|
|
1127
|
-
let maxSize = Platform.image.maxPatternSize;
|
|
1128
|
-
if (!image.isSVG) {
|
|
1129
|
-
const imageSize = image.width * image.height;
|
|
1130
|
-
if (maxSize > imageSize)
|
|
1131
|
-
maxSize = imageSize;
|
|
1132
|
-
}
|
|
1133
|
-
if (size > maxSize)
|
|
1134
|
-
imageScale = Math.sqrt(size / maxSize);
|
|
1135
|
-
if (imageScale) {
|
|
1136
|
-
scaleX /= imageScale;
|
|
1137
|
-
scaleY /= imageScale;
|
|
1138
|
-
width /= imageScale;
|
|
1139
|
-
height /= imageScale;
|
|
1140
|
-
}
|
|
1141
|
-
if (sx) {
|
|
1142
|
-
scaleX /= sx;
|
|
1143
|
-
scaleY /= sy;
|
|
1144
|
-
}
|
|
1145
|
-
if (transform || scaleX !== 1 || scaleY !== 1) {
|
|
1146
|
-
if (!imageMatrix) {
|
|
1147
|
-
imageMatrix = get$2();
|
|
1148
|
-
if (transform)
|
|
1149
|
-
copy$1(imageMatrix, transform);
|
|
1150
|
-
}
|
|
1151
|
-
scale(imageMatrix, 1 / scaleX, 1 / scaleY);
|
|
1152
|
-
}
|
|
1153
|
-
const pattern = Platform.canvas.createPattern(image.getCanvas(width < 1 ? 1 : width, height < 1 ? 1 : height, opacity), repeat || (Platform.origin.noRepeat || 'no-repeat'));
|
|
1154
|
-
try {
|
|
1155
|
-
if (paint.transform)
|
|
1156
|
-
paint.transform = null;
|
|
1157
|
-
if (imageMatrix)
|
|
1158
|
-
pattern.setTransform ? pattern.setTransform(imageMatrix) : paint.transform = imageMatrix;
|
|
1159
|
-
}
|
|
1160
|
-
catch (_a) {
|
|
1161
|
-
paint.transform = imageMatrix;
|
|
1162
|
-
}
|
|
1163
|
-
paint.style = pattern;
|
|
1164
|
-
paint.patternId = id;
|
|
1165
|
-
return true;
|
|
1166
|
-
}
|
|
1167
|
-
else {
|
|
1168
|
-
return false;
|
|
1169
|
-
}
|
|
1170
|
-
}
|
|
1171
|
-
|
|
1172
|
-
const { abs } = Math;
|
|
1173
|
-
function checkImage(ui, canvas, paint, allowPaint) {
|
|
1174
|
-
const { scaleX, scaleY } = ui.__world;
|
|
1175
|
-
if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
|
|
1176
|
-
return false;
|
|
1177
|
-
}
|
|
1178
|
-
else {
|
|
1179
|
-
const { data } = paint;
|
|
1180
|
-
if (allowPaint) {
|
|
1181
|
-
if (!data.repeat) {
|
|
1182
|
-
let { width, height } = data;
|
|
1183
|
-
width *= abs(scaleX) * canvas.pixelRatio;
|
|
1184
|
-
height *= abs(scaleY) * canvas.pixelRatio;
|
|
1185
|
-
if (data.scaleX) {
|
|
1186
|
-
width *= data.scaleX;
|
|
1187
|
-
height *= data.scaleY;
|
|
1188
|
-
}
|
|
1189
|
-
allowPaint = width * height > Platform.image.maxCacheSize;
|
|
1190
|
-
}
|
|
1191
|
-
else {
|
|
1192
|
-
allowPaint = false;
|
|
1193
|
-
}
|
|
1194
|
-
}
|
|
1195
|
-
if (allowPaint) {
|
|
1196
|
-
canvas.save();
|
|
1197
|
-
canvas.clip();
|
|
1198
|
-
if (paint.blendMode)
|
|
1199
|
-
canvas.blendMode = paint.blendMode;
|
|
1200
|
-
if (data.opacity)
|
|
1201
|
-
canvas.opacity *= data.opacity;
|
|
1202
|
-
if (data.transform)
|
|
1203
|
-
canvas.transform(data.transform);
|
|
1204
|
-
canvas.drawImage(paint.image.view, 0, 0, data.width, data.height);
|
|
1205
|
-
canvas.restore();
|
|
1206
|
-
return true;
|
|
1207
|
-
}
|
|
1208
|
-
else {
|
|
1209
|
-
if (!paint.style || Export$1.running) {
|
|
1210
|
-
createPattern(ui, paint, canvas.pixelRatio);
|
|
1211
|
-
}
|
|
1212
|
-
else {
|
|
1213
|
-
if (!paint.patternTask) {
|
|
1214
|
-
paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
|
|
1215
|
-
paint.patternTask = null;
|
|
1216
|
-
if (canvas.bounds.hit(ui.__world))
|
|
1217
|
-
createPattern(ui, paint, canvas.pixelRatio);
|
|
1218
|
-
ui.forceUpdate('surface');
|
|
1219
|
-
}), 300);
|
|
1220
|
-
}
|
|
1221
|
-
}
|
|
1222
|
-
return false;
|
|
1223
|
-
}
|
|
1041
|
+
canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
|
|
1224
1042
|
}
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
function recycleImage(attrName, data) {
|
|
1228
|
-
const paints = data['_' + attrName];
|
|
1229
|
-
if (paints instanceof Array) {
|
|
1230
|
-
let image, recycleMap, input, url;
|
|
1231
|
-
for (let i = 0, len = paints.length; i < len; i++) {
|
|
1232
|
-
image = paints[i].image;
|
|
1233
|
-
url = image && image.url;
|
|
1234
|
-
if (url) {
|
|
1235
|
-
if (!recycleMap)
|
|
1236
|
-
recycleMap = {};
|
|
1237
|
-
recycleMap[url] = true;
|
|
1238
|
-
ImageManager.recycle(image);
|
|
1239
|
-
if (image.loading) {
|
|
1240
|
-
if (!input) {
|
|
1241
|
-
input = (data.__input && data.__input[attrName]) || [];
|
|
1242
|
-
if (!(input instanceof Array))
|
|
1243
|
-
input = [input];
|
|
1244
|
-
}
|
|
1245
|
-
image.unload(paints[i].loadId, !input.some((item) => item.url === url));
|
|
1246
|
-
}
|
|
1247
|
-
}
|
|
1248
|
-
}
|
|
1249
|
-
return recycleMap;
|
|
1250
|
-
}
|
|
1251
|
-
return null;
|
|
1252
|
-
}
|
|
1253
|
-
|
|
1254
|
-
function fillText(ui, canvas) {
|
|
1255
|
-
let row;
|
|
1256
|
-
const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
|
|
1257
|
-
for (let i = 0, len = rows.length; i < len; i++) {
|
|
1258
|
-
row = rows[i];
|
|
1259
|
-
if (row.text) {
|
|
1260
|
-
canvas.fillText(row.text, row.x, row.y);
|
|
1261
|
-
}
|
|
1262
|
-
else if (row.data) {
|
|
1263
|
-
row.data.forEach(charData => {
|
|
1264
|
-
canvas.fillText(charData.char, charData.x, row.y);
|
|
1265
|
-
});
|
|
1266
|
-
}
|
|
1267
|
-
if (decorationY)
|
|
1268
|
-
canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight);
|
|
1269
|
-
}
|
|
1270
|
-
}
|
|
1271
|
-
|
|
1272
|
-
function fill(fill, ui, canvas) {
|
|
1273
|
-
canvas.fillStyle = fill;
|
|
1274
|
-
ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
|
|
1275
|
-
}
|
|
1276
|
-
function fills(fills, ui, canvas) {
|
|
1277
|
-
let item;
|
|
1278
|
-
const { windingRule, __font } = ui.__;
|
|
1279
|
-
for (let i = 0, len = fills.length; i < len; i++) {
|
|
1280
|
-
item = fills[i];
|
|
1281
|
-
if (item.image && checkImage(ui, canvas, item, !__font))
|
|
1282
|
-
continue;
|
|
1283
|
-
if (item.style) {
|
|
1284
|
-
canvas.fillStyle = item.style;
|
|
1285
|
-
if (item.transform) {
|
|
1286
|
-
canvas.save();
|
|
1287
|
-
canvas.transform(item.transform);
|
|
1288
|
-
if (item.blendMode)
|
|
1289
|
-
canvas.blendMode = item.blendMode;
|
|
1290
|
-
__font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
|
|
1291
|
-
canvas.restore();
|
|
1292
|
-
}
|
|
1293
|
-
else {
|
|
1294
|
-
if (item.blendMode) {
|
|
1295
|
-
canvas.saveBlendMode(item.blendMode);
|
|
1296
|
-
__font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
|
|
1297
|
-
canvas.restoreBlendMode();
|
|
1298
|
-
}
|
|
1299
|
-
else {
|
|
1300
|
-
__font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
|
|
1301
|
-
}
|
|
1302
|
-
}
|
|
1303
|
-
}
|
|
1304
|
-
}
|
|
1305
|
-
}
|
|
1306
|
-
|
|
1307
|
-
function strokeText(stroke, ui, canvas, renderOptions) {
|
|
1308
|
-
const { strokeAlign } = ui.__;
|
|
1309
|
-
const isStrokes = typeof stroke !== 'string';
|
|
1310
|
-
switch (strokeAlign) {
|
|
1311
|
-
case 'center':
|
|
1312
|
-
canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
|
|
1313
|
-
isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
|
|
1314
|
-
break;
|
|
1315
|
-
case 'inside':
|
|
1316
|
-
drawAlignStroke('inside', stroke, isStrokes, ui, canvas, renderOptions);
|
|
1317
|
-
break;
|
|
1318
|
-
case 'outside':
|
|
1319
|
-
drawAlignStroke('outside', stroke, isStrokes, ui, canvas, renderOptions);
|
|
1320
|
-
break;
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
function drawAlignStroke(align, stroke, isStrokes, ui, canvas, renderOptions) {
|
|
1324
|
-
const { strokeWidth, __font } = ui.__;
|
|
1325
|
-
const out = canvas.getSameCanvas(true);
|
|
1326
|
-
out.setStroke(isStrokes ? undefined : stroke, strokeWidth * 2, ui.__);
|
|
1327
|
-
out.font = __font;
|
|
1328
|
-
isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
|
|
1329
|
-
out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
|
|
1330
|
-
fillText(ui, out);
|
|
1331
|
-
out.blendMode = 'normal';
|
|
1332
|
-
if (ui.__worldFlipped || renderOptions.matrix) {
|
|
1333
|
-
canvas.copyWorldByReset(out);
|
|
1334
|
-
}
|
|
1335
|
-
else {
|
|
1336
|
-
canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds);
|
|
1337
|
-
}
|
|
1338
|
-
out.recycle();
|
|
1043
|
+
out.recycle(ui.__nowWorld);
|
|
1339
1044
|
}
|
|
1340
1045
|
function drawTextStroke(ui, canvas) {
|
|
1341
1046
|
let row;
|
|
@@ -1358,7 +1063,7 @@ function drawStrokesStyle(strokes, isText, ui, canvas) {
|
|
|
1358
1063
|
let item;
|
|
1359
1064
|
for (let i = 0, len = strokes.length; i < len; i++) {
|
|
1360
1065
|
item = strokes[i];
|
|
1361
|
-
if (item.image && checkImage(ui, canvas, item, false))
|
|
1066
|
+
if (item.image && PaintImage.checkImage(ui, canvas, item, false))
|
|
1362
1067
|
continue;
|
|
1363
1068
|
if (item.style) {
|
|
1364
1069
|
canvas.strokeStyle = item.style;
|
|
@@ -1374,138 +1079,567 @@ function drawStrokesStyle(strokes, isText, ui, canvas) {
|
|
|
1374
1079
|
}
|
|
1375
1080
|
}
|
|
1376
1081
|
|
|
1377
|
-
function stroke(stroke, ui, canvas
|
|
1082
|
+
function stroke(stroke, ui, canvas) {
|
|
1378
1083
|
const options = ui.__;
|
|
1379
|
-
const {
|
|
1380
|
-
if (!
|
|
1084
|
+
const { __strokeWidth, strokeAlign, __font } = options;
|
|
1085
|
+
if (!__strokeWidth)
|
|
1381
1086
|
return;
|
|
1382
1087
|
if (__font) {
|
|
1383
|
-
strokeText(stroke, ui, canvas
|
|
1088
|
+
strokeText(stroke, ui, canvas);
|
|
1384
1089
|
}
|
|
1385
1090
|
else {
|
|
1386
1091
|
switch (strokeAlign) {
|
|
1387
1092
|
case 'center':
|
|
1388
|
-
canvas.setStroke(stroke,
|
|
1093
|
+
canvas.setStroke(stroke, __strokeWidth, options);
|
|
1389
1094
|
canvas.stroke();
|
|
1390
1095
|
break;
|
|
1391
1096
|
case 'inside':
|
|
1392
1097
|
canvas.save();
|
|
1393
|
-
canvas.setStroke(stroke,
|
|
1098
|
+
canvas.setStroke(stroke, __strokeWidth * 2, options);
|
|
1394
1099
|
options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
|
|
1395
1100
|
canvas.stroke();
|
|
1396
1101
|
canvas.restore();
|
|
1397
1102
|
break;
|
|
1398
1103
|
case 'outside':
|
|
1399
|
-
const out = canvas.getSameCanvas(true);
|
|
1400
|
-
out.setStroke(stroke,
|
|
1104
|
+
const out = canvas.getSameCanvas(true, true);
|
|
1105
|
+
out.setStroke(stroke, __strokeWidth * 2, options);
|
|
1401
1106
|
ui.__drawRenderPath(out);
|
|
1402
1107
|
out.stroke();
|
|
1403
1108
|
options.windingRule ? out.clip(options.windingRule) : out.clip();
|
|
1404
1109
|
out.clearWorld(ui.__layout.renderBounds);
|
|
1405
|
-
if (ui.__worldFlipped
|
|
1406
|
-
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);
|
|
1407
1152
|
}
|
|
1408
1153
|
else {
|
|
1409
|
-
canvas.copyWorldToInner(out, ui.
|
|
1154
|
+
canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
|
|
1410
1155
|
}
|
|
1411
|
-
out.recycle();
|
|
1156
|
+
out.recycle(ui.__nowWorld);
|
|
1412
1157
|
break;
|
|
1413
1158
|
}
|
|
1414
1159
|
}
|
|
1415
1160
|
}
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
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 && !Export.running)) {
|
|
1545
|
+
return false;
|
|
1423
1546
|
}
|
|
1424
1547
|
else {
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
drawStrokesStyle(strokes, false, ui, canvas);
|
|
1435
|
-
canvas.restore();
|
|
1436
|
-
break;
|
|
1437
|
-
case 'outside':
|
|
1438
|
-
const { renderBounds } = ui.__layout;
|
|
1439
|
-
const out = canvas.getSameCanvas(true);
|
|
1440
|
-
ui.__drawRenderPath(out);
|
|
1441
|
-
out.setStroke(undefined, strokeWidth * 2, ui.__);
|
|
1442
|
-
drawStrokesStyle(strokes, false, ui, out);
|
|
1443
|
-
options.windingRule ? out.clip(options.windingRule) : out.clip();
|
|
1444
|
-
out.clearWorld(renderBounds);
|
|
1445
|
-
if (ui.__worldFlipped || renderOptions.matrix) {
|
|
1446
|
-
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;
|
|
1447
1557
|
}
|
|
1448
|
-
|
|
1449
|
-
|
|
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);
|
|
1450
1589
|
}
|
|
1451
|
-
|
|
1452
|
-
|
|
1590
|
+
}
|
|
1591
|
+
return false;
|
|
1453
1592
|
}
|
|
1454
1593
|
}
|
|
1455
1594
|
}
|
|
1456
1595
|
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
shapeBounds = getOuterOf(__world, matrix);
|
|
1479
|
-
bounds = getByMove(shapeBounds, -matrix.e, -matrix.f);
|
|
1480
|
-
if (options.matrix)
|
|
1481
|
-
matrix.multiply(options.matrix);
|
|
1482
|
-
options = Object.assign(Object.assign({}, options), { matrix });
|
|
1483
|
-
}
|
|
1484
|
-
else {
|
|
1485
|
-
if (options.matrix) {
|
|
1486
|
-
scaleX *= options.matrix.a;
|
|
1487
|
-
scaleY *= options.matrix.d;
|
|
1488
|
-
bounds = shapeBounds = getOuterOf(__world, options.matrix);
|
|
1489
|
-
}
|
|
1490
|
-
else {
|
|
1491
|
-
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
|
+
}
|
|
1492
1617
|
}
|
|
1493
|
-
|
|
1618
|
+
return recycleMap;
|
|
1494
1619
|
}
|
|
1495
|
-
|
|
1496
|
-
return {
|
|
1497
|
-
canvas, matrix, bounds,
|
|
1498
|
-
worldCanvas, shapeBounds, scaleX, scaleY
|
|
1499
|
-
};
|
|
1620
|
+
return null;
|
|
1500
1621
|
}
|
|
1501
1622
|
|
|
1502
|
-
const
|
|
1503
|
-
|
|
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 = {};
|
|
1504
1638
|
function linearGradient(paint, box) {
|
|
1505
1639
|
let { from, to, type, blendMode, opacity } = paint;
|
|
1506
|
-
from ||
|
|
1507
|
-
to ||
|
|
1508
|
-
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);
|
|
1509
1643
|
applyStops(style, paint.stops, opacity);
|
|
1510
1644
|
const data = { type, style };
|
|
1511
1645
|
if (blendMode)
|
|
@@ -1516,137 +1650,84 @@ function applyStops(gradient, stops, opacity) {
|
|
|
1516
1650
|
let stop;
|
|
1517
1651
|
for (let i = 0, len = stops.length; i < len; i++) {
|
|
1518
1652
|
stop = stops[i];
|
|
1519
|
-
|
|
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
|
+
}
|
|
1520
1659
|
}
|
|
1521
1660
|
}
|
|
1522
1661
|
|
|
1523
|
-
const {
|
|
1524
|
-
const { get
|
|
1525
|
-
const
|
|
1526
|
-
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;
|
|
1527
1665
|
const realFrom$1 = {};
|
|
1528
1666
|
const realTo$1 = {};
|
|
1529
1667
|
function radialGradient(paint, box) {
|
|
1530
1668
|
let { from, to, type, opacity, blendMode, stretch } = paint;
|
|
1531
|
-
from ||
|
|
1532
|
-
to ||
|
|
1533
|
-
const { x, y, width, height } = box;
|
|
1534
|
-
set$1(realFrom$1, x + from.x * width, y + from.y * height);
|
|
1535
|
-
set$1(realTo$1, x + to.x * width, y + to.y * height);
|
|
1536
|
-
let transform;
|
|
1537
|
-
if (width !== height || stretch) {
|
|
1538
|
-
transform = get$1();
|
|
1539
|
-
scaleOfOuter$1(transform, realFrom$1, width / height * (stretch || 1), 1);
|
|
1540
|
-
rotateOfOuter$1(transform, realFrom$1, getAngle$1(realFrom$1, realTo$1) + 90);
|
|
1541
|
-
}
|
|
1669
|
+
toPoint$1(from || 'center', box, realFrom$1);
|
|
1670
|
+
toPoint$1(to || 'bottom', box, realTo$1);
|
|
1542
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));
|
|
1543
1672
|
applyStops(style, paint.stops, opacity);
|
|
1544
|
-
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;
|
|
1545
1677
|
if (blendMode)
|
|
1546
1678
|
data.blendMode = blendMode;
|
|
1547
1679
|
return data;
|
|
1548
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
|
+
}
|
|
1549
1698
|
|
|
1550
|
-
const {
|
|
1551
|
-
const {
|
|
1552
|
-
const defaultFrom = { x: 0.5, y: 0.5 };
|
|
1553
|
-
const defaultTo = { x: 0.5, y: 1 };
|
|
1699
|
+
const { getDistance } = PointHelper;
|
|
1700
|
+
const { toPoint } = AroundHelper;
|
|
1554
1701
|
const realFrom = {};
|
|
1555
1702
|
const realTo = {};
|
|
1556
1703
|
function conicGradient(paint, box) {
|
|
1557
1704
|
let { from, to, type, opacity, blendMode, stretch } = paint;
|
|
1558
|
-
from ||
|
|
1559
|
-
to ||
|
|
1560
|
-
const { x, y, width, height } = box;
|
|
1561
|
-
set(realFrom, x + from.x * width, y + from.y * height);
|
|
1562
|
-
set(realTo, x + to.x * width, y + to.y * height);
|
|
1563
|
-
const transform = get();
|
|
1564
|
-
const angle = getAngle(realFrom, realTo);
|
|
1565
|
-
if (Platform.conicGradientRotate90) {
|
|
1566
|
-
scaleOfOuter(transform, realFrom, width / height * (stretch || 1), 1);
|
|
1567
|
-
rotateOfOuter(transform, realFrom, angle + 90);
|
|
1568
|
-
}
|
|
1569
|
-
else {
|
|
1570
|
-
scaleOfOuter(transform, realFrom, 1, width / height * (stretch || 1));
|
|
1571
|
-
rotateOfOuter(transform, realFrom, angle);
|
|
1572
|
-
}
|
|
1705
|
+
toPoint(from || 'center', box, realFrom);
|
|
1706
|
+
toPoint(to || 'bottom', box, realTo);
|
|
1573
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));
|
|
1574
1708
|
applyStops(style, paint.stops, opacity);
|
|
1575
|
-
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;
|
|
1576
1713
|
if (blendMode)
|
|
1577
1714
|
data.blendMode = blendMode;
|
|
1578
1715
|
return data;
|
|
1579
1716
|
}
|
|
1580
1717
|
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
if (!(paints instanceof Array))
|
|
1588
|
-
paints = [paints];
|
|
1589
|
-
recycleMap = recycleImage(attrName, data);
|
|
1590
|
-
for (let i = 0, len = paints.length; i < len; i++) {
|
|
1591
|
-
item = getLeafPaint(attrName, paints[i], ui);
|
|
1592
|
-
if (item)
|
|
1593
|
-
value.push(item);
|
|
1594
|
-
}
|
|
1595
|
-
data['_' + attrName] = value.length ? value : undefined;
|
|
1596
|
-
let isPixel;
|
|
1597
|
-
if (paints.length === 1) {
|
|
1598
|
-
const paint = paints[0];
|
|
1599
|
-
if (paint.type === 'image')
|
|
1600
|
-
isPixel = ImageManager$1.isPixel(paint);
|
|
1601
|
-
}
|
|
1602
|
-
if (attrName === 'fill') {
|
|
1603
|
-
data.__pixelFill = isPixel;
|
|
1604
|
-
}
|
|
1605
|
-
else {
|
|
1606
|
-
data.__pixelStroke = isPixel;
|
|
1607
|
-
}
|
|
1608
|
-
}
|
|
1609
|
-
function getLeafPaint(attrName, paint, ui) {
|
|
1610
|
-
if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
|
|
1611
|
-
return undefined;
|
|
1612
|
-
const { boxBounds } = ui.__layout;
|
|
1613
|
-
switch (paint.type) {
|
|
1614
|
-
case 'solid':
|
|
1615
|
-
let { type, blendMode, color, opacity } = paint;
|
|
1616
|
-
return { type, blendMode, style: ColorConvert$1.string(color, opacity) };
|
|
1617
|
-
case 'image':
|
|
1618
|
-
return image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
|
|
1619
|
-
case 'linear':
|
|
1620
|
-
return linearGradient(paint, boxBounds);
|
|
1621
|
-
case 'radial':
|
|
1622
|
-
return radialGradient(paint, boxBounds);
|
|
1623
|
-
case 'angular':
|
|
1624
|
-
return conicGradient(paint, boxBounds);
|
|
1625
|
-
default:
|
|
1626
|
-
return paint.r ? { type: 'solid', style: ColorConvert$1.string(paint) } : undefined;
|
|
1627
|
-
}
|
|
1628
|
-
}
|
|
1629
|
-
|
|
1630
|
-
var UIPaint = /*#__PURE__*/Object.freeze({
|
|
1631
|
-
__proto__: null,
|
|
1632
|
-
compute: compute,
|
|
1633
|
-
drawTextStroke: drawTextStroke,
|
|
1634
|
-
fill: fill,
|
|
1635
|
-
fillText: fillText,
|
|
1636
|
-
fills: fills,
|
|
1637
|
-
recycleImage: recycleImage,
|
|
1638
|
-
shape: shape,
|
|
1639
|
-
stroke: stroke,
|
|
1640
|
-
strokeText: strokeText,
|
|
1641
|
-
strokes: strokes
|
|
1642
|
-
});
|
|
1718
|
+
const PaintGradientModule = {
|
|
1719
|
+
linearGradient,
|
|
1720
|
+
radialGradient,
|
|
1721
|
+
conicGradient,
|
|
1722
|
+
getTransform
|
|
1723
|
+
};
|
|
1643
1724
|
|
|
1644
1725
|
const { copy, toOffsetOutBounds: toOffsetOutBounds$1 } = BoundsHelper;
|
|
1645
1726
|
const tempBounds = {};
|
|
1646
1727
|
const offsetOutBounds$1 = {};
|
|
1647
|
-
function shadow(ui, current, shape
|
|
1728
|
+
function shadow(ui, current, shape) {
|
|
1648
1729
|
let copyBounds, spreadScale;
|
|
1649
|
-
const {
|
|
1730
|
+
const { __nowWorld: nowWorld, __layout } = ui;
|
|
1650
1731
|
const { shadow } = ui.__;
|
|
1651
1732
|
const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
|
|
1652
1733
|
const other = current.getSameCanvas();
|
|
@@ -1661,21 +1742,21 @@ function shadow(ui, current, shape, renderOptions) {
|
|
|
1661
1742
|
other.restore();
|
|
1662
1743
|
other.save();
|
|
1663
1744
|
if (worldCanvas) {
|
|
1664
|
-
other.copyWorld(other, bounds,
|
|
1665
|
-
copyBounds =
|
|
1745
|
+
other.copyWorld(other, bounds, nowWorld, 'copy');
|
|
1746
|
+
copyBounds = nowWorld;
|
|
1666
1747
|
}
|
|
1667
|
-
worldCanvas ? other.copyWorld(worldCanvas,
|
|
1748
|
+
worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
|
|
1668
1749
|
}
|
|
1669
|
-
if (ui.__worldFlipped
|
|
1670
|
-
current.copyWorldByReset(other, copyBounds,
|
|
1750
|
+
if (ui.__worldFlipped) {
|
|
1751
|
+
current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
|
|
1671
1752
|
}
|
|
1672
1753
|
else {
|
|
1673
1754
|
current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
|
|
1674
1755
|
}
|
|
1675
1756
|
if (end && index < end)
|
|
1676
|
-
other.
|
|
1757
|
+
other.clearWorld(copyBounds, true);
|
|
1677
1758
|
});
|
|
1678
|
-
other.recycle();
|
|
1759
|
+
other.recycle(copyBounds);
|
|
1679
1760
|
}
|
|
1680
1761
|
function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
|
|
1681
1762
|
const { bounds, shapeBounds } = shape;
|
|
@@ -1706,9 +1787,9 @@ function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
|
|
|
1706
1787
|
|
|
1707
1788
|
const { toOffsetOutBounds } = BoundsHelper;
|
|
1708
1789
|
const offsetOutBounds = {};
|
|
1709
|
-
function innerShadow(ui, current, shape
|
|
1790
|
+
function innerShadow(ui, current, shape) {
|
|
1710
1791
|
let copyBounds, spreadScale;
|
|
1711
|
-
const {
|
|
1792
|
+
const { __nowWorld: nowWorld, __layout: __layout } = ui;
|
|
1712
1793
|
const { innerShadow } = ui.__;
|
|
1713
1794
|
const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
|
|
1714
1795
|
const other = current.getSameCanvas();
|
|
@@ -1721,40 +1802,115 @@ function innerShadow(ui, current, shape, renderOptions) {
|
|
|
1721
1802
|
drawWorldShadow(other, offsetOutBounds, spreadScale, shape);
|
|
1722
1803
|
other.restore();
|
|
1723
1804
|
if (worldCanvas) {
|
|
1724
|
-
other.copyWorld(other, bounds,
|
|
1725
|
-
other.copyWorld(worldCanvas,
|
|
1726
|
-
copyBounds =
|
|
1805
|
+
other.copyWorld(other, bounds, nowWorld, 'copy');
|
|
1806
|
+
other.copyWorld(worldCanvas, nowWorld, nowWorld, 'source-out');
|
|
1807
|
+
copyBounds = nowWorld;
|
|
1727
1808
|
}
|
|
1728
1809
|
else {
|
|
1729
1810
|
other.copyWorld(shape.canvas, shapeBounds, bounds, 'source-out');
|
|
1730
1811
|
copyBounds = bounds;
|
|
1731
1812
|
}
|
|
1732
1813
|
other.fillWorld(copyBounds, item.color, 'source-in');
|
|
1733
|
-
if (ui.__worldFlipped
|
|
1734
|
-
current.copyWorldByReset(other, copyBounds,
|
|
1814
|
+
if (ui.__worldFlipped) {
|
|
1815
|
+
current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
|
|
1735
1816
|
}
|
|
1736
1817
|
else {
|
|
1737
1818
|
current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
|
|
1738
1819
|
}
|
|
1739
1820
|
if (end && index < end)
|
|
1740
|
-
other.
|
|
1821
|
+
other.clearWorld(copyBounds, true);
|
|
1741
1822
|
});
|
|
1742
|
-
other.recycle();
|
|
1823
|
+
other.recycle(copyBounds);
|
|
1743
1824
|
}
|
|
1744
1825
|
|
|
1745
1826
|
function blur(ui, current, origin) {
|
|
1746
1827
|
const { blur } = ui.__;
|
|
1747
|
-
origin.setWorldBlur(blur * ui.
|
|
1748
|
-
origin.copyWorldToInner(current, ui.
|
|
1828
|
+
origin.setWorldBlur(blur * ui.__nowWorld.a);
|
|
1829
|
+
origin.copyWorldToInner(current, ui.__nowWorld, ui.__layout.renderBounds);
|
|
1749
1830
|
origin.filter = 'none';
|
|
1750
1831
|
}
|
|
1751
1832
|
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
shadow
|
|
1757
|
-
|
|
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
|
+
}
|
|
1758
1914
|
|
|
1759
1915
|
const money = '¥¥$€££¢¢';
|
|
1760
1916
|
const letter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
|
|
@@ -1911,7 +2067,8 @@ function createRows(drawData, content, style) {
|
|
|
1911
2067
|
if (breakAll) {
|
|
1912
2068
|
if (wordWidth)
|
|
1913
2069
|
addWord();
|
|
1914
|
-
|
|
2070
|
+
if (rowWidth)
|
|
2071
|
+
addRow();
|
|
1915
2072
|
}
|
|
1916
2073
|
else {
|
|
1917
2074
|
if (!afterBreak)
|
|
@@ -1919,10 +2076,12 @@ function createRows(drawData, content, style) {
|
|
|
1919
2076
|
if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
|
|
1920
2077
|
if (wordWidth)
|
|
1921
2078
|
addWord();
|
|
1922
|
-
|
|
2079
|
+
if (rowWidth)
|
|
2080
|
+
addRow();
|
|
1923
2081
|
}
|
|
1924
2082
|
else {
|
|
1925
|
-
|
|
2083
|
+
if (rowWidth)
|
|
2084
|
+
addRow();
|
|
1926
2085
|
}
|
|
1927
2086
|
}
|
|
1928
2087
|
}
|
|
@@ -2017,11 +2176,11 @@ function layoutChar(drawData, style, width, _height) {
|
|
|
2017
2176
|
if (mode === WordMode) {
|
|
2018
2177
|
wordChar = { char: '', x: charX };
|
|
2019
2178
|
charX = toWordChar(word.data, charX, wordChar);
|
|
2020
|
-
if (wordChar.char !== ' ')
|
|
2179
|
+
if (row.isOverflow || wordChar.char !== ' ')
|
|
2021
2180
|
row.data.push(wordChar);
|
|
2022
2181
|
}
|
|
2023
2182
|
else {
|
|
2024
|
-
charX = toChar(word.data, charX, row.data);
|
|
2183
|
+
charX = toChar(word.data, charX, row.data, row.isOverflow);
|
|
2025
2184
|
}
|
|
2026
2185
|
if (!row.paraEnd && addWordWidth) {
|
|
2027
2186
|
charX += addWordWidth;
|
|
@@ -2048,9 +2207,9 @@ function toWordChar(data, charX, wordChar) {
|
|
|
2048
2207
|
});
|
|
2049
2208
|
return charX;
|
|
2050
2209
|
}
|
|
2051
|
-
function toChar(data, charX, rowData) {
|
|
2210
|
+
function toChar(data, charX, rowData, isOverflow) {
|
|
2052
2211
|
data.forEach(char => {
|
|
2053
|
-
if (char.char !== ' ') {
|
|
2212
|
+
if (isOverflow || char.char !== ' ') {
|
|
2054
2213
|
char.x = charX;
|
|
2055
2214
|
rowData.push(char);
|
|
2056
2215
|
}
|
|
@@ -2082,12 +2241,14 @@ function layoutText(drawData, style) {
|
|
|
2082
2241
|
for (let i = 0, len = rows.length; i < len; i++) {
|
|
2083
2242
|
row = rows[i];
|
|
2084
2243
|
row.x = x;
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
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
|
+
}
|
|
2091
2252
|
}
|
|
2092
2253
|
if (row.paraStart && paraSpacing && i > 0)
|
|
2093
2254
|
starY += paraSpacing;
|
|
@@ -2123,16 +2284,20 @@ function layoutText(drawData, style) {
|
|
|
2123
2284
|
bounds.height = realHeight;
|
|
2124
2285
|
}
|
|
2125
2286
|
|
|
2126
|
-
function clipText(drawData, style) {
|
|
2287
|
+
function clipText(drawData, style, x, width) {
|
|
2288
|
+
if (!width)
|
|
2289
|
+
return;
|
|
2127
2290
|
const { rows, overflow } = drawData;
|
|
2128
2291
|
let { textOverflow } = style;
|
|
2129
2292
|
rows.splice(overflow);
|
|
2130
|
-
if (textOverflow !== '
|
|
2131
|
-
if (textOverflow === '
|
|
2293
|
+
if (textOverflow && textOverflow !== 'show') {
|
|
2294
|
+
if (textOverflow === 'hide')
|
|
2295
|
+
textOverflow = '';
|
|
2296
|
+
else if (textOverflow === 'ellipsis')
|
|
2132
2297
|
textOverflow = '...';
|
|
2133
2298
|
let char, charRight;
|
|
2134
|
-
const ellipsisWidth = Platform.canvas.measureText(textOverflow).width;
|
|
2135
|
-
const right =
|
|
2299
|
+
const ellipsisWidth = textOverflow ? Platform.canvas.measureText(textOverflow).width : 0;
|
|
2300
|
+
const right = x + width - ellipsisWidth;
|
|
2136
2301
|
const list = style.textWrap === 'none' ? rows : [rows[overflow - 1]];
|
|
2137
2302
|
list.forEach(row => {
|
|
2138
2303
|
if (row.isOverflow && row.data) {
|
|
@@ -2179,42 +2344,40 @@ function decorationText(drawData, style) {
|
|
|
2179
2344
|
}
|
|
2180
2345
|
|
|
2181
2346
|
const { top, right, bottom, left } = Direction4;
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
if (
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
}
|
|
2217
|
-
};
|
|
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
|
+
}
|
|
2218
2381
|
function padAutoText(padding, drawData, style, width, height) {
|
|
2219
2382
|
if (!width) {
|
|
2220
2383
|
switch (style.textAlign) {
|
|
@@ -2242,67 +2405,157 @@ function offsetText(drawData, attrName, value) {
|
|
|
2242
2405
|
rows[i][attrName] += value;
|
|
2243
2406
|
}
|
|
2244
2407
|
|
|
2245
|
-
const
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
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
|
|
2255
2424
|
};
|
|
2256
2425
|
|
|
2257
|
-
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 = {
|
|
2258
2445
|
export(leaf, filename, options) {
|
|
2259
|
-
|
|
2446
|
+
this.running = true;
|
|
2447
|
+
const fileType = FileHelper.fileType(filename);
|
|
2448
|
+
options = FileHelper.getExportOptions(options);
|
|
2260
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
|
+
}
|
|
2261
2471
|
const { leafer } = leaf;
|
|
2262
2472
|
if (leafer) {
|
|
2473
|
+
checkLazy(leaf);
|
|
2263
2474
|
leafer.waitViewCompleted(() => __awaiter(this, void 0, void 0, function* () {
|
|
2264
|
-
let
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
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;
|
|
2271
2491
|
}
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
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);
|
|
2284
2518
|
}
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
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
|
+
let sliceLeaf;
|
|
2523
|
+
if (slice) {
|
|
2524
|
+
sliceLeaf = leaf;
|
|
2525
|
+
sliceLeaf.__worldOpacity = 0;
|
|
2526
|
+
leaf = leafer;
|
|
2527
|
+
renderOptions.bounds = canvas.bounds;
|
|
2288
2528
|
}
|
|
2289
|
-
|
|
2290
|
-
|
|
2529
|
+
canvas.save();
|
|
2530
|
+
if (isFrame && fill !== undefined) {
|
|
2531
|
+
const oldFill = leaf.get('fill');
|
|
2532
|
+
leaf.fill = '';
|
|
2533
|
+
leaf.__render(canvas, renderOptions);
|
|
2534
|
+
leaf.fill = oldFill;
|
|
2291
2535
|
}
|
|
2292
2536
|
else {
|
|
2293
|
-
|
|
2537
|
+
leaf.__render(canvas, renderOptions);
|
|
2294
2538
|
}
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
if (
|
|
2299
|
-
canvas
|
|
2539
|
+
canvas.restore();
|
|
2540
|
+
if (sliceLeaf)
|
|
2541
|
+
sliceLeaf.__updateWorldOpacity();
|
|
2542
|
+
if (trim) {
|
|
2543
|
+
trimBounds = getTrimBounds(canvas);
|
|
2544
|
+
const old = canvas, { width, height } = trimBounds;
|
|
2545
|
+
const config = { x: 0, y: 0, width, height, pixelRatio };
|
|
2546
|
+
canvas = Creator.canvas(config);
|
|
2547
|
+
canvas.copyWorld(old, trimBounds, config);
|
|
2548
|
+
}
|
|
2549
|
+
if (needFill)
|
|
2550
|
+
canvas.fillWorld(canvas.bounds, fill || '#FFFFFF', 'destination-over');
|
|
2551
|
+
if (onCanvas)
|
|
2552
|
+
onCanvas(canvas);
|
|
2553
|
+
const data = filename === 'canvas' ? canvas : yield canvas.export(filename, options);
|
|
2554
|
+
over({ data, width: canvas.pixelWidth, height: canvas.pixelHeight, renderBounds, trimBounds });
|
|
2300
2555
|
}));
|
|
2301
2556
|
}
|
|
2302
2557
|
else {
|
|
2303
|
-
|
|
2304
|
-
resolve();
|
|
2305
|
-
Export.running = false;
|
|
2558
|
+
over({ data: false });
|
|
2306
2559
|
}
|
|
2307
2560
|
}));
|
|
2308
2561
|
}
|
|
@@ -2315,11 +2568,63 @@ function addTask(task) {
|
|
|
2315
2568
|
tasker.add(() => __awaiter(this, void 0, void 0, function* () { return yield task(resolve); }), { parallel: false });
|
|
2316
2569
|
});
|
|
2317
2570
|
}
|
|
2571
|
+
function checkLazy(leaf) {
|
|
2572
|
+
if (leaf.__.__needComputePaint)
|
|
2573
|
+
leaf.__.__computePaint();
|
|
2574
|
+
if (leaf.isBranch)
|
|
2575
|
+
leaf.children.forEach(child => checkLazy(child));
|
|
2576
|
+
}
|
|
2577
|
+
|
|
2578
|
+
const canvas = LeaferCanvasBase.prototype;
|
|
2579
|
+
const debug = Debug.get('@leafer-ui/export');
|
|
2580
|
+
canvas.export = function (filename, options) {
|
|
2581
|
+
const { quality, blob } = FileHelper.getExportOptions(options);
|
|
2582
|
+
if (filename.includes('.')) {
|
|
2583
|
+
return this.saveAs(filename, quality);
|
|
2584
|
+
}
|
|
2585
|
+
else if (blob) {
|
|
2586
|
+
return this.toBlob(filename, quality);
|
|
2587
|
+
}
|
|
2588
|
+
else {
|
|
2589
|
+
return this.toDataURL(filename, quality);
|
|
2590
|
+
}
|
|
2591
|
+
};
|
|
2592
|
+
canvas.toBlob = function (type, quality) {
|
|
2593
|
+
return new Promise((resolve) => {
|
|
2594
|
+
Platform.origin.canvasToBolb(this.view, type, quality).then((blob) => {
|
|
2595
|
+
resolve(blob);
|
|
2596
|
+
}).catch((e) => {
|
|
2597
|
+
debug.error(e);
|
|
2598
|
+
resolve(null);
|
|
2599
|
+
});
|
|
2600
|
+
});
|
|
2601
|
+
};
|
|
2602
|
+
canvas.toDataURL = function (type, quality) {
|
|
2603
|
+
return Platform.origin.canvasToDataURL(this.view, type, quality);
|
|
2604
|
+
};
|
|
2605
|
+
canvas.saveAs = function (filename, quality) {
|
|
2606
|
+
return new Promise((resolve) => {
|
|
2607
|
+
Platform.origin.canvasSaveAs(this.view, filename, quality).then(() => {
|
|
2608
|
+
resolve(true);
|
|
2609
|
+
}).catch((e) => {
|
|
2610
|
+
debug.error(e);
|
|
2611
|
+
resolve(false);
|
|
2612
|
+
});
|
|
2613
|
+
});
|
|
2614
|
+
};
|
|
2318
2615
|
|
|
2319
|
-
Object.assign(
|
|
2320
|
-
Object.assign(
|
|
2321
|
-
Object.assign(
|
|
2322
|
-
Object.assign(
|
|
2323
|
-
Object.assign(
|
|
2616
|
+
Object.assign(TextConvert, TextConvertModule);
|
|
2617
|
+
Object.assign(ColorConvert, ColorConvertModule);
|
|
2618
|
+
Object.assign(Paint, PaintModule);
|
|
2619
|
+
Object.assign(PaintImage, PaintImageModule);
|
|
2620
|
+
Object.assign(PaintGradient, PaintGradientModule);
|
|
2621
|
+
Object.assign(Effect, EffectModule);
|
|
2622
|
+
Object.assign(Export, ExportModule);
|
|
2623
|
+
|
|
2624
|
+
Object.assign(Creator, {
|
|
2625
|
+
interaction: (target, canvas, selector, options) => { return new InteractionBase(target, canvas, selector, options); },
|
|
2626
|
+
hitCanvas: (options, manager) => new LeaferCanvas(options, manager),
|
|
2627
|
+
hitCanvasManager: () => new HitCanvasManager()
|
|
2628
|
+
});
|
|
2324
2629
|
|
|
2325
2630
|
export { Layouter, LeaferCanvas, Renderer, Selector, Watcher, useCanvas };
|