implement utf8, part 6

This commit is contained in:
IntelOrca 2015-07-27 14:26:22 +01:00
parent 795c01cab5
commit d6a7025a3a
8 changed files with 7623 additions and 120 deletions

View File

@ -58,6 +58,7 @@
<ClCompile Include="..\src\interface\widget.c" />
<ClCompile Include="..\src\interface\window.c" />
<ClCompile Include="..\src\intro.c" />
<ClCompile Include="..\src\localisation\convert.c" />
<ClCompile Include="..\src\localisation\currency.c" />
<ClCompile Include="..\src\localisation\date.c" />
<ClCompile Include="..\src\localisation\language.c" />

View File

@ -495,6 +495,9 @@
<ClCompile Include="..\src\cheats.c">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="..\src\localisation\convert.c">
<Filter>Source\Localisation</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\management\award.h">

View File

@ -4,15 +4,13 @@
<LocalDebuggerWorkingDirectory>$(TargetDir)</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerCommand>$(TargetDir)\openrct2.exe</LocalDebuggerCommand>
<LocalDebuggerCommandArguments>
</LocalDebuggerCommandArguments>
<LocalDebuggerCommandArguments>"C:\Program Files (x86)\Infogrames\RollerCoaster Tycoon 2\Scenarios\Electric Fields.SC6"</LocalDebuggerCommandArguments>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release with Tests|Win32'">
<LocalDebuggerWorkingDirectory>$(TargetDir)</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerCommand>$(TargetDir)\openrct2.exe</LocalDebuggerCommand>
<LocalDebuggerCommandArguments>
</LocalDebuggerCommandArguments>
<LocalDebuggerCommandArguments>"C:\Program Files (x86)\Infogrames\RollerCoaster Tycoon 2\Scenarios\Electric Fields.SC6"</LocalDebuggerCommandArguments>
</PropertyGroup>
<PropertyGroup>
<ShowAllFiles>false</ShowAllFiles>
@ -21,5 +19,6 @@
<LocalDebuggerCommand>$(TargetDir)\openrct2.exe</LocalDebuggerCommand>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerWorkingDirectory>$(TargetDir)</LocalDebuggerWorkingDirectory>
<LocalDebuggerCommandArguments>"C:\Program Files (x86)\Infogrames\RollerCoaster Tycoon 2\Scenarios\Electric Fields.SC6"</LocalDebuggerCommandArguments>
</PropertyGroup>
</Project>

View File

@ -299,121 +299,109 @@ int gfx_clip_string(utf8 *text, int width)
* num_lines (edi) - out
* font_height (ebx) - out
*/
int gfx_wrap_string(char* buffer, int width, int* num_lines, int* font_height)
int gfx_wrap_string(utf8 *text, int width, int *num_lines, int *font_height)
{
unsigned int line_width = 0;
unsigned int max_width = 0;
rct_g1_element g1_element;
int lineWidth = 0;
int maxWidth = 0;
rct_g1_element g1Element;
*num_lines = 0;
*font_height = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16);
// Pointer to the start of the current word
unsigned char* curr_word = NULL;
utf8 *currentWord = NULL;
// Width of line up to current word
unsigned int curr_width;
for (unsigned char* curr_char = buffer; *curr_char != (uint8)0; curr_char++) {
int currentWidth;
utf8 *ch = text;
utf8 *lastCh;
int codepoint;
while ((codepoint = utf8_get_next(ch, &lastCh)) != 0) {
// Remember start of current word and line width up to this word
if (*curr_char == ' ') {
curr_word = curr_char;
curr_width = line_width;
}
// 5 is RCT2 new line?
if (*curr_char != 5) {
if (*curr_char < ' ') {
switch(*curr_char) {
case FORMAT_MOVE_X:
case FORMAT_ADJUST_PALETTE:
case 3:
case 4:
curr_char++;
continue;
case FORMAT_NEWLINE:
case FORMAT_NEWLINE_SMALLER:
continue;
case FORMAT_TINYFONT:
*font_height = 0x1C0;
continue;
case FORMAT_BIGFONT:
*font_height = 0x2A0;
continue;
case FORMAT_MEDIUMFONT:
*font_height = 0xE0;
continue;
case FORMAT_SMALLFONT:
*font_height = 0;
continue;
case FORMAT_OUTLINE:
case FORMAT_OUTLINE_OFF:
case FORMAT_WINDOW_COLOUR_1:
case FORMAT_WINDOW_COLOUR_2:
case FORMAT_WINDOW_COLOUR_3:
case 0x10:
continue;
case FORMAT_INLINE_SPRITE:
g1_element = g1Elements[*((uint32*)(curr_char + 1)) & 0x7FFFF];
line_width += g1_element.width;
curr_char += 4;
break;
default:
if (*curr_char <= 0x16) {
curr_char += 2;
continue;
}
curr_char += 4;
continue;
}
}
line_width += _spriteFontCharacterWidths[*font_height + (*curr_char - 0x20)];
if ((int)line_width <= width) {
continue;
}
if (curr_word == 0) {
curr_char--;
unsigned char* old_char = curr_char;
unsigned char swap_char = 0;
unsigned char temp;
// Insert NULL at current character
// Aboslutely no guarantee that this won't overrun!
do {
temp = swap_char;
swap_char = *curr_char;
*curr_char = temp;
curr_char++;
} while(swap_char != 0);
*curr_char = swap_char;
curr_char = old_char;
curr_char++;
*num_lines += 1;
if (line_width > max_width) {
max_width = line_width;
}
line_width = 0;
curr_word = 0;
continue;
}
curr_char = curr_word;
line_width = curr_width;
}
*num_lines += 1;
*curr_char = 0;
if (line_width > max_width) {
max_width = line_width;
if (codepoint == ' ') {
currentWord = ch;
currentWidth = lineWidth;
}
if (utf8_is_format_code(codepoint)) {
switch (codepoint) {
case FORMAT_MOVE_X:
case FORMAT_ADJUST_PALETTE:
case 3:
case 4:
ch++;
break;
case FORMAT_NEWLINE:
case FORMAT_NEWLINE_SMALLER:
*num_lines += 1;
*ch = 0;
if (lineWidth > maxWidth) {
maxWidth = lineWidth;
}
lineWidth = 0;
currentWord = 0;
break;
case FORMAT_TINYFONT:
*font_height = FONT_SPRITE_BASE_TINY;
break;
case FORMAT_SMALLFONT:
*font_height = FONT_SPRITE_BASE_SMALL;
break;
case FORMAT_MEDIUMFONT:
*font_height = FONT_SPRITE_BASE_MEDIUM;
break;
case FORMAT_BIGFONT:
*font_height = FONT_SPRITE_BASE_BIG;
break;
case FORMAT_OUTLINE:
case FORMAT_OUTLINE_OFF:
case FORMAT_WINDOW_COLOUR_1:
case FORMAT_WINDOW_COLOUR_2:
case FORMAT_WINDOW_COLOUR_3:
case 0x10:
break;
case FORMAT_INLINE_SPRITE:
g1Element = g1Elements[*((uint32*)(ch + 1)) & 0x7FFFF];
lineWidth += g1Element.width;
lastCh += 4;
break;
default:
if (codepoint < FORMAT_COLOUR_CODE_START || codepoint > FORMAT_COLOUR_CODE_END) {
if (codepoint <= 0x16) {
lastCh += 2;
} else {
lastCh += 4;
}
}
break;
}
ch = lastCh;
} else {
lineWidth += _spriteFontCharacterWidths[*font_height + utf8_get_sprite_offset_for_codepoint(codepoint)];
if ((int)lineWidth <= width) {
ch = lastCh;
} else if (currentWord == NULL) {
// Single word is longer than line, insert null terminator
utf8 *end = get_string_end(ch);
memmove(ch + 1, ch, end - ch + 1);
*ch++ = 0;
maxWidth = max(maxWidth, lineWidth);
*num_lines += 1;
lineWidth = 0;
currentWord = NULL;
} else {
ch = currentWord;
*ch++ = 0;
maxWidth = max(maxWidth, currentWidth);
*num_lines += 1;
lineWidth = 0;
currentWord = NULL;
}
}
line_width = 0;
curr_word = 0;
}
if (max_width == 0)return line_width;
return max_width;
return maxWidth == 0 ? lineWidth : maxWidth;
}
@ -1018,15 +1006,6 @@ static void ttf_draw_string_raw_ttf(rct_drawpixelinfo *dpi, const utf8 *text, te
break;
}
int fontStyle = TTF_GetFontStyle(font);
int newFontStyle = 0;
if (info->flags & TEXT_DRAW_FLAG_OUTLINE) {
newFontStyle |= TTF_STYLE_BOLD;
}
if (fontStyle != newFontStyle) {
TTF_SetFontStyle(font, newFontStyle);
}
if (info->flags & TEXT_DRAW_FLAG_NO_DRAW) {
int width, height;
@ -1079,7 +1058,12 @@ static void ttf_draw_string_raw_ttf(rct_drawpixelinfo *dpi, const utf8 *text, te
int dstScanSkip = dpi->width + dpi->pitch - width;
for (int yy = 0; yy < height; yy++) {
for (int xx = 0; xx < width; xx++) {
if (*src != 0) *dst = colour;
if (*src != 0) {
*dst = colour;
if (info->flags & TEXT_DRAW_FLAG_OUTLINE) {
*(dst + width + dstScanSkip + 1) = 0;
}
}
src++;
dst++;
}

7477
src/localisation/convert.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -99,6 +99,9 @@ uint32 utf8_get_next(const utf8 *char_ptr, const utf8 **nextchar_ptr)
} else if ((char_ptr[0] & 0xF0) == 0xE0) {
result = ((char_ptr[0] & 0x0F) << 12) | ((char_ptr[1] & 0x3F) << 6) | (char_ptr[2] & 0x3F);
numBytes = 3;
} else if ((char_ptr[0] & 0xF8) == 0xF0) {
result = ((char_ptr[0] & 0x07) << 18) | ((char_ptr[1] & 0x3F) << 12) | ((char_ptr[1] & 0x3F) << 6) | (char_ptr[2] & 0x3F);
numBytes = 4;
} else {
// TODO 4 bytes
result = ' ';
@ -384,6 +387,8 @@ static utf8 *convert_multibyte_charset(const char *src)
uint8 a = *ch++;
uint8 b = *ch++;
uint16 codepoint = (a << 8) | b;
codepoint = encoding_convert_gb2312_to_unicode(codepoint - 0x8080);
dst = utf8_write_codepoint(dst, codepoint);
} else {
*dst++ = *ch++;
@ -391,7 +396,8 @@ static utf8 *convert_multibyte_charset(const char *src)
}
*dst++ = 0;
int actualLength = dst - buffer;
return realloc(buffer, actualLength);
buffer = realloc(buffer, actualLength);
return buffer;
}
static bool rct2_language_is_multibyte_charset(int languageId)

View File

@ -180,7 +180,7 @@ int utf8_get_sprite_offset_for_codepoint(int codepoint)
case FORMAT_TICK: return 172 - 32;
case FORMAT_CROSS: return 173 - 32;
default:
if (codepoint > 224) codepoint = ' ';
if (codepoint > 224) codepoint = 'W';
return codepoint - 32;
}
}
@ -797,6 +797,36 @@ void generate_string_file()
fclose(f);
}
utf8 *get_string_end(utf8 *text)
{
int codepoint;
const utf8 *ch = text;
while ((codepoint = utf8_get_next(ch, &ch)) != 0) {
if (utf8_is_format_code(codepoint)) {
switch (codepoint) {
case FORMAT_MOVE_X:
case FORMAT_ADJUST_PALETTE:
case 3:
case 4:
ch++;
break;
case FORMAT_INLINE_SPRITE:
ch += 4;
break;
default:
if (codepoint <= 22) {
ch += 2;
} else {
ch += 4;
}
break;
}
}
}
return ch - 1;
}
/**
* Return the length of the string in buffer.
* note you can't use strlen as there can be inline sprites!

View File

@ -35,6 +35,7 @@ void format_string_raw(char *dest, char *src, void *args);
void format_string_to_upper(char *dest, rct_string_id format, void *args);
void generate_string_file();
void error_string_quit(int error, rct_string_id format);
utf8 *get_string_end(utf8 *text);
int get_string_length(const utf8* buffer);
void user_string_clear_all();
@ -45,6 +46,8 @@ bool is_user_string_id(rct_string_id stringId);
utf8 *win1252_to_utf8_alloc(const char *src);
int win1252_to_utf8(utf8string dst, const char *src, int maxBufferLength);
wchar_t encoding_convert_gb2312_to_unicode(wchar_t gb2312);
#define MAX_USER_STRINGS 1024
#define USER_STRING_MAX_LENGTH 32