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:
parent
7bd6adefd8
commit
23feb4cf8f
26
src/ttf.cpp
26
src/ttf.cpp
@ -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",
|
||||
|
@ -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 |
Loading…
Reference in New Issue
Block a user