@next2d/display 1.14.20

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.
@@ -0,0 +1,2164 @@
1
+ import { GraphicsBitmapFill } from "./GraphicsBitmapFill";
2
+ import { GraphicsGradientFill } from "./GraphicsGradientFill";
3
+ import { $currentPlayer } from "@next2d/util";
4
+ import { $doUpdated, $Math, $Number, $getArray, $poolArray, $toColorInt, $intToRGBA, $clamp, $boundsMatrix, $poolBoundsObject, $Infinity, $getFloat32Array6, $multiplicationMatrix, $poolFloat32Array6, $getBoundsObject, $Float32Array, $getFloat32Array4, $linearGradientXY } from "@next2d/share";
5
+ /**
6
+ * Graphics クラスには、ベクターシェイプの作成に使用できる一連のメソッドがあります。
7
+ * 描画をサポートする表示オブジェクトには、Sprite および Shape オブジェクトがあります。
8
+ * これらの各クラスには、Graphics オブジェクトである graphics プロパティがあります。
9
+ * 以下は、簡単に使用できるように用意されているヘルパー関数の一例です。
10
+ * drawRect()、drawRoundRect()、drawCircle()、および drawEllipse()。
11
+ *
12
+ * The Graphics class contains a set of methods that you can use to create a vector shape.
13
+ * Display objects that support drawing include Sprite and Shape objects.
14
+ * Each of these classes includes a graphics property that is a Graphics object.
15
+ * The following are among those helper functions provided for ease of use:
16
+ * drawRect(), drawRoundRect(), drawCircle(), and drawEllipse().
17
+ *
18
+ * @class
19
+ * @memberOf next2d.display
20
+ */
21
+ export class Graphics {
22
+ /**
23
+ * @param {DisplayObject} src
24
+ *
25
+ * @constructor
26
+ * @public
27
+ */
28
+ constructor(src = null) {
29
+ /**
30
+ * @type {DisplayObject}
31
+ * @default null
32
+ * @private
33
+ */
34
+ this._$displayObject = src;
35
+ /**
36
+ * @type {number}
37
+ * @default 0
38
+ * @private
39
+ */
40
+ this._$maxAlpha = 0;
41
+ /**
42
+ * @type {number}
43
+ * @default 0
44
+ * @private
45
+ */
46
+ this._$pointerX = 0;
47
+ /**
48
+ * @type {number}
49
+ * @default 0
50
+ * @private
51
+ */
52
+ this._$pointerY = 0;
53
+ /**
54
+ * @type {boolean}
55
+ * @default false
56
+ * @private
57
+ */
58
+ this._$canDraw = false;
59
+ /**
60
+ * @type {number}
61
+ * @default 0
62
+ * @private
63
+ */
64
+ this._$fillType = 0;
65
+ /**
66
+ * @type {GraphicsGradientFill}
67
+ * @default null
68
+ * @private
69
+ */
70
+ this._$fillGradient = null;
71
+ /**
72
+ * @type {GraphicsGradientFill}
73
+ * @default null
74
+ * @private
75
+ */
76
+ this._$fillBitmap = null;
77
+ /**
78
+ * @type {number}
79
+ * @default 0
80
+ * @private
81
+ */
82
+ this._$fillStyleR = 0;
83
+ /**
84
+ * @type {number}
85
+ * @default 0
86
+ * @private
87
+ */
88
+ this._$fillStyleG = 0;
89
+ /**
90
+ * @type {number}
91
+ * @default 0
92
+ * @private
93
+ */
94
+ this._$fillStyleB = 0;
95
+ /**
96
+ * @type {number}
97
+ * @default 0
98
+ * @private
99
+ */
100
+ this._$fillStyleA = 0;
101
+ /**
102
+ * @type {boolean}
103
+ * @default false
104
+ * @private
105
+ */
106
+ this._$doFill = false;
107
+ /**
108
+ * @type {number}
109
+ * @default 0
110
+ * @private
111
+ */
112
+ this._$lineType = 0;
113
+ /**
114
+ * @type {GraphicsGradientFill}
115
+ * @default 0
116
+ * @private
117
+ */
118
+ this._$lineGradient = null;
119
+ /**
120
+ * @type {string}
121
+ * @default none
122
+ * @private
123
+ */
124
+ this._$caps = "none";
125
+ /**
126
+ * @type {string}
127
+ * @default round
128
+ * @private
129
+ */
130
+ this._$joints = "round";
131
+ /**
132
+ * @type {number}
133
+ * @default 0
134
+ * @private
135
+ */
136
+ this._$miterLimit = 0;
137
+ /**
138
+ * @type {number}
139
+ * @default 1
140
+ * @private
141
+ */
142
+ this._$lineWidth = 1;
143
+ /**
144
+ * @type {number}
145
+ * @default 0
146
+ * @private
147
+ */
148
+ this._$lineStyleR = 0;
149
+ /**
150
+ * @type {number}
151
+ * @default 0
152
+ * @private
153
+ */
154
+ this._$lineStyleG = 0;
155
+ /**
156
+ * @type {number}
157
+ * @default 0
158
+ * @private
159
+ */
160
+ this._$lineStyleB = 0;
161
+ /**
162
+ * @type {number}
163
+ * @default 0
164
+ * @private
165
+ */
166
+ this._$lineStyleA = 0;
167
+ /**
168
+ * @type {boolean}
169
+ * @default false
170
+ * @private
171
+ */
172
+ this._$doLine = false;
173
+ /**
174
+ * @type {number}
175
+ * @default Number.MAX_VALUE
176
+ * @private
177
+ */
178
+ this._$xMin = $Number.MAX_VALUE;
179
+ /**
180
+ * @type {number}
181
+ * @default -Number.MAX_VALUE
182
+ * @private
183
+ */
184
+ this._$xMax = -$Number.MAX_VALUE;
185
+ /**
186
+ * @type {number}
187
+ * @default Number.MAX_VALUE
188
+ * @private
189
+ */
190
+ this._$yMin = $Number.MAX_VALUE;
191
+ /**
192
+ * @type {number}
193
+ * @default -Number.MAX_VALUE
194
+ * @private
195
+ */
196
+ this._$yMax = -$Number.MAX_VALUE;
197
+ /**
198
+ * @type {Float32Array}
199
+ * @default null
200
+ * @private
201
+ */
202
+ this._$buffer = null;
203
+ /**
204
+ * @type {array}
205
+ * @default null
206
+ * @private
207
+ */
208
+ this._$recode = null;
209
+ /**
210
+ * @type {array}
211
+ * @default null
212
+ * @private
213
+ */
214
+ this._$fills = null;
215
+ /**
216
+ * @type {array}
217
+ * @default null
218
+ * @private
219
+ */
220
+ this._$lines = null;
221
+ }
222
+ /**
223
+ * @description 指定されたクラスのストリングを返します。
224
+ * Returns the string representation of the specified class.
225
+ *
226
+ * @return {string}
227
+ * @default [class Graphics]
228
+ * @method
229
+ * @static
230
+ */
231
+ static toString() {
232
+ return "[class Graphics]";
233
+ }
234
+ /**
235
+ * @description 指定されたクラスの空間名を返します。
236
+ * Returns the space name of the specified class.
237
+ *
238
+ * @return {string}
239
+ * @default next2d.display.Bitmap
240
+ * @const
241
+ * @static
242
+ */
243
+ static get namespace() {
244
+ return "next2d.display.Graphics";
245
+ }
246
+ /**
247
+ * @description 指定されたオブジェクトのストリングを返します。
248
+ * Returns the string representation of the specified object.
249
+ *
250
+ * @return {string}
251
+ * @default [object Graphics]
252
+ * @method
253
+ * @public
254
+ */
255
+ toString() {
256
+ return "[object Graphics]";
257
+ }
258
+ /**
259
+ * @description 指定されたオブジェクトの空間名を返します。
260
+ * Returns the space name of the specified object.
261
+ *
262
+ * @return {string}
263
+ * @default next2d.display.Graphics
264
+ * @const
265
+ * @public
266
+ */
267
+ get namespace() {
268
+ return "next2d.display.Graphics";
269
+ }
270
+ /**
271
+ * @return {number}
272
+ * @default 0
273
+ * @const
274
+ * @static
275
+ * @private
276
+ */
277
+ static get MOVE_TO() {
278
+ return 0;
279
+ }
280
+ /**
281
+ * @return {number}
282
+ * @default 1
283
+ * @const
284
+ * @static
285
+ * @private
286
+ */
287
+ static get CURVE_TO() {
288
+ return 1;
289
+ }
290
+ /**
291
+ * @return {number}
292
+ * @default 2
293
+ * @const
294
+ * @static
295
+ * @private
296
+ */
297
+ static get LINE_TO() {
298
+ return 2;
299
+ }
300
+ /**
301
+ * @return {number}
302
+ * @default 3
303
+ * @const
304
+ * @static
305
+ * @private
306
+ */
307
+ static get CUBIC() {
308
+ return 3;
309
+ }
310
+ /**
311
+ * @return {number}
312
+ * @default 4
313
+ * @const
314
+ * @static
315
+ * @private
316
+ */
317
+ static get ARC() {
318
+ return 4;
319
+ }
320
+ /**
321
+ * @return {number}
322
+ * @default 5
323
+ * @const
324
+ * @static
325
+ * @private
326
+ */
327
+ static get FILL_STYLE() {
328
+ return 5;
329
+ }
330
+ /**
331
+ * @return {number}
332
+ * @default 6
333
+ * @const
334
+ * @static
335
+ * @private
336
+ */
337
+ static get STROKE_STYLE() {
338
+ return 6;
339
+ }
340
+ /**
341
+ * @return {number}
342
+ * @default 7
343
+ * @const
344
+ * @static
345
+ * @private
346
+ */
347
+ static get END_FILL() {
348
+ return 7;
349
+ }
350
+ /**
351
+ * @return {number}
352
+ * @default 8
353
+ * @const
354
+ * @static
355
+ * @private
356
+ */
357
+ static get END_STROKE() {
358
+ return 8;
359
+ }
360
+ /**
361
+ * @return {number}
362
+ * @default 9
363
+ * @const
364
+ * @static
365
+ * @private
366
+ */
367
+ static get BEGIN_PATH() {
368
+ return 9;
369
+ }
370
+ /**
371
+ * @return {number}
372
+ * @default 10
373
+ * @const
374
+ * @static
375
+ * @private
376
+ */
377
+ static get GRADIENT_FILL() {
378
+ return 10;
379
+ }
380
+ /**
381
+ * @return {number}
382
+ * @default 11
383
+ * @const
384
+ * @static
385
+ * @private
386
+ */
387
+ static get GRADIENT_STROKE() {
388
+ return 11;
389
+ }
390
+ /**
391
+ * @return {number}
392
+ * @default 12
393
+ * @const
394
+ * @static
395
+ * @private
396
+ */
397
+ static get CLOSE_PATH() {
398
+ return 12;
399
+ }
400
+ /**
401
+ * @return {number}
402
+ * @default 13
403
+ * @const
404
+ * @static
405
+ * @private
406
+ */
407
+ static get BITMAP_FILL() {
408
+ return 13;
409
+ }
410
+ /**
411
+ * @return {number}
412
+ * @default 14
413
+ * @const
414
+ * @static
415
+ * @private
416
+ */
417
+ static get BITMAP_STROKE() {
418
+ return 14;
419
+ }
420
+ /**
421
+ * @description 描画領域をビットマップイメージで塗りつぶします。
422
+ * Fills a drawing area with a bitmap image.
423
+ *
424
+ * @param {BitmapData} bitmap_data
425
+ * @param {Matrix} [matrix=null]
426
+ * @param {boolean} [repeat=true]
427
+ * @param {boolean} [smooth=false]
428
+ * @return {Graphics}
429
+ * @method
430
+ * @public
431
+ */
432
+ beginBitmapFill(bitmap_data, matrix = null, repeat = true, smooth = false) {
433
+ // end fill
434
+ if (this._$doFill) {
435
+ this.endFill();
436
+ }
437
+ if (!this._$fills) {
438
+ this._$fills = $getArray();
439
+ }
440
+ // start
441
+ this._$maxAlpha = 1;
442
+ this._$doFill = true;
443
+ this._$canDraw = true;
444
+ // beginPath
445
+ this._$fills.push(Graphics.BEGIN_PATH);
446
+ this._$fillType = Graphics.BITMAP_FILL;
447
+ this._$fillBitmap = new GraphicsBitmapFill(bitmap_data, matrix, repeat, smooth);
448
+ return this;
449
+ }
450
+ /**
451
+ * @description 描画のときに他の Graphics メソッド(lineTo() や drawCircle() など)
452
+ * に対する今後の呼び出しに使用する単純な一色塗りを指定します。
453
+ * Specifies a simple one-color fill that subsequent calls
454
+ * to other Graphics methods (such as lineTo() or drawCircle()) use when drawing.
455
+ *
456
+ * @param {string|number} [color=0]
457
+ * @param {number} [alpha=1.0]
458
+ * @return {Graphics}
459
+ * @method
460
+ * @public
461
+ */
462
+ beginFill(color = 0, alpha = 1) {
463
+ // end fill
464
+ if (this._$doFill) {
465
+ this.endFill();
466
+ }
467
+ if (!this._$fills) {
468
+ this._$fills = $getArray();
469
+ }
470
+ // valid
471
+ color = $clamp($toColorInt(color), 0, 0xffffff, 0);
472
+ alpha = $clamp(alpha, 0, 1, 1);
473
+ // setup
474
+ this._$maxAlpha = $Math.max(this._$maxAlpha, alpha);
475
+ this._$doFill = true;
476
+ this._$canDraw = true;
477
+ // beginPath
478
+ this._$fills.push(Graphics.BEGIN_PATH);
479
+ // add Fill Style
480
+ const object = $intToRGBA(color, alpha);
481
+ this._$fillType = Graphics.FILL_STYLE;
482
+ this._$fillStyleR = object.R;
483
+ this._$fillStyleG = object.G;
484
+ this._$fillStyleB = object.B;
485
+ this._$fillStyleA = object.A;
486
+ return this;
487
+ }
488
+ /**
489
+ * @description Graphics の他のメソッド(lineTo()、drawCircle() など)に対する、
490
+ * オブジェクトの後続の呼び出しに使用するグラデーション塗りを指定します。
491
+ * Specifies a gradient fill used by subsequent calls
492
+ * to other Graphics methods (such as lineTo() or drawCircle()) for the object.
493
+ *
494
+ * @param {string} type
495
+ * @param {array} colors
496
+ * @param {array} alphas
497
+ * @param {array} ratios
498
+ * @param {Matrix} [matrix=null]
499
+ * @param {string} [spread_method=SpreadMethod.PAD]
500
+ * @param {string} [interpolation_method=InterpolationMethod.RGB]
501
+ * @param {number} [focal_point_ratio=0]
502
+ * @return {Graphics}
503
+ * @method
504
+ * @public
505
+ */
506
+ beginGradientFill(type, colors, alphas, ratios, matrix = null, spread_method = "pad", interpolation_method = "rgb", focal_point_ratio = 0) {
507
+ if (this._$doFill) {
508
+ this.endFill();
509
+ }
510
+ if (!this._$fills) {
511
+ this._$fills = $getArray();
512
+ }
513
+ // setup
514
+ for (let idx = 0; idx < alphas.length; ++idx) {
515
+ this._$maxAlpha = $Math.max(this._$maxAlpha, alphas[idx]);
516
+ }
517
+ this._$doFill = true;
518
+ this._$canDraw = true;
519
+ // beginPath
520
+ this._$fills.push(Graphics.BEGIN_PATH);
521
+ this._$fillType = Graphics.GRADIENT_FILL;
522
+ this._$fillGradient = new GraphicsGradientFill(type, colors, alphas, ratios, matrix, spread_method, interpolation_method, focal_point_ratio);
523
+ return this;
524
+ }
525
+ /**
526
+ * @description この Graphics オブジェクトに描画されているグラフィックをクリアし、
527
+ * 塗りと線のスタイルの設定をリセットします。
528
+ * Clears the graphics that were drawn to this Graphics object,
529
+ * and resets fill and line style settings.
530
+ *
531
+ * @return {Graphics}
532
+ * @method
533
+ * @public
534
+ */
535
+ clear() {
536
+ // param clear
537
+ this._$maxAlpha = 0;
538
+ this._$pointerX = 0;
539
+ this._$pointerY = 0;
540
+ this._$canDraw = false;
541
+ // fill
542
+ this._$fillType = 0;
543
+ this._$fillGradient = null;
544
+ this._$fillBitmap = null;
545
+ this._$fillStyleR = 0;
546
+ this._$fillStyleG = 0;
547
+ this._$fillStyleB = 0;
548
+ this._$fillStyleA = 0;
549
+ this._$doFill = false;
550
+ // stroke
551
+ this._$lineType = 0;
552
+ this._$lineGradient = null;
553
+ this._$caps = "none";
554
+ this._$joints = "round";
555
+ this._$miterLimit = 0;
556
+ this._$lineWidth = 1;
557
+ this._$lineStyleR = 0;
558
+ this._$lineStyleG = 0;
559
+ this._$lineStyleB = 0;
560
+ this._$lineStyleA = 0;
561
+ this._$doLine = false;
562
+ // bounds size
563
+ this._$xMin = $Number.MAX_VALUE;
564
+ this._$xMax = -$Number.MAX_VALUE;
565
+ this._$yMin = $Number.MAX_VALUE;
566
+ this._$yMax = -$Number.MAX_VALUE;
567
+ // init array
568
+ if (this._$recode) {
569
+ $poolArray(this._$recode);
570
+ }
571
+ if (this._$fills) {
572
+ $poolArray(this._$fills);
573
+ }
574
+ if (this._$lines) {
575
+ $poolArray(this._$lines);
576
+ }
577
+ this._$buffer = null;
578
+ this._$recode = null;
579
+ this._$fills = null;
580
+ this._$lines = null;
581
+ // restart
582
+ this._$restart();
583
+ return this;
584
+ }
585
+ /**
586
+ * @description すべての描画コマンドをソース Graphics オブジェクトから、呼び出し Graphics オブジェクトにコピーします。
587
+ * Copies all of drawing commands from the source Graphics object into the calling Graphics object.
588
+ *
589
+ * @return {Graphics}
590
+ * @method
591
+ * @public
592
+ */
593
+ clone() {
594
+ const graphics = new Graphics();
595
+ graphics.copyFrom(this);
596
+ return graphics;
597
+ }
598
+ /**
599
+ * @description すべての描画コマンドをソース Graphics オブジェクトから、呼び出し Graphics オブジェクトにコピーします。
600
+ * Copies all of drawing commands from the source Graphics object into the calling Graphics object.
601
+ *
602
+ * @param {Graphics} graphics
603
+ * @return {void}
604
+ * @method
605
+ * @public
606
+ */
607
+ copyFrom(graphics) {
608
+ if (graphics._$fillGradient) {
609
+ this._$fillGradient = graphics._$fillGradient.clone();
610
+ }
611
+ if (graphics._$fillBitmap) {
612
+ this._$fillBitmap = graphics._$fillBitmap.clone();
613
+ }
614
+ // fill
615
+ this._$doFill = graphics._$doFill;
616
+ this._$fillType = graphics._$fillType;
617
+ this._$fillStyleR = graphics._$fillStyleR;
618
+ this._$fillStyleG = graphics._$fillStyleG;
619
+ this._$fillStyleB = graphics._$fillStyleB;
620
+ this._$fillStyleA = graphics._$fillStyleA;
621
+ if (graphics._$lineGradient) {
622
+ this._$lineGradient = graphics._$lineGradient.clone();
623
+ }
624
+ // stroke
625
+ this._$doLine = graphics._$doLine;
626
+ this._$lineType = graphics._$lineType;
627
+ this._$caps = graphics._$caps;
628
+ this._$joints = graphics._$joints;
629
+ this._$miterLimit = graphics._$miterLimit;
630
+ this._$lineWidth = graphics._$lineWidth;
631
+ this._$lineStyleR = graphics._$lineStyleR;
632
+ this._$lineStyleG = graphics._$lineStyleG;
633
+ this._$lineStyleB = graphics._$lineStyleB;
634
+ this._$lineStyleA = graphics._$lineStyleA;
635
+ // bounds
636
+ this._$xMin = graphics._$xMin;
637
+ this._$xMax = graphics._$xMax;
638
+ this._$yMin = graphics._$yMin;
639
+ this._$yMax = graphics._$yMax;
640
+ // params
641
+ this._$maxAlpha = graphics._$maxAlpha;
642
+ this._$pointerX = graphics._$pointerX;
643
+ this._$pointerY = graphics._$pointerY;
644
+ this._$canDraw = graphics._$canDraw;
645
+ // path params
646
+ if (graphics._$fills) {
647
+ this._$fills = graphics._$fills.slice(0);
648
+ }
649
+ if (graphics._$lines) {
650
+ this._$lines = graphics._$lines.slice(0);
651
+ }
652
+ if (graphics._$recode) {
653
+ this._$recode = graphics._$recode.slice(0);
654
+ }
655
+ }
656
+ /**
657
+ * @description 現在の描画位置から指定されたアンカーポイントに 3 次ベジェ曲線を描画します。
658
+ * Draws a cubic Bezier curve from the current drawing position to the specified anchor point.
659
+ *
660
+ * @param {number} control_x1
661
+ * @param {number} control_y1
662
+ * @param {number} control_x2
663
+ * @param {number} control_y2
664
+ * @param {number} anchor_x
665
+ * @param {number} anchor_y
666
+ * @return {Graphics}
667
+ * @method
668
+ * @public
669
+ */
670
+ cubicCurveTo(control_x1, control_y1, control_x2, control_y2, anchor_x, anchor_y) {
671
+ anchor_x = +anchor_x || 0;
672
+ anchor_y = +anchor_y || 0;
673
+ if (this._$pointerX === anchor_x && this._$pointerY === anchor_y) {
674
+ return this;
675
+ }
676
+ control_x1 = +control_x1 || 0;
677
+ control_y1 = +control_y1 || 0;
678
+ control_x2 = +control_x2 || 0;
679
+ control_y2 = +control_y2 || 0;
680
+ // set bounds
681
+ this._$setBounds(control_x1, control_y1);
682
+ this._$setBounds(control_x2, control_y2);
683
+ this._$setBounds(anchor_x, anchor_y);
684
+ this._$margePath($getArray(Graphics.CUBIC, control_x1, control_y1, control_x2, control_y2, anchor_x, anchor_y));
685
+ this._$pointerX = anchor_x;
686
+ this._$pointerY = anchor_y;
687
+ // restart
688
+ this._$restart();
689
+ return this;
690
+ }
691
+ /**
692
+ * @description (controlX, controlY) で指定されたコントロールポイントを使用し、
693
+ * 現在の描画位置から (anchorX, anchorY) まで、現在の線のスタイルで 2 次ベジェ曲線を描画します。
694
+ * Draws a quadratic Bezier curve using the current line style from
695
+ * the current drawing position to (anchorX, anchorY)
696
+ * and using the control point that (controlX, controlY) specifies.
697
+ *
698
+ * @param {number} control_x
699
+ * @param {number} control_y
700
+ * @param {number} anchor_x
701
+ * @param {number} anchor_y
702
+ * @return {Graphics}
703
+ * @method
704
+ * @public
705
+ */
706
+ curveTo(control_x, control_y, anchor_x, anchor_y) {
707
+ anchor_x = +anchor_x || 0;
708
+ anchor_y = +anchor_y || 0;
709
+ if (this._$pointerX === anchor_x && this._$pointerY === anchor_y) {
710
+ return this;
711
+ }
712
+ control_x = +control_x || 0;
713
+ control_y = +control_y || 0;
714
+ this._$setBounds(control_x, control_y);
715
+ this._$setBounds(anchor_x, anchor_y);
716
+ this._$margePath($getArray(Graphics.CURVE_TO, control_x, control_y, anchor_x, anchor_y));
717
+ this._$pointerX = anchor_x;
718
+ this._$pointerY = anchor_y;
719
+ // restart
720
+ this._$restart();
721
+ return this;
722
+ }
723
+ /**
724
+ * @description 円を描画します。
725
+ * Draws a circle.
726
+ *
727
+ * @param {number} x
728
+ * @param {number} y
729
+ * @param {number} radius
730
+ * @return {Graphics}
731
+ * @method
732
+ * @public
733
+ */
734
+ drawCircle(x, y, radius) {
735
+ x = +x || 0;
736
+ y = +y || 0;
737
+ radius = +radius || 0;
738
+ this._$setBounds(x - radius, y - radius);
739
+ this._$setBounds(x + radius, y + radius);
740
+ this._$margePath($getArray(Graphics.MOVE_TO, x + radius, y, Graphics.ARC, x, y, radius));
741
+ this._$pointerX = x;
742
+ this._$pointerY = y;
743
+ // restart
744
+ this._$restart();
745
+ return this;
746
+ }
747
+ /**
748
+ * @description 楕円を描画します。
749
+ * Draws an ellipse.
750
+ *
751
+ * @param {number} x
752
+ * @param {number} y
753
+ * @param {number} width
754
+ * @param {number} height
755
+ * @return {Graphics}
756
+ * @method
757
+ * @public
758
+ */
759
+ drawEllipse(x, y, width, height) {
760
+ x = +x || 0;
761
+ y = +y || 0;
762
+ width = +width || 0;
763
+ height = +height || 0;
764
+ const hw = width / 2; // half width
765
+ const hh = height / 2; // half height
766
+ const x0 = x + hw;
767
+ const y0 = y + hh;
768
+ const x1 = x + width;
769
+ const y1 = y + height;
770
+ const c = 4 / 3 * ($Math.SQRT2 - 1);
771
+ const cw = c * hw;
772
+ const ch = c * hh;
773
+ return this
774
+ .moveTo(x0, y)
775
+ .cubicCurveTo(x0 + cw, y, x1, y0 - ch, x1, y0)
776
+ .cubicCurveTo(x1, y0 + ch, x0 + cw, y1, x0, y1)
777
+ .cubicCurveTo(x0 - cw, y1, x, y0 + ch, x, y0)
778
+ .cubicCurveTo(x, y0 - ch, x0 - cw, y, x0, y);
779
+ }
780
+ /**
781
+ * @description 矩形を描画します。
782
+ * Draws a rectangle.
783
+ *
784
+ * @param {number} x
785
+ * @param {number} y
786
+ * @param {number} width
787
+ * @param {number} height
788
+ * @return {Graphics}
789
+ * @method
790
+ * @public
791
+ */
792
+ drawRect(x, y, width, height) {
793
+ // valid
794
+ x = +x || 0;
795
+ y = +y || 0;
796
+ width = +width || 0;
797
+ height = +height || 0;
798
+ const xMax = x + width;
799
+ const yMax = y + height;
800
+ return this
801
+ .moveTo(x, y)
802
+ .lineTo(x, yMax)
803
+ .lineTo(xMax, yMax)
804
+ .lineTo(xMax, y)
805
+ .lineTo(x, y);
806
+ }
807
+ /**
808
+ * @description 角丸矩形を描画します。
809
+ * Draws a rounded rectangle.
810
+ *
811
+ * @param {number} x
812
+ * @param {number} y
813
+ * @param {number} width
814
+ * @param {number} height
815
+ * @param {number} ellipse_width
816
+ * @param {number} [ellipse_height=NaN]
817
+ * @return {Graphics}
818
+ * @method
819
+ * @public
820
+ */
821
+ drawRoundRect(x, y, width, height, ellipse_width, ellipse_height = NaN) {
822
+ x = +x || 0;
823
+ y = +y || 0;
824
+ width = +width || 0;
825
+ height = +height || 0;
826
+ ellipse_width = +ellipse_width || 0;
827
+ ellipse_height = +ellipse_height || ellipse_width;
828
+ const hew = ellipse_width / 2;
829
+ const heh = ellipse_height / 2;
830
+ const c = 4 / 3 * ($Math.SQRT2 - 1);
831
+ const cw = c * hew;
832
+ const ch = c * heh;
833
+ const dx0 = x + hew;
834
+ const dx1 = x + width;
835
+ const dx2 = dx1 - hew;
836
+ const dy0 = y + heh;
837
+ const dy1 = y + height;
838
+ const dy2 = dy1 - heh;
839
+ return this
840
+ .moveTo(dx0, y)
841
+ .lineTo(dx2, y)
842
+ .cubicCurveTo(dx2 + cw, y, dx1, dy0 - ch, dx1, dy0)
843
+ .lineTo(dx1, dy2)
844
+ .cubicCurveTo(dx1, dy2 + ch, dx2 + cw, dy1, dx2, dy1)
845
+ .lineTo(dx0, dy1)
846
+ .cubicCurveTo(dx0 - cw, dy1, x, dy2 + ch, x, dy2)
847
+ .lineTo(x, dy0)
848
+ .cubicCurveTo(x, dy0 - ch, dx0 - cw, y, dx0, y);
849
+ }
850
+ /**
851
+ * @description beginFill()、beginGradientFill()、または beginBitmapFill() メソッドへの
852
+ * 最後の呼び出し以降に追加された線と曲線に塗りを適用します。
853
+ * Applies a fill to the lines and curves that were added since
854
+ * the last call to the beginFill(), beginGradientFill(),
855
+ * or beginBitmapFill() method.
856
+ *
857
+ * @return {Graphics}
858
+ * @method
859
+ * @public
860
+ */
861
+ endFill() {
862
+ if (this._$doFill && this._$fills && this._$fills.length > 7) {
863
+ if (!this._$recode) {
864
+ this._$recode = $getArray();
865
+ }
866
+ if (this._$fills[2] !== this._$fills[this._$fills.length - 2]
867
+ || this._$fills[3] !== this._$fills[this._$fills.length - 1]) {
868
+ this._$fills.push(Graphics.LINE_TO, this._$fills[2], this._$fills[3]);
869
+ }
870
+ this._$recode.push(...this._$fills);
871
+ // fill
872
+ switch (this._$fillType) {
873
+ case Graphics.FILL_STYLE:
874
+ this._$recode.push(this._$fillType, this._$fillStyleR, this._$fillStyleG, this._$fillStyleB, this._$fillStyleA, Graphics.END_FILL);
875
+ break;
876
+ case Graphics.GRADIENT_FILL:
877
+ if (this._$fillGradient) {
878
+ this._$recode.push(this._$fillType, ...this._$fillGradient.toArray());
879
+ }
880
+ break;
881
+ case Graphics.BITMAP_FILL:
882
+ if (this._$fillBitmap) {
883
+ this._$recode.push(this._$fillType, ...this._$fillBitmap.toArray());
884
+ }
885
+ break;
886
+ }
887
+ }
888
+ if (this._$fills) {
889
+ $poolArray(this._$fills);
890
+ this._$fills = null;
891
+ }
892
+ // reset
893
+ this._$fillType = 0;
894
+ this._$fillGradient = null;
895
+ this._$fillBitmap = null;
896
+ this._$fillStyleR = 0;
897
+ this._$fillStyleG = 0;
898
+ this._$fillStyleB = 0;
899
+ this._$fillStyleA = 0;
900
+ this._$doFill = false;
901
+ // restart
902
+ this._$restart();
903
+ return this;
904
+ }
905
+ /**
906
+ * @description lineStyle()、または lineGradientStyle() メソッドへの
907
+ * 最後の呼び出し以降に追加された線と曲線に塗りを適用します。
908
+ * Applies a fill to the lines and curves that were added since
909
+ * the last call to the beginFill() or beginGradientFill() method.
910
+ *
911
+ * @return {Graphics}
912
+ * @method
913
+ * @public
914
+ */
915
+ endLine() {
916
+ if (this._$doLine && this._$lines) {
917
+ if (!this._$recode) {
918
+ this._$recode = $getArray();
919
+ }
920
+ this._$recode.push(...this._$lines);
921
+ // clear
922
+ $poolArray(this._$lines);
923
+ this._$lines = null;
924
+ // fill
925
+ switch (this._$lineType) {
926
+ case Graphics.STROKE_STYLE:
927
+ this._$recode.push(this._$lineType, this._$lineWidth, this._$caps, this._$joints, this._$miterLimit, this._$lineStyleR, this._$lineStyleG, this._$lineStyleB, this._$lineStyleA, Graphics.END_STROKE);
928
+ break;
929
+ case Graphics.GRADIENT_STROKE:
930
+ if (this._$lineGradient) {
931
+ this._$recode.push(this._$lineType, this._$lineWidth, this._$caps, this._$joints, this._$miterLimit, ...this._$lineGradient.toArray());
932
+ }
933
+ break;
934
+ case Graphics.BITMAP_STROKE:
935
+ if (this._$fillBitmap) {
936
+ this._$recode.push(this._$lineType, this._$lineWidth, this._$caps, this._$joints, this._$miterLimit, ...this._$fillBitmap.toArray());
937
+ }
938
+ break;
939
+ }
940
+ }
941
+ // reset
942
+ this._$lineType = 0;
943
+ this._$lineWidth = 0;
944
+ this._$lineGradient = null;
945
+ this._$lineStyleR = 0;
946
+ this._$lineStyleG = 0;
947
+ this._$lineStyleB = 0;
948
+ this._$lineStyleA = 0;
949
+ this._$caps = "none";
950
+ this._$joints = "round";
951
+ this._$miterLimit = 0;
952
+ this._$doLine = false;
953
+ // restart
954
+ this._$restart();
955
+ return this;
956
+ }
957
+ /**
958
+ * @description 線の描画で、線として使用するビットマップを指定します。
959
+ * Specifies a bitmap to use for the line stroke when drawing lines.
960
+ *
961
+ * @param {BitmapData} bitmap_data
962
+ * @param {Matrix} [matrix=null]
963
+ * @param {boolean} [repeat=true]
964
+ * @param {boolean} [smooth=false]
965
+ * @return {Graphics}
966
+ * @method
967
+ * @public
968
+ */
969
+ lineBitmapStyle(bitmap_data, matrix = null, repeat = true, smooth = false) {
970
+ // end fill
971
+ if (this._$doLine) {
972
+ this.endLine();
973
+ }
974
+ if (!this._$lines) {
975
+ this._$lines = $getArray();
976
+ }
977
+ // start
978
+ this._$maxAlpha = 1;
979
+ this._$doLine = true;
980
+ this._$canDraw = true;
981
+ // beginPath
982
+ this._$lines.push(Graphics.BEGIN_PATH);
983
+ this._$lineType = Graphics.BITMAP_STROKE;
984
+ this._$fillBitmap = new GraphicsBitmapFill(bitmap_data, matrix, repeat, smooth);
985
+ return this;
986
+ }
987
+ /**
988
+ * @description 線の描画で使用するグラデーションを指定します。
989
+ * Specifies a gradient to use for the stroke when drawing lines.
990
+ *
991
+ * @param {string} type
992
+ * @param {array} colors
993
+ * @param {array} alphas
994
+ * @param {array} ratios
995
+ * @param {Matrix} [matrix=null]
996
+ * @param {string} [spread_method=SpreadMethod.PAD]
997
+ * @param {string} [interpolation_method=InterpolationMethod.RGB]
998
+ * @param {number} [focal_point_ratio=0]
999
+ * @return {Graphics}
1000
+ * @method
1001
+ * @public
1002
+ */
1003
+ lineGradientStyle(type, colors, alphas, ratios, matrix = null, spread_method = "pad", interpolation_method = "rgb", focal_point_ratio = 0) {
1004
+ if (!this._$doLine) {
1005
+ return this;
1006
+ }
1007
+ if (!this._$lines) {
1008
+ this._$lines = $getArray();
1009
+ }
1010
+ // setup
1011
+ for (let idx = 0; idx < alphas.length; ++idx) {
1012
+ this._$maxAlpha = $Math.max(this._$maxAlpha, alphas[idx]);
1013
+ }
1014
+ // beginPath
1015
+ this._$lines.push(Graphics.BEGIN_PATH);
1016
+ this._$lineType = Graphics.GRADIENT_STROKE;
1017
+ this._$lineGradient = new GraphicsGradientFill(type, colors, alphas, ratios, matrix, spread_method, interpolation_method, focal_point_ratio);
1018
+ return this;
1019
+ }
1020
+ /**
1021
+ * @description lineTo() メソッドや drawCircle() メソッドなど、
1022
+ * Graphics のメソッドの後続の呼び出しに使用する線スタイルを指定します。
1023
+ * Specifies a line style used for subsequent calls
1024
+ * to Graphics methods such as the lineTo() method
1025
+ * or the drawCircle() method.
1026
+ *
1027
+ * @param {number} [thickness=NaN]
1028
+ * @param {number|string} [color=0]
1029
+ * @param {number} [alpha=1]
1030
+ * @param {string} [caps=CapsStyle.NONE]
1031
+ * @param {string} [joints=JointStyle.ROUND]
1032
+ * @param {number} [miter_limit=3]
1033
+ * @return {Graphics}
1034
+ * @method
1035
+ * @public
1036
+ */
1037
+ lineStyle(thickness = 1, color = 0, alpha = 1, caps = "round", joints = "round", miter_limit = 3) {
1038
+ if (this._$doLine) {
1039
+ this.endLine();
1040
+ }
1041
+ if (!this._$lines) {
1042
+ this._$lines = $getArray();
1043
+ }
1044
+ color = $clamp($toColorInt(color), 0, 0xffffff, 0);
1045
+ alpha = $clamp(+alpha, 0, 1, 1);
1046
+ // setup
1047
+ this._$maxAlpha = $Math.max(this._$maxAlpha, alpha);
1048
+ this._$doLine = true;
1049
+ this._$canDraw = true;
1050
+ // beginPath
1051
+ if (this._$pointerX || this._$pointerY) {
1052
+ this._$lines.push(Graphics.BEGIN_PATH, Graphics.MOVE_TO, this._$pointerX, this._$pointerY);
1053
+ }
1054
+ else {
1055
+ this._$lines.push(Graphics.BEGIN_PATH);
1056
+ }
1057
+ // add Fill Style
1058
+ const object = $intToRGBA(color, alpha);
1059
+ // color
1060
+ this._$lineType = Graphics.STROKE_STYLE;
1061
+ this._$lineStyleR = object.R;
1062
+ this._$lineStyleG = object.G;
1063
+ this._$lineStyleB = object.B;
1064
+ this._$lineStyleA = object.A;
1065
+ // param
1066
+ this._$lineWidth = thickness;
1067
+ this._$caps = `${caps}`;
1068
+ this._$joints = `${joints}`;
1069
+ // set miter limit
1070
+ if (this._$joints === "miter") {
1071
+ this._$miterLimit = miter_limit;
1072
+ }
1073
+ return this;
1074
+ }
1075
+ /**
1076
+ * @description 現在の描画位置から (x, y) まで、現在の線のスタイルを使用して線を描画します。
1077
+ * その後で、現在の描画位置は (x, y) に設定されます。
1078
+ * Draws a line using the current line style from the current drawing position to (x, y);
1079
+ * the current drawing position is then set to (x, y).
1080
+ *
1081
+ * @param {number} x
1082
+ * @param {number} y
1083
+ * @returns {Graphics}
1084
+ * @method
1085
+ * @public
1086
+ */
1087
+ lineTo(x, y) {
1088
+ x = +x || 0;
1089
+ y = +y || 0;
1090
+ if (this._$pointerX === x && this._$pointerY === y) {
1091
+ return this;
1092
+ }
1093
+ this._$setBounds(x, y);
1094
+ this._$margePath($getArray(Graphics.LINE_TO, x, y));
1095
+ this._$pointerX = x;
1096
+ this._$pointerY = y;
1097
+ // restart
1098
+ this._$restart();
1099
+ return this;
1100
+ }
1101
+ /**
1102
+ * @description 現在の描画位置を (x, y) に移動します。
1103
+ * Moves the current drawing position to (x, y).
1104
+ *
1105
+ * @param {number} x
1106
+ * @param {number} y
1107
+ * @returns {Graphics}
1108
+ * @method
1109
+ * @public
1110
+ */
1111
+ moveTo(x, y) {
1112
+ x = +x || 0;
1113
+ y = +y || 0;
1114
+ this._$pointerX = x;
1115
+ this._$pointerY = y;
1116
+ this._$setBounds(x, y);
1117
+ let duplication = false;
1118
+ if (this._$doFill && this._$fills) {
1119
+ const isMove = this._$fills[this._$fills.length - 3] === Graphics.MOVE_TO;
1120
+ if (isMove) {
1121
+ duplication = true;
1122
+ this._$fills[this._$fills.length - 2] = x;
1123
+ this._$fills[this._$fills.length - 1] = y;
1124
+ }
1125
+ }
1126
+ if (this._$doLine && this._$lines) {
1127
+ const isMove = this._$lines[this._$lines.length - 3] === Graphics.MOVE_TO;
1128
+ if (isMove) {
1129
+ duplication = true;
1130
+ this._$lines[this._$lines.length - 2] = x;
1131
+ this._$lines[this._$lines.length - 1] = y;
1132
+ }
1133
+ }
1134
+ if (!duplication) {
1135
+ this._$margePath($getArray(Graphics.MOVE_TO, x, y));
1136
+ }
1137
+ // restart
1138
+ this._$restart();
1139
+ return this;
1140
+ }
1141
+ /**
1142
+ * @param {CanvasToWebGLContext} context
1143
+ * @param {Float32Array} matrix
1144
+ * @return {void}
1145
+ * @method
1146
+ * @private
1147
+ */
1148
+ _$clip(context, matrix) {
1149
+ // size
1150
+ const baseBounds = this._$getBounds();
1151
+ const bounds = $boundsMatrix(baseBounds, matrix);
1152
+ $poolBoundsObject(baseBounds);
1153
+ const width = $Math.ceil($Math.abs(bounds.xMax - bounds.xMin));
1154
+ const height = $Math.ceil($Math.abs(bounds.yMax - bounds.yMin));
1155
+ $poolBoundsObject(bounds);
1156
+ switch (true) {
1157
+ case width === 0:
1158
+ case height === 0:
1159
+ case width === -$Infinity:
1160
+ case height === -$Infinity:
1161
+ case width === $Infinity:
1162
+ case height === $Infinity:
1163
+ return;
1164
+ default:
1165
+ break;
1166
+ }
1167
+ context.reset();
1168
+ context.setTransform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
1169
+ this._$doDraw(context, null, true);
1170
+ context.clip();
1171
+ }
1172
+ /**
1173
+ * @param {CanvasToWebGLContext} context
1174
+ * @param {Float32Array} matrix
1175
+ * @param {Float32Array} color_transform
1176
+ * @param {string} [blend_mode=BlendMode.NORMAL]
1177
+ * @param {array} [filters=null]
1178
+ * @return {void}
1179
+ * @method
1180
+ * @private
1181
+ */
1182
+ _$draw(context, matrix, color_transform, blend_mode = "normal", filters = null) {
1183
+ if (!this._$maxAlpha) {
1184
+ return;
1185
+ }
1186
+ const alpha = $clamp(color_transform[3] + color_transform[7] / 255, 0, 1);
1187
+ const displayObject = this._$displayObject;
1188
+ // set grid data
1189
+ let hasGrid = displayObject._$scale9Grid !== null;
1190
+ // 9スライスを有効にしたオブジェクトが回転・傾斜成分を含む場合は
1191
+ // 9スライスは無効になる
1192
+ const rawMatrix = displayObject._$transform._$rawMatrix();
1193
+ if (hasGrid) {
1194
+ hasGrid = hasGrid
1195
+ && $Math.abs(rawMatrix[1]) < 0.001
1196
+ && $Math.abs(rawMatrix[2]) < 0.0001;
1197
+ }
1198
+ // size
1199
+ const baseBounds = this._$getBounds();
1200
+ const bounds = $boundsMatrix(baseBounds, matrix);
1201
+ const xMax = bounds.xMax;
1202
+ const xMin = bounds.xMin;
1203
+ const yMax = bounds.yMax;
1204
+ const yMin = bounds.yMin;
1205
+ $poolBoundsObject(bounds);
1206
+ const width = $Math.ceil($Math.abs(xMax - xMin));
1207
+ const height = $Math.ceil($Math.abs(yMax - yMin));
1208
+ switch (true) {
1209
+ case width === 0:
1210
+ case height === 0:
1211
+ case width === -$Infinity:
1212
+ case height === -$Infinity:
1213
+ case width === $Infinity:
1214
+ case height === $Infinity:
1215
+ return;
1216
+ default:
1217
+ break;
1218
+ }
1219
+ // cache current buffer
1220
+ const manager = context.frameBuffer;
1221
+ const currentAttachment = manager.currentAttachment;
1222
+ if (!currentAttachment
1223
+ || xMin > currentAttachment.width
1224
+ || yMin > currentAttachment.height) {
1225
+ return;
1226
+ }
1227
+ let xScale = +$Math.sqrt(matrix[0] * matrix[0]
1228
+ + matrix[1] * matrix[1]);
1229
+ if (!$Number.isInteger(xScale)) {
1230
+ const value = xScale.toString();
1231
+ const index = value.indexOf("e");
1232
+ if (index !== -1) {
1233
+ xScale = +value.slice(0, index);
1234
+ }
1235
+ xScale = +xScale.toFixed(4);
1236
+ }
1237
+ let yScale = +$Math.sqrt(matrix[2] * matrix[2]
1238
+ + matrix[3] * matrix[3]);
1239
+ if (!$Number.isInteger(yScale)) {
1240
+ const value = yScale.toString();
1241
+ const index = value.indexOf("e");
1242
+ if (index !== -1) {
1243
+ yScale = +value.slice(0, index);
1244
+ }
1245
+ yScale = +yScale.toFixed(4);
1246
+ }
1247
+ if (0 > xMin + width || 0 > yMin + height) {
1248
+ if (filters && filters.length
1249
+ && displayObject._$canApply(filters)) {
1250
+ let filterBounds = $getBoundsObject(0, width, 0, height);
1251
+ for (let idx = 0; idx < filters.length; ++idx) {
1252
+ filterBounds = filters[idx]
1253
+ ._$generateFilterRect(filterBounds, xScale, yScale);
1254
+ }
1255
+ if (0 > filterBounds.xMin + filterBounds.xMax
1256
+ || 0 > filterBounds.yMin + filterBounds.yMax) {
1257
+ $poolBoundsObject(filterBounds);
1258
+ return;
1259
+ }
1260
+ $poolBoundsObject(filterBounds);
1261
+ }
1262
+ else {
1263
+ return;
1264
+ }
1265
+ }
1266
+ // get cache
1267
+ const keys = $getArray(xScale, yScale);
1268
+ let uniqueId = `${displayObject._$instanceId}`;
1269
+ if (!hasGrid
1270
+ && displayObject._$loaderInfo
1271
+ && displayObject._$characterId) {
1272
+ uniqueId = `${displayObject._$loaderInfo._$id}@${displayObject._$characterId}`;
1273
+ }
1274
+ const player = $currentPlayer();
1275
+ const cacheStore = player.cacheStore;
1276
+ const cacheKeys = cacheStore.generateKeys(uniqueId, keys, color_transform);
1277
+ $poolArray(keys);
1278
+ let texture = cacheStore.get(cacheKeys);
1279
+ if (!texture) {
1280
+ const currentAttachment = manager.currentAttachment;
1281
+ // resize
1282
+ let width = $Math.ceil($Math.abs(baseBounds.xMax - baseBounds.xMin) * xScale);
1283
+ let height = $Math.ceil($Math.abs(baseBounds.yMax - baseBounds.yMin) * yScale);
1284
+ const textureScale = context._$getTextureScale(width, height);
1285
+ if (textureScale < 1) {
1286
+ width *= textureScale;
1287
+ height *= textureScale;
1288
+ }
1289
+ // create cache buffer
1290
+ const attachment = manager
1291
+ .createCacheAttachment(width, height, true);
1292
+ context._$bind(attachment);
1293
+ // reset
1294
+ context.reset();
1295
+ context.setTransform(xScale, 0, 0, yScale, -baseBounds.xMin * xScale, -baseBounds.yMin * yScale);
1296
+ if (hasGrid) {
1297
+ const mScale = player.scaleX;
1298
+ const baseMatrix = $getFloat32Array6(mScale, 0, 0, mScale, 0, 0);
1299
+ const pMatrix = $multiplicationMatrix(baseMatrix, rawMatrix);
1300
+ $poolFloat32Array6(baseMatrix);
1301
+ const aMatrixBase = displayObject
1302
+ ._$parent
1303
+ ._$transform
1304
+ .concatenatedMatrix
1305
+ ._$matrix;
1306
+ $poolFloat32Array6(aMatrixBase);
1307
+ const aMatrix = $getFloat32Array6(aMatrixBase[0], aMatrixBase[1], aMatrixBase[2], aMatrixBase[3], aMatrixBase[4] * mScale - xMin, aMatrixBase[5] * mScale - yMin);
1308
+ const apMatrix = $multiplicationMatrix(aMatrix, pMatrix);
1309
+ const aOffsetX = apMatrix[4] - (matrix[4] - xMin);
1310
+ const aOffsetY = apMatrix[5] - (matrix[5] - yMin);
1311
+ $poolFloat32Array6(apMatrix);
1312
+ const parentBounds = $boundsMatrix(baseBounds, pMatrix);
1313
+ const parentXMax = +parentBounds.xMax;
1314
+ const parentXMin = +parentBounds.xMin;
1315
+ const parentYMax = +parentBounds.yMax;
1316
+ const parentYMin = +parentBounds.yMin;
1317
+ const parentWidth = $Math.ceil($Math.abs(parentXMax - parentXMin));
1318
+ const parentHeight = $Math.ceil($Math.abs(parentYMax - parentYMin));
1319
+ $poolBoundsObject(parentBounds);
1320
+ context.grid.enable(parentXMin, parentYMin, parentWidth, parentHeight, baseBounds, displayObject._$scale9Grid, mScale, pMatrix[0], pMatrix[1], pMatrix[2], pMatrix[3], pMatrix[4], pMatrix[5], aMatrix[0], aMatrix[1], aMatrix[2], aMatrix[3], aMatrix[4] - aOffsetX, aMatrix[5] - aOffsetY);
1321
+ $poolFloat32Array6(pMatrix);
1322
+ $poolFloat32Array6(aMatrix);
1323
+ }
1324
+ // plain alpha
1325
+ color_transform[3] = 1;
1326
+ this._$doDraw(context, color_transform, false);
1327
+ if (hasGrid) {
1328
+ context.grid.disable();
1329
+ }
1330
+ texture = manager.getTextureFromCurrentAttachment();
1331
+ // set cache
1332
+ cacheStore.set(cacheKeys, texture);
1333
+ // release buffer
1334
+ manager.releaseAttachment(attachment, false);
1335
+ // end draw and reset current buffer
1336
+ context._$bind(currentAttachment);
1337
+ }
1338
+ let drawFilter = false;
1339
+ let offsetX = 0;
1340
+ let offsetY = 0;
1341
+ if (filters && filters.length
1342
+ && displayObject._$canApply(filters)) {
1343
+ drawFilter = true;
1344
+ texture = displayObject._$drawFilter(context, texture, matrix, filters, width, height);
1345
+ if (texture) {
1346
+ offsetX = texture._$offsetX;
1347
+ offsetY = texture._$offsetY;
1348
+ }
1349
+ }
1350
+ const radianX = $Math.atan2(matrix[1], matrix[0]);
1351
+ const radianY = $Math.atan2(-matrix[2], matrix[3]);
1352
+ if (!drawFilter && (radianX || radianY)) {
1353
+ const tx = baseBounds.xMin * xScale;
1354
+ const ty = baseBounds.yMin * yScale;
1355
+ const cosX = $Math.cos(radianX);
1356
+ const sinX = $Math.sin(radianX);
1357
+ const cosY = $Math.cos(radianY);
1358
+ const sinY = $Math.sin(radianY);
1359
+ context.setTransform(cosX, sinX, -sinY, cosY, tx * cosX - ty * sinY + matrix[4], tx * sinX + ty * cosY + matrix[5]);
1360
+ }
1361
+ else {
1362
+ context.setTransform(1, 0, 0, 1, xMin - offsetX, yMin - offsetY);
1363
+ }
1364
+ // draw
1365
+ if (texture) {
1366
+ context.reset();
1367
+ context.globalAlpha = alpha;
1368
+ context.imageSmoothingEnabled = true;
1369
+ context.globalCompositeOperation = blend_mode;
1370
+ context.drawImage(texture, 0, 0, texture.width, texture.height, color_transform);
1371
+ }
1372
+ // pool
1373
+ $poolArray(cacheKeys);
1374
+ $poolBoundsObject(baseBounds);
1375
+ }
1376
+ /**
1377
+ * @param {CanvasToWebGLContext} context
1378
+ * @param {Float32Array} [color_transform=null]
1379
+ * @param {boolean} [is_clip=false]
1380
+ * @return {void}
1381
+ * @method
1382
+ * @private
1383
+ */
1384
+ _$doDraw(context, color_transform = null, is_clip = false) {
1385
+ // draw
1386
+ context.reset();
1387
+ context.beginPath();
1388
+ this._$runCommand(context, color_transform, is_clip);
1389
+ }
1390
+ /**
1391
+ * @param {CanvasRenderingContext2D} context
1392
+ * @param {Float32Array} matrix
1393
+ * @param {object} options
1394
+ * @param {boolean} [is_clip=false]
1395
+ * @return {boolean}
1396
+ * @method
1397
+ * @private
1398
+ */
1399
+ _$hit(context, matrix, options, is_clip = false) {
1400
+ context.beginPath();
1401
+ context.setTransform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
1402
+ return this._$runCommand(context, null, is_clip, options);
1403
+ }
1404
+ /**
1405
+ * @return {object}
1406
+ * @method
1407
+ * @private
1408
+ */
1409
+ _$getBounds() {
1410
+ const displayObject = this._$displayObject;
1411
+ if (displayObject && displayObject._$bounds) {
1412
+ return $getBoundsObject(displayObject._$bounds.xMin, displayObject._$bounds.xMax, displayObject._$bounds.yMin, displayObject._$bounds.yMax);
1413
+ }
1414
+ return $getBoundsObject(this._$xMin, this._$xMax, this._$yMin, this._$yMax);
1415
+ }
1416
+ /**
1417
+ * @return {void}
1418
+ * @method
1419
+ * @private
1420
+ */
1421
+ _$restart() {
1422
+ if (this._$displayObject) {
1423
+ this._$displayObject._$posted = false;
1424
+ this._$buffer = null;
1425
+ if (!this._$displayObject._$isUpdated()) {
1426
+ this._$displayObject._$doChanged();
1427
+ $doUpdated();
1428
+ const player = $currentPlayer();
1429
+ const cacheStore = player.cacheStore;
1430
+ cacheStore.removeCache(this._$displayObject._$instanceId);
1431
+ if (this._$displayObject._$characterId) {
1432
+ cacheStore.removeCache(this._$displayObject._$characterId);
1433
+ }
1434
+ }
1435
+ }
1436
+ }
1437
+ /**
1438
+ * @param {number} [x=0]
1439
+ * @param {number} [y=0]
1440
+ * @return {void}
1441
+ * @method
1442
+ * @private
1443
+ */
1444
+ _$setBounds(x = 0, y = 0) {
1445
+ this._$setFillBounds(x, y);
1446
+ if (this._$doLine) {
1447
+ this._$setLineBounds(x, y);
1448
+ }
1449
+ }
1450
+ /**
1451
+ * @param {number} x
1452
+ * @param {number} y
1453
+ * @return {void}
1454
+ * @method
1455
+ * @private
1456
+ */
1457
+ _$setFillBounds(x = 0, y = 0) {
1458
+ this._$xMin = $Math.min(this._$xMin, x);
1459
+ this._$xMax = $Math.max(this._$xMax, x);
1460
+ this._$yMin = $Math.min(this._$yMin, y);
1461
+ this._$yMax = $Math.max(this._$yMax, y);
1462
+ }
1463
+ /**
1464
+ * @param {number} x
1465
+ * @param {number} y
1466
+ * @return {void}
1467
+ * @method
1468
+ * @private
1469
+ */
1470
+ _$setLineBounds(x = 0, y = 0) {
1471
+ this._$xMin = $Math.min(this._$xMin, $Math.min(x, this._$pointerX));
1472
+ this._$xMax = $Math.max(this._$xMax, $Math.max(x, this._$pointerX));
1473
+ this._$yMin = $Math.min(this._$yMin, $Math.min(y, this._$pointerY));
1474
+ this._$yMax = $Math.max(this._$yMax, $Math.max(y, this._$pointerY));
1475
+ // correction
1476
+ const half = this._$lineWidth / 2;
1477
+ const radian90 = 0.5 * $Math.PI;
1478
+ const radian1 = $Math.atan2(y - this._$pointerY, x - this._$pointerX); // to end point
1479
+ const radian2 = $Math.atan2(this._$pointerY - y, this._$pointerX - x); // to start point
1480
+ const radian3 = radian1 + radian90;
1481
+ const radian4 = radian1 - radian90;
1482
+ const radian5 = radian2 + radian90;
1483
+ const radian6 = radian2 - radian90;
1484
+ // init
1485
+ let x1 = x + half;
1486
+ let x2 = -half + x;
1487
+ let x3 = this._$pointerX + half;
1488
+ let x4 = -half + this._$pointerX;
1489
+ let y1 = y + half;
1490
+ let y2 = -half + y;
1491
+ let y3 = this._$pointerY + half;
1492
+ let y4 = -half + this._$pointerY;
1493
+ this._$xMin = $Math.min(this._$xMin, $Math.min(x1, $Math.min(x2, $Math.min(x3, x4))));
1494
+ this._$xMax = $Math.max(this._$xMax, $Math.max(x1, $Math.max(x2, $Math.max(x3, x4))));
1495
+ this._$yMin = $Math.min(this._$yMin, $Math.min(y1, $Math.min(y2, $Math.min(y3, y4))));
1496
+ this._$yMax = $Math.max(this._$yMax, $Math.max(y1, $Math.max(y2, $Math.max(y3, y4))));
1497
+ // pointer x
1498
+ if ($Math.abs(radian3) % radian90 !== 0) {
1499
+ x1 = x + $Math.cos(radian3) * half;
1500
+ }
1501
+ if ($Math.abs(radian4) % radian90 !== 0) {
1502
+ x2 = x + $Math.cos(radian4) * half;
1503
+ }
1504
+ if ($Math.abs(radian5) % radian90 !== 0) {
1505
+ x3 = this._$pointerX + $Math.cos(radian5) * half;
1506
+ }
1507
+ if ($Math.abs(radian6) % radian90 !== 0) {
1508
+ x4 = this._$pointerX + $Math.cos(radian6) * half;
1509
+ }
1510
+ // pointer y
1511
+ if (radian3 && $Math.abs(radian3) % $Math.PI !== 0) {
1512
+ y1 = y + $Math.sin(radian3) * half;
1513
+ }
1514
+ if (radian4 && $Math.abs(radian4) % $Math.PI !== 0) {
1515
+ y2 = y + $Math.sin(radian4) * half;
1516
+ }
1517
+ if (radian5 && $Math.abs(radian5) % $Math.PI !== 0) {
1518
+ y3 = this._$pointerY + $Math.sin(radian5) * half;
1519
+ }
1520
+ if (radian6 && $Math.abs(radian6) % $Math.PI !== 0) {
1521
+ y4 = this._$pointerY + $Math.sin(radian6) * half;
1522
+ }
1523
+ this._$xMin = $Math.min(this._$xMin, $Math.min(x1, $Math.min(x2, $Math.min(x3, x4))));
1524
+ this._$xMax = $Math.max(this._$xMax, $Math.max(x1, $Math.max(x2, $Math.max(x3, x4))));
1525
+ this._$yMin = $Math.min(this._$yMin, $Math.min(y1, $Math.min(y2, $Math.min(y3, y4))));
1526
+ this._$yMax = $Math.max(this._$yMax, $Math.max(y1, $Math.max(y2, $Math.max(y3, y4))));
1527
+ // case
1528
+ switch (this._$caps) {
1529
+ case "round":
1530
+ if ($Math.abs(radian1) % radian90 !== 0) {
1531
+ const rx1 = x + $Math.cos(radian1) * half;
1532
+ this._$xMin = $Math.min(this._$xMin, rx1);
1533
+ this._$xMax = $Math.max(this._$xMax, rx1);
1534
+ }
1535
+ if (radian1 && $Math.abs(radian1) % $Math.PI !== 0) {
1536
+ const ry1 = y + $Math.sin(radian1) * half;
1537
+ this._$yMin = $Math.min(this._$yMin, ry1);
1538
+ this._$yMax = $Math.max(this._$yMax, ry1);
1539
+ }
1540
+ if ($Math.abs(radian2) % radian90 !== 0) {
1541
+ const rx2 = this._$pointerX + $Math.cos(radian2) * half;
1542
+ this._$xMin = $Math.min(this._$xMin, rx2);
1543
+ this._$xMax = $Math.max(this._$xMax, rx2);
1544
+ }
1545
+ if (radian2 && $Math.abs(radian2) % $Math.PI !== 0) {
1546
+ const ry2 = this._$pointerY + $Math.sin(radian2) * half;
1547
+ this._$yMin = $Math.min(this._$yMin, ry2);
1548
+ this._$yMax = $Math.max(this._$yMax, ry2);
1549
+ }
1550
+ break;
1551
+ case "square":
1552
+ if ($Math.abs(radian1) % radian90 !== 0) {
1553
+ const r1cos = $Math.cos(radian1) * half;
1554
+ const rx1 = x1 + r1cos;
1555
+ const rx2 = x2 + r1cos;
1556
+ this._$xMin = $Math.min(this._$xMin, $Math.min(rx1, rx2));
1557
+ this._$xMax = $Math.max(this._$xMax, $Math.max(rx1, rx2));
1558
+ }
1559
+ if ($Math.abs(radian2) % radian90 !== 0) {
1560
+ const r2cos = $Math.cos(radian2) * half;
1561
+ const rx3 = x3 + r2cos;
1562
+ const rx4 = x4 + r2cos;
1563
+ this._$xMin = $Math.min(this._$xMin, $Math.min(rx3, rx4));
1564
+ this._$xMax = $Math.max(this._$xMax, $Math.max(rx3, rx4));
1565
+ }
1566
+ if (radian1 && $Math.abs(radian1) % $Math.PI !== 0) {
1567
+ const r1sin = $Math.sin(radian1) * half;
1568
+ const ry1 = y1 + r1sin;
1569
+ const ry2 = y2 + r1sin;
1570
+ this._$yMin = $Math.min(this._$yMin, $Math.min(ry1, ry2));
1571
+ this._$yMax = $Math.max(this._$yMax, $Math.max(ry1, ry2));
1572
+ }
1573
+ if (radian2 && $Math.abs(radian2) % $Math.PI !== 0) {
1574
+ const r2sin = $Math.sin(radian2) * half;
1575
+ const ry3 = y3 + r2sin;
1576
+ const ry4 = y4 + r2sin;
1577
+ this._$yMin = $Math.min(this._$yMin, $Math.min(ry3, ry4));
1578
+ this._$yMax = $Math.max(this._$yMax, $Math.max(ry3, ry4));
1579
+ }
1580
+ break;
1581
+ default:
1582
+ break;
1583
+ }
1584
+ }
1585
+ /**
1586
+ * @param {array} data
1587
+ * @method
1588
+ * @private
1589
+ */
1590
+ _$margePath(data) {
1591
+ if (this._$doFill && this._$fills) {
1592
+ this._$fills.push(...data);
1593
+ }
1594
+ if (this._$doLine && this._$lines) {
1595
+ this._$lines.push(...data);
1596
+ }
1597
+ $poolArray(data);
1598
+ }
1599
+ /**
1600
+ * @return {Float32Array}
1601
+ * @method
1602
+ * @private
1603
+ */
1604
+ _$getRecodes() {
1605
+ // fixed logic
1606
+ if (this._$doLine) {
1607
+ this.endLine();
1608
+ }
1609
+ // fixed logic
1610
+ if (this._$doFill) {
1611
+ this.endFill();
1612
+ }
1613
+ if (!this._$recode) {
1614
+ this._$recode = $getArray();
1615
+ }
1616
+ if (!this._$buffer) {
1617
+ const array = $getArray();
1618
+ const recode = this._$recode;
1619
+ for (let idx = 0; idx < recode.length;) {
1620
+ const type = recode[idx++];
1621
+ array.push(type);
1622
+ switch (type) {
1623
+ case Graphics.BEGIN_PATH:
1624
+ case Graphics.END_FILL:
1625
+ case Graphics.END_STROKE:
1626
+ case Graphics.CLOSE_PATH:
1627
+ break;
1628
+ case Graphics.MOVE_TO:
1629
+ case Graphics.LINE_TO:
1630
+ array.push(recode[idx++], recode[idx++]);
1631
+ break;
1632
+ case Graphics.CURVE_TO:
1633
+ case Graphics.FILL_STYLE:
1634
+ array.push(recode[idx++], recode[idx++], recode[idx++], recode[idx++]);
1635
+ break;
1636
+ case Graphics.CUBIC:
1637
+ array.push(recode[idx++], recode[idx++], recode[idx++], recode[idx++], recode[idx++], recode[idx++]);
1638
+ break;
1639
+ case Graphics.STROKE_STYLE:
1640
+ {
1641
+ array.push(recode[idx++]);
1642
+ const lineCap = recode[idx++];
1643
+ switch (lineCap) {
1644
+ case "none":
1645
+ array.push(0);
1646
+ break;
1647
+ case "round":
1648
+ array.push(1);
1649
+ break;
1650
+ case "square":
1651
+ array.push(2);
1652
+ break;
1653
+ }
1654
+ const lineJoin = recode[idx++];
1655
+ switch (lineJoin) {
1656
+ case "bevel":
1657
+ array.push(0);
1658
+ break;
1659
+ case "miter":
1660
+ array.push(1);
1661
+ break;
1662
+ case "round":
1663
+ array.push(2);
1664
+ break;
1665
+ }
1666
+ array.push(recode[idx++], // MITER LIMIT
1667
+ recode[idx++], recode[idx++], recode[idx++], recode[idx++]);
1668
+ }
1669
+ break;
1670
+ case Graphics.ARC:
1671
+ array.push(recode[idx++], recode[idx++], recode[idx++]);
1672
+ break;
1673
+ case Graphics.GRADIENT_FILL:
1674
+ {
1675
+ const type = recode[idx++];
1676
+ const stops = recode[idx++];
1677
+ const matrix = recode[idx++];
1678
+ const spread = recode[idx++];
1679
+ const interpolation = recode[idx++];
1680
+ const focal = recode[idx++];
1681
+ array.push(type === "linear" ? 0 : 1);
1682
+ array.push(stops.length);
1683
+ for (let idx = 0; idx < stops.length; ++idx) {
1684
+ const color = stops[idx];
1685
+ array.push(color.ratio, color.R, color.G, color.B, color.A);
1686
+ }
1687
+ array.push(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
1688
+ switch (spread) {
1689
+ case "reflect":
1690
+ array.push(0);
1691
+ break;
1692
+ case "repeat":
1693
+ array.push(1);
1694
+ break;
1695
+ default:
1696
+ array.push(2);
1697
+ break;
1698
+ }
1699
+ array.push(interpolation === "linearRGB" ? 0 : 1);
1700
+ array.push(focal);
1701
+ }
1702
+ break;
1703
+ case Graphics.GRADIENT_STROKE:
1704
+ {
1705
+ array.push(recode[idx++]);
1706
+ const lineCap = recode[idx++];
1707
+ switch (lineCap) {
1708
+ case "none":
1709
+ array.push(0);
1710
+ break;
1711
+ case "round":
1712
+ array.push(1);
1713
+ break;
1714
+ case "square":
1715
+ array.push(2);
1716
+ break;
1717
+ }
1718
+ const lineJoin = recode[idx++];
1719
+ switch (lineJoin) {
1720
+ case "bevel":
1721
+ array.push(0);
1722
+ break;
1723
+ case "miter":
1724
+ array.push(1);
1725
+ break;
1726
+ case "round":
1727
+ array.push(2);
1728
+ break;
1729
+ }
1730
+ // miterLimit
1731
+ array.push(recode[idx++]);
1732
+ const type = recode[idx++];
1733
+ const stops = recode[idx++];
1734
+ const matrix = recode[idx++];
1735
+ const spread = recode[idx++];
1736
+ const interpolation = recode[idx++];
1737
+ const focal = recode[idx++];
1738
+ array.push(type === "linear" ? 0 : 1);
1739
+ array.push(stops.length);
1740
+ for (let idx = 0; idx < stops.length; ++idx) {
1741
+ const color = stops[idx];
1742
+ array.push(color.ratio, color.R, color.G, color.B, color.A);
1743
+ }
1744
+ array.push(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
1745
+ switch (spread) {
1746
+ case "reflect":
1747
+ array.push(0);
1748
+ break;
1749
+ case "repeat":
1750
+ array.push(1);
1751
+ break;
1752
+ default:
1753
+ array.push(2);
1754
+ break;
1755
+ }
1756
+ array.push(interpolation === "linearRGB" ? 0 : 1);
1757
+ array.push(focal);
1758
+ }
1759
+ break;
1760
+ case Graphics.BITMAP_FILL:
1761
+ {
1762
+ const bitmapData = recode[idx++];
1763
+ let buffer;
1764
+ if (bitmapData.image !== null || bitmapData.canvas !== null) {
1765
+ const player = $currentPlayer();
1766
+ const cacheStore = player.cacheStore;
1767
+ const canvas = cacheStore.getCanvas();
1768
+ const width = bitmapData.width;
1769
+ const height = bitmapData.height;
1770
+ canvas.width = width;
1771
+ canvas.height = height;
1772
+ const context = canvas.getContext("2d");
1773
+ if (!context) {
1774
+ throw new Error("the context is null.");
1775
+ }
1776
+ // @ts-ignore
1777
+ context.drawImage(bitmapData.image || bitmapData.canvas, 0, 0);
1778
+ buffer = new Uint8Array(context.getImageData(0, 0, width, height).data);
1779
+ cacheStore.destroy(context);
1780
+ }
1781
+ else if (bitmapData._$buffer !== null) {
1782
+ buffer = bitmapData._$buffer;
1783
+ }
1784
+ else {
1785
+ break;
1786
+ }
1787
+ array.push(bitmapData.width, bitmapData.height, this._$xMax - this._$xMin, this._$yMax - this._$yMin, buffer.length);
1788
+ for (let idx = 0; idx < buffer.length; ++idx) {
1789
+ array.push(buffer[idx]);
1790
+ }
1791
+ const matrix = recode[idx++];
1792
+ if (matrix) {
1793
+ array.push(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
1794
+ }
1795
+ else {
1796
+ array.push(1, 0, 0, 1, 0, 0);
1797
+ }
1798
+ const repeat = recode[idx++];
1799
+ array.push(repeat ? 1 : 0);
1800
+ const smooth = recode[idx++];
1801
+ array.push(smooth ? 1 : 0);
1802
+ }
1803
+ break;
1804
+ case Graphics.BITMAP_STROKE:
1805
+ {
1806
+ array.push(recode[idx++]);
1807
+ const lineCap = recode[idx++];
1808
+ switch (lineCap) {
1809
+ case "none":
1810
+ array.push(0);
1811
+ break;
1812
+ case "round":
1813
+ array.push(1);
1814
+ break;
1815
+ case "square":
1816
+ array.push(2);
1817
+ break;
1818
+ }
1819
+ const lineJoin = recode[idx++];
1820
+ switch (lineJoin) {
1821
+ case "bevel":
1822
+ array.push(0);
1823
+ break;
1824
+ case "miter":
1825
+ array.push(1);
1826
+ break;
1827
+ case "round":
1828
+ array.push(2);
1829
+ break;
1830
+ }
1831
+ // MITER LIMIT
1832
+ array.push(recode[idx++]);
1833
+ const bitmapData = recode[idx++];
1834
+ let buffer;
1835
+ if (bitmapData.image !== null || bitmapData.canvas !== null) {
1836
+ const player = $currentPlayer();
1837
+ const cacheStore = player.cacheStore;
1838
+ const canvas = cacheStore.getCanvas();
1839
+ const width = bitmapData.width;
1840
+ const height = bitmapData.height;
1841
+ canvas.width = width;
1842
+ canvas.height = height;
1843
+ const context = canvas.getContext("2d");
1844
+ if (!context) {
1845
+ throw new Error("the context is null.");
1846
+ }
1847
+ // @ts-ignore
1848
+ context.drawImage(bitmapData.image || bitmapData.canvas, 0, 0);
1849
+ buffer = new Uint8Array(context.getImageData(0, 0, width, height).data);
1850
+ cacheStore.destroy(context);
1851
+ }
1852
+ else if (bitmapData._$buffer !== null) {
1853
+ buffer = bitmapData._$buffer;
1854
+ }
1855
+ else {
1856
+ break;
1857
+ }
1858
+ array.push(bitmapData.width, bitmapData.height, this._$xMax - this._$xMin, this._$yMax - this._$yMin, buffer.length);
1859
+ for (let idx = 0; idx < buffer.length; ++idx) {
1860
+ array.push(buffer[idx]);
1861
+ }
1862
+ const matrix = recode[idx++];
1863
+ if (matrix) {
1864
+ array.push(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
1865
+ }
1866
+ else {
1867
+ array.push(1, 0, 0, 1, 0, 0);
1868
+ }
1869
+ const repeat = recode[idx++];
1870
+ array.push(repeat ? 1 : 0);
1871
+ const smooth = recode[idx++];
1872
+ array.push(smooth ? 1 : 0);
1873
+ }
1874
+ break;
1875
+ default:
1876
+ break;
1877
+ }
1878
+ }
1879
+ this._$buffer = new $Float32Array(array);
1880
+ }
1881
+ return this._$buffer.slice();
1882
+ }
1883
+ /**
1884
+ * @param {CanvasToWebGLContext|CanvasRenderingContext2D} context
1885
+ * @param {Float32Array} [color_transform=null]
1886
+ * @param {boolean} [is_clip=false]
1887
+ * @param {object} [options=null]
1888
+ * @return {boolean}
1889
+ * @method
1890
+ * @private
1891
+ */
1892
+ _$runCommand(context, color_transform = null, is_clip = false, options = null) {
1893
+ // fixed logic
1894
+ if (this._$doLine) {
1895
+ this.endLine();
1896
+ }
1897
+ // fixed logic
1898
+ if (this._$doFill) {
1899
+ this.endFill();
1900
+ }
1901
+ if (!this._$recode) {
1902
+ return false;
1903
+ }
1904
+ const recode = this._$recode;
1905
+ const length = recode.length;
1906
+ for (let idx = 0; idx < length;) {
1907
+ switch (recode[idx++]) {
1908
+ case Graphics.BEGIN_PATH:
1909
+ context.beginPath();
1910
+ break;
1911
+ case Graphics.MOVE_TO:
1912
+ context.moveTo(recode[idx++], recode[idx++]);
1913
+ break;
1914
+ case Graphics.LINE_TO:
1915
+ context.lineTo(recode[idx++], recode[idx++]);
1916
+ break;
1917
+ case Graphics.CURVE_TO:
1918
+ context.quadraticCurveTo(recode[idx++], recode[idx++], recode[idx++], recode[idx++]);
1919
+ break;
1920
+ case Graphics.FILL_STYLE:
1921
+ {
1922
+ if (is_clip || options) {
1923
+ idx += 4;
1924
+ continue;
1925
+ }
1926
+ const color = $getFloat32Array4();
1927
+ color[0] = recode[idx++] / 255;
1928
+ color[1] = recode[idx++] / 255;
1929
+ color[2] = recode[idx++] / 255;
1930
+ color[3] = recode[idx++] / 255;
1931
+ if (color_transform !== null) {
1932
+ if (color_transform[3] !== 1 || color_transform[7] !== 0) {
1933
+ color[3] = $Math.max(0, $Math.min(color[3] * color_transform[3] + color_transform[7], 255)) / 255;
1934
+ }
1935
+ }
1936
+ context.fillStyle = color;
1937
+ }
1938
+ break;
1939
+ case Graphics.END_FILL:
1940
+ if (options && "isPointInPath" in context
1941
+ && context.isPointInPath(options.x, options.y)) {
1942
+ return true;
1943
+ }
1944
+ if (!is_clip && !options) {
1945
+ context.fill();
1946
+ }
1947
+ break;
1948
+ case Graphics.STROKE_STYLE:
1949
+ {
1950
+ if (is_clip || options) {
1951
+ idx += 8;
1952
+ continue;
1953
+ }
1954
+ context.lineWidth = recode[idx++];
1955
+ context.lineCap = recode[idx++];
1956
+ context.lineJoin = recode[idx++];
1957
+ context.miterLimit = recode[idx++];
1958
+ const color = $getFloat32Array4();
1959
+ color[0] = recode[idx++] / 255;
1960
+ color[1] = recode[idx++] / 255;
1961
+ color[2] = recode[idx++] / 255;
1962
+ color[3] = recode[idx++] / 255;
1963
+ if (color_transform !== null) {
1964
+ if (color_transform[3] !== 1 || color_transform[7] !== 0) {
1965
+ color[3] = $Math.max(0, $Math.min(color[3] * color_transform[3] + color_transform[7], 255)) / 255;
1966
+ }
1967
+ }
1968
+ context.strokeStyle = color;
1969
+ }
1970
+ break;
1971
+ case Graphics.END_STROKE:
1972
+ if (options && "isPointInStroke" in context
1973
+ && context.isPointInStroke(options.x, options.y)) {
1974
+ return true;
1975
+ }
1976
+ if (!is_clip && !options) {
1977
+ context.stroke();
1978
+ }
1979
+ break;
1980
+ case Graphics.CLOSE_PATH:
1981
+ context.closePath();
1982
+ break;
1983
+ case Graphics.CUBIC:
1984
+ context.bezierCurveTo(recode[idx++], recode[idx++], recode[idx++], recode[idx++], recode[idx++], recode[idx++]);
1985
+ break;
1986
+ case Graphics.ARC:
1987
+ context.arc(recode[idx++], recode[idx++], recode[idx++], 0, 2 * $Math.PI);
1988
+ break;
1989
+ case Graphics.GRADIENT_FILL:
1990
+ {
1991
+ if (options && "isPointInPath" in context
1992
+ && context.isPointInPath(options.x, options.y)) {
1993
+ return true;
1994
+ }
1995
+ if (is_clip || options
1996
+ || context instanceof CanvasRenderingContext2D // fixed logic
1997
+ ) {
1998
+ idx += 6;
1999
+ continue;
2000
+ }
2001
+ const type = recode[idx++];
2002
+ const stops = recode[idx++];
2003
+ const matrix = recode[idx++];
2004
+ const spread = recode[idx++];
2005
+ const interpolation = recode[idx++];
2006
+ const focal = recode[idx++];
2007
+ let css;
2008
+ if (type === "linear") {
2009
+ const xy = $linearGradientXY(matrix);
2010
+ css = context.createLinearGradient(xy[0], xy[1], xy[2], xy[3], interpolation, spread);
2011
+ }
2012
+ else {
2013
+ context.save();
2014
+ context.transform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
2015
+ css = context.createRadialGradient(0, 0, 0, 0, 0, 819.2, interpolation, spread, focal);
2016
+ }
2017
+ for (let idx = 0; idx < stops.length; ++idx) {
2018
+ const color = stops[idx];
2019
+ let alpha = color.A;
2020
+ if (color_transform) {
2021
+ if (color_transform[3] !== 1 || color_transform[7] !== 0) {
2022
+ alpha = $Math.max(0, $Math.min(color.A * color_transform[3] + color_transform[7], 255)) | 0;
2023
+ }
2024
+ }
2025
+ css.addColorStop(color.ratio, $getFloat32Array4(color.R, color.G, color.B, alpha));
2026
+ }
2027
+ context.fillStyle = css;
2028
+ context.fill();
2029
+ if (type === "radial") {
2030
+ context.restore();
2031
+ }
2032
+ }
2033
+ break;
2034
+ case Graphics.GRADIENT_STROKE:
2035
+ {
2036
+ if (options && "isPointInStroke" in context
2037
+ && context.isPointInStroke(options.x, options.y)) {
2038
+ return true;
2039
+ }
2040
+ if (is_clip || options
2041
+ || context instanceof CanvasRenderingContext2D // fixed logic
2042
+ ) {
2043
+ idx += 12;
2044
+ continue;
2045
+ }
2046
+ context.lineWidth = recode[idx++];
2047
+ context.lineCap = recode[idx++];
2048
+ context.lineJoin = recode[idx++];
2049
+ context.miterLimit = recode[idx++];
2050
+ const type = recode[idx++];
2051
+ const stops = recode[idx++];
2052
+ const matrix = recode[idx++];
2053
+ const spread = recode[idx++];
2054
+ const interpolation = recode[idx++];
2055
+ const focal = recode[idx++];
2056
+ let css;
2057
+ if (type === "linear") {
2058
+ const xy = $linearGradientXY(matrix);
2059
+ css = context.createLinearGradient(xy[0], xy[1], xy[2], xy[3], interpolation, spread);
2060
+ }
2061
+ else {
2062
+ context.save();
2063
+ context.transform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
2064
+ css = context.createRadialGradient(0, 0, 0, 0, 0, 819.2, interpolation, spread, focal);
2065
+ }
2066
+ for (let idx = 0; idx < stops.length; ++idx) {
2067
+ const color = stops[idx];
2068
+ let alpha = color.A;
2069
+ if (color_transform) {
2070
+ if (color_transform[3] !== 1 || color_transform[7] !== 0) {
2071
+ alpha = $Math.max(0, $Math.min(color.A * color_transform[3] + color_transform[7], 255)) | 0;
2072
+ }
2073
+ }
2074
+ css.addColorStop(color.ratio, $getFloat32Array4(color.R, color.G, color.B, alpha));
2075
+ }
2076
+ context.strokeStyle = css;
2077
+ context.stroke();
2078
+ if (type === "radial") {
2079
+ context.restore();
2080
+ }
2081
+ }
2082
+ break;
2083
+ case Graphics.BITMAP_FILL:
2084
+ {
2085
+ if (options && "isPointInPath" in context
2086
+ && context.isPointInPath(options.x, options.y)) {
2087
+ return true;
2088
+ }
2089
+ if (is_clip || options
2090
+ || context instanceof CanvasRenderingContext2D // fixed logic
2091
+ ) {
2092
+ idx += 6;
2093
+ continue;
2094
+ }
2095
+ context.save();
2096
+ const bitmapData = recode[idx++];
2097
+ const matrix = recode[idx++];
2098
+ const repeat = recode[idx++];
2099
+ const smooth = recode[idx++];
2100
+ if (matrix) {
2101
+ context.transform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
2102
+ }
2103
+ const texture = bitmapData.getTexture();
2104
+ if (!texture || !color_transform) {
2105
+ break;
2106
+ }
2107
+ if (!repeat
2108
+ && bitmapData.width === this._$xMax - this._$xMin
2109
+ && bitmapData.height === this._$yMax - this._$yMin) {
2110
+ context.drawImage(texture, 0, 0, bitmapData.width, bitmapData.height);
2111
+ }
2112
+ else {
2113
+ context.fillStyle = context.createPattern(texture, repeat, color_transform);
2114
+ context.imageSmoothingEnabled = smooth;
2115
+ context.fill();
2116
+ }
2117
+ // restore
2118
+ context.restore();
2119
+ context.imageSmoothingEnabled = false;
2120
+ }
2121
+ break;
2122
+ case Graphics.BITMAP_STROKE:
2123
+ {
2124
+ if (options && "isPointInStroke" in context
2125
+ && context.isPointInStroke(options.x, options.y)) {
2126
+ return true;
2127
+ }
2128
+ if (is_clip || options
2129
+ || context instanceof CanvasRenderingContext2D // fixed logic
2130
+ ) {
2131
+ idx += 9;
2132
+ continue;
2133
+ }
2134
+ context.save();
2135
+ context.lineWidth = recode[idx++];
2136
+ context.lineCap = recode[idx++];
2137
+ context.lineJoin = recode[idx++];
2138
+ context.miterLimit = recode[idx++];
2139
+ const bitmapData = recode[idx++];
2140
+ const matrix = recode[idx++];
2141
+ const repeat = recode[idx++];
2142
+ const smooth = recode[idx++];
2143
+ if (matrix) {
2144
+ context.transform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
2145
+ }
2146
+ const texture = bitmapData.getTexture();
2147
+ if (!texture || !color_transform) {
2148
+ break;
2149
+ }
2150
+ context.strokeStyle = context.createPattern(texture, repeat, color_transform);
2151
+ context.imageSmoothingEnabled = smooth;
2152
+ context.stroke();
2153
+ // restore
2154
+ context.restore();
2155
+ context.imageSmoothingEnabled = false;
2156
+ }
2157
+ break;
2158
+ default:
2159
+ break;
2160
+ }
2161
+ }
2162
+ return false;
2163
+ }
2164
+ }