Font: fall back to using freetype's 2.9.1 algorithm for calculating font metrics like ascent/descent
This allows us to upgrade freetype beyond 2.9.1 (actually, 2.8.1 due to a bug in freetype 2.9) without wildly different font metrics. The reason that we don't want to change font metrics algorithms is that freetype's new algorithm is very different than the algorithm used for SWF fonts. The older freetype algorithm is closer to SWF, so we want to stick with it. Thankfully, freetype supports accessing various metrics stored in font files in a more raw form, so we can provide our own custom algorithm in a way that is fully supported by freetype. I just copied the existing algorithm straight from 2.9.1 to restore our preferred behavior. I confirmed that, after this change, OpenFL renders metrics like Lime 8.1.3. But we have the same upgraded freetype as Lime 8.2.0 that we had to revert for 8.2.1. I plan to experiment with a mode that matches SWF even more closely, now that I have a better understanding of how fonts and freetype work.
This commit is contained in:
@@ -110,6 +110,12 @@
|
|||||||
<compilerflag value="-I${NATIVE_TOOLKIT_PATH}/freetype/include" />
|
<compilerflag value="-I${NATIVE_TOOLKIT_PATH}/freetype/include" />
|
||||||
<compilerflag value="-DLIME_FREETYPE" />
|
<compilerflag value="-DLIME_FREETYPE" />
|
||||||
|
|
||||||
|
<!--
|
||||||
|
prefer FreeType's font metrics algorithm from 2.9.1
|
||||||
|
it behaves more like SWF than the new algorithm
|
||||||
|
-->
|
||||||
|
<compilerflag value="-DLIME_FREETYPE_LEGACY_METRICS" />
|
||||||
|
|
||||||
<file name="src/text/Font.cpp" />
|
<file name="src/text/Font.cpp" />
|
||||||
|
|
||||||
<section if="LIME_HARFBUZZ">
|
<section if="LIME_HARFBUZZ">
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include FT_BITMAP_H
|
#include FT_BITMAP_H
|
||||||
#include FT_SFNT_NAMES_H
|
#include FT_SFNT_NAMES_H
|
||||||
#include FT_TRUETYPE_IDS_H
|
#include FT_TRUETYPE_IDS_H
|
||||||
|
#include FT_TRUETYPE_TABLES_H
|
||||||
#include FT_GLYPH_H
|
#include FT_GLYPH_H
|
||||||
#include FT_OUTLINE_H
|
#include FT_OUTLINE_H
|
||||||
#endif
|
#endif
|
||||||
@@ -536,6 +537,57 @@ namespace lime {
|
|||||||
|
|
||||||
wchar_t* family_name = GetFamilyName ();
|
wchar_t* family_name = GetFamilyName ();
|
||||||
|
|
||||||
|
#ifdef LIME_FREETYPE_LEGACY_METRICS
|
||||||
|
|
||||||
|
// this is FreeType's font metrics algorithm from 2.9.1
|
||||||
|
// it behaves more like SWF than the new algorithm
|
||||||
|
|
||||||
|
TT_OS2* os2 = (TT_OS2*)FT_Get_Sfnt_Table(((FT_Face)face), ft_sfnt_os2);
|
||||||
|
TT_HoriHeader* hhea = (TT_HoriHeader*)FT_Get_Sfnt_Table(((FT_Face)face), ft_sfnt_hhea);
|
||||||
|
|
||||||
|
int calculatedAscender = hhea->Ascender;
|
||||||
|
int calculatedDescender = hhea->Descender;
|
||||||
|
int calculatedHeight = calculatedAscender - calculatedDescender + hhea->Line_Gap;
|
||||||
|
|
||||||
|
if (!( calculatedAscender || calculatedDescender ))
|
||||||
|
{
|
||||||
|
if (os2->version != 0xFFFFU)
|
||||||
|
{
|
||||||
|
if (os2->sTypoAscender || os2->sTypoDescender)
|
||||||
|
{
|
||||||
|
|
||||||
|
calculatedAscender = os2->sTypoAscender;
|
||||||
|
calculatedDescender = os2->sTypoDescender;
|
||||||
|
calculatedHeight = calculatedAscender - calculatedDescender + os2->sTypoLineGap;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
calculatedAscender = (FT_Short)os2->usWinAscent;
|
||||||
|
calculatedDescender = -(FT_Short)os2->usWinDescent;
|
||||||
|
calculatedHeight = calculatedAscender - calculatedDescender;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!calculatedAscender || !calculatedDescender) {
|
||||||
|
|
||||||
|
calculatedAscender = ((FT_Face)face)->ascender;
|
||||||
|
calculatedDescender = ((FT_Face)face)->descender;
|
||||||
|
calculatedHeight = ((FT_Face)face)->height;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int calculatedAscender = ((FT_Face)face)->ascender;
|
||||||
|
int calculatedDescender = ((FT_Face)face)->descender;
|
||||||
|
int calculatedHeight = ((FT_Face)face)->height;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
if (useCFFIValue) {
|
if (useCFFIValue) {
|
||||||
|
|
||||||
value ret = alloc_empty_object ();
|
value ret = alloc_empty_object ();
|
||||||
@@ -548,9 +600,9 @@ namespace lime {
|
|||||||
alloc_field (ret, val_id ("family_name"), family_name == NULL ? alloc_string (((FT_Face)face)->family_name) : alloc_wstring (family_name));
|
alloc_field (ret, val_id ("family_name"), family_name == NULL ? alloc_string (((FT_Face)face)->family_name) : alloc_wstring (family_name));
|
||||||
alloc_field (ret, val_id ("style_name"), alloc_string (((FT_Face)face)->style_name));
|
alloc_field (ret, val_id ("style_name"), alloc_string (((FT_Face)face)->style_name));
|
||||||
alloc_field (ret, val_id ("em_size"), alloc_int (((FT_Face)face)->units_per_EM));
|
alloc_field (ret, val_id ("em_size"), alloc_int (((FT_Face)face)->units_per_EM));
|
||||||
alloc_field (ret, val_id ("ascend"), alloc_int (((FT_Face)face)->ascender));
|
alloc_field (ret, val_id ("ascend"), alloc_int (calculatedAscender));
|
||||||
alloc_field (ret, val_id ("descend"), alloc_int (((FT_Face)face)->descender));
|
alloc_field (ret, val_id ("descend"), alloc_int (calculatedDescender));
|
||||||
alloc_field (ret, val_id ("height"), alloc_int (((FT_Face)face)->height));
|
alloc_field (ret, val_id ("height"), alloc_int (calculatedHeight));
|
||||||
|
|
||||||
delete family_name;
|
delete family_name;
|
||||||
|
|
||||||
@@ -647,9 +699,9 @@ namespace lime {
|
|||||||
hl_dyn_setp (ret, hl_hash_utf8 ("family_name"), &hlt_bytes, _family_name);
|
hl_dyn_setp (ret, hl_hash_utf8 ("family_name"), &hlt_bytes, _family_name);
|
||||||
hl_dyn_setp (ret, hl_hash_utf8 ("style_name"), &hlt_bytes, style_name);
|
hl_dyn_setp (ret, hl_hash_utf8 ("style_name"), &hlt_bytes, style_name);
|
||||||
hl_dyn_seti (ret, hl_hash_utf8 ("em_size"), &hlt_i32, ((FT_Face)face)->units_per_EM);
|
hl_dyn_seti (ret, hl_hash_utf8 ("em_size"), &hlt_i32, ((FT_Face)face)->units_per_EM);
|
||||||
hl_dyn_seti (ret, hl_hash_utf8 ("ascend"), &hlt_i32, ((FT_Face)face)->ascender);
|
hl_dyn_seti (ret, hl_hash_utf8 ("ascend"), &hlt_i32, calculatedAscender);
|
||||||
hl_dyn_seti (ret, hl_hash_utf8 ("descend"), &hlt_i32, ((FT_Face)face)->descender);
|
hl_dyn_seti (ret, hl_hash_utf8 ("descend"), &hlt_i32, calculatedDescender);
|
||||||
hl_dyn_seti (ret, hl_hash_utf8 ("height"), &hlt_i32, ((FT_Face)face)->height);
|
hl_dyn_seti (ret, hl_hash_utf8 ("height"), &hlt_i32, calculatedHeight);
|
||||||
|
|
||||||
// 'glyphs' field
|
// 'glyphs' field
|
||||||
hl_varray* _glyphs = (hl_varray*)hl_alloc_array (&hlt_dynobj, num_glyphs);
|
hl_varray* _glyphs = (hl_varray*)hl_alloc_array (&hlt_dynobj, num_glyphs);
|
||||||
@@ -721,15 +773,113 @@ namespace lime {
|
|||||||
|
|
||||||
int Font::GetAscender () {
|
int Font::GetAscender () {
|
||||||
|
|
||||||
|
#ifdef LIME_FREETYPE_LEGACY_METRICS
|
||||||
|
|
||||||
|
// this is FreeType's font metrics algorithm from 2.9.1
|
||||||
|
// it behaves more like SWF than the new algorithm
|
||||||
|
|
||||||
|
TT_OS2* os2 = (TT_OS2*)FT_Get_Sfnt_Table(((FT_Face)face), ft_sfnt_os2);
|
||||||
|
TT_HoriHeader* hhea = (TT_HoriHeader*)FT_Get_Sfnt_Table(((FT_Face)face), ft_sfnt_hhea);
|
||||||
|
|
||||||
|
int calculatedAscender = hhea->Ascender;
|
||||||
|
int calculatedDescender = hhea->Descender;
|
||||||
|
int calculatedHeight = calculatedAscender - calculatedDescender + hhea->Line_Gap;
|
||||||
|
|
||||||
|
if (!( calculatedAscender || calculatedDescender ))
|
||||||
|
{
|
||||||
|
if (os2->version != 0xFFFFU)
|
||||||
|
{
|
||||||
|
if (os2->sTypoAscender || os2->sTypoDescender)
|
||||||
|
{
|
||||||
|
|
||||||
|
calculatedAscender = os2->sTypoAscender;
|
||||||
|
calculatedDescender = os2->sTypoDescender;
|
||||||
|
calculatedHeight = calculatedAscender - calculatedDescender + os2->sTypoLineGap;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
calculatedAscender = (FT_Short)os2->usWinAscent;
|
||||||
|
calculatedDescender = -(FT_Short)os2->usWinDescent;
|
||||||
|
calculatedHeight = calculatedAscender - calculatedDescender;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!calculatedAscender || !calculatedDescender) {
|
||||||
|
|
||||||
|
calculatedAscender = ((FT_Face)face)->ascender;
|
||||||
|
calculatedDescender = ((FT_Face)face)->descender;
|
||||||
|
calculatedHeight = ((FT_Face)face)->height;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return calculatedAscender;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
return ((FT_Face)face)->ascender;
|
return ((FT_Face)face)->ascender;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Font::GetDescender () {
|
int Font::GetDescender () {
|
||||||
|
|
||||||
|
#ifdef LIME_FREETYPE_LEGACY_METRICS
|
||||||
|
|
||||||
|
// this is FreeType's font metrics algorithm from 2.9.1
|
||||||
|
// it behaves more like SWF than the new algorithm
|
||||||
|
|
||||||
|
TT_OS2* os2 = (TT_OS2*)FT_Get_Sfnt_Table(((FT_Face)face), ft_sfnt_os2);
|
||||||
|
TT_HoriHeader* hhea = (TT_HoriHeader*)FT_Get_Sfnt_Table(((FT_Face)face), ft_sfnt_hhea);
|
||||||
|
|
||||||
|
int calculatedAscender = hhea->Ascender;
|
||||||
|
int calculatedDescender = hhea->Descender;
|
||||||
|
int calculatedHeight = calculatedAscender - calculatedDescender + hhea->Line_Gap;
|
||||||
|
|
||||||
|
if (!( calculatedAscender || calculatedDescender ))
|
||||||
|
{
|
||||||
|
if (os2->version != 0xFFFFU)
|
||||||
|
{
|
||||||
|
if (os2->sTypoAscender || os2->sTypoDescender)
|
||||||
|
{
|
||||||
|
|
||||||
|
calculatedAscender = os2->sTypoAscender;
|
||||||
|
calculatedDescender = os2->sTypoDescender;
|
||||||
|
calculatedHeight = calculatedAscender - calculatedDescender + os2->sTypoLineGap;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
calculatedAscender = (FT_Short)os2->usWinAscent;
|
||||||
|
calculatedDescender = -(FT_Short)os2->usWinDescent;
|
||||||
|
calculatedHeight = calculatedAscender - calculatedDescender;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!calculatedAscender || !calculatedDescender) {
|
||||||
|
|
||||||
|
calculatedAscender = ((FT_Face)face)->ascender;
|
||||||
|
calculatedDescender = ((FT_Face)face)->descender;
|
||||||
|
calculatedHeight = ((FT_Face)face)->height;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return calculatedDescender;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
return ((FT_Face)face)->descender;
|
return ((FT_Face)face)->descender;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -911,8 +1061,56 @@ namespace lime {
|
|||||||
|
|
||||||
int Font::GetHeight () {
|
int Font::GetHeight () {
|
||||||
|
|
||||||
|
#ifdef LIME_FREETYPE_LEGACY_METRICS
|
||||||
|
|
||||||
|
// this is FreeType's font metrics algorithm from 2.9.1
|
||||||
|
// it behaves more like SWF than the new algorithm
|
||||||
|
|
||||||
|
TT_OS2* os2 = (TT_OS2*)FT_Get_Sfnt_Table(((FT_Face)face), ft_sfnt_os2);
|
||||||
|
TT_HoriHeader* hhea = (TT_HoriHeader*)FT_Get_Sfnt_Table(((FT_Face)face), ft_sfnt_hhea);
|
||||||
|
|
||||||
|
int calculatedAscender = hhea->Ascender;
|
||||||
|
int calculatedDescender = hhea->Descender;
|
||||||
|
int calculatedHeight = calculatedAscender - calculatedDescender + hhea->Line_Gap;
|
||||||
|
|
||||||
|
if (!( calculatedAscender || calculatedDescender ))
|
||||||
|
{
|
||||||
|
if (os2->version != 0xFFFFU)
|
||||||
|
{
|
||||||
|
if (os2->sTypoAscender || os2->sTypoDescender)
|
||||||
|
{
|
||||||
|
|
||||||
|
calculatedAscender = os2->sTypoAscender;
|
||||||
|
calculatedDescender = os2->sTypoDescender;
|
||||||
|
calculatedHeight = calculatedAscender - calculatedDescender +
|
||||||
|
os2->sTypoLineGap;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
calculatedAscender = (FT_Short)os2->usWinAscent;
|
||||||
|
calculatedDescender = -(FT_Short)os2->usWinDescent;
|
||||||
|
calculatedHeight = calculatedAscender - calculatedDescender;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!calculatedHeight) {
|
||||||
|
|
||||||
|
calculatedHeight = ((FT_Face)face)->height;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return calculatedHeight;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
return ((FT_Face)face)->height;
|
return ((FT_Face)face)->height;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -989,7 +1187,7 @@ namespace lime {
|
|||||||
unsigned char g = bitmap.buffer[i * pitch + j * 3 + 1];
|
unsigned char g = bitmap.buffer[i * pitch + j * 3 + 1];
|
||||||
unsigned char b = bitmap.buffer[i * pitch + j * 3 + 2];
|
unsigned char b = bitmap.buffer[i * pitch + j * 3 + 2];
|
||||||
unsigned char a = (r + g + b) / 3;
|
unsigned char a = (r + g + b) / 3;
|
||||||
|
|
||||||
//Red
|
//Red
|
||||||
position[(i * width + j) * 4 + 0] = r;
|
position[(i * width + j) * 4 + 0] = r;
|
||||||
//Green
|
//Green
|
||||||
@@ -1039,10 +1237,10 @@ namespace lime {
|
|||||||
return totalOffset;
|
return totalOffset;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::SetSize(size_t size, size_t dpi)
|
void Font::SetSize(size_t size, size_t dpi)
|
||||||
{
|
{
|
||||||
//We changed the function signature to include a dpi argument which changes this from
|
//We changed the function signature to include a dpi argument which changes this from
|
||||||
//the default value of 72 for dpi. Any public api that uses this should probably be changed
|
//the default value of 72 for dpi. Any public api that uses this should probably be changed
|
||||||
//to allow setting the dpi in an appropriate future release.
|
//to allow setting the dpi in an appropriate future release.
|
||||||
size_t hdpi = dpi;
|
size_t hdpi = dpi;
|
||||||
|
|||||||
Reference in New Issue
Block a user