1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-02-03 04:05:49 +01:00

implement utf8, part 2

This commit is contained in:
IntelOrca
2015-07-26 13:58:53 +01:00
parent c4b355f648
commit e21bea62ce
5 changed files with 213 additions and 79 deletions

View File

@@ -112,6 +112,7 @@
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="..\..\data\language\chinese_traditional.txt" />
<Text Include="..\..\data\language\dutch.txt" />
<Text Include="..\..\data\language\english_uk.txt" />
<Text Include="..\..\data\language\english_us.txt" />

View File

@@ -37,5 +37,8 @@
<Text Include="..\..\data\language\swedish.txt">
<Filter>Resource Files\Language</Filter>
</Text>
<Text Include="..\..\data\language\chinese_traditional.txt">
<Filter>Resource Files\Language</Filter>
</Text>
</ItemGroup>
</Project>

View File

@@ -29,6 +29,8 @@ static void ttf_draw_string(rct_drawpixelinfo *dpi, char *buffer, int colour, in
static bool _ttfInitialised = false;
static TTF_Font *_ttfFont = NULL;
static int _ttfFontOffsetX = 0;
static int _ttfFontOffsetY = 0;
/**
*
@@ -1267,12 +1269,14 @@ bool ttf_initialise()
if (TTF_Init() != 0)
return false;
_ttfFont = TTF_OpenFont("C:\\Windows\\Fonts\\tahoma.ttf", 11);
_ttfFont = TTF_OpenFont("C:\\Windows\\Fonts\\msyh.ttc", 11);
if (_ttfFont == NULL) {
TTF_Quit();
return false;
}
_ttfFontOffsetX = 0;
_ttfFontOffsetY = -2;
_ttfInitialised = true;
}
return true;
@@ -1290,6 +1294,8 @@ void ttf_dispose()
}
enum {
TEXT_DRAW_FLAG_OUTLINE = 1 << 1,
TEXT_DRAW_FLAG_TTF = 1 << 30,
TEXT_DRAW_FLAG_NO_DRAW = 1 << 31
};
@@ -1297,14 +1303,50 @@ typedef struct {
int x;
int y;
int flags;
uint8 colour;
uint8 palette[8];
uint16 font_sprite_base;
} text_draw_info;
static void ttf_draw_string_raw(rct_drawpixelinfo *dpi, const utf8 *text, text_draw_info *info)
static bool utf8_is_format_code(int codepoint)
{
if (codepoint < 32) return true;
if (codepoint >= 123 && codepoint <= 155) return true;
return false;
}
static void ttf_draw_string_raw_sprite(rct_drawpixelinfo *dpi, const utf8 *text, text_draw_info *info)
{
const utf8 *ch = text;
int codepoint;
while (!utf8_is_format_code(codepoint = utf8_get_next(ch, &ch))) {
uint32 charOffset = info->font_sprite_base + codepoint - 32;
int charWidth = RCT2_ADDRESS(RCT2_ADDRESS_FONT_CHAR_WIDTH, uint8)[charOffset] & 0xFF;
if (!(info->flags & TEXT_DRAW_FLAG_NO_DRAW)) {
RCT2_GLOBAL(0x009ABDA4, uint8*) = (uint8*)&info->palette;
RCT2_GLOBAL(0x00EDF81C, uint32) = (IMAGE_TYPE_USE_PALETTE << 28);
gfx_draw_sprite_palette_set(dpi, SPR_CHAR_START + ((IMAGE_TYPE_USE_PALETTE << 28) | charOffset), info->x, info->y, info->palette, NULL);
}
info->x += charWidth;
};
}
static void ttf_draw_string_raw_ttf(rct_drawpixelinfo *dpi, const utf8 *text, text_draw_info *info)
{
if (!_ttfInitialised && !ttf_initialise())
return;
int fontStyle = TTF_GetFontStyle(_ttfFont);
int newFontStyle = 0;
if (info->flags & TEXT_DRAW_FLAG_OUTLINE) {
newFontStyle |= TTF_STYLE_BOLD;
}
if (fontStyle != newFontStyle) {
TTF_SetFontStyle(_ttfFont, newFontStyle);
}
if (info->flags & TEXT_DRAW_FLAG_NO_DRAW) {
int width, height;
@@ -1312,7 +1354,7 @@ static void ttf_draw_string_raw(rct_drawpixelinfo *dpi, const utf8 *text, text_d
info->x += width;
return;
} else {
uint8 colour = info->colour;
uint8 colour = info->palette[1];
SDL_Color c = { 0, 0, 0, 255 };
SDL_Surface *surface = TTF_RenderUTF8_Solid(_ttfFont, text, c);
if (surface == NULL)
@@ -1323,10 +1365,17 @@ static void ttf_draw_string_raw(rct_drawpixelinfo *dpi, const utf8 *text, text_d
return;
}
int drawX = info->x + _ttfFontOffsetX;
int drawY = info->y + _ttfFontOffsetY;
int width = surface->w;
int height = surface->h;
int skipX = info->x - dpi->x;
int skipY = info->y - dpi->y;
int overflowX = (dpi->x + dpi->width) - (drawX + width);
int overflowY = (dpi->y + dpi->height) - (drawY + height);
if (overflowX < 0) width += overflowX;
if (overflowY < 0) height += overflowY;
int skipX = drawX - dpi->x;
int skipY = drawY - dpi->y;
info->x += width;
uint8 *src = surface->pixels;
@@ -1335,11 +1384,14 @@ static void ttf_draw_string_raw(rct_drawpixelinfo *dpi, const utf8 *text, text_d
if (skipX < 0) {
width += skipX;
src += -skipX;
skipX = 0;
}
if (skipY < 0) {
height += skipY;
src += (-skipY * surface->pitch);
skipY = 0;
}
dst += skipX;
dst += skipY * (dpi->width + dpi->pitch);
@@ -1360,11 +1412,13 @@ static void ttf_draw_string_raw(rct_drawpixelinfo *dpi, const utf8 *text, text_d
}
}
static bool utf8_is_format_code(int codepoint)
static void ttf_draw_string_raw(rct_drawpixelinfo *dpi, const utf8 *text, text_draw_info *info)
{
if (codepoint < 32) return true;
if (codepoint >= 123 && codepoint <= 155) return true;
return false;
if (info->flags & TEXT_DRAW_FLAG_TTF) {
ttf_draw_string_raw_ttf(dpi, text, info);
} else {
ttf_draw_string_raw_sprite(dpi, text, info);
}
}
static const utf8 *ttf_process_format_code(rct_drawpixelinfo *dpi, const utf8 *text, text_draw_info *info)
@@ -1378,65 +1432,88 @@ static const utf8 *ttf_process_format_code(rct_drawpixelinfo *dpi, const utf8 *t
info->x += *nextCh++;
break;
case FORMAT_ADJUST_PALETTE:
{
uint16 eax = palette_to_g1_offset[*nextCh++];
rct_g1_element *g1Element = &g1Elements[eax];
uint32 ebx = g1Element->offset[249] + 256;
if (!(info->flags & TEXT_DRAW_FLAG_OUTLINE)) {
ebx = ebx & 0xFF;
}
info->palette[1] = ebx & 0xFF;
info->palette[2] = (ebx >> 8) & 0xFF;
// Adjust the text palette
memcpy(info->palette + 3, &(g1Element->offset[247]), 2);
memcpy(info->palette + 5, &(g1Element->offset[250]), 2);
// Set the palette pointer
RCT2_GLOBAL(0x009ABDA4, uint32) = (uint32)&info->palette;
break;
}
case 3:
case 4:
nextCh++;
break;
case FORMAT_NEWLINE:
if (info->font_sprite_base <= 224) { info->y += 28; }
else if (info->font_sprite_base <= 448) { info->y += 24; }
else { info->y += 18; }
break;
case FORMAT_NEWLINE_SMALLER:
break;
case FORMAT_TINYFONT:
info->font_sprite_base = 448;
break;
case FORMAT_BIGFONT:
info->font_sprite_base = 672;
break;
case FORMAT_MEDIUMFONT:
info->font_sprite_base = 224;
break;
case FORMAT_SMALLFONT:
info->font_sprite_base = 0;
break;
case FORMAT_OUTLINE:
info->flags |= TEXT_DRAW_FLAG_OUTLINE;
break;
case FORMAT_OUTLINE_OFF:
info->flags &= ~TEXT_DRAW_FLAG_OUTLINE;
break;
case FORMAT_WINDOW_COLOUR_1:
{
uint8 palette[5];
uint16 flags = info->flags;
colour_char_window(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_WINDOW_COLOUR_1, uint8) - FORMAT_COLOUR_CODE_START, &flags, palette);
info->colour = palette[1];
colour_char_window(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_WINDOW_COLOUR_1, uint8), &flags, info->palette);
break;
}
case FORMAT_WINDOW_COLOUR_2:
{
uint8 palette[5];
uint16 flags = info->flags;
colour_char_window(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_WINDOW_COLOUR_2, uint8) - FORMAT_COLOUR_CODE_START, &flags, palette);
info->colour = palette[1];
colour_char_window(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_WINDOW_COLOUR_2, uint8), &flags, info->palette);
break;
}
case FORMAT_WINDOW_COLOUR_3:
{
uint8 palette[5];
uint16 flags = info->flags;
colour_char_window(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_WINDOW_COLOUR_3, uint8) - FORMAT_COLOUR_CODE_START, &flags, palette);
info->colour = palette[1];
colour_char_window(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_WINDOW_COLOUR_3, uint8), &flags, info->palette);
break;
}
case 0x10:
break;
case FORMAT_INLINE_SPRITE:
// g1Element = g1Elements[*((uint32*)(nextCh)) & 0x7FFFF];
// width += g1Element.width;
{
nextCh += 4;
uint32 imageId = *((uint32*)(nextCh - 3));
rct_g1_element *g1Element = &g1Elements[imageId & 0x7FFFF];
if (!(info->flags & TEXT_DRAW_FLAG_NO_DRAW)) {
gfx_draw_sprite(dpi, imageId, info->x, info->y, 0);
}
info->x += g1Element->width;
break;
}
default:
if (codepoint >= FORMAT_COLOUR_CODE_START && codepoint <= FORMAT_COLOUR_CODE_END) {
if (info->flags == 1) {
}
uint8 palette[5];
uint16 flags = info->flags;
colour_char(codepoint - FORMAT_COLOUR_CODE_START, &flags, palette);
info->colour = palette[1];
colour_char(codepoint - FORMAT_COLOUR_CODE_START, &flags, info->palette);
} else if (codepoint <= 0x16) { //case 0x11? FORMAT_NEW_LINE_X_Y
nextCh += 2;
} else {
@@ -1468,24 +1545,86 @@ static const utf8 *ttf_process_glyph_run(rct_drawpixelinfo *dpi, const utf8 *tex
}
}
static void ttf_draw_string(rct_drawpixelinfo *dpi, char *text, int colour, int x, int y)
static void ttf_process_string(rct_drawpixelinfo *dpi, const utf8 *text, text_draw_info *info)
{
text_draw_info info;
info.colour = colour;
info.flags = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_FLAGS, uint16);
info.x = x;
info.y = y;
const utf8 *ch = text;
const utf8 *nextCh;
int codepoint;
while ((codepoint = utf8_get_next(ch, &nextCh)) != 0) {
if (utf8_is_format_code(codepoint)) {
ch = ttf_process_format_code(dpi, ch, &info);
ch = ttf_process_format_code(dpi, ch, info);
} else {
ch = ttf_process_glyph_run(dpi, ch, &info);
ch = ttf_process_glyph_run(dpi, ch, info);
}
}
}
static void ttf_process_initial_colour(int colour, text_draw_info *info)
{
if (colour != 254 && colour != 255) {
info->flags &= ~(1 | 2 | 4 | 8);
if (info->font_sprite_base < 0) {
info->flags |= 4;
if (info->font_sprite_base != -1) {
info->flags |= 8;
}
info->font_sprite_base = 224;
}
if (colour & (1 << 5)) {
info->flags |= TEXT_DRAW_FLAG_OUTLINE;
}
colour &= ~(1 << 5);
if (!(colour & (1 << 6))) {
if (!(info->flags & 1)) {
uint16 flags = info->flags;
colour_char_window(colour, &flags, (uint8*)&info->palette);
}
} else {
info->flags |= 1;
colour &= 0x1F;
uint32 eax;
if (info->flags & 4) {
if (info->flags & 8) {
eax = RCT2_ADDRESS(0x0141FC48, uint8)[colour * 8];
eax = eax << 16;
eax = eax | RCT2_ADDRESS(0x0141FC46, uint8)[colour * 8];
} else {
eax = RCT2_ADDRESS(0x0141FC49, uint8)[colour * 8];
eax = eax << 16;
eax = eax | RCT2_ADDRESS(0x0141FC47, uint8)[colour * 8];
}
} else {
eax = RCT2_ADDRESS(0x0141FC4A, uint8)[colour * 8];
eax = eax << 16;
eax = eax | RCT2_ADDRESS(0x0141FC48, uint8)[colour * 8];
}
// Adjust text palette. Store current colour? ;
info->palette[1] = eax & 0xFF;
info->palette[2] = (eax >> 8) & 0xFF;
info->palette[3] = (eax >> 16) & 0xFF;
info->palette[4] = (eax >> 24) & 0xFF;
RCT2_GLOBAL(0x009ABDA4, uint8*) = (uint8*)&info->palette;
eax = 0;
}
}
}
static void ttf_draw_string(rct_drawpixelinfo *dpi, char *text, int colour, int x, int y)
{
text_draw_info info;
info.font_sprite_base = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16);
info.flags = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_FLAGS, uint16);
info.x = x;
info.y = y;
info.flags |= TEXT_DRAW_FLAG_TTF;
memset(info.palette, 0, sizeof(info.palette));
ttf_process_initial_colour(colour, &info);
ttf_process_string(dpi, text, &info);
gLastDrawStringX = info.x;
gLastDrawStringY = info.y;
@@ -1494,23 +1633,15 @@ static void ttf_draw_string(rct_drawpixelinfo *dpi, char *text, int colour, int
static int ttf_get_string_width(const utf8 *text)
{
text_draw_info info;
info.colour = 0;
info.font_sprite_base = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16);
info.flags = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_FLAGS, uint16);
info.x = 0;
info.y = 0;
info.flags |= TEXT_DRAW_FLAG_TTF;
info.flags |= TEXT_DRAW_FLAG_NO_DRAW;
const utf8 *ch = text;
const utf8 *nextCh;
int codepoint;
while ((codepoint = utf8_get_next(ch, &nextCh)) != 0) {
if (utf8_is_format_code(codepoint)) {
ch = ttf_process_format_code(NULL, ch, &info);
} else {
ch = ttf_process_glyph_run(NULL, ch, &info);
}
}
ttf_process_string(NULL, text, &info);
return info.x;
}

View File

@@ -34,33 +34,35 @@ typedef struct {
} language_data;
const char *language_names[LANGUAGE_COUNT] = {
"", // LANGUAGE_UNDEFINED
"English (UK)", // LANGUAGE_ENGLISH_UK
"English (US)", // LANGUAGE_ENGLISH_US
"Deutsch", // LANGUAGE_GERMAN
"Nederlands", // LANGUAGE_DUTCH
"Fran\u00E7ais", // LANGUAGE_FRENCH
"Magyar", // LANGUAGE_HUNGARIAN
"Polski", // LANGUAGE_POLISH
"Espa\u00F1ol", // LANGUAGE_SPANISH
"Svenska", // LANGUAGE_SWEDISH
"Italiano", // LANGUAGE_ITALIAN
"Portug\u00CAs (BR)"// LANGUAGE_PORTUGUESE_BR
"", // LANGUAGE_UNDEFINED
"English (UK)", // LANGUAGE_ENGLISH_UK
"English (US)", // LANGUAGE_ENGLISH_US
"Deutsch", // LANGUAGE_GERMAN
"Nederlands", // LANGUAGE_DUTCH
"Fran\u00E7ais", // LANGUAGE_FRENCH
"Magyar", // LANGUAGE_HUNGARIAN
"Polski", // LANGUAGE_POLISH
"Espa\u00F1ol", // LANGUAGE_SPANISH
"Svenska", // LANGUAGE_SWEDISH
"Italiano", // LANGUAGE_ITALIAN
"Portug\u00CAs (BR)", // LANGUAGE_PORTUGUESE_BR
"Chinese Traditional" // LANGUAGE_CHINESE_TRADITIONAL
};
const char *language_filenames[LANGUAGE_COUNT] = {
"", // LANGUAGE_UNDEFINED
"english_uk", // LANGUAGE_ENGLISH_UK
"english_us", // LANGUAGE_ENGLISH_US
"german", // LANGUAGE_GERMAN
"dutch", // LANGUAGE_DUTCH
"french", // LANGUAGE_FRENCH
"hungarian", // LANGUAGE_HUNGARIAN
"polish", // LANGUAGE_POLISH
"spanish_sp", // LANGUAGE_SPANISH
"swedish", // LANGUAGE_SWEDISH
"italian", // LANGUAGE_ITALIAN
"portuguese_br" // LANGUAGE_PORTUGUESE_BR
"", // LANGUAGE_UNDEFINED
"english_uk", // LANGUAGE_ENGLISH_UK
"english_us", // LANGUAGE_ENGLISH_US
"german", // LANGUAGE_GERMAN
"dutch", // LANGUAGE_DUTCH
"french", // LANGUAGE_FRENCH
"hungarian", // LANGUAGE_HUNGARIAN
"polish", // LANGUAGE_POLISH
"spanish_sp", // LANGUAGE_SPANISH
"swedish", // LANGUAGE_SWEDISH
"italian", // LANGUAGE_ITALIAN
"portuguese_br", // LANGUAGE_PORTUGUESE_BR
"chinese_traditional" // LANGUAGE_CHINESE_TRADITIONAL
};
int gCurrentLanguage = LANGUAGE_UNDEFINED;
@@ -101,7 +103,7 @@ uint32 utf8_get_next(const utf8 *char_ptr, const utf8 **nextchar_ptr)
utf8 *utf8_write_codepoint(utf8 *dst, uint32 codepoint)
{
if (codepoint <= 0x7F) {
dst[0] = codepoint;
dst[0] = (utf8)codepoint;
return dst + 1;
} else if (codepoint <= 0x7FF) {
dst[0] = 0xC0 | ((codepoint >> 6) & 0x1F);
@@ -231,12 +233,8 @@ static int language_open_file(const char *filename, language_data *language)
// Handle UTF-8
char *srcNext;
int utf8Char = utf8_get_next(src, &srcNext);
uint32 utf8Char = utf8_get_next(src, &srcNext);
i += srcNext - src - 1;
if (utf8Char > 0xFF)
utf8Char = '?';
else if (utf8Char > 0x7F)
utf8Char &= 0xFF;
switch (mode) {
case 0:
@@ -267,7 +265,7 @@ static int language_open_file(const char *filename, language_data *language)
*dst = 0;
mode = 0;
} else {
*dst++ = utf8Char;
dst = utf8_write_codepoint(dst, utf8Char);
}
break;
case 2:

View File

@@ -36,6 +36,7 @@ enum {
LANGUAGE_SWEDISH,
LANGUAGE_ITALIAN,
LANGUAGE_PORTUGUESE_BR,
LANGUAGE_CHINESE_TRADITIONAL,
LANGUAGE_COUNT
};