public BitmapFontData(string fontFile, bool flip) : this() { FontFile = fontFile; IsFlipped = flip; using (TextReader reader = new StreamReader(FontFile)) { reader.ReadLine(); // Info string line = reader.ReadLine(); if (line == null) { throw new IOException("Invalid font file: " + fontFile); } string[] common = line.Split(SpaceToken, 4); if (common.Length < 4) { throw new IOException("Invalid font file: " + fontFile); } if (!common[1].StartsWith("lineHeight=")) { throw new IOException("Invalid font file: " + fontFile); } LineHeight = int.Parse(common[1].Substring(11)); if (!common[2].StartsWith("base=")) { throw new IOException("Invalid font file: " + fontFile); } int baseLine = int.Parse(common[2].Substring(5)); line = reader.ReadLine(); if (line == null) { throw new IOException("Invalid font file: " + fontFile); } string[] pageLine = line.Split(SpaceToken, 4); if (pageLine.Length < 3) { throw new IOException("Invalid font file: " + fontFile); } if (!pageLine[2].StartsWith("file=")) { throw new IOException("Invalid font file: " + fontFile); } string imageFilename = null; if (pageLine[2].EndsWith("\"")) { imageFilename = pageLine[2].Substring(6, pageLine[2].Length - 6 - 1); } else { imageFilename = pageLine[2].Substring(5, pageLine[2].Length - 5); } ImagePath = Path.Combine(Path.GetDirectoryName(fontFile), imageFilename); Descent = 0; while (true) { line = reader.ReadLine(); if (line == null) { break; } if (line.StartsWith("kernings ")) { break; } if (!line.StartsWith("char ")) { continue; } Glyph glyph = new Glyph(); string[] tokens = line.Split(SpaceEqToken, StringSplitOptions.RemoveEmptyEntries); int ch = int.Parse(tokens[2]); if (ch <= char.MaxValue) { this[(char)ch] = glyph; } else { continue; } glyph.SrcX = int.Parse(tokens[4]); glyph.SrcY = int.Parse(tokens[6]); glyph.Width = int.Parse(tokens[8]); glyph.Height = int.Parse(tokens[10]); glyph.XOffset = int.Parse(tokens[12]); glyph.YOffset = flip ? int.Parse(tokens[14]) : -(glyph.Height + int.Parse(tokens[14])); glyph.XAdvance = int.Parse(tokens[16]); if (glyph.Width > 0 && glyph.Height > 0) { Descent = Math.Min(baseLine + glyph.YOffset, Descent); } } while (true) { line = reader.ReadLine(); if (line == null) { break; } if (!line.StartsWith("kerning ")) { break; } string[] tokens = line.Split(SpaceEqToken, StringSplitOptions.RemoveEmptyEntries); int first = int.Parse(tokens[2]); int second = int.Parse(tokens[4]); if (first < 0 || first > char.MaxValue || second < 0 || second > char.MaxValue) { continue; } Glyph g = this[(char)first]; int amount = int.Parse(tokens[6]); g.SetKerning((char)second, amount); } Glyph spaceGlyph = this[' ']; if (spaceGlyph == null) { Glyph xAdvanceGlyph = this['l']; if (xAdvanceGlyph == null) { xAdvanceGlyph = FirstGlyph; } this[' '] = spaceGlyph = new Glyph() { XAdvance = xAdvanceGlyph.XAdvance, }; } SpaceWidth = (spaceGlyph != null) ? spaceGlyph.XAdvance + spaceGlyph.Width : 1; Glyph xGlyph = null; for (int i = 0; i < BitmapFont.XChars.Length; i++) { xGlyph = this[BitmapFont.XChars[i]]; if (xGlyph != null) { break; } } if (xGlyph == null) { xGlyph = FirstGlyph; } XHeight = xGlyph.Height; Glyph capGlyph = null; for (int i = 0; i < BitmapFont.CapChars.Length; i++) { capGlyph = this[BitmapFont.CapChars[i]]; if (capGlyph != null) { break; } } if (capGlyph == null) { foreach (Glyph[] page in Glyphs) { if (page == null) { continue; } foreach (Glyph glyph in page) { if (glyph == null || glyph.Height == 0 || glyph.Width == 0) { continue; } CapHeight = Math.Min(CapHeight, glyph.Height); } } } else { CapHeight = capGlyph.Height; } Ascent = baseLine - CapHeight; Down = -LineHeight; if (flip) { Ascent = -Ascent; Down = -Down; } } }
public void ComputeGlyphAdvancesAndPositions(CharSequence str, IList <float> glyphAdvances, IList <float> glyphPositions) { glyphAdvances.Clear(); glyphPositions.Clear(); int index = 0; int end = str.Length; float width = 0; Glyph lastGlyph = null; BitmapFontData data = Data; if (data.ScaleX == 1) { for (; index < end; index++) { char ch = str[index]; Glyph g = data[ch]; if (g != null) { if (lastGlyph != null) { width += lastGlyph.GetKerning(ch); } lastGlyph = g; glyphAdvances.Add(g.XAdvance); glyphPositions.Add(width); width += g.XAdvance; } } glyphAdvances.Add(0); glyphPositions.Add(width); } else { float scaleX = data.ScaleX; for (; index < end; index++) { char ch = str[index]; Glyph g = data[ch]; if (g != null) { if (lastGlyph != null) { width += lastGlyph.GetKerning(ch) * scaleX; } lastGlyph = g; float xAdvance = g.XAdvance * scaleX; glyphAdvances.Add(xAdvance); glyphPositions.Add(width); width += xAdvance; } } glyphAdvances.Add(0); glyphPositions.Add(width); } }