mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-12-04 03:32:29 +00:00
Merge pull request #18734 from hrydgard/more-sdl-fallback-font-work
SDL fallback fonts: Add more font names
This commit is contained in:
commit
97647a561d
@ -18,6 +18,18 @@
|
|||||||
#include "SDL2/SDL.h"
|
#include "SDL2/SDL.h"
|
||||||
#include "SDL2/SDL_ttf.h"
|
#include "SDL2/SDL_ttf.h"
|
||||||
|
|
||||||
|
static std::string getlocale() {
|
||||||
|
// setlocale is not an intuitive function...
|
||||||
|
char *curlocale = setlocale(LC_CTYPE, nullptr);
|
||||||
|
std::string loc = curlocale ? std::string(curlocale) : "en_US";
|
||||||
|
size_t ptPos = loc.find('.');
|
||||||
|
// Remove any secondary specifier.
|
||||||
|
if (ptPos != std::string::npos) {
|
||||||
|
loc.resize(ptPos);
|
||||||
|
}
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
|
||||||
TextDrawerSDL::TextDrawerSDL(Draw::DrawContext *draw): TextDrawer(draw) {
|
TextDrawerSDL::TextDrawerSDL(Draw::DrawContext *draw): TextDrawer(draw) {
|
||||||
if (TTF_Init() < 0) {
|
if (TTF_Init() < 0) {
|
||||||
ERROR_LOG(G3D, "Unable to initialize SDL2_ttf");
|
ERROR_LOG(G3D, "Unable to initialize SDL2_ttf");
|
||||||
@ -29,7 +41,7 @@ TextDrawerSDL::TextDrawerSDL(Draw::DrawContext *draw): TextDrawer(draw) {
|
|||||||
config = FcInitLoadConfigAndFonts();
|
config = FcInitLoadConfigAndFonts();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PrepareFallbackFonts();
|
PrepareFallbackFonts(getlocale());
|
||||||
}
|
}
|
||||||
|
|
||||||
TextDrawerSDL::~TextDrawerSDL() {
|
TextDrawerSDL::~TextDrawerSDL() {
|
||||||
@ -44,25 +56,56 @@ TextDrawerSDL::~TextDrawerSDL() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If a user complains about missing characters on SDL, re-visit this!
|
// If a user complains about missing characters on SDL, re-visit this!
|
||||||
void TextDrawerSDL::PrepareFallbackFonts() {
|
void TextDrawerSDL::PrepareFallbackFonts(std::string_view locale) {
|
||||||
#if defined(USE_SDL2_TTF_FONTCONFIG)
|
#if defined(USE_SDL2_TTF_FONTCONFIG)
|
||||||
FcObjectSet *os = FcObjectSetBuild (FC_FILE, FC_INDEX, (char *) 0);
|
FcObjectSet *os = FcObjectSetBuild (FC_FILE, FC_INDEX, (char *) 0);
|
||||||
|
|
||||||
// To install the fallback font in ubuntu:
|
// To install the recommended Droid Sans fallback font in Ubuntu:
|
||||||
// sudo apt install fonts-droid-fallback
|
// sudo apt install fonts-droid-fallback
|
||||||
const char *names[] = {
|
const char *hardcodedNames[] = {
|
||||||
"Droid Sans Fallback",
|
|
||||||
"Droid Sans Medium",
|
"Droid Sans Medium",
|
||||||
"Droid Sans Bold",
|
"Droid Sans Fallback",
|
||||||
"Source Han Sans Medium",
|
"Source Han Sans Medium",
|
||||||
"DejaVu Sans Condensed",
|
|
||||||
"Noto Sans CJK Medium",
|
"Noto Sans CJK Medium",
|
||||||
"Noto Sans Hebrew Medium",
|
"Noto Sans Hebrew Medium",
|
||||||
"Noto Sans Lao Medium",
|
"Noto Sans Lao Medium",
|
||||||
"Noto Sans Thai Medium",
|
"Noto Sans Thai Medium",
|
||||||
|
"DejaVu Sans Condensed",
|
||||||
|
"DejaVu Sans",
|
||||||
|
"Meera Regular",
|
||||||
|
"FreeSans",
|
||||||
|
"Gargi",
|
||||||
|
"KacstDigital",
|
||||||
|
"KacstFarsi",
|
||||||
|
"Khmer OS",
|
||||||
|
"Paduak",
|
||||||
|
"Paduak",
|
||||||
|
"Jamrul",
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < ARRAY_SIZE(names); i++) {
|
std::vector<const char *> names;
|
||||||
|
if (locale == "zh_CN") {
|
||||||
|
names.push_back("Noto Sans CJK SC");
|
||||||
|
} else if (locale == "zh_TW") {
|
||||||
|
names.push_back("Noto Sans CJK TC");
|
||||||
|
names.push_back("Noto Sans CJK HK");
|
||||||
|
} else if (locale == "ja_JP") {
|
||||||
|
names.push_back("Noto Sans CJK JP");
|
||||||
|
} else if (locale == "ko_KR") {
|
||||||
|
names.push_back("Noto Sans CJK KR");
|
||||||
|
} else {
|
||||||
|
// Let's just pick one.
|
||||||
|
names.push_back("Noto Sans CJK JP");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then push all the hardcoded ones.
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(hardcodedNames); i++) {
|
||||||
|
names.push_back(hardcodedNames[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// First, add the region-specific Noto fonts according to the locale.
|
||||||
|
|
||||||
|
for (int i = 0; i < names.size(); i++) {
|
||||||
// printf("trying font name %s\n", names[i]);
|
// printf("trying font name %s\n", names[i]);
|
||||||
FcPattern *name = FcNameParse((const FcChar8 *)names[i]);
|
FcPattern *name = FcNameParse((const FcChar8 *)names[i]);
|
||||||
FcFontSet *foundFonts = FcFontList(config, name, os);
|
FcFontSet *foundFonts = FcFontList(config, name, os);
|
||||||
@ -159,19 +202,25 @@ uint32_t TextDrawerSDL::CheckMissingGlyph(const std::string& text) {
|
|||||||
return missingGlyph;
|
return missingGlyph;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this returns true, the first font in fallbackFonts_ can be used as a fallback.
|
// If this returns >= 0, the nth font in fallbackFonts_ can be used as a fallback.
|
||||||
bool TextDrawerSDL::FindFallbackFonts(uint32_t missingGlyph, int ptSize) {
|
int TextDrawerSDL::FindFallbackFonts(uint32_t missingGlyph, int ptSize) {
|
||||||
// If we encounter a missing glyph, try to use one of the fallback fonts.
|
auto iter = glyphFallbackFontIndex_.find(missingGlyph);
|
||||||
|
|
||||||
|
if (iter != glyphFallbackFontIndex_.end()) {
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we encounter a missing glyph, try to use one of already loaded fallback fonts.
|
||||||
for (int i = 0; i < fallbackFonts_.size(); i++) {
|
for (int i = 0; i < fallbackFonts_.size(); i++) {
|
||||||
TTF_Font *fallbackFont = fallbackFonts_[i];
|
TTF_Font *fallbackFont = fallbackFonts_[i];
|
||||||
if (TTF_GlyphIsProvided32(fallbackFont, missingGlyph)) {
|
if (TTF_GlyphIsProvided32(fallbackFont, missingGlyph)) {
|
||||||
fallbackFonts_.erase(fallbackFonts_.begin() + i);
|
glyphFallbackFontIndex_[missingGlyph] = i;
|
||||||
fallbackFonts_.insert(fallbackFonts_.begin(), fallbackFont);
|
return i;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If none of the loaded fonts can handle it, load more fonts.
|
// If none of the loaded fonts can handle it, load more fonts.
|
||||||
|
// TODO: Don't retry already tried fonts.
|
||||||
for (int i = 0; i < fallbackFontPaths_.size(); i++) {
|
for (int i = 0; i < fallbackFontPaths_.size(); i++) {
|
||||||
std::string& fontPath = fallbackFontPaths_[i].first;
|
std::string& fontPath = fallbackFontPaths_[i].first;
|
||||||
int faceIndex = fallbackFontPaths_[i].second;
|
int faceIndex = fallbackFontPaths_[i].second;
|
||||||
@ -179,14 +228,16 @@ bool TextDrawerSDL::FindFallbackFonts(uint32_t missingGlyph, int ptSize) {
|
|||||||
TTF_Font *font = TTF_OpenFontIndex(fontPath.c_str(), ptSize, faceIndex);
|
TTF_Font *font = TTF_OpenFontIndex(fontPath.c_str(), ptSize, faceIndex);
|
||||||
|
|
||||||
if (TTF_GlyphIsProvided32(font, missingGlyph)) {
|
if (TTF_GlyphIsProvided32(font, missingGlyph)) {
|
||||||
fallbackFonts_.insert(fallbackFonts_.begin(), font);
|
fallbackFonts_.push_back(font);
|
||||||
return true;
|
return fallbackFonts_.size() - 1;
|
||||||
} else {
|
} else {
|
||||||
TTF_CloseFont(font);
|
TTF_CloseFont(font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
// Not found at all? Let's remember that for this glyph.
|
||||||
|
glyphFallbackFontIndex_[missingGlyph] = -1;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t TextDrawerSDL::SetFont(const char *fontName, int size, int flags) {
|
uint32_t TextDrawerSDL::SetFont(const char *fontName, int size, int flags) {
|
||||||
@ -234,13 +285,17 @@ void TextDrawerSDL::MeasureString(const char *str, size_t len, float *w, float *
|
|||||||
if (iter != sizeCache_.end()) {
|
if (iter != sizeCache_.end()) {
|
||||||
entry = iter->second.get();
|
entry = iter->second.get();
|
||||||
} else {
|
} else {
|
||||||
|
printf("re-measuring %s\n", str);
|
||||||
TTF_Font *font = fontMap_.find(fontHash_)->second;
|
TTF_Font *font = fontMap_.find(fontHash_)->second;
|
||||||
int ptSize = TTF_FontHeight(font) / 1.35;
|
int ptSize = TTF_FontHeight(font) / 1.35;
|
||||||
|
|
||||||
uint32_t missingGlyph = CheckMissingGlyph(key.text);
|
uint32_t missingGlyph = CheckMissingGlyph(key.text);
|
||||||
|
|
||||||
if (missingGlyph && FindFallbackFonts(missingGlyph, ptSize)) {
|
if (missingGlyph) {
|
||||||
font = fallbackFonts_[0];
|
int fallbackFont = FindFallbackFonts(missingGlyph, ptSize);
|
||||||
|
if (fallbackFont >= 0) {
|
||||||
|
font = fallbackFonts_[fallbackFont];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int width = 0;
|
int width = 0;
|
||||||
@ -270,8 +325,11 @@ void TextDrawerSDL::MeasureStringRect(const char *str, size_t len, const Bounds
|
|||||||
int ptSize = TTF_FontHeight(font) / 1.35;
|
int ptSize = TTF_FontHeight(font) / 1.35;
|
||||||
uint32_t missingGlyph = CheckMissingGlyph(toMeasure);
|
uint32_t missingGlyph = CheckMissingGlyph(toMeasure);
|
||||||
|
|
||||||
if (missingGlyph && FindFallbackFonts(missingGlyph, ptSize)) {
|
if (missingGlyph) {
|
||||||
font = fallbackFonts_[0];
|
int fallbackFont = FindFallbackFonts(missingGlyph, ptSize);
|
||||||
|
if (fallbackFont >= 0) {
|
||||||
|
font = fallbackFonts_[fallbackFont];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> lines;
|
std::vector<std::string> lines;
|
||||||
@ -381,8 +439,11 @@ void TextDrawerSDL::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStrin
|
|||||||
|
|
||||||
uint32_t missingGlyph = CheckMissingGlyph(processedStr);
|
uint32_t missingGlyph = CheckMissingGlyph(processedStr);
|
||||||
|
|
||||||
if (missingGlyph && FindFallbackFonts(missingGlyph, ptSize)) {
|
if (missingGlyph) {
|
||||||
font = fallbackFonts_[0];
|
int fallbackFont = FindFallbackFonts(missingGlyph, ptSize);
|
||||||
|
if (fallbackFont >= 0) {
|
||||||
|
font = fallbackFonts_[fallbackFont];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SDL_TTF_VERSION_ATLEAST(2, 20, 0)
|
#if SDL_TTF_VERSION_ATLEAST(2, 20, 0)
|
||||||
|
@ -28,9 +28,9 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void ClearCache() override;
|
void ClearCache() override;
|
||||||
void PrepareFallbackFonts();
|
void PrepareFallbackFonts(std::string_view locale);
|
||||||
uint32_t CheckMissingGlyph(const std::string& text);
|
uint32_t CheckMissingGlyph(const std::string& text);
|
||||||
bool FindFallbackFonts(uint32_t missingGlyph, int ptSize);
|
int FindFallbackFonts(uint32_t missingGlyph, int ptSize);
|
||||||
|
|
||||||
uint32_t fontHash_;
|
uint32_t fontHash_;
|
||||||
std::map<uint32_t, _TTF_Font *> fontMap_;
|
std::map<uint32_t, _TTF_Font *> fontMap_;
|
||||||
@ -41,6 +41,8 @@ protected:
|
|||||||
std::vector<_TTF_Font *> fallbackFonts_;
|
std::vector<_TTF_Font *> fallbackFonts_;
|
||||||
std::vector<std::pair<std::string, int>> fallbackFontPaths_; // path and font face index
|
std::vector<std::pair<std::string, int>> fallbackFontPaths_; // path and font face index
|
||||||
|
|
||||||
|
std::map<int, int> glyphFallbackFontIndex_;
|
||||||
|
|
||||||
#if defined(USE_SDL2_TTF_FONTCONFIG)
|
#if defined(USE_SDL2_TTF_FONTCONFIG)
|
||||||
FcConfig *config;
|
FcConfig *config;
|
||||||
#endif
|
#endif
|
||||||
|
@ -563,9 +563,9 @@ bool System_GetPropertyBool(SystemProperty prop) {
|
|||||||
#if PPSSPP_PLATFORM(SWITCH)
|
#if PPSSPP_PLATFORM(SWITCH)
|
||||||
case SYSPROP_HAS_TEXT_INPUT_DIALOG:
|
case SYSPROP_HAS_TEXT_INPUT_DIALOG:
|
||||||
return __nx_applet_type == AppletType_Application || __nx_applet_type != AppletType_SystemApplication;
|
return __nx_applet_type == AppletType_Application || __nx_applet_type != AppletType_SystemApplication;
|
||||||
|
#endif
|
||||||
case SYSPROP_HAS_KEYBOARD:
|
case SYSPROP_HAS_KEYBOARD:
|
||||||
return true;
|
return true;
|
||||||
#endif
|
|
||||||
case SYSPROP_APP_GOLD:
|
case SYSPROP_APP_GOLD:
|
||||||
#ifdef GOLD
|
#ifdef GOLD
|
||||||
return true;
|
return true;
|
||||||
|
@ -44,6 +44,7 @@ protected:
|
|||||||
void dialogFinished(const Screen *dialog, DialogResult result) override;
|
void dialogFinished(const Screen *dialog, DialogResult result) override;
|
||||||
|
|
||||||
void CreateTabs() override;
|
void CreateTabs() override;
|
||||||
|
bool ShowSearchControls() const { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void PreCreateViews() override;
|
void PreCreateViews() override;
|
||||||
|
Loading…
Reference in New Issue
Block a user