TTF: use metrics of 'A' to determine cap height.

SolveSpace 2.0 used the height of 'A' (i.e. cap height) to determine
the reference height.
SolveSpace 2.1 completely broke that during transition to Freetype,
and used something more or less random, by using FT_Set_Char_Size
with units_per_EM.
SolveSpace 2.2 attempted to fix that, but also used something more
or less random, by using FT_Request_Size with "unit" values.

Turns out that Freetype actually doesn't have a concept of cap height
at all. It is possible to extract it from the TT_OS2 table that is
present in some TrueType fonts, but it is not present in Microsoft
fonts (the msttcorefonts ones), and for those Linux fonts in which
it is present it doesn't appear very reliable.

So instead, use the height of 'A' instead, like version 2.0 did.
This has the advantage that it is quite bulletproof, and also matches
exactly what the old files are measured against.

One downside is that fonts without an 'A' glyph would not render.
We can deal with that when it becomes a problem.
This commit is contained in:
whitequark 2016-11-02 08:59:33 +00:00
parent 7bd6adefd8
commit 23feb4cf8f
3 changed files with 25 additions and 2 deletions

View File

@ -168,6 +168,28 @@ bool TtfFont::LoadFromFile(FT_Library fontLibrary, bool nameOnly) {
return false;
}
char chr = 'A';
uint32_t gid = FT_Get_Char_Index(fontFace, 'A');
if (gid == 0) {
dbp("freetype: CID-to-GID mapping for CID 0x%04x failed: %s; using CID as GID",
chr, ft_error_string(gid));
gid = chr;
}
if(gid) {
if(int fterr = FT_Load_Glyph(fontFace, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING)) {
dbp("freetype: cannot load glyph for GID 0x%04x: %s",
gid, ft_error_string(fterr));
FT_Done_Face(fontFace);
fontFace = NULL;
return false;
}
FT_BBox bbox;
FT_Outline_Get_CBox(&fontFace->glyph->outline, &bbox);
capHeight = (double)bbox.yMax;
}
return true;
}
@ -264,7 +286,7 @@ void TtfFont::PlotString(const std::string &str,
* ones, antialiasing mitigates this considerably though.
*/
if(int fterr = FT_Load_Glyph(fontFace, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING)) {
dbp("freetype: cannot load glyph (gid %d): %s",
dbp("freetype: cannot load glyph for GID 0x%04x: %s",
gid, ft_error_string(fterr));
return;
}
@ -294,7 +316,7 @@ void TtfFont::PlotString(const std::string &str,
data.u = u;
data.v = v;
data.beziers = sbl;
data.factor = 1.0f/(float)(1 << 16);
data.factor = 1.0 / capHeight;
data.bx = bx;
if(int fterr = FT_Outline_Decompose(&fontFace->glyph->outline, &outlineFuncs, &data)) {
dbp("freetype: bezier decomposition failed (gid %d): %s",

View File

@ -14,6 +14,7 @@ public:
std::string fontFile;
std::string name;
FT_FaceRec_ *fontFace;
double capHeight;
std::string FontFileBaseName() const;
bool LoadFromFile(FT_LibraryRec_ *fontLibrary, bool nameOnly = true);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB