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.
This commit is contained in:
David Capello 2025-06-11 12:49:52 -03:00
parent 68342bdb66
commit af6e8b65c3
8 changed files with 33 additions and 30 deletions

View File

@ -34,14 +34,14 @@
type="spritesheet" type="spritesheet"
descent="2" descent="2"
file="aseprite_font.png"> file="aseprite_font.png">
<fallback font="Unicode" size="8" /> <fallback font="Unicode" size="14" />
</font> </font>
<font name="Aseprite Mini" <font name="Aseprite Mini"
type="spritesheet" type="spritesheet"
descent="1" descent="1"
file="aseprite_mini.png"> file="aseprite_mini.png">
<fallback font="Unicode" size="6" /> <fallback font="Unicode" size="10" />
</font> </font>
</fonts> </fonts>

2
laf

@ -1 +1 @@
Subproject commit 7d30a582e5c8655fab368c4d61f3125855a7b30d Subproject commit 81478c15f5be116651327e8c615265aa19c78be2

View File

@ -1372,8 +1372,8 @@ private:
if (!item) if (!item)
return; return;
const std::string lang = item->langId(); const std::string lang = item->langId();
const bool state = (lang == "ar" || lang == "ja" || lang == "ko" || lang == "yue_Hant" || const bool state = (lang == "ar" || lang == "ja" || lang == "ko" || lang == "th" ||
lang == "zh_Hans" || lang == "zh_Hant"); lang == "yue_Hant" || lang == "zh_Hans" || lang == "zh_Hant");
fontWarningFiller()->setVisible(state); fontWarningFiller()->setVisible(state);
fontWarning()->setVisible(state); fontWarning()->setVisible(state);
layout(); layout();

View File

@ -15,6 +15,7 @@
#include "text/font_mgr.h" #include "text/font_mgr.h"
#include "text/sprite_sheet_font.h" #include "text/sprite_sheet_font.h"
#include "ui/manager.h" #include "ui/manager.h"
#include "ui/scale.h"
#include <set> #include <set>
@ -87,9 +88,9 @@ text::FontRef FontData::getFont(text::FontMgrRef& fontMgr, float size)
// Load fallback // Load fallback
if (m_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) if (font)
font->setFallback(fallback.get()); font->setFallback(fallback);
else else
return fallback; // Don't double-cache the fallback font return fallback; // Don't double-cache the fallback font
} }

View File

@ -311,6 +311,9 @@ static FontData* load_font(const XMLElement* xmlFont, const std::string& xmlFile
if (!font && systemStr) { if (!font && systemStr) {
font = try_to_load_system_font(xmlFont); font = try_to_load_system_font(xmlFont);
} }
if (font && nameStr)
font->setName(nameStr);
} }
else { else {
throw base::Exception( throw base::Exception(
@ -1440,14 +1443,10 @@ void SkinTheme::drawEntryText(ui::Graphics* g, ui::Entry* widget)
IntersectClip clip(g, bounds); IntersectClip clip(g, bounds);
if (clip) { 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() g->drawTextWithDelegate(std::string(pos, textString.end()), // TODO use a string_view()
colors.text(), colors.text(),
ColorNone, ColorNone,
gfx::Point(bounds.x, bounds.y + baselineShift), bounds.origin(),
&delegate); &delegate);
} }
} }

View File

@ -136,7 +136,7 @@ class StatusBar::Indicators : public HBox {
g->drawText(text(), g->drawText(text(),
textColor, textColor,
ColorNone, ColorNone,
Point(rc.x, guiscaled_center(rc.y, rc.h, font()->lineHeight()))); Point(rc.x, guiscaled_center(rc.y, rc.h, textHeight())));
} }
} }
}; };

View File

@ -656,10 +656,8 @@ void Theme::measureLayer(const Widget* widget,
} }
else { else {
// We can use Widget::textSize() because we're going to use // We can use Widget::textSize() because we're going to use
// the widget font and, probably, the cached TextBlob width. // the widget font and, probably, the cached TextBlob size.
text::FontMetrics metrics; textSize = widget->textSize();
widget->font()->metrics(&metrics);
textSize = gfx::Size(widget->textSize().w, metrics.descent - metrics.ascent);
} }
textHint.offset(layer.offset()); textHint.offset(layer.offset());
@ -1044,7 +1042,8 @@ void Theme::drawMnemonicUnderline(Graphics* g,
decode.next(); // Go to first char decode.next(); // Go to first char
size_t glyphUtf8Begin = 0; 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) { text::TextBlob::RunInfo& info) {
for (int i = 0; i < info.glyphCount; ++i, decode.next()) { for (int i = 0; i < info.glyphCount; ++i, decode.next()) {
// TODO This doesn't work because the TextBlob::RunInfo::clusters is nullptr at this // 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) if (thickness < 1.0f)
thickness = 1.0f; thickness = 1.0f;
mnemonicBounds = gfx::RectF( mnemonicBounds = gfx::RectF(pt.x + mnemonicBounds.x,
pt.x + mnemonicBounds.x, pt.y + baseline + metrics.underlinePosition * guiscale(),
pt.y - metrics.ascent + metrics.underlinePosition * guiscale(), mnemonicBounds.w,
mnemonicBounds.w, thickness);
thickness);
g->drawRect(mnemonicBounds, paint); g->drawRect(mnemonicBounds, paint);
break; break;

View File

@ -965,6 +965,9 @@ int Widget::textWidth() const
int Widget::textHeight() const int Widget::textHeight() const
{ {
if (auto blob = textBlob())
return blob->textHeight();
text::FontMetrics metrics; text::FontMetrics metrics;
font()->metrics(&metrics); font()->metrics(&metrics);
return metrics.descent - metrics.ascent; return metrics.descent - metrics.ascent;
@ -1896,14 +1899,16 @@ text::ShaperFeatures Widget::onGetTextShaperFeatures() const
float Widget::onGetTextBaseline() const float Widget::onGetTextBaseline() const
{ {
text::FontMetrics metrics; // Here we use TextBlob::textHeight() which is calculated as
font()->metrics(&metrics); // descent+ascent to measure the text height, without the
// Here we only use the descent+ascent to measure the text height, // metrics.leading part (which is the used to separate text lines in
// without the metrics.leading part (which is the used to separate // a paragraph, but here'd make widgets too big).
// text lines in a paragraph, but here'd make widgets too big) text::TextBlobRef blob = textBlob();
const float textHeight = metrics.descent - metrics.ascent; if (!blob)
return 0.0f;
const gfx::Rect rc = clientChildrenBounds(); 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) void Widget::onDragEnter(DragEvent& e)