public float LineHeight(float sz) { var r = (int)Math.Round(sz); if (r % 2 != 0) { r--; //Every 2 pixel sizes } GlyphCollection g; if (!glyphs.TryGetValue(r, out g)) { Face.SetCharSize(0, r, 0, 96); g = new GlyphCollection(); g.Font = this; g.Size = r; g.LineHeight = (float)Face.Size.Metrics.Height; g.Ascender = Face.Size.Metrics.Ascender.ToInt32(); glyphs.Add(r, g); } return(g.LineHeight); }
internal unsafe void AddCharacter(GlyphCollection col, uint cp) { if (cp == (uint)'\t') { var spaceGlyph = col.GetGlyph((uint)' '); col.glyphs.Add(cp, new GlyphInfo(spaceGlyph.AdvanceX * 4, spaceGlyph.AdvanceY, spaceGlyph.CharIndex, spaceGlyph.Kerning)); } Face.SetCharSize(0, col.Size, 0, 96); var c_face = Face; bool dobold = emulate_bold; bool doitalics = emulate_italics; bool dokern = true; uint index = c_face.GetCharIndex(cp); if (index == 0) { //Glyph does not exist in font if (cp == (uint)'?') { throw new Exception("Font does not have required ASCII character '?'"); } var fallback = Platform.GetFallbackFace(ren.FT, cp); if ((index = fallback.GetCharIndex(cp)) != 0) { try { c_face = fallback; c_face.SetCharSize(0, col.Size, 0, 96); dobold = doitalics = dokern = false; } catch (Exception) { var qmGlyph = col.GetGlyph((uint)'?'); col.glyphs.Add(cp, qmGlyph); return; } } else { var qmGlyph = col.GetGlyph((uint)'?'); col.glyphs.Add(cp, qmGlyph); return; } } c_face.LoadGlyph(index, LoadFlags.Default | LoadFlags.ForceAutohint, LoadTarget.Normal); if (dobold) { //Automatically determine a strength var strength = (c_face.UnitsPerEM * c_face.Size.Metrics.ScaleY.Value) / 0x10000; strength /= 24; c_face.Glyph.Outline.Embolden(Fixed26Dot6.FromRawValue(strength)); } if (doitalics) { c_face.Glyph.Outline.Transform(new FTMatrix(0x10000, 0x0366A, 0x00000, 0x10000)); } c_face.Glyph.RenderGlyph(RenderMode.Normal); if (c_face.Glyph.Bitmap.Width == 0 || c_face.Glyph.Bitmap.Rows == 0) { col.glyphs.Add(cp, new GlyphInfo( (int)Math.Ceiling((float)c_face.Glyph.Advance.X), (int)Math.Ceiling((float)c_face.Glyph.Advance.Y), index, dokern && Face.HasKerning ) ); } else { if (c_face.Glyph.Bitmap.PixelMode != PixelMode.Gray) { throw new NotImplementedException(); } if (currentX + c_face.Glyph.Bitmap.Width > TEXTURE_SIZE) { currentX = 0; currentY += lineMax; lineMax = 0; } if (currentY + c_face.Glyph.Bitmap.Rows > TEXTURE_SIZE) { currentX = 0; currentY = 0; lineMax = 0; textures.Add(new Texture2D( TEXTURE_SIZE, TEXTURE_SIZE, false, SurfaceFormat.R8 )); FLLog.Debug("Text", string.Format("{0}@{1}, New Texture", facename, col.Size)); } lineMax = (int)Math.Max(lineMax, c_face.Glyph.Bitmap.Rows); var rect = new Rectangle( currentX, currentY, c_face.Glyph.Bitmap.Width, c_face.Glyph.Bitmap.Rows ); var tex = textures [textures.Count - 1]; GL.PixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); //Set tex.SetData(0, rect, c_face.Glyph.Bitmap.Buffer); GL.PixelStorei(GL.GL_UNPACK_ALIGNMENT, 4); currentX += c_face.Glyph.Bitmap.Width; col.glyphs.Add( cp, new GlyphInfo( tex, rect, (int)Math.Ceiling((float)c_face.Glyph.Advance.X), (int)Math.Ceiling((float)c_face.Glyph.Advance.Y), (int)Math.Ceiling((float)c_face.Glyph.Metrics.HorizontalAdvance), c_face.Glyph.BitmapLeft, c_face.Glyph.BitmapTop, index, dokern && Face.HasKerning ) ); } }