@next2d/text 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.
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/dist/TextField.d.ts +635 -0
- package/dist/TextField.js +2661 -0
- package/dist/TextFormat.d.ts +250 -0
- package/dist/TextFormat.js +460 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/package.json +43 -0
|
@@ -0,0 +1,2661 @@
|
|
|
1
|
+
import { TextFormat } from "./TextFormat";
|
|
2
|
+
import { InteractiveObject, Sprite } from "@next2d/display";
|
|
3
|
+
import { FocusEvent, Event as Next2DEvent, MouseEvent as Next2DMouseEvent } from "@next2d/events";
|
|
4
|
+
import { Tween } from "@next2d/ui";
|
|
5
|
+
import { Rectangle } from "@next2d/geom";
|
|
6
|
+
import { $currentPlayer, $DIV, $isSafari, $MOUSE_DOWN, $MOUSE_UP, $MOUSE_WHEEL, $P_TAG, $PREFIX, $rendererWorker, $SCROLL, $textContext, $TOUCH_END, $TOUCH_START, $devicePixelRatio, $document, $RegExp } from "@next2d/util";
|
|
7
|
+
import { $doUpdated, $clamp, $getArray, $intToRGBA, $isNaN, $Math, $requestAnimationFrame, $toColorInt, $getMap, $poolFloat32Array6, $boundsMatrix, $multiplicationMatrix, $poolBoundsObject, $multiplicationColor, $Infinity, $Number, $poolArray, $poolFloat32Array8, $generateFontStyle, $getBoundsObject } from "@next2d/share";
|
|
8
|
+
/**
|
|
9
|
+
* TextField クラスは、テキストの表示と入力用の表示オブジェクトを作成するために使用されます。
|
|
10
|
+
* プロパティインスペクターを使用して、テキストフィールドにインスタンス名を付けることができます。
|
|
11
|
+
* また、TextField クラスのメソッドとプロパティを使用して、JavaScript でテキストフィールドを操作できます。
|
|
12
|
+
*
|
|
13
|
+
* The TextField class is used to create display objects for text display and input.
|
|
14
|
+
* You can give a text field an instance name in the Property inspector
|
|
15
|
+
* and use the methods and properties of the TextField class to manipulate it with JavaScript.
|
|
16
|
+
*
|
|
17
|
+
* @class
|
|
18
|
+
* @memberOf next2d.text
|
|
19
|
+
* @extends InteractiveObject
|
|
20
|
+
*/
|
|
21
|
+
export class TextField extends InteractiveObject {
|
|
22
|
+
/**
|
|
23
|
+
* @constructor
|
|
24
|
+
* @public
|
|
25
|
+
*/
|
|
26
|
+
constructor() {
|
|
27
|
+
super();
|
|
28
|
+
/**
|
|
29
|
+
* @type {boolean}
|
|
30
|
+
* @default false
|
|
31
|
+
* @private
|
|
32
|
+
*/
|
|
33
|
+
this._$background = false;
|
|
34
|
+
/**
|
|
35
|
+
* @type {number}
|
|
36
|
+
* @default 0xffffff
|
|
37
|
+
* @private
|
|
38
|
+
*/
|
|
39
|
+
this._$backgroundColor = 0xffffff;
|
|
40
|
+
/**
|
|
41
|
+
* @type {boolean}
|
|
42
|
+
* @default false
|
|
43
|
+
* @private
|
|
44
|
+
*/
|
|
45
|
+
this._$border = false;
|
|
46
|
+
/**
|
|
47
|
+
* @type {number}
|
|
48
|
+
* @default 0x000000
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
51
|
+
this._$borderColor = 0x000000;
|
|
52
|
+
/**
|
|
53
|
+
* @type {string}
|
|
54
|
+
* @default ""
|
|
55
|
+
* @private
|
|
56
|
+
*/
|
|
57
|
+
this._$htmlText = "";
|
|
58
|
+
/**
|
|
59
|
+
* @type {boolean}
|
|
60
|
+
* @default false
|
|
61
|
+
* @private
|
|
62
|
+
*/
|
|
63
|
+
this._$multiline = false;
|
|
64
|
+
/**
|
|
65
|
+
* @type {string}
|
|
66
|
+
* @default ""
|
|
67
|
+
* @private
|
|
68
|
+
*/
|
|
69
|
+
this._$text = "";
|
|
70
|
+
/**
|
|
71
|
+
* @type {boolean}
|
|
72
|
+
* @default false
|
|
73
|
+
* @private
|
|
74
|
+
*/
|
|
75
|
+
this._$wordWrap = false;
|
|
76
|
+
/**
|
|
77
|
+
* @type {number}
|
|
78
|
+
* @default 0
|
|
79
|
+
* @private
|
|
80
|
+
*/
|
|
81
|
+
this._$scrollH = 0;
|
|
82
|
+
/**
|
|
83
|
+
* @type {number}
|
|
84
|
+
* @default 1
|
|
85
|
+
* @private
|
|
86
|
+
*/
|
|
87
|
+
this._$scrollV = 1;
|
|
88
|
+
/**
|
|
89
|
+
* @type {number}
|
|
90
|
+
* @default null
|
|
91
|
+
* @private
|
|
92
|
+
*/
|
|
93
|
+
this._$maxScrollV = null;
|
|
94
|
+
/**
|
|
95
|
+
* @type {number}
|
|
96
|
+
* @default null
|
|
97
|
+
* @private
|
|
98
|
+
*/
|
|
99
|
+
this._$maxScrollH = null;
|
|
100
|
+
/**
|
|
101
|
+
* @type {number}
|
|
102
|
+
* @default 0
|
|
103
|
+
* @private
|
|
104
|
+
*/
|
|
105
|
+
this._$maxChars = 0;
|
|
106
|
+
// TextFormat
|
|
107
|
+
const textFormat = new TextFormat();
|
|
108
|
+
textFormat._$setDefault();
|
|
109
|
+
/**
|
|
110
|
+
* @type {TextFormat}
|
|
111
|
+
* @private
|
|
112
|
+
*/
|
|
113
|
+
this._$defaultTextFormat = textFormat;
|
|
114
|
+
/**
|
|
115
|
+
* @type {string}
|
|
116
|
+
* @default ""
|
|
117
|
+
* @private
|
|
118
|
+
*/
|
|
119
|
+
this._$rawHtmlText = "";
|
|
120
|
+
/**
|
|
121
|
+
* @type {object}
|
|
122
|
+
* @private
|
|
123
|
+
*/
|
|
124
|
+
this._$bounds = {
|
|
125
|
+
"xMin": 0,
|
|
126
|
+
"xMax": 100,
|
|
127
|
+
"yMin": 0,
|
|
128
|
+
"yMax": 100
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* @type {object}
|
|
132
|
+
* @private
|
|
133
|
+
*/
|
|
134
|
+
this._$originBounds = {
|
|
135
|
+
"xMin": 0,
|
|
136
|
+
"xMax": 100,
|
|
137
|
+
"yMin": 0,
|
|
138
|
+
"yMax": 100
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* @type {string}
|
|
142
|
+
* @default null
|
|
143
|
+
* @private
|
|
144
|
+
*/
|
|
145
|
+
this._$restrict = "";
|
|
146
|
+
/**
|
|
147
|
+
* @type {boolean}
|
|
148
|
+
* @default false
|
|
149
|
+
* @private
|
|
150
|
+
*/
|
|
151
|
+
this._$isHTML = false;
|
|
152
|
+
/**
|
|
153
|
+
* @type {boolean}
|
|
154
|
+
* @default false
|
|
155
|
+
* @private
|
|
156
|
+
*/
|
|
157
|
+
this._$createdTextData = false;
|
|
158
|
+
/**
|
|
159
|
+
* @type {array}
|
|
160
|
+
* @private
|
|
161
|
+
*/
|
|
162
|
+
this._$textData = $getArray();
|
|
163
|
+
/**
|
|
164
|
+
* @type {number}
|
|
165
|
+
* @default null
|
|
166
|
+
* @private
|
|
167
|
+
*/
|
|
168
|
+
this._$textHeight = null;
|
|
169
|
+
/**
|
|
170
|
+
* @type {number}
|
|
171
|
+
* @default null
|
|
172
|
+
* @private
|
|
173
|
+
*/
|
|
174
|
+
this._$textWidth = null;
|
|
175
|
+
/**
|
|
176
|
+
* @type {array}
|
|
177
|
+
* @private
|
|
178
|
+
*/
|
|
179
|
+
this._$widthTable = $getArray();
|
|
180
|
+
/**
|
|
181
|
+
* @type {HTMLTextAreaElement}
|
|
182
|
+
* @default null
|
|
183
|
+
* @private
|
|
184
|
+
*/
|
|
185
|
+
this._$textarea = null;
|
|
186
|
+
/**
|
|
187
|
+
* @type {string}
|
|
188
|
+
* @default TextFieldAutoSize.NONE
|
|
189
|
+
* @private
|
|
190
|
+
*/
|
|
191
|
+
this._$autoSize = "none";
|
|
192
|
+
/**
|
|
193
|
+
* @type {boolean}
|
|
194
|
+
* @default false
|
|
195
|
+
* @private
|
|
196
|
+
*/
|
|
197
|
+
this._$autoFontSize = false;
|
|
198
|
+
/**
|
|
199
|
+
* @type {array}
|
|
200
|
+
* @default null
|
|
201
|
+
* @private
|
|
202
|
+
*/
|
|
203
|
+
this._$heightTable = $getArray();
|
|
204
|
+
/**
|
|
205
|
+
* @type {array}
|
|
206
|
+
* @private
|
|
207
|
+
*/
|
|
208
|
+
this._$textFormatTable = $getArray();
|
|
209
|
+
/**
|
|
210
|
+
* @type {boolean}
|
|
211
|
+
* @default false
|
|
212
|
+
* @private
|
|
213
|
+
*/
|
|
214
|
+
this._$textAreaActive = false;
|
|
215
|
+
/**
|
|
216
|
+
* @type {number}
|
|
217
|
+
* @default 0
|
|
218
|
+
* @private
|
|
219
|
+
*/
|
|
220
|
+
this._$totalWidth = 0;
|
|
221
|
+
/**
|
|
222
|
+
* @type {array}
|
|
223
|
+
* @private
|
|
224
|
+
*/
|
|
225
|
+
this._$objectTable = $getArray();
|
|
226
|
+
/**
|
|
227
|
+
* @type {array}
|
|
228
|
+
* @private
|
|
229
|
+
*/
|
|
230
|
+
this._$imageData = $getArray();
|
|
231
|
+
/**
|
|
232
|
+
* @type {boolean}
|
|
233
|
+
* @default true
|
|
234
|
+
* @private
|
|
235
|
+
*/
|
|
236
|
+
this._$scrollEnabled = true;
|
|
237
|
+
/**
|
|
238
|
+
* @type {Sprite}
|
|
239
|
+
* @default null
|
|
240
|
+
* @private
|
|
241
|
+
*/
|
|
242
|
+
this._$scrollSprite = null;
|
|
243
|
+
/**
|
|
244
|
+
* @type {string}
|
|
245
|
+
* @default null
|
|
246
|
+
* @private
|
|
247
|
+
*/
|
|
248
|
+
this._$type = "static";
|
|
249
|
+
/**
|
|
250
|
+
* @type {array}
|
|
251
|
+
* @default null
|
|
252
|
+
* @private
|
|
253
|
+
*/
|
|
254
|
+
this._$textHeightTable = $getArray();
|
|
255
|
+
/**
|
|
256
|
+
* @type {boolean}
|
|
257
|
+
* @default false
|
|
258
|
+
* @private
|
|
259
|
+
*/
|
|
260
|
+
this._$focus = false;
|
|
261
|
+
/**
|
|
262
|
+
* @type {boolean}
|
|
263
|
+
* @default false
|
|
264
|
+
* @private
|
|
265
|
+
*/
|
|
266
|
+
this._$isComposing = false;
|
|
267
|
+
/**
|
|
268
|
+
* @type {number}
|
|
269
|
+
* @default 0
|
|
270
|
+
* @private
|
|
271
|
+
*/
|
|
272
|
+
this._$thickness = 0;
|
|
273
|
+
/**
|
|
274
|
+
* @type {number}
|
|
275
|
+
* @default 0
|
|
276
|
+
* @private
|
|
277
|
+
*/
|
|
278
|
+
this._$thicknessColor = 0;
|
|
279
|
+
/**
|
|
280
|
+
* @type {string}
|
|
281
|
+
* @default TextFormatVerticalAlign.TOP
|
|
282
|
+
* @private
|
|
283
|
+
*/
|
|
284
|
+
this._$verticalAlign = "top";
|
|
285
|
+
/**
|
|
286
|
+
* @type {Map}
|
|
287
|
+
* @private
|
|
288
|
+
*/
|
|
289
|
+
this._$heightCache = $getMap();
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* @description 指定されたクラスのストリングを返します。
|
|
293
|
+
* Returns the string representation of the specified class.
|
|
294
|
+
*
|
|
295
|
+
* @return {string}
|
|
296
|
+
* @default [class TextField]
|
|
297
|
+
* @method
|
|
298
|
+
* @static
|
|
299
|
+
*/
|
|
300
|
+
static toString() {
|
|
301
|
+
return "[class TextField]";
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* @description 指定されたクラスの空間名を返します。
|
|
305
|
+
* Returns the space name of the specified class.
|
|
306
|
+
*
|
|
307
|
+
* @return {string}
|
|
308
|
+
* @default next2d.text.TextField
|
|
309
|
+
* @const
|
|
310
|
+
* @static
|
|
311
|
+
*/
|
|
312
|
+
static get namespace() {
|
|
313
|
+
return "next2d.text.TextField";
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* @description 指定されたオブジェクトのストリングを返します。
|
|
317
|
+
* Returns the string representation of the specified object.
|
|
318
|
+
*
|
|
319
|
+
* @return {string}
|
|
320
|
+
* @default [object TextField]
|
|
321
|
+
* @method
|
|
322
|
+
* @public
|
|
323
|
+
*/
|
|
324
|
+
toString() {
|
|
325
|
+
return "[object TextField]";
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* @description 指定されたオブジェクトの空間名を返します。
|
|
329
|
+
* Returns the space name of the specified object.
|
|
330
|
+
*
|
|
331
|
+
* @return {string}
|
|
332
|
+
* @default next2d.text.TextField
|
|
333
|
+
* @const
|
|
334
|
+
* @public
|
|
335
|
+
*/
|
|
336
|
+
get namespace() {
|
|
337
|
+
return "next2d.text.TextField";
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* @description テキストサイズの自動的な拡大 / 縮小および整列を制御します。
|
|
341
|
+
* Controls automatic sizing and alignment of text size.
|
|
342
|
+
*
|
|
343
|
+
* @member {boolean}
|
|
344
|
+
* @default false
|
|
345
|
+
* @public
|
|
346
|
+
*/
|
|
347
|
+
get autoFontSize() {
|
|
348
|
+
return this._$autoFontSize;
|
|
349
|
+
}
|
|
350
|
+
set autoFontSize(auto_font_size) {
|
|
351
|
+
if (auto_font_size !== this._$autoFontSize) {
|
|
352
|
+
this._$autoFontSize = auto_font_size;
|
|
353
|
+
this._$reload();
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* @description テキストフィールドの自動的な拡大 / 縮小および整列を制御します。
|
|
358
|
+
* Controls automatic sizing and alignment of text fields.
|
|
359
|
+
*
|
|
360
|
+
* @member {string}
|
|
361
|
+
* @default TextFieldAutoSize.NONE
|
|
362
|
+
* @public
|
|
363
|
+
*/
|
|
364
|
+
get autoSize() {
|
|
365
|
+
return this._$autoSize;
|
|
366
|
+
}
|
|
367
|
+
set autoSize(auto_size) {
|
|
368
|
+
if (auto_size !== this._$autoSize) {
|
|
369
|
+
this._$autoSize = auto_size;
|
|
370
|
+
this._$reload();
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* @description テキストフィールドに背景の塗りつぶしがあるかどうかを指定します。
|
|
375
|
+
* Specifies whether the text field has a background fill.
|
|
376
|
+
*
|
|
377
|
+
* @member {boolean}
|
|
378
|
+
* @default false
|
|
379
|
+
* @public
|
|
380
|
+
*/
|
|
381
|
+
get background() {
|
|
382
|
+
return this._$background;
|
|
383
|
+
}
|
|
384
|
+
set background(background) {
|
|
385
|
+
if (background !== this._$background) {
|
|
386
|
+
this._$background = !!background;
|
|
387
|
+
this._$reset();
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* @description テキストフィールドの背景の色です。
|
|
392
|
+
* The color of the text field background.
|
|
393
|
+
*
|
|
394
|
+
* @member {number}
|
|
395
|
+
* @default 0xffffff
|
|
396
|
+
* @public
|
|
397
|
+
*/
|
|
398
|
+
get backgroundColor() {
|
|
399
|
+
return this._$backgroundColor;
|
|
400
|
+
}
|
|
401
|
+
set backgroundColor(background_color) {
|
|
402
|
+
background_color = $clamp($toColorInt(background_color), 0, 0xffffff, 0xffffff);
|
|
403
|
+
if (background_color !== this._$backgroundColor) {
|
|
404
|
+
this._$backgroundColor = background_color;
|
|
405
|
+
this._$reset();
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* @description テキストフィールドに境界線があるかどうかを指定します。
|
|
410
|
+
* Specifies whether the text field has a border.
|
|
411
|
+
*
|
|
412
|
+
* @member {boolean}
|
|
413
|
+
* @default false
|
|
414
|
+
* @public
|
|
415
|
+
*/
|
|
416
|
+
get border() {
|
|
417
|
+
return this._$border;
|
|
418
|
+
}
|
|
419
|
+
set border(border) {
|
|
420
|
+
if (border !== this._$border) {
|
|
421
|
+
this._$border = !!border;
|
|
422
|
+
this._$reset();
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* @description テキストフィールドの境界線の色です。
|
|
427
|
+
* The color of the text field border.
|
|
428
|
+
*
|
|
429
|
+
* @member {number}
|
|
430
|
+
* @default 0x000000
|
|
431
|
+
* @public
|
|
432
|
+
*/
|
|
433
|
+
get borderColor() {
|
|
434
|
+
return this._$borderColor;
|
|
435
|
+
}
|
|
436
|
+
set borderColor(border_color) {
|
|
437
|
+
border_color = $clamp($toColorInt(border_color), 0, 0xffffff, 0);
|
|
438
|
+
if (border_color !== this._$borderColor) {
|
|
439
|
+
this._$borderColor = border_color;
|
|
440
|
+
this._$reset();
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* @description テキストに適用するフォーマットを指定します。
|
|
445
|
+
* Specifies the formatting to be applied to the text.
|
|
446
|
+
*
|
|
447
|
+
* @member {TextFormat}
|
|
448
|
+
* @public
|
|
449
|
+
*/
|
|
450
|
+
get defaultTextFormat() {
|
|
451
|
+
return this._$defaultTextFormat._$clone();
|
|
452
|
+
}
|
|
453
|
+
set defaultTextFormat(text_format) {
|
|
454
|
+
text_format._$merge(this._$defaultTextFormat);
|
|
455
|
+
this._$defaultTextFormat = text_format;
|
|
456
|
+
this._$reset();
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* @description このオブジェクトでマウスまたはその他のユーザー入力メッセージを
|
|
460
|
+
*
|
|
461
|
+
* @member {boolean}
|
|
462
|
+
* @default false
|
|
463
|
+
* @public
|
|
464
|
+
*/
|
|
465
|
+
get focus() {
|
|
466
|
+
return this._$focus;
|
|
467
|
+
}
|
|
468
|
+
set focus(focus) {
|
|
469
|
+
if (this._$focus === focus) {
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
this._$focus = focus;
|
|
473
|
+
if (this._$focus) {
|
|
474
|
+
if (this._$type === "input") {
|
|
475
|
+
const player = $currentPlayer();
|
|
476
|
+
const div = $document
|
|
477
|
+
.getElementById(player.contentElementId);
|
|
478
|
+
if (!div) {
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
this._$createTextAreaElement(player._$scale);
|
|
482
|
+
// setup
|
|
483
|
+
const element = this._$textarea;
|
|
484
|
+
if (!element) {
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
const matrix = this._$transform.concatenatedMatrix;
|
|
488
|
+
const bounds = this._$getBounds(null);
|
|
489
|
+
const color = $intToRGBA($toColorInt(this._$defaultTextFormat.color), 100);
|
|
490
|
+
element.style.color = `rgb(${color.R},${color.G},${color.B})`;
|
|
491
|
+
element.style.left = `${(matrix.tx + bounds.xMin + player.x / player._$scale / $devicePixelRatio) * player._$scale}px`;
|
|
492
|
+
element.style.top = `${(matrix.ty + bounds.yMin + player.y / player._$scale / $devicePixelRatio) * player._$scale}px`;
|
|
493
|
+
element.style.width = `${$Math.ceil((this.width - 1) * player._$scale)}px`;
|
|
494
|
+
element.style.height = `${$Math.ceil((this.height - 1) * player._$scale)}px`;
|
|
495
|
+
// set text
|
|
496
|
+
element.value = this.text;
|
|
497
|
+
div.appendChild(element);
|
|
498
|
+
$requestAnimationFrame(() => {
|
|
499
|
+
element.focus();
|
|
500
|
+
});
|
|
501
|
+
this._$doChanged();
|
|
502
|
+
$doUpdated();
|
|
503
|
+
this._$textAreaActive = true;
|
|
504
|
+
// focus in event
|
|
505
|
+
if (this.willTrigger(FocusEvent.FOCUS_IN)) {
|
|
506
|
+
this.dispatchEvent(new FocusEvent(FocusEvent.FOCUS_IN));
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
// execute
|
|
512
|
+
if (this._$textarea) {
|
|
513
|
+
this._$textarea.dispatchEvent(new Event(`${$PREFIX}_blur`));
|
|
514
|
+
if (this.willTrigger(FocusEvent.FOCUS_OUT)) {
|
|
515
|
+
this.dispatchEvent(new FocusEvent(FocusEvent.FOCUS_OUT));
|
|
516
|
+
}
|
|
517
|
+
this._$textarea.remove();
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* @description テキストフィールドの内容を HTML で表します。
|
|
523
|
+
* Contains the HTML representation of the text field contents.
|
|
524
|
+
*
|
|
525
|
+
* @member {string}
|
|
526
|
+
* @default ""
|
|
527
|
+
* @public
|
|
528
|
+
*/
|
|
529
|
+
get htmlText() {
|
|
530
|
+
return this._$htmlText;
|
|
531
|
+
}
|
|
532
|
+
set htmlText(html_text) {
|
|
533
|
+
if (this._$htmlText !== html_text) {
|
|
534
|
+
this._$htmlText = `${html_text}`;
|
|
535
|
+
this._$rawHtmlText = "";
|
|
536
|
+
this._$text = "";
|
|
537
|
+
this._$isHTML = true;
|
|
538
|
+
this._$textFormatTable.length = 0;
|
|
539
|
+
this._$reload();
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* @description テキストフィールド内の文字数です。
|
|
544
|
+
* The int of characters in a text field.
|
|
545
|
+
*
|
|
546
|
+
* @member {number}
|
|
547
|
+
* @readonly
|
|
548
|
+
* @public
|
|
549
|
+
*/
|
|
550
|
+
get length() {
|
|
551
|
+
return this.text.length;
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* @description ユーザーが入力するときに、テキストフィールドに入力できる最大の文字数です。
|
|
555
|
+
* The maximum number of characters that the text field can contain,
|
|
556
|
+
* as entered by a user.
|
|
557
|
+
*
|
|
558
|
+
* @member {number}
|
|
559
|
+
* @default 0
|
|
560
|
+
* @public
|
|
561
|
+
*/
|
|
562
|
+
get maxChars() {
|
|
563
|
+
return this._$maxChars;
|
|
564
|
+
}
|
|
565
|
+
set maxChars(max_chars) {
|
|
566
|
+
this._$maxChars = max_chars | 0;
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* TODO
|
|
570
|
+
* @description scrollH の最大値です。
|
|
571
|
+
* The maximum value of scrollH.
|
|
572
|
+
*
|
|
573
|
+
* @member {number}
|
|
574
|
+
* @readonly
|
|
575
|
+
* @public
|
|
576
|
+
*/
|
|
577
|
+
get maxScrollH() {
|
|
578
|
+
if (this._$maxScrollH === null) {
|
|
579
|
+
this._$maxScrollH = 0;
|
|
580
|
+
}
|
|
581
|
+
return this._$maxScrollH;
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* @description scrollV の最大値です。
|
|
585
|
+
* The maximum value of scrollV.
|
|
586
|
+
*
|
|
587
|
+
* @member {number}
|
|
588
|
+
* @readonly
|
|
589
|
+
* @public
|
|
590
|
+
*/
|
|
591
|
+
get maxScrollV() {
|
|
592
|
+
if (this._$maxScrollV === null) {
|
|
593
|
+
this._$maxScrollV = 1;
|
|
594
|
+
this._$getTextData();
|
|
595
|
+
if (!this._$textHeightTable.length) {
|
|
596
|
+
return this._$maxScrollV;
|
|
597
|
+
}
|
|
598
|
+
const length = this._$textHeightTable.length;
|
|
599
|
+
const maxHeight = this.height;
|
|
600
|
+
if (maxHeight > this.textHeight) {
|
|
601
|
+
return this._$maxScrollV;
|
|
602
|
+
}
|
|
603
|
+
let textHeight = 0;
|
|
604
|
+
let idx = 0;
|
|
605
|
+
while (length > idx) {
|
|
606
|
+
textHeight += this._$textHeightTable[idx++];
|
|
607
|
+
if (textHeight > maxHeight) {
|
|
608
|
+
break;
|
|
609
|
+
}
|
|
610
|
+
this._$maxScrollV++;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
return this._$maxScrollV;
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* @description フィールドが複数行テキストフィールドであるかどうかを示します。
|
|
617
|
+
* Indicates whether field is a multiline text field.
|
|
618
|
+
*
|
|
619
|
+
* @member {boolean}
|
|
620
|
+
* @default false
|
|
621
|
+
* @public
|
|
622
|
+
*/
|
|
623
|
+
get multiline() {
|
|
624
|
+
return this._$multiline;
|
|
625
|
+
}
|
|
626
|
+
set multiline(multiline) {
|
|
627
|
+
if (multiline !== this._$multiline) {
|
|
628
|
+
this._$multiline = !!multiline;
|
|
629
|
+
this._$reset();
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* @description フィールドが複数行テキストフィールドであるかどうかを示します。
|
|
634
|
+
* Indicates whether field is a multiline text field.
|
|
635
|
+
*
|
|
636
|
+
* @member {number}
|
|
637
|
+
* @readonly
|
|
638
|
+
* @public
|
|
639
|
+
*/
|
|
640
|
+
get numLines() {
|
|
641
|
+
if (!this._$createdTextData) {
|
|
642
|
+
this._$getTextData();
|
|
643
|
+
}
|
|
644
|
+
return this._$objectTable.length;
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* @description ユーザーがテキストフィールドに入力できる文字のセットを指定します。
|
|
648
|
+
* Indicates the set of characters that a user can enter into the text field.
|
|
649
|
+
*
|
|
650
|
+
* @member {string}
|
|
651
|
+
* @default null
|
|
652
|
+
* @public
|
|
653
|
+
*/
|
|
654
|
+
get restrict() {
|
|
655
|
+
return this._$restrict;
|
|
656
|
+
}
|
|
657
|
+
set restrict(restrict) {
|
|
658
|
+
this._$restrict = `${restrict}`;
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* @description スクロール機能のON/OFFの制御。
|
|
662
|
+
* Control ON/OFF of the scroll function.
|
|
663
|
+
*
|
|
664
|
+
* @member {boolean}
|
|
665
|
+
* @default true
|
|
666
|
+
* @public
|
|
667
|
+
*/
|
|
668
|
+
get scrollEnabled() {
|
|
669
|
+
return this._$scrollEnabled;
|
|
670
|
+
}
|
|
671
|
+
set scrollEnabled(scroll_enabled) {
|
|
672
|
+
this._$scrollEnabled = scroll_enabled;
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* TODO
|
|
676
|
+
* @description 現在の水平スクロール位置です。
|
|
677
|
+
* The current horizontal scrolling position.
|
|
678
|
+
*
|
|
679
|
+
* @member {number}
|
|
680
|
+
* @public
|
|
681
|
+
*/
|
|
682
|
+
get scrollH() {
|
|
683
|
+
return this._$scrollH;
|
|
684
|
+
}
|
|
685
|
+
set scrollH(scroll_h) {
|
|
686
|
+
scroll_h = $clamp(scroll_h | 0, 0, this.maxScrollH);
|
|
687
|
+
if (this._$scrollH !== scroll_h) {
|
|
688
|
+
this._$scrollH = scroll_h;
|
|
689
|
+
this._$reset();
|
|
690
|
+
if (this.willTrigger(Next2DEvent.SCROLL)) {
|
|
691
|
+
this.dispatchEvent(new Next2DEvent(Next2DEvent.SCROLL, true));
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* @description テキストフィールドのテキストの垂直位置です。
|
|
697
|
+
* The vertical position of text in a text field.
|
|
698
|
+
*
|
|
699
|
+
* @member {number}
|
|
700
|
+
* @public
|
|
701
|
+
*/
|
|
702
|
+
get scrollV() {
|
|
703
|
+
return this._$scrollV;
|
|
704
|
+
}
|
|
705
|
+
set scrollV(scroll_v) {
|
|
706
|
+
scroll_v = $clamp(scroll_v | 0, 1, this.maxScrollV);
|
|
707
|
+
if (this._$scrollV !== scroll_v) {
|
|
708
|
+
this._$scrollV = $Math.max(1, scroll_v);
|
|
709
|
+
this._$reset();
|
|
710
|
+
if (this._$scrollSprite && this.textHeight > this.height) {
|
|
711
|
+
this._$scrollSprite.height = this.height * this.height / this.textHeight - 1;
|
|
712
|
+
const parent = this._$parent;
|
|
713
|
+
if (parent) {
|
|
714
|
+
// view start
|
|
715
|
+
this._$scrollSprite.alpha = 1;
|
|
716
|
+
// set position
|
|
717
|
+
this._$scrollSprite.x = this.x + this.width - this._$scrollSprite.width - 0.5;
|
|
718
|
+
this._$scrollSprite.y = this.y + 0.5
|
|
719
|
+
+ (this.height - 1 - this._$scrollSprite.height)
|
|
720
|
+
/ (this.maxScrollV - 1)
|
|
721
|
+
* (this._$scrollV - 1);
|
|
722
|
+
// added sprite
|
|
723
|
+
parent.addChildAt(this._$scrollSprite, parent.getChildIndex(this) + 1);
|
|
724
|
+
// start animation
|
|
725
|
+
if (this._$scrollSprite.hasLocalVariable("job")) {
|
|
726
|
+
this._$scrollSprite.getLocalVariable("job").stop();
|
|
727
|
+
}
|
|
728
|
+
const job = Tween.add(this._$scrollSprite, { "alpha": 1 }, { "alpha": 0 }, 1);
|
|
729
|
+
job.addEventListener(Next2DEvent.COMPLETE, (event) => {
|
|
730
|
+
const sprite = event.target.target;
|
|
731
|
+
sprite.deleteLocalVariable("job");
|
|
732
|
+
if (sprite.parent) {
|
|
733
|
+
sprite.parent.removeChild(sprite);
|
|
734
|
+
}
|
|
735
|
+
});
|
|
736
|
+
job.start();
|
|
737
|
+
this._$scrollSprite.setLocalVariable("job", job);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
if (this.willTrigger(Next2DEvent.SCROLL)) {
|
|
741
|
+
this.dispatchEvent(new Next2DEvent(Next2DEvent.SCROLL, true));
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* @description テキストフィールド内の現在のテキストであるストリングです。
|
|
747
|
+
* A string that is the current text in the text field.
|
|
748
|
+
*
|
|
749
|
+
* @member {string}
|
|
750
|
+
* @default ""
|
|
751
|
+
* @public
|
|
752
|
+
*/
|
|
753
|
+
get text() {
|
|
754
|
+
if (!this._$isHTML) {
|
|
755
|
+
return this._$text;
|
|
756
|
+
}
|
|
757
|
+
if (this._$rawHtmlText) {
|
|
758
|
+
return this._$rawHtmlText;
|
|
759
|
+
}
|
|
760
|
+
let text = "";
|
|
761
|
+
const textData = this._$getTextData();
|
|
762
|
+
for (let idx = 1; idx < textData.length; ++idx) {
|
|
763
|
+
const object = textData[idx];
|
|
764
|
+
switch (object.mode) {
|
|
765
|
+
case "text":
|
|
766
|
+
text += object.text;
|
|
767
|
+
break;
|
|
768
|
+
case "break":
|
|
769
|
+
text += "\r";
|
|
770
|
+
break;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
this._$rawHtmlText = text;
|
|
774
|
+
return text;
|
|
775
|
+
}
|
|
776
|
+
set text(text) {
|
|
777
|
+
if (text === null) {
|
|
778
|
+
text = "";
|
|
779
|
+
}
|
|
780
|
+
text = `${text}`;
|
|
781
|
+
if (text !== this._$text) {
|
|
782
|
+
this._$text = text;
|
|
783
|
+
this._$htmlText = "";
|
|
784
|
+
this._$isHTML = false;
|
|
785
|
+
this._$textFormatTable.length = 0;
|
|
786
|
+
this._$reload();
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* @description テキストフィールドのテキストの色です(16 進数形式)。
|
|
791
|
+
* The color of the text in a text field, in hexadecimal format.
|
|
792
|
+
*
|
|
793
|
+
* @member {number}
|
|
794
|
+
* @public
|
|
795
|
+
*/
|
|
796
|
+
get textColor() {
|
|
797
|
+
return this._$defaultTextFormat.color || 0;
|
|
798
|
+
}
|
|
799
|
+
set textColor(text_color) {
|
|
800
|
+
this._$defaultTextFormat.color = text_color;
|
|
801
|
+
this._$reload();
|
|
802
|
+
}
|
|
803
|
+
/**
|
|
804
|
+
* @description テキストの高さです(ピクセル単位)。
|
|
805
|
+
* The height of the text in pixels.
|
|
806
|
+
*
|
|
807
|
+
* @member {number}
|
|
808
|
+
* @readonly
|
|
809
|
+
* @public
|
|
810
|
+
*/
|
|
811
|
+
get textHeight() {
|
|
812
|
+
if (this.text === "") {
|
|
813
|
+
return 0;
|
|
814
|
+
}
|
|
815
|
+
if (this._$textHeight === null) {
|
|
816
|
+
// setup
|
|
817
|
+
this._$textHeight = 2;
|
|
818
|
+
this._$getTextData();
|
|
819
|
+
const length = this._$textHeightTable.length;
|
|
820
|
+
if (length === 1) {
|
|
821
|
+
this._$textHeight += this._$defaultTextFormat.leading || 0;
|
|
822
|
+
}
|
|
823
|
+
for (let idx = 0; idx < length; ++idx) {
|
|
824
|
+
this._$textHeight += this._$textHeightTable[idx];
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
return this._$textHeight;
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* @description テキストの幅です(ピクセル単位)。
|
|
831
|
+
* The width of the text in pixels.
|
|
832
|
+
*
|
|
833
|
+
* @member {number}
|
|
834
|
+
* @readonly
|
|
835
|
+
* @public
|
|
836
|
+
*/
|
|
837
|
+
get textWidth() {
|
|
838
|
+
if (this._$textWidth === null) {
|
|
839
|
+
// setup
|
|
840
|
+
this._$textWidth = 0;
|
|
841
|
+
this._$getTextData();
|
|
842
|
+
for (let idx = 0; idx < this._$widthTable.length; ++idx) {
|
|
843
|
+
this._$textWidth = $Math.max(this._$textWidth, this._$widthTable[idx]);
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
return this._$textWidth;
|
|
847
|
+
}
|
|
848
|
+
/**
|
|
849
|
+
* @description 輪郭のテキスト幅です。0(デフォルト値)で無効にできます。
|
|
850
|
+
* The text width of the outline, which can be disabled with 0 (the default value).
|
|
851
|
+
*
|
|
852
|
+
* @member {number}
|
|
853
|
+
* @default 0
|
|
854
|
+
* @public
|
|
855
|
+
*/
|
|
856
|
+
get thickness() {
|
|
857
|
+
return this._$thickness;
|
|
858
|
+
}
|
|
859
|
+
set thickness(thickness) {
|
|
860
|
+
thickness |= 0;
|
|
861
|
+
if (thickness !== this._$thickness) {
|
|
862
|
+
this._$thickness = thickness;
|
|
863
|
+
this._$reset();
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* @description 輪郭のテキストの色です(16 進数形式)。
|
|
868
|
+
* The color of the outline text. (Hexadecimal format)
|
|
869
|
+
*
|
|
870
|
+
* @member {number}
|
|
871
|
+
* @default 0
|
|
872
|
+
* @public
|
|
873
|
+
*/
|
|
874
|
+
get thicknessColor() {
|
|
875
|
+
return this._$thicknessColor;
|
|
876
|
+
}
|
|
877
|
+
set thicknessColor(thickness_color) {
|
|
878
|
+
thickness_color = $clamp($toColorInt(thickness_color), 0, 0xffffff, 0);
|
|
879
|
+
if (thickness_color !== this._$thicknessColor) {
|
|
880
|
+
this._$thicknessColor = thickness_color;
|
|
881
|
+
this._$reset();
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* @description テキストフィールドのタイプです。
|
|
886
|
+
* The type of the text field.
|
|
887
|
+
*
|
|
888
|
+
* @member {string}
|
|
889
|
+
* @default TextFieldType.STATIC
|
|
890
|
+
* @public
|
|
891
|
+
*/
|
|
892
|
+
get type() {
|
|
893
|
+
return this._$type;
|
|
894
|
+
}
|
|
895
|
+
set type(type) {
|
|
896
|
+
this._$type = type;
|
|
897
|
+
if (type === "static") {
|
|
898
|
+
this._$textarea = null;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* @description 縦方向の揃え位置を指定するプロパティです。
|
|
903
|
+
* This property specifies the vertical alignment position.
|
|
904
|
+
*
|
|
905
|
+
* @member {string}
|
|
906
|
+
* @default TextFormatVerticalAlign.TOP
|
|
907
|
+
* @public
|
|
908
|
+
*/
|
|
909
|
+
get verticalAlign() {
|
|
910
|
+
return this._$verticalAlign;
|
|
911
|
+
}
|
|
912
|
+
set verticalAlign(vertical_align) {
|
|
913
|
+
if (vertical_align !== this._$verticalAlign) {
|
|
914
|
+
this._$verticalAlign = vertical_align;
|
|
915
|
+
this._$reset();
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
/**
|
|
919
|
+
* @description テキストフィールドのテキストを折り返すかどうかを示すブール値です。
|
|
920
|
+
* A Boolean value that indicates whether the text field has word wrap.
|
|
921
|
+
*
|
|
922
|
+
* @member {boolean}
|
|
923
|
+
* @default false
|
|
924
|
+
* @public
|
|
925
|
+
*/
|
|
926
|
+
get wordWrap() {
|
|
927
|
+
return this._$wordWrap;
|
|
928
|
+
}
|
|
929
|
+
set wordWrap(word_wrap) {
|
|
930
|
+
if (this._$wordWrap !== word_wrap) {
|
|
931
|
+
this._$wordWrap = !!word_wrap;
|
|
932
|
+
this._$reset();
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* @description 表示オブジェクトの幅を示します(ピクセル単位)。
|
|
937
|
+
* Indicates the width of the display object, in pixels.
|
|
938
|
+
*
|
|
939
|
+
* @member {number}
|
|
940
|
+
* @public
|
|
941
|
+
*/
|
|
942
|
+
get width() {
|
|
943
|
+
return super.width;
|
|
944
|
+
}
|
|
945
|
+
set width(width) {
|
|
946
|
+
width = +width;
|
|
947
|
+
if (!$isNaN(width) && width > -1) {
|
|
948
|
+
const bounds = this._$getBounds(null);
|
|
949
|
+
const xMin = $Math.abs(bounds.xMin);
|
|
950
|
+
this._$originBounds.xMax = width + xMin;
|
|
951
|
+
this._$originBounds.xMin = xMin;
|
|
952
|
+
this._$bounds.xMax = this._$originBounds.xMax;
|
|
953
|
+
this._$bounds.xMin = this._$originBounds.xMin;
|
|
954
|
+
super.width = width;
|
|
955
|
+
this._$reload();
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
/**
|
|
959
|
+
* @description 表示オブジェクトの高さを示します(ピクセル単位)。
|
|
960
|
+
* Indicates the height of the display object, in pixels.
|
|
961
|
+
*
|
|
962
|
+
* @member {number}
|
|
963
|
+
* @public
|
|
964
|
+
*/
|
|
965
|
+
get height() {
|
|
966
|
+
return super.height;
|
|
967
|
+
}
|
|
968
|
+
set height(height) {
|
|
969
|
+
height = +height;
|
|
970
|
+
if (!$isNaN(height) && height > -1) {
|
|
971
|
+
const bounds = this._$getBounds(null);
|
|
972
|
+
const yMin = $Math.abs(bounds.yMin);
|
|
973
|
+
this._$originBounds.yMax = height + yMin;
|
|
974
|
+
this._$bounds.yMax = this._$originBounds.yMax;
|
|
975
|
+
this._$bounds.yMin = this._$originBounds.yMin;
|
|
976
|
+
super.height = height;
|
|
977
|
+
this._$reload();
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
/**
|
|
981
|
+
* @description 親 DisplayObjectContainer のローカル座標を基準にした
|
|
982
|
+
* DisplayObject インスタンスの x 座標を示します。
|
|
983
|
+
* Indicates the x coordinate
|
|
984
|
+
* of the DisplayObject instance relative to the local coordinates
|
|
985
|
+
* of the parent DisplayObjectContainer.
|
|
986
|
+
*
|
|
987
|
+
* @member {number}
|
|
988
|
+
* @public
|
|
989
|
+
*/
|
|
990
|
+
get x() {
|
|
991
|
+
const matrix = this._$transform.matrix;
|
|
992
|
+
const bounds = this._$getBounds(null);
|
|
993
|
+
return matrix._$matrix[4] + bounds.xMin;
|
|
994
|
+
}
|
|
995
|
+
set x(x) {
|
|
996
|
+
const bounds = this._$getBounds(null);
|
|
997
|
+
super.x = x - bounds.xMin;
|
|
998
|
+
}
|
|
999
|
+
/**
|
|
1000
|
+
* @description 親 DisplayObjectContainer のローカル座標を基準にした
|
|
1001
|
+
* DisplayObject インスタンスの y 座標を示します。
|
|
1002
|
+
* Indicates the y coordinate
|
|
1003
|
+
* of the DisplayObject instance relative to the local coordinates
|
|
1004
|
+
* of the parent DisplayObjectContainer.
|
|
1005
|
+
*
|
|
1006
|
+
* @member {number}
|
|
1007
|
+
* @public
|
|
1008
|
+
*/
|
|
1009
|
+
get y() {
|
|
1010
|
+
const matrix = this._$transform.matrix;
|
|
1011
|
+
const bounds = this._$getBounds(null);
|
|
1012
|
+
return matrix._$matrix[5] + bounds.yMin;
|
|
1013
|
+
}
|
|
1014
|
+
set y(y) {
|
|
1015
|
+
const bounds = this._$getBounds(null);
|
|
1016
|
+
super.y = y - bounds.yMin;
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* @description newText パラメーターで指定されたストリングを、
|
|
1020
|
+
* テキストフィールドのテキストの最後に付加します。
|
|
1021
|
+
* Appends the string specified by the newText parameter
|
|
1022
|
+
* to the end of the text of the text field.
|
|
1023
|
+
*
|
|
1024
|
+
* @param {string} new_text
|
|
1025
|
+
* @return void
|
|
1026
|
+
* @method
|
|
1027
|
+
* @public
|
|
1028
|
+
*/
|
|
1029
|
+
appendText(new_text) {
|
|
1030
|
+
const currentText = this.text;
|
|
1031
|
+
this.text = currentText + `${new_text}`;
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* @description beginIndex パラメーターと endIndex パラメーターで指定された範囲の
|
|
1035
|
+
* テキストのフォーマット情報を含む TextFormat オブジェクトを返します。
|
|
1036
|
+
* Returns a TextFormat object that contains formatting information
|
|
1037
|
+
* for the range of text that the beginIndex and endIndex parameters specify.
|
|
1038
|
+
*
|
|
1039
|
+
* @param {int} [begin_index=-1]
|
|
1040
|
+
* @param {int} [end_index=-1]
|
|
1041
|
+
* @return {TextFormat}
|
|
1042
|
+
* @method
|
|
1043
|
+
* @public
|
|
1044
|
+
*/
|
|
1045
|
+
getTextFormat(begin_index = -1, end_index = -1) {
|
|
1046
|
+
begin_index |= 0;
|
|
1047
|
+
end_index |= 0;
|
|
1048
|
+
const data = this._$getTextData();
|
|
1049
|
+
const length = end_index > -1 ? end_index : data.length;
|
|
1050
|
+
let init = false;
|
|
1051
|
+
let textFormat = new TextFormat();
|
|
1052
|
+
let idx = begin_index > -1 ? begin_index : 0;
|
|
1053
|
+
for (; idx < length; ++idx) {
|
|
1054
|
+
if (data[idx].mode === "break") {
|
|
1055
|
+
continue;
|
|
1056
|
+
}
|
|
1057
|
+
const tf = data[idx].textFormat;
|
|
1058
|
+
if (!init) {
|
|
1059
|
+
init = true;
|
|
1060
|
+
textFormat = tf._$clone();
|
|
1061
|
+
continue;
|
|
1062
|
+
}
|
|
1063
|
+
textFormat.align = textFormat.align !== tf.align ? null : tf.align;
|
|
1064
|
+
textFormat.blockIndent = textFormat.blockIndent !== tf.blockIndent ? null : tf.blockIndent;
|
|
1065
|
+
textFormat.bold = textFormat.bold !== tf.bold ? null : tf.bold;
|
|
1066
|
+
textFormat.color = textFormat.color !== tf.color ? null : tf.color;
|
|
1067
|
+
textFormat.font = textFormat.font !== tf.font ? null : tf.font;
|
|
1068
|
+
textFormat.indent = textFormat.indent !== tf.indent ? null : tf.indent;
|
|
1069
|
+
textFormat.italic = textFormat.italic !== tf.italic ? null : tf.italic;
|
|
1070
|
+
textFormat.leading = textFormat.leading !== tf.leading ? null : tf.leading;
|
|
1071
|
+
textFormat.leftMargin = textFormat.leftMargin !== tf.leftMargin ? null : tf.leftMargin;
|
|
1072
|
+
textFormat.letterSpacing = textFormat.letterSpacing !== tf.letterSpacing ? null : tf.letterSpacing;
|
|
1073
|
+
textFormat.rightMargin = textFormat.rightMargin !== tf.rightMargin ? null : tf.rightMargin;
|
|
1074
|
+
textFormat.size = textFormat.size !== tf.size ? null : tf.size;
|
|
1075
|
+
textFormat.underline = textFormat.underline !== tf.underline ? null : tf.underline;
|
|
1076
|
+
}
|
|
1077
|
+
return textFormat;
|
|
1078
|
+
}
|
|
1079
|
+
/**
|
|
1080
|
+
* @description lineIndex パラメーターで指定された行のテキストを返します。
|
|
1081
|
+
* Returns the text of the line specified by the lineIndex parameter.
|
|
1082
|
+
*
|
|
1083
|
+
* @param {number} line_index
|
|
1084
|
+
* @return {string}
|
|
1085
|
+
* @public
|
|
1086
|
+
*/
|
|
1087
|
+
getLineText(line_index) {
|
|
1088
|
+
if (!this._$text && !this._$htmlText) {
|
|
1089
|
+
return "";
|
|
1090
|
+
}
|
|
1091
|
+
line_index |= 0;
|
|
1092
|
+
let lineText = "";
|
|
1093
|
+
const textData = this._$getTextData();
|
|
1094
|
+
for (let idx = 0; idx < textData.length; idx++) {
|
|
1095
|
+
const obj = textData[idx];
|
|
1096
|
+
if (obj.yIndex > line_index) {
|
|
1097
|
+
break;
|
|
1098
|
+
}
|
|
1099
|
+
if (obj.yIndex !== line_index) {
|
|
1100
|
+
continue;
|
|
1101
|
+
}
|
|
1102
|
+
if (obj.mode !== "text") {
|
|
1103
|
+
continue;
|
|
1104
|
+
}
|
|
1105
|
+
lineText += obj.text;
|
|
1106
|
+
}
|
|
1107
|
+
return lineText;
|
|
1108
|
+
}
|
|
1109
|
+
/**
|
|
1110
|
+
* @description beginIndex パラメーターと endIndex パラメーターで指定された文字範囲を、
|
|
1111
|
+
* newText パラメーターの内容に置き換えます。
|
|
1112
|
+
* Replaces the range of characters that the beginIndex
|
|
1113
|
+
* and endIndex parameters specify with the contents of the newText parameter.
|
|
1114
|
+
*
|
|
1115
|
+
* @param {number} begin_index
|
|
1116
|
+
* @param {number} end_index
|
|
1117
|
+
* @param {string} new_text
|
|
1118
|
+
* @return {void}
|
|
1119
|
+
* @method
|
|
1120
|
+
* @public
|
|
1121
|
+
*/
|
|
1122
|
+
replaceText(begin_index, end_index, new_text) {
|
|
1123
|
+
begin_index |= 0;
|
|
1124
|
+
end_index |= 0;
|
|
1125
|
+
if (begin_index > -1 && end_index > -1 && end_index >= begin_index) {
|
|
1126
|
+
const text = this.text;
|
|
1127
|
+
if (begin_index >= text.length) {
|
|
1128
|
+
if (end_index >= text.length && end_index >= begin_index) {
|
|
1129
|
+
this.text = text + `${new_text}`;
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
else {
|
|
1133
|
+
this.text = text.slice(0, begin_index)
|
|
1134
|
+
+ `${new_text}`
|
|
1135
|
+
+ text.slice(end_index, text.length);
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* @description format パラメーターで指定したテキストフォーマットを、
|
|
1141
|
+
* テキストフィールド内の指定されたテキストに適用します。
|
|
1142
|
+
* Applies the text formatting that the format parameter specifies
|
|
1143
|
+
* to the specified text in a text field.
|
|
1144
|
+
*
|
|
1145
|
+
* @param {TextFormat} text_format
|
|
1146
|
+
* @param {number} [begin_index=-1]
|
|
1147
|
+
* @param {number} [end_index=-1]
|
|
1148
|
+
* @return {void}
|
|
1149
|
+
* @method
|
|
1150
|
+
* @public
|
|
1151
|
+
*/
|
|
1152
|
+
setTextFormat(text_format, begin_index = -1, end_index = -1) {
|
|
1153
|
+
// setup
|
|
1154
|
+
begin_index |= 0;
|
|
1155
|
+
end_index |= 0;
|
|
1156
|
+
const textData = this._$getTextData();
|
|
1157
|
+
this._$reset();
|
|
1158
|
+
switch (true) {
|
|
1159
|
+
case begin_index === -1 && end_index === -1:
|
|
1160
|
+
for (let idx = 0; idx < textData.length; ++idx) {
|
|
1161
|
+
this._$textFormatTable[idx] = text_format._$clone();
|
|
1162
|
+
}
|
|
1163
|
+
break;
|
|
1164
|
+
case begin_index > -1 && end_index === -1:
|
|
1165
|
+
{
|
|
1166
|
+
let idx = begin_index + 1;
|
|
1167
|
+
let obj = textData[idx];
|
|
1168
|
+
if (obj.mode === "wrap") {
|
|
1169
|
+
obj = textData[++idx];
|
|
1170
|
+
}
|
|
1171
|
+
this._$textFormatTable[idx] = text_format._$clone();
|
|
1172
|
+
}
|
|
1173
|
+
break;
|
|
1174
|
+
case begin_index > -1 && end_index > -1 && end_index > begin_index:
|
|
1175
|
+
{
|
|
1176
|
+
let offset = 0;
|
|
1177
|
+
for (let idx = begin_index; idx < end_index; ++idx) {
|
|
1178
|
+
const obj = textData[idx];
|
|
1179
|
+
if (!obj) {
|
|
1180
|
+
continue;
|
|
1181
|
+
}
|
|
1182
|
+
if (obj.mode === "wrap" || obj.mode === "break") {
|
|
1183
|
+
++end_index;
|
|
1184
|
+
--offset;
|
|
1185
|
+
continue;
|
|
1186
|
+
}
|
|
1187
|
+
this._$textFormatTable[idx + offset] = text_format._$clone();
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
break;
|
|
1191
|
+
}
|
|
1192
|
+
this._$getTextData();
|
|
1193
|
+
this._$resize();
|
|
1194
|
+
}
|
|
1195
|
+
/**
|
|
1196
|
+
* @return {array}
|
|
1197
|
+
* @method
|
|
1198
|
+
* @private
|
|
1199
|
+
*/
|
|
1200
|
+
_$getTextData() {
|
|
1201
|
+
if (!this._$createdTextData) {
|
|
1202
|
+
this._$createdTextData = true;
|
|
1203
|
+
// reset
|
|
1204
|
+
this._$textData.length = 0;
|
|
1205
|
+
this._$imageData.length = 0;
|
|
1206
|
+
this._$heightTable.length = 0;
|
|
1207
|
+
this._$textHeightTable.length = 0;
|
|
1208
|
+
this._$objectTable.length = 0;
|
|
1209
|
+
this._$widthTable.length = 0;
|
|
1210
|
+
this._$heightCache.clear();
|
|
1211
|
+
let tfCopyOffset = -1;
|
|
1212
|
+
if (this._$isHTML) {
|
|
1213
|
+
// html text
|
|
1214
|
+
let htmlText = this._$htmlText;
|
|
1215
|
+
const index = htmlText.search(/(< .*>|<>)/g);
|
|
1216
|
+
if (index > -1) {
|
|
1217
|
+
htmlText = htmlText.slice(0, index);
|
|
1218
|
+
}
|
|
1219
|
+
htmlText = htmlText.replace(/\r\n/g, "\r\r");
|
|
1220
|
+
if ($P_TAG.innerHTML !== htmlText) {
|
|
1221
|
+
$P_TAG.textContent = "";
|
|
1222
|
+
$P_TAG.insertAdjacentHTML("afterbegin", htmlText);
|
|
1223
|
+
}
|
|
1224
|
+
// setup
|
|
1225
|
+
let tf = this._$defaultTextFormat;
|
|
1226
|
+
if (this._$textData.length in this._$textFormatTable) {
|
|
1227
|
+
const tft = this._$textFormatTable[this._$textData.length]._$clone();
|
|
1228
|
+
tft._$merge(tf);
|
|
1229
|
+
tf = tft;
|
|
1230
|
+
}
|
|
1231
|
+
// init
|
|
1232
|
+
this._$totalWidth = 0;
|
|
1233
|
+
this._$heightTable[0] = 0;
|
|
1234
|
+
this._$textHeightTable[0] = this._$getTextHeight(tf);
|
|
1235
|
+
this._$widthTable[0] = 0;
|
|
1236
|
+
const obj = {
|
|
1237
|
+
"mode": "break",
|
|
1238
|
+
"x": 0,
|
|
1239
|
+
"yIndex": 0,
|
|
1240
|
+
"textFormat": tf._$clone()
|
|
1241
|
+
};
|
|
1242
|
+
this._$objectTable[0] = obj;
|
|
1243
|
+
this._$textData[0] = obj;
|
|
1244
|
+
this._$parseTag($P_TAG, tf._$clone(), tfCopyOffset);
|
|
1245
|
+
}
|
|
1246
|
+
else {
|
|
1247
|
+
// plain text
|
|
1248
|
+
const texts = this._$multiline
|
|
1249
|
+
? this._$text.split("\n")
|
|
1250
|
+
: [this._$text.replace("\n", "")];
|
|
1251
|
+
for (let idx = 0; idx < texts.length; ++idx) {
|
|
1252
|
+
// reset
|
|
1253
|
+
this._$totalWidth = 0;
|
|
1254
|
+
let tf = this.defaultTextFormat;
|
|
1255
|
+
const yIndex = this._$wordWrap || this._$multiline
|
|
1256
|
+
? this._$heightTable.length
|
|
1257
|
+
: 0;
|
|
1258
|
+
this._$heightTable[yIndex] = 0;
|
|
1259
|
+
this._$textHeightTable[yIndex] = this._$getTextHeight(tf);
|
|
1260
|
+
this._$widthTable[yIndex] = 0;
|
|
1261
|
+
if (yIndex) {
|
|
1262
|
+
this._$heightTable[yIndex] = this._$heightTable[yIndex - 1];
|
|
1263
|
+
this._$textHeightTable[yIndex] = this._$textHeightTable[yIndex - 1];
|
|
1264
|
+
}
|
|
1265
|
+
if (this._$textData.length in this._$textFormatTable) {
|
|
1266
|
+
const tft = this._$textFormatTable[this._$textData.length]._$clone();
|
|
1267
|
+
tft._$merge(tf);
|
|
1268
|
+
tf = tft;
|
|
1269
|
+
}
|
|
1270
|
+
const obj = {
|
|
1271
|
+
"mode": "break",
|
|
1272
|
+
"x": 0,
|
|
1273
|
+
"yIndex": yIndex,
|
|
1274
|
+
"textFormat": tf._$clone()
|
|
1275
|
+
};
|
|
1276
|
+
tf = this.defaultTextFormat;
|
|
1277
|
+
this._$objectTable[yIndex] = obj;
|
|
1278
|
+
this._$textData[this._$textData.length] = obj;
|
|
1279
|
+
// parse text data
|
|
1280
|
+
const text = texts[idx];
|
|
1281
|
+
if (text) {
|
|
1282
|
+
tfCopyOffset = this._$parseText(text, tf, tfCopyOffset);
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
// clear
|
|
1287
|
+
this._$heightCache.clear();
|
|
1288
|
+
}
|
|
1289
|
+
return this._$textData;
|
|
1290
|
+
}
|
|
1291
|
+
/**
|
|
1292
|
+
* @param {Element} tag
|
|
1293
|
+
* @param {TextFormat} text_format
|
|
1294
|
+
* @param {number} tf_copy_offset
|
|
1295
|
+
* @return {void}
|
|
1296
|
+
* @private
|
|
1297
|
+
*/
|
|
1298
|
+
_$parseTag(tag, text_format, tf_copy_offset) {
|
|
1299
|
+
const childNodes = tag.childNodes;
|
|
1300
|
+
const length = childNodes.length;
|
|
1301
|
+
for (let idx = 0; idx < length; ++idx) {
|
|
1302
|
+
let tf = text_format._$clone();
|
|
1303
|
+
const node = childNodes[idx];
|
|
1304
|
+
if (node.nodeType === 3) {
|
|
1305
|
+
tf_copy_offset = this._$parseText(node.nodeValue || "", tf, tf_copy_offset);
|
|
1306
|
+
continue;
|
|
1307
|
+
}
|
|
1308
|
+
switch (node.nodeName) {
|
|
1309
|
+
case "P":
|
|
1310
|
+
{
|
|
1311
|
+
if (node.hasAttribute("align")) {
|
|
1312
|
+
const align = node.getAttribute("align");
|
|
1313
|
+
if (align === "center" || align === "left" || align === "right") {
|
|
1314
|
+
tf.align = align;
|
|
1315
|
+
if (this._$textData.length === 1) {
|
|
1316
|
+
this._$textData[0].textFormat.align = tf.align;
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
this._$parseTag(node, tf, tf_copy_offset);
|
|
1321
|
+
if (!this._$multiline) {
|
|
1322
|
+
break;
|
|
1323
|
+
}
|
|
1324
|
+
// reset
|
|
1325
|
+
this._$totalWidth = this._$getImageOffsetX();
|
|
1326
|
+
const yIndex = this._$heightTable.length;
|
|
1327
|
+
this._$heightTable[yIndex] = 0;
|
|
1328
|
+
this._$textHeightTable[yIndex] = 0;
|
|
1329
|
+
this._$widthTable[yIndex] = 0;
|
|
1330
|
+
if (yIndex) {
|
|
1331
|
+
this._$heightTable[yIndex] = this._$heightTable[yIndex - 1];
|
|
1332
|
+
this._$textHeightTable[yIndex] = this._$textHeightTable[yIndex - 1];
|
|
1333
|
+
}
|
|
1334
|
+
if (this._$textData.length in this._$textFormatTable) {
|
|
1335
|
+
const tft = this._$textFormatTable[this._$textData.length]._$clone();
|
|
1336
|
+
tft._$merge(tf);
|
|
1337
|
+
tf = tft;
|
|
1338
|
+
}
|
|
1339
|
+
const obj = {
|
|
1340
|
+
"mode": "break",
|
|
1341
|
+
"x": 0,
|
|
1342
|
+
"yIndex": yIndex,
|
|
1343
|
+
"textFormat": tf
|
|
1344
|
+
};
|
|
1345
|
+
this._$objectTable[yIndex] = obj;
|
|
1346
|
+
this._$textData.push(obj);
|
|
1347
|
+
}
|
|
1348
|
+
break;
|
|
1349
|
+
case "B": // bold
|
|
1350
|
+
tf.bold = true;
|
|
1351
|
+
this._$parseTag(node, tf, tf_copy_offset);
|
|
1352
|
+
break;
|
|
1353
|
+
case "I": // italic
|
|
1354
|
+
tf.italic = true;
|
|
1355
|
+
this._$parseTag(node, tf, tf_copy_offset);
|
|
1356
|
+
break;
|
|
1357
|
+
case "U": // underline
|
|
1358
|
+
tf.underline = true;
|
|
1359
|
+
this._$parseTag(node, tf, tf_copy_offset);
|
|
1360
|
+
break;
|
|
1361
|
+
case "FONT": // FONT
|
|
1362
|
+
if (node.hasAttribute("face")) {
|
|
1363
|
+
tf.font = node.getAttribute("face");
|
|
1364
|
+
}
|
|
1365
|
+
if (node.hasAttribute("size")) {
|
|
1366
|
+
const size = node.getAttribute("size");
|
|
1367
|
+
if (size) {
|
|
1368
|
+
tf.size = +size;
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
if (node.hasAttribute("color")) {
|
|
1372
|
+
tf.color = $toColorInt(node.getAttribute("color"));
|
|
1373
|
+
}
|
|
1374
|
+
if (node.hasAttribute("letterSpacing")) {
|
|
1375
|
+
const letterSpacing = node.getAttribute("size");
|
|
1376
|
+
if (letterSpacing) {
|
|
1377
|
+
tf.letterSpacing = +letterSpacing;
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
this._$parseTag(node, tf, tf_copy_offset);
|
|
1381
|
+
break;
|
|
1382
|
+
case "BR": // br
|
|
1383
|
+
{
|
|
1384
|
+
if (!this._$multiline) {
|
|
1385
|
+
break;
|
|
1386
|
+
}
|
|
1387
|
+
// add y index
|
|
1388
|
+
const yIndex = this._$heightTable.length;
|
|
1389
|
+
this._$heightTable[yIndex] = this._$heightTable[yIndex - 1];
|
|
1390
|
+
this._$textHeightTable[yIndex] = this._$textHeightTable[yIndex - 1];
|
|
1391
|
+
this._$widthTable[yIndex] = 0;
|
|
1392
|
+
// reset
|
|
1393
|
+
this._$totalWidth = this._$getImageOffsetX();
|
|
1394
|
+
// new clone
|
|
1395
|
+
tf.indent = 0;
|
|
1396
|
+
// set x offset
|
|
1397
|
+
const obj = {
|
|
1398
|
+
"mode": "break",
|
|
1399
|
+
"x": 0,
|
|
1400
|
+
"yIndex": yIndex,
|
|
1401
|
+
"textFormat": tf
|
|
1402
|
+
};
|
|
1403
|
+
this._$objectTable[yIndex] = obj;
|
|
1404
|
+
this._$textData[this._$textData.length] = obj;
|
|
1405
|
+
}
|
|
1406
|
+
break;
|
|
1407
|
+
case "IMG":
|
|
1408
|
+
{
|
|
1409
|
+
if (!node.hasAttribute("src")) {
|
|
1410
|
+
break;
|
|
1411
|
+
}
|
|
1412
|
+
const src = node.getAttribute("src");
|
|
1413
|
+
if (!src) {
|
|
1414
|
+
break;
|
|
1415
|
+
}
|
|
1416
|
+
let width = 0;
|
|
1417
|
+
if (node.hasAttribute("width")) {
|
|
1418
|
+
const attribute = node.getAttribute("width");
|
|
1419
|
+
if (attribute) {
|
|
1420
|
+
width = +attribute;
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
let height = 0;
|
|
1424
|
+
if (node.hasAttribute("height")) {
|
|
1425
|
+
const attribute = node.getAttribute("height");
|
|
1426
|
+
if (attribute) {
|
|
1427
|
+
height = +attribute;
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
let vspace = 8;
|
|
1431
|
+
if (node.hasAttribute("vspace")) {
|
|
1432
|
+
const attribute = node.getAttribute("vspace");
|
|
1433
|
+
if (attribute) {
|
|
1434
|
+
vspace = +attribute;
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
let hspace = 8;
|
|
1438
|
+
if (node.hasAttribute("hspace")) {
|
|
1439
|
+
const attribute = node.getAttribute("hspace");
|
|
1440
|
+
if (attribute) {
|
|
1441
|
+
hspace = +attribute;
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
let totalTextHeight = 0;
|
|
1445
|
+
for (let idx = 0; idx < this._$textHeightTable.length; idx++) {
|
|
1446
|
+
totalTextHeight += this._$textHeightTable[idx];
|
|
1447
|
+
}
|
|
1448
|
+
const image = new Image();
|
|
1449
|
+
const obj = {
|
|
1450
|
+
"mode": "image",
|
|
1451
|
+
"image": image,
|
|
1452
|
+
"src": src,
|
|
1453
|
+
"loaded": false,
|
|
1454
|
+
"x": 0,
|
|
1455
|
+
"y": totalTextHeight,
|
|
1456
|
+
"width": width,
|
|
1457
|
+
"height": height,
|
|
1458
|
+
"hspace": hspace,
|
|
1459
|
+
"vspace": vspace,
|
|
1460
|
+
"textFormat": tf._$clone()
|
|
1461
|
+
};
|
|
1462
|
+
image.crossOrigin = "anonymous";
|
|
1463
|
+
image.addEventListener("load", () => {
|
|
1464
|
+
if (!obj.width) {
|
|
1465
|
+
obj.width = image.width;
|
|
1466
|
+
}
|
|
1467
|
+
if (!obj.height) {
|
|
1468
|
+
obj.height = image.height;
|
|
1469
|
+
}
|
|
1470
|
+
obj.loaded = true;
|
|
1471
|
+
this._$reload();
|
|
1472
|
+
});
|
|
1473
|
+
image.src = src;
|
|
1474
|
+
if (this._$imageData.length > 0) {
|
|
1475
|
+
const prevImage = this._$imageData[this._$imageData.length - 1];
|
|
1476
|
+
const imageBottom = prevImage.y + prevImage.height + prevImage.vspace * 2;
|
|
1477
|
+
obj.y = $Math.max(totalTextHeight, imageBottom);
|
|
1478
|
+
}
|
|
1479
|
+
this._$textData[this._$textData.length] = obj;
|
|
1480
|
+
this._$imageData[this._$imageData.length] = obj;
|
|
1481
|
+
}
|
|
1482
|
+
break;
|
|
1483
|
+
default:
|
|
1484
|
+
this._$parseTag(node, tf, tf_copy_offset);
|
|
1485
|
+
break;
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
/**
|
|
1490
|
+
* @param {string} text
|
|
1491
|
+
* @param {TextFormat} text_format
|
|
1492
|
+
* @param {number} tf_copy_offset
|
|
1493
|
+
* @returns {number}
|
|
1494
|
+
* @method
|
|
1495
|
+
* @private
|
|
1496
|
+
*/
|
|
1497
|
+
_$parseText(text, text_format, tf_copy_offset) {
|
|
1498
|
+
let yIndex = this._$heightTable.length - 1;
|
|
1499
|
+
// new format
|
|
1500
|
+
let tf = text_format._$clone();
|
|
1501
|
+
const matrix = this._$transform.concatenatedMatrix._$matrix;
|
|
1502
|
+
const boundsWidth = (this._$originBounds.xMax - this._$originBounds.xMin)
|
|
1503
|
+
* (matrix[0] / matrix[3]);
|
|
1504
|
+
$poolFloat32Array6(matrix);
|
|
1505
|
+
const maxWidth = boundsWidth - tf._$widthMargin() - 4;
|
|
1506
|
+
for (let idx = 0; idx < text.length; ++idx) {
|
|
1507
|
+
tf = text_format._$clone();
|
|
1508
|
+
if (this._$textData.length + tf_copy_offset in this._$textFormatTable) {
|
|
1509
|
+
const tft = this._$textFormatTable[this._$textData.length + tf_copy_offset]._$clone();
|
|
1510
|
+
tft._$merge(tf);
|
|
1511
|
+
tf = tft;
|
|
1512
|
+
}
|
|
1513
|
+
// reset object
|
|
1514
|
+
const obj = {
|
|
1515
|
+
"mode": "text",
|
|
1516
|
+
"text": text[idx],
|
|
1517
|
+
"x": 0,
|
|
1518
|
+
"width": 0,
|
|
1519
|
+
"height": 0,
|
|
1520
|
+
"yIndex": yIndex,
|
|
1521
|
+
"textFormat": tf
|
|
1522
|
+
};
|
|
1523
|
+
let breakCode = false;
|
|
1524
|
+
if (this._$multiline) {
|
|
1525
|
+
breakCode = obj.text === "\n" || obj.text === "\r" || obj.text === "\n\r";
|
|
1526
|
+
}
|
|
1527
|
+
const leading = yIndex ? tf.leading || 0 : 0;
|
|
1528
|
+
let width = 0;
|
|
1529
|
+
let height = 0;
|
|
1530
|
+
let textHeight = 0;
|
|
1531
|
+
let wrapObj;
|
|
1532
|
+
if (!$textContext) {
|
|
1533
|
+
continue;
|
|
1534
|
+
}
|
|
1535
|
+
$textContext.font = tf._$generateFontStyle();
|
|
1536
|
+
width = $textContext.measureText(obj.text || "").width;
|
|
1537
|
+
width += tf.letterSpacing || 0;
|
|
1538
|
+
height = this._$getTextHeight(tf);
|
|
1539
|
+
textHeight = height + leading;
|
|
1540
|
+
obj.height = height;
|
|
1541
|
+
if (breakCode ||
|
|
1542
|
+
this._$wordWrap && this._$totalWidth + width > maxWidth) {
|
|
1543
|
+
// add y index
|
|
1544
|
+
this._$widthTable[++yIndex] = 0;
|
|
1545
|
+
obj.yIndex = yIndex;
|
|
1546
|
+
this._$heightTable[yIndex] = this._$heightTable[yIndex - 1];
|
|
1547
|
+
this._$textHeightTable[yIndex] = this._$textHeightTable[yIndex - 1];
|
|
1548
|
+
// reset
|
|
1549
|
+
this._$totalWidth = this._$getImageOffsetX();
|
|
1550
|
+
// new clone
|
|
1551
|
+
tf = tf._$clone();
|
|
1552
|
+
tf.indent = 0;
|
|
1553
|
+
// set x offset
|
|
1554
|
+
const mode = breakCode ? "break" : "wrap";
|
|
1555
|
+
wrapObj = {
|
|
1556
|
+
"mode": mode,
|
|
1557
|
+
"x": 0,
|
|
1558
|
+
"yIndex": yIndex,
|
|
1559
|
+
"textFormat": tf
|
|
1560
|
+
};
|
|
1561
|
+
this._$objectTable[yIndex] = wrapObj;
|
|
1562
|
+
if (!breakCode) {
|
|
1563
|
+
--tf_copy_offset;
|
|
1564
|
+
}
|
|
1565
|
+
let text = obj.text || "";
|
|
1566
|
+
let chunkLength = 0;
|
|
1567
|
+
let isSeparated = true;
|
|
1568
|
+
const pattern = /[0-9a-zA-Z?!;:.,?!。、;:〜]/g;
|
|
1569
|
+
while (text.match(pattern)) {
|
|
1570
|
+
++chunkLength;
|
|
1571
|
+
const prevObj = this._$textData[this._$textData.length - chunkLength];
|
|
1572
|
+
if (prevObj.mode !== "text") {
|
|
1573
|
+
isSeparated = false;
|
|
1574
|
+
break;
|
|
1575
|
+
}
|
|
1576
|
+
text = prevObj.text || "";
|
|
1577
|
+
}
|
|
1578
|
+
if (chunkLength > 1 && this._$textData) {
|
|
1579
|
+
const text = this._$textData[this._$textData.length - chunkLength + 1].text || "";
|
|
1580
|
+
if (text.match(/[0-9a-zA-Z]/g)) {
|
|
1581
|
+
--chunkLength;
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
if (chunkLength > 0 && isSeparated) {
|
|
1585
|
+
const insertIdx = this._$textData.length - chunkLength;
|
|
1586
|
+
this._$textData.splice(insertIdx, 0, wrapObj);
|
|
1587
|
+
// prev line
|
|
1588
|
+
let offset = 1;
|
|
1589
|
+
let targetObj = this._$textData[insertIdx - offset];
|
|
1590
|
+
this._$widthTable[yIndex - 1] = 0;
|
|
1591
|
+
this._$heightTable[yIndex - 1] = 0;
|
|
1592
|
+
this._$textHeightTable[yIndex - 1] = 0;
|
|
1593
|
+
while (targetObj.mode === "text") {
|
|
1594
|
+
height = this._$getTextHeight(targetObj.textFormat);
|
|
1595
|
+
textHeight = height + leading;
|
|
1596
|
+
this._$widthTable[yIndex - 1] += targetObj.width || 0;
|
|
1597
|
+
this._$heightTable[yIndex - 1] = $Math.max(this._$heightTable[yIndex - 1], height);
|
|
1598
|
+
this._$textHeightTable[yIndex - 1] = $Math.max(this._$textHeightTable[yIndex - 1], textHeight);
|
|
1599
|
+
++offset;
|
|
1600
|
+
targetObj = this._$textData[insertIdx - offset];
|
|
1601
|
+
}
|
|
1602
|
+
// new line
|
|
1603
|
+
offset = 1;
|
|
1604
|
+
while (this._$textData.length > insertIdx + offset) {
|
|
1605
|
+
targetObj = this._$textData[insertIdx + offset];
|
|
1606
|
+
++offset;
|
|
1607
|
+
height = this._$getTextHeight(targetObj.textFormat);
|
|
1608
|
+
textHeight = height + leading;
|
|
1609
|
+
this._$heightTable[yIndex] = $Math.max(this._$heightTable[yIndex], height);
|
|
1610
|
+
this._$textHeightTable[yIndex] = $Math.max(this._$textHeightTable[yIndex], textHeight);
|
|
1611
|
+
targetObj.x = this._$totalWidth;
|
|
1612
|
+
targetObj.yIndex = yIndex;
|
|
1613
|
+
this._$totalWidth += targetObj.width || 0;
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
else {
|
|
1617
|
+
this._$textData[this._$textData.length] = wrapObj;
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
if (!breakCode) {
|
|
1621
|
+
// width data
|
|
1622
|
+
obj.width = width;
|
|
1623
|
+
obj.x = this._$totalWidth;
|
|
1624
|
+
this._$totalWidth += width;
|
|
1625
|
+
if (this._$widthTable) {
|
|
1626
|
+
this._$widthTable[yIndex] = $Math.max(this._$widthTable[yIndex], this._$totalWidth);
|
|
1627
|
+
}
|
|
1628
|
+
// height data
|
|
1629
|
+
this._$heightTable[yIndex] = $Math.max(this._$heightTable[yIndex], height);
|
|
1630
|
+
this._$textHeightTable[yIndex] = $Math.max(this._$textHeightTable[yIndex], textHeight);
|
|
1631
|
+
this._$textData[this._$textData.length] = obj;
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
return tf_copy_offset;
|
|
1635
|
+
}
|
|
1636
|
+
/**
|
|
1637
|
+
* @param {TextFormat} text_format
|
|
1638
|
+
* @return {number}
|
|
1639
|
+
* @private
|
|
1640
|
+
*/
|
|
1641
|
+
_$getTextHeight(text_format) {
|
|
1642
|
+
const size = text_format.size || 0;
|
|
1643
|
+
const font = text_format.font || "";
|
|
1644
|
+
const weight = text_format.bold ? "bold" : "normal";
|
|
1645
|
+
// use cache
|
|
1646
|
+
const key = `${size}_${font}_${weight}`;
|
|
1647
|
+
if (this._$heightCache.has(key)) {
|
|
1648
|
+
return this._$heightCache.get(key) || 0;
|
|
1649
|
+
}
|
|
1650
|
+
// update dom data
|
|
1651
|
+
const style = $DIV.style;
|
|
1652
|
+
const fontSize = `${size}px`;
|
|
1653
|
+
if (style.fontSize !== fontSize) {
|
|
1654
|
+
style.fontSize = fontSize;
|
|
1655
|
+
}
|
|
1656
|
+
if (style.fontFamily !== font) {
|
|
1657
|
+
style.fontFamily = font;
|
|
1658
|
+
}
|
|
1659
|
+
if (style.fontWeight !== weight) {
|
|
1660
|
+
style.fontWeight = weight;
|
|
1661
|
+
}
|
|
1662
|
+
const height = 10 > size
|
|
1663
|
+
? $DIV.clientHeight * size * 0.1
|
|
1664
|
+
: $DIV.clientHeight;
|
|
1665
|
+
// cache
|
|
1666
|
+
this._$heightCache.set(key, height);
|
|
1667
|
+
return height;
|
|
1668
|
+
}
|
|
1669
|
+
/**
|
|
1670
|
+
* @return {number}
|
|
1671
|
+
* @private
|
|
1672
|
+
*/
|
|
1673
|
+
_$getImageOffsetX() {
|
|
1674
|
+
if (!this._$imageData.length) {
|
|
1675
|
+
return 0;
|
|
1676
|
+
}
|
|
1677
|
+
let totalTextHeight = 0;
|
|
1678
|
+
for (let idx = 0; idx < this._$textHeightTable.length; ++idx) {
|
|
1679
|
+
totalTextHeight += this._$textHeightTable[idx];
|
|
1680
|
+
}
|
|
1681
|
+
if (this._$imageData) {
|
|
1682
|
+
for (let idx = 0; idx < this._$imageData.length; ++idx) {
|
|
1683
|
+
const image = this._$imageData[idx];
|
|
1684
|
+
const imageHeight = image.height + image.vspace * 2;
|
|
1685
|
+
if (image.y <= totalTextHeight
|
|
1686
|
+
&& totalTextHeight < image.y + imageHeight) {
|
|
1687
|
+
return image.width + image.hspace * 2;
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
return 0;
|
|
1692
|
+
}
|
|
1693
|
+
/**
|
|
1694
|
+
* @return {void}
|
|
1695
|
+
* @method
|
|
1696
|
+
* @private
|
|
1697
|
+
*/
|
|
1698
|
+
_$reset() {
|
|
1699
|
+
this._$createdTextData = false;
|
|
1700
|
+
this._$textData.length = 0;
|
|
1701
|
+
this._$imageData.length = 0;
|
|
1702
|
+
this._$heightTable.length = 0;
|
|
1703
|
+
this._$textHeightTable.length = 0;
|
|
1704
|
+
this._$widthTable.length = 0;
|
|
1705
|
+
this._$objectTable.length = 0;
|
|
1706
|
+
this._$textHeight = null;
|
|
1707
|
+
this._$textWidth = null;
|
|
1708
|
+
this._$totalWidth = 0;
|
|
1709
|
+
this._$maxScrollH = null;
|
|
1710
|
+
this._$maxScrollV = null;
|
|
1711
|
+
this._$doChanged();
|
|
1712
|
+
$doUpdated();
|
|
1713
|
+
// cache clear
|
|
1714
|
+
const player = $currentPlayer();
|
|
1715
|
+
player.cacheStore.removeCache(this._$instanceId);
|
|
1716
|
+
}
|
|
1717
|
+
/**
|
|
1718
|
+
* @return {void}
|
|
1719
|
+
* @method
|
|
1720
|
+
* @private
|
|
1721
|
+
*/
|
|
1722
|
+
_$reload() {
|
|
1723
|
+
this._$reset();
|
|
1724
|
+
this._$getTextData();
|
|
1725
|
+
if (this._$autoSize === "none" && this._$autoFontSize) {
|
|
1726
|
+
let fontSize = this._$defaultTextFormat.size || 0;
|
|
1727
|
+
const cacheSize = fontSize;
|
|
1728
|
+
if (this.width && this.textWidth
|
|
1729
|
+
&& this.textWidth > this.width) {
|
|
1730
|
+
while (this.textWidth > this.width) {
|
|
1731
|
+
this._$defaultTextFormat.size = fontSize--;
|
|
1732
|
+
if (1 > fontSize) {
|
|
1733
|
+
this._$defaultTextFormat.size = 1;
|
|
1734
|
+
break;
|
|
1735
|
+
}
|
|
1736
|
+
this._$reset();
|
|
1737
|
+
this._$getTextData();
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
if (this.height && this.textHeight
|
|
1741
|
+
&& this.textHeight > this.height) {
|
|
1742
|
+
while (this.textHeight > this.height) {
|
|
1743
|
+
this._$defaultTextFormat.size = fontSize--;
|
|
1744
|
+
if (1 > fontSize) {
|
|
1745
|
+
this._$defaultTextFormat.size = 1;
|
|
1746
|
+
break;
|
|
1747
|
+
}
|
|
1748
|
+
this._$reset();
|
|
1749
|
+
this._$getTextData();
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
// restore
|
|
1753
|
+
this._$defaultTextFormat.size = cacheSize;
|
|
1754
|
+
}
|
|
1755
|
+
this._$resize();
|
|
1756
|
+
}
|
|
1757
|
+
/**
|
|
1758
|
+
* @return {void}
|
|
1759
|
+
* @method
|
|
1760
|
+
* @private
|
|
1761
|
+
*/
|
|
1762
|
+
_$resize() {
|
|
1763
|
+
// update bounds
|
|
1764
|
+
if (this._$autoSize !== "none") {
|
|
1765
|
+
const tf = this._$defaultTextFormat;
|
|
1766
|
+
const width = this.textWidth + 4 + tf._$widthMargin();
|
|
1767
|
+
if (this._$wordWrap) {
|
|
1768
|
+
this._$bounds.xMax = this._$originBounds.xMax;
|
|
1769
|
+
this._$bounds.xMin = this._$originBounds.xMin;
|
|
1770
|
+
}
|
|
1771
|
+
else {
|
|
1772
|
+
switch (this._$autoSize) {
|
|
1773
|
+
case "left":
|
|
1774
|
+
this._$bounds.xMax = width + this._$bounds.xMin;
|
|
1775
|
+
break;
|
|
1776
|
+
case "center":
|
|
1777
|
+
this._$bounds.xMax = width + this._$bounds.xMin;
|
|
1778
|
+
break;
|
|
1779
|
+
case "right":
|
|
1780
|
+
this._$bounds.xMax = this._$originBounds.xMax
|
|
1781
|
+
- (this._$originBounds.xMax - this._$originBounds.xMin
|
|
1782
|
+
- (width - this._$originBounds.xMin));
|
|
1783
|
+
break;
|
|
1784
|
+
default:
|
|
1785
|
+
break;
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
// set height
|
|
1789
|
+
this._$bounds.yMax = this.textHeight
|
|
1790
|
+
+ 4 + this._$originBounds.yMin;
|
|
1791
|
+
}
|
|
1792
|
+
else {
|
|
1793
|
+
if (this._$scrollEnabled && !this._$scrollSprite) {
|
|
1794
|
+
this._$scrollSprite = new Sprite();
|
|
1795
|
+
this._$scrollSprite
|
|
1796
|
+
.graphics
|
|
1797
|
+
.beginFill("#000", 0.3)
|
|
1798
|
+
.drawRoundRect(0, 0, 3, 3, 3);
|
|
1799
|
+
this._$scrollSprite.scale9Grid = new Rectangle(1.5, 1.5, 0.1, 0.1);
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
/**
|
|
1804
|
+
* @param {object} obj
|
|
1805
|
+
* @param {number} width
|
|
1806
|
+
* @return {number}
|
|
1807
|
+
* @private
|
|
1808
|
+
*/
|
|
1809
|
+
_$getAlignOffset(obj, width) {
|
|
1810
|
+
// default
|
|
1811
|
+
const totalWidth = this._$widthTable[obj.yIndex];
|
|
1812
|
+
const textFormat = obj.textFormat;
|
|
1813
|
+
let indent = 0;
|
|
1814
|
+
indent += textFormat.blockIndent || 0;
|
|
1815
|
+
indent += textFormat.leftMargin || 0;
|
|
1816
|
+
const rightMargin = textFormat.rightMargin || 0;
|
|
1817
|
+
switch (true) {
|
|
1818
|
+
// wordWrap case
|
|
1819
|
+
case !this._$wordWrap && totalWidth > width:
|
|
1820
|
+
return $Math.max(0, indent);
|
|
1821
|
+
case textFormat.align === "center": // format CENTER
|
|
1822
|
+
case this._$autoSize === "center": // autoSize CENTER
|
|
1823
|
+
return $Math.max(0, width / 2 - indent - rightMargin - totalWidth / 2);
|
|
1824
|
+
case textFormat.align === "right": // format RIGHT
|
|
1825
|
+
case this._$autoSize === "right": // autoSize RIGHT
|
|
1826
|
+
return $Math.max(0, width - indent - totalWidth - rightMargin - 2);
|
|
1827
|
+
// autoSize LEFT
|
|
1828
|
+
// format LEFT
|
|
1829
|
+
default:
|
|
1830
|
+
return $Math.max(0, indent + 2);
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
/**
|
|
1834
|
+
* @param {Float32Array} [matrix=null]
|
|
1835
|
+
* @returns {object}
|
|
1836
|
+
* @method
|
|
1837
|
+
* @private
|
|
1838
|
+
*/
|
|
1839
|
+
_$getBounds(matrix = null) {
|
|
1840
|
+
if (matrix) {
|
|
1841
|
+
let multiMatrix = matrix;
|
|
1842
|
+
const rawMatrix = this._$transform._$rawMatrix();
|
|
1843
|
+
if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0
|
|
1844
|
+
|| rawMatrix[2] !== 0 || rawMatrix[3] !== 1
|
|
1845
|
+
|| rawMatrix[4] !== 0 || rawMatrix[5] !== 0) {
|
|
1846
|
+
multiMatrix = $multiplicationMatrix(matrix, rawMatrix);
|
|
1847
|
+
}
|
|
1848
|
+
return $boundsMatrix(this._$bounds, multiMatrix);
|
|
1849
|
+
}
|
|
1850
|
+
return $getBoundsObject(this._$bounds.xMin, this._$bounds.xMax, this._$bounds.yMin, this._$bounds.yMax);
|
|
1851
|
+
}
|
|
1852
|
+
/**
|
|
1853
|
+
* @param {object} character
|
|
1854
|
+
* @return {void}
|
|
1855
|
+
* @method
|
|
1856
|
+
* @private
|
|
1857
|
+
*/
|
|
1858
|
+
_$buildCharacter(character) {
|
|
1859
|
+
const textFormat = this._$defaultTextFormat;
|
|
1860
|
+
textFormat.font = character.font;
|
|
1861
|
+
textFormat.size = character.size | 0;
|
|
1862
|
+
textFormat.align = character.align;
|
|
1863
|
+
textFormat.color = character.color | 0;
|
|
1864
|
+
textFormat.leading = character.leading;
|
|
1865
|
+
textFormat.letterSpacing = character.letterSpacing;
|
|
1866
|
+
textFormat.leftMargin = character.leftMargin;
|
|
1867
|
+
textFormat.rightMargin = character.rightMargin;
|
|
1868
|
+
switch (character.fontType) {
|
|
1869
|
+
case 1:
|
|
1870
|
+
textFormat.bold = true;
|
|
1871
|
+
break;
|
|
1872
|
+
case 2:
|
|
1873
|
+
textFormat.italic = true;
|
|
1874
|
+
break;
|
|
1875
|
+
case 3:
|
|
1876
|
+
textFormat.bold = true;
|
|
1877
|
+
textFormat.italic = true;
|
|
1878
|
+
break;
|
|
1879
|
+
}
|
|
1880
|
+
// setup
|
|
1881
|
+
this._$type = character.inputType;
|
|
1882
|
+
this._$multiline = !!character.multiline;
|
|
1883
|
+
this._$wordWrap = !!character.wordWrap;
|
|
1884
|
+
this._$border = !!character.border;
|
|
1885
|
+
this._$scrollEnabled = !!character.scroll;
|
|
1886
|
+
this._$thickness = character.thickness | 0;
|
|
1887
|
+
this._$thicknessColor = character.thicknessColor | 0;
|
|
1888
|
+
// bounds
|
|
1889
|
+
this._$bounds.xMin = character.originBounds.xMin;
|
|
1890
|
+
this._$bounds.xMax = character.originBounds.xMax;
|
|
1891
|
+
this._$bounds.yMin = character.originBounds.yMin;
|
|
1892
|
+
this._$bounds.yMax = character.originBounds.yMax;
|
|
1893
|
+
this._$originBounds.xMin = character.originBounds.xMin;
|
|
1894
|
+
this._$originBounds.xMax = character.originBounds.xMax;
|
|
1895
|
+
this._$originBounds.yMin = character.originBounds.yMin;
|
|
1896
|
+
this._$originBounds.yMax = character.originBounds.yMax;
|
|
1897
|
+
switch (character.autoSize) {
|
|
1898
|
+
case 1:
|
|
1899
|
+
this.autoSize = character.align;
|
|
1900
|
+
break;
|
|
1901
|
+
case 2:
|
|
1902
|
+
this.autoFontSize = true;
|
|
1903
|
+
break;
|
|
1904
|
+
}
|
|
1905
|
+
this.text = character.text;
|
|
1906
|
+
if ($rendererWorker && this._$stage) {
|
|
1907
|
+
this._$createWorkerInstance();
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
/**
|
|
1911
|
+
* @param {object} character
|
|
1912
|
+
* @return {void}
|
|
1913
|
+
* @method
|
|
1914
|
+
* @private
|
|
1915
|
+
*/
|
|
1916
|
+
_$sync(character) {
|
|
1917
|
+
this._$buildCharacter(character);
|
|
1918
|
+
}
|
|
1919
|
+
/**
|
|
1920
|
+
* @param {object} tag
|
|
1921
|
+
* @param {DisplayObjectContainer} parent
|
|
1922
|
+
* @return {object}
|
|
1923
|
+
* @method
|
|
1924
|
+
* @private
|
|
1925
|
+
*/
|
|
1926
|
+
_$build(tag, parent) {
|
|
1927
|
+
const character = this
|
|
1928
|
+
._$baseBuild(tag, parent);
|
|
1929
|
+
this._$buildCharacter(character);
|
|
1930
|
+
return character;
|
|
1931
|
+
}
|
|
1932
|
+
/**
|
|
1933
|
+
* @param {CanvasToWebGLContext} context
|
|
1934
|
+
* @param {Float32Array} matrix
|
|
1935
|
+
* @returns {void}
|
|
1936
|
+
* @method
|
|
1937
|
+
* @private
|
|
1938
|
+
*/
|
|
1939
|
+
_$clip(context, matrix) {
|
|
1940
|
+
// size
|
|
1941
|
+
const bounds = this._$getBounds();
|
|
1942
|
+
const xMax = bounds.xMax;
|
|
1943
|
+
const xMin = bounds.xMin;
|
|
1944
|
+
const yMax = bounds.yMax;
|
|
1945
|
+
const yMin = bounds.yMin;
|
|
1946
|
+
$poolBoundsObject(bounds);
|
|
1947
|
+
const width = $Math.ceil($Math.abs(xMax - xMin));
|
|
1948
|
+
const height = $Math.ceil($Math.abs(yMax - yMin));
|
|
1949
|
+
if (!width || !height) {
|
|
1950
|
+
return;
|
|
1951
|
+
}
|
|
1952
|
+
let multiMatrix = matrix;
|
|
1953
|
+
const rawMatrix = this._$transform._$rawMatrix();
|
|
1954
|
+
if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0
|
|
1955
|
+
|| rawMatrix[2] !== 0 || rawMatrix[3] !== 1
|
|
1956
|
+
|| rawMatrix[4] !== 0 || rawMatrix[5] !== 0) {
|
|
1957
|
+
multiMatrix = $multiplicationMatrix(matrix, rawMatrix);
|
|
1958
|
+
}
|
|
1959
|
+
context.reset();
|
|
1960
|
+
context.setTransform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
|
|
1961
|
+
context.beginPath();
|
|
1962
|
+
context.moveTo(0, 0);
|
|
1963
|
+
context.lineTo(width, 0);
|
|
1964
|
+
context.lineTo(width, height);
|
|
1965
|
+
context.lineTo(0, height);
|
|
1966
|
+
context.lineTo(0, 0);
|
|
1967
|
+
context.clip();
|
|
1968
|
+
if (multiMatrix !== matrix) {
|
|
1969
|
+
$poolFloat32Array6(multiMatrix);
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
/**
|
|
1973
|
+
* @param {CanvasToWebGLContext} context
|
|
1974
|
+
* @param {Float32Array} matrix
|
|
1975
|
+
* @param {Float32Array} color_transform
|
|
1976
|
+
* @return {void}
|
|
1977
|
+
* @method
|
|
1978
|
+
* @private
|
|
1979
|
+
*/
|
|
1980
|
+
_$draw(context, matrix, color_transform) {
|
|
1981
|
+
if (!this._$visible || this._$textAreaActive) {
|
|
1982
|
+
return;
|
|
1983
|
+
}
|
|
1984
|
+
if (!this._$background && !this._$border && !this.text) {
|
|
1985
|
+
return;
|
|
1986
|
+
}
|
|
1987
|
+
let multiColor = color_transform;
|
|
1988
|
+
const rawColor = this._$transform._$rawColorTransform();
|
|
1989
|
+
if (rawColor[0] !== 1 || rawColor[1] !== 1
|
|
1990
|
+
|| rawColor[2] !== 1 || rawColor[3] !== 1
|
|
1991
|
+
|| rawColor[4] !== 0 || rawColor[5] !== 0
|
|
1992
|
+
|| rawColor[6] !== 0 || rawColor[7] !== 0) {
|
|
1993
|
+
multiColor = $multiplicationColor(color_transform, rawColor);
|
|
1994
|
+
}
|
|
1995
|
+
const alpha = $clamp(multiColor[3] + multiColor[7] / 255, 0, 1);
|
|
1996
|
+
if (!alpha) {
|
|
1997
|
+
return;
|
|
1998
|
+
}
|
|
1999
|
+
let multiMatrix = matrix;
|
|
2000
|
+
const rawMatrix = this._$transform._$rawMatrix();
|
|
2001
|
+
if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0
|
|
2002
|
+
|| rawMatrix[2] !== 0 || rawMatrix[3] !== 1
|
|
2003
|
+
|| rawMatrix[4] !== 0 || rawMatrix[5] !== 0) {
|
|
2004
|
+
multiMatrix = $multiplicationMatrix(matrix, rawMatrix);
|
|
2005
|
+
}
|
|
2006
|
+
const baseBounds = this._$getBounds(null);
|
|
2007
|
+
baseBounds.xMin -= this._$thickness;
|
|
2008
|
+
baseBounds.xMax += this._$thickness;
|
|
2009
|
+
baseBounds.yMin -= this._$thickness;
|
|
2010
|
+
baseBounds.yMax += this._$thickness;
|
|
2011
|
+
const bounds = $boundsMatrix(baseBounds, multiMatrix);
|
|
2012
|
+
const xMax = +bounds.xMax;
|
|
2013
|
+
const xMin = +bounds.xMin;
|
|
2014
|
+
const yMax = +bounds.yMax;
|
|
2015
|
+
const yMin = +bounds.yMin;
|
|
2016
|
+
$poolBoundsObject(bounds);
|
|
2017
|
+
const width = $Math.ceil($Math.abs(xMax - xMin));
|
|
2018
|
+
const height = $Math.ceil($Math.abs(yMax - yMin));
|
|
2019
|
+
switch (true) {
|
|
2020
|
+
case width === 0:
|
|
2021
|
+
case height === 0:
|
|
2022
|
+
case width === -$Infinity:
|
|
2023
|
+
case height === -$Infinity:
|
|
2024
|
+
case width === $Infinity:
|
|
2025
|
+
case height === $Infinity:
|
|
2026
|
+
return;
|
|
2027
|
+
default:
|
|
2028
|
+
break;
|
|
2029
|
+
}
|
|
2030
|
+
if (0 > xMin + width || 0 > yMin + height) {
|
|
2031
|
+
return;
|
|
2032
|
+
}
|
|
2033
|
+
// cache current buffer
|
|
2034
|
+
const manager = context.frameBuffer;
|
|
2035
|
+
const currentAttachment = manager.currentAttachment;
|
|
2036
|
+
if (!currentAttachment
|
|
2037
|
+
|| xMin > currentAttachment.width
|
|
2038
|
+
|| yMin > currentAttachment.height) {
|
|
2039
|
+
return;
|
|
2040
|
+
}
|
|
2041
|
+
let xScale = +$Math.sqrt(multiMatrix[0] * multiMatrix[0]
|
|
2042
|
+
+ multiMatrix[1] * multiMatrix[1]);
|
|
2043
|
+
if (!$Number.isInteger(xScale)) {
|
|
2044
|
+
const value = xScale.toString();
|
|
2045
|
+
const index = value.indexOf("e");
|
|
2046
|
+
if (index !== -1) {
|
|
2047
|
+
xScale = +value.slice(0, index);
|
|
2048
|
+
}
|
|
2049
|
+
xScale = +xScale.toFixed(4);
|
|
2050
|
+
}
|
|
2051
|
+
let yScale = +$Math.sqrt(multiMatrix[2] * multiMatrix[2]
|
|
2052
|
+
+ multiMatrix[3] * multiMatrix[3]);
|
|
2053
|
+
if (!$Number.isInteger(yScale)) {
|
|
2054
|
+
const value = yScale.toString();
|
|
2055
|
+
const index = value.indexOf("e");
|
|
2056
|
+
if (index !== -1) {
|
|
2057
|
+
yScale = +value.slice(0, index);
|
|
2058
|
+
}
|
|
2059
|
+
yScale = +yScale.toFixed(4);
|
|
2060
|
+
}
|
|
2061
|
+
const filters = this._$filters || this.filters;
|
|
2062
|
+
if (0 > xMin + width || 0 > yMin + height) {
|
|
2063
|
+
if (filters.length && this._$canApply(filters)) {
|
|
2064
|
+
let filterBounds = $getBoundsObject(0, width, 0, height);
|
|
2065
|
+
for (let idx = 0; idx < filters.length; ++idx) {
|
|
2066
|
+
filterBounds = filters[idx]
|
|
2067
|
+
._$generateFilterRect(filterBounds, xScale, yScale);
|
|
2068
|
+
}
|
|
2069
|
+
if (0 > filterBounds.xMin + filterBounds.xMax
|
|
2070
|
+
|| 0 > filterBounds.yMin + filterBounds.yMax) {
|
|
2071
|
+
$poolBoundsObject(filterBounds);
|
|
2072
|
+
return;
|
|
2073
|
+
}
|
|
2074
|
+
$poolBoundsObject(filterBounds);
|
|
2075
|
+
}
|
|
2076
|
+
else {
|
|
2077
|
+
return;
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
2080
|
+
const blendMode = this._$blendMode || this.blendMode;
|
|
2081
|
+
const keys = $getArray(xScale, yScale);
|
|
2082
|
+
const instanceId = this._$instanceId;
|
|
2083
|
+
const player = $currentPlayer();
|
|
2084
|
+
const cacheStore = player.cacheStore;
|
|
2085
|
+
const cacheKeys = cacheStore.generateKeys(instanceId, keys);
|
|
2086
|
+
let texture = cacheStore.get(cacheKeys);
|
|
2087
|
+
// texture is small or renew
|
|
2088
|
+
if (this._$isUpdated()) {
|
|
2089
|
+
cacheStore.removeCache(instanceId);
|
|
2090
|
+
texture = null;
|
|
2091
|
+
}
|
|
2092
|
+
if (!texture) {
|
|
2093
|
+
// resize
|
|
2094
|
+
const lineWidth = $Math.min(1, $Math.max(xScale, yScale));
|
|
2095
|
+
const baseWidth = $Math.ceil($Math.abs(baseBounds.xMax - baseBounds.xMin) * xScale);
|
|
2096
|
+
const baseHeight = $Math.ceil($Math.abs(baseBounds.yMax - baseBounds.yMin) * yScale);
|
|
2097
|
+
// alpha reset
|
|
2098
|
+
multiColor[3] = 1;
|
|
2099
|
+
// new canvas
|
|
2100
|
+
const canvas = cacheStore.getCanvas();
|
|
2101
|
+
canvas.width = baseWidth + lineWidth * 2;
|
|
2102
|
+
canvas.height = baseHeight + lineWidth * 2;
|
|
2103
|
+
const ctx = canvas.getContext("2d");
|
|
2104
|
+
if (!ctx) {
|
|
2105
|
+
throw new Error("the context is null.");
|
|
2106
|
+
}
|
|
2107
|
+
// border and background
|
|
2108
|
+
if (this._$background || this._$border) {
|
|
2109
|
+
ctx.beginPath();
|
|
2110
|
+
ctx.moveTo(0, 0);
|
|
2111
|
+
ctx.lineTo(baseWidth, 0);
|
|
2112
|
+
ctx.lineTo(baseWidth, baseHeight);
|
|
2113
|
+
ctx.lineTo(0, baseHeight);
|
|
2114
|
+
ctx.lineTo(0, 0);
|
|
2115
|
+
if (this._$background) {
|
|
2116
|
+
const rgb = $intToRGBA(this._$backgroundColor);
|
|
2117
|
+
const alpha = $Math.max(0, $Math.min(rgb.A * 255 * multiColor[3] + multiColor[7], 255)) / 255;
|
|
2118
|
+
ctx.fillStyle = `rgba(${rgb.R},${rgb.G},${rgb.B},${alpha})`;
|
|
2119
|
+
ctx.fill();
|
|
2120
|
+
}
|
|
2121
|
+
if (this._$border) {
|
|
2122
|
+
const rgb = $intToRGBA(this._$borderColor);
|
|
2123
|
+
const alpha = $Math.max(0, $Math.min(rgb.A * 255 * multiColor[3] + multiColor[7], 255)) / 255;
|
|
2124
|
+
ctx.lineWidth = lineWidth;
|
|
2125
|
+
ctx.strokeStyle = `rgba(${rgb.R},${rgb.G},${rgb.B},${alpha})`;
|
|
2126
|
+
ctx.stroke();
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
// mask start
|
|
2130
|
+
ctx.save();
|
|
2131
|
+
ctx.beginPath();
|
|
2132
|
+
ctx.moveTo(2, 2);
|
|
2133
|
+
ctx.lineTo(baseWidth - 2, 2);
|
|
2134
|
+
ctx.lineTo(baseWidth - 2, baseHeight - 2);
|
|
2135
|
+
ctx.lineTo(2, baseHeight - 2);
|
|
2136
|
+
ctx.lineTo(2, 2);
|
|
2137
|
+
ctx.clip();
|
|
2138
|
+
ctx.beginPath();
|
|
2139
|
+
ctx.setTransform(xScale, 0, 0, yScale, 0, 0);
|
|
2140
|
+
this._$doDraw(ctx, matrix, multiColor, baseWidth / xScale);
|
|
2141
|
+
ctx.restore();
|
|
2142
|
+
texture = manager.createTextureFromCanvas(ctx.canvas);
|
|
2143
|
+
// set cache
|
|
2144
|
+
cacheStore.set(cacheKeys, texture);
|
|
2145
|
+
// destroy cache
|
|
2146
|
+
cacheStore.destroy(ctx);
|
|
2147
|
+
}
|
|
2148
|
+
let drawFilter = false;
|
|
2149
|
+
let offsetX = 0;
|
|
2150
|
+
let offsetY = 0;
|
|
2151
|
+
if (filters && filters.length
|
|
2152
|
+
&& this._$canApply(filters)) {
|
|
2153
|
+
drawFilter = true;
|
|
2154
|
+
texture = this._$drawFilter(context, texture, multiMatrix, filters, width, height);
|
|
2155
|
+
offsetX = texture._$offsetX;
|
|
2156
|
+
offsetY = texture._$offsetY;
|
|
2157
|
+
}
|
|
2158
|
+
const radianX = $Math.atan2(multiMatrix[1], multiMatrix[0]);
|
|
2159
|
+
const radianY = $Math.atan2(-multiMatrix[2], multiMatrix[3]);
|
|
2160
|
+
if (!drawFilter && (radianX || radianY)) {
|
|
2161
|
+
const tx = baseBounds.xMin * xScale;
|
|
2162
|
+
const ty = baseBounds.yMin * yScale;
|
|
2163
|
+
const cosX = $Math.cos(radianX);
|
|
2164
|
+
const sinX = $Math.sin(radianX);
|
|
2165
|
+
const cosY = $Math.cos(radianY);
|
|
2166
|
+
const sinY = $Math.sin(radianY);
|
|
2167
|
+
context.setTransform(cosX, sinX, -sinY, cosY, tx * cosX - ty * sinY + multiMatrix[4], tx * sinX + ty * cosY + multiMatrix[5]);
|
|
2168
|
+
}
|
|
2169
|
+
else {
|
|
2170
|
+
context.setTransform(1, 0, 0, 1, xMin - offsetX, yMin - offsetY);
|
|
2171
|
+
}
|
|
2172
|
+
// draw
|
|
2173
|
+
context.reset();
|
|
2174
|
+
context.globalAlpha = alpha;
|
|
2175
|
+
context.imageSmoothingEnabled = true;
|
|
2176
|
+
context.globalCompositeOperation = blendMode;
|
|
2177
|
+
context.drawImage(texture, 0, 0, texture.width, texture.height, multiColor);
|
|
2178
|
+
// get cache
|
|
2179
|
+
$poolArray(cacheKeys);
|
|
2180
|
+
$poolBoundsObject(baseBounds);
|
|
2181
|
+
// pool
|
|
2182
|
+
if (multiMatrix !== matrix) {
|
|
2183
|
+
$poolFloat32Array6(multiMatrix);
|
|
2184
|
+
}
|
|
2185
|
+
if (multiColor !== color_transform) {
|
|
2186
|
+
$poolFloat32Array8(multiColor);
|
|
2187
|
+
}
|
|
2188
|
+
}
|
|
2189
|
+
/**
|
|
2190
|
+
* @param {CanvasRenderingContext2D} context
|
|
2191
|
+
* @param {Float32Array} matrix
|
|
2192
|
+
* @param {Float32Array} color_transform
|
|
2193
|
+
* @param {number} width
|
|
2194
|
+
* @return {void}
|
|
2195
|
+
* @method
|
|
2196
|
+
* @private
|
|
2197
|
+
*/
|
|
2198
|
+
_$doDraw(context, matrix, color_transform, width) {
|
|
2199
|
+
// init
|
|
2200
|
+
const textData = this._$getTextData();
|
|
2201
|
+
const limitWidth = this.width;
|
|
2202
|
+
const limitHeight = this.height;
|
|
2203
|
+
// setup
|
|
2204
|
+
let xOffset = 0;
|
|
2205
|
+
let offsetHeight = 0;
|
|
2206
|
+
let currentV = 0;
|
|
2207
|
+
let yOffset = 0;
|
|
2208
|
+
if (this._$verticalAlign !== "top"
|
|
2209
|
+
&& this.height > this.textHeight) {
|
|
2210
|
+
switch (this._$verticalAlign) {
|
|
2211
|
+
case "middle":
|
|
2212
|
+
yOffset = (this.height - this.textHeight + 2) / 2;
|
|
2213
|
+
break;
|
|
2214
|
+
case "bottom":
|
|
2215
|
+
yOffset = this.height - this.textHeight + 2;
|
|
2216
|
+
break;
|
|
2217
|
+
}
|
|
2218
|
+
}
|
|
2219
|
+
for (let idx = 0; idx < textData.length; ++idx) {
|
|
2220
|
+
const obj = textData[idx];
|
|
2221
|
+
if (obj.width === 0) {
|
|
2222
|
+
continue;
|
|
2223
|
+
}
|
|
2224
|
+
// check
|
|
2225
|
+
const offsetWidth = xOffset + obj.x;
|
|
2226
|
+
if (this._$autoSize === "none"
|
|
2227
|
+
&& (offsetHeight > limitHeight || offsetWidth > limitWidth)) {
|
|
2228
|
+
continue;
|
|
2229
|
+
}
|
|
2230
|
+
const tf = obj.textFormat;
|
|
2231
|
+
// color
|
|
2232
|
+
const rgb = $intToRGBA(tf.color || 0);
|
|
2233
|
+
const alpha = $Math.max(0, $Math.min(rgb.A * 255 * color_transform[3] + color_transform[7], 255)) / 255;
|
|
2234
|
+
context.fillStyle = `rgba(${rgb.R},${rgb.G},${rgb.B},${alpha})`;
|
|
2235
|
+
if (this._$thickness) {
|
|
2236
|
+
const rgb = $intToRGBA(this._$thicknessColor);
|
|
2237
|
+
const alpha = $Math.max(0, $Math.min(rgb.A * 255 * color_transform[3] + color_transform[7], 255)) / 255;
|
|
2238
|
+
context.lineWidth = this._$thickness;
|
|
2239
|
+
context.strokeStyle = `rgba(${rgb.R},${rgb.G},${rgb.B},${alpha})`;
|
|
2240
|
+
}
|
|
2241
|
+
const yIndex = obj.yIndex | 0;
|
|
2242
|
+
switch (obj.mode) {
|
|
2243
|
+
case "break":
|
|
2244
|
+
case "wrap":
|
|
2245
|
+
currentV++;
|
|
2246
|
+
if (this.scrollV > currentV) {
|
|
2247
|
+
continue;
|
|
2248
|
+
}
|
|
2249
|
+
offsetHeight += this._$textHeightTable[yIndex];
|
|
2250
|
+
xOffset = this._$getAlignOffset(this._$objectTable[yIndex], width);
|
|
2251
|
+
if (tf.underline) {
|
|
2252
|
+
const offset = tf.size ? tf.size / 12 : 0;
|
|
2253
|
+
const rgb = $intToRGBA(tf.color || 0);
|
|
2254
|
+
const alpha = $Math.max(0, $Math.min(rgb.A * 255 * color_transform[3] + color_transform[7], 255)) / 255;
|
|
2255
|
+
context.lineWidth = $Math.max(1, 1 / $Math.min(matrix[0], matrix[3]));
|
|
2256
|
+
context.strokeStyle = `rgba(${rgb.R},${rgb.G},${rgb.B},${alpha})`;
|
|
2257
|
+
context.beginPath();
|
|
2258
|
+
context.moveTo(xOffset, yOffset + offsetHeight - offset);
|
|
2259
|
+
context.lineTo(xOffset + this._$widthTable[yIndex], yOffset + offsetHeight - offset);
|
|
2260
|
+
context.stroke();
|
|
2261
|
+
}
|
|
2262
|
+
break;
|
|
2263
|
+
case "text":
|
|
2264
|
+
{
|
|
2265
|
+
if (this.scrollV > currentV) {
|
|
2266
|
+
continue;
|
|
2267
|
+
}
|
|
2268
|
+
let offsetY = offsetHeight - this._$heightTable[0];
|
|
2269
|
+
if (!$isSafari && tf.size) {
|
|
2270
|
+
offsetY += $devicePixelRatio * (tf.size / 12);
|
|
2271
|
+
}
|
|
2272
|
+
context.beginPath();
|
|
2273
|
+
context.textBaseline = "top";
|
|
2274
|
+
context.font = $generateFontStyle(tf.font || "", tf.size || 0, !!tf.italic, !!tf.bold);
|
|
2275
|
+
if (this._$thickness) {
|
|
2276
|
+
context.strokeText(obj.text, offsetWidth, yOffset + offsetY);
|
|
2277
|
+
}
|
|
2278
|
+
context.fillText(obj.text, offsetWidth, yOffset + offsetY);
|
|
2279
|
+
}
|
|
2280
|
+
break;
|
|
2281
|
+
case "image":
|
|
2282
|
+
if (!obj.loaded) {
|
|
2283
|
+
continue;
|
|
2284
|
+
}
|
|
2285
|
+
context.beginPath();
|
|
2286
|
+
context.drawImage(obj.image, obj.hspace, yOffset + obj.y, obj.width, obj.height);
|
|
2287
|
+
break;
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
/**
|
|
2292
|
+
* @param {CanvasRenderingContext2D} context
|
|
2293
|
+
* @param {Float32Array} matrix
|
|
2294
|
+
* @param {object} options
|
|
2295
|
+
* @return {boolean}
|
|
2296
|
+
* @method
|
|
2297
|
+
* @private
|
|
2298
|
+
*/
|
|
2299
|
+
_$mouseHit(context, matrix, options) {
|
|
2300
|
+
if (!this._$visible) {
|
|
2301
|
+
return false;
|
|
2302
|
+
}
|
|
2303
|
+
return this._$hit(context, matrix, options);
|
|
2304
|
+
}
|
|
2305
|
+
/**
|
|
2306
|
+
* @param {CanvasRenderingContext2D} context
|
|
2307
|
+
* @param {Float32Array} matrix
|
|
2308
|
+
* @param {object} options
|
|
2309
|
+
* @return {boolean}
|
|
2310
|
+
* @method
|
|
2311
|
+
* @private
|
|
2312
|
+
*/
|
|
2313
|
+
_$hit(context, matrix, options) {
|
|
2314
|
+
let multiMatrix = matrix;
|
|
2315
|
+
const rawMatrix = this._$transform._$rawMatrix();
|
|
2316
|
+
if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0
|
|
2317
|
+
|| rawMatrix[2] !== 0 || rawMatrix[3] !== 1
|
|
2318
|
+
|| rawMatrix[4] !== 0 || rawMatrix[5] !== 0) {
|
|
2319
|
+
multiMatrix = $multiplicationMatrix(matrix, rawMatrix);
|
|
2320
|
+
}
|
|
2321
|
+
const baseBounds = this._$getBounds(null);
|
|
2322
|
+
const bounds = $boundsMatrix(baseBounds, multiMatrix);
|
|
2323
|
+
const xMax = +bounds.xMax;
|
|
2324
|
+
const xMin = +bounds.xMin;
|
|
2325
|
+
const yMax = +bounds.yMax;
|
|
2326
|
+
const yMin = +bounds.yMin;
|
|
2327
|
+
$poolBoundsObject(bounds);
|
|
2328
|
+
$poolBoundsObject(baseBounds);
|
|
2329
|
+
const width = $Math.ceil($Math.abs(xMax - xMin));
|
|
2330
|
+
const height = $Math.ceil($Math.abs(yMax - yMin));
|
|
2331
|
+
context.setTransform(1, 0, 0, 1, xMin, yMin);
|
|
2332
|
+
context.beginPath();
|
|
2333
|
+
context.moveTo(0, 0);
|
|
2334
|
+
context.lineTo(width, 0);
|
|
2335
|
+
context.lineTo(width, height);
|
|
2336
|
+
context.lineTo(0, height);
|
|
2337
|
+
context.lineTo(0, 0);
|
|
2338
|
+
if (multiMatrix !== matrix) {
|
|
2339
|
+
$poolFloat32Array6(multiMatrix);
|
|
2340
|
+
}
|
|
2341
|
+
return context.isPointInPath(options.x, options.y);
|
|
2342
|
+
}
|
|
2343
|
+
/**
|
|
2344
|
+
* @param {number} scale
|
|
2345
|
+
* @return {void}
|
|
2346
|
+
* @method
|
|
2347
|
+
* @private
|
|
2348
|
+
*/
|
|
2349
|
+
_$createTextAreaElement(scale) {
|
|
2350
|
+
// new text area
|
|
2351
|
+
if (!this._$textarea) {
|
|
2352
|
+
this._$textarea = $document.createElement("textarea");
|
|
2353
|
+
this._$textarea.value = this.text;
|
|
2354
|
+
this._$textarea.id = `${$PREFIX}_TextField_${this._$instanceId}`;
|
|
2355
|
+
if (!this._$wordWrap) {
|
|
2356
|
+
this._$textarea.wrap = "off";
|
|
2357
|
+
}
|
|
2358
|
+
const textFormat = this._$defaultTextFormat;
|
|
2359
|
+
// setup
|
|
2360
|
+
let style = "";
|
|
2361
|
+
style += "position: absolute;";
|
|
2362
|
+
style += "outline: 0;";
|
|
2363
|
+
style += `padding: 2px 2px 2px ${$Math.max(3, textFormat.leftMargin || 0)}px;`;
|
|
2364
|
+
style += "margin: 0;";
|
|
2365
|
+
style += "appearance: none;";
|
|
2366
|
+
style += "resize: none;";
|
|
2367
|
+
style += "overflow: hidden;";
|
|
2368
|
+
style += `z-index: ${0x7fffffff};`;
|
|
2369
|
+
style += "vertical-align: top;";
|
|
2370
|
+
this._$textarea.setAttribute("style", style);
|
|
2371
|
+
// add blur event
|
|
2372
|
+
this._$textarea.addEventListener(`${$PREFIX}_blur`, (event) => {
|
|
2373
|
+
// set new text
|
|
2374
|
+
const element = event.target;
|
|
2375
|
+
let value = element.value;
|
|
2376
|
+
if (value && this._$restrict) {
|
|
2377
|
+
let pattern = this._$restrict;
|
|
2378
|
+
if (pattern[0] !== "[") {
|
|
2379
|
+
pattern = "[" + pattern;
|
|
2380
|
+
}
|
|
2381
|
+
if (pattern[pattern.length - 1] !== "]") {
|
|
2382
|
+
pattern += "]";
|
|
2383
|
+
}
|
|
2384
|
+
const found = value.match(new $RegExp(pattern, "gm"));
|
|
2385
|
+
value = found ? found.join("") : "";
|
|
2386
|
+
}
|
|
2387
|
+
const player = $currentPlayer();
|
|
2388
|
+
const div = $document.getElementById(player.contentElementId);
|
|
2389
|
+
if (div) {
|
|
2390
|
+
const element = $document.getElementById(`${$PREFIX}_TextField_${this._$instanceId}`);
|
|
2391
|
+
if (element) {
|
|
2392
|
+
element.remove();
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
this.text = value;
|
|
2396
|
+
this._$focus = false;
|
|
2397
|
+
this._$textAreaActive = false;
|
|
2398
|
+
this._$doChanged();
|
|
2399
|
+
$doUpdated();
|
|
2400
|
+
});
|
|
2401
|
+
// input event
|
|
2402
|
+
this._$textarea.addEventListener("input", (event) => {
|
|
2403
|
+
// set new text
|
|
2404
|
+
const element = event.target;
|
|
2405
|
+
const player = $currentPlayer();
|
|
2406
|
+
let value = element.value;
|
|
2407
|
+
// SafariではInputEvent.isComposingがundefined
|
|
2408
|
+
if (this._$restrict && !this._$isComposing && value) {
|
|
2409
|
+
let pattern = this._$restrict;
|
|
2410
|
+
if (pattern[0] !== "[") {
|
|
2411
|
+
pattern = "[" + pattern;
|
|
2412
|
+
}
|
|
2413
|
+
if (pattern[pattern.length - 1] !== "]") {
|
|
2414
|
+
pattern += "]";
|
|
2415
|
+
}
|
|
2416
|
+
const found = value.match(new $RegExp(pattern, "gm"));
|
|
2417
|
+
value = found ? found.join("") : "";
|
|
2418
|
+
}
|
|
2419
|
+
if (!this._$isComposing && this.text !== value) {
|
|
2420
|
+
// update
|
|
2421
|
+
this.text = value;
|
|
2422
|
+
element.value = value;
|
|
2423
|
+
if (this.willTrigger(Next2DEvent.CHANGE)) {
|
|
2424
|
+
this.dispatchEvent(new Next2DEvent(Next2DEvent.CHANGE, true));
|
|
2425
|
+
}
|
|
2426
|
+
// setup
|
|
2427
|
+
// const element = this._$textarea;
|
|
2428
|
+
const matrix = this._$transform.concatenatedMatrix;
|
|
2429
|
+
const bounds = this._$getBounds(null);
|
|
2430
|
+
element.style.left = `${$Math.floor((matrix.tx + bounds.xMin + player.x / player._$scale / $devicePixelRatio) * player._$scale)}px`;
|
|
2431
|
+
element.style.top = `${$Math.floor((matrix.ty + bounds.yMin + player.y / player._$scale / $devicePixelRatio) * player._$scale)}px`;
|
|
2432
|
+
element.style.width = `${$Math.ceil((this.width - 1) * player._$scale)}px`;
|
|
2433
|
+
element.style.height = `${$Math.ceil((this.height - 1) * player._$scale)}px`;
|
|
2434
|
+
}
|
|
2435
|
+
});
|
|
2436
|
+
// IME入力開始時のevent
|
|
2437
|
+
this._$textarea.addEventListener("compositionstart", () => {
|
|
2438
|
+
this._$isComposing = true;
|
|
2439
|
+
});
|
|
2440
|
+
// IME入力確定時のevent
|
|
2441
|
+
this._$textarea.addEventListener("compositionend", (event) => {
|
|
2442
|
+
this._$isComposing = false;
|
|
2443
|
+
const element = event.target;
|
|
2444
|
+
let value = element.value;
|
|
2445
|
+
if (!this._$restrict || !value) {
|
|
2446
|
+
return;
|
|
2447
|
+
}
|
|
2448
|
+
let pattern = this._$restrict;
|
|
2449
|
+
if (pattern[0] !== "[") {
|
|
2450
|
+
pattern = "[" + pattern;
|
|
2451
|
+
}
|
|
2452
|
+
if (pattern[pattern.length - 1] !== "]") {
|
|
2453
|
+
pattern += "]";
|
|
2454
|
+
}
|
|
2455
|
+
const found = value.match(new $RegExp(pattern, "gm"));
|
|
2456
|
+
value = found ? found.join("") : "";
|
|
2457
|
+
// update
|
|
2458
|
+
this.text = value;
|
|
2459
|
+
element.value = value;
|
|
2460
|
+
});
|
|
2461
|
+
// add click event
|
|
2462
|
+
this._$textarea.addEventListener("click", () => {
|
|
2463
|
+
if (this.willTrigger(Next2DMouseEvent.CLICK)) {
|
|
2464
|
+
this.dispatchEvent(new Next2DMouseEvent(Next2DMouseEvent.CLICK));
|
|
2465
|
+
}
|
|
2466
|
+
});
|
|
2467
|
+
// add mousewheel event
|
|
2468
|
+
this._$textarea.addEventListener($MOUSE_WHEEL, (event) => {
|
|
2469
|
+
this.scrollV += event.deltaY;
|
|
2470
|
+
});
|
|
2471
|
+
// add scroll event
|
|
2472
|
+
this._$textarea.addEventListener($SCROLL, (event) => {
|
|
2473
|
+
const element = event.target;
|
|
2474
|
+
this.scrollV = element.scrollTop
|
|
2475
|
+
/ (element.scrollHeight - element.clientHeight)
|
|
2476
|
+
* this.maxScrollV + 1;
|
|
2477
|
+
});
|
|
2478
|
+
// down event
|
|
2479
|
+
this._$textarea.addEventListener($TOUCH_START, () => {
|
|
2480
|
+
const player = $currentPlayer();
|
|
2481
|
+
player._$state = "down";
|
|
2482
|
+
});
|
|
2483
|
+
// up event
|
|
2484
|
+
this._$textarea.addEventListener($TOUCH_END, () => {
|
|
2485
|
+
const player = $currentPlayer();
|
|
2486
|
+
player._$state = "up";
|
|
2487
|
+
});
|
|
2488
|
+
// down event
|
|
2489
|
+
this._$textarea.addEventListener($MOUSE_DOWN, () => {
|
|
2490
|
+
const player = $currentPlayer();
|
|
2491
|
+
player._$state = "down";
|
|
2492
|
+
});
|
|
2493
|
+
// up event
|
|
2494
|
+
this._$textarea.addEventListener($MOUSE_UP, () => {
|
|
2495
|
+
const player = $currentPlayer();
|
|
2496
|
+
player._$state = "up";
|
|
2497
|
+
});
|
|
2498
|
+
}
|
|
2499
|
+
// change style
|
|
2500
|
+
const tf = this._$defaultTextFormat;
|
|
2501
|
+
const fontSize = tf.size
|
|
2502
|
+
? $Math.ceil(tf.size * scale * this._$transform.concatenatedMatrix.d)
|
|
2503
|
+
: 0;
|
|
2504
|
+
this._$textarea.style.fontSize = `${fontSize}px`;
|
|
2505
|
+
this._$textarea.style.fontFamily = tf.font || "Times New Roman";
|
|
2506
|
+
this._$textarea.style.lineHeight = `${(fontSize + $Math.max(0, tf.leading || 0)) / fontSize}em`;
|
|
2507
|
+
if (this._$autoSize !== "none") {
|
|
2508
|
+
this._$textarea.style.textAlign = "center";
|
|
2509
|
+
}
|
|
2510
|
+
else {
|
|
2511
|
+
this._$textarea.style.textAlign = tf.align || "none";
|
|
2512
|
+
}
|
|
2513
|
+
this._$textarea.addEventListener("keydown", (event) => {
|
|
2514
|
+
const element = event.target;
|
|
2515
|
+
let value = element.value;
|
|
2516
|
+
// SafariではInputEvent.isComposingがundefined
|
|
2517
|
+
if (this._$restrict && !this._$isComposing && value) {
|
|
2518
|
+
let pattern = this._$restrict;
|
|
2519
|
+
if (pattern[0] !== "[") {
|
|
2520
|
+
pattern = "[" + pattern;
|
|
2521
|
+
}
|
|
2522
|
+
if (pattern[pattern.length - 1] !== "]") {
|
|
2523
|
+
pattern += "]";
|
|
2524
|
+
}
|
|
2525
|
+
const found = value.match(new $RegExp(pattern, "gm"));
|
|
2526
|
+
value = found ? found.join("") : "";
|
|
2527
|
+
}
|
|
2528
|
+
// update
|
|
2529
|
+
if (!this._$isComposing) {
|
|
2530
|
+
this.text = value;
|
|
2531
|
+
element.value = value;
|
|
2532
|
+
}
|
|
2533
|
+
// enter off
|
|
2534
|
+
if (event.code === "Enter" && !this._$multiline) {
|
|
2535
|
+
return false;
|
|
2536
|
+
}
|
|
2537
|
+
});
|
|
2538
|
+
const style = this._$textarea.style;
|
|
2539
|
+
if (this._$border) {
|
|
2540
|
+
style.border = `solid 1px #${this.borderColor.toString(16)}`;
|
|
2541
|
+
}
|
|
2542
|
+
else {
|
|
2543
|
+
style.border = "none";
|
|
2544
|
+
}
|
|
2545
|
+
if (this._$border || this._$background) {
|
|
2546
|
+
style.backgroundColor = `#${this.backgroundColor.toString(16)}`;
|
|
2547
|
+
}
|
|
2548
|
+
else {
|
|
2549
|
+
style.backgroundColor = "transparent";
|
|
2550
|
+
}
|
|
2551
|
+
//reset
|
|
2552
|
+
this._$textarea.maxLength = this._$maxChars ? this._$maxChars : 0x7fffffff;
|
|
2553
|
+
}
|
|
2554
|
+
/**
|
|
2555
|
+
* @return {void}
|
|
2556
|
+
* @method
|
|
2557
|
+
* @private
|
|
2558
|
+
*/
|
|
2559
|
+
_$createWorkerInstance() {
|
|
2560
|
+
if (this._$created || !$rendererWorker) {
|
|
2561
|
+
return;
|
|
2562
|
+
}
|
|
2563
|
+
this._$created = true;
|
|
2564
|
+
const bounds = this._$getBounds();
|
|
2565
|
+
const message = {
|
|
2566
|
+
"command": "createTextField",
|
|
2567
|
+
"instanceId": this._$instanceId,
|
|
2568
|
+
"parentId": this._$parent ? this._$parent._$instanceId : -1,
|
|
2569
|
+
"xMin": bounds.xMin,
|
|
2570
|
+
"yMin": bounds.yMin,
|
|
2571
|
+
"xMax": bounds.xMax,
|
|
2572
|
+
"yMax": bounds.yMax,
|
|
2573
|
+
"textData": this._$getTextData(),
|
|
2574
|
+
"scrollV": this.scrollV,
|
|
2575
|
+
"widthTable": this._$widthTable,
|
|
2576
|
+
"heightTable": this._$heightTable,
|
|
2577
|
+
"textHeightTable": this._$textHeightTable,
|
|
2578
|
+
"objectTable": this._$objectTable,
|
|
2579
|
+
"limitWidth": this.width,
|
|
2580
|
+
"limitHeight": this.height,
|
|
2581
|
+
"textHeight": this.textHeight,
|
|
2582
|
+
"verticalAlign": this._$verticalAlign,
|
|
2583
|
+
"autoSize": this._$autoSize,
|
|
2584
|
+
"wordWrap": this._$wordWrap,
|
|
2585
|
+
"border": this._$border,
|
|
2586
|
+
"background": this._$background,
|
|
2587
|
+
"thickness": this._$thickness
|
|
2588
|
+
};
|
|
2589
|
+
if (this._$border) {
|
|
2590
|
+
message.borderColor = this._$borderColor;
|
|
2591
|
+
}
|
|
2592
|
+
if (this._$background) {
|
|
2593
|
+
message.backgroundColor = this._$backgroundColor;
|
|
2594
|
+
}
|
|
2595
|
+
if (this._$thickness) {
|
|
2596
|
+
message.thicknessColor = this._$backgroundColor;
|
|
2597
|
+
}
|
|
2598
|
+
if (this._$characterId > -1) {
|
|
2599
|
+
message.characterId = this._$characterId;
|
|
2600
|
+
}
|
|
2601
|
+
if (this._$loaderInfo) {
|
|
2602
|
+
message.loaderInfoId = this._$loaderInfo._$id;
|
|
2603
|
+
}
|
|
2604
|
+
if (this._$scale9Grid) {
|
|
2605
|
+
message.grid = {
|
|
2606
|
+
"x": this._$scale9Grid.x,
|
|
2607
|
+
"y": this._$scale9Grid.y,
|
|
2608
|
+
"w": this._$scale9Grid.width,
|
|
2609
|
+
"h": this._$scale9Grid.height
|
|
2610
|
+
};
|
|
2611
|
+
}
|
|
2612
|
+
$rendererWorker.postMessage(message);
|
|
2613
|
+
}
|
|
2614
|
+
/**
|
|
2615
|
+
* @return {void}
|
|
2616
|
+
* @method
|
|
2617
|
+
* @private
|
|
2618
|
+
*/
|
|
2619
|
+
_$postProperty() {
|
|
2620
|
+
if (!$rendererWorker) {
|
|
2621
|
+
return;
|
|
2622
|
+
}
|
|
2623
|
+
const message = this._$createMessage();
|
|
2624
|
+
message.textAreaActive = this._$textAreaActive;
|
|
2625
|
+
const bounds = this._$getBounds(null);
|
|
2626
|
+
message.xMin = bounds.xMin;
|
|
2627
|
+
message.yMin = bounds.yMin;
|
|
2628
|
+
message.xMax = bounds.xMax;
|
|
2629
|
+
message.yMax = bounds.yMax;
|
|
2630
|
+
$poolBoundsObject(bounds);
|
|
2631
|
+
if (this._$isUpdated()) {
|
|
2632
|
+
message.textData = this._$getTextData();
|
|
2633
|
+
message.scrollV = this.scrollV;
|
|
2634
|
+
message.widthTable = this._$widthTable;
|
|
2635
|
+
message.heightTable = this._$heightTable;
|
|
2636
|
+
message.textHeightTable = this._$textHeightTable;
|
|
2637
|
+
message.objectTable = this._$objectTable;
|
|
2638
|
+
message.limitWidth = this.width;
|
|
2639
|
+
message.limitHeight = this.height;
|
|
2640
|
+
message.textHeight = this.textHeight;
|
|
2641
|
+
message.verticalAlign = this._$verticalAlign;
|
|
2642
|
+
message.autoSize = this._$autoSize;
|
|
2643
|
+
message.wordWrap = this._$wordWrap;
|
|
2644
|
+
message.border = this._$border;
|
|
2645
|
+
if (this._$border) {
|
|
2646
|
+
message.borderColor = this._$borderColor;
|
|
2647
|
+
}
|
|
2648
|
+
message.background = this._$background;
|
|
2649
|
+
if (this._$background) {
|
|
2650
|
+
message.backgroundColor = this._$backgroundColor;
|
|
2651
|
+
}
|
|
2652
|
+
message.thickness = this._$thickness;
|
|
2653
|
+
if (this._$thickness) {
|
|
2654
|
+
message.thicknessColor = this._$backgroundColor;
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
$rendererWorker.postMessage(message);
|
|
2658
|
+
this._$posted = true;
|
|
2659
|
+
this._$updated = false;
|
|
2660
|
+
}
|
|
2661
|
+
}
|