WIP: use kerning for text measuring.

This commit is contained in:
2025-06-29 15:53:29 +02:00
parent 0ec4e45c38
commit 9bc9810c8f
3 changed files with 37 additions and 5 deletions

View File

@@ -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)

View File

@@ -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,
};
}

View File

@@ -47,6 +47,7 @@ public class FontLoader : ResourceLoader<Font>
if (error != 0)
throw new Exception("Failed to load font face");
font.UnitsPerEm = face->units_per_EM;
font.FacePtr = (nint)face;
}
}