@leafer-draw/node 1.0.0-rc.10

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 ADDED
@@ -0,0 +1,2219 @@
1
+ 'use strict';
2
+
3
+ var core = require('@leafer/core');
4
+ var fs = require('fs');
5
+ var draw = require('@leafer-ui/draw');
6
+
7
+ /******************************************************************************
8
+ Copyright (c) Microsoft Corporation.
9
+
10
+ Permission to use, copy, modify, and/or distribute this software for any
11
+ purpose with or without fee is hereby granted.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
18
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19
+ PERFORMANCE OF THIS SOFTWARE.
20
+ ***************************************************************************** */
21
+ /* global Reflect, Promise, SuppressedError, Symbol */
22
+
23
+
24
+ function __awaiter(thisArg, _arguments, P, generator) {
25
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
26
+ return new (P || (P = Promise))(function (resolve, reject) {
27
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
28
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
29
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
30
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
31
+ });
32
+ }
33
+
34
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
35
+ var e = new Error(message);
36
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
37
+ };
38
+
39
+ class LeaferCanvas extends core.LeaferCanvasBase {
40
+ get allowBackgroundColor() { return true; }
41
+ init() {
42
+ this.__createView();
43
+ this.__createContext();
44
+ this.resize(this.config);
45
+ if (core.Platform.roundRectPatch) {
46
+ this.context.__proto__.roundRect = null;
47
+ core.canvasPatch(this.context.__proto__);
48
+ }
49
+ }
50
+ __createView() {
51
+ this.view = core.Platform.origin.createCanvas(1, 1);
52
+ }
53
+ updateViewSize() {
54
+ const { width, height, pixelRatio } = this;
55
+ this.view.width = Math.ceil(width * pixelRatio);
56
+ this.view.height = Math.ceil(height * pixelRatio);
57
+ this.clientBounds = this.bounds;
58
+ }
59
+ }
60
+
61
+ const { mineType, fileType } = core.FileHelper;
62
+ Object.assign(core.Creator, {
63
+ canvas: (options, manager) => new LeaferCanvas(options, manager),
64
+ image: (options) => new core.LeaferImage(options)
65
+ });
66
+ function useCanvas(canvasType, power) {
67
+ core.Platform.canvasType = canvasType;
68
+ if (!core.Platform.origin) {
69
+ if (canvasType === 'skia') {
70
+ const { Canvas, loadImage } = power;
71
+ core.Platform.origin = {
72
+ createCanvas: (width, height, format) => new Canvas(width, height, format),
73
+ canvasToDataURL: (canvas, type, quality) => canvas.toDataURLSync(type, { quality }),
74
+ canvasToBolb: (canvas, type, quality) => canvas.toBuffer(type, { quality }),
75
+ canvasSaveAs: (canvas, filename, quality) => canvas.saveAs(filename, { quality }),
76
+ loadImage
77
+ };
78
+ core.Platform.roundRectPatch = true;
79
+ }
80
+ else if (canvasType === 'napi') {
81
+ const { Canvas, loadImage } = power;
82
+ core.Platform.origin = {
83
+ createCanvas: (width, height, format) => new Canvas(width, height, format),
84
+ canvasToDataURL: (canvas, type, quality) => canvas.toDataURL(mineType(type), quality),
85
+ canvasToBolb: (canvas, type, quality) => __awaiter(this, void 0, void 0, function* () { return canvas.toBuffer(mineType(type), quality); }),
86
+ canvasSaveAs: (canvas, filename, quality) => __awaiter(this, void 0, void 0, function* () { return fs.writeFileSync(filename, canvas.toBuffer(mineType(fileType(filename)), quality)); }),
87
+ loadImage
88
+ };
89
+ }
90
+ core.Platform.ellipseToCurve = true;
91
+ core.Platform.event = {
92
+ stopDefault(_origin) { },
93
+ stopNow(_origin) { },
94
+ stop(_origin) { }
95
+ };
96
+ core.Platform.canvas = core.Creator.canvas();
97
+ }
98
+ }
99
+ core.Platform.name = 'node';
100
+ core.Platform.requestRender = function (render) { setTimeout(render); };
101
+ core.Platform.devicePixelRatio = 1;
102
+ core.Platform.conicGradientSupport = true;
103
+
104
+ class Watcher {
105
+ get childrenChanged() { return this.hasAdd || this.hasRemove || this.hasVisible; }
106
+ get updatedList() {
107
+ if (this.hasRemove) {
108
+ const updatedList = new core.LeafList();
109
+ this.__updatedList.list.forEach(item => { if (item.leafer)
110
+ updatedList.add(item); });
111
+ return updatedList;
112
+ }
113
+ else {
114
+ return this.__updatedList;
115
+ }
116
+ }
117
+ constructor(target, userConfig) {
118
+ this.totalTimes = 0;
119
+ this.config = {};
120
+ this.__updatedList = new core.LeafList();
121
+ this.target = target;
122
+ if (userConfig)
123
+ this.config = core.DataHelper.default(userConfig, this.config);
124
+ this.__listenEvents();
125
+ }
126
+ start() {
127
+ if (this.disabled)
128
+ return;
129
+ this.running = true;
130
+ }
131
+ stop() {
132
+ this.running = false;
133
+ }
134
+ disable() {
135
+ this.stop();
136
+ this.__removeListenEvents();
137
+ this.disabled = true;
138
+ }
139
+ update() {
140
+ this.changed = true;
141
+ if (this.running)
142
+ this.target.emit(core.RenderEvent.REQUEST);
143
+ }
144
+ __onAttrChange(event) {
145
+ this.__updatedList.add(event.target);
146
+ this.update();
147
+ }
148
+ __onChildEvent(event) {
149
+ if (event.type === core.ChildEvent.ADD) {
150
+ this.hasAdd = true;
151
+ this.__pushChild(event.child);
152
+ }
153
+ else {
154
+ this.hasRemove = true;
155
+ this.__updatedList.add(event.parent);
156
+ }
157
+ this.update();
158
+ }
159
+ __pushChild(child) {
160
+ this.__updatedList.add(child);
161
+ if (child.isBranch)
162
+ this.__loopChildren(child);
163
+ }
164
+ __loopChildren(parent) {
165
+ const { children } = parent;
166
+ for (let i = 0, len = children.length; i < len; i++)
167
+ this.__pushChild(children[i]);
168
+ }
169
+ __onRquestData() {
170
+ this.target.emitEvent(new core.WatchEvent(core.WatchEvent.DATA, { updatedList: this.updatedList }));
171
+ this.__updatedList = new core.LeafList();
172
+ this.totalTimes++;
173
+ this.changed = false;
174
+ this.hasVisible = false;
175
+ this.hasRemove = false;
176
+ this.hasAdd = false;
177
+ }
178
+ __listenEvents() {
179
+ const { target } = this;
180
+ this.__eventIds = [
181
+ target.on_(core.PropertyEvent.CHANGE, this.__onAttrChange, this),
182
+ target.on_([core.ChildEvent.ADD, core.ChildEvent.REMOVE], this.__onChildEvent, this),
183
+ target.on_(core.WatchEvent.REQUEST, this.__onRquestData, this)
184
+ ];
185
+ }
186
+ __removeListenEvents() {
187
+ this.target.off_(this.__eventIds);
188
+ }
189
+ destroy() {
190
+ if (this.target) {
191
+ this.stop();
192
+ this.__removeListenEvents();
193
+ this.target = null;
194
+ this.__updatedList = null;
195
+ }
196
+ }
197
+ }
198
+
199
+ const { updateAllMatrix: updateAllMatrix$1, updateBounds: updateOneBounds, updateAllWorldOpacity } = core.LeafHelper;
200
+ const { pushAllChildBranch, pushAllParent } = core.BranchHelper;
201
+ function updateMatrix(updateList, levelList) {
202
+ let layout;
203
+ updateList.list.forEach(leaf => {
204
+ layout = leaf.__layout;
205
+ if (levelList.without(leaf) && !layout.proxyZoom) {
206
+ if (layout.matrixChanged) {
207
+ updateAllMatrix$1(leaf, true);
208
+ levelList.add(leaf);
209
+ if (leaf.isBranch)
210
+ pushAllChildBranch(leaf, levelList);
211
+ pushAllParent(leaf, levelList);
212
+ }
213
+ else if (layout.boundsChanged) {
214
+ levelList.add(leaf);
215
+ if (leaf.isBranch)
216
+ leaf.__tempNumber = 0;
217
+ pushAllParent(leaf, levelList);
218
+ }
219
+ }
220
+ });
221
+ }
222
+ function updateBounds(boundsList) {
223
+ let list, branch, children;
224
+ boundsList.sort(true);
225
+ boundsList.levels.forEach(level => {
226
+ list = boundsList.levelMap[level];
227
+ for (let i = 0, len = list.length; i < len; i++) {
228
+ branch = list[i];
229
+ if (branch.isBranch && branch.__tempNumber) {
230
+ children = branch.children;
231
+ for (let j = 0, jLen = children.length; j < jLen; j++) {
232
+ if (!children[j].isBranch) {
233
+ updateOneBounds(children[j]);
234
+ }
235
+ }
236
+ }
237
+ updateOneBounds(branch);
238
+ }
239
+ });
240
+ }
241
+ function updateChange(updateList) {
242
+ updateList.list.forEach(leaf => {
243
+ if (leaf.__layout.opacityChanged)
244
+ updateAllWorldOpacity(leaf);
245
+ leaf.__updateChange();
246
+ });
247
+ }
248
+
249
+ const { worldBounds } = core.LeafBoundsHelper;
250
+ const bigBounds = { x: 0, y: 0, width: 100000, height: 100000 };
251
+ class LayoutBlockData {
252
+ constructor(list) {
253
+ this.updatedBounds = new core.Bounds();
254
+ this.beforeBounds = new core.Bounds();
255
+ this.afterBounds = new core.Bounds();
256
+ if (list instanceof Array)
257
+ list = new core.LeafList(list);
258
+ this.updatedList = list;
259
+ }
260
+ setBefore() {
261
+ this.beforeBounds.setListWithFn(this.updatedList.list, worldBounds);
262
+ }
263
+ setAfter() {
264
+ const { list } = this.updatedList;
265
+ if (list.some(leaf => leaf.noBounds)) {
266
+ this.afterBounds.set(bigBounds);
267
+ }
268
+ else {
269
+ this.afterBounds.setListWithFn(list, worldBounds);
270
+ }
271
+ this.updatedBounds.setList([this.beforeBounds, this.afterBounds]);
272
+ }
273
+ merge(data) {
274
+ this.updatedList.addList(data.updatedList.list);
275
+ this.beforeBounds.add(data.beforeBounds);
276
+ this.afterBounds.add(data.afterBounds);
277
+ this.updatedBounds.add(data.updatedBounds);
278
+ }
279
+ destroy() {
280
+ this.updatedList = null;
281
+ }
282
+ }
283
+
284
+ const { updateAllMatrix, updateAllChange } = core.LeafHelper;
285
+ const debug$1 = core.Debug.get('Layouter');
286
+ class Layouter {
287
+ constructor(target, userConfig) {
288
+ this.totalTimes = 0;
289
+ this.config = {};
290
+ this.__levelList = new core.LeafLevelList();
291
+ this.target = target;
292
+ if (userConfig)
293
+ this.config = core.DataHelper.default(userConfig, this.config);
294
+ this.__listenEvents();
295
+ }
296
+ start() {
297
+ if (this.disabled)
298
+ return;
299
+ this.running = true;
300
+ }
301
+ stop() {
302
+ this.running = false;
303
+ }
304
+ disable() {
305
+ this.stop();
306
+ this.__removeListenEvents();
307
+ this.disabled = true;
308
+ }
309
+ layout() {
310
+ if (!this.running)
311
+ return;
312
+ const { target } = this;
313
+ this.times = 0;
314
+ try {
315
+ target.emit(core.LayoutEvent.START);
316
+ this.layoutOnce();
317
+ target.emitEvent(new core.LayoutEvent(core.LayoutEvent.END, this.layoutedBlocks, this.times));
318
+ }
319
+ catch (e) {
320
+ debug$1.error(e);
321
+ }
322
+ this.layoutedBlocks = null;
323
+ }
324
+ layoutAgain() {
325
+ if (this.layouting) {
326
+ this.waitAgain = true;
327
+ }
328
+ else {
329
+ this.layoutOnce();
330
+ }
331
+ }
332
+ layoutOnce() {
333
+ if (this.layouting)
334
+ return debug$1.warn('layouting');
335
+ if (this.times > 3)
336
+ return debug$1.warn('layout max times');
337
+ this.times++;
338
+ this.totalTimes++;
339
+ this.layouting = true;
340
+ this.target.emit(core.WatchEvent.REQUEST);
341
+ if (this.totalTimes > 1) {
342
+ this.partLayout();
343
+ }
344
+ else {
345
+ this.fullLayout();
346
+ }
347
+ this.layouting = false;
348
+ if (this.waitAgain) {
349
+ this.waitAgain = false;
350
+ this.layoutOnce();
351
+ }
352
+ }
353
+ partLayout() {
354
+ var _a;
355
+ if (!((_a = this.__updatedList) === null || _a === void 0 ? void 0 : _a.length))
356
+ return;
357
+ const t = core.Run.start('PartLayout');
358
+ const { target, __updatedList: updateList } = this;
359
+ const { BEFORE, LAYOUT, AFTER } = core.LayoutEvent;
360
+ const blocks = this.getBlocks(updateList);
361
+ blocks.forEach(item => item.setBefore());
362
+ target.emitEvent(new core.LayoutEvent(BEFORE, blocks, this.times));
363
+ this.extraBlock = null;
364
+ updateList.sort();
365
+ updateMatrix(updateList, this.__levelList);
366
+ updateBounds(this.__levelList);
367
+ updateChange(updateList);
368
+ if (this.extraBlock)
369
+ blocks.push(this.extraBlock);
370
+ blocks.forEach(item => item.setAfter());
371
+ target.emitEvent(new core.LayoutEvent(LAYOUT, blocks, this.times));
372
+ target.emitEvent(new core.LayoutEvent(AFTER, blocks, this.times));
373
+ this.addBlocks(blocks);
374
+ this.__levelList.reset();
375
+ this.__updatedList = null;
376
+ core.Run.end(t);
377
+ }
378
+ fullLayout() {
379
+ const t = core.Run.start('FullLayout');
380
+ const { target } = this;
381
+ const { BEFORE, LAYOUT, AFTER } = core.LayoutEvent;
382
+ const blocks = this.getBlocks(new core.LeafList(target));
383
+ target.emitEvent(new core.LayoutEvent(BEFORE, blocks, this.times));
384
+ Layouter.fullLayout(target);
385
+ blocks.forEach(item => { item.setAfter(); });
386
+ target.emitEvent(new core.LayoutEvent(LAYOUT, blocks, this.times));
387
+ target.emitEvent(new core.LayoutEvent(AFTER, blocks, this.times));
388
+ this.addBlocks(blocks);
389
+ core.Run.end(t);
390
+ }
391
+ static fullLayout(target) {
392
+ updateAllMatrix(target, true);
393
+ if (target.isBranch) {
394
+ core.BranchHelper.updateBounds(target);
395
+ }
396
+ else {
397
+ core.LeafHelper.updateBounds(target);
398
+ }
399
+ updateAllChange(target);
400
+ }
401
+ addExtra(leaf) {
402
+ const block = this.extraBlock || (this.extraBlock = new LayoutBlockData([]));
403
+ block.updatedList.add(leaf);
404
+ block.beforeBounds.add(leaf.__world);
405
+ }
406
+ createBlock(data) {
407
+ return new LayoutBlockData(data);
408
+ }
409
+ getBlocks(list) {
410
+ return [this.createBlock(list)];
411
+ }
412
+ addBlocks(current) {
413
+ this.layoutedBlocks ? this.layoutedBlocks.push(...current) : this.layoutedBlocks = current;
414
+ }
415
+ __onReceiveWatchData(event) {
416
+ this.__updatedList = event.data.updatedList;
417
+ }
418
+ __listenEvents() {
419
+ const { target } = this;
420
+ this.__eventIds = [
421
+ target.on_(core.LayoutEvent.REQUEST, this.layout, this),
422
+ target.on_(core.LayoutEvent.AGAIN, this.layoutAgain, this),
423
+ target.on_(core.WatchEvent.DATA, this.__onReceiveWatchData, this)
424
+ ];
425
+ }
426
+ __removeListenEvents() {
427
+ this.target.off_(this.__eventIds);
428
+ }
429
+ destroy() {
430
+ if (this.target) {
431
+ this.stop();
432
+ this.__removeListenEvents();
433
+ this.target = this.config = null;
434
+ }
435
+ }
436
+ }
437
+
438
+ const debug = core.Debug.get('Renderer');
439
+ class Renderer {
440
+ get needFill() { return !!(!this.canvas.allowBackgroundColor && this.config.fill); }
441
+ constructor(target, canvas, userConfig) {
442
+ this.FPS = 60;
443
+ this.totalTimes = 0;
444
+ this.times = 0;
445
+ this.config = {
446
+ usePartRender: true,
447
+ maxFPS: 60
448
+ };
449
+ this.target = target;
450
+ this.canvas = canvas;
451
+ if (userConfig)
452
+ this.config = core.DataHelper.default(userConfig, this.config);
453
+ this.__listenEvents();
454
+ this.__requestRender();
455
+ }
456
+ start() {
457
+ this.running = true;
458
+ }
459
+ stop() {
460
+ this.running = false;
461
+ }
462
+ update() {
463
+ this.changed = true;
464
+ }
465
+ requestLayout() {
466
+ this.target.emit(core.LayoutEvent.REQUEST);
467
+ }
468
+ render(callback) {
469
+ if (!(this.running && this.canvas.view)) {
470
+ this.changed = true;
471
+ return;
472
+ }
473
+ const { target } = this;
474
+ this.times = 0;
475
+ this.totalBounds = new core.Bounds();
476
+ debug.log(target.innerName, '--->');
477
+ try {
478
+ this.emitRender(core.RenderEvent.START);
479
+ this.renderOnce(callback);
480
+ this.emitRender(core.RenderEvent.END, this.totalBounds);
481
+ core.ImageManager.clearRecycled();
482
+ }
483
+ catch (e) {
484
+ this.rendering = false;
485
+ debug.error(e);
486
+ }
487
+ debug.log('-------------|');
488
+ }
489
+ renderAgain() {
490
+ if (this.rendering) {
491
+ this.waitAgain = true;
492
+ }
493
+ else {
494
+ this.renderOnce();
495
+ }
496
+ }
497
+ renderOnce(callback) {
498
+ if (this.rendering)
499
+ return debug.warn('rendering');
500
+ if (this.times > 3)
501
+ return debug.warn('render max times');
502
+ this.times++;
503
+ this.totalTimes++;
504
+ this.rendering = true;
505
+ this.changed = false;
506
+ this.renderBounds = new core.Bounds();
507
+ this.renderOptions = {};
508
+ if (callback) {
509
+ this.emitRender(core.RenderEvent.BEFORE);
510
+ callback();
511
+ }
512
+ else {
513
+ this.requestLayout();
514
+ this.emitRender(core.RenderEvent.BEFORE);
515
+ if (this.config.usePartRender && this.totalTimes > 1) {
516
+ this.partRender();
517
+ }
518
+ else {
519
+ this.fullRender();
520
+ }
521
+ }
522
+ this.emitRender(core.RenderEvent.RENDER, this.renderBounds, this.renderOptions);
523
+ this.emitRender(core.RenderEvent.AFTER, this.renderBounds, this.renderOptions);
524
+ this.updateBlocks = null;
525
+ this.rendering = false;
526
+ if (this.waitAgain) {
527
+ this.waitAgain = false;
528
+ this.renderOnce();
529
+ }
530
+ }
531
+ partRender() {
532
+ const { canvas, updateBlocks: list } = this;
533
+ if (!list)
534
+ return debug.warn('PartRender: need update attr');
535
+ this.mergeBlocks();
536
+ list.forEach(block => { if (canvas.bounds.hit(block) && !block.isEmpty())
537
+ this.clipRender(block); });
538
+ }
539
+ clipRender(block) {
540
+ const t = core.Run.start('PartRender');
541
+ const { canvas } = this;
542
+ const bounds = block.getIntersect(canvas.bounds);
543
+ const includes = block.includes(this.target.__world);
544
+ const realBounds = new core.Bounds(bounds);
545
+ canvas.save();
546
+ if (includes && !core.Debug.showRepaint) {
547
+ canvas.clear();
548
+ }
549
+ else {
550
+ bounds.spread(1 + 1 / this.canvas.pixelRatio).ceil();
551
+ canvas.clearWorld(bounds, true);
552
+ canvas.clipWorld(bounds, true);
553
+ }
554
+ this.__render(bounds, includes, realBounds);
555
+ canvas.restore();
556
+ core.Run.end(t);
557
+ }
558
+ fullRender() {
559
+ const t = core.Run.start('FullRender');
560
+ const { canvas } = this;
561
+ canvas.save();
562
+ canvas.clear();
563
+ this.__render(canvas.bounds, true);
564
+ canvas.restore();
565
+ core.Run.end(t);
566
+ }
567
+ __render(bounds, includes, realBounds) {
568
+ const options = bounds.includes(this.target.__world) ? { includes } : { bounds, includes };
569
+ if (this.needFill)
570
+ this.canvas.fillWorld(bounds, this.config.fill);
571
+ if (core.Debug.showRepaint)
572
+ this.canvas.strokeWorld(bounds, 'red');
573
+ this.target.__render(this.canvas, options);
574
+ this.renderBounds = realBounds || bounds;
575
+ this.renderOptions = options;
576
+ this.totalBounds.isEmpty() ? this.totalBounds = this.renderBounds : this.totalBounds.add(this.renderBounds);
577
+ if (core.Debug.showHitView)
578
+ this.renderHitView(options);
579
+ if (core.Debug.showBoundsView)
580
+ this.renderBoundsView(options);
581
+ this.canvas.updateRender();
582
+ }
583
+ renderHitView(_options) { }
584
+ renderBoundsView(_options) { }
585
+ addBlock(block) {
586
+ if (!this.updateBlocks)
587
+ this.updateBlocks = [];
588
+ this.updateBlocks.push(block);
589
+ }
590
+ mergeBlocks() {
591
+ const { updateBlocks: list } = this;
592
+ if (list) {
593
+ const bounds = new core.Bounds();
594
+ bounds.setList(list);
595
+ list.length = 0;
596
+ list.push(bounds);
597
+ }
598
+ }
599
+ __requestRender() {
600
+ const startTime = Date.now();
601
+ core.Platform.requestRender(() => {
602
+ this.FPS = Math.min(60, Math.ceil(1000 / (Date.now() - startTime)));
603
+ if (this.running) {
604
+ this.target.emit(core.AnimateEvent.FRAME);
605
+ if (this.changed && this.canvas.view)
606
+ this.render();
607
+ this.target.emit(core.RenderEvent.NEXT);
608
+ }
609
+ if (this.target)
610
+ this.__requestRender();
611
+ });
612
+ }
613
+ __onResize(e) {
614
+ if (this.canvas.unreal)
615
+ return;
616
+ if (e.bigger || !e.samePixelRatio) {
617
+ const { width, height } = e.old;
618
+ const bounds = new core.Bounds(0, 0, width, height);
619
+ if (!bounds.includes(this.target.__world) || this.needFill || !e.samePixelRatio) {
620
+ this.addBlock(this.canvas.bounds);
621
+ this.target.forceUpdate('surface');
622
+ }
623
+ }
624
+ }
625
+ __onLayoutEnd(event) {
626
+ if (event.data)
627
+ event.data.map(item => {
628
+ let empty;
629
+ if (item.updatedList)
630
+ item.updatedList.list.some(leaf => {
631
+ empty = (!leaf.__world.width || !leaf.__world.height);
632
+ if (empty) {
633
+ if (!leaf.isLeafer)
634
+ debug.tip(leaf.innerName, ': empty');
635
+ empty = (!leaf.isBranch || leaf.isBranchLeaf);
636
+ }
637
+ return empty;
638
+ });
639
+ this.addBlock(empty ? this.canvas.bounds : item.updatedBounds);
640
+ });
641
+ }
642
+ emitRender(type, bounds, options) {
643
+ this.target.emitEvent(new core.RenderEvent(type, this.times, bounds, options));
644
+ }
645
+ __listenEvents() {
646
+ const { target } = this;
647
+ this.__eventIds = [
648
+ target.on_(core.RenderEvent.REQUEST, this.update, this),
649
+ target.on_(core.LayoutEvent.END, this.__onLayoutEnd, this),
650
+ target.on_(core.RenderEvent.AGAIN, this.renderAgain, this),
651
+ target.on_(core.ResizeEvent.RESIZE, this.__onResize, this)
652
+ ];
653
+ }
654
+ __removeListenEvents() {
655
+ this.target.off_(this.__eventIds);
656
+ }
657
+ destroy() {
658
+ if (this.target) {
659
+ this.stop();
660
+ this.__removeListenEvents();
661
+ this.target = null;
662
+ this.canvas = null;
663
+ this.config = null;
664
+ }
665
+ }
666
+ }
667
+
668
+ Object.assign(core.Creator, {
669
+ watcher: (target, options) => new Watcher(target, options),
670
+ layouter: (target, options) => new Layouter(target, options),
671
+ renderer: (target, canvas, options) => new Renderer(target, canvas, options),
672
+ selector: (_target, _options) => undefined,
673
+ interaction: (_target, _canvas, _selector, _options) => undefined
674
+ });
675
+ core.Platform.layout = Layouter.fullLayout;
676
+
677
+ const PaintImage = {};
678
+ const PaintGradient = {};
679
+
680
+ function fillText(ui, canvas) {
681
+ let row;
682
+ const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
683
+ for (let i = 0, len = rows.length; i < len; i++) {
684
+ row = rows[i];
685
+ if (row.text) {
686
+ canvas.fillText(row.text, row.x, row.y);
687
+ }
688
+ else if (row.data) {
689
+ row.data.forEach(charData => {
690
+ canvas.fillText(charData.char, charData.x, row.y);
691
+ });
692
+ }
693
+ if (decorationY)
694
+ canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight);
695
+ }
696
+ }
697
+
698
+ function fill(fill, ui, canvas) {
699
+ canvas.fillStyle = fill;
700
+ ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill());
701
+ }
702
+ function fills(fills, ui, canvas) {
703
+ let item;
704
+ const { windingRule, __font } = ui.__;
705
+ for (let i = 0, len = fills.length; i < len; i++) {
706
+ item = fills[i];
707
+ if (item.image && PaintImage.checkImage(ui, canvas, item, !__font))
708
+ continue;
709
+ if (item.style) {
710
+ canvas.fillStyle = item.style;
711
+ if (item.transform) {
712
+ canvas.save();
713
+ canvas.transform(item.transform);
714
+ if (item.blendMode)
715
+ canvas.blendMode = item.blendMode;
716
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
717
+ canvas.restore();
718
+ }
719
+ else {
720
+ if (item.blendMode) {
721
+ canvas.saveBlendMode(item.blendMode);
722
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
723
+ canvas.restoreBlendMode();
724
+ }
725
+ else {
726
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill());
727
+ }
728
+ }
729
+ }
730
+ }
731
+ }
732
+
733
+ function strokeText(stroke, ui, canvas) {
734
+ const { strokeAlign } = ui.__;
735
+ const isStrokes = typeof stroke !== 'string';
736
+ switch (strokeAlign) {
737
+ case 'center':
738
+ canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__);
739
+ isStrokes ? drawStrokesStyle(stroke, true, ui, canvas) : drawTextStroke(ui, canvas);
740
+ break;
741
+ case 'inside':
742
+ drawAlignStroke('inside', stroke, isStrokes, ui, canvas);
743
+ break;
744
+ case 'outside':
745
+ drawAlignStroke('outside', stroke, isStrokes, ui, canvas);
746
+ break;
747
+ }
748
+ }
749
+ function drawAlignStroke(align, stroke, isStrokes, ui, canvas) {
750
+ const { __strokeWidth, __font } = ui.__;
751
+ const out = canvas.getSameCanvas(true, true);
752
+ out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__);
753
+ out.font = __font;
754
+ isStrokes ? drawStrokesStyle(stroke, true, ui, out) : drawTextStroke(ui, out);
755
+ out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in';
756
+ fillText(ui, out);
757
+ out.blendMode = 'normal';
758
+ if (ui.__worldFlipped) {
759
+ canvas.copyWorldByReset(out, ui.__nowWorld);
760
+ }
761
+ else {
762
+ canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
763
+ }
764
+ out.recycle(ui.__nowWorld);
765
+ }
766
+ function drawTextStroke(ui, canvas) {
767
+ let row;
768
+ const { rows, decorationY, decorationHeight } = ui.__.__textDrawData;
769
+ for (let i = 0, len = rows.length; i < len; i++) {
770
+ row = rows[i];
771
+ if (row.text) {
772
+ canvas.strokeText(row.text, row.x, row.y);
773
+ }
774
+ else if (row.data) {
775
+ row.data.forEach(charData => {
776
+ canvas.strokeText(charData.char, charData.x, row.y);
777
+ });
778
+ }
779
+ if (decorationY)
780
+ canvas.strokeRect(row.x, row.y + decorationY, row.width, decorationHeight);
781
+ }
782
+ }
783
+ function drawStrokesStyle(strokes, isText, ui, canvas) {
784
+ let item;
785
+ for (let i = 0, len = strokes.length; i < len; i++) {
786
+ item = strokes[i];
787
+ if (item.image && PaintImage.checkImage(ui, canvas, item, false))
788
+ continue;
789
+ if (item.style) {
790
+ canvas.strokeStyle = item.style;
791
+ if (item.blendMode) {
792
+ canvas.saveBlendMode(item.blendMode);
793
+ isText ? drawTextStroke(ui, canvas) : canvas.stroke();
794
+ canvas.restoreBlendMode();
795
+ }
796
+ else {
797
+ isText ? drawTextStroke(ui, canvas) : canvas.stroke();
798
+ }
799
+ }
800
+ }
801
+ }
802
+
803
+ function stroke(stroke, ui, canvas) {
804
+ const options = ui.__;
805
+ const { __strokeWidth, strokeAlign, __font } = options;
806
+ if (!__strokeWidth)
807
+ return;
808
+ if (__font) {
809
+ strokeText(stroke, ui, canvas);
810
+ }
811
+ else {
812
+ switch (strokeAlign) {
813
+ case 'center':
814
+ canvas.setStroke(stroke, __strokeWidth, options);
815
+ canvas.stroke();
816
+ break;
817
+ case 'inside':
818
+ canvas.save();
819
+ canvas.setStroke(stroke, __strokeWidth * 2, options);
820
+ options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
821
+ canvas.stroke();
822
+ canvas.restore();
823
+ break;
824
+ case 'outside':
825
+ const out = canvas.getSameCanvas(true, true);
826
+ out.setStroke(stroke, __strokeWidth * 2, options);
827
+ ui.__drawRenderPath(out);
828
+ out.stroke();
829
+ options.windingRule ? out.clip(options.windingRule) : out.clip();
830
+ out.clearWorld(ui.__layout.renderBounds);
831
+ if (ui.__worldFlipped) {
832
+ canvas.copyWorldByReset(out, ui.__nowWorld);
833
+ }
834
+ else {
835
+ canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds);
836
+ }
837
+ out.recycle(ui.__nowWorld);
838
+ break;
839
+ }
840
+ }
841
+ }
842
+ function strokes(strokes, ui, canvas) {
843
+ const options = ui.__;
844
+ const { __strokeWidth, strokeAlign, __font } = options;
845
+ if (!__strokeWidth)
846
+ return;
847
+ if (__font) {
848
+ strokeText(strokes, ui, canvas);
849
+ }
850
+ else {
851
+ switch (strokeAlign) {
852
+ case 'center':
853
+ canvas.setStroke(undefined, __strokeWidth, options);
854
+ drawStrokesStyle(strokes, false, ui, canvas);
855
+ break;
856
+ case 'inside':
857
+ canvas.save();
858
+ canvas.setStroke(undefined, __strokeWidth * 2, options);
859
+ options.windingRule ? canvas.clip(options.windingRule) : canvas.clip();
860
+ drawStrokesStyle(strokes, false, ui, canvas);
861
+ canvas.restore();
862
+ break;
863
+ case 'outside':
864
+ const { renderBounds } = ui.__layout;
865
+ const out = canvas.getSameCanvas(true, true);
866
+ ui.__drawRenderPath(out);
867
+ out.setStroke(undefined, __strokeWidth * 2, options);
868
+ drawStrokesStyle(strokes, false, ui, out);
869
+ options.windingRule ? out.clip(options.windingRule) : out.clip();
870
+ out.clearWorld(renderBounds);
871
+ if (ui.__worldFlipped) {
872
+ canvas.copyWorldByReset(out, ui.__nowWorld);
873
+ }
874
+ else {
875
+ canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds);
876
+ }
877
+ out.recycle(ui.__nowWorld);
878
+ break;
879
+ }
880
+ }
881
+ }
882
+
883
+ const { getSpread, getOuterOf, getByMove, getIntersectData } = core.BoundsHelper;
884
+ function shape(ui, current, options) {
885
+ const canvas = current.getSameCanvas();
886
+ const nowWorld = ui.__nowWorld;
887
+ let bounds, fitMatrix, shapeBounds, worldCanvas;
888
+ let { scaleX, scaleY } = nowWorld;
889
+ if (scaleX < 0)
890
+ scaleX = -scaleX;
891
+ if (scaleY < 0)
892
+ scaleY = -scaleY;
893
+ if (current.bounds.includes(nowWorld)) {
894
+ worldCanvas = canvas;
895
+ bounds = shapeBounds = nowWorld;
896
+ }
897
+ else {
898
+ const { renderShapeSpread: spread } = ui.__layout;
899
+ const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, spread * scaleX, spread * scaleY) : current.bounds, nowWorld);
900
+ fitMatrix = current.bounds.getFitMatrix(worldClipBounds);
901
+ let { a: fitScaleX, d: fitScaleY } = fitMatrix;
902
+ if (fitMatrix.a < 1) {
903
+ worldCanvas = current.getSameCanvas();
904
+ ui.__renderShape(worldCanvas, options);
905
+ scaleX *= fitScaleX;
906
+ scaleY *= fitScaleY;
907
+ }
908
+ shapeBounds = getOuterOf(nowWorld, fitMatrix);
909
+ bounds = getByMove(shapeBounds, -fitMatrix.e, -fitMatrix.f);
910
+ if (options.matrix) {
911
+ const { matrix } = options;
912
+ fitMatrix.multiply(matrix);
913
+ fitScaleX *= matrix.scaleX;
914
+ fitScaleY *= matrix.scaleY;
915
+ }
916
+ options = Object.assign(Object.assign({}, options), { matrix: fitMatrix.withScale(fitScaleX, fitScaleY) });
917
+ }
918
+ ui.__renderShape(canvas, options);
919
+ return {
920
+ canvas, matrix: fitMatrix, bounds,
921
+ worldCanvas, shapeBounds, scaleX, scaleY
922
+ };
923
+ }
924
+
925
+ let recycleMap;
926
+ function compute(attrName, ui) {
927
+ const data = ui.__, leafPaints = [];
928
+ let paints = data.__input[attrName], hasOpacityPixel;
929
+ if (!(paints instanceof Array))
930
+ paints = [paints];
931
+ recycleMap = PaintImage.recycleImage(attrName, data);
932
+ for (let i = 0, len = paints.length, item; i < len; i++) {
933
+ item = getLeafPaint(attrName, paints[i], ui);
934
+ if (item)
935
+ leafPaints.push(item);
936
+ }
937
+ data['_' + attrName] = leafPaints.length ? leafPaints : undefined;
938
+ if (leafPaints.length && leafPaints[0].image)
939
+ hasOpacityPixel = leafPaints[0].image.hasOpacityPixel;
940
+ if (attrName === 'fill') {
941
+ data.__pixelFill = hasOpacityPixel;
942
+ }
943
+ else {
944
+ data.__pixelStroke = hasOpacityPixel;
945
+ }
946
+ }
947
+ function getLeafPaint(attrName, paint, ui) {
948
+ if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0)
949
+ return undefined;
950
+ const { boxBounds } = ui.__layout;
951
+ switch (paint.type) {
952
+ case 'solid':
953
+ let { type, blendMode, color, opacity } = paint;
954
+ return { type, blendMode, style: draw.ColorConvert.string(color, opacity) };
955
+ case 'image':
956
+ return PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url]);
957
+ case 'linear':
958
+ return PaintGradient.linearGradient(paint, boxBounds);
959
+ case 'radial':
960
+ return PaintGradient.radialGradient(paint, boxBounds);
961
+ case 'angular':
962
+ return PaintGradient.conicGradient(paint, boxBounds);
963
+ default:
964
+ return paint.r ? { type: 'solid', style: draw.ColorConvert.string(paint) } : undefined;
965
+ }
966
+ }
967
+
968
+ const PaintModule = {
969
+ compute,
970
+ fill,
971
+ fills,
972
+ fillText,
973
+ stroke,
974
+ strokes,
975
+ strokeText,
976
+ drawTextStroke,
977
+ shape
978
+ };
979
+
980
+ let origin = {};
981
+ const { get: get$4, rotateOfOuter: rotateOfOuter$2, translate: translate$1, scaleOfOuter: scaleOfOuter$2, scale: scaleHelper, rotate } = core.MatrixHelper;
982
+ function fillOrFitMode(data, mode, box, width, height, rotation) {
983
+ const transform = get$4();
984
+ const swap = rotation && rotation !== 180;
985
+ const sw = box.width / (swap ? height : width);
986
+ const sh = box.height / (swap ? width : height);
987
+ const scale = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh);
988
+ const x = box.x + (box.width - width * scale) / 2;
989
+ const y = box.y + (box.height - height * scale) / 2;
990
+ translate$1(transform, x, y);
991
+ scaleHelper(transform, scale);
992
+ if (rotation)
993
+ rotateOfOuter$2(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation);
994
+ data.scaleX = data.scaleY = scale;
995
+ data.transform = transform;
996
+ }
997
+ function clipMode(data, box, x, y, scaleX, scaleY, rotation) {
998
+ const transform = get$4();
999
+ translate$1(transform, box.x, box.y);
1000
+ if (x || y)
1001
+ translate$1(transform, x, y);
1002
+ if (scaleX) {
1003
+ scaleHelper(transform, scaleX, scaleY);
1004
+ data.scaleX = transform.a;
1005
+ data.scaleY = transform.d;
1006
+ }
1007
+ if (rotation)
1008
+ rotate(transform, rotation);
1009
+ data.transform = transform;
1010
+ }
1011
+ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation) {
1012
+ const transform = get$4();
1013
+ if (rotation) {
1014
+ rotate(transform, rotation);
1015
+ switch (rotation) {
1016
+ case 90:
1017
+ translate$1(transform, height, 0);
1018
+ break;
1019
+ case 180:
1020
+ translate$1(transform, width, height);
1021
+ break;
1022
+ case 270:
1023
+ translate$1(transform, 0, width);
1024
+ break;
1025
+ }
1026
+ }
1027
+ origin.x = box.x;
1028
+ origin.y = box.y;
1029
+ if (x || y)
1030
+ origin.x += x, origin.y += y;
1031
+ translate$1(transform, origin.x, origin.y);
1032
+ if (scaleX) {
1033
+ scaleOfOuter$2(transform, origin, scaleX, scaleY);
1034
+ data.scaleX = scaleX;
1035
+ data.scaleY = scaleY;
1036
+ }
1037
+ data.transform = transform;
1038
+ }
1039
+
1040
+ const { get: get$3, translate } = core.MatrixHelper;
1041
+ function createData(leafPaint, image, paint, box) {
1042
+ let { width, height } = image;
1043
+ const { opacity, mode, offset, scale, size, rotation, blendMode, repeat } = paint;
1044
+ const sameBox = box.width === width && box.height === height;
1045
+ if (blendMode)
1046
+ leafPaint.blendMode = blendMode;
1047
+ const data = leafPaint.data = { mode };
1048
+ let x, y, scaleX, scaleY;
1049
+ if (offset)
1050
+ x = offset.x, y = offset.y;
1051
+ if (size) {
1052
+ scaleX = (typeof size === 'number' ? size : size.width) / width;
1053
+ scaleY = (typeof size === 'number' ? size : size.height) / height;
1054
+ }
1055
+ else if (scale) {
1056
+ scaleX = typeof scale === 'number' ? scale : scale.x;
1057
+ scaleY = typeof scale === 'number' ? scale : scale.y;
1058
+ }
1059
+ switch (mode) {
1060
+ case 'strench':
1061
+ if (!sameBox)
1062
+ width = box.width, height = box.height;
1063
+ if (box.x || box.y) {
1064
+ data.transform = get$3();
1065
+ translate(data.transform, box.x, box.y);
1066
+ }
1067
+ break;
1068
+ case 'clip':
1069
+ if (offset || scaleX || rotation)
1070
+ clipMode(data, box, x, y, scaleX, scaleY, rotation);
1071
+ break;
1072
+ case 'repeat':
1073
+ if (!sameBox || scaleX || rotation)
1074
+ repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation);
1075
+ if (!repeat)
1076
+ data.repeat = 'repeat';
1077
+ break;
1078
+ case 'fit':
1079
+ case 'cover':
1080
+ default:
1081
+ if (!sameBox || rotation)
1082
+ fillOrFitMode(data, mode, box, width, height, rotation);
1083
+ }
1084
+ data.width = width;
1085
+ data.height = height;
1086
+ if (opacity)
1087
+ data.opacity = opacity;
1088
+ if (repeat)
1089
+ data.repeat = typeof repeat === 'string' ? (repeat === 'x' ? 'repeat-x' : 'repeat-y') : 'repeat';
1090
+ }
1091
+
1092
+ let cache, box = new core.Bounds();
1093
+ const { isSame } = core.BoundsHelper;
1094
+ function image(ui, attrName, paint, boxBounds, firstUse) {
1095
+ let leafPaint, event;
1096
+ const image = core.ImageManager.get(paint);
1097
+ if (cache && paint === cache.paint && isSame(boxBounds, cache.boxBounds)) {
1098
+ leafPaint = cache.leafPaint;
1099
+ }
1100
+ else {
1101
+ leafPaint = { type: paint.type };
1102
+ leafPaint.image = image;
1103
+ cache = image.use > 1 ? { leafPaint, paint, boxBounds: box.set(boxBounds) } : null;
1104
+ }
1105
+ if (firstUse || image.loading)
1106
+ event = { image, attrName, attrValue: paint };
1107
+ if (image.ready) {
1108
+ checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds);
1109
+ if (firstUse) {
1110
+ onLoad(ui, event);
1111
+ onLoadSuccess(ui, event);
1112
+ }
1113
+ }
1114
+ else if (image.error) {
1115
+ if (firstUse)
1116
+ onLoadError(ui, event, image.error);
1117
+ }
1118
+ else {
1119
+ if (firstUse)
1120
+ onLoad(ui, event);
1121
+ leafPaint.loadId = image.load(() => {
1122
+ if (!ui.destroyed) {
1123
+ if (checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds))
1124
+ ui.forceUpdate('surface');
1125
+ onLoadSuccess(ui, event);
1126
+ }
1127
+ leafPaint.loadId = null;
1128
+ }, (error) => {
1129
+ onLoadError(ui, event, error);
1130
+ leafPaint.loadId = null;
1131
+ });
1132
+ }
1133
+ return leafPaint;
1134
+ }
1135
+ function checkSizeAndCreateData(ui, attrName, paint, image, leafPaint, boxBounds) {
1136
+ if (attrName === 'fill' && !ui.__.__naturalWidth) {
1137
+ const data = ui.__;
1138
+ data.__naturalWidth = image.width;
1139
+ data.__naturalHeight = image.height;
1140
+ if (data.__autoWidth || data.__autoHeight) {
1141
+ ui.forceUpdate('width');
1142
+ if (ui.__proxyData) {
1143
+ ui.setProxyAttr('width', data.width);
1144
+ ui.setProxyAttr('height', data.height);
1145
+ }
1146
+ return false;
1147
+ }
1148
+ }
1149
+ if (!leafPaint.data)
1150
+ createData(leafPaint, image, paint, boxBounds);
1151
+ return true;
1152
+ }
1153
+ function onLoad(ui, event) {
1154
+ emit(ui, core.ImageEvent.LOAD, event);
1155
+ }
1156
+ function onLoadSuccess(ui, event) {
1157
+ emit(ui, core.ImageEvent.LOADED, event);
1158
+ }
1159
+ function onLoadError(ui, event, error) {
1160
+ event.error = error;
1161
+ ui.forceUpdate('surface');
1162
+ emit(ui, core.ImageEvent.ERROR, event);
1163
+ }
1164
+ function emit(ui, type, data) {
1165
+ if (ui.hasEvent(type))
1166
+ ui.emitEvent(new core.ImageEvent(type, data));
1167
+ }
1168
+
1169
+ const { get: get$2, scale, copy: copy$1 } = core.MatrixHelper;
1170
+ const { round, abs: abs$1 } = Math;
1171
+ function createPattern(ui, paint, pixelRatio) {
1172
+ let { scaleX, scaleY } = ui.__world;
1173
+ const id = scaleX + '-' + scaleY;
1174
+ if (paint.patternId !== id && !ui.destroyed) {
1175
+ scaleX = abs$1(scaleX);
1176
+ scaleY = abs$1(scaleY);
1177
+ const { image, data } = paint;
1178
+ let imageScale, imageMatrix, { width, height, scaleX: sx, scaleY: sy, opacity, transform, repeat } = data;
1179
+ if (sx) {
1180
+ imageMatrix = get$2();
1181
+ copy$1(imageMatrix, transform);
1182
+ scale(imageMatrix, 1 / sx, 1 / sy);
1183
+ scaleX *= sx;
1184
+ scaleY *= sy;
1185
+ }
1186
+ scaleX *= pixelRatio;
1187
+ scaleY *= pixelRatio;
1188
+ width *= scaleX;
1189
+ height *= scaleY;
1190
+ const size = width * height;
1191
+ if (!repeat) {
1192
+ if (size > core.Platform.image.maxCacheSize)
1193
+ return false;
1194
+ }
1195
+ let maxSize = core.Platform.image.maxPatternSize;
1196
+ if (!image.isSVG) {
1197
+ const imageSize = image.width * image.height;
1198
+ if (maxSize > imageSize)
1199
+ maxSize = imageSize;
1200
+ }
1201
+ if (size > maxSize)
1202
+ imageScale = Math.sqrt(size / maxSize);
1203
+ if (imageScale) {
1204
+ scaleX /= imageScale;
1205
+ scaleY /= imageScale;
1206
+ width /= imageScale;
1207
+ height /= imageScale;
1208
+ }
1209
+ if (sx) {
1210
+ scaleX /= sx;
1211
+ scaleY /= sy;
1212
+ }
1213
+ if (transform || scaleX !== 1 || scaleY !== 1) {
1214
+ if (!imageMatrix) {
1215
+ imageMatrix = get$2();
1216
+ if (transform)
1217
+ copy$1(imageMatrix, transform);
1218
+ }
1219
+ scale(imageMatrix, 1 / scaleX, 1 / scaleY);
1220
+ }
1221
+ const canvas = image.getCanvas(width < 1 ? 1 : round(width), height < 1 ? 1 : round(height), opacity);
1222
+ const pattern = image.getPattern(canvas, repeat || (core.Platform.origin.noRepeat || 'no-repeat'), imageMatrix, paint);
1223
+ paint.style = pattern;
1224
+ paint.patternId = id;
1225
+ return true;
1226
+ }
1227
+ else {
1228
+ return false;
1229
+ }
1230
+ }
1231
+
1232
+ const { abs } = Math;
1233
+ function checkImage(ui, canvas, paint, allowPaint) {
1234
+ const { scaleX, scaleY } = ui.__world;
1235
+ if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
1236
+ return false;
1237
+ }
1238
+ else {
1239
+ const { data } = paint;
1240
+ if (allowPaint) {
1241
+ if (!data.repeat) {
1242
+ let { width, height } = data;
1243
+ width *= abs(scaleX) * canvas.pixelRatio;
1244
+ height *= abs(scaleY) * canvas.pixelRatio;
1245
+ if (data.scaleX) {
1246
+ width *= data.scaleX;
1247
+ height *= data.scaleY;
1248
+ }
1249
+ allowPaint = width * height > core.Platform.image.maxCacheSize;
1250
+ }
1251
+ else {
1252
+ allowPaint = false;
1253
+ }
1254
+ }
1255
+ if (allowPaint) {
1256
+ canvas.save();
1257
+ canvas.clip();
1258
+ if (paint.blendMode)
1259
+ canvas.blendMode = paint.blendMode;
1260
+ if (data.opacity)
1261
+ canvas.opacity *= data.opacity;
1262
+ if (data.transform)
1263
+ canvas.transform(data.transform);
1264
+ canvas.drawImage(paint.image.view, 0, 0, data.width, data.height);
1265
+ canvas.restore();
1266
+ return true;
1267
+ }
1268
+ else {
1269
+ if (!paint.style || draw.Export.running) {
1270
+ createPattern(ui, paint, canvas.pixelRatio);
1271
+ }
1272
+ else {
1273
+ if (!paint.patternTask) {
1274
+ paint.patternTask = core.ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
1275
+ paint.patternTask = null;
1276
+ if (canvas.bounds.hit(ui.__world))
1277
+ createPattern(ui, paint, canvas.pixelRatio);
1278
+ ui.forceUpdate('surface');
1279
+ }), 300);
1280
+ }
1281
+ }
1282
+ return false;
1283
+ }
1284
+ }
1285
+ }
1286
+
1287
+ function recycleImage(attrName, data) {
1288
+ const paints = data['_' + attrName];
1289
+ if (paints instanceof Array) {
1290
+ let image, recycleMap, input, url;
1291
+ for (let i = 0, len = paints.length; i < len; i++) {
1292
+ image = paints[i].image;
1293
+ url = image && image.url;
1294
+ if (url) {
1295
+ if (!recycleMap)
1296
+ recycleMap = {};
1297
+ recycleMap[url] = true;
1298
+ core.ImageManager.recycle(image);
1299
+ if (image.loading) {
1300
+ if (!input) {
1301
+ input = (data.__input && data.__input[attrName]) || [];
1302
+ if (!(input instanceof Array))
1303
+ input = [input];
1304
+ }
1305
+ image.unload(paints[i].loadId, !input.some((item) => item.url === url));
1306
+ }
1307
+ }
1308
+ }
1309
+ return recycleMap;
1310
+ }
1311
+ return null;
1312
+ }
1313
+
1314
+ const PaintImageModule = {
1315
+ image,
1316
+ createData,
1317
+ fillOrFitMode,
1318
+ clipMode,
1319
+ repeatMode,
1320
+ createPattern,
1321
+ checkImage,
1322
+ recycleImage
1323
+ };
1324
+
1325
+ const defaultFrom$2 = { x: 0.5, y: 0 };
1326
+ const defaultTo$2 = { x: 0.5, y: 1 };
1327
+ function linearGradient(paint, box) {
1328
+ let { from, to, type, blendMode, opacity } = paint;
1329
+ from || (from = defaultFrom$2);
1330
+ to || (to = defaultTo$2);
1331
+ const style = core.Platform.canvas.createLinearGradient(box.x + from.x * box.width, box.y + from.y * box.height, box.x + to.x * box.width, box.y + to.y * box.height);
1332
+ applyStops(style, paint.stops, opacity);
1333
+ const data = { type, style };
1334
+ if (blendMode)
1335
+ data.blendMode = blendMode;
1336
+ return data;
1337
+ }
1338
+ function applyStops(gradient, stops, opacity) {
1339
+ let stop;
1340
+ for (let i = 0, len = stops.length; i < len; i++) {
1341
+ stop = stops[i];
1342
+ gradient.addColorStop(stop.offset, draw.ColorConvert.string(stop.color, opacity));
1343
+ }
1344
+ }
1345
+
1346
+ const { set: set$1, getAngle: getAngle$1, getDistance: getDistance$1 } = core.PointHelper;
1347
+ const { get: get$1, rotateOfOuter: rotateOfOuter$1, scaleOfOuter: scaleOfOuter$1 } = core.MatrixHelper;
1348
+ const defaultFrom$1 = { x: 0.5, y: 0.5 };
1349
+ const defaultTo$1 = { x: 0.5, y: 1 };
1350
+ const realFrom$1 = {};
1351
+ const realTo$1 = {};
1352
+ function radialGradient(paint, box) {
1353
+ let { from, to, type, opacity, blendMode, stretch } = paint;
1354
+ from || (from = defaultFrom$1);
1355
+ to || (to = defaultTo$1);
1356
+ const { x, y, width, height } = box;
1357
+ set$1(realFrom$1, x + from.x * width, y + from.y * height);
1358
+ set$1(realTo$1, x + to.x * width, y + to.y * height);
1359
+ let transform;
1360
+ if (width !== height || stretch) {
1361
+ transform = get$1();
1362
+ scaleOfOuter$1(transform, realFrom$1, width / height * (stretch || 1), 1);
1363
+ rotateOfOuter$1(transform, realFrom$1, getAngle$1(realFrom$1, realTo$1) + 90);
1364
+ }
1365
+ const style = core.Platform.canvas.createRadialGradient(realFrom$1.x, realFrom$1.y, 0, realFrom$1.x, realFrom$1.y, getDistance$1(realFrom$1, realTo$1));
1366
+ applyStops(style, paint.stops, opacity);
1367
+ const data = { type, style, transform };
1368
+ if (blendMode)
1369
+ data.blendMode = blendMode;
1370
+ return data;
1371
+ }
1372
+
1373
+ const { set, getAngle, getDistance } = core.PointHelper;
1374
+ const { get, rotateOfOuter, scaleOfOuter } = core.MatrixHelper;
1375
+ const defaultFrom = { x: 0.5, y: 0.5 };
1376
+ const defaultTo = { x: 0.5, y: 1 };
1377
+ const realFrom = {};
1378
+ const realTo = {};
1379
+ function conicGradient(paint, box) {
1380
+ let { from, to, type, opacity, blendMode, stretch } = paint;
1381
+ from || (from = defaultFrom);
1382
+ to || (to = defaultTo);
1383
+ const { x, y, width, height } = box;
1384
+ set(realFrom, x + from.x * width, y + from.y * height);
1385
+ set(realTo, x + to.x * width, y + to.y * height);
1386
+ const transform = get();
1387
+ const angle = getAngle(realFrom, realTo);
1388
+ if (core.Platform.conicGradientRotate90) {
1389
+ scaleOfOuter(transform, realFrom, width / height * (stretch || 1), 1);
1390
+ rotateOfOuter(transform, realFrom, angle + 90);
1391
+ }
1392
+ else {
1393
+ scaleOfOuter(transform, realFrom, 1, width / height * (stretch || 1));
1394
+ rotateOfOuter(transform, realFrom, angle);
1395
+ }
1396
+ const style = core.Platform.conicGradientSupport ? core.Platform.canvas.createConicGradient(0, realFrom.x, realFrom.y) : core.Platform.canvas.createRadialGradient(realFrom.x, realFrom.y, 0, realFrom.x, realFrom.y, getDistance(realFrom, realTo));
1397
+ applyStops(style, paint.stops, opacity);
1398
+ const data = { type, style, transform };
1399
+ if (blendMode)
1400
+ data.blendMode = blendMode;
1401
+ return data;
1402
+ }
1403
+
1404
+ const PaintGradientModule = {
1405
+ linearGradient,
1406
+ radialGradient,
1407
+ conicGradient
1408
+ };
1409
+
1410
+ const { copy, toOffsetOutBounds: toOffsetOutBounds$1 } = core.BoundsHelper;
1411
+ const tempBounds = {};
1412
+ const offsetOutBounds$1 = {};
1413
+ function shadow(ui, current, shape) {
1414
+ let copyBounds, spreadScale;
1415
+ const { __nowWorld: nowWorld, __layout } = ui;
1416
+ const { shadow } = ui.__;
1417
+ const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
1418
+ const other = current.getSameCanvas();
1419
+ const end = shadow.length - 1;
1420
+ toOffsetOutBounds$1(bounds, offsetOutBounds$1);
1421
+ shadow.forEach((item, index) => {
1422
+ other.setWorldShadow((offsetOutBounds$1.offsetX + item.x * scaleX), (offsetOutBounds$1.offsetY + item.y * scaleY), item.blur * scaleX, item.color);
1423
+ spreadScale = item.spread ? 1 + item.spread * 2 / (__layout.boxBounds.width + (__layout.strokeBoxSpread || 0) * 2) : 0;
1424
+ drawWorldShadow(other, offsetOutBounds$1, spreadScale, shape);
1425
+ copyBounds = bounds;
1426
+ if (item.box) {
1427
+ other.restore();
1428
+ other.save();
1429
+ if (worldCanvas) {
1430
+ other.copyWorld(other, bounds, nowWorld, 'copy');
1431
+ copyBounds = nowWorld;
1432
+ }
1433
+ worldCanvas ? other.copyWorld(worldCanvas, nowWorld, nowWorld, 'destination-out') : other.copyWorld(shape.canvas, shapeBounds, bounds, 'destination-out');
1434
+ }
1435
+ if (ui.__worldFlipped) {
1436
+ current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1437
+ }
1438
+ else {
1439
+ current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1440
+ }
1441
+ if (end && index < end)
1442
+ other.clearWorld(copyBounds, true);
1443
+ });
1444
+ other.recycle(copyBounds);
1445
+ }
1446
+ function drawWorldShadow(canvas, outBounds, spreadScale, shape) {
1447
+ const { bounds, shapeBounds } = shape;
1448
+ if (core.Platform.fullImageShadow) {
1449
+ copy(tempBounds, canvas.bounds);
1450
+ tempBounds.x += (outBounds.x - shapeBounds.x);
1451
+ tempBounds.y += (outBounds.y - shapeBounds.y);
1452
+ if (spreadScale) {
1453
+ const { matrix } = shape;
1454
+ tempBounds.x -= (bounds.x + (matrix ? matrix.e : 0) + bounds.width / 2) * (spreadScale - 1);
1455
+ tempBounds.y -= (bounds.y + (matrix ? matrix.f : 0) + bounds.height / 2) * (spreadScale - 1);
1456
+ tempBounds.width *= spreadScale;
1457
+ tempBounds.height *= spreadScale;
1458
+ }
1459
+ canvas.copyWorld(shape.canvas, canvas.bounds, tempBounds);
1460
+ }
1461
+ else {
1462
+ if (spreadScale) {
1463
+ copy(tempBounds, outBounds);
1464
+ tempBounds.x -= (outBounds.width / 2) * (spreadScale - 1);
1465
+ tempBounds.y -= (outBounds.height / 2) * (spreadScale - 1);
1466
+ tempBounds.width *= spreadScale;
1467
+ tempBounds.height *= spreadScale;
1468
+ }
1469
+ canvas.copyWorld(shape.canvas, shapeBounds, spreadScale ? tempBounds : outBounds);
1470
+ }
1471
+ }
1472
+
1473
+ const { toOffsetOutBounds } = core.BoundsHelper;
1474
+ const offsetOutBounds = {};
1475
+ function innerShadow(ui, current, shape) {
1476
+ let copyBounds, spreadScale;
1477
+ const { __nowWorld: nowWorld, __layout: __layout } = ui;
1478
+ const { innerShadow } = ui.__;
1479
+ const { worldCanvas, bounds, shapeBounds, scaleX, scaleY } = shape;
1480
+ const other = current.getSameCanvas();
1481
+ const end = innerShadow.length - 1;
1482
+ toOffsetOutBounds(bounds, offsetOutBounds);
1483
+ innerShadow.forEach((item, index) => {
1484
+ other.save();
1485
+ other.setWorldShadow((offsetOutBounds.offsetX + item.x * scaleX), (offsetOutBounds.offsetY + item.y * scaleY), item.blur * scaleX);
1486
+ spreadScale = item.spread ? 1 - item.spread * 2 / (__layout.boxBounds.width + (__layout.strokeBoxSpread || 0) * 2) : 0;
1487
+ drawWorldShadow(other, offsetOutBounds, spreadScale, shape);
1488
+ other.restore();
1489
+ if (worldCanvas) {
1490
+ other.copyWorld(other, bounds, nowWorld, 'copy');
1491
+ other.copyWorld(worldCanvas, nowWorld, nowWorld, 'source-out');
1492
+ copyBounds = nowWorld;
1493
+ }
1494
+ else {
1495
+ other.copyWorld(shape.canvas, shapeBounds, bounds, 'source-out');
1496
+ copyBounds = bounds;
1497
+ }
1498
+ other.fillWorld(copyBounds, item.color, 'source-in');
1499
+ if (ui.__worldFlipped) {
1500
+ current.copyWorldByReset(other, copyBounds, nowWorld, item.blendMode);
1501
+ }
1502
+ else {
1503
+ current.copyWorldToInner(other, copyBounds, __layout.renderBounds, item.blendMode);
1504
+ }
1505
+ if (end && index < end)
1506
+ other.clearWorld(copyBounds, true);
1507
+ });
1508
+ other.recycle(copyBounds);
1509
+ }
1510
+
1511
+ function blur(ui, current, origin) {
1512
+ const { blur } = ui.__;
1513
+ origin.setWorldBlur(blur * ui.__world.a);
1514
+ origin.copyWorldToInner(current, ui.__world, ui.__layout.renderBounds);
1515
+ origin.filter = 'none';
1516
+ }
1517
+
1518
+ function backgroundBlur(_ui, _current, _shape) {
1519
+ }
1520
+
1521
+ const EffectModule = {
1522
+ shadow,
1523
+ innerShadow,
1524
+ blur,
1525
+ backgroundBlur
1526
+ };
1527
+
1528
+ const { excludeRenderBounds } = core.LeafBoundsHelper;
1529
+ draw.Group.prototype.__renderMask = function (canvas, options) {
1530
+ let child, maskCanvas, contentCanvas, maskOpacity, currentMask;
1531
+ const { children } = this;
1532
+ for (let i = 0, len = children.length; i < len; i++) {
1533
+ child = children[i];
1534
+ if (child.__.mask) {
1535
+ if (currentMask) {
1536
+ maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
1537
+ maskCanvas = contentCanvas = null;
1538
+ }
1539
+ if (child.__.maskType === 'path') {
1540
+ if (child.opacity < 1) {
1541
+ currentMask = 'opacity-path';
1542
+ maskOpacity = child.opacity;
1543
+ if (!contentCanvas)
1544
+ contentCanvas = getCanvas(canvas);
1545
+ }
1546
+ else {
1547
+ currentMask = 'path';
1548
+ canvas.save();
1549
+ }
1550
+ child.__clip(contentCanvas || canvas, options);
1551
+ }
1552
+ else {
1553
+ currentMask = 'alpha';
1554
+ if (!maskCanvas)
1555
+ maskCanvas = getCanvas(canvas);
1556
+ if (!contentCanvas)
1557
+ contentCanvas = getCanvas(canvas);
1558
+ child.__render(maskCanvas, options);
1559
+ }
1560
+ if (child.__.maskType !== 'clipping')
1561
+ continue;
1562
+ }
1563
+ if (excludeRenderBounds(child, options))
1564
+ continue;
1565
+ child.__render(contentCanvas || canvas, options);
1566
+ }
1567
+ maskEnd(this, currentMask, canvas, contentCanvas, maskCanvas, maskOpacity);
1568
+ };
1569
+ function maskEnd(leaf, maskMode, canvas, contentCanvas, maskCanvas, maskOpacity) {
1570
+ switch (maskMode) {
1571
+ case 'alpha':
1572
+ usePixelMask(leaf, canvas, contentCanvas, maskCanvas);
1573
+ break;
1574
+ case 'opacity-path':
1575
+ copyContent(leaf, canvas, contentCanvas, maskOpacity);
1576
+ break;
1577
+ case 'path':
1578
+ canvas.restore();
1579
+ }
1580
+ }
1581
+ function getCanvas(canvas) {
1582
+ return canvas.getSameCanvas(false, true);
1583
+ }
1584
+ function usePixelMask(leaf, canvas, content, mask) {
1585
+ const realBounds = leaf.__nowWorld;
1586
+ content.resetTransform();
1587
+ content.opacity = 1;
1588
+ content.useMask(mask, realBounds);
1589
+ mask.recycle(realBounds);
1590
+ copyContent(leaf, canvas, content, 1);
1591
+ }
1592
+ function copyContent(leaf, canvas, content, maskOpacity) {
1593
+ const realBounds = leaf.__nowWorld;
1594
+ canvas.resetTransform();
1595
+ canvas.opacity = maskOpacity;
1596
+ canvas.copyWorld(content, realBounds);
1597
+ content.recycle(realBounds);
1598
+ }
1599
+
1600
+ const money = '¥¥$€££¢¢';
1601
+ const letter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
1602
+ const langBefore = '《(「〈『〖【〔{┌<‘“=' + money;
1603
+ const langAfter = '》)」〉』〗】〕}┐>’”!?,、。:;‰';
1604
+ const langSymbol = '≮≯≈≠=…';
1605
+ const langBreak$1 = '—/~|┆·';
1606
+ const beforeChar = '{[(<\'"' + langBefore;
1607
+ const afterChar = '>)]}%!?,.:;\'"' + langAfter;
1608
+ const symbolChar = afterChar + '_#~&*+\\=|' + langSymbol;
1609
+ const breakChar = '- ' + langBreak$1;
1610
+ const cjkRangeList = [
1611
+ [0x4E00, 0x9FFF],
1612
+ [0x3400, 0x4DBF],
1613
+ [0x20000, 0x2A6DF],
1614
+ [0x2A700, 0x2B73F],
1615
+ [0x2B740, 0x2B81F],
1616
+ [0x2B820, 0x2CEAF],
1617
+ [0x2CEB0, 0x2EBEF],
1618
+ [0x30000, 0x3134F],
1619
+ [0x31350, 0x323AF],
1620
+ [0x2E80, 0x2EFF],
1621
+ [0x2F00, 0x2FDF],
1622
+ [0x2FF0, 0x2FFF],
1623
+ [0x3000, 0x303F],
1624
+ [0x31C0, 0x31EF],
1625
+ [0x3200, 0x32FF],
1626
+ [0x3300, 0x33FF],
1627
+ [0xF900, 0xFAFF],
1628
+ [0xFE30, 0xFE4F],
1629
+ [0x1F200, 0x1F2FF],
1630
+ [0x2F800, 0x2FA1F],
1631
+ ];
1632
+ const cjkReg = new RegExp(cjkRangeList.map(([start, end]) => `[\\u${start.toString(16)}-\\u${end.toString(16)}]`).join('|'));
1633
+ function mapChar(str) {
1634
+ const map = {};
1635
+ str.split('').forEach(char => map[char] = true);
1636
+ return map;
1637
+ }
1638
+ const letterMap = mapChar(letter);
1639
+ const beforeMap = mapChar(beforeChar);
1640
+ const afterMap = mapChar(afterChar);
1641
+ const symbolMap = mapChar(symbolChar);
1642
+ const breakMap = mapChar(breakChar);
1643
+ var CharType;
1644
+ (function (CharType) {
1645
+ CharType[CharType["Letter"] = 0] = "Letter";
1646
+ CharType[CharType["Single"] = 1] = "Single";
1647
+ CharType[CharType["Before"] = 2] = "Before";
1648
+ CharType[CharType["After"] = 3] = "After";
1649
+ CharType[CharType["Symbol"] = 4] = "Symbol";
1650
+ CharType[CharType["Break"] = 5] = "Break";
1651
+ })(CharType || (CharType = {}));
1652
+ const { Letter: Letter$1, Single: Single$1, Before: Before$1, After: After$1, Symbol: Symbol$1, Break: Break$1 } = CharType;
1653
+ function getCharType(char) {
1654
+ if (letterMap[char]) {
1655
+ return Letter$1;
1656
+ }
1657
+ else if (breakMap[char]) {
1658
+ return Break$1;
1659
+ }
1660
+ else if (beforeMap[char]) {
1661
+ return Before$1;
1662
+ }
1663
+ else if (afterMap[char]) {
1664
+ return After$1;
1665
+ }
1666
+ else if (symbolMap[char]) {
1667
+ return Symbol$1;
1668
+ }
1669
+ else if (cjkReg.test(char)) {
1670
+ return Single$1;
1671
+ }
1672
+ else {
1673
+ return Letter$1;
1674
+ }
1675
+ }
1676
+
1677
+ const TextRowHelper = {
1678
+ trimRight(row) {
1679
+ const { words } = row;
1680
+ let trimRight = 0, len = words.length, char;
1681
+ for (let i = len - 1; i > -1; i--) {
1682
+ char = words[i].data[0];
1683
+ if (char.char === ' ') {
1684
+ trimRight++;
1685
+ row.width -= char.width;
1686
+ }
1687
+ else {
1688
+ break;
1689
+ }
1690
+ }
1691
+ if (trimRight)
1692
+ words.splice(len - trimRight, trimRight);
1693
+ }
1694
+ };
1695
+
1696
+ function getTextCase(char, textCase, firstChar) {
1697
+ switch (textCase) {
1698
+ case 'title':
1699
+ return firstChar ? char.toUpperCase() : char;
1700
+ case 'upper':
1701
+ return char.toUpperCase();
1702
+ case 'lower':
1703
+ return char.toLowerCase();
1704
+ default:
1705
+ return char;
1706
+ }
1707
+ }
1708
+
1709
+ const { trimRight } = TextRowHelper;
1710
+ const { Letter, Single, Before, After, Symbol, Break } = CharType;
1711
+ let word, row, wordWidth, rowWidth, realWidth;
1712
+ let char, charWidth, startCharSize, charSize, charType, lastCharType, langBreak, afterBreak, paraStart;
1713
+ let textDrawData, rows = [], bounds;
1714
+ function createRows(drawData, content, style) {
1715
+ textDrawData = drawData;
1716
+ rows = drawData.rows;
1717
+ bounds = drawData.bounds;
1718
+ const { __letterSpacing, paraIndent, textCase } = style;
1719
+ const { canvas } = core.Platform;
1720
+ const { width, height } = bounds;
1721
+ const charMode = width || height || __letterSpacing || (textCase !== 'none');
1722
+ if (charMode) {
1723
+ const wrap = style.textWrap !== 'none';
1724
+ const breakAll = style.textWrap === 'break';
1725
+ paraStart = true;
1726
+ lastCharType = null;
1727
+ startCharSize = charWidth = charSize = wordWidth = rowWidth = 0;
1728
+ word = { data: [] }, row = { words: [] };
1729
+ for (let i = 0, len = content.length; i < len; i++) {
1730
+ char = content[i];
1731
+ if (char === '\n') {
1732
+ if (wordWidth)
1733
+ addWord();
1734
+ row.paraEnd = true;
1735
+ addRow();
1736
+ paraStart = true;
1737
+ }
1738
+ else {
1739
+ charType = getCharType(char);
1740
+ if (charType === Letter && textCase !== 'none')
1741
+ char = getTextCase(char, textCase, !wordWidth);
1742
+ charWidth = canvas.measureText(char).width;
1743
+ if (__letterSpacing) {
1744
+ if (__letterSpacing < 0)
1745
+ charSize = charWidth;
1746
+ charWidth += __letterSpacing;
1747
+ }
1748
+ langBreak = (charType === Single && (lastCharType === Single || lastCharType === Letter)) || (lastCharType === Single && charType !== After);
1749
+ afterBreak = ((charType === Before || charType === Single) && (lastCharType === Symbol || lastCharType === After));
1750
+ realWidth = paraStart && paraIndent ? width - paraIndent : width;
1751
+ if (wrap && (width && rowWidth + wordWidth + charWidth > realWidth)) {
1752
+ if (breakAll) {
1753
+ if (wordWidth)
1754
+ addWord();
1755
+ addRow();
1756
+ }
1757
+ else {
1758
+ if (!afterBreak)
1759
+ afterBreak = charType === Letter && lastCharType == After;
1760
+ if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
1761
+ if (wordWidth)
1762
+ addWord();
1763
+ addRow();
1764
+ }
1765
+ else {
1766
+ addRow();
1767
+ }
1768
+ }
1769
+ }
1770
+ if (char === ' ' && paraStart !== true && (rowWidth + wordWidth) === 0) ;
1771
+ else {
1772
+ if (charType === Break) {
1773
+ if (char === ' ' && wordWidth)
1774
+ addWord();
1775
+ addChar(char, charWidth);
1776
+ addWord();
1777
+ }
1778
+ else if (langBreak || afterBreak) {
1779
+ if (wordWidth)
1780
+ addWord();
1781
+ addChar(char, charWidth);
1782
+ }
1783
+ else {
1784
+ addChar(char, charWidth);
1785
+ }
1786
+ }
1787
+ lastCharType = charType;
1788
+ }
1789
+ }
1790
+ if (wordWidth)
1791
+ addWord();
1792
+ if (rowWidth)
1793
+ addRow();
1794
+ rows.length > 0 && (rows[rows.length - 1].paraEnd = true);
1795
+ }
1796
+ else {
1797
+ content.split('\n').forEach(content => {
1798
+ textDrawData.paraNumber++;
1799
+ rows.push({ x: paraIndent || 0, text: content, width: canvas.measureText(content).width, paraStart: true });
1800
+ });
1801
+ }
1802
+ }
1803
+ function addChar(char, width) {
1804
+ if (charSize && !startCharSize)
1805
+ startCharSize = charSize;
1806
+ word.data.push({ char, width });
1807
+ wordWidth += width;
1808
+ }
1809
+ function addWord() {
1810
+ rowWidth += wordWidth;
1811
+ word.width = wordWidth;
1812
+ row.words.push(word);
1813
+ word = { data: [] };
1814
+ wordWidth = 0;
1815
+ }
1816
+ function addRow() {
1817
+ if (paraStart) {
1818
+ textDrawData.paraNumber++;
1819
+ row.paraStart = true;
1820
+ paraStart = false;
1821
+ }
1822
+ if (charSize) {
1823
+ row.startCharSize = startCharSize;
1824
+ row.endCharSize = charSize;
1825
+ startCharSize = 0;
1826
+ }
1827
+ row.width = rowWidth;
1828
+ if (bounds.width)
1829
+ trimRight(row);
1830
+ rows.push(row);
1831
+ row = { words: [] };
1832
+ rowWidth = 0;
1833
+ }
1834
+
1835
+ const CharMode = 0;
1836
+ const WordMode = 1;
1837
+ const TextMode = 2;
1838
+ function layoutChar(drawData, style, width, _height) {
1839
+ const { rows } = drawData;
1840
+ const { textAlign, paraIndent, letterSpacing } = style;
1841
+ let charX, addWordWidth, indentWidth, mode, wordChar;
1842
+ rows.forEach(row => {
1843
+ if (row.words) {
1844
+ indentWidth = paraIndent && row.paraStart ? paraIndent : 0;
1845
+ addWordWidth = (width && textAlign === 'justify' && row.words.length > 1) ? (width - row.width - indentWidth) / (row.words.length - 1) : 0;
1846
+ mode = (letterSpacing || row.isOverflow) ? CharMode : (addWordWidth > 0.01 ? WordMode : TextMode);
1847
+ if (row.isOverflow && !letterSpacing)
1848
+ row.textMode = true;
1849
+ if (mode === TextMode) {
1850
+ row.x += indentWidth;
1851
+ toTextChar$1(row);
1852
+ }
1853
+ else {
1854
+ row.x += indentWidth;
1855
+ charX = row.x;
1856
+ row.data = [];
1857
+ row.words.forEach(word => {
1858
+ if (mode === WordMode) {
1859
+ wordChar = { char: '', x: charX };
1860
+ charX = toWordChar(word.data, charX, wordChar);
1861
+ if (wordChar.char !== ' ')
1862
+ row.data.push(wordChar);
1863
+ }
1864
+ else {
1865
+ charX = toChar(word.data, charX, row.data);
1866
+ }
1867
+ if (!row.paraEnd && addWordWidth) {
1868
+ charX += addWordWidth;
1869
+ row.width += addWordWidth;
1870
+ }
1871
+ });
1872
+ }
1873
+ row.words = null;
1874
+ }
1875
+ });
1876
+ }
1877
+ function toTextChar$1(row) {
1878
+ row.text = '';
1879
+ row.words.forEach(word => {
1880
+ word.data.forEach(char => {
1881
+ row.text += char.char;
1882
+ });
1883
+ });
1884
+ }
1885
+ function toWordChar(data, charX, wordChar) {
1886
+ data.forEach(char => {
1887
+ wordChar.char += char.char;
1888
+ charX += char.width;
1889
+ });
1890
+ return charX;
1891
+ }
1892
+ function toChar(data, charX, rowData) {
1893
+ data.forEach(char => {
1894
+ if (char.char !== ' ') {
1895
+ char.x = charX;
1896
+ rowData.push(char);
1897
+ }
1898
+ charX += char.width;
1899
+ });
1900
+ return charX;
1901
+ }
1902
+
1903
+ function layoutText(drawData, style) {
1904
+ const { rows, bounds } = drawData;
1905
+ const { __lineHeight, __baseLine, __letterSpacing, __clipText, textAlign, verticalAlign, paraSpacing } = style;
1906
+ let { x, y, width, height } = bounds, realHeight = __lineHeight * rows.length + (paraSpacing ? paraSpacing * (drawData.paraNumber - 1) : 0);
1907
+ let starY = __baseLine;
1908
+ if (__clipText && realHeight > height) {
1909
+ realHeight = Math.max(height, __lineHeight);
1910
+ drawData.overflow = rows.length;
1911
+ }
1912
+ else {
1913
+ switch (verticalAlign) {
1914
+ case 'middle':
1915
+ y += (height - realHeight) / 2;
1916
+ break;
1917
+ case 'bottom':
1918
+ y += (height - realHeight);
1919
+ }
1920
+ }
1921
+ starY += y;
1922
+ let row, rowX, rowWidth;
1923
+ for (let i = 0, len = rows.length; i < len; i++) {
1924
+ row = rows[i];
1925
+ row.x = x;
1926
+ switch (textAlign) {
1927
+ case 'center':
1928
+ row.x += (width - row.width) / 2;
1929
+ break;
1930
+ case 'right':
1931
+ row.x += width - row.width;
1932
+ }
1933
+ if (row.paraStart && paraSpacing && i > 0)
1934
+ starY += paraSpacing;
1935
+ row.y = starY;
1936
+ starY += __lineHeight;
1937
+ if (drawData.overflow > i && starY > realHeight) {
1938
+ row.isOverflow = true;
1939
+ drawData.overflow = i + 1;
1940
+ }
1941
+ rowX = row.x;
1942
+ rowWidth = row.width;
1943
+ if (__letterSpacing < 0) {
1944
+ if (row.width < 0) {
1945
+ rowWidth = -row.width + style.fontSize + __letterSpacing;
1946
+ rowX -= rowWidth;
1947
+ rowWidth += style.fontSize;
1948
+ }
1949
+ else {
1950
+ rowWidth -= __letterSpacing;
1951
+ }
1952
+ }
1953
+ if (rowX < bounds.x)
1954
+ bounds.x = rowX;
1955
+ if (rowWidth > bounds.width)
1956
+ bounds.width = rowWidth;
1957
+ if (__clipText && width && width < rowWidth) {
1958
+ row.isOverflow = true;
1959
+ if (!drawData.overflow)
1960
+ drawData.overflow = rows.length;
1961
+ }
1962
+ }
1963
+ bounds.y = y;
1964
+ bounds.height = realHeight;
1965
+ }
1966
+
1967
+ function clipText(drawData, style) {
1968
+ const { rows, overflow } = drawData;
1969
+ let { textOverflow } = style;
1970
+ rows.splice(overflow);
1971
+ if (textOverflow !== 'hide') {
1972
+ if (textOverflow === 'ellipsis')
1973
+ textOverflow = '...';
1974
+ let char, charRight;
1975
+ const ellipsisWidth = core.Platform.canvas.measureText(textOverflow).width;
1976
+ const right = style.x + style.width - ellipsisWidth;
1977
+ const list = style.textWrap === 'none' ? rows : [rows[overflow - 1]];
1978
+ list.forEach(row => {
1979
+ if (row.isOverflow && row.data) {
1980
+ let end = row.data.length - 1;
1981
+ for (let i = end; i > -1; i--) {
1982
+ char = row.data[i];
1983
+ charRight = char.x + char.width;
1984
+ if (i === end && charRight < right) {
1985
+ break;
1986
+ }
1987
+ else if (charRight < right && char.char !== ' ') {
1988
+ row.data.splice(i + 1);
1989
+ row.width -= char.width;
1990
+ break;
1991
+ }
1992
+ row.width -= char.width;
1993
+ }
1994
+ row.width += ellipsisWidth;
1995
+ row.data.push({ char: textOverflow, x: charRight });
1996
+ if (row.textMode)
1997
+ toTextChar(row);
1998
+ }
1999
+ });
2000
+ }
2001
+ }
2002
+ function toTextChar(row) {
2003
+ row.text = '';
2004
+ row.data.forEach(char => {
2005
+ row.text += char.char;
2006
+ });
2007
+ row.data = null;
2008
+ }
2009
+
2010
+ function decorationText(drawData, style) {
2011
+ const { fontSize } = style;
2012
+ drawData.decorationHeight = fontSize / 11;
2013
+ switch (style.textDecoration) {
2014
+ case 'under':
2015
+ drawData.decorationY = fontSize * 0.15;
2016
+ break;
2017
+ case 'delete':
2018
+ drawData.decorationY = -fontSize * 0.35;
2019
+ }
2020
+ }
2021
+
2022
+ const { top, right, bottom, left } = core.Direction4;
2023
+ function getDrawData(content, style) {
2024
+ if (typeof content !== 'string')
2025
+ content = String(content);
2026
+ let x = 0, y = 0;
2027
+ let width = style.__getInput('width') || 0;
2028
+ let height = style.__getInput('height') || 0;
2029
+ const { textDecoration, __font, __padding: padding } = style;
2030
+ if (padding) {
2031
+ if (width) {
2032
+ x = padding[left];
2033
+ width -= (padding[right] + padding[left]);
2034
+ }
2035
+ if (height) {
2036
+ y = padding[top];
2037
+ height -= (padding[top] + padding[bottom]);
2038
+ }
2039
+ }
2040
+ const drawData = {
2041
+ bounds: { x, y, width, height },
2042
+ rows: [],
2043
+ paraNumber: 0,
2044
+ font: core.Platform.canvas.font = __font
2045
+ };
2046
+ createRows(drawData, content, style);
2047
+ if (padding)
2048
+ padAutoText(padding, drawData, style, width, height);
2049
+ layoutText(drawData, style);
2050
+ layoutChar(drawData, style, width);
2051
+ if (drawData.overflow)
2052
+ clipText(drawData, style);
2053
+ if (textDecoration !== 'none')
2054
+ decorationText(drawData, style);
2055
+ return drawData;
2056
+ }
2057
+ function padAutoText(padding, drawData, style, width, height) {
2058
+ if (!width) {
2059
+ switch (style.textAlign) {
2060
+ case 'left':
2061
+ offsetText(drawData, 'x', padding[left]);
2062
+ break;
2063
+ case 'right':
2064
+ offsetText(drawData, 'x', -padding[right]);
2065
+ }
2066
+ }
2067
+ if (!height) {
2068
+ switch (style.verticalAlign) {
2069
+ case 'top':
2070
+ offsetText(drawData, 'y', padding[top]);
2071
+ break;
2072
+ case 'bottom':
2073
+ offsetText(drawData, 'y', -padding[bottom]);
2074
+ }
2075
+ }
2076
+ }
2077
+ function offsetText(drawData, attrName, value) {
2078
+ const { bounds, rows } = drawData;
2079
+ bounds[attrName] += value;
2080
+ for (let i = 0; i < rows.length; i++)
2081
+ rows[i][attrName] += value;
2082
+ }
2083
+
2084
+ const TextConvertModule = {
2085
+ getDrawData
2086
+ };
2087
+
2088
+ function string(color, opacity) {
2089
+ if (typeof color === 'string')
2090
+ return color;
2091
+ let a = color.a === undefined ? 1 : color.a;
2092
+ if (opacity)
2093
+ a *= opacity;
2094
+ const rgb = color.r + ',' + color.g + ',' + color.b;
2095
+ return a === 1 ? 'rgb(' + rgb + ')' : 'rgba(' + rgb + ',' + a + ')';
2096
+ }
2097
+
2098
+ const ColorConvertModule = {
2099
+ string
2100
+ };
2101
+
2102
+ const { setPoint, addPoint, toBounds } = core.TwoPointBoundsHelper;
2103
+ function getTrimBounds(canvas) {
2104
+ const { width, height } = canvas.view;
2105
+ const { data } = canvas.context.getImageData(0, 0, width, height);
2106
+ let x, y, pointBounds, index = 0;
2107
+ for (let i = 0; i < data.length; i += 4) {
2108
+ if (data[i + 3] !== 0) {
2109
+ x = index % width;
2110
+ y = (index - x) / width;
2111
+ pointBounds ? addPoint(pointBounds, x, y) : setPoint(pointBounds = {}, x, y);
2112
+ }
2113
+ index++;
2114
+ }
2115
+ const bounds = new core.Bounds();
2116
+ toBounds(pointBounds, bounds);
2117
+ return bounds.scale(1 / canvas.pixelRatio).ceil();
2118
+ }
2119
+
2120
+ const ExportModule = {
2121
+ export(leaf, filename, options) {
2122
+ this.running = true;
2123
+ return addTask((success) => new Promise((resolve) => {
2124
+ const over = (result) => {
2125
+ success(result);
2126
+ resolve();
2127
+ this.running = false;
2128
+ };
2129
+ const { leafer } = leaf;
2130
+ if (leafer) {
2131
+ leafer.waitViewCompleted(() => __awaiter(this, void 0, void 0, function* () {
2132
+ let renderBounds, trimBounds, scaleX = 1, scaleY = 1;
2133
+ options = core.FileHelper.getExportOptions(options);
2134
+ const { scale, pixelRatio, slice, trim } = options;
2135
+ const screenshot = options.screenshot || leaf.isApp;
2136
+ const fill = options.fill === undefined ? ((leaf.isLeafer && screenshot) ? leaf.fill : '') : options.fill;
2137
+ const needFill = core.FileHelper.isOpaqueImage(filename) || fill, matrix = new core.Matrix();
2138
+ if (screenshot) {
2139
+ renderBounds = screenshot === true ? (leaf.isLeafer ? leafer.canvas.bounds : leaf.worldRenderBounds) : screenshot;
2140
+ }
2141
+ else {
2142
+ const { localTransform, __world: world } = leaf;
2143
+ matrix.set(world).divide(localTransform).invert();
2144
+ scaleX = 1 / (world.scaleX / leaf.scaleX);
2145
+ scaleY = 1 / (world.scaleY / leaf.scaleY);
2146
+ renderBounds = leaf.getBounds('render', 'local');
2147
+ }
2148
+ let { x, y, width, height } = renderBounds;
2149
+ if (scale) {
2150
+ matrix.scale(scale);
2151
+ width *= scale, height *= scale;
2152
+ scaleX *= scale, scaleY *= scale;
2153
+ }
2154
+ let canvas = core.Creator.canvas({ width, height, pixelRatio });
2155
+ const renderOptions = { matrix: matrix.translate(-x, -y).withScale(scaleX, scaleY) };
2156
+ if (slice) {
2157
+ leaf = leafer;
2158
+ renderOptions.bounds = canvas.bounds;
2159
+ }
2160
+ canvas.save();
2161
+ leaf.__render(canvas, renderOptions);
2162
+ canvas.restore();
2163
+ if (trim) {
2164
+ trimBounds = getTrimBounds(canvas);
2165
+ const old = canvas, { width, height } = trimBounds;
2166
+ const config = { x: 0, y: 0, width, height, pixelRatio };
2167
+ canvas = core.Creator.canvas(config);
2168
+ canvas.copyWorld(old, trimBounds, config);
2169
+ }
2170
+ if (needFill)
2171
+ canvas.fillWorld(canvas.bounds, fill || '#FFFFFF', 'destination-over');
2172
+ const data = filename === 'canvas' ? canvas : yield canvas.export(filename, options);
2173
+ over({ data, renderBounds, trimBounds });
2174
+ }));
2175
+ }
2176
+ else {
2177
+ over({ data: false });
2178
+ }
2179
+ }));
2180
+ }
2181
+ };
2182
+ let tasker;
2183
+ function addTask(task) {
2184
+ if (!tasker)
2185
+ tasker = new core.TaskProcessor();
2186
+ return new Promise((resolve) => {
2187
+ tasker.add(() => __awaiter(this, void 0, void 0, function* () { return yield task(resolve); }), { parallel: false });
2188
+ });
2189
+ }
2190
+
2191
+ Object.assign(draw.TextConvert, TextConvertModule);
2192
+ Object.assign(draw.ColorConvert, ColorConvertModule);
2193
+ Object.assign(draw.Paint, PaintModule);
2194
+ Object.assign(draw.PaintImage, PaintImageModule);
2195
+ Object.assign(draw.PaintGradient, PaintGradientModule);
2196
+ Object.assign(draw.Effect, EffectModule);
2197
+ Object.assign(draw.Export, ExportModule);
2198
+
2199
+ Object.defineProperty(exports, 'LeaferImage', {
2200
+ enumerable: true,
2201
+ get: function () { return core.LeaferImage; }
2202
+ });
2203
+ exports.Layouter = Layouter;
2204
+ exports.LeaferCanvas = LeaferCanvas;
2205
+ exports.Renderer = Renderer;
2206
+ exports.Watcher = Watcher;
2207
+ exports.useCanvas = useCanvas;
2208
+ Object.keys(core).forEach(function (k) {
2209
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
2210
+ enumerable: true,
2211
+ get: function () { return core[k]; }
2212
+ });
2213
+ });
2214
+ Object.keys(draw).forEach(function (k) {
2215
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
2216
+ enumerable: true,
2217
+ get: function () { return draw[k]; }
2218
+ });
2219
+ });