mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-26 11:48:36 +01:00
Add multi-font support to the final text-rendering backend (SDL_ttf)
This commit is contained in:
1 parent
582c2e28ca
commit
bf5e524243
3 files changed
+53
-41
No files matched your search
@@ -187,12 +187,15 @@ void TextDrawerSDL::PrepareFallbackFonts(std::string_view locale) {
|
||||
}
|
||||
|
||||
uint32_t TextDrawerSDL::CheckMissingGlyph(std::string_view text) {
|
||||
auto iter = fontMap_.find(fontHash_);
|
||||
auto iter = fontMap_.find(fontStyle_);
|
||||
if (iter == fontMap_.end()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TTF_Font *font = iter->second;
|
||||
if (!font) {
|
||||
return 0;
|
||||
}
|
||||
UTF8 utf8Decoded(text);
|
||||
|
||||
uint32_t missingGlyph = 0;
|
||||
@@ -245,48 +248,42 @@ int TextDrawerSDL::FindFallbackFonts(uint32_t missingGlyph, int ptSize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t TextDrawerSDL::SetOrCreateFont(const FontStyle &style) {
|
||||
const uint32_t fontHash = style.Hash();
|
||||
|
||||
auto iter = fontMap_.find(fontHash);
|
||||
void TextDrawerSDL::SetOrCreateFont(const FontStyle &style) {
|
||||
auto iter = fontMap_.find(style);
|
||||
if (iter != fontMap_.end()) {
|
||||
fontHash_ = fontHash;
|
||||
return fontHash;
|
||||
fontStyle_ = style;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string useFont = !style.fontName.empty() ? style.fontName : std::string("Roboto-Condensed.ttf");
|
||||
const int ptSize = (int)((style.sizePts + 6) / dpiScale_);
|
||||
std::string useFont = "assets/" + GetFilenameForFontStyle(style) + ".ttf";
|
||||
|
||||
TTF_Font *font = TTF_OpenFont(useFont.c_str(), ptSize);
|
||||
|
||||
if (!font) {
|
||||
File::FileInfo fileInfo;
|
||||
g_VFS.GetFileInfo("Roboto-Condensed.ttf", &fileInfo);
|
||||
font = TTF_OpenFont(fileInfo.fullName.c_str(), ptSize);
|
||||
if (loadedFonts_.find(useFont) == loadedFonts_.end()) {
|
||||
int ptSize = static_cast<int>(style.sizePts / dpiScale_ * 1.25f);
|
||||
TTF_Font *font = TTF_OpenFont(useFont.c_str(), ptSize);
|
||||
if (!font) {
|
||||
ERROR_LOG(Log::G3D, "Failed to load font file %s", useFont.c_str());
|
||||
}
|
||||
// Still, mark it with a nullptr to avoid retrying.
|
||||
loadedFonts_[useFont] = font;
|
||||
}
|
||||
|
||||
fontMap_[fontHash] = font;
|
||||
fontHash_ = fontHash;
|
||||
return fontHash;
|
||||
}
|
||||
|
||||
void TextDrawerSDL::SetFont(uint32_t fontHandle) {
|
||||
uint32_t fontHash = fontHandle;
|
||||
auto iter = fontMap_.find(fontHash);
|
||||
if (iter != fontMap_.end()) {
|
||||
fontHash_ = fontHandle;
|
||||
} else {
|
||||
ERROR_LOG(Log::G3D, "Invalid font handle %08x", fontHandle);
|
||||
}
|
||||
fontMap_[style] = loadedFonts_[useFont];
|
||||
fontStyle_ = style;
|
||||
}
|
||||
|
||||
void TextDrawerSDL::MeasureStringInternal(std::string_view str, float *w, float *h) {
|
||||
TTF_Font *font = fontMap_.find(fontHash_)->second;
|
||||
int ptSize = TTF_FontHeight(font) / 1.35;
|
||||
TTF_Font *font = fontMap_.find(fontStyle_)->second;
|
||||
|
||||
if (!font) {
|
||||
*w = 1.0f;
|
||||
*h = 1.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t missingGlyph = CheckMissingGlyph(str);
|
||||
|
||||
if (missingGlyph) {
|
||||
int ptSize = static_cast<int>(fontStyle_.sizePts / dpiScale_ * 1.25f);
|
||||
int fallbackFont = FindFallbackFonts(missingGlyph, ptSize);
|
||||
if (fallbackFont >= 0 && fallbackFont < (int)fallbackFonts_.size()) {
|
||||
font = fallbackFonts_[fallbackFont];
|
||||
@@ -300,8 +297,8 @@ void TextDrawerSDL::MeasureStringInternal(std::string_view str, float *w, float
|
||||
std::string text(str);
|
||||
TTF_SizeUTF8(font, text.c_str(), &width, &height);
|
||||
|
||||
*w = width;
|
||||
*h = height;
|
||||
*w = (float)width;
|
||||
*h = (float)height;
|
||||
}
|
||||
|
||||
bool TextDrawerSDL::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) {
|
||||
@@ -322,14 +319,17 @@ bool TextDrawerSDL::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStrin
|
||||
processedStr.push_back(' ');
|
||||
}
|
||||
|
||||
auto fontIter = fontMap_.find(fontHash_);
|
||||
auto fontIter = fontMap_.find(fontStyle_);
|
||||
if (fontIter == fontMap_.end()) {
|
||||
ERROR_LOG(Log::G3D, "Font hash not in map: %08x", fontHash_);
|
||||
ERROR_LOG(Log::G3D, "Font style not in map");
|
||||
return false;
|
||||
}
|
||||
|
||||
TTF_Font *font = fontIter->second;
|
||||
int ptSize = TTF_FontHeight(font) / 1.35;
|
||||
if (!font) {
|
||||
return false;
|
||||
}
|
||||
int ptSize = TTF_FontHeight(font) / 1.25;
|
||||
|
||||
uint32_t missingGlyph = CheckMissingGlyph(processedStr);
|
||||
|
||||
@@ -392,12 +392,19 @@ bool TextDrawerSDL::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStrin
|
||||
}
|
||||
|
||||
void TextDrawerSDL::ClearFonts() {
|
||||
for (auto iter : fontMap_) {
|
||||
TTF_CloseFont(iter.second);
|
||||
for (auto iter : loadedFonts_) {
|
||||
if (iter.second) {
|
||||
TTF_CloseFont(iter.second);
|
||||
}
|
||||
}
|
||||
for (auto iter : fallbackFonts_) {
|
||||
TTF_CloseFont(iter);
|
||||
if (iter) {
|
||||
TTF_CloseFont(iter);
|
||||
}
|
||||
}
|
||||
|
||||
// We wipe all the maps, including fontMap_. Everything it contains is also in loadedFonts_ which is cleared above.
|
||||
loadedFonts_.clear();
|
||||
fontMap_.clear();
|
||||
fallbackFonts_.clear();
|
||||
}
|
||||
|
||||
@@ -19,8 +19,7 @@ public:
|
||||
TextDrawerSDL(Draw::DrawContext *draw);
|
||||
~TextDrawerSDL();
|
||||
|
||||
uint32_t SetOrCreateFont(const FontStyle &style) override;
|
||||
void SetFont(uint32_t fontHandle) override; // Shortcut once you've set the font once.
|
||||
void SetOrCreateFont(const FontStyle &style) override;
|
||||
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override;
|
||||
|
||||
protected:
|
||||
@@ -34,7 +33,11 @@ private:
|
||||
uint32_t CheckMissingGlyph(std::string_view text);
|
||||
int FindFallbackFonts(uint32_t missingGlyph, int ptSize);
|
||||
|
||||
std::map<uint32_t, TTF_Font *> fontMap_;
|
||||
// NOTE: This can contain dupes. The below doesn't.
|
||||
std::map<FontStyle, TTF_Font *> fontMap_;
|
||||
|
||||
// These are the ones we free. fontMap points into this map.
|
||||
std::map<std::string, TTF_Font *> loadedFonts_;
|
||||
|
||||
std::vector<TTF_Font *> fallbackFonts_;
|
||||
std::vector<std::pair<std::string, int>> fallbackFontPaths_; // path and font face index
|
||||
|
||||
@@ -32,12 +32,14 @@ void ApplyGravity(const Bounds &outer, const Margins &margins, float w, float h,
|
||||
case Gravity::G_LEFT: inner.x = outer.x + margins.left; break;
|
||||
case Gravity::G_RIGHT: inner.x = outer.x + outer.w - w - margins.right; break;
|
||||
case Gravity::G_HCENTER: inner.x = outer.x + (outer.w - w) * 0.5f; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
switch ((Gravity)((int)gravity & (int)Gravity::G_VERTMASK)) {
|
||||
case Gravity::G_TOP: inner.y = outer.y + margins.top; break;
|
||||
case Gravity::G_BOTTOM: inner.y = outer.y + outer.h - h - margins.bottom; break;
|
||||
case Gravity::G_VCENTER: inner.y = outer.y + (outer.h - h) * 0.5f; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user