GUI: allow ingame CJK dialogs regardless of the launcher language

This allows a text widget to be expressly marked as Japanese, Korean or Chinese, so that the theme engine may use an appropriate font.
This commit is contained in:
athrxx 2020-10-25 01:38:05 +02:00
parent fb834e55fb
commit 5b6ffeaa3d
7 changed files with 146 additions and 14 deletions

View File

@ -382,16 +382,23 @@ void HelpDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 da
#pragma mark -
InfoDialog::InfoDialog(ScummEngine *scumm, int res)
: ScummDialog(0, 0, 0, 0), _vm(scumm) { // dummy x and w
: ScummDialog(0, 0, 0, 0), _vm(scumm), _style(GUI::ThemeEngine::kFontStyleBold) { // dummy x and w
_message = queryResString(res);
Common::Language lang = (_vm->_language == Common::KO_KOR || _vm->_language == Common::JA_JPN ||
_vm->_language == Common::ZH_TWN || _vm->_language == Common::ZH_CNA) ? _vm->_language : Common::UNK_LANG;
// Width and height are dummy
_text = new GUI::StaticTextWidget(this, 0, 0, 10, 10, _message, kTextAlignCenter);
_text = new GUI::StaticTextWidget(this, 0, 0, 10, 10, _message, kTextAlignCenter, Common::U32String(), GUI::ThemeEngine::kFontStyleBold, lang);
// Store this for the calls to getStringWidth() and getStringHeight() in reflowLayout().
if (lang != Common::UNK_LANG)
_style = GUI::ThemeEngine::kFontStyleLangExtra;
}
InfoDialog::InfoDialog(ScummEngine *scumm, const U32String &message)
: ScummDialog(0, 0, 0, 0), _vm(scumm) { // dummy x and w
: ScummDialog(0, 0, 0, 0), _vm(scumm), _style(GUI::ThemeEngine::kFontStyleBold) { // dummy x and w
_message = message;
@ -409,8 +416,8 @@ void InfoDialog::reflowLayout() {
const int screenW = g_system->getOverlayWidth();
const int screenH = g_system->getOverlayHeight();
int width = g_gui.getStringWidth(_message) + 16;
int height = g_gui.getFontHeight() + 8;
int width = g_gui.getStringWidth(_message, _style) + 16;
int height = g_gui.getFontHeight(_style) + 8;
_w = width;
_h = height;

View File

@ -72,6 +72,7 @@ protected:
ScummEngine *_vm;
U32String _message;
GUI::StaticTextWidget *_text;
GUI::ThemeEngine::FontStyle _style;
public:
// arbitrary message

View File

@ -553,7 +553,7 @@ bool ThemeEngine::addFont(TextData textId, const Common::String &language, const
Common::String localized = FontMan.genLocalizedFontFilename(file);
const Common::String charset
#ifdef USE_TRANSLATION
(TransMan.getCurrentCharset())
(textId == kTextDataExtraLang ? "" : TransMan.getCurrentCharset())
#endif
;
@ -598,6 +598,63 @@ bool ThemeEngine::addFont(TextData textId, const Common::String &language, const
}
// This should work independently of the translation manager, since it is is just about displaying
// correct ingame messages in Chinese, Korean and Japanese games, even if the launcher is set to
// English and/or the translations are disabled.
Common::Array<Common::Language> getLangIdentifiers(const Common::String &language) {
struct IdStr2Lang {
const char strId[6];
Common::Language lang;
};
// I have added only the languages that currently make sense (the only other extra font that we
// currently have is for Hindi, but that language is only supported in the launcher, there are
// no games in Hindi).
IdStr2Lang matchPairs[] = {
// { "hi", Common::UNK_LANG },
{ "ja", Common::JA_JPN },
{ "ko", Common::KO_KOR },
{ "zh", Common::ZH_ANY },
{ "zh", Common::ZH_CNA },
{ "zh", Common::ZH_TWN }
};
Common::Array<Common::Language> result;
for (int i = 0; i < ARRAYSIZE(matchPairs); ++i) {
if (language.contains(matchPairs[i].strId))
result.push_back(matchPairs[i].lang);
}
return result;
}
void ThemeEngine::storeFontNames(TextData textId, const Common::String &language, const Common::String &file, const Common::String &scalableFile, const int pointsize) {
if (language.empty())
return;
Common::Array<Common::Language> langs = getLangIdentifiers(language);
if (langs.empty())
return;
Common::Array<LangExtraFont>::iterator entry = Common::find(_langExtraFonts.begin(), _langExtraFonts.end(), langs[0]);
if (entry == _langExtraFonts.end())
_langExtraFonts.push_back(LangExtraFont(textId, langs, file, scalableFile, pointsize));
else
entry->storeFileNames(textId, file, scalableFile, pointsize);
}
bool ThemeEngine::loadExtraFont(FontStyle style, Common::Language lang) {
if (style >= kFontStyleMax)
return false;
Common::Array<LangExtraFont>::iterator entry = Common::find(_langExtraFonts.begin(), _langExtraFonts.end(), lang);
if (entry == _langExtraFonts.end())
return false;
TextData td = fontStyleToData(style);
return addFont(GUI::TextData::kTextDataExtraLang, Common::String(), entry->file(td), entry->sclFile(td), entry->fntSize(td));
}
bool ThemeEngine::addTextColor(TextColor colorId, int r, int g, int b) {
if (colorId >= kTextColorMAX)
return false;

View File

@ -27,6 +27,7 @@
#include "common/fs.h"
#include "common/hash-str.h"
#include "common/hashmap.h"
#include "common/language.h"
#include "common/list.h"
#include "common/str.h"
#include "common/rect.h"
@ -151,6 +152,7 @@ enum TextData {
kTextDataNormalFont,
kTextDataTooltip,
kTextDataConsole,
kTextDataExtraLang,
kTextDataMAX
};
@ -169,6 +171,34 @@ enum TextColor {
kTextColorMAX
};
class LangExtraFont {
public:
LangExtraFont(TextData textId, Common::Array<Common::Language> &lngs, const Common::String &file, const Common::String &scalableFile, int ps) : _langs(lngs) {
storeFileNames(textId, file, scalableFile, ps);
}
void storeFileNames(TextData textId, const Common::String &file, const Common::String &scalableFile, int ps) {
assert(textId < kTextDataMAX);
_fontFilesStd[textId] = file;
_fontFilesScalable[textId] = scalableFile;
_fontSize[textId] = ps;
}
bool operator==(Common::Language l) const {
return (Common::find(_langs.begin(), _langs.end(), l) != _langs.end());
}
Common::String file(TextData textId) const { return _fontFilesStd[textId]; }
Common::String sclFile(TextData textId) const { return _fontFilesScalable[textId]; }
int fntSize(TextData textId) const { return _fontSize[textId]; }
private:
Common::Array<Common::Language> _langs;
Common::String _fontFilesStd[kTextDataMAX];
Common::String _fontFilesScalable[kTextDataMAX];
int _fontSize[kTextDataMAX];
};
class ThemeEngine {
protected:
typedef Common::HashMap<Common::String, Graphics::Surface *> ImagesMap;
@ -241,6 +271,7 @@ public:
kFontStyleFixedItalic = 5, ///< Fixed size italic font.
kFontStyleTooltip = 6, ///< Tiny console font
kFontStyleConsole = 7, ///< Debug console font
kFontStyleLangExtra = 8, ///< Language specific font for ingame dialogs (e. g. the SCUMM pause/restart dialogs)
kFontStyleMax
};
@ -380,6 +411,8 @@ public:
return kTextDataTooltip;
if (font == kFontStyleConsole)
return kTextDataConsole;
if (font == kFontStyleLangExtra)
return kTextDataExtraLang;
return kTextDataDefault;
}
@ -520,6 +553,22 @@ public:
*/
bool addFont(TextData textId, const Common::String &language, const Common::String &file, const Common::String &scalableFile, const int pointsize);
/**
* Store language specific font names for ingame GUI dialogs which might require
* a different language than the current GUI setting
*
* @param textId, language, file, scalableFile, pointsize All exactly the same as with addFont()
*/
void storeFontNames(TextData textId, const Common::String &language, const Common::String &file, const Common::String &scalableFile, const int pointsize);
/**
* Load language specific font for ingame use
* @param style font style associated with the font file
* @param lang language associated with the font file
* @return
*/
bool loadExtraFont(FontStyle style, Common::Language lang);
/**
* Interface for the ThemeParser class: adds a text color value.
*
@ -741,6 +790,11 @@ protected:
/** Array of all font colors available. */
TextColorData *_textColors[kTextColorMAX];
/** Extra font file names for languages like Japanese, Korean or Chinese
* for use in ingame dialogs (like the SCUMM pause/restart dialogs)
*/
Common::Array<LangExtraFont> _langExtraFonts;
ImagesMap _bitmaps;
AImagesMap _abitmaps;
Graphics::PixelFormat _overlayFormat;

View File

@ -222,6 +222,9 @@ bool ThemeParser::parserCallback_language(ParserNode *node) {
scalableFile = getParentNode(node)->values["scalable_file"];
}
_theme->storeFontNames(textDataId, node->values["id"], file, scalableFile, pointsize);
if (!_theme->addFont(textDataId, node->values["id"], file, scalableFile, pointsize))
return parserError("Error loading localized Font in theme engine.");

View File

@ -293,24 +293,22 @@ void Widget::read(const Common::U32String &str) {
#pragma mark -
StaticTextWidget::StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::U32String &text, Graphics::TextAlign align, const Common::U32String &tooltip, ThemeEngine::FontStyle font)
StaticTextWidget::StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::U32String &text, Graphics::TextAlign align, const Common::U32String &tooltip, ThemeEngine::FontStyle font, Common::Language lang)
: Widget(boss, x, y, w, h, tooltip) {
setFlags(WIDGET_ENABLED);
_type = kStaticTextWidget;
_label = text;
_font = font;
_align = Graphics::convertTextAlignH(align, g_gui.useRTL() && _useRTL);
setFont(font, lang);
}
StaticTextWidget::StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::U32String &text, const Common::U32String &tooltip, ThemeEngine::FontStyle font)
StaticTextWidget::StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::U32String &text, const Common::U32String &tooltip, ThemeEngine::FontStyle font, Common::Language lang)
: Widget(boss, name, tooltip) {
setFlags(WIDGET_ENABLED | WIDGET_CLEARBG);
_type = kStaticTextWidget;
_label = text;
_align = Graphics::convertTextAlignH(g_gui.xmlEval()->getWidgetTextHAlign(name), g_gui.useRTL() && _useRTL);
_font = font;
setFont(font, lang);
}
void StaticTextWidget::setValue(int value) {
@ -342,6 +340,16 @@ void StaticTextWidget::drawWidget() {
);
}
void StaticTextWidget::setFont(ThemeEngine::FontStyle font, Common::Language lang) {
_font = font;
if (lang == Common::UNK_LANG)
return;
if (g_gui.theme()->loadExtraFont(font, lang))
_font = GUI::ThemeEngine::kFontStyleLangExtra;
}
#pragma mark -
ButtonWidget::ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::U32String &label, const Common::U32String &tooltip, uint32 cmd, uint8 hotkey)

View File

@ -200,9 +200,10 @@ protected:
Common::U32String _label;
Graphics::TextAlign _align;
ThemeEngine::FontStyle _font;
public:
StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::U32String &text, Graphics::TextAlign align, const Common::U32String &tooltip = Common::U32String(""), ThemeEngine::FontStyle font = ThemeEngine::kFontStyleBold);
StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::U32String &text, const Common::U32String &tooltip = Common::U32String(""), ThemeEngine::FontStyle font = ThemeEngine::kFontStyleBold);
StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::U32String &text, Graphics::TextAlign align, const Common::U32String &tooltip = Common::U32String(""), ThemeEngine::FontStyle font = ThemeEngine::kFontStyleBold, Common::Language lang = Common::UNK_LANG);
StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::U32String &text, const Common::U32String &tooltip = Common::U32String(""), ThemeEngine::FontStyle font = ThemeEngine::kFontStyleBold, Common::Language lang = Common::UNK_LANG);
void setValue(int value);
void setLabel(const Common::U32String &label);
void handleMouseEntered(int button) override { readLabel(); }
@ -213,6 +214,7 @@ public:
protected:
void drawWidget() override;
void setFont(ThemeEngine::FontStyle font, Common::Language lang);
};
/* ButtonWidget */