ASYLUM: Support rendering Chinese text

This commit is contained in:
Vladimir Serbinenko 2023-02-27 22:23:53 +01:00
parent c424bc3ea6
commit 6baaf9c54a
2 changed files with 114 additions and 9 deletions

View File

@ -30,12 +30,13 @@
#include "asylum/asylum.h"
#include "asylum/respack.h"
#if defined(USE_FREETYPE2)
#include "graphics/fonts/ttf.h"
#endif
namespace Asylum {
Text::Text(AsylumEngine *engine) : _vm(engine) {
_curFontFlags = 0;
_fontResource = nullptr;
_transTableNum = 0;
Text::Text(AsylumEngine *engine) : _vm(engine), _fontResource(nullptr), _transTableNum(0), _curFontFlags(0), _chineseFontLoadAttempted(false) {
}
Text::~Text() {
@ -59,23 +60,46 @@ ResourceId Text::loadFont(ResourceId resourceId) {
return previousFont;
}
void Text::loadChineseFont() {
if (_chineseFontLoadAttempted)
return;
_chineseFontLoadAttempted = true;
#if defined(USE_FREETYPE2)
_chineseFont.reset(Graphics::loadTTFFontFromArchive("NotoSansSC-Regular.otf", 32, Graphics::kTTFSizeModeCharacter, 0, Graphics::kTTFRenderModeLight));
#endif
}
void Text::setPosition(const Common::Point &point) {
_position = point;
}
int16 Text::getWidth(char c) {
if (!_fontResource)
error("[Text::getWidth] Font not initialized properly");
if (!_fontResource)
error("[Text::getWidth] Font not initialized properly");
GraphicFrame *font = _fontResource->getFrame((uint8)c);
GraphicFrame *font = _fontResource->getFrame((uint8)c);
return (int16)(font->surface.w + font->x - _curFontFlags);
return (int16)(font->surface.w + font->x - _curFontFlags);
}
int16 Text::getChineseWidth(const Common::U32String &utext) {
loadChineseFont();
if (!_chineseFont)
return 0;
return _chineseFont->getStringWidth(utext);
}
int16 Text::getWidth(const char *text) {
if (!_fontResource)
error("[Text::getWidth] font resource hasn't been loaded yet!");
if (_vm->getLanguage() == Common::Language::ZH_CHN) {
return getChineseWidth(Common::U32String(text, Common::CodePage::kGBK));
}
int16 width = 0;
char character = *text;
@ -97,6 +121,10 @@ int16 Text::getWidth(const char *text, int16 length) {
if (length == 0)
return 0;
if (_vm->getLanguage() == Common::Language::ZH_CHN) {
return getChineseWidth(Common::U32String(text, length, Common::CodePage::kGBK));
}
int16 width = 0;
char character = *text;
@ -135,10 +163,33 @@ void Text::drawChar(char character) {
_position.x += (int16)fontLetter->surface.w + fontLetter->x - _curFontFlags;
}
void Text::drawChinese(const Common::U32String &utext) {
loadChineseFont();
if (!_chineseFont)
return;
Graphics::Surface *surf = getScreen()->getSurface();
uint8 color = 0;
// TODO: Add more colors
switch (_fontResource->getResourceId()) {
default:
debug(5, "Unrecognized font resource 0x%x for string %s", _fontResource->getResourceId(), utext.encode().c_str());
color = 1;
break;
}
_chineseFont->drawString(surf, utext, _position.x, _position.y, surf->w - _position.x, color);
_position.x += _chineseFont->getStringWidth(utext);
}
void Text::draw(const char *text) {
if (!text)
return;
if (_vm->getLanguage() == Common::Language::ZH_CHN) {
drawChinese(Common::U32String(text, Common::CodePage::kGBK));
return;
}
if (_vm->getLanguage() == Common::HE_ISR)
text = Common::convertBiDiString(text, Common::kWindows1255).c_str();
while (*text) {
@ -154,6 +205,11 @@ void Text::draw(const char *text, int16 length) {
if (!text)
return;
if (_vm->getLanguage() == Common::Language::ZH_CHN) {
drawChinese(Common::U32String(text, length, Common::CodePage::kGBK));
return;
}
if (_vm->getLanguage() == Common::HE_ISR)
text = Common::convertBiDiString(Common::String(text, length), Common::kWindows1255).c_str();
for (int16 i = 0; i < length; i++)
@ -189,6 +245,48 @@ int16 Text::draw(int16 a1, int16 a2, TextCentering centering, const Common::Poin
if (!text || !*text)
return 0;
// TODO: Make non-Chinese into Graphics::Font as well.
if (_vm->getLanguage() == Common::Language::ZH_CHN) {
Common::Array<Common::U32String> lines;
Common::Point coords = point;
int16 printed = 0;
loadChineseFont();
if (!_chineseFont)
return 0;
char *buf = scumm_strdup(text);
for (char *ptr = buf; *ptr; ptr++)
if (*ptr == 1 || *ptr == 2) // Start of heading (SOH) or start of text (STX)
*ptr = '\n';
Common::U32String utext(buf, Common::CodePage::kGBK);
free(buf);
_chineseFont->wordWrapText(utext, width, lines);
for (int index = a1; index <= (a1 + a2) && index < (int)lines.size(); index++) {
switch (centering) {
default:
case kTextCalculate:
break;
case kTextCenter:
setPosition(coords + Common::Point((width - getChineseWidth(lines[index])) / 2, 0));
drawChinese(lines[index]);
break;
case kTextNormal:
setPosition(coords);
drawChinese(lines[index]);
break;
}
coords.y += spacing;
++printed;
}
return printed;
}
Common::Point coords = point;
int16 printed = 0;

View File

@ -24,6 +24,7 @@
#include "common/rect.h"
#include "common/scummsys.h"
#include "graphics/font.h"
#include "asylum/shared.h"
@ -47,7 +48,6 @@ public:
ResourceId loadFont(ResourceId resourceId);
void setPosition(const Common::Point &point);
int16 getWidth(char c);
int16 getWidth(const char *text);
int16 getWidth(const char *text, int16 length);
int16 getWidth(ResourceId resourceId);
@ -61,6 +61,7 @@ public:
void draw(const char *text, ResourceId fontResourceId, int16 y);
void draw(const char *text, int16 length);
int16 draw(TextCentering centering, const Common::Point &point, int16 spacing, int16 width, const char *text);
void drawChinese(const Common::U32String &utext);
int16 draw(int16 a1, int16 a2, TextCentering centering, const Common::Point &point, int16 spacing, int16 width, const char *text);
void drawCentered(const Common::Point &point, int16 width, const char *text);
@ -70,8 +71,12 @@ public:
void setTransTableNum(uint32 val) { _transTableNum = val; }
private:
int16 getWidth(char c);
void drawChar(char character);
int16 getChineseWidth(const Common::U32String &utext);
void loadChineseFont();
AsylumEngine *_vm;
GraphicResource *_fontResource;
@ -81,6 +86,8 @@ private:
Common::Point _position;
uint8 _curFontFlags;
Common::ScopedPtr<Graphics::Font> _chineseFont;
bool _chineseFontLoadAttempted;
};
} // end of namespace Asylum