Don't show unusable fonts in font selector.
Before this commit, certain fonts (e.g. Terminus) would appear in the selector but cause a crash (assertion failure) if they are used. After this commit, we make sure all preconditions are met before showing a font there. Also, improve error reporting to always print font filename.pull/507/head
parent
e74137dc67
commit
14e095c93a
64
src/ttf.cpp
64
src/ttf.cpp
|
@ -97,9 +97,9 @@ TtfFont *TtfFontList::LoadFont(const std::string &font)
|
|||
if(tf != l.end()) {
|
||||
if(tf->fontFace == NULL) {
|
||||
if(tf->IsResource())
|
||||
tf->LoadFromResource(fontLibrary, /*nameOnly=*/false);
|
||||
tf->LoadFromResource(fontLibrary, /*keepOpen=*/true);
|
||||
else
|
||||
tf->LoadFromFile(fontLibrary, /*nameOnly=*/false);
|
||||
tf->LoadFromFile(fontLibrary, /*keepOpen=*/true);
|
||||
}
|
||||
return tf;
|
||||
} else {
|
||||
|
@ -155,7 +155,7 @@ bool TtfFont::IsResource() const {
|
|||
//-----------------------------------------------------------------------------
|
||||
// Load a TrueType font into memory.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool TtfFont::LoadFromFile(FT_Library fontLibrary, bool nameOnly) {
|
||||
bool TtfFont::LoadFromFile(FT_Library fontLibrary, bool keepOpen) {
|
||||
ssassert(!IsResource(), "Cannot load a font provided by a resource as a file.");
|
||||
|
||||
FT_Open_Args args = {};
|
||||
|
@ -171,14 +171,14 @@ bool TtfFont::LoadFromFile(FT_Library fontLibrary, bool nameOnly) {
|
|||
return false;
|
||||
}
|
||||
|
||||
return ExtractTTFData(nameOnly);
|
||||
return ExtractTTFData(keepOpen);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Load a TrueType from resource in memory. Implemented to load bundled fonts
|
||||
// through theresource system.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool TtfFont::LoadFromResource(FT_Library fontLibrary, bool nameOnly) {
|
||||
bool TtfFont::LoadFromResource(FT_Library fontLibrary, bool keepOpen) {
|
||||
ssassert(IsResource(), "Font to be loaded as resource is not provided by a resource "
|
||||
"or does not have the 'res://' prefix.");
|
||||
|
||||
|
@ -196,13 +196,13 @@ bool TtfFont::LoadFromResource(FT_Library fontLibrary, bool nameOnly) {
|
|||
return false;
|
||||
}
|
||||
|
||||
return ExtractTTFData(nameOnly);
|
||||
return ExtractTTFData(keepOpen);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Extract font information. We care about the font name and unit size.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool TtfFont::ExtractTTFData(bool nameOnly) {
|
||||
bool TtfFont::ExtractTTFData(bool keepOpen) {
|
||||
if(int fterr = FT_Select_Charmap(fontFace, FT_ENCODING_UNICODE)) {
|
||||
dbp("freetype: loading unicode CMap for file '%s' failed: %s",
|
||||
fontFile.raw.c_str(), ft_error_string(fterr));
|
||||
|
@ -214,12 +214,6 @@ bool TtfFont::ExtractTTFData(bool nameOnly) {
|
|||
name = std::string(fontFace->family_name) +
|
||||
" (" + std::string(fontFace->style_name) + ")";
|
||||
|
||||
if(nameOnly) {
|
||||
FT_Done_Face(fontFace);
|
||||
fontFace = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
// We always ask Freetype to give us a unit size character.
|
||||
// It uses fixed point; put the unit size somewhere in the middle of the dynamic
|
||||
// range of its 26.6 fixed point type, and adjust the factors so that the unit
|
||||
|
@ -231,8 +225,8 @@ bool TtfFont::ExtractTTFData(bool nameOnly) {
|
|||
sizeRequest.horiResolution = 128;
|
||||
sizeRequest.vertResolution = 128;
|
||||
if(int fterr = FT_Request_Size(fontFace, &sizeRequest)) {
|
||||
dbp("freetype: cannot set character size: %s",
|
||||
ft_error_string(fterr));
|
||||
dbp("freetype: size request for file '%s' failed: %s",
|
||||
fontFile.raw.c_str(), ft_error_string(fterr));
|
||||
FT_Done_Face(fontFace);
|
||||
fontFace = NULL;
|
||||
return false;
|
||||
|
@ -241,16 +235,17 @@ bool TtfFont::ExtractTTFData(bool nameOnly) {
|
|||
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));
|
||||
dbp("freetype: CID-to-GID mapping for CID 0x%04x in file '%s' failed: %s; "
|
||||
"using CID as GID",
|
||||
chr, fontFile.raw.c_str(), ft_error_string(gid));
|
||||
dbp("Assuming cap height is the same as requested height (this is likely wrong).");
|
||||
capHeight = (double)sizeRequest.height;
|
||||
}
|
||||
|
||||
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));
|
||||
dbp("freetype: cannot load glyph for GID 0x%04x in file '%s': %s",
|
||||
gid, fontFile.raw.c_str(), ft_error_string(fterr));
|
||||
FT_Done_Face(fontFace);
|
||||
fontFace = NULL;
|
||||
return false;
|
||||
|
@ -261,6 +256,15 @@ bool TtfFont::ExtractTTFData(bool nameOnly) {
|
|||
capHeight = (double)bbox.yMax;
|
||||
}
|
||||
|
||||
// If we just wanted to get the font's name and figure out if it's actually usable, close
|
||||
// it now. If we don't do this, and there are a lot of fonts, we can bump into the file
|
||||
// descriptor limit (especially on Windows), breaking all file operations.
|
||||
if(!keepOpen) {
|
||||
FT_Done_Face(fontFace);
|
||||
fontFace = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -343,8 +347,9 @@ void TtfFont::PlotString(const std::string &str,
|
|||
for(char32_t cid : ReadUTF8(str)) {
|
||||
uint32_t gid = FT_Get_Char_Index(fontFace, cid);
|
||||
if (gid == 0) {
|
||||
dbp("freetype: CID-to-GID mapping for CID 0x%04x failed: %s; using CID as GID",
|
||||
cid, ft_error_string(gid));
|
||||
dbp("freetype: CID-to-GID mapping for CID 0x%04x in file '%s' failed: %s; "
|
||||
"using CID as GID",
|
||||
cid, fontFile.raw.c_str(), ft_error_string(gid));
|
||||
gid = cid;
|
||||
}
|
||||
|
||||
|
@ -357,8 +362,8 @@ 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 for GID 0x%04x: %s",
|
||||
gid, ft_error_string(fterr));
|
||||
dbp("freetype: cannot load glyph for GID 0x%04x in file '%s': %s",
|
||||
gid, fontFile.raw.c_str(), ft_error_string(fterr));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -390,8 +395,8 @@ void TtfFont::PlotString(const std::string &str,
|
|||
data.factor = (float)(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",
|
||||
gid, ft_error_string(fterr));
|
||||
dbp("freetype: bezier decomposition failed for GID 0x%4x in file '%s': %s",
|
||||
gid, fontFile.raw.c_str(), ft_error_string(fterr));
|
||||
}
|
||||
|
||||
// And we're done, so advance our position by the requested advance
|
||||
|
@ -408,13 +413,14 @@ double TtfFont::AspectRatio(const std::string &str) {
|
|||
for(char32_t chr : ReadUTF8(str)) {
|
||||
uint32_t gid = FT_Get_Char_Index(fontFace, chr);
|
||||
if (gid == 0) {
|
||||
dbp("freetype: CID-to-GID mapping for CID 0x%04x failed: %s; using CID as GID",
|
||||
chr, ft_error_string(gid));
|
||||
dbp("freetype: CID-to-GID mapping for CID 0x%04x in file '%s' failed: %s; "
|
||||
"using CID as GID",
|
||||
chr, fontFile.raw.c_str(), ft_error_string(gid));
|
||||
}
|
||||
|
||||
if(int fterr = FT_Load_Glyph(fontFace, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING)) {
|
||||
dbp("freetype: cannot load glyph (GID 0x%04x): %s",
|
||||
gid, ft_error_string(fterr));
|
||||
dbp("freetype: cannot load glyph for GID 0x%04x in file '%s': %s",
|
||||
gid, fontFile.raw.c_str(), ft_error_string(fterr));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,14 +20,14 @@ public:
|
|||
bool IsResource() const;
|
||||
|
||||
std::string FontFileBaseName() const;
|
||||
bool LoadFromFile(FT_LibraryRec_ *fontLibrary, bool nameOnly = true);
|
||||
bool LoadFromResource(FT_LibraryRec_ *fontLibrary, bool nameOnly = true);
|
||||
bool LoadFromFile(FT_LibraryRec_ *fontLibrary, bool keepOpen = false);
|
||||
bool LoadFromResource(FT_LibraryRec_ *fontLibrary, bool keepOpen = false);
|
||||
|
||||
void PlotString(const std::string &str,
|
||||
SBezierList *sbl, Vector origin, Vector u, Vector v);
|
||||
double AspectRatio(const std::string &str);
|
||||
|
||||
bool ExtractTTFData(bool nameOnly);
|
||||
bool ExtractTTFData(bool keepOpen);
|
||||
};
|
||||
|
||||
class TtfFontList {
|
||||
|
|
Loading…
Reference in New Issue