Skip to content

Commit 6cfa27c

Browse files
pchoteteinarss
authored andcommitted
Replace per-color font caches with tinted rendering.
1 parent a405969 commit 6cfa27c

File tree

1 file changed

+40
-47
lines changed

1 file changed

+40
-47
lines changed

OpenRA.Game/Graphics/SpriteFont.cs

Lines changed: 40 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ public sealed class SpriteFont : IDisposable
2323
readonly SheetBuilder builder;
2424
readonly Func<string, float> lineWidth;
2525
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;
2828
readonly Cache<int, float[]> dilationElements;
2929

3030
float deviceScale;
@@ -39,17 +39,20 @@ public SpriteFont(string name, byte[] data, int size, int ascender, float scale,
3939
this.builder = builder;
4040

4141
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);
4544
dilationElements = new Cache<int, float[]>(CreateCircularWeightMap);
4645

4746
// 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;
4948
lineWidth = line => line.Sum(characterWidth) / deviceScale;
5049

50+
// Pre-cache small font sizes so glyphs are immediately available when we need them
5151
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();
5356

5457
TopOffset = size - ascender;
5558
}
@@ -61,14 +64,6 @@ public void SetScale(float scale)
6164
contrastGlyphs.Clear();
6265
}
6366

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-
7267
void DrawTextContrast(string text, float2 location, Color contrastColor, int contrastOffset)
7368
{
7469
// 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
7873
var screenContrast = (int)(contrastOffset * deviceScale);
7974
var screen = new int2((int)(location.X * deviceScale + 0.5f), (int)(location.Y * deviceScale + 0.5f));
8075
var contrastVector = new float2(screenContrast, screenContrast);
76+
var tint = new float3(contrastColor.R / 255f, contrastColor.G / 255f, contrastColor.B / 255f);
8177
foreach (var s in text)
8278
{
8379
if (s == '\n')
@@ -87,15 +83,16 @@ void DrawTextContrast(string text, float2 location, Color contrastColor, int con
8783
continue;
8884
}
8985

90-
var g = glyphs[(s, Color.Black)];
86+
var g = glyphs[s];
9187

9288
// Convert screen coordinates back to UI coordinates for drawing
9389
if (g.Sprite != null)
9490
{
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,
9793
(screen + g.Offset - contrastVector) / deviceScale,
98-
contrastSprite.Size / deviceScale);
94+
contrastSprite.Size / deviceScale,
95+
tint);
9996
}
10097

10198
screen += new int2((int)(g.Advance + 0.5f), 0);
@@ -109,6 +106,7 @@ public void DrawText(string text, float2 location, Color c)
109106

110107
// Calculate positions in screen pixel coordinates
111108
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);
112110
foreach (var s in text)
113111
{
114112
if (s == '\n')
@@ -118,13 +116,14 @@ public void DrawText(string text, float2 location, Color c)
118116
continue;
119117
}
120118

121-
var g = glyphs[(s, c)];
119+
var g = glyphs[s];
122120

123121
// Convert screen coordinates back to UI coordinates for drawing
124122
if (g.Sprite != null)
125-
Game.Renderer.RgbaSpriteRenderer.DrawSprite(g.Sprite,
123+
Game.Renderer.RgbaSpriteRenderer.DrawSpriteWithTint(g.Sprite,
126124
(screen + g.Offset).ToFloat2() / deviceScale,
127-
g.Sprite.Size / deviceScale);
125+
g.Sprite.Size / deviceScale,
126+
tint);
128127

129128
screen += new int2((int)(g.Advance + 0.5f), 0);
130129
}
@@ -144,6 +143,7 @@ public void DrawText(string text, float2 location, Color c, float angle)
144143
var offset = new float2(0, size);
145144
var cosa = (float)Math.Cos(-angle);
146145
var sina = (float)Math.Sin(-angle);
146+
var tint = new float3(c.R / 255f, c.G / 255f, c.B / 255f);
147147

148148
var p = offset;
149149
foreach (var s in text)
@@ -155,7 +155,7 @@ public void DrawText(string text, float2 location, Color c, float angle)
155155
continue;
156156
}
157157

158-
var g = glyphs[(s, c)];
158+
var g = glyphs[s];
159159
if (g.Sprite != null)
160160
{
161161
var tl = new float2(
@@ -172,11 +172,12 @@ public void DrawText(string text, float2 location, Color c, float angle)
172172

173173
// Offset rotated glyph to align the top-left corner with the screen pixel grid
174174
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,
176176
ra + screenOffset,
177177
rb + screenOffset,
178178
rc + screenOffset,
179-
rd + screenOffset);
179+
rd + screenOffset,
180+
tint);
180181
}
181182

182183
p += new float2(g.Advance / deviceScale, 0);
@@ -241,10 +242,9 @@ public int2 Measure(string text)
241242
return new int2((int)Math.Ceiling(lines.Max(lineWidth)), lines.Length * size);
242243
}
243244

244-
GlyphInfo CreateGlyph((char C, Color Color) c)
245+
GlyphInfo CreateGlyph(char c)
245246
{
246-
var glyph = font.CreateGlyph(c.C, size, deviceScale);
247-
247+
var glyph = font.CreateGlyph(c, size, deviceScale);
248248
if (glyph.Data == null)
249249
{
250250
return new GlyphInfo
@@ -274,12 +274,10 @@ GlyphInfo CreateGlyph((char C, Color Color) c)
274274
if (p != 0)
275275
{
276276
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;
283281
}
284282
}
285283
}
@@ -347,16 +345,12 @@ float[] CreateCircularWeightMap(int r)
347345
return elem;
348346
}
349347

350-
Sprite CreateContrastGlyph((char, Color, int) c)
348+
Sprite CreateContrastGlyph((char C, int Radius) c)
351349
{
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;
358352

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));
360354
var dest = s.Sheet.GetData();
361355
var destStride = s.Sheet.Size.Width * 4;
362356

@@ -398,11 +392,10 @@ Sprite CreateContrastGlyph((char, Color, int) c)
398392
if (alpha > 0)
399393
{
400394
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;
406399
}
407400
}
408401
}

0 commit comments

Comments
 (0)