WIP: use kerning for text measuring.
This commit is contained in:
@@ -73,7 +73,7 @@ public class TestGame : Game
|
|||||||
|
|
||||||
if (Input.IsActionPressed("accept"))
|
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)
|
if (Input.IsActionPressed("cancel") && _container.Children.Count != 0)
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ public class Font : Resource, IDisposable
|
|||||||
public byte[]? Buffer { get; private set; }
|
public byte[]? Buffer { get; private set; }
|
||||||
public long BufferSize { get; set; }
|
public long BufferSize { get; set; }
|
||||||
|
|
||||||
|
internal float UnitsPerEm;
|
||||||
|
|
||||||
internal nint FacePtr;
|
internal nint FacePtr;
|
||||||
internal nint LibraryPtr;
|
internal nint LibraryPtr;
|
||||||
|
|
||||||
@@ -78,9 +80,10 @@ public class Font : Resource, IDisposable
|
|||||||
float maxAscent = 0;
|
float maxAscent = 0;
|
||||||
float maxDescent = 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;
|
totalWidth += glyph.Advance;
|
||||||
|
|
||||||
@@ -89,15 +92,43 @@ public class Font : Resource, IDisposable
|
|||||||
|
|
||||||
if (ascent > maxAscent)
|
if (ascent > maxAscent)
|
||||||
maxAscent = ascent;
|
maxAscent = ascent;
|
||||||
|
|
||||||
if (descent > maxDescent)
|
if (descent > maxDescent)
|
||||||
maxDescent = descent;
|
maxDescent = descent;
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
char prevChar = text[i - 1];
|
||||||
|
totalWidth += GetKerning(prevChar, c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float totalHeight = maxAscent + maxDescent;
|
float totalHeight = maxAscent + maxDescent;
|
||||||
return new Rect(totalWidth, totalHeight);
|
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)
|
public Glyph GetGlyph(char character)
|
||||||
{
|
{
|
||||||
if (_glyphs.TryGetValue(character, out var glyph))
|
if (_glyphs.TryGetValue(character, out var glyph))
|
||||||
@@ -128,7 +159,7 @@ public class Font : Resource, IDisposable
|
|||||||
Width = metrics.width >> 6,
|
Width = metrics.width >> 6,
|
||||||
Height = metrics.height >> 6,
|
Height = metrics.height >> 6,
|
||||||
Bearing = new Vector2(metrics.horiBearingX >> 6, metrics.horiBearingY >> 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)
|
if (error != 0)
|
||||||
throw new Exception("Failed to load font face");
|
throw new Exception("Failed to load font face");
|
||||||
|
|
||||||
|
font.UnitsPerEm = face->units_per_EM;
|
||||||
font.FacePtr = (nint)face;
|
font.FacePtr = (nint)face;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user