diff --git a/TestGame/TestGame.cs b/TestGame/TestGame.cs index fbda807..2b24d34 100644 --- a/TestGame/TestGame.cs +++ b/TestGame/TestGame.cs @@ -73,7 +73,7 @@ public class TestGame : Game if (Input.IsActionPressed("accept")) { - _container.AddChild(new Label("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", _font)); + _container.AddChild(new Label("Hello, World!", _font)); } if (Input.IsActionPressed("cancel") && _container.Children.Count != 0) diff --git a/Voile/Source/Resources/Font.cs b/Voile/Source/Resources/Font.cs index bd7253e..f9bece5 100644 --- a/Voile/Source/Resources/Font.cs +++ b/Voile/Source/Resources/Font.cs @@ -31,6 +31,8 @@ public class Font : Resource, IDisposable public byte[]? Buffer { get; private set; } public long BufferSize { get; set; } + internal float UnitsPerEm; + internal nint FacePtr; internal nint LibraryPtr; @@ -78,9 +80,10 @@ public class Font : Resource, IDisposable float maxAscent = 0; float maxDescent = 0; - foreach (char c in text) + for (int i = 0; i < text.Length; i++) { - var glyph = GetGlyph(c); + char c = text[i]; + Glyph glyph = GetGlyph(c); totalWidth += glyph.Advance; @@ -89,15 +92,43 @@ public class Font : Resource, IDisposable if (ascent > maxAscent) maxAscent = ascent; - if (descent > maxDescent) maxDescent = descent; + + if (i > 0) + { + char prevChar = text[i - 1]; + totalWidth += GetKerning(prevChar, c); + } } float totalHeight = maxAscent + maxDescent; return new Rect(totalWidth, totalHeight); } + public int GetKerning(char left, char right) + { + unsafe + { + if (FacePtr == IntPtr.Zero) + return 0; + + FT_FaceRec_* face = (FT_FaceRec_*)FacePtr; + + uint leftIndex = FT_Get_Char_Index(face, left); + uint rightIndex = FT_Get_Char_Index(face, right); + + if (leftIndex == 0 || rightIndex == 0) + return 0; + + FT_Vector_ kerning; + if (FT_Get_Kerning(face, leftIndex, rightIndex, FT_Kerning_Mode_.FT_KERNING_DEFAULT, &kerning) != 0) + return 0; + + return (int)kerning.x; + } + } + public Glyph GetGlyph(char character) { if (_glyphs.TryGetValue(character, out var glyph)) @@ -128,7 +159,7 @@ public class Font : Resource, IDisposable Width = metrics.width >> 6, Height = metrics.height >> 6, Bearing = new Vector2(metrics.horiBearingX >> 6, metrics.horiBearingY >> 6), - Advance = (int)glyph->advance.x >> 6, + Advance = (int)metrics.horiAdvance >> 6, }; } diff --git a/Voile/Source/Resources/Loaders/FontLoader.cs b/Voile/Source/Resources/Loaders/FontLoader.cs index 6e3fb28..af0da0d 100644 --- a/Voile/Source/Resources/Loaders/FontLoader.cs +++ b/Voile/Source/Resources/Loaders/FontLoader.cs @@ -47,6 +47,7 @@ public class FontLoader : ResourceLoader if (error != 0) throw new Exception("Failed to load font face"); + font.UnitsPerEm = face->units_per_EM; font.FacePtr = (nint)face; } }