@vpmedia/phaser 1.123.0 → 1.125.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +635 -623
- package/dist/index.js.map +1 -1
- package/dist/phaser/core/animation.d.ts +3 -3
- package/dist/phaser/core/animation.d.ts.map +1 -1
- package/dist/phaser/core/animation_manager.d.ts.map +1 -1
- package/dist/phaser/core/animation_parser.d.ts +27 -2
- package/dist/phaser/core/animation_parser.d.ts.map +1 -1
- package/dist/phaser/core/array_set.d.ts +11 -11
- package/dist/phaser/core/array_set.d.ts.map +1 -1
- package/dist/phaser/core/cache.d.ts.map +1 -1
- package/dist/phaser/core/callback.d.ts.map +1 -1
- package/dist/phaser/core/dom.d.ts +125 -19
- package/dist/phaser/core/dom.d.ts.map +1 -1
- package/dist/phaser/core/factory.d.ts +3 -2
- package/dist/phaser/core/factory.d.ts.map +1 -1
- package/dist/phaser/core/frame_data.d.ts.map +1 -1
- package/dist/phaser/core/input.d.ts +3 -2
- package/dist/phaser/core/input.d.ts.map +1 -1
- package/dist/phaser/core/input_handler.d.ts.map +1 -1
- package/dist/phaser/core/input_mouse.d.ts +5 -1
- package/dist/phaser/core/input_mouse.d.ts.map +1 -1
- package/dist/phaser/core/input_pointer.d.ts +3 -3
- package/dist/phaser/core/input_pointer.d.ts.map +1 -1
- package/dist/phaser/core/input_touch.d.ts +8 -8
- package/dist/phaser/core/input_touch.d.ts.map +1 -1
- package/dist/phaser/core/loader.d.ts +11 -2
- package/dist/phaser/core/loader.d.ts.map +1 -1
- package/dist/phaser/core/loader_parser.d.ts +14 -1
- package/dist/phaser/core/loader_parser.d.ts.map +1 -1
- package/dist/phaser/core/raf.d.ts +1 -1
- package/dist/phaser/core/raf.d.ts.map +1 -1
- package/dist/phaser/core/scale_manager.d.ts.map +1 -1
- package/dist/phaser/core/scene_manager.d.ts.map +1 -1
- package/dist/phaser/core/signal.d.ts.map +1 -1
- package/dist/phaser/core/sound.d.ts.map +1 -1
- package/dist/phaser/core/sound_manager.d.ts +1 -1
- package/dist/phaser/core/sound_manager.d.ts.map +1 -1
- package/dist/phaser/core/stage.d.ts +16 -6
- package/dist/phaser/core/stage.d.ts.map +1 -1
- package/dist/phaser/core/time.d.ts.map +1 -1
- package/dist/phaser/core/timer.d.ts +1 -1
- package/dist/phaser/core/timer.d.ts.map +1 -1
- package/dist/phaser/core/tween.d.ts +13 -5
- package/dist/phaser/core/tween.d.ts.map +1 -1
- package/dist/phaser/core/tween_data.d.ts +9 -7
- package/dist/phaser/core/tween_data.d.ts.map +1 -1
- package/dist/phaser/core/tween_manager.d.ts.map +1 -1
- package/dist/phaser/display/button.d.ts +6 -5
- package/dist/phaser/display/button.d.ts.map +1 -1
- package/dist/phaser/display/canvas/buffer.d.ts +1 -1
- package/dist/phaser/display/canvas/buffer.d.ts.map +1 -1
- package/dist/phaser/display/canvas/masker.d.ts +1 -1
- package/dist/phaser/display/canvas/masker.d.ts.map +1 -1
- package/dist/phaser/display/canvas/pool.d.ts +2 -2
- package/dist/phaser/display/canvas/pool.d.ts.map +1 -1
- package/dist/phaser/display/canvas/renderer.d.ts +9 -8
- package/dist/phaser/display/canvas/renderer.d.ts.map +1 -1
- package/dist/phaser/display/display_object.d.ts +5 -3
- package/dist/phaser/display/display_object.d.ts.map +1 -1
- package/dist/phaser/display/graphics.d.ts +1 -1
- package/dist/phaser/display/graphics.d.ts.map +1 -1
- package/dist/phaser/display/group.d.ts +1 -1
- package/dist/phaser/display/group.d.ts.map +1 -1
- package/dist/phaser/display/image.d.ts +6 -5
- package/dist/phaser/display/image.d.ts.map +1 -1
- package/dist/phaser/display/sprite_util.d.ts +3 -2
- package/dist/phaser/display/sprite_util.d.ts.map +1 -1
- package/dist/phaser/display/text.d.ts +2 -16
- package/dist/phaser/display/text.d.ts.map +1 -1
- package/dist/phaser/display/webgl/abstract_filter.d.ts +14 -8
- package/dist/phaser/display/webgl/abstract_filter.d.ts.map +1 -1
- package/dist/phaser/display/webgl/blend_manager.d.ts +2 -3
- package/dist/phaser/display/webgl/blend_manager.d.ts.map +1 -1
- package/dist/phaser/display/webgl/earcut.d.ts.map +1 -1
- package/dist/phaser/display/webgl/fast_sprite_batch.d.ts +11 -5
- package/dist/phaser/display/webgl/fast_sprite_batch.d.ts.map +1 -1
- package/dist/phaser/display/webgl/filter_manager.d.ts +6 -4
- package/dist/phaser/display/webgl/filter_manager.d.ts.map +1 -1
- package/dist/phaser/display/webgl/filter_texture.d.ts +4 -4
- package/dist/phaser/display/webgl/filter_texture.d.ts.map +1 -1
- package/dist/phaser/display/webgl/graphics.d.ts +2 -2
- package/dist/phaser/display/webgl/graphics.d.ts.map +1 -1
- package/dist/phaser/display/webgl/mask_manager.d.ts +3 -2
- package/dist/phaser/display/webgl/mask_manager.d.ts.map +1 -1
- package/dist/phaser/display/webgl/render_texture.d.ts +11 -8
- package/dist/phaser/display/webgl/render_texture.d.ts.map +1 -1
- package/dist/phaser/display/webgl/renderer.d.ts +8 -4
- package/dist/phaser/display/webgl/renderer.d.ts.map +1 -1
- package/dist/phaser/display/webgl/shader/normal.d.ts +28 -3
- package/dist/phaser/display/webgl/shader/normal.d.ts.map +1 -1
- package/dist/phaser/display/webgl/sprite_batch.d.ts +6 -5
- package/dist/phaser/display/webgl/sprite_batch.d.ts.map +1 -1
- package/dist/phaser/display/webgl/stencil_manager.d.ts +3 -3
- package/dist/phaser/display/webgl/stencil_manager.d.ts.map +1 -1
- package/dist/phaser/display/webgl/texture.d.ts.map +1 -1
- package/dist/phaser/display/webgl/texture_util.d.ts +2 -2
- package/dist/phaser/display/webgl/texture_util.d.ts.map +1 -1
- package/dist/phaser/display/webgl/util.d.ts +1 -1
- package/dist/phaser/display/webgl/util.d.ts.map +1 -1
- package/dist/phaser/geom/circle.d.ts.map +1 -1
- package/dist/phaser/geom/line.d.ts +10 -1
- package/dist/phaser/geom/line.d.ts.map +1 -1
- package/dist/phaser/geom/rectangle.d.ts.map +1 -1
- package/dist/phaser/geom/util/circle.d.ts +2 -1
- package/dist/phaser/geom/util/circle.d.ts.map +1 -1
- package/dist/phaser/geom/util/point.d.ts +1 -1
- package/dist/phaser/geom/util/point.d.ts.map +1 -1
- package/dist/phaser/geom/util/rectangle.d.ts +1 -1
- package/dist/phaser/geom/util/rectangle.d.ts.map +1 -1
- package/dist/phaser/util/math.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/phaser/core/animation.ts +11 -11
- package/src/phaser/core/animation_manager.ts +12 -12
- package/src/phaser/core/animation_parser.ts +39 -37
- package/src/phaser/core/array_set.ts +28 -28
- package/src/phaser/core/cache.test.ts +33 -33
- package/src/phaser/core/cache.ts +7 -7
- package/src/phaser/core/callback.ts +1 -0
- package/src/phaser/core/callback_context.test.ts +8 -8
- package/src/phaser/core/device_util.ts +4 -4
- package/src/phaser/core/dom.ts +38 -24
- package/src/phaser/core/factory.ts +9 -2
- package/src/phaser/core/frame_data.test.ts +23 -23
- package/src/phaser/core/frame_data.ts +2 -5
- package/src/phaser/core/game.ts +12 -12
- package/src/phaser/core/input.ts +11 -10
- package/src/phaser/core/input_handler.test.ts +18 -18
- package/src/phaser/core/input_handler.ts +14 -14
- package/src/phaser/core/input_mouse.ts +13 -12
- package/src/phaser/core/input_pointer.test.ts +26 -26
- package/src/phaser/core/input_pointer.ts +4 -4
- package/src/phaser/core/input_touch.ts +8 -8
- package/src/phaser/core/loader.test.ts +26 -26
- package/src/phaser/core/loader.ts +63 -75
- package/src/phaser/core/loader_parser.test.ts +16 -16
- package/src/phaser/core/loader_parser.ts +16 -6
- package/src/phaser/core/raf.ts +1 -1
- package/src/phaser/core/registry.test.ts +6 -6
- package/src/phaser/core/scale_manager.ts +12 -11
- package/src/phaser/core/scene_manager.test.ts +30 -30
- package/src/phaser/core/scene_manager.ts +3 -3
- package/src/phaser/core/signal.test.ts +8 -8
- package/src/phaser/core/signal.ts +3 -3
- package/src/phaser/core/signal_dispatch.test.ts +30 -30
- package/src/phaser/core/sound.ts +45 -40
- package/src/phaser/core/sound_manager.ts +18 -22
- package/src/phaser/core/sound_sprite.ts +1 -1
- package/src/phaser/core/stage.ts +22 -12
- package/src/phaser/core/time.ts +1 -1
- package/src/phaser/core/timer.test.ts +47 -47
- package/src/phaser/core/timer.ts +2 -2
- package/src/phaser/core/tween.ts +34 -36
- package/src/phaser/core/tween_data.test.ts +119 -0
- package/src/phaser/core/tween_data.ts +54 -39
- package/src/phaser/core/tween_easing.test.ts +5 -5
- package/src/phaser/core/tween_manager.ts +2 -2
- package/src/phaser/display/bitmap_text.test.ts +30 -30
- package/src/phaser/display/bitmap_text.ts +3 -3
- package/src/phaser/display/button.ts +20 -18
- package/src/phaser/display/canvas/buffer.ts +2 -2
- package/src/phaser/display/canvas/graphics.ts +2 -2
- package/src/phaser/display/canvas/masker.ts +1 -1
- package/src/phaser/display/canvas/pool.test.ts +20 -20
- package/src/phaser/display/canvas/pool.ts +6 -6
- package/src/phaser/display/canvas/renderer.ts +18 -16
- package/src/phaser/display/canvas/tinter.ts +1 -1
- package/src/phaser/display/canvas/util.test.ts +25 -25
- package/src/phaser/display/canvas/util.ts +2 -2
- package/src/phaser/display/display_object.ts +16 -15
- package/src/phaser/display/graphics.test.ts +70 -20
- package/src/phaser/display/graphics.ts +46 -42
- package/src/phaser/display/group.ts +13 -12
- package/src/phaser/display/image.ts +35 -31
- package/src/phaser/display/sprite_util.ts +4 -3
- package/src/phaser/display/text.test.ts +28 -25
- package/src/phaser/display/text.ts +56 -62
- package/src/phaser/display/webgl/abstract_filter.ts +21 -11
- package/src/phaser/display/webgl/blend_manager.ts +4 -5
- package/src/phaser/display/webgl/earcut.test.ts +20 -20
- package/src/phaser/display/webgl/earcut.ts +46 -42
- package/src/phaser/display/webgl/fast_sprite_batch.ts +21 -16
- package/src/phaser/display/webgl/filter_manager.ts +7 -4
- package/src/phaser/display/webgl/filter_texture.ts +5 -5
- package/src/phaser/display/webgl/graphics.ts +3 -3
- package/src/phaser/display/webgl/mask_manager.ts +9 -14
- package/src/phaser/display/webgl/render_texture.ts +15 -14
- package/src/phaser/display/webgl/renderer.ts +10 -9
- package/src/phaser/display/webgl/shader/normal.ts +45 -35
- package/src/phaser/display/webgl/shader/shader.test.ts +24 -24
- package/src/phaser/display/webgl/shader_manager.test.ts +18 -18
- package/src/phaser/display/webgl/shader_manager.ts +1 -1
- package/src/phaser/display/webgl/sprite_batch.ts +10 -10
- package/src/phaser/display/webgl/stencil_manager.ts +4 -4
- package/src/phaser/display/webgl/texture.ts +2 -1
- package/src/phaser/display/webgl/texture_util.ts +2 -2
- package/src/phaser/display/webgl/util.ts +4 -4
- package/src/phaser/geom/circle.test.ts +38 -38
- package/src/phaser/geom/circle.ts +7 -7
- package/src/phaser/geom/ellipse.test.ts +12 -12
- package/src/phaser/geom/line.test.ts +15 -15
- package/src/phaser/geom/line.ts +5 -2
- package/src/phaser/geom/matrix.test.ts +31 -31
- package/src/phaser/geom/point.test.ts +31 -31
- package/src/phaser/geom/polygon.test.ts +27 -27
- package/src/phaser/geom/polygon.ts +2 -2
- package/src/phaser/geom/rectangle.test.ts +87 -87
- package/src/phaser/geom/rectangle.ts +12 -13
- package/src/phaser/geom/rounded_rectangle.test.ts +9 -9
- package/src/phaser/geom/util/circle.test.ts +5 -5
- package/src/phaser/geom/util/circle.ts +8 -11
- package/src/phaser/geom/util/ellipse.test.ts +2 -2
- package/src/phaser/geom/util/line.test.ts +2 -2
- package/src/phaser/geom/util/matrix.test.ts +4 -4
- package/src/phaser/geom/util/point.test.ts +2 -2
- package/src/phaser/geom/util/point.ts +6 -8
- package/src/phaser/geom/util/polygon.test.ts +2 -2
- package/src/phaser/geom/util/rectangle.test.ts +2 -2
- package/src/phaser/geom/util/rectangle.ts +1 -1
- package/src/phaser/geom/util/rounded_rectangle.test.ts +2 -2
- package/src/phaser/util/math.test.ts +41 -41
- package/src/phaser/util/math.ts +7 -5
|
@@ -7,12 +7,14 @@ import { DisplayObject } from './display_object.js';
|
|
|
7
7
|
import { getBounds, getLocalBounds, renderCanvas, renderWebGL, setTexture } from './sprite_util.js';
|
|
8
8
|
import { Texture } from './webgl/texture.js';
|
|
9
9
|
import type { Game } from '../core/game.js';
|
|
10
|
-
import
|
|
10
|
+
import { Frame } from '../core/frame.js';
|
|
11
11
|
import type { Matrix } from '../geom/matrix.js';
|
|
12
12
|
import type { RenderSession } from './render_session.js';
|
|
13
|
+
import type { AbstractFilter } from './webgl/abstract_filter.js';
|
|
14
|
+
import type { ImageCacheEntry } from '../core/cache.js';
|
|
13
15
|
|
|
14
16
|
export class Image extends DisplayObject {
|
|
15
|
-
public key!:
|
|
17
|
+
public key!: string | number | Texture | null;
|
|
16
18
|
public texture!: Texture;
|
|
17
19
|
declare public _width: number;
|
|
18
20
|
declare public _height: number;
|
|
@@ -21,8 +23,8 @@ export class Image extends DisplayObject {
|
|
|
21
23
|
public tilingTexture!: Texture | null;
|
|
22
24
|
public tintedTexture!: HTMLCanvasElement | null;
|
|
23
25
|
public blendMode!: number;
|
|
24
|
-
public shader!:
|
|
25
|
-
public _frame!:
|
|
26
|
+
public shader!: AbstractFilter | null;
|
|
27
|
+
public _frame!: Frame | Rectangle | null;
|
|
26
28
|
public pendingDestroy!: boolean;
|
|
27
29
|
declare public events: EventManager;
|
|
28
30
|
public animations!: AnimationManager;
|
|
@@ -98,11 +100,11 @@ export class Image extends DisplayObject {
|
|
|
98
100
|
this.tintedTexture = null;
|
|
99
101
|
this.shader = null;
|
|
100
102
|
this._frame = null;
|
|
101
|
-
if (this.events) {
|
|
103
|
+
if (this.events as EventManager | undefined) {
|
|
102
104
|
this.events.destroy();
|
|
103
105
|
}
|
|
104
106
|
this.events = null!;
|
|
105
|
-
if (this.animations) {
|
|
107
|
+
if (this.animations as AnimationManager | undefined) {
|
|
106
108
|
this.animations.destroy();
|
|
107
109
|
}
|
|
108
110
|
this.animations = null!;
|
|
@@ -117,7 +119,7 @@ export class Image extends DisplayObject {
|
|
|
117
119
|
this.destroy();
|
|
118
120
|
return;
|
|
119
121
|
}
|
|
120
|
-
if (!this.exists ||
|
|
122
|
+
if (!this.exists || this.parent?.exists !== true) {
|
|
121
123
|
this.renderOrderID = -1;
|
|
122
124
|
return;
|
|
123
125
|
}
|
|
@@ -125,7 +127,7 @@ export class Image extends DisplayObject {
|
|
|
125
127
|
this.game.stage.currentRenderOrderID += 1;
|
|
126
128
|
this.renderOrderID = this.game.stage.currentRenderOrderID;
|
|
127
129
|
}
|
|
128
|
-
if (this.animations) {
|
|
130
|
+
if (this.animations as AnimationManager | undefined) {
|
|
129
131
|
this.animations.update();
|
|
130
132
|
}
|
|
131
133
|
for (const child of this.children) {
|
|
@@ -161,7 +163,7 @@ export class Image extends DisplayObject {
|
|
|
161
163
|
this.setTexture(textureKey);
|
|
162
164
|
} else {
|
|
163
165
|
const img = cache.getImage(textureKey ?? undefined, true);
|
|
164
|
-
if (img) {
|
|
166
|
+
if (img as ImageCacheEntry | undefined) {
|
|
165
167
|
this.key = img.key;
|
|
166
168
|
this.setTexture(new Texture(img.base));
|
|
167
169
|
this.texture.baseTexture.skipRender = textureKey === '__default';
|
|
@@ -180,7 +182,7 @@ export class Image extends DisplayObject {
|
|
|
180
182
|
* Sets the current frame of this image.
|
|
181
183
|
* @param {Frame} frame - The frame to set.
|
|
182
184
|
*/
|
|
183
|
-
public setFrame(frame: Frame): void {
|
|
185
|
+
public setFrame(frame: Frame | Rectangle): void {
|
|
184
186
|
this._frame = frame;
|
|
185
187
|
this.texture.frame.x = frame.x;
|
|
186
188
|
this.texture.frame.y = frame.y;
|
|
@@ -190,25 +192,26 @@ export class Image extends DisplayObject {
|
|
|
190
192
|
this.texture.crop.y = frame.y;
|
|
191
193
|
this.texture.crop.width = frame.width;
|
|
192
194
|
this.texture.crop.height = frame.height;
|
|
193
|
-
|
|
195
|
+
const trimmed = frame instanceof Frame && frame.trimmed ? frame : null;
|
|
196
|
+
if (trimmed) {
|
|
194
197
|
if (this.texture.trim) {
|
|
195
|
-
this.texture.trim.x =
|
|
196
|
-
this.texture.trim.y =
|
|
197
|
-
this.texture.trim.width =
|
|
198
|
-
this.texture.trim.height =
|
|
198
|
+
this.texture.trim.x = trimmed.spriteSourceSizeX;
|
|
199
|
+
this.texture.trim.y = trimmed.spriteSourceSizeY;
|
|
200
|
+
this.texture.trim.width = trimmed.sourceSizeW;
|
|
201
|
+
this.texture.trim.height = trimmed.sourceSizeH;
|
|
199
202
|
} else {
|
|
200
203
|
this.texture.trim = new Rectangle(
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
204
|
+
trimmed.spriteSourceSizeX,
|
|
205
|
+
trimmed.spriteSourceSizeY,
|
|
206
|
+
trimmed.sourceSizeW,
|
|
207
|
+
trimmed.sourceSizeH
|
|
205
208
|
);
|
|
206
209
|
}
|
|
207
|
-
this.texture.width =
|
|
208
|
-
this.texture.height =
|
|
209
|
-
this.texture.frame.width =
|
|
210
|
-
this.texture.frame.height =
|
|
211
|
-
} else if (
|
|
210
|
+
this.texture.width = trimmed.sourceSizeW;
|
|
211
|
+
this.texture.height = trimmed.sourceSizeH;
|
|
212
|
+
this.texture.frame.width = trimmed.sourceSizeW;
|
|
213
|
+
this.texture.frame.height = trimmed.sourceSizeH;
|
|
214
|
+
} else if (this.texture.trim) {
|
|
212
215
|
this.texture.trim = null;
|
|
213
216
|
}
|
|
214
217
|
if (this.cropRect) {
|
|
@@ -281,7 +284,7 @@ export class Image extends DisplayObject {
|
|
|
281
284
|
* @param {boolean} copy - Whether to copy the rect or use it directly.
|
|
282
285
|
*/
|
|
283
286
|
public crop(rect: Rectangle, copy = false): void {
|
|
284
|
-
if (rect) {
|
|
287
|
+
if (rect as Rectangle | undefined) {
|
|
285
288
|
if (copy && this.cropRect !== null) {
|
|
286
289
|
this.cropRect.setTo(rect.x, rect.y, rect.width, rect.height);
|
|
287
290
|
} else if (copy && this.cropRect === null) {
|
|
@@ -308,13 +311,14 @@ export class Image extends DisplayObject {
|
|
|
308
311
|
const oldY = this.texture.crop.y;
|
|
309
312
|
const oldW = this.texture.crop.width;
|
|
310
313
|
const oldH = this.texture.crop.height;
|
|
314
|
+
const frame = this._frame!;
|
|
311
315
|
this._crop = clone(this.cropRect, this._crop);
|
|
312
|
-
this._crop.x +=
|
|
313
|
-
this._crop.y +=
|
|
314
|
-
const cx = Math.max(
|
|
315
|
-
const cy = Math.max(
|
|
316
|
-
const cw = Math.min(
|
|
317
|
-
const ch = Math.min(
|
|
316
|
+
this._crop.x += frame.x;
|
|
317
|
+
this._crop.y += frame.y;
|
|
318
|
+
const cx = Math.max(frame.x, this._crop.x);
|
|
319
|
+
const cy = Math.max(frame.y, this._crop.y);
|
|
320
|
+
const cw = Math.min(frame.right, this._crop.right) - cx;
|
|
321
|
+
const ch = Math.min(frame.bottom, this._crop.bottom) - cy;
|
|
318
322
|
this.texture.crop.x = cx;
|
|
319
323
|
this.texture.crop.y = cy;
|
|
320
324
|
this.texture.crop.width = cw;
|
|
@@ -6,6 +6,7 @@ import type { Texture } from './webgl/texture.js';
|
|
|
6
6
|
import type { Matrix } from '../geom/matrix.js';
|
|
7
7
|
import type { RenderSession } from './render_session.js';
|
|
8
8
|
import { setSmoothing } from './canvas/util.js';
|
|
9
|
+
import type { Rectangle } from '../geom/rectangle.js';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Sets the texture of a sprite.
|
|
@@ -29,7 +30,7 @@ export const setTexture = (target: Image, texture: Texture, destroyBase = false)
|
|
|
29
30
|
* @param {object} matrix - The transformation matrix.
|
|
30
31
|
* @returns {Rectangle} The bounds rectangle.
|
|
31
32
|
*/
|
|
32
|
-
export const getBounds = (target: Image, matrix: Matrix | null = null) => {
|
|
33
|
+
export const getBounds = (target: Image, matrix: Matrix | null = null): Rectangle => {
|
|
33
34
|
if (target.currentBounds) {
|
|
34
35
|
return target.currentBounds;
|
|
35
36
|
}
|
|
@@ -110,7 +111,7 @@ export const getBounds = (target: Image, matrix: Matrix | null = null) => {
|
|
|
110
111
|
* @param {Image} target - The target image to get local bounds for.
|
|
111
112
|
* @returns {Rectangle} The local bounds rectangle.
|
|
112
113
|
*/
|
|
113
|
-
export const getLocalBounds = (target: Image) => {
|
|
114
|
+
export const getLocalBounds = (target: Image): Rectangle => {
|
|
114
115
|
const matrixCache = target.worldTransform;
|
|
115
116
|
target.worldTransform = getIdentityMatrix();
|
|
116
117
|
for (const child of target.children) {
|
|
@@ -221,7 +222,7 @@ export const renderCanvas = (
|
|
|
221
222
|
renderSession.context.globalAlpha = target.worldAlpha;
|
|
222
223
|
|
|
223
224
|
// If smoothingEnabled is supported and we need to change the smoothing property for this texture
|
|
224
|
-
if (renderSession.smoothProperty && renderSession.scaleMode !== target.texture.baseTexture.scaleMode) {
|
|
225
|
+
if (renderSession.smoothProperty !== null && renderSession.scaleMode !== target.texture.baseTexture.scaleMode) {
|
|
225
226
|
renderSession.scaleMode = target.texture.baseTexture.scaleMode;
|
|
226
227
|
setSmoothing(renderSession.context, renderSession.smoothProperty, renderSession.scaleMode === SCALE_LINEAR);
|
|
227
228
|
}
|
|
@@ -36,99 +36,102 @@ const createContext2D = (): CanvasRenderingContext2D =>
|
|
|
36
36
|
const createGame = (): Game =>
|
|
37
37
|
({
|
|
38
38
|
renderer: { resolution: 1 },
|
|
39
|
-
cache: { getImage: () => null },
|
|
40
|
-
add: { existing: (child: unknown) => child },
|
|
39
|
+
cache: { getImage: (): null => null },
|
|
40
|
+
add: { existing: (child: unknown): unknown => child },
|
|
41
41
|
}) as unknown as Game;
|
|
42
42
|
|
|
43
43
|
const createText = (value: string | number): Text => new Text(createGame(), 0, 0, value);
|
|
44
44
|
|
|
45
|
-
describe('Text', () => {
|
|
45
|
+
describe('Text', (): void => {
|
|
46
46
|
const originalGetContext = HTMLCanvasElement.prototype.getContext;
|
|
47
47
|
|
|
48
|
-
beforeAll(() => {
|
|
49
|
-
HTMLCanvasElement.prototype.getContext = function getContext(
|
|
48
|
+
beforeAll((): void => {
|
|
49
|
+
HTMLCanvasElement.prototype.getContext = function getContext(
|
|
50
|
+
this: HTMLCanvasElement,
|
|
51
|
+
id: string
|
|
52
|
+
): CanvasRenderingContext2D | null {
|
|
50
53
|
return id === '2d' ? createContext2D() : null;
|
|
51
54
|
} as typeof HTMLCanvasElement.prototype.getContext;
|
|
52
55
|
});
|
|
53
56
|
|
|
54
|
-
beforeEach(() => {
|
|
57
|
+
beforeEach((): void => {
|
|
55
58
|
getRegistry().CACHE_MISSING_IMAGE = textureFromCanvas(document.createElement('canvas'));
|
|
56
59
|
});
|
|
57
60
|
|
|
58
|
-
afterAll(() => {
|
|
61
|
+
afterAll((): void => {
|
|
59
62
|
HTMLCanvasElement.prototype.getContext = originalGetContext;
|
|
60
63
|
});
|
|
61
64
|
|
|
62
|
-
describe('constructor', () => {
|
|
63
|
-
it('keeps a string as-is', () => {
|
|
65
|
+
describe('constructor', (): void => {
|
|
66
|
+
it('keeps a string as-is', (): void => {
|
|
64
67
|
expect(createText('hello').text).toBe('hello');
|
|
65
68
|
});
|
|
66
69
|
|
|
67
70
|
// Callers pass numbers straight into game.add.text(). The constructor must coerce:
|
|
68
71
|
// updateText() calls .split() on the value, which throws on a number.
|
|
69
|
-
it('coerces a number to its string form', () => {
|
|
72
|
+
it('coerces a number to its string form', (): void => {
|
|
70
73
|
expect(createText(42).text).toBe('42');
|
|
71
74
|
});
|
|
72
75
|
|
|
73
|
-
it('coerces zero rather than falling back to the empty string', () => {
|
|
76
|
+
it('coerces zero rather than falling back to the empty string', (): void => {
|
|
74
77
|
expect(createText(0).text).toBe('0');
|
|
75
78
|
});
|
|
76
79
|
|
|
77
|
-
it('coerces a negative number', () => {
|
|
80
|
+
it('coerces a negative number', (): void => {
|
|
78
81
|
expect(createText(-7).text).toBe('-7');
|
|
79
82
|
});
|
|
80
83
|
|
|
81
|
-
it('defaults to the empty string', () => {
|
|
84
|
+
it('defaults to the empty string', (): void => {
|
|
82
85
|
expect(new Text(createGame(), 0, 0).text).toBe('');
|
|
83
86
|
});
|
|
84
87
|
|
|
85
|
-
it('renders a numeric label without throwing', () => {
|
|
86
|
-
expect(() => createText(2026)).not.toThrow();
|
|
88
|
+
it('renders a numeric label without throwing', (): void => {
|
|
89
|
+
expect((): Text => createText(2026)).not.toThrow();
|
|
87
90
|
});
|
|
88
91
|
});
|
|
89
92
|
|
|
90
|
-
describe('text setter', () => {
|
|
91
|
-
it('coerces a number assigned after construction', () => {
|
|
93
|
+
describe('text setter', (): void => {
|
|
94
|
+
it('coerces a number assigned after construction', (): void => {
|
|
92
95
|
const text = createText('start');
|
|
93
96
|
text.text = 99;
|
|
94
97
|
expect(text.text).toBe('99');
|
|
95
98
|
});
|
|
96
99
|
});
|
|
97
100
|
|
|
98
|
-
describe('fontSize', () => {
|
|
101
|
+
describe('fontSize', (): void => {
|
|
99
102
|
// A px-suffixed size cannot be read with Number(); it yields NaN. An autofix made exactly that
|
|
100
103
|
// substitution once already.
|
|
101
|
-
it('reads a px size back as a number', () => {
|
|
104
|
+
it('reads a px size back as a number', (): void => {
|
|
102
105
|
const text = new Text(createGame(), 0, 0, 'hello', { font: '20px Arial' });
|
|
103
106
|
expect(text.fontSize).toBe(20);
|
|
104
107
|
});
|
|
105
108
|
|
|
106
|
-
it('round trips through the setter', () => {
|
|
109
|
+
it('round trips through the setter', (): void => {
|
|
107
110
|
const text = createText('hello');
|
|
108
111
|
text.fontSize = 32;
|
|
109
112
|
expect(text.fontSize).toBe(32);
|
|
110
113
|
});
|
|
111
114
|
|
|
112
|
-
it('reads zero back as zero', () => {
|
|
115
|
+
it('reads zero back as zero', (): void => {
|
|
113
116
|
const text = createText('hello');
|
|
114
117
|
text.fontSize = 0;
|
|
115
118
|
expect(text.fontSize).toBe(0);
|
|
116
119
|
});
|
|
117
120
|
|
|
118
|
-
it('never reports NaN for a styled font', () => {
|
|
121
|
+
it('never reports NaN for a styled font', (): void => {
|
|
119
122
|
const text = new Text(createGame(), 0, 0, 'hello', { font: 'bold 14px Arial' });
|
|
120
123
|
expect(Number.isNaN(text.fontSize)).toBe(false);
|
|
121
124
|
});
|
|
122
125
|
});
|
|
123
126
|
|
|
124
|
-
describe('setText', () => {
|
|
125
|
-
it('coerces a number', () => {
|
|
127
|
+
describe('setText', (): void => {
|
|
128
|
+
it('coerces a number', (): void => {
|
|
126
129
|
const text = createText('start');
|
|
127
130
|
text.setText(123);
|
|
128
131
|
expect(text.text).toBe('123');
|
|
129
132
|
});
|
|
130
133
|
|
|
131
|
-
it('returns itself for chaining', () => {
|
|
134
|
+
it('returns itself for chaining', (): void => {
|
|
132
135
|
const text = createText('start');
|
|
133
136
|
expect(text.setText('next')).toBe(text);
|
|
134
137
|
});
|
|
@@ -199,16 +199,16 @@ export class Text extends Image {
|
|
|
199
199
|
tabs: source.tabs ?? 0,
|
|
200
200
|
};
|
|
201
201
|
const components = this.fontToComponents(resolved.font);
|
|
202
|
-
if (resolved.fontStyle) {
|
|
202
|
+
if (resolved.fontStyle !== undefined && resolved.fontStyle !== '') {
|
|
203
203
|
components.fontStyle = resolved.fontStyle;
|
|
204
204
|
}
|
|
205
|
-
if (resolved.fontVariant) {
|
|
205
|
+
if (resolved.fontVariant !== undefined && resolved.fontVariant !== '') {
|
|
206
206
|
components.fontVariant = resolved.fontVariant;
|
|
207
207
|
}
|
|
208
|
-
if (resolved.fontWeight) {
|
|
208
|
+
if (resolved.fontWeight !== undefined && resolved.fontWeight !== '') {
|
|
209
209
|
components.fontWeight = String(resolved.fontWeight);
|
|
210
210
|
}
|
|
211
|
-
if (resolved.fontSize) {
|
|
211
|
+
if (resolved.fontSize !== undefined && resolved.fontSize !== '') {
|
|
212
212
|
const fontSize = typeof resolved.fontSize === 'number' ? `${resolved.fontSize}px` : resolved.fontSize;
|
|
213
213
|
resolved.fontSize = fontSize;
|
|
214
214
|
components.fontSize = fontSize;
|
|
@@ -229,10 +229,7 @@ export class Text extends Image {
|
|
|
229
229
|
public updateText(): void {
|
|
230
230
|
this.texture.baseTexture.resolution = this._res;
|
|
231
231
|
this.context.font = this.style.font;
|
|
232
|
-
|
|
233
|
-
if (this.style.wordWrap) {
|
|
234
|
-
outputText = this.runWordWrap(this.text);
|
|
235
|
-
}
|
|
232
|
+
const outputText = this.style.wordWrap ? this.runWordWrap(this.text) : this.text;
|
|
236
233
|
// Split text into lines
|
|
237
234
|
const lines = outputText.split(/(?:\r\n|\r|\n)/);
|
|
238
235
|
// Calculate text width
|
|
@@ -250,24 +247,28 @@ export class Text extends Image {
|
|
|
250
247
|
}
|
|
251
248
|
this._charCount = 0;
|
|
252
249
|
for (let i = 0; i < drawnLines; i += 1) {
|
|
250
|
+
const currentLine = lines[i]!;
|
|
253
251
|
if (tabs === 0) {
|
|
254
252
|
// Simple layout (no tabs)
|
|
255
253
|
lineWidth = this.style.strokeThickness + this.padding.x;
|
|
256
|
-
lineWidth += this.hasCharacterStyles()
|
|
254
|
+
lineWidth += this.hasCharacterStyles()
|
|
255
|
+
? this.measureLine(currentLine)
|
|
256
|
+
: this.context.measureText(currentLine).width;
|
|
257
257
|
// Adjust for wrapped text
|
|
258
258
|
if (this.style.wordWrap) {
|
|
259
259
|
lineWidth -= this.context.measureText(' ').width;
|
|
260
260
|
}
|
|
261
261
|
} else {
|
|
262
262
|
// Complex layout (tabs)
|
|
263
|
-
const line =
|
|
263
|
+
const line = currentLine.split(/(?:\t)/);
|
|
264
264
|
lineWidth = this.padding.x + this.style.strokeThickness;
|
|
265
265
|
if (Array.isArray(tabs)) {
|
|
266
266
|
let tab = 0;
|
|
267
267
|
for (let c = 0; c < line.length; c += 1) {
|
|
268
|
+
const part = line[c]!;
|
|
268
269
|
const section = this.hasCharacterStyles()
|
|
269
|
-
? this.measureLine(
|
|
270
|
-
: Math.ceil(this.context.measureText(
|
|
270
|
+
? this.measureLine(part)
|
|
271
|
+
: Math.ceil(this.context.measureText(part).width);
|
|
271
272
|
if (c > 0) {
|
|
272
273
|
tab += tabs[c - 1]!;
|
|
273
274
|
}
|
|
@@ -301,7 +302,7 @@ export class Text extends Image {
|
|
|
301
302
|
}
|
|
302
303
|
this.canvas.height = height * this._res;
|
|
303
304
|
this.context.scale(this._res, this._res);
|
|
304
|
-
if (this.style.backgroundColor) {
|
|
305
|
+
if (this.style.backgroundColor !== null && this.style.backgroundColor !== '') {
|
|
305
306
|
this.context.fillStyle = this.style.backgroundColor;
|
|
306
307
|
this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
|
307
308
|
}
|
|
@@ -317,6 +318,7 @@ export class Text extends Image {
|
|
|
317
318
|
this._charCount = 0;
|
|
318
319
|
// Draw text line by line
|
|
319
320
|
for (let i = 0; i < drawnLines; i += 1) {
|
|
321
|
+
const line = lines[i]!;
|
|
320
322
|
// Split the line by
|
|
321
323
|
linePositionX = this.style.strokeThickness / 2;
|
|
322
324
|
linePositionY = this.style.strokeThickness / 2 + i * lineHeight + fontProperties.ascent;
|
|
@@ -333,22 +335,22 @@ export class Text extends Image {
|
|
|
333
335
|
linePositionY = Math.round(linePositionY);
|
|
334
336
|
}
|
|
335
337
|
if (this.hasCharacterStyles()) {
|
|
336
|
-
this.updateLine(
|
|
338
|
+
this.updateLine(line, linePositionX, linePositionY);
|
|
337
339
|
} else {
|
|
338
340
|
if (this.style.stroke && this.style.strokeThickness) {
|
|
339
341
|
this.updateShadow(this.style.shadowStroke ?? false);
|
|
340
342
|
if (tabs === 0) {
|
|
341
|
-
this.context.strokeText(
|
|
343
|
+
this.context.strokeText(line, linePositionX, linePositionY);
|
|
342
344
|
} else {
|
|
343
|
-
this.renderTabLine(
|
|
345
|
+
this.renderTabLine(line, linePositionX, linePositionY, false);
|
|
344
346
|
}
|
|
345
347
|
}
|
|
346
348
|
if (this.style.fill) {
|
|
347
349
|
this.updateShadow(this.style.shadowFill ?? false);
|
|
348
350
|
if (tabs === 0) {
|
|
349
|
-
this.context.fillText(
|
|
351
|
+
this.context.fillText(line, linePositionX, linePositionY);
|
|
350
352
|
} else {
|
|
351
|
-
this.renderTabLine(
|
|
353
|
+
this.renderTabLine(line, linePositionX, linePositionY, true);
|
|
352
354
|
}
|
|
353
355
|
}
|
|
354
356
|
}
|
|
@@ -382,16 +384,17 @@ export class Text extends Image {
|
|
|
382
384
|
}
|
|
383
385
|
}
|
|
384
386
|
} else {
|
|
387
|
+
let cursor = x;
|
|
385
388
|
for (const part of text) {
|
|
386
389
|
const section = Math.ceil(this.context.measureText(part).width);
|
|
387
390
|
// How far to the next tab?
|
|
388
|
-
snap = snapToCeil(
|
|
391
|
+
snap = snapToCeil(cursor, tabs);
|
|
389
392
|
if (fill) {
|
|
390
393
|
this.context.fillText(part, snap, y);
|
|
391
394
|
} else {
|
|
392
395
|
this.context.strokeText(part, snap, y);
|
|
393
396
|
}
|
|
394
|
-
|
|
397
|
+
cursor = snap + section;
|
|
395
398
|
}
|
|
396
399
|
}
|
|
397
400
|
}
|
|
@@ -439,24 +442,24 @@ export class Text extends Image {
|
|
|
439
442
|
const components = this.fontToComponents(this.context.font);
|
|
440
443
|
const charFontStyle = this.fontStyles[this._charCount];
|
|
441
444
|
const charFontWeight = this.fontWeights[this._charCount];
|
|
442
|
-
if (charFontStyle) {
|
|
445
|
+
if (charFontStyle !== undefined && charFontStyle !== null && charFontStyle !== '') {
|
|
443
446
|
components.fontStyle = charFontStyle;
|
|
444
447
|
}
|
|
445
|
-
if (charFontWeight) {
|
|
448
|
+
if (charFontWeight !== undefined && charFontWeight !== null && charFontWeight !== '') {
|
|
446
449
|
components.fontWeight = charFontWeight;
|
|
447
450
|
}
|
|
448
451
|
this.context.font = this.componentsToFont(components);
|
|
449
452
|
}
|
|
450
453
|
if (this.style.stroke && this.style.strokeThickness) {
|
|
451
454
|
const charStrokeColor = this.strokeColors[this._charCount];
|
|
452
|
-
if (charStrokeColor) {
|
|
455
|
+
if (charStrokeColor !== undefined && charStrokeColor !== null && charStrokeColor !== '') {
|
|
453
456
|
this.context.strokeStyle = charStrokeColor;
|
|
454
457
|
}
|
|
455
458
|
this.updateShadow(this.style.shadowStroke ?? false);
|
|
456
459
|
}
|
|
457
460
|
if (this.style.fill) {
|
|
458
461
|
const charFillColor = this.colors[this._charCount];
|
|
459
|
-
if (charFillColor) {
|
|
462
|
+
if (charFillColor !== undefined && charFillColor !== null && charFillColor !== '') {
|
|
460
463
|
this.context.fillStyle = charFillColor;
|
|
461
464
|
}
|
|
462
465
|
this.updateShadow(this.style.shadowFill ?? false);
|
|
@@ -474,36 +477,37 @@ export class Text extends Image {
|
|
|
474
477
|
* @param {number} y - The y position to start updating from.
|
|
475
478
|
*/
|
|
476
479
|
public updateLine(line: string, x: number, y: number): void {
|
|
480
|
+
let cursor = x;
|
|
477
481
|
for (const letter of line) {
|
|
478
482
|
if (this.fontWeights.length > 0 || this.fontStyles.length > 0) {
|
|
479
483
|
const components = this.fontToComponents(this.context.font);
|
|
480
484
|
const charFontStyle = this.fontStyles[this._charCount];
|
|
481
485
|
const charFontWeight = this.fontWeights[this._charCount];
|
|
482
|
-
if (charFontStyle) {
|
|
486
|
+
if (charFontStyle !== undefined && charFontStyle !== null && charFontStyle !== '') {
|
|
483
487
|
components.fontStyle = charFontStyle;
|
|
484
488
|
}
|
|
485
|
-
if (charFontWeight) {
|
|
489
|
+
if (charFontWeight !== undefined && charFontWeight !== null && charFontWeight !== '') {
|
|
486
490
|
components.fontWeight = charFontWeight;
|
|
487
491
|
}
|
|
488
492
|
this.context.font = this.componentsToFont(components);
|
|
489
493
|
}
|
|
490
494
|
if (this.style.stroke && this.style.strokeThickness) {
|
|
491
495
|
const charStrokeColor = this.strokeColors[this._charCount];
|
|
492
|
-
if (charStrokeColor) {
|
|
496
|
+
if (charStrokeColor !== undefined && charStrokeColor !== null && charStrokeColor !== '') {
|
|
493
497
|
this.context.strokeStyle = charStrokeColor;
|
|
494
498
|
}
|
|
495
499
|
this.updateShadow(this.style.shadowStroke ?? false);
|
|
496
|
-
this.context.strokeText(letter,
|
|
500
|
+
this.context.strokeText(letter, cursor, y);
|
|
497
501
|
}
|
|
498
502
|
if (this.style.fill) {
|
|
499
503
|
const charFillColor = this.colors[this._charCount];
|
|
500
|
-
if (charFillColor) {
|
|
504
|
+
if (charFillColor !== undefined && charFillColor !== null && charFillColor !== '') {
|
|
501
505
|
this.context.fillStyle = charFillColor;
|
|
502
506
|
}
|
|
503
507
|
this.updateShadow(this.style.shadowFill ?? false);
|
|
504
|
-
this.context.fillText(letter,
|
|
508
|
+
this.context.fillText(letter, cursor, y);
|
|
505
509
|
}
|
|
506
|
-
|
|
510
|
+
cursor += this.context.measureText(letter).width;
|
|
507
511
|
this._charCount += 1;
|
|
508
512
|
}
|
|
509
513
|
}
|
|
@@ -738,7 +742,7 @@ export class Text extends Image {
|
|
|
738
742
|
* @param {string} font - The font string to convert.
|
|
739
743
|
* @returns {{ font: string, fontStyle?: string, fontVariant?: string, fontWeight?: string, fontSize?: string, fontFamily?: string }} The font components.
|
|
740
744
|
*/
|
|
741
|
-
public fontToComponents(font: string) {
|
|
745
|
+
public fontToComponents(font: string): FontComponents {
|
|
742
746
|
// The format is specified in http://www.w3.org/TR/CSS2/fonts.html#font-shorthand:
|
|
743
747
|
// style - normal | italic | oblique | inherit
|
|
744
748
|
// variant - normal | small-caps | inherit
|
|
@@ -776,31 +780,20 @@ export class Text extends Image {
|
|
|
776
780
|
* @returns {string} The font string.
|
|
777
781
|
*/
|
|
778
782
|
public componentsToFont(components: FontComponents): string {
|
|
779
|
-
const parts = [];
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
if (v && v !== 'normal') {
|
|
791
|
-
parts.push(v);
|
|
792
|
-
}
|
|
793
|
-
v = components.fontSize;
|
|
794
|
-
if (v && v !== 'medium') {
|
|
795
|
-
parts.push(v);
|
|
796
|
-
}
|
|
797
|
-
v = components.fontFamily;
|
|
798
|
-
if (v) {
|
|
799
|
-
parts.push(v);
|
|
800
|
-
}
|
|
783
|
+
const parts: string[] = [];
|
|
784
|
+
const push = (value: string | number | undefined, skip: string): void => {
|
|
785
|
+
if (value !== undefined && value !== '' && value !== skip) {
|
|
786
|
+
parts.push(String(value));
|
|
787
|
+
}
|
|
788
|
+
};
|
|
789
|
+
push(components.fontStyle, 'normal');
|
|
790
|
+
push(components.fontVariant, 'normal');
|
|
791
|
+
push(components.fontWeight, 'normal');
|
|
792
|
+
push(components.fontSize, 'medium');
|
|
793
|
+
push(components.fontFamily, '');
|
|
801
794
|
if (parts.length === 0) {
|
|
802
795
|
// Fallback to whatever value the 'font' was
|
|
803
|
-
parts.push(components.font);
|
|
796
|
+
parts.push(components.font ?? '');
|
|
804
797
|
}
|
|
805
798
|
return parts.join(' ');
|
|
806
799
|
}
|
|
@@ -826,19 +819,20 @@ export class Text extends Image {
|
|
|
826
819
|
* @param {string[]|string[][]} list - The list of text to parse.
|
|
827
820
|
* @returns {Text} This Text object for chaining.
|
|
828
821
|
*/
|
|
829
|
-
public parseList(list:
|
|
822
|
+
public parseList(list: string[] | string[][]): this {
|
|
830
823
|
if (!Array.isArray(list)) {
|
|
831
824
|
return this;
|
|
832
825
|
}
|
|
833
826
|
let s = '';
|
|
834
827
|
for (let i = 0; i < list.length; i += 1) {
|
|
835
|
-
|
|
836
|
-
|
|
828
|
+
const row = list[i]!;
|
|
829
|
+
if (Array.isArray(row)) {
|
|
830
|
+
s += row.join('\t');
|
|
837
831
|
if (i < list.length - 1) {
|
|
838
832
|
s += '\n';
|
|
839
833
|
}
|
|
840
834
|
} else {
|
|
841
|
-
s +=
|
|
835
|
+
s += row;
|
|
842
836
|
if (i < list.length - 1) {
|
|
843
837
|
s += '\t';
|
|
844
838
|
}
|
|
@@ -963,7 +957,7 @@ export class Text extends Image {
|
|
|
963
957
|
* @returns {CanvasRenderingContext2D} The font properties canvas context.
|
|
964
958
|
*/
|
|
965
959
|
public getFontPropertiesContext(): CanvasRenderingContext2D {
|
|
966
|
-
if (
|
|
960
|
+
if (globalThis.PhaserRegistry.fontPropertiesContext === undefined) {
|
|
967
961
|
const canvas = this.getFontPropertiesCanvas();
|
|
968
962
|
const context = canvas.getContext('2d', { willReadFrequently: true });
|
|
969
963
|
if (!context) {
|
|
@@ -1023,7 +1017,7 @@ export class Text extends Image {
|
|
|
1023
1017
|
context.textBaseline = 'alphabetic';
|
|
1024
1018
|
context.fillStyle = '#000';
|
|
1025
1019
|
context.fillText('|MÉq', 0, baseline);
|
|
1026
|
-
if (
|
|
1020
|
+
if (context.getImageData(0, 0, width, height) === null) {
|
|
1027
1021
|
const fallback: FontProperties = {
|
|
1028
1022
|
ascent: baseline,
|
|
1029
1023
|
descent: baseline + 6,
|
|
@@ -1166,7 +1160,7 @@ export class Text extends Image {
|
|
|
1166
1160
|
if (typeof size === 'number') {
|
|
1167
1161
|
return size;
|
|
1168
1162
|
}
|
|
1169
|
-
if (size && /(?:^0$|px$)/.exec(size)) {
|
|
1163
|
+
if (size !== undefined && size !== '' && /(?:^0$|px$)/.exec(size)) {
|
|
1170
1164
|
// Number() cannot read the value here: the string carries a px suffix.
|
|
1171
1165
|
// eslint-disable-next-line unicorn/prefer-number-coercion
|
|
1172
1166
|
return Number.parseInt(size, 10);
|
|
@@ -1,31 +1,41 @@
|
|
|
1
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
2
|
+
import type { NormalShader } from './shader/normal.js';
|
|
3
|
+
|
|
4
|
+
/** A shader uniform: its GLSL type and the value bound to it. */
|
|
5
|
+
export type ShaderUniform = {
|
|
6
|
+
type: string;
|
|
7
|
+
value: unknown;
|
|
8
|
+
};
|
|
9
|
+
|
|
1
10
|
export class AbstractFilter {
|
|
2
|
-
|
|
3
|
-
public passes
|
|
4
|
-
public shaders
|
|
5
|
-
public dirty
|
|
6
|
-
public padding
|
|
7
|
-
public uniforms
|
|
8
|
-
public fragmentSrc
|
|
11
|
+
public _UID: string;
|
|
12
|
+
public passes: AbstractFilter[];
|
|
13
|
+
public shaders: NormalShader[];
|
|
14
|
+
public dirty: boolean;
|
|
15
|
+
public padding: number;
|
|
16
|
+
public uniforms: Record<string, ShaderUniform>;
|
|
17
|
+
public fragmentSrc: string[];
|
|
9
18
|
/**
|
|
10
19
|
* Creates a new AbstractFilter instance.
|
|
11
20
|
* @param {string[]} fragmentSrc - The fragment shader source.
|
|
12
21
|
* @param {object} uniforms - The uniform variables for the shader.
|
|
13
22
|
*/
|
|
14
|
-
public constructor(fragmentSrc: string[], uniforms?:
|
|
23
|
+
public constructor(fragmentSrc: string[], uniforms?: Record<string, ShaderUniform>) {
|
|
24
|
+
this._UID = uuidv4();
|
|
15
25
|
this.passes = [this];
|
|
16
26
|
this.shaders = [];
|
|
17
27
|
this.dirty = true;
|
|
18
28
|
this.padding = 0;
|
|
19
29
|
this.uniforms = uniforms ?? {};
|
|
20
|
-
this.fragmentSrc = fragmentSrc
|
|
30
|
+
this.fragmentSrc = fragmentSrc;
|
|
21
31
|
}
|
|
22
32
|
|
|
23
33
|
/**
|
|
24
34
|
* Initializes the filter.
|
|
25
35
|
*/
|
|
26
36
|
public syncUniforms(): void {
|
|
27
|
-
for (
|
|
28
|
-
|
|
37
|
+
for (const shader of this.shaders) {
|
|
38
|
+
shader.dirty = true;
|
|
29
39
|
}
|
|
30
40
|
}
|
|
31
41
|
}
|