@@ -23,8 +23,8 @@ public sealed class SpriteFont : IDisposable
23
23
readonly SheetBuilder builder ;
24
24
readonly Func < string , float > lineWidth ;
25
25
readonly IFont font ;
26
- readonly Cache < ( char C , Color Color ) , GlyphInfo > glyphs ;
27
- readonly Cache < ( char , Color , int ) , Sprite > contrastGlyphs ;
26
+ readonly Cache < char , GlyphInfo > glyphs ;
27
+ readonly Cache < ( char C , int Radius ) , Sprite > contrastGlyphs ;
28
28
readonly Cache < int , float [ ] > dilationElements ;
29
29
30
30
float deviceScale ;
@@ -39,17 +39,20 @@ public SpriteFont(string name, byte[] data, int size, int ascender, float scale,
39
39
this . builder = builder ;
40
40
41
41
font = Game . Renderer . CreateFont ( data ) ;
42
-
43
- glyphs = new Cache < ( char , Color ) , GlyphInfo > ( CreateGlyph ) ;
44
- contrastGlyphs = new Cache < ( char , Color , int ) , Sprite > ( CreateContrastGlyph ) ;
42
+ glyphs = new Cache < char , GlyphInfo > ( CreateGlyph ) ;
43
+ contrastGlyphs = new Cache < ( char , int ) , Sprite > ( CreateContrastGlyph ) ;
45
44
dilationElements = new Cache < int , float [ ] > ( CreateCircularWeightMap ) ;
46
45
47
46
// PERF: Cache these delegates for Measure calls.
48
- Func < char , float > characterWidth = character => glyphs [ ( character , Color . White ) ] . Advance ;
47
+ Func < char , float > characterWidth = character => glyphs [ character ] . Advance ;
49
48
lineWidth = line => line . Sum ( characterWidth ) / deviceScale ;
50
49
50
+ // Pre-cache small font sizes so glyphs are immediately available when we need them
51
51
if ( size <= 24 )
52
- PrecacheColor ( Color . White , name ) ;
52
+ using ( new PerfTimer ( "Precache {0} {1}px" . F ( name , size ) ) )
53
+ for ( var n = ( char ) 0x20 ; n < ( char ) 0x7f ; n ++ )
54
+ if ( glyphs [ n ] == null )
55
+ throw new InvalidOperationException ( ) ;
53
56
54
57
TopOffset = size - ascender ;
55
58
}
@@ -61,14 +64,6 @@ public void SetScale(float scale)
61
64
contrastGlyphs . Clear ( ) ;
62
65
}
63
66
64
- void PrecacheColor ( Color c , string name )
65
- {
66
- using ( new PerfTimer ( "PrecacheColor {0} {1}px {2}" . F ( name , size , c ) ) )
67
- for ( var n = ( char ) 0x20 ; n < ( char ) 0x7f ; n ++ )
68
- if ( glyphs [ ( n , c ) ] == null )
69
- throw new InvalidOperationException ( ) ;
70
- }
71
-
72
67
void DrawTextContrast ( string text , float2 location , Color contrastColor , int contrastOffset )
73
68
{
74
69
// Offset from the baseline position to the top-left of the glyph for rendering
@@ -78,6 +73,7 @@ void DrawTextContrast(string text, float2 location, Color contrastColor, int con
78
73
var screenContrast = ( int ) ( contrastOffset * deviceScale ) ;
79
74
var screen = new int2 ( ( int ) ( location . X * deviceScale + 0.5f ) , ( int ) ( location . Y * deviceScale + 0.5f ) ) ;
80
75
var contrastVector = new float2 ( screenContrast , screenContrast ) ;
76
+ var tint = new float3 ( contrastColor . R / 255f , contrastColor . G / 255f , contrastColor . B / 255f ) ;
81
77
foreach ( var s in text )
82
78
{
83
79
if ( s == '\n ' )
@@ -87,15 +83,16 @@ void DrawTextContrast(string text, float2 location, Color contrastColor, int con
87
83
continue ;
88
84
}
89
85
90
- var g = glyphs [ ( s , Color . Black ) ] ;
86
+ var g = glyphs [ s ] ;
91
87
92
88
// Convert screen coordinates back to UI coordinates for drawing
93
89
if ( g . Sprite != null )
94
90
{
95
- var contrastSprite = contrastGlyphs [ ( s , contrastColor , screenContrast ) ] ;
96
- Game . Renderer . RgbaSpriteRenderer . DrawSprite ( contrastSprite ,
91
+ var contrastSprite = contrastGlyphs [ ( s , screenContrast ) ] ;
92
+ Game . Renderer . RgbaSpriteRenderer . DrawSpriteWithTint ( contrastSprite ,
97
93
( screen + g . Offset - contrastVector ) / deviceScale ,
98
- contrastSprite . Size / deviceScale ) ;
94
+ contrastSprite . Size / deviceScale ,
95
+ tint ) ;
99
96
}
100
97
101
98
screen += new int2 ( ( int ) ( g . Advance + 0.5f ) , 0 ) ;
@@ -109,6 +106,7 @@ public void DrawText(string text, float2 location, Color c)
109
106
110
107
// Calculate positions in screen pixel coordinates
111
108
var screen = new int2 ( ( int ) ( location . X * deviceScale + 0.5f ) , ( int ) ( location . Y * deviceScale + 0.5f ) ) ;
109
+ var tint = new float3 ( c . R / 255f , c . G / 255f , c . B / 255f ) ;
112
110
foreach ( var s in text )
113
111
{
114
112
if ( s == '\n ' )
@@ -118,13 +116,14 @@ public void DrawText(string text, float2 location, Color c)
118
116
continue ;
119
117
}
120
118
121
- var g = glyphs [ ( s , c ) ] ;
119
+ var g = glyphs [ s ] ;
122
120
123
121
// Convert screen coordinates back to UI coordinates for drawing
124
122
if ( g . Sprite != null )
125
- Game . Renderer . RgbaSpriteRenderer . DrawSprite ( g . Sprite ,
123
+ Game . Renderer . RgbaSpriteRenderer . DrawSpriteWithTint ( g . Sprite ,
126
124
( screen + g . Offset ) . ToFloat2 ( ) / deviceScale ,
127
- g . Sprite . Size / deviceScale ) ;
125
+ g . Sprite . Size / deviceScale ,
126
+ tint ) ;
128
127
129
128
screen += new int2 ( ( int ) ( g . Advance + 0.5f ) , 0 ) ;
130
129
}
@@ -144,6 +143,7 @@ public void DrawText(string text, float2 location, Color c, float angle)
144
143
var offset = new float2 ( 0 , size ) ;
145
144
var cosa = ( float ) Math . Cos ( - angle ) ;
146
145
var sina = ( float ) Math . Sin ( - angle ) ;
146
+ var tint = new float3 ( c . R / 255f , c . G / 255f , c . B / 255f ) ;
147
147
148
148
var p = offset ;
149
149
foreach ( var s in text )
@@ -155,7 +155,7 @@ public void DrawText(string text, float2 location, Color c, float angle)
155
155
continue ;
156
156
}
157
157
158
- var g = glyphs [ ( s , c ) ] ;
158
+ var g = glyphs [ s ] ;
159
159
if ( g . Sprite != null )
160
160
{
161
161
var tl = new float2 (
@@ -172,11 +172,12 @@ public void DrawText(string text, float2 location, Color c, float angle)
172
172
173
173
// Offset rotated glyph to align the top-left corner with the screen pixel grid
174
174
var screenOffset = new float2 ( ( int ) ( ra . X * deviceScale + 0.5f ) , ( int ) ( ra . Y * deviceScale + 0.5f ) ) / deviceScale - ra ;
175
- Game . Renderer . RgbaSpriteRenderer . DrawSprite ( g . Sprite ,
175
+ Game . Renderer . RgbaSpriteRenderer . DrawSpriteWithTint ( g . Sprite ,
176
176
ra + screenOffset ,
177
177
rb + screenOffset ,
178
178
rc + screenOffset ,
179
- rd + screenOffset ) ;
179
+ rd + screenOffset ,
180
+ tint ) ;
180
181
}
181
182
182
183
p += new float2 ( g . Advance / deviceScale , 0 ) ;
@@ -241,10 +242,9 @@ public int2 Measure(string text)
241
242
return new int2 ( ( int ) Math . Ceiling ( lines . Max ( lineWidth ) ) , lines . Length * size ) ;
242
243
}
243
244
244
- GlyphInfo CreateGlyph ( ( char C , Color Color ) c )
245
+ GlyphInfo CreateGlyph ( char c )
245
246
{
246
- var glyph = font . CreateGlyph ( c . C , size , deviceScale ) ;
247
-
247
+ var glyph = font . CreateGlyph ( c , size , deviceScale ) ;
248
248
if ( glyph . Data == null )
249
249
{
250
250
return new GlyphInfo
@@ -274,12 +274,10 @@ GlyphInfo CreateGlyph((char C, Color Color) c)
274
274
if ( p != 0 )
275
275
{
276
276
var q = destStride * ( j + s . Bounds . Top ) + 4 * ( i + s . Bounds . Left ) ;
277
- var pmc = Util . PremultiplyAlpha ( Color . FromArgb ( p , c . Color ) ) ;
278
-
279
- dest [ q ] = pmc . B ;
280
- dest [ q + 1 ] = pmc . G ;
281
- dest [ q + 2 ] = pmc . R ;
282
- dest [ q + 3 ] = pmc . A ;
277
+ dest [ q ] = p ;
278
+ dest [ q + 1 ] = p ;
279
+ dest [ q + 2 ] = p ;
280
+ dest [ q + 3 ] = p ;
283
281
}
284
282
}
285
283
}
@@ -347,16 +345,12 @@ float[] CreateCircularWeightMap(int r)
347
345
return elem ;
348
346
}
349
347
350
- Sprite CreateContrastGlyph ( ( char , Color , int ) c )
348
+ Sprite CreateContrastGlyph ( ( char C , int Radius ) c )
351
349
{
352
- // Source glyph color doesn't matter, so use black
353
- var glyph = glyphs [ ( c . Item1 , Color . Black ) ] ;
354
- var color = c . Item2 ;
355
- var r = c . Item3 ;
356
-
357
- var size = new Size ( glyph . Sprite . Bounds . Width + 2 * r , glyph . Sprite . Bounds . Height + 2 * r ) ;
350
+ var glyph = glyphs [ c . C ] ;
351
+ var r = c . Radius ;
358
352
359
- var s = builder . Allocate ( size ) ;
353
+ var s = builder . Allocate ( new Size ( glyph . Sprite . Bounds . Width + 2 * r , glyph . Sprite . Bounds . Height + 2 * r ) ) ;
360
354
var dest = s . Sheet . GetData ( ) ;
361
355
var destStride = s . Sheet . Size . Width * 4 ;
362
356
@@ -398,11 +392,10 @@ Sprite CreateContrastGlyph((char, Color, int) c)
398
392
if ( alpha > 0 )
399
393
{
400
394
var q = destStride * ( j + s . Bounds . Top ) + 4 * ( i + s . Bounds . Left ) ;
401
- var pmc = Util . PremultiplyAlpha ( Color . FromArgb ( alpha , color ) ) ;
402
- dest [ q ] = pmc . B ;
403
- dest [ q + 1 ] = pmc . G ;
404
- dest [ q + 2 ] = pmc . R ;
405
- dest [ q + 3 ] = pmc . A ;
395
+ dest [ q ] = alpha ;
396
+ dest [ q + 1 ] = alpha ;
397
+ dest [ q + 2 ] = alpha ;
398
+ dest [ q + 3 ] = alpha ;
406
399
}
407
400
}
408
401
}
0 commit comments