Show More
Commit Description:
Add more stories.
Commit Description:
Add more stories.
References:
File last commit:
Show/Diff file:
Action:
SpriteFontPlus/src/FontStashSharp/FontSystem.cs
815 lines | 17.7 KiB | text/x-csharp | CSharpLexer
815 lines | 17.7 KiB | text/x-csharp | CSharpLexer
r0 | using System; | ||
using System.Collections.Generic; | |||
using System.Text; | |||
using Microsoft.Xna.Framework; | |||
using Microsoft.Xna.Framework.Graphics; | |||
namespace FontStashSharp | |||
{ | |||
internal class FontSystem | |||
{ | |||
private readonly Dictionary<int, Dictionary<int, FontGlyph>> _glyphs = new Dictionary<int, Dictionary<int, FontGlyph>>(); | |||
private readonly List<Font> _fonts = new List<Font>(); | |||
private float _ith; | |||
private float _itw; | |||
private FontAtlas _currentAtlas; | |||
private Point _size; | |||
private int _fontSize; | |||
public int FontSize | |||
{ | |||
get | |||
{ | |||
return _fontSize; | |||
} | |||
set | |||
{ | |||
if (value == _fontSize) | |||
{ | |||
return; | |||
} | |||
_fontSize = value; | |||
foreach (var f in _fonts) | |||
{ | |||
f.Recalculate(_fontSize); | |||
} | |||
} | |||
} | |||
public readonly int Blur; | |||
public float Spacing; | |||
public Vector2 Scale; | |||
public bool UseKernings = true; | |||
public int? DefaultCharacter = ' '; | |||
public FontAtlas CurrentAtlas | |||
{ | |||
get | |||
{ | |||
if (_currentAtlas == null) | |||
{ | |||
_currentAtlas = new FontAtlas(_size.X, _size.Y, 256); | |||
Atlases.Add(_currentAtlas); | |||
} | |||
return _currentAtlas; | |||
} | |||
} | |||
public List<FontAtlas> Atlases { get; } = new List<FontAtlas>(); | |||
public event EventHandler CurrentAtlasFull; | |||
public FontSystem(int width, int height, int blur = 0) | |||
{ | |||
if (width <= 0) | |||
{ | |||
throw new ArgumentOutOfRangeException(nameof(width)); | |||
} | |||
if (height <= 0) | |||
{ | |||
throw new ArgumentOutOfRangeException(nameof(height)); | |||
} | |||
if (blur < 0 || blur > 20) | |||
{ | |||
throw new ArgumentOutOfRangeException(nameof(blur)); | |||
} | |||
Blur = blur; | |||
_size = new Point(width, height); | |||
_itw = 1.0f / _size.X; | |||
_ith = 1.0f / _size.Y; | |||
ClearState(); | |||
} | |||
public void ClearState() | |||
{ | |||
FontSize = 12; | |||
Spacing = 0; | |||
} | |||
public void AddFontMem(byte[] data) | |||
{ | |||
var font = Font.FromMemory(data); | |||
font.Recalculate(FontSize); | |||
_fonts.Add(font); | |||
} | |||
private Dictionary<int, FontGlyph> GetGlyphsCollection(int size) | |||
{ | |||
Dictionary<int, FontGlyph> result; | |||
if (_glyphs.TryGetValue(size, out result)) | |||
{ | |||
return result; | |||
} | |||
result = new Dictionary<int, FontGlyph>(); | |||
_glyphs[size] = result; | |||
return result; | |||
} | |||
private void PreDraw(string str, out Dictionary<int, FontGlyph> glyphs, out float ascent, out float lineHeight) | |||
{ | |||
glyphs = GetGlyphsCollection(FontSize); | |||
// Determine ascent and lineHeight from first character | |||
ascent = 0; | |||
lineHeight = 0; | |||
for (int i = 0; i < str.Length; i += char.IsSurrogatePair(str, i) ? 2 : 1) | |||
{ | |||
var codepoint = char.ConvertToUtf32(str, i); | |||
var glyph = GetGlyph(null, glyphs, codepoint); | |||
if (glyph == null) | |||
{ | |||
continue; | |||
} | |||
ascent = glyph.Font.Ascent; | |||
lineHeight = glyph.Font.LineHeight; | |||
break; | |||
} | |||
} | |||
public float DrawText(SpriteBatch batch, float x, float y, string str, Color color, float depth) | |||
{ | |||
if (string.IsNullOrEmpty(str)) return 0.0f; | |||
Dictionary<int, FontGlyph> glyphs; | |||
float ascent, lineHeight; | |||
PreDraw(str, out glyphs, out ascent, out lineHeight); | |||
float originX = 0.0f; | |||
float originY = 0.0f; | |||
originY += ascent; | |||
FontGlyph prevGlyph = null; | |||
var q = new FontGlyphSquad(); | |||
for (int i = 0; i < str.Length; i += char.IsSurrogatePair(str, i) ? 2 : 1) | |||
{ | |||
var codepoint = char.ConvertToUtf32(str, i); | |||
if (codepoint == '\n') | |||
{ | |||
originX = 0.0f; | |||
originY += lineHeight; | |||
prevGlyph = null; | |||
continue; | |||
} | |||
var glyph = GetGlyph(batch.GraphicsDevice, glyphs, codepoint); | |||
if (glyph == null) | |||
{ | |||
continue; | |||
} | |||
GetQuad(glyph, prevGlyph, Spacing, ref originX, ref originY, ref q); | |||
if (!glyph.IsEmpty) | |||
{ | |||
q.X0 = (int)(q.X0 * Scale.X); | |||
q.X1 = (int)(q.X1 * Scale.X); | |||
q.Y0 = (int)(q.Y0 * Scale.Y); | |||
q.Y1 = (int)(q.Y1 * Scale.Y); | |||
var destRect = new Rectangle((int)(x + q.X0), | |||
(int)(y + q.Y0), | |||
(int)(q.X1 - q.X0), | |||
(int)(q.Y1 - q.Y0)); | |||
var sourceRect = new Rectangle((int)(q.S0 * _size.X), | |||
(int)(q.T0 * _size.Y), | |||
(int)((q.S1 - q.S0) * _size.X), | |||
(int)((q.T1 - q.T0) * _size.Y)); | |||
batch.Draw(glyph.Atlas.Texture, | |||
destRect, | |||
sourceRect, | |||
color, | |||
0f, | |||
Vector2.Zero, | |||
SpriteEffects.None, | |||
depth); | |||
} | |||
prevGlyph = glyph; | |||
} | |||
return x; | |||
} | |||
public float DrawText(SpriteBatch batch, float x, float y, string str, Color[] glyphColors, float depth) | |||
{ | |||
if (string.IsNullOrEmpty(str)) return 0.0f; | |||
Dictionary<int, FontGlyph> glyphs; | |||
float ascent, lineHeight; | |||
PreDraw(str, out glyphs, out ascent, out lineHeight); | |||
float originX = 0.0f; | |||
float originY = 0.0f; | |||
originY += ascent; | |||
FontGlyph prevGlyph = null; | |||
var pos = 0; | |||
var q = new FontGlyphSquad(); | |||
for (int i = 0; i < str.Length; i += char.IsSurrogatePair(str, i) ? 2 : 1) | |||
{ | |||
var codepoint = char.ConvertToUtf32(str, i); | |||
if (codepoint == '\n') | |||
{ | |||
originX = 0.0f; | |||
originY += lineHeight; | |||
prevGlyph = null; | |||
++pos; | |||
continue; | |||
} | |||
var glyph = GetGlyph(batch.GraphicsDevice, glyphs, codepoint); | |||
if (glyph == null) | |||
{ | |||
++pos; | |||
continue; | |||
} | |||
GetQuad(glyph, prevGlyph, Spacing, ref originX, ref originY, ref q); | |||
if (!glyph.IsEmpty) | |||
{ | |||
q.X0 = (int)(q.X0 * Scale.X); | |||
q.X1 = (int)(q.X1 * Scale.X); | |||
q.Y0 = (int)(q.Y0 * Scale.Y); | |||
q.Y1 = (int)(q.Y1 * Scale.Y); | |||
var destRect = new Rectangle((int)(x + q.X0), | |||
(int)(y + q.Y0), | |||
(int)(q.X1 - q.X0), | |||
(int)(q.Y1 - q.Y0)); | |||
var sourceRect = new Rectangle((int)(q.S0 * _size.X), | |||
(int)(q.T0 * _size.Y), | |||
(int)((q.S1 - q.S0) * _size.X), | |||
(int)((q.T1 - q.T0) * _size.Y)); | |||
batch.Draw(glyph.Atlas.Texture, | |||
destRect, | |||
sourceRect, | |||
glyphColors[pos], | |||
0f, | |||
Vector2.Zero, | |||
SpriteEffects.None, | |||
depth); | |||
} | |||
prevGlyph = glyph; | |||
++pos; | |||
} | |||
return x; | |||
} | |||
private void PreDraw(StringBuilder str, out Dictionary<int, FontGlyph> glyphs, out float ascent, out float lineHeight) | |||
{ | |||
glyphs = GetGlyphsCollection(FontSize); | |||
// Determine ascent and lineHeight from first character | |||
ascent = 0; | |||
lineHeight = 0; | |||
for (int i = 0; i < str.Length; i += StringBuilderIsSurrogatePair(str, i) ? 2 : 1) | |||
{ | |||
var codepoint = StringBuilderConvertToUtf32(str, i); | |||
var glyph = GetGlyph(null, glyphs, codepoint); | |||
if (glyph == null) | |||
{ | |||
continue; | |||
} | |||
ascent = glyph.Font.Ascent; | |||
lineHeight = glyph.Font.LineHeight; | |||
break; | |||
} | |||
} | |||
public float DrawText(SpriteBatch batch, float x, float y, StringBuilder str, Color color, float depth) | |||
{ | |||
if (str == null || str.Length == 0) return 0.0f; | |||
Dictionary<int, FontGlyph> glyphs; | |||
float ascent, lineHeight; | |||
PreDraw(str, out glyphs, out ascent, out lineHeight); | |||
float originX = 0.0f; | |||
float originY = 0.0f; | |||
originY += ascent; | |||
FontGlyph prevGlyph = null; | |||
var q = new FontGlyphSquad(); | |||
for (int i = 0; i < str.Length; i += StringBuilderIsSurrogatePair(str, i) ? 2 : 1) | |||
{ | |||
var codepoint = StringBuilderConvertToUtf32(str, i); | |||
if (codepoint == '\n') | |||
{ | |||
originX = 0.0f; | |||
originY += lineHeight; | |||
prevGlyph = null; | |||
continue; | |||
} | |||
var glyph = GetGlyph(batch.GraphicsDevice, glyphs, codepoint); | |||
if (glyph == null) | |||
{ | |||
continue; | |||
} | |||
GetQuad(glyph, prevGlyph, Spacing, ref originX, ref originY, ref q); | |||
if (!glyph.IsEmpty) | |||
{ | |||
q.X0 = (int)(q.X0 * Scale.X); | |||
q.X1 = (int)(q.X1 * Scale.X); | |||
q.Y0 = (int)(q.Y0 * Scale.Y); | |||
q.Y1 = (int)(q.Y1 * Scale.Y); | |||
var destRect = new Rectangle((int)(x + q.X0), | |||
(int)(y + q.Y0), | |||
(int)(q.X1 - q.X0), | |||
(int)(q.Y1 - q.Y0)); | |||
var sourceRect = new Rectangle((int)(q.S0 * _size.X), | |||
(int)(q.T0 * _size.Y), | |||
(int)((q.S1 - q.S0) * _size.X), | |||
(int)((q.T1 - q.T0) * _size.Y)); | |||
batch.Draw(glyph.Atlas.Texture, | |||
destRect, | |||
sourceRect, | |||
color, | |||
0f, | |||
Vector2.Zero, | |||
SpriteEffects.None, | |||
depth); | |||
} | |||
prevGlyph = glyph; | |||
} | |||
return x; | |||
} | |||
public float DrawText(SpriteBatch batch, float x, float y, StringBuilder str, Color[] glyphColors, float depth) | |||
{ | |||
if (str == null || str.Length == 0) return 0.0f; | |||
Dictionary<int, FontGlyph> glyphs; | |||
float ascent, lineHeight; | |||
PreDraw(str, out glyphs, out ascent, out lineHeight); | |||
float originX = 0.0f; | |||
float originY = 0.0f; | |||
originY += ascent; | |||
FontGlyph prevGlyph = null; | |||
var pos = 0; | |||
var q = new FontGlyphSquad(); | |||
for (int i = 0; i < str.Length; i += StringBuilderIsSurrogatePair(str, i) ? 2 : 1) | |||
{ | |||
var codepoint = StringBuilderConvertToUtf32(str, i); | |||
if (codepoint == '\n') | |||
{ | |||
originX = 0.0f; | |||
originY += lineHeight; | |||
prevGlyph = null; | |||
++pos; | |||
continue; | |||
} | |||
var glyph = GetGlyph(batch.GraphicsDevice, glyphs, codepoint); | |||
if (glyph == null) | |||
{ | |||
++pos; | |||
continue; | |||
} | |||
GetQuad(glyph, prevGlyph, Spacing, ref originX, ref originY, ref q); | |||
if (!glyph.IsEmpty) | |||
{ | |||
q.X0 = (int)(q.X0 * Scale.X); | |||
q.X1 = (int)(q.X1 * Scale.X); | |||
q.Y0 = (int)(q.Y0 * Scale.Y); | |||
q.Y1 = (int)(q.Y1 * Scale.Y); | |||
var destRect = new Rectangle((int)(x + q.X0), | |||
(int)(y + q.Y0), | |||
(int)(q.X1 - q.X0), | |||
(int)(q.Y1 - q.Y0)); | |||
var sourceRect = new Rectangle((int)(q.S0 * _size.X), | |||
(int)(q.T0 * _size.Y), | |||
(int)((q.S1 - q.S0) * _size.X), | |||
(int)((q.T1 - q.T0) * _size.Y)); | |||
batch.Draw(glyph.Atlas.Texture, | |||
destRect, | |||
sourceRect, | |||
glyphColors[pos], | |||
0f, | |||
Vector2.Zero, | |||
SpriteEffects.None, | |||
depth); | |||
} | |||
prevGlyph = glyph; | |||
++pos; | |||
} | |||
return x; | |||
} | |||
public float TextBounds(float x, float y, string str, ref Bounds bounds) | |||
{ | |||
if (string.IsNullOrEmpty(str)) return 0.0f; | |||
Dictionary<int, FontGlyph> glyphs; | |||
float ascent, lineHeight; | |||
PreDraw(str, out glyphs, out ascent, out lineHeight); | |||
var q = new FontGlyphSquad(); | |||
y += ascent; | |||
float minx, maxx, miny, maxy; | |||
minx = maxx = x; | |||
miny = maxy = y; | |||
float startx = x; | |||
FontGlyph prevGlyph = null; | |||
for (int i = 0; i < str.Length; i += char.IsSurrogatePair(str, i) ? 2 : 1) | |||
{ | |||
var codepoint = char.ConvertToUtf32(str, i); | |||
if (codepoint == '\n') | |||
{ | |||
x = startx; | |||
y += lineHeight; | |||
prevGlyph = null; | |||
continue; | |||
} | |||
var glyph = GetGlyph(null, glyphs, codepoint); | |||
if (glyph == null) | |||
{ | |||
continue; | |||
} | |||
GetQuad(glyph, prevGlyph, Spacing, ref x, ref y, ref q); | |||
if (q.X0 < minx) | |||
minx = q.X0; | |||
if (x > maxx) | |||
maxx = x; | |||
if (q.Y0 < miny) | |||
miny = q.Y0; | |||
if (q.Y1 > maxy) | |||
maxy = q.Y1; | |||
prevGlyph = glyph; | |||
} | |||
float advance = x - startx; | |||
bounds.X = minx; | |||
bounds.Y = miny; | |||
bounds.X2 = maxx; | |||
bounds.Y2 = maxy; | |||
return advance; | |||
} | |||
public float TextBounds(float x, float y, StringBuilder str, ref Bounds bounds) | |||
{ | |||
if (str == null || str.Length == 0) return 0.0f; | |||
Dictionary<int, FontGlyph> glyphs; | |||
float ascent, lineHeight; | |||
PreDraw(str, out glyphs, out ascent, out lineHeight); | |||
var q = new FontGlyphSquad(); | |||
y += ascent; | |||
float minx, maxx, miny, maxy; | |||
minx = maxx = x; | |||
miny = maxy = y; | |||
float startx = x; | |||
FontGlyph prevGlyph = null; | |||
for (int i = 0; i < str.Length; i += StringBuilderIsSurrogatePair(str, i) ? 2 : 1) | |||
{ | |||
var codepoint = StringBuilderConvertToUtf32(str, i); | |||
if (codepoint == '\n') | |||
{ | |||
x = startx; | |||
y += lineHeight; | |||
prevGlyph = null; | |||
continue; | |||
} | |||
var glyph = GetGlyph(null, glyphs, codepoint); | |||
if (glyph == null) | |||
{ | |||
continue; | |||
} | |||
GetQuad(glyph, prevGlyph, Spacing, ref x, ref y, ref q); | |||
if (q.X0 < minx) | |||
minx = q.X0; | |||
if (x > maxx) | |||
maxx = x; | |||
if (q.Y0 < miny) | |||
miny = q.Y0; | |||
if (q.Y1 > maxy) | |||
maxy = q.Y1; | |||
prevGlyph = glyph; | |||
} | |||
float advance = x - startx; | |||
bounds.X = minx; | |||
bounds.Y = miny; | |||
bounds.X2 = maxx; | |||
bounds.Y2 = maxy; | |||
return advance; | |||
} | |||
public List<Rectangle> GetGlyphRects(float x, float y, string str){ | |||
List<Rectangle> Rects = new List<Rectangle>(); | |||
if (string.IsNullOrEmpty(str)) return Rects; | |||
Dictionary<int, FontGlyph> glyphs; | |||
float ascent, lineHeight; | |||
PreDraw(str, out glyphs, out ascent, out lineHeight); | |||
var q = new FontGlyphSquad(); | |||
y += ascent; | |||
float minx, maxx, miny, maxy; | |||
minx = maxx = x; | |||
miny = maxy = y; | |||
float startx = x; | |||
FontGlyph prevGlyph = null; | |||
for (int i = 0; i < str.Length; i += char.IsSurrogatePair(str, i) ? 2 : 1) | |||
{ | |||
var codepoint = char.ConvertToUtf32(str, i); | |||
if (codepoint == '\n') | |||
{ | |||
x = startx; | |||
y += lineHeight; | |||
prevGlyph = null; | |||
continue; | |||
} | |||
var glyph = GetGlyph(null, glyphs, codepoint); | |||
if (glyph == null) | |||
{ | |||
continue; | |||
} | |||
GetQuad(glyph, prevGlyph, Spacing, ref x, ref y, ref q); | |||
Rects.Add(new Rectangle((int)q.X0, (int)q.Y0, (int)(q.X1-q.X0), (int)(q.Y1-q.Y0))); | |||
prevGlyph = glyph; | |||
} | |||
return Rects; | |||
} | |||
public List<Rectangle> GetGlyphRects(float x, float y, StringBuilder str){ | |||
List<Rectangle> Rects = new List<Rectangle>(); | |||
if (str == null || str.Length == 0) return Rects; | |||
Dictionary<int, FontGlyph> glyphs; | |||
float ascent, lineHeight; | |||
PreDraw(str, out glyphs, out ascent, out lineHeight); | |||
var q = new FontGlyphSquad(); | |||
y += ascent; | |||
float minx, maxx, miny, maxy; | |||
minx = maxx = x; | |||
miny = maxy = y; | |||
float startx = x; | |||
FontGlyph prevGlyph = null; | |||
for (int i = 0; i < str.Length; i += StringBuilderIsSurrogatePair(str, i) ? 2 : 1) | |||
{ | |||
var codepoint = StringBuilderConvertToUtf32(str, i); | |||
if (codepoint == '\n') | |||
{ | |||
x = startx; | |||
y += lineHeight; | |||
prevGlyph = null; | |||
continue; | |||
} | |||
var glyph = GetGlyph(null, glyphs, codepoint); | |||
if (glyph == null) | |||
{ | |||
continue; | |||
} | |||
GetQuad(glyph, prevGlyph, Spacing, ref x, ref y, ref q); | |||
Rects.Add(new Rectangle((int)q.X0, (int)q.Y0, (int)(q.X1-q.X0), (int)(q.Y1-q.Y0))); | |||
prevGlyph = glyph; | |||
} | |||
return Rects; | |||
} | |||
bool StringBuilderIsSurrogatePair(StringBuilder sb, int index) | |||
{ | |||
if (index + 1 < sb.Length) | |||
return char.IsSurrogatePair(sb[index], sb[index + 1]); | |||
return false; | |||
} | |||
int StringBuilderConvertToUtf32(StringBuilder sb, int index) | |||
{ | |||
if (!char.IsHighSurrogate(sb[index])) | |||
return sb[index]; | |||
return char.ConvertToUtf32(sb[index], sb[index + 1]); | |||
} | |||
public void Reset(int width, int height) | |||
{ | |||
Atlases.Clear(); | |||
_glyphs.Clear(); | |||
if (width == _size.X && height == _size.Y) | |||
return; | |||
_size = new Point(width, height); | |||
_itw = 1.0f / _size.X; | |||
_ith = 1.0f / _size.Y; | |||
} | |||
public void Reset() | |||
{ | |||
Reset(_size.X, _size.Y); | |||
} | |||
private int GetCodepointIndex(int codepoint, out Font font) | |||
{ | |||
font = null; | |||
int g = 0; | |||
foreach (var f in _fonts) | |||
{ | |||
g = f.GetGlyphIndex(codepoint); | |||
if (g != 0) | |||
{ | |||
font = f; | |||
break; | |||
} | |||
} | |||
return g; | |||
} | |||
private FontGlyph GetGlyphWithoutBitmap(Dictionary<int, FontGlyph> glyphs, int codepoint) | |||
{ | |||
FontGlyph glyph = null; | |||
if (glyphs.TryGetValue(codepoint, out glyph)) | |||
{ | |||
return glyph; | |||
} | |||
Font font; | |||
var g = GetCodepointIndex(codepoint, out font); | |||
if (g == 0) | |||
{ | |||
return null; | |||
} | |||
int advance = 0, lsb = 0, x0 = 0, y0 = 0, x1 = 0, y1 = 0; | |||
font.BuildGlyphBitmap(g, FontSize, font.Scale, ref advance, ref lsb, ref x0, ref y0, ref x1, ref y1); | |||
var gw = x1 - x0; | |||
var gh = y1 - y0; | |||
glyph = new FontGlyph | |||
{ | |||
Font = font, | |||
Codepoint = codepoint, | |||
Size = FontSize, | |||
Index = g, | |||
Bounds = new Rectangle(0, 0, gw, gh), | |||
XAdvance = (int)(font.Scale * advance * 10.0f), | |||
XOffset = x0, | |||
YOffset = y0 | |||
}; | |||
glyphs[codepoint] = glyph; | |||
return glyph; | |||
} | |||
private FontGlyph GetGlyphInternal(GraphicsDevice graphicsDevice, Dictionary<int, FontGlyph> glyphs, int codepoint) | |||
{ | |||
var glyph = GetGlyphWithoutBitmap(glyphs, codepoint); | |||
if (glyph == null) | |||
{ | |||
return null; | |||
} | |||
if (graphicsDevice == null || glyph.Atlas != null || glyph.IsEmpty) | |||
return glyph; | |||
var currentAtlas = CurrentAtlas; | |||
int gx = 0, gy = 0; | |||
var gw = glyph.Bounds.Width; | |||
var gh = glyph.Bounds.Height; | |||
if (!currentAtlas.AddRect(gw, gh, ref gx, ref gy)) | |||
{ | |||
CurrentAtlasFull?.Invoke(this, EventArgs.Empty); | |||
// This code will force creation of new atlas | |||
_currentAtlas = null; | |||
currentAtlas = CurrentAtlas; | |||
// Try to add again | |||
if (!currentAtlas.AddRect(gw, gh, ref gx, ref gy)) | |||
{ | |||
throw new Exception(string.Format("Could not add rect to the newly created atlas. gw={0}, gh={1}", gw, gh)); | |||
} | |||
} | |||
glyph.Bounds.X = gx; | |||
glyph.Bounds.Y = gy; | |||
currentAtlas.RenderGlyph(graphicsDevice, glyph); | |||
glyph.Atlas = currentAtlas; | |||
return glyph; | |||
} | |||
private FontGlyph GetGlyph(GraphicsDevice graphicsDevice, Dictionary<int, FontGlyph> glyphs, int codepoint) | |||
{ | |||
var result = GetGlyphInternal(graphicsDevice, glyphs, codepoint); | |||
if (result == null && DefaultCharacter != null) | |||
{ | |||
result = GetGlyphInternal(graphicsDevice, glyphs, DefaultCharacter.Value); | |||
} | |||
return result; | |||
} | |||
private void GetQuad(FontGlyph glyph, FontGlyph prevGlyph, float spacing, ref float x, ref float y, ref FontGlyphSquad q) | |||
{ | |||
if (prevGlyph != null) | |||
{ | |||
float adv = 0; | |||
if (UseKernings && glyph.Font == prevGlyph.Font) | |||
{ | |||
adv = prevGlyph.GetKerning(glyph) * glyph.Font.Scale; | |||
} | |||
x += (int)(adv + spacing + 0.5f); | |||
} | |||
float rx = x + glyph.XOffset; | |||
float ry = y + glyph.YOffset; | |||
q.X0 = rx; | |||
q.Y0 = ry; | |||
q.X1 = rx + glyph.Bounds.Width; | |||
q.Y1 = ry + glyph.Bounds.Height; | |||
q.S0 = glyph.Bounds.X * _itw; | |||
q.T0 = glyph.Bounds.Y * _ith; | |||
q.S1 = glyph.Bounds.Right * _itw; | |||
q.T1 = glyph.Bounds.Bottom * _ith; | |||
x += (int)(glyph.XAdvance / 10.0f + 0.5f); | |||
} | |||
} | |||
} |