• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

excaliburjs / Excalibur / 15354777440

30 May 2025 08:03PM UTC coverage: 87.858% (-1.5%) from 89.344%
15354777440

Pull #3385

github

web-flow
Merge a00f57733 into e6ec66358
Pull Request #3385: updated Meet action to add tolerance

5002 of 6948 branches covered (71.99%)

3 of 5 new or added lines in 2 files covered. (60.0%)

872 existing lines in 83 files now uncovered.

13661 of 15549 relevant lines covered (87.86%)

25187.01 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

39.53
/src/engine/Graphics/Text.ts
1
import type { ExcaliburGraphicsContext } from './Context/ExcaliburGraphicsContext';
2
import type { BoundingBox } from '../Collision/BoundingBox';
3
import type { SpriteFont } from './SpriteFont';
4
import type { GraphicOptions } from './Graphic';
5
import { Graphic } from './Graphic';
6
import { Color } from '../Color';
7
import { Font } from './Font';
8

9
export interface TextOptions {
10
  /**
11
   * Text to draw
12
   */
13
  text: string;
14

15
  /**
16
   * Optionally override the font color, currently unsupported by SpriteFont
17
   */
18
  color?: Color;
19

20
  /**
21
   * Optionally specify a font, if none specified a default font is used (System sans-serif 10 pixel)
22
   */
23
  font?: Font | SpriteFont;
24

25
  /**
26
   * Optionally specify a maximum width in pixels for our text, and wrap to the next line if needed.
27
   */
28
  maxWidth?: number;
29
}
30

31
/**
32
 * Represent Text graphics in excalibur
33
 *
34
 * Useful for in game labels, ui, or overlays
35
 */
36
export class Text extends Graphic {
37
  public color?: Color;
38
  public maxWidth?: number;
39
  constructor(options: TextOptions & GraphicOptions) {
40
    super(options);
5✔
41
    // This order is important font, color, then text
42
    this.font = options.font ?? new Font();
5!
43
    this.color = options.color ?? this.color;
5!
44
    this.text = options.text;
5✔
45
    this.maxWidth = options.maxWidth;
5✔
46
  }
47

48
  public clone(): Text {
UNCOV
49
    return new Text({
×
50
      text: this.text.slice(),
51
      color: this.color?.clone() ?? Color.Black,
×
52
      font: this.font.clone(),
53
      maxWidth: this.maxWidth
54
    });
55
  }
56

57
  private _text: string = '';
5✔
58
  public get text() {
59
    return this._text;
2✔
60
  }
61

62
  public set text(value: string) {
63
    this._text = value;
10✔
64
    this._calculateDimension();
10✔
65
  }
66

67
  private _font!: Font | SpriteFont;
68
  public get font(): Font | SpriteFont {
69
    return this._font;
20✔
70
  }
71
  public set font(font: Font | SpriteFont) {
72
    this._font = font;
11✔
73
  }
74

75
  private _textWidth: number = 0;
5✔
76

77
  public get width() {
78
    if (this._textWidth === 0) {
×
UNCOV
79
      this._calculateDimension();
×
80
    }
UNCOV
81
    return this._textWidth * this.scale.x;
×
82
  }
83

84
  private _textHeight: number = 0;
5✔
85
  public get height() {
86
    if (this._textHeight === 0) {
×
UNCOV
87
      this._calculateDimension();
×
88
    }
UNCOV
89
    return this._textHeight * this.scale.y;
×
90
  }
91

92
  private _calculateDimension() {
93
    const { width, height } = this.font.measureText(this._text, this.maxWidth);
10✔
94
    this._textWidth = width;
10✔
95
    this._textHeight = height;
10✔
96
  }
97

98
  public get localBounds(): BoundingBox {
99
    return this.font.measureText(this._text, this.maxWidth).scale(this.scale);
10✔
100
  }
101

102
  protected override _rotate(_ex: ExcaliburGraphicsContext) {
103
    // None this is delegated to font
104
    // This override erases the default behavior
105
  }
106

107
  protected override _flip(_ex: ExcaliburGraphicsContext) {
108
    // None this is delegated to font
109
    // This override erases the default behavior
110
  }
111

112
  protected override _preDraw(ex: ExcaliburGraphicsContext, x: number, y: number): void {
UNCOV
113
    if (this.isStale() || this.font.isStale()) {
×
UNCOV
114
      this.font.flipHorizontal = this.flipHorizontal;
×
UNCOV
115
      this.font.flipVertical = this.flipVertical;
×
UNCOV
116
      this.font.rotation = this.rotation;
×
UNCOV
117
      this.font.origin = this.origin;
×
UNCOV
118
      this.font.opacity = this.opacity;
×
119
    }
UNCOV
120
    this.font.tint = this.tint;
×
UNCOV
121
    super._preDraw(ex, x, y);
×
122
  }
123

124
  protected override _drawImage(ex: ExcaliburGraphicsContext, x: number, y: number) {
UNCOV
125
    let color = Color.Black;
×
UNCOV
126
    if (this.font instanceof Font) {
×
UNCOV
127
      color = this.color ?? this.font.color;
×
128
    }
129

UNCOV
130
    const { width, height } = this.font.measureText(this._text, this.maxWidth);
×
UNCOV
131
    this._textWidth = width;
×
UNCOV
132
    this._textHeight = height;
×
133

UNCOV
134
    this.font.render(ex, this._text, color, x, y, this.maxWidth);
×
135

136
    if (this.font.showDebug) {
×
137
      ex.debug.drawRect(x - width, y - height, width * 2, height * 2);
×
138
      if (this.maxWidth != null) {
×
UNCOV
139
        ex.debug.drawRect(x, y, this.maxWidth, this.height, {
×
140
          color: Color.Yellow
141
        });
142
      }
143
    }
144
  }
145
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc