From af6e8b65c3c8a3fddba6bc95c594265c2fd6256c Mon Sep 17 00:00:00 2001 From: David Capello Date: Wed, 11 Jun 2025 12:49:52 -0300 Subject: [PATCH] Fix default font for CJK and other translations (fix #5210) Now we use the correct fallback font with its size for non-existent glyph in the sprite sheet font. --- data/fonts/fonts.xml | 4 ++-- laf | 2 +- src/app/commands/cmd_options.cpp | 4 ++-- src/app/fonts/font_data.cpp | 5 +++-- src/app/ui/skin/skin_theme.cpp | 9 ++++----- src/app/ui/status_bar.cpp | 2 +- src/ui/theme.cpp | 18 ++++++++---------- src/ui/widget.cpp | 19 ++++++++++++------- 8 files changed, 33 insertions(+), 30 deletions(-) diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml index 58cd7fc4b..7ce9b8353 100644 --- a/data/fonts/fonts.xml +++ b/data/fonts/fonts.xml @@ -34,14 +34,14 @@ type="spritesheet" descent="2" file="aseprite_font.png"> - + - + diff --git a/laf b/laf index 7d30a582e..81478c15f 160000 --- a/laf +++ b/laf @@ -1 +1 @@ -Subproject commit 7d30a582e5c8655fab368c4d61f3125855a7b30d +Subproject commit 81478c15f5be116651327e8c615265aa19c78be2 diff --git a/src/app/commands/cmd_options.cpp b/src/app/commands/cmd_options.cpp index 56b9415ed..9f258f94b 100644 --- a/src/app/commands/cmd_options.cpp +++ b/src/app/commands/cmd_options.cpp @@ -1372,8 +1372,8 @@ private: if (!item) return; const std::string lang = item->langId(); - const bool state = (lang == "ar" || lang == "ja" || lang == "ko" || lang == "yue_Hant" || - lang == "zh_Hans" || lang == "zh_Hant"); + const bool state = (lang == "ar" || lang == "ja" || lang == "ko" || lang == "th" || + lang == "yue_Hant" || lang == "zh_Hans" || lang == "zh_Hant"); fontWarningFiller()->setVisible(state); fontWarning()->setVisible(state); layout(); diff --git a/src/app/fonts/font_data.cpp b/src/app/fonts/font_data.cpp index 497882c89..020b345af 100644 --- a/src/app/fonts/font_data.cpp +++ b/src/app/fonts/font_data.cpp @@ -15,6 +15,7 @@ #include "text/font_mgr.h" #include "text/sprite_sheet_font.h" #include "ui/manager.h" +#include "ui/scale.h" #include @@ -87,9 +88,9 @@ text::FontRef FontData::getFont(text::FontMgrRef& fontMgr, float size) // Load fallback if (m_fallback) { - text::FontRef fallback = m_fallback->getFont(fontMgr, m_fallbackSize); + text::FontRef fallback = m_fallback->getFont(fontMgr, m_fallbackSize * ui::guiscale()); if (font) - font->setFallback(fallback.get()); + font->setFallback(fallback); else return fallback; // Don't double-cache the fallback font } diff --git a/src/app/ui/skin/skin_theme.cpp b/src/app/ui/skin/skin_theme.cpp index 18a748cab..65dffdfaf 100644 --- a/src/app/ui/skin/skin_theme.cpp +++ b/src/app/ui/skin/skin_theme.cpp @@ -311,6 +311,9 @@ static FontData* load_font(const XMLElement* xmlFont, const std::string& xmlFile if (!font && systemStr) { font = try_to_load_system_font(xmlFont); } + + if (font && nameStr) + font->setName(nameStr); } else { throw base::Exception( @@ -1440,14 +1443,10 @@ void SkinTheme::drawEntryText(ui::Graphics* g, ui::Entry* widget) IntersectClip clip(g, bounds); if (clip) { - text::FontMetrics metrics; - widget->font()->metrics(&metrics); - const float baselineShift = -metrics.ascent - widget->textBlob()->baseline(); - g->drawTextWithDelegate(std::string(pos, textString.end()), // TODO use a string_view() colors.text(), ColorNone, - gfx::Point(bounds.x, bounds.y + baselineShift), + bounds.origin(), &delegate); } } diff --git a/src/app/ui/status_bar.cpp b/src/app/ui/status_bar.cpp index 5da647067..61801dbb2 100644 --- a/src/app/ui/status_bar.cpp +++ b/src/app/ui/status_bar.cpp @@ -136,7 +136,7 @@ class StatusBar::Indicators : public HBox { g->drawText(text(), textColor, ColorNone, - Point(rc.x, guiscaled_center(rc.y, rc.h, font()->lineHeight()))); + Point(rc.x, guiscaled_center(rc.y, rc.h, textHeight()))); } } }; diff --git a/src/ui/theme.cpp b/src/ui/theme.cpp index 9d037511a..302c4a727 100644 --- a/src/ui/theme.cpp +++ b/src/ui/theme.cpp @@ -656,10 +656,8 @@ void Theme::measureLayer(const Widget* widget, } else { // We can use Widget::textSize() because we're going to use - // the widget font and, probably, the cached TextBlob width. - text::FontMetrics metrics; - widget->font()->metrics(&metrics); - textSize = gfx::Size(widget->textSize().w, metrics.descent - metrics.ascent); + // the widget font and, probably, the cached TextBlob size. + textSize = widget->textSize(); } textHint.offset(layer.offset()); @@ -1044,7 +1042,8 @@ void Theme::drawMnemonicUnderline(Graphics* g, decode.next(); // Go to first char size_t glyphUtf8Begin = 0; - textBlob->visitRuns([g, mnemonicUtf8Pos, pt, &paint, &decode, &glyphUtf8Begin, &text]( + float baseline = textBlob->baseline(); + textBlob->visitRuns([g, baseline, mnemonicUtf8Pos, pt, &paint, &decode, &glyphUtf8Begin, &text]( text::TextBlob::RunInfo& info) { for (int i = 0; i < info.glyphCount; ++i, decode.next()) { // TODO This doesn't work because the TextBlob::RunInfo::clusters is nullptr at this @@ -1061,11 +1060,10 @@ void Theme::drawMnemonicUnderline(Graphics* g, if (thickness < 1.0f) thickness = 1.0f; - mnemonicBounds = gfx::RectF( - pt.x + mnemonicBounds.x, - pt.y - metrics.ascent + metrics.underlinePosition * guiscale(), - mnemonicBounds.w, - thickness); + mnemonicBounds = gfx::RectF(pt.x + mnemonicBounds.x, + pt.y + baseline + metrics.underlinePosition * guiscale(), + mnemonicBounds.w, + thickness); g->drawRect(mnemonicBounds, paint); break; diff --git a/src/ui/widget.cpp b/src/ui/widget.cpp index b13850334..c5275b0e8 100644 --- a/src/ui/widget.cpp +++ b/src/ui/widget.cpp @@ -965,6 +965,9 @@ int Widget::textWidth() const int Widget::textHeight() const { + if (auto blob = textBlob()) + return blob->textHeight(); + text::FontMetrics metrics; font()->metrics(&metrics); return metrics.descent - metrics.ascent; @@ -1896,14 +1899,16 @@ text::ShaperFeatures Widget::onGetTextShaperFeatures() const float Widget::onGetTextBaseline() const { - text::FontMetrics metrics; - font()->metrics(&metrics); - // Here we only use the descent+ascent to measure the text height, - // without the metrics.leading part (which is the used to separate - // text lines in a paragraph, but here'd make widgets too big) - const float textHeight = metrics.descent - metrics.ascent; + // Here we use TextBlob::textHeight() which is calculated as + // descent+ascent to measure the text height, without the + // metrics.leading part (which is the used to separate text lines in + // a paragraph, but here'd make widgets too big). + text::TextBlobRef blob = textBlob(); + if (!blob) + return 0.0f; + const gfx::Rect rc = clientChildrenBounds(); - return guiscaled_center(rc.y, rc.h, textHeight) - metrics.ascent; + return guiscaled_center(rc.y, rc.h, blob->textHeight()) + blob->baseline(); } void Widget::onDragEnter(DragEvent& e)