149 lines
3.2 KiB
C#
149 lines
3.2 KiB
C#
![]() |
|
||
|
using Godot;
|
||
|
using System.Collections.Generic;
|
||
|
|
||
|
namespace Rokojori
|
||
|
{
|
||
|
[Tool]
|
||
|
[GlobalClass]
|
||
|
public partial class FontDefinition: Resource
|
||
|
{
|
||
|
[ExportToolButton( "Clear Cache" )]
|
||
|
public Callable refreshButton => Callable.From(
|
||
|
()=>
|
||
|
{
|
||
|
ClearCache();
|
||
|
}
|
||
|
);
|
||
|
|
||
|
[Export]
|
||
|
public FontGlyph[] glyphs;
|
||
|
|
||
|
[Export]
|
||
|
public float defaultWidth = 0.1f;
|
||
|
|
||
|
[ExportGroup("Height")]
|
||
|
[Export]
|
||
|
public float baseToTop;
|
||
|
|
||
|
[Export]
|
||
|
public float baseToBottom;
|
||
|
|
||
|
[ExportGroup("Kerning")]
|
||
|
[Export]
|
||
|
public float defaultKerning;
|
||
|
|
||
|
[Export]
|
||
|
public FontKerningPair[] kerningPairs;
|
||
|
|
||
|
HashSet<string> _emptyGlyphs = new HashSet<string>();
|
||
|
Dictionary<string,FontGlyph> _glyphMap = new Dictionary<string, FontGlyph>();
|
||
|
Dictionary<string,float> _kerning = new Dictionary<string, float>();
|
||
|
|
||
|
void ClearCache()
|
||
|
{
|
||
|
_emptyGlyphs = new HashSet<string>();
|
||
|
_glyphMap = new Dictionary<string, FontGlyph>();
|
||
|
_kerning = new Dictionary<string, float>();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
public float GetWidth( string characters )
|
||
|
{
|
||
|
var width = 0f;
|
||
|
|
||
|
for ( int i = 0; i < characters.Length; i++ )
|
||
|
{
|
||
|
|
||
|
width += GetCharacterWidth( characters[ i ] + "" );
|
||
|
|
||
|
if ( i == 0 )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
var kerning = GetKerning( characters[ i - 1 ], characters[ i ] );
|
||
|
|
||
|
width += kerning;
|
||
|
}
|
||
|
|
||
|
return width;
|
||
|
}
|
||
|
|
||
|
public List<float> GetOffsets( string characters )
|
||
|
{
|
||
|
var positions = new List<float>();
|
||
|
var position = 0f;
|
||
|
|
||
|
for ( int i = 0; i < characters.Length; i++ )
|
||
|
{
|
||
|
if ( i != 0 )
|
||
|
{
|
||
|
position += GetKerning( characters[ i - 1 ], characters[ i ] );
|
||
|
}
|
||
|
|
||
|
positions.Add( position );
|
||
|
|
||
|
position += GetCharacterWidth( characters[ i ] + "" );
|
||
|
}
|
||
|
|
||
|
return positions;
|
||
|
}
|
||
|
|
||
|
public float GetKerning( string characterBefore, string characterAfter )
|
||
|
{
|
||
|
var gBefore = GetFontGlyph( characterBefore );
|
||
|
var gAfter = GetFontGlyph( characterAfter );
|
||
|
|
||
|
return GetKerning( gBefore == null ? -1 : gBefore.kerningGroup, gAfter == null ? -1 : gAfter.kerningGroup );
|
||
|
}
|
||
|
|
||
|
public float GetKerning( int before, int after )
|
||
|
{
|
||
|
var kernID = before + "|" + after;
|
||
|
|
||
|
if ( _kerning.ContainsKey( kernID ) )
|
||
|
{
|
||
|
return _kerning[ kernID ];
|
||
|
}
|
||
|
|
||
|
var kp = kerningPairs.Find( kp => kp.kerningGroupBefore == before && kp.kerningGroupAfter == after );
|
||
|
_kerning[ kernID ] = kp == null ? defaultKerning : kp.kerningWidth;
|
||
|
|
||
|
return _kerning[ kernID ];
|
||
|
}
|
||
|
|
||
|
public FontGlyph GetFontGlyph( string character )
|
||
|
{
|
||
|
if ( _glyphMap.ContainsKey( character ) )
|
||
|
{
|
||
|
return _glyphMap[ character ];
|
||
|
}
|
||
|
|
||
|
if ( _emptyGlyphs.Contains( character ) )
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
var glyph = glyphs.Find( g => g.characters == character );
|
||
|
|
||
|
if ( glyph == null )
|
||
|
{
|
||
|
_emptyGlyphs.Add( character );
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
_glyphMap[ character ] = glyph;
|
||
|
|
||
|
return glyph;
|
||
|
}
|
||
|
|
||
|
public float GetCharacterWidth( string character )
|
||
|
{
|
||
|
var g = GetFontGlyph( character );
|
||
|
|
||
|
return g == null ? defaultWidth : g.width;
|
||
|
}
|
||
|
}
|
||
|
}
|