Implement couriersud's proposal to put style name in the config name for SDL fonts

Enumerate available font styles as well as families
Still has a problem in that TTC fonts are enumerated but can't be loaded by SDL_ttf
This commit is contained in:
Vas Crabb 2016-03-17 13:28:30 +11:00
parent f0e580e40a
commit f99198c5c2

View File

@ -57,7 +57,7 @@ private:
static constexpr double POINT_SIZE = 144.0; static constexpr double POINT_SIZE = 144.0;
#if !defined(SDLMAME_HAIKU) && !defined(SDLMAME_EMSCRIPTEN) #if !defined(SDLMAME_HAIKU) && !defined(SDLMAME_EMSCRIPTEN)
TTF_Font_ptr search_font_config(std::string const &name, bool bold, bool italic, bool underline, bool &bakedstyles); TTF_Font_ptr search_font_config(std::string const &family, std::string const &style, bool &bakedstyles);
#endif #endif
bool BDF_Check_Magic(std::string const &name); bool BDF_Check_Magic(std::string const &name);
TTF_Font_ptr TTF_OpenFont_Magic(std::string const &name, int fsize); TTF_Font_ptr TTF_OpenFont_Magic(std::string const &name, int fsize);
@ -69,29 +69,29 @@ bool osd_font_sdl::open(std::string const &font_path, std::string const &_name,
{ {
bool bakedstyles = false; bool bakedstyles = false;
// accept qualifiers from the name
std::string name(_name); std::string name(_name);
if (name.compare("default") == 0) if (name.compare("default") == 0)
{ {
name = "Liberation Sans"; name = "Liberation Sans|Regular";
} }
bool const bold = (strreplace(name, "[B]", "") + strreplace(name, "[b]", "") > 0); // accept qualifiers from the name
bool const italic = (strreplace(name, "[I]", "") + strreplace(name, "[i]", "") > 0);
bool const underline = (strreplace(name, "[U]", "") + strreplace(name, "[u]", "") > 0); bool const underline = (strreplace(name, "[U]", "") + strreplace(name, "[u]", "") > 0);
bool const strike = (strreplace(name, "[S]", "") + strreplace(name, "[s]", "") > 0); bool const strike = (strreplace(name, "[S]", "") + strreplace(name, "[s]", "") > 0);
std::string::size_type const separator = name.rfind('|');
std::string const family(name.substr(0, separator));
std::string const style((std::string::npos != separator) ? name.substr(separator + 1) : std::string());
// first up, try it as a filename // first up, try it as a filename
TTF_Font_ptr font = TTF_OpenFont_Magic(name, POINT_SIZE); TTF_Font_ptr font = TTF_OpenFont_Magic(family, POINT_SIZE);
// if no success, try the font path // if no success, try the font path
if (!font) if (!font)
{ {
osd_printf_verbose("Searching font %s in -%s\n", name.c_str(), OPTION_FONTPATH); osd_printf_verbose("Searching font %s in -%s\n", family.c_str(), OPTION_FONTPATH);
//emu_file file(options().font_path(), OPEN_FLAG_READ); //emu_file file(options().font_path(), OPEN_FLAG_READ);
emu_file file(font_path.c_str(), OPEN_FLAG_READ); emu_file file(font_path.c_str(), OPEN_FLAG_READ);
if (file.open(name.c_str()) == osd_file::error::NONE) if (file.open(family.c_str()) == osd_file::error::NONE)
{ {
std::string full_name = file.fullpath(); std::string full_name = file.fullpath();
font = TTF_OpenFont_Magic(full_name, POINT_SIZE); font = TTF_OpenFont_Magic(full_name, POINT_SIZE);
@ -104,7 +104,7 @@ bool osd_font_sdl::open(std::string const &font_path, std::string const &_name,
#if !defined(SDLMAME_HAIKU) && !defined(SDLMAME_EMSCRIPTEN) #if !defined(SDLMAME_HAIKU) && !defined(SDLMAME_EMSCRIPTEN)
if (!font) if (!font)
{ {
font = search_font_config(name, bold, italic, underline, bakedstyles); font = search_font_config(family, style, bakedstyles);
} }
#endif #endif
@ -118,21 +118,21 @@ bool osd_font_sdl::open(std::string const &font_path, std::string const &_name,
} }
// apply styles // apply styles
int style = 0; int styleflags = 0;
if (!bakedstyles) if (!bakedstyles)
{ {
style |= bold ? TTF_STYLE_BOLD : 0; if ((style.find("Bold") != std::string::npos) || (style.find("Black") != std::string::npos)) styleflags |= TTF_STYLE_BOLD;
style |= italic ? TTF_STYLE_ITALIC : 0; if ((style.find("Italic") != std::string::npos) || (style.find("Oblique") != std::string::npos)) styleflags |= TTF_STYLE_ITALIC;
} }
style |= underline ? TTF_STYLE_UNDERLINE : 0; styleflags |= underline ? TTF_STYLE_UNDERLINE : 0;
// SDL_ttf 2.0.9 and earlier does not define TTF_STYLE_STRIKETHROUGH // SDL_ttf 2.0.9 and earlier does not define TTF_STYLE_STRIKETHROUGH
#if SDL_VERSIONNUM(TTF_MAJOR_VERSION, TTF_MINOR_VERSION, TTF_PATCHLEVEL) > SDL_VERSIONNUM(2,0,9) #if SDL_VERSIONNUM(TTF_MAJOR_VERSION, TTF_MINOR_VERSION, TTF_PATCHLEVEL) > SDL_VERSIONNUM(2,0,9)
style |= strike ? TTF_STYLE_STRIKETHROUGH : 0; styleflags |= strike ? TTF_STYLE_STRIKETHROUGH : 0;
#else #else
if (strike) if (strike)
osd_printf_warning("Ignoring strikethrough for SDL_TTF older than 2.0.10\n"); osd_printf_warning("Ignoring strikethrough for SDL_TTF older than 2.0.10\n");
#endif // PATCHLEVEL #endif // PATCHLEVEL
TTF_SetFontStyle(font.get(), style); TTF_SetFontStyle(font.get(), styleflags);
height = TTF_FontLineSkip(font.get()); height = TTF_FontLineSkip(font.get());
@ -219,31 +219,18 @@ bool osd_font_sdl::BDF_Check_Magic(std::string const &name)
} }
#if !defined(SDLMAME_HAIKU) && !defined(SDLMAME_EMSCRIPTEN) #if !defined(SDLMAME_HAIKU) && !defined(SDLMAME_EMSCRIPTEN)
osd_font_sdl::TTF_Font_ptr osd_font_sdl::search_font_config(std::string const &name, bool bold, bool italic, bool underline, bool &bakedstyles) osd_font_sdl::TTF_Font_ptr osd_font_sdl::search_font_config(std::string const &family, std::string const &style, bool &bakedstyles)
{ {
TTF_Font_ptr font(nullptr, &TTF_CloseFont); TTF_Font_ptr font(nullptr, &TTF_CloseFont);
FcConfig *const config = FcConfigGetCurrent(); FcConfig *const config = FcConfigGetCurrent();
std::unique_ptr<FcPattern, void (*)(FcPattern *)> pat(FcPatternCreate(), &FcPatternDestroy); std::unique_ptr<FcPattern, void (*)(FcPattern *)> pat(FcPatternCreate(), &FcPatternDestroy);
std::unique_ptr<FcObjectSet, void (*)(FcObjectSet *)> os(FcObjectSetCreate(), &FcObjectSetDestroy); std::unique_ptr<FcObjectSet, void (*)(FcObjectSet *)> os(FcObjectSetCreate(), &FcObjectSetDestroy);
FcPatternAddString(pat.get(), FC_FAMILY, (const FcChar8 *)name.c_str()); FcPatternAddString(pat.get(), FC_FAMILY, (const FcChar8 *)family.c_str());
// try and get a font with the requested styles baked-in // try and get a font with the requested styles baked-in
if (bold) if (!style.empty())
{ FcPatternAddString(pat.get(), FC_STYLE, (const FcChar8 *)style.c_str());
if (italic)
FcPatternAddString(pat.get(), FC_STYLE, (const FcChar8 *)"Bold Italic");
else
FcPatternAddString(pat.get(), FC_STYLE, (const FcChar8 *)"Bold");
}
else if (italic)
{
FcPatternAddString(pat.get(), FC_STYLE, (const FcChar8 *)"Italic");
}
else
{
FcPatternAddString(pat.get(), FC_STYLE, (const FcChar8 *)"Regular");
}
FcPatternAddString(pat.get(), FC_FONTFORMAT, (const FcChar8 *)"TrueType"); FcPatternAddString(pat.get(), FC_FONTFORMAT, (const FcChar8 *)"TrueType");
@ -266,12 +253,10 @@ osd_font_sdl::TTF_Font_ptr osd_font_sdl::search_font_config(std::string const &n
} }
// didn't get a font above? try again with no baked-in styles // didn't get a font above? try again with no baked-in styles
if (!font) if (!font && !style.empty())
{ {
pat.reset(FcPatternCreate()); pat.reset(FcPatternCreate());
FcPatternAddString(pat.get(), FC_FAMILY, (const FcChar8 *)name.c_str()); FcPatternAddString(pat.get(), FC_FAMILY, (const FcChar8 *)family.c_str());
//Quite a lot of fonts don't have a "Regular" font type attribute
//FcPatternAddString(pat.get(), FC_STYLE, (const FcChar8 *)"Regular");
FcPatternAddString(pat.get(), FC_FONTFORMAT, (const FcChar8 *)"TrueType"); FcPatternAddString(pat.get(), FC_FONTFORMAT, (const FcChar8 *)"TrueType");
fontset.reset(FcFontList(config, pat.get(), os.get())); fontset.reset(FcFontList(config, pat.get(), os.get()));
@ -338,6 +323,7 @@ bool font_sdl::get_font_families(std::string const &font_path, std::vector<std::
std::unique_ptr<FcObjectSet, void (*)(FcObjectSet *)> os(FcObjectSetCreate(), &FcObjectSetDestroy); std::unique_ptr<FcObjectSet, void (*)(FcObjectSet *)> os(FcObjectSetCreate(), &FcObjectSetDestroy);
FcObjectSetAdd(os.get(), FC_FAMILY); FcObjectSetAdd(os.get(), FC_FAMILY);
FcObjectSetAdd(os.get(), FC_FILE); FcObjectSetAdd(os.get(), FC_FILE);
FcObjectSetAdd(os.get(), FC_STYLE);
std::unique_ptr<FcFontSet, void (*)(FcFontSet *)> fontset(FcFontList(config, pat.get(), os.get()), &FcFontSetDestroy); std::unique_ptr<FcFontSet, void (*)(FcFontSet *)> fontset(FcFontList(config, pat.get(), os.get()), &FcFontSetDestroy);
for (int i = 0; (i < fontset->nfont); i++) for (int i = 0; (i < fontset->nfont); i++)
@ -350,19 +336,30 @@ bool font_sdl::get_font_families(std::string const &font_path, std::vector<std::
{ {
auto const compare_fonts = [](std::pair<std::string, std::string> const &a, std::pair<std::string, std::string> const &b) -> bool auto const compare_fonts = [](std::pair<std::string, std::string> const &a, std::pair<std::string, std::string> const &b) -> bool
{ {
int const first = core_stricmp(a.first.c_str(), b.first.c_str()); int const second = core_stricmp(a.second.c_str(), b.second.c_str());
if (first < 0) return true; if (second < 0) return true;
else if (first > 0) return false; else if (second > 0) return false;
else return core_stricmp(b.second.c_str(), b.second.c_str()) < 0; else return core_stricmp(b.first.c_str(), b.first.c_str()) < 0;
}; };
std::pair<std::string, std::string> font((const char *)val.u.s, (const char *)val.u.s); std::string config((const char *)val.u.s);
std::string display(config);
if ((FcPatternGet(fontset->fonts[i], FC_STYLE, 0, &val) == FcResultMatch) && (val.type == FcTypeString))
{
config.push_back('|');
config.append((const char *)val.u.s);
display.push_back(' ');
display.append((const char *)val.u.s);
}
std::pair<std::string, std::string> font(std::move(config), std::move(display));
auto const pos = std::lower_bound(result.begin(), result.end(), font, compare_fonts); auto const pos = std::lower_bound(result.begin(), result.end(), font, compare_fonts);
if ((result.end() == pos) || (pos->first != font.first)) result.emplace(pos, std::move(font)); if ((result.end() == pos) || (pos->first != font.first)) result.emplace(pos, std::move(font));
} }
} }
#endif
return true; return true;
#else
return false;
#endif
} }
#else /* SDLMAME_UNIX */ #else /* SDLMAME_UNIX */