WIP: use kerning for text measuring.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user