mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-23 15:52:55 +01:00
implement utf8, part 3
This commit is contained in:
@@ -28,17 +28,28 @@ static int ttf_get_string_width(const utf8 *text);
|
||||
static void ttf_draw_string(rct_drawpixelinfo *dpi, char *buffer, int colour, int x, int y);
|
||||
|
||||
static bool _ttfInitialised = false;
|
||||
static TTF_Font *_ttfFont = NULL;
|
||||
static TTF_Font *_ttfFont[4] = { NULL };
|
||||
static int _ttfFontOffsetX = 0;
|
||||
static int _ttfFontOffsetY = 0;
|
||||
|
||||
static const int TTFFontSizes[] = { 7, 9, 11, 13 };
|
||||
|
||||
enum {
|
||||
FONT_SPRITE_BASE_TINY = 448,
|
||||
FONT_SPRITE_BASE_SMALL = 0,
|
||||
FONT_SPRITE_BASE_MEDIUM = 224,
|
||||
FONT_SPRITE_BASE_BIG = 672
|
||||
};
|
||||
|
||||
static uint8 *_spriteFontCharacterWidths = (uint8*)RCT2_ADDRESS_FONT_CHAR_WIDTH;
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006C19AC
|
||||
*/
|
||||
void gfx_load_character_widths(){
|
||||
|
||||
uint8* char_width_pointer = RCT2_ADDRESS(RCT2_ADDRESS_FONT_CHAR_WIDTH, uint8);
|
||||
uint8* char_width_pointer = _spriteFontCharacterWidths;
|
||||
for (int char_set_offset = 0; char_set_offset < 4*0xE0; char_set_offset+=0xE0){
|
||||
for (uint8 c = 0; c < 0xE0; c++, char_width_pointer++){
|
||||
rct_g1_element g1 = g1Elements[c + SPR_CHAR_START + char_set_offset];
|
||||
@@ -108,7 +119,7 @@ int gfx_get_string_width_new_lined(char* buffer){
|
||||
for (uint8* curr_char = (uint8*)buffer; *curr_char != (uint8)0; curr_char++) {
|
||||
|
||||
if (*curr_char >= 0x20) {
|
||||
width += RCT2_ADDRESS(RCT2_ADDRESS_FONT_CHAR_WIDTH, uint8)[*current_font_sprite_base + (*curr_char - 0x20)];
|
||||
width += _spriteFontCharacterWidths[*current_font_sprite_base + (*curr_char - 0x20)];
|
||||
continue;
|
||||
}
|
||||
switch (*curr_char) {
|
||||
@@ -175,72 +186,7 @@ int gfx_get_string_width_new_lined(char* buffer){
|
||||
*/
|
||||
int gfx_get_string_width(char* buffer)
|
||||
{
|
||||
if (_ttfInitialised) {
|
||||
return ttf_get_string_width(buffer);
|
||||
}
|
||||
|
||||
// Current font sprites
|
||||
uint16* current_font_sprite_base;
|
||||
// Width of string
|
||||
int width;
|
||||
rct_g1_element g1_element;
|
||||
|
||||
current_font_sprite_base = RCT2_ADDRESS(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16);
|
||||
width = 0;
|
||||
|
||||
for (uint8* curr_char = (uint8*)buffer; *curr_char != (uint8)0; curr_char++) {
|
||||
|
||||
if (*curr_char >= 0x20) {
|
||||
width += RCT2_ADDRESS(RCT2_ADDRESS_FONT_CHAR_WIDTH, uint8)[*current_font_sprite_base + (*curr_char - 0x20)];
|
||||
continue;
|
||||
}
|
||||
switch(*curr_char) {
|
||||
case FORMAT_MOVE_X:
|
||||
curr_char++;
|
||||
width = *curr_char;
|
||||
break;
|
||||
case FORMAT_ADJUST_PALETTE:
|
||||
case 3:
|
||||
case 4:
|
||||
curr_char++;
|
||||
break;
|
||||
case FORMAT_NEWLINE:
|
||||
case FORMAT_NEWLINE_SMALLER:
|
||||
continue;
|
||||
case FORMAT_TINYFONT:
|
||||
*current_font_sprite_base = 0x1C0;
|
||||
break;
|
||||
case FORMAT_BIGFONT:
|
||||
*current_font_sprite_base = 0x2A0;
|
||||
break;
|
||||
case FORMAT_MEDIUMFONT:
|
||||
*current_font_sprite_base = 0x0E0;
|
||||
break;
|
||||
case FORMAT_SMALLFONT:
|
||||
*current_font_sprite_base = 0;
|
||||
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:
|
||||
continue;
|
||||
case FORMAT_INLINE_SPRITE:
|
||||
g1_element = g1Elements[*((uint32*)(curr_char + 1)) & 0x7FFFF];
|
||||
width += g1_element.width;
|
||||
curr_char += 4;
|
||||
break;
|
||||
default:
|
||||
if (*curr_char <= 0x16) { //case 0x11? FORMAT_NEW_LINE_X_Y
|
||||
curr_char += 2;
|
||||
continue;
|
||||
}
|
||||
curr_char += 4;//never happens?
|
||||
break;
|
||||
}
|
||||
}
|
||||
return width;
|
||||
return ttf_get_string_width(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -250,57 +196,52 @@ int gfx_get_string_width(char* buffer)
|
||||
* buffer (esi)
|
||||
* width (edi)
|
||||
*/
|
||||
int gfx_clip_string(char* buffer, int width)
|
||||
int gfx_clip_string(utf8 *text, int width)
|
||||
{
|
||||
// Location of font sprites
|
||||
uint16 current_font_sprite_base;
|
||||
// Width the string has to fit into
|
||||
unsigned int max_width;
|
||||
// Character to change to ellipsis
|
||||
unsigned char* last_char;
|
||||
// Width of the string, including ellipsis
|
||||
|
||||
unsigned int clipped_width;
|
||||
|
||||
rct_g1_element g1_element;
|
||||
uint16 fontSpriteBase;
|
||||
int maxWidth;
|
||||
|
||||
if (width < 6) {
|
||||
*buffer = 0;
|
||||
*text = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fontSpriteBase = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16);
|
||||
int dotCharacterWidth = _spriteFontCharacterWidths[fontSpriteBase + ('.' - ' ')];
|
||||
int elipsisCharacterWidth = dotCharacterWidth * 3;
|
||||
|
||||
current_font_sprite_base = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16);
|
||||
max_width = width - (3 * RCT2_ADDRESS(0x141E9F6, uint8)[current_font_sprite_base]);
|
||||
maxWidth = width - elipsisCharacterWidth;
|
||||
|
||||
clipped_width = 0;
|
||||
last_char = buffer;
|
||||
|
||||
for (unsigned char* curr_char = buffer; *curr_char != (uint8)0; curr_char++) {
|
||||
if (*curr_char < 0x20) {
|
||||
switch (*curr_char) {
|
||||
int clippedWidth = 0;
|
||||
utf8 *lastCh = text;
|
||||
utf8 *ch = text;
|
||||
int codepoint;
|
||||
while ((codepoint = utf8_get_next(ch, &ch)) != 0) {
|
||||
if (utf8_is_format_code(codepoint)) {
|
||||
switch (codepoint) {
|
||||
case FORMAT_MOVE_X:
|
||||
curr_char++;
|
||||
clipped_width = *curr_char;
|
||||
continue;
|
||||
clippedWidth = *ch++;
|
||||
break;
|
||||
case FORMAT_ADJUST_PALETTE:
|
||||
case 3:
|
||||
case 4:
|
||||
curr_char++;
|
||||
continue;
|
||||
ch++;
|
||||
break;
|
||||
case FORMAT_NEWLINE:
|
||||
case FORMAT_NEWLINE_SMALLER:
|
||||
continue;
|
||||
break;
|
||||
case FORMAT_TINYFONT:
|
||||
current_font_sprite_base = 0x1C0;
|
||||
break;
|
||||
case FORMAT_BIGFONT:
|
||||
current_font_sprite_base = 0x2A0;
|
||||
break;
|
||||
case FORMAT_MEDIUMFONT:
|
||||
current_font_sprite_base = 0x0E0;
|
||||
fontSpriteBase = 448;
|
||||
break;
|
||||
case FORMAT_SMALLFONT:
|
||||
current_font_sprite_base = 0;
|
||||
fontSpriteBase = 0;
|
||||
break;
|
||||
case FORMAT_MEDIUMFONT:
|
||||
fontSpriteBase = 224;
|
||||
break;
|
||||
case FORMAT_BIGFONT:
|
||||
fontSpriteBase = 672;
|
||||
break;
|
||||
case FORMAT_OUTLINE:
|
||||
case FORMAT_OUTLINE_OFF:
|
||||
@@ -308,36 +249,40 @@ int gfx_clip_string(char* buffer, int width)
|
||||
case FORMAT_WINDOW_COLOUR_2:
|
||||
case FORMAT_WINDOW_COLOUR_3:
|
||||
case 0x10:
|
||||
continue;
|
||||
break;
|
||||
case FORMAT_INLINE_SPRITE:
|
||||
g1_element = g1Elements[*((uint32*)(curr_char + 1)) & 0x7FFFF];
|
||||
clipped_width += g1_element.width;
|
||||
curr_char += 4;
|
||||
continue;
|
||||
g1_element = g1Elements[*((uint32*)(ch - 1)) & 0x7FFFF];
|
||||
clippedWidth += g1_element.width;
|
||||
ch += 4;
|
||||
break;
|
||||
default:
|
||||
if (*curr_char <= 0x16) { //case 0x11? FORMAT_NEW_LINE_X_Y
|
||||
curr_char += 2;
|
||||
continue;
|
||||
if (codepoint >= FORMAT_COLOUR_CODE_START || codepoint <= FORMAT_COLOUR_CODE_END) {
|
||||
break;
|
||||
}
|
||||
curr_char += 4;//never happens?
|
||||
continue;
|
||||
if (codepoint <= 22) { //case 0x11? FORMAT_NEW_LINE_X_Y
|
||||
ch += 2;
|
||||
} else {
|
||||
ch += 4;//never happens?
|
||||
}
|
||||
break;
|
||||
}
|
||||
max_width = width - (3 * RCT2_ADDRESS(0x141E9F6, uint8)[current_font_sprite_base]);
|
||||
}
|
||||
|
||||
clipped_width += RCT2_ADDRESS(RCT2_ADDRESS_FONT_CHAR_WIDTH, uint8)[current_font_sprite_base + (*curr_char - 0x20)];
|
||||
|
||||
if ((int)clipped_width > width) {
|
||||
// *((uint32*)last_char) = '...';
|
||||
strcpy(last_char-3, "...");
|
||||
clipped_width = width;
|
||||
return clipped_width;
|
||||
}
|
||||
if (clipped_width <= max_width) {
|
||||
last_char = curr_char+1;
|
||||
dotCharacterWidth = _spriteFontCharacterWidths[fontSpriteBase + ('.' - ' ')];
|
||||
elipsisCharacterWidth = dotCharacterWidth * 3;
|
||||
maxWidth = width - elipsisCharacterWidth;
|
||||
} else {
|
||||
clippedWidth += _spriteFontCharacterWidths[fontSpriteBase + utf8_get_sprite_offset_for_codepoint(codepoint)];
|
||||
if (clippedWidth > width) {
|
||||
strcpy(lastCh - 3, "...");
|
||||
clippedWidth = width;
|
||||
return clippedWidth;
|
||||
}
|
||||
if (clippedWidth <= maxWidth) {
|
||||
lastCh = ch + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return clipped_width;
|
||||
return clippedWidth;
|
||||
}
|
||||
|
||||
|
||||
@@ -423,7 +368,7 @@ int gfx_wrap_string(char* buffer, int width, int* num_lines, int* font_height)
|
||||
}
|
||||
}
|
||||
|
||||
line_width += RCT2_ADDRESS(RCT2_ADDRESS_FONT_CHAR_WIDTH, uint8)[*font_height + (*curr_char - 0x20)];
|
||||
line_width += _spriteFontCharacterWidths[*font_height + (*curr_char - 0x20)];
|
||||
|
||||
if ((int)line_width <= width) {
|
||||
continue;
|
||||
@@ -790,298 +735,7 @@ void colour_char_window(uint8 colour, uint16* current_font_flags,uint8* palette_
|
||||
*/
|
||||
void gfx_draw_string(rct_drawpixelinfo *dpi, char *buffer, int colour, int x, int y)
|
||||
{
|
||||
if (_ttfInitialised) {
|
||||
ttf_draw_string(dpi, buffer, colour, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
int eax, ebx, ebp;
|
||||
rct_g1_element* g1_element;
|
||||
|
||||
// Maximum length/height of string
|
||||
int max_x = x;
|
||||
int max_y = y;
|
||||
|
||||
//
|
||||
uint16 *current_font_flags = RCT2_ADDRESS(RCT2_ADDRESS_CURRENT_FONT_FLAGS, uint16);
|
||||
sint16 *current_font_sprite_base = RCT2_ADDRESS(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, sint16);
|
||||
|
||||
uint8* palette_pointer = text_palette;
|
||||
|
||||
// Flag for skipping non-printing characters
|
||||
int skip_char = 0;
|
||||
|
||||
if (colour != 0xFE) {
|
||||
|
||||
if (x >= dpi->x + dpi->width)
|
||||
return;
|
||||
|
||||
if (x + 0x280 <= dpi->x)
|
||||
return;
|
||||
|
||||
if (y >= dpi->y + dpi->height)
|
||||
return;
|
||||
|
||||
if (y + 0x5A <= dpi->y) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (colour != 0xFF) {
|
||||
|
||||
// switch_colour:
|
||||
*current_font_flags = 0;
|
||||
if (*current_font_sprite_base < 0) {
|
||||
*current_font_flags |= 4;
|
||||
if (*current_font_sprite_base != -1) {
|
||||
*current_font_flags |= 8;
|
||||
}
|
||||
*current_font_sprite_base = 224;
|
||||
}
|
||||
if (colour & (1 << 5)) {
|
||||
*current_font_flags |= 2;
|
||||
}
|
||||
colour &= ~(1 << 5);
|
||||
|
||||
if (!(colour & 0x40)) {
|
||||
ebp = colour;
|
||||
if (*current_font_flags & 1) {
|
||||
if ((y + 0x13 <= dpi->y) || (dpi->y + dpi->height <= y)) {
|
||||
skip_char = 1;
|
||||
} else {
|
||||
skip_char = 0;
|
||||
}
|
||||
} else {
|
||||
colour_char_window(ebp, current_font_flags, palette_pointer);
|
||||
}
|
||||
} else {
|
||||
*current_font_flags |= 1;
|
||||
colour &= 0x1F;
|
||||
|
||||
if (*current_font_flags & 4) {
|
||||
if (*current_font_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? ;
|
||||
palette_pointer[1] = eax & 0xFF;
|
||||
palette_pointer[2] = (eax >> 8) & 0xFF;
|
||||
palette_pointer[3] = (eax >> 16) & 0xFF;
|
||||
palette_pointer[4] = (eax >> 24) & 0xFF;
|
||||
RCT2_GLOBAL(0x009ABDA4, uint32) = (uint32)palette_pointer;
|
||||
eax = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((y + 0x13 <= dpi->y) || (dpi->y + dpi->height <= y)) {
|
||||
skip_char = 1;
|
||||
}
|
||||
|
||||
for (uint8 al = *buffer; al > 0; ++buffer, al = *buffer) {
|
||||
|
||||
// Skip to the next printing character
|
||||
if (skip_char) {
|
||||
if (al < 0x20) {
|
||||
// Control codes
|
||||
skip_char = 0;
|
||||
} else if (al >= FORMAT_COLOUR_CODE_START && al <= FORMAT_COLOUR_CODE_END) {
|
||||
// Colour codes
|
||||
if (*current_font_flags == 1) {
|
||||
if ((y + 0x13 <= dpi->y) || (dpi->y + dpi->height <= y)) {
|
||||
skip_char = 1;
|
||||
} else {
|
||||
skip_char = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
colour_char(al - FORMAT_COLOUR_CODE_START, current_font_flags, palette_pointer);
|
||||
continue;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Control codes
|
||||
switch (al) {
|
||||
case FORMAT_MOVE_X://Start New Line at start+buffer x, same y. (Overwrite?)
|
||||
max_x = x + (uint8)*++buffer;
|
||||
break;
|
||||
case FORMAT_ADJUST_PALETTE:
|
||||
al = *++buffer;
|
||||
if (*current_font_flags & 1) {
|
||||
if ((y + 0x13 <= dpi->y) || (dpi->y + dpi->height <= y)) {
|
||||
skip_char = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
eax = palette_to_g1_offset[al]; //RCT2_ADDRESS(0x097FCBC, uint32)[al * 4];
|
||||
g1_element = &g1Elements[eax];
|
||||
ebx = g1_element->offset[0xF9] + (1 << 8);
|
||||
if (!(*current_font_flags & 2)) {
|
||||
ebx = ebx & 0xFF;
|
||||
}
|
||||
|
||||
palette_pointer[1] = ebx & 0xff;
|
||||
palette_pointer[2] = (ebx >> 8) & 0xff;
|
||||
//Adjust the text palette
|
||||
memcpy(palette_pointer + 3, &(g1_element->offset[0xF7]), 2);
|
||||
memcpy(palette_pointer + 5, &(g1_element->offset[0xFA]), 2);
|
||||
//Set the palette pointer
|
||||
RCT2_GLOBAL(0x009ABDA4, uint32) = (uint32)palette_pointer;
|
||||
|
||||
|
||||
if ((y + 0x13 <= dpi->y) || (dpi->y + dpi->height <= y)) {
|
||||
skip_char = 1;
|
||||
}
|
||||
break;
|
||||
case FORMAT_NEWLINE://Start New Line at set y lower
|
||||
max_x = x;
|
||||
if (*current_font_sprite_base <= 224) {
|
||||
max_y += 10;
|
||||
break;
|
||||
}
|
||||
else if (*current_font_sprite_base == 448) {
|
||||
max_y += 6;
|
||||
break;
|
||||
}
|
||||
max_y += 18;
|
||||
break;
|
||||
case FORMAT_NEWLINE_SMALLER://Start New Line at set y lower
|
||||
max_x = x;
|
||||
if (*current_font_sprite_base <= 224) {
|
||||
max_y += 5;
|
||||
break;
|
||||
}
|
||||
else if (*current_font_sprite_base == 448) {
|
||||
max_y += 3;
|
||||
break;
|
||||
}
|
||||
max_y += 9;
|
||||
break;
|
||||
case FORMAT_TINYFONT:
|
||||
*current_font_sprite_base = 448;
|
||||
break;
|
||||
case FORMAT_BIGFONT:
|
||||
*current_font_sprite_base = 672;
|
||||
break;
|
||||
case FORMAT_MEDIUMFONT:
|
||||
*current_font_sprite_base = 224;
|
||||
break;
|
||||
case FORMAT_SMALLFONT:
|
||||
*current_font_sprite_base = 0;
|
||||
break;
|
||||
case FORMAT_OUTLINE:
|
||||
*current_font_flags |= 2;
|
||||
break;
|
||||
case FORMAT_OUTLINE_OFF:
|
||||
*current_font_flags &= 0x0FFFD;
|
||||
break;
|
||||
case FORMAT_WINDOW_COLOUR_1:
|
||||
ebp = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_WINDOW_COLOUR_1, uint8);
|
||||
if (*current_font_flags & 1) {
|
||||
if ((y + 0x13 <= dpi->y) || (dpi->y + dpi->height <= y)) {
|
||||
skip_char = 1;
|
||||
}
|
||||
else {
|
||||
skip_char = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
colour_char_window(ebp, current_font_flags, palette_pointer);
|
||||
break;
|
||||
case FORMAT_WINDOW_COLOUR_2:
|
||||
ebp = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_WINDOW_COLOUR_2, uint8);
|
||||
if (*current_font_flags & 1) {
|
||||
if ((y + 0x13 <= dpi->y) || (dpi->y + dpi->height <= y)) {
|
||||
skip_char = 1;
|
||||
}
|
||||
else {
|
||||
skip_char = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
colour_char_window(ebp, current_font_flags, palette_pointer);
|
||||
break;
|
||||
case FORMAT_WINDOW_COLOUR_3:
|
||||
ebp = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_WINDOW_COLOUR_3, uint8);
|
||||
if (*current_font_flags & 1) {
|
||||
if ((y + 0x13 <= dpi->y) || (dpi->y + dpi->height <= y)) {
|
||||
skip_char = 1;
|
||||
}
|
||||
else {
|
||||
skip_char = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
colour_char_window(ebp, current_font_flags, palette_pointer);
|
||||
break;
|
||||
case FORMAT_NEWLINE_X_Y: //Start new line at specified x,y
|
||||
max_x = x + *++buffer;
|
||||
max_y = y + *++buffer;
|
||||
break;
|
||||
case FORMAT_INLINE_SPRITE:
|
||||
buffer += 4;
|
||||
if (max_x >= dpi->x + dpi->width) {
|
||||
skip_char = 1;
|
||||
break;
|
||||
}
|
||||
uint32 image_id = *((uint32*)(buffer - 3));
|
||||
uint32 image_offset = image_id & 0x7FFFF;
|
||||
g1_element = &g1Elements[image_offset];
|
||||
|
||||
gfx_draw_sprite(dpi, image_id, max_x, max_y, 0);
|
||||
|
||||
max_x = max_x + g1_element->width;
|
||||
break;
|
||||
default:
|
||||
// Colour codes
|
||||
if ((al >= FORMAT_COLOUR_CODE_START) && (al <= FORMAT_COLOUR_CODE_END)){
|
||||
|
||||
if (*current_font_flags == 1) {
|
||||
if ((y + 0x13 <= dpi->y) || (dpi->y + dpi->height <= y)) {
|
||||
skip_char = 1;
|
||||
} else {
|
||||
skip_char = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
colour_char(al - FORMAT_COLOUR_CODE_START, current_font_flags, palette_pointer);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Normal Characters
|
||||
if (max_x >= dpi->x + dpi->width) {
|
||||
skip_char = 1;
|
||||
}
|
||||
if (max_x + 0x1A < dpi->x) {
|
||||
ebx = al-0x20;
|
||||
ebx += *current_font_sprite_base;
|
||||
max_x = max_x + (RCT2_ADDRESS(RCT2_ADDRESS_FONT_CHAR_WIDTH, uint8)[ebx] & 0xFF);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 char_offset = al - 0x20 + *current_font_sprite_base;
|
||||
RCT2_GLOBAL(0x00EDF81C, uint32) = (IMAGE_TYPE_USE_PALETTE << 28);
|
||||
|
||||
gfx_draw_sprite_palette_set(dpi, ((IMAGE_TYPE_USE_PALETTE << 28) | char_offset) + SPR_CHAR_START, max_x, max_y, palette_pointer, NULL);
|
||||
max_x += (RCT2_ADDRESS(RCT2_ADDRESS_FONT_CHAR_WIDTH, uint8)[char_offset] & 0xFF);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
gLastDrawStringX = max_x;
|
||||
gLastDrawStringY = max_y;
|
||||
ttf_draw_string(dpi, buffer, colour, x, y);
|
||||
}
|
||||
|
||||
void draw_string_left_underline(rct_drawpixelinfo *dpi, int format, void *args, int colour, int x, int y)
|
||||
@@ -1269,14 +923,18 @@ bool ttf_initialise()
|
||||
if (TTF_Init() != 0)
|
||||
return false;
|
||||
|
||||
_ttfFont = TTF_OpenFont("C:\\Windows\\Fonts\\msyh.ttc", 11);
|
||||
if (_ttfFont == NULL) {
|
||||
TTF_Quit();
|
||||
return false;
|
||||
utf8 fontPath[MAX_PATH] = "C:\\Windows\\Fonts\\";
|
||||
strcat(fontPath, gTrueTypeFontPath);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
_ttfFont[i] = TTF_OpenFont(fontPath, TTFFontSizes[i]);
|
||||
if (_ttfFont[i] == NULL) {
|
||||
TTF_Quit();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_ttfFontOffsetX = 0;
|
||||
_ttfFontOffsetY = -2;
|
||||
_ttfFontOffsetY = -3;
|
||||
_ttfInitialised = true;
|
||||
}
|
||||
return true;
|
||||
@@ -1287,10 +945,15 @@ void ttf_dispose()
|
||||
if (!_ttfInitialised)
|
||||
return;
|
||||
|
||||
if (_ttfFont != NULL)
|
||||
TTF_CloseFont(_ttfFont);
|
||||
if (_ttfFont != NULL) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
TTF_CloseFont(_ttfFont[i]);
|
||||
_ttfFont[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
TTF_Quit();
|
||||
_ttfInitialised = false;
|
||||
}
|
||||
|
||||
enum {
|
||||
@@ -1300,6 +963,8 @@ enum {
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int startX;
|
||||
int startY;
|
||||
int x;
|
||||
int y;
|
||||
int flags;
|
||||
@@ -1307,21 +972,14 @@ typedef struct {
|
||||
uint16 font_sprite_base;
|
||||
} text_draw_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;
|
||||
uint32 charOffset = info->font_sprite_base + utf8_get_sprite_offset_for_codepoint(codepoint);
|
||||
int charWidth = _spriteFontCharacterWidths[charOffset] & 0xFF;
|
||||
|
||||
if (!(info->flags & TEXT_DRAW_FLAG_NO_DRAW)) {
|
||||
RCT2_GLOBAL(0x009ABDA4, uint8*) = (uint8*)&info->palette;
|
||||
@@ -1338,25 +996,42 @@ static void ttf_draw_string_raw_ttf(rct_drawpixelinfo *dpi, const utf8 *text, te
|
||||
if (!_ttfInitialised && !ttf_initialise())
|
||||
return;
|
||||
|
||||
int fontStyle = TTF_GetFontStyle(_ttfFont);
|
||||
TTF_Font *font;
|
||||
switch (info->font_sprite_base) {
|
||||
case FONT_SPRITE_BASE_TINY:
|
||||
font = _ttfFont[0];
|
||||
break;
|
||||
case FONT_SPRITE_BASE_SMALL:
|
||||
font = _ttfFont[1];
|
||||
break;
|
||||
default:
|
||||
case FONT_SPRITE_BASE_MEDIUM:
|
||||
font = _ttfFont[2];
|
||||
break;
|
||||
case FONT_SPRITE_BASE_BIG:
|
||||
font = _ttfFont[3];
|
||||
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(_ttfFont, newFontStyle);
|
||||
TTF_SetFontStyle(font, newFontStyle);
|
||||
}
|
||||
|
||||
if (info->flags & TEXT_DRAW_FLAG_NO_DRAW) {
|
||||
int width, height;
|
||||
|
||||
TTF_SizeUTF8(_ttfFont, text, &width, &height);
|
||||
TTF_SizeUTF8(font, text, &width, &height);
|
||||
info->x += width;
|
||||
return;
|
||||
} else {
|
||||
uint8 colour = info->palette[1];
|
||||
SDL_Color c = { 0, 0, 0, 255 };
|
||||
SDL_Surface *surface = TTF_RenderUTF8_Solid(_ttfFont, text, c);
|
||||
SDL_Surface *surface = TTF_RenderUTF8_Solid(font, text, c);
|
||||
if (surface == NULL)
|
||||
return;
|
||||
|
||||
@@ -1429,7 +1104,7 @@ static const utf8 *ttf_process_format_code(rct_drawpixelinfo *dpi, const utf8 *t
|
||||
codepoint = utf8_get_next(text, &nextCh);
|
||||
switch (codepoint) {
|
||||
case FORMAT_MOVE_X:
|
||||
info->x += *nextCh++;
|
||||
info->x = info->startX + *nextCh++;
|
||||
break;
|
||||
case FORMAT_ADJUST_PALETTE:
|
||||
{
|
||||
@@ -1464,14 +1139,14 @@ static const utf8 *ttf_process_format_code(rct_drawpixelinfo *dpi, const utf8 *t
|
||||
case FORMAT_TINYFONT:
|
||||
info->font_sprite_base = 448;
|
||||
break;
|
||||
case FORMAT_BIGFONT:
|
||||
info->font_sprite_base = 672;
|
||||
case FORMAT_SMALLFONT:
|
||||
info->font_sprite_base = 0;
|
||||
break;
|
||||
case FORMAT_MEDIUMFONT:
|
||||
info->font_sprite_base = 224;
|
||||
break;
|
||||
case FORMAT_SMALLFONT:
|
||||
info->font_sprite_base = 0;
|
||||
case FORMAT_BIGFONT:
|
||||
info->font_sprite_base = 672;
|
||||
break;
|
||||
case FORMAT_OUTLINE:
|
||||
info->flags |= TEXT_DRAW_FLAG_OUTLINE;
|
||||
@@ -1501,13 +1176,13 @@ static const utf8 *ttf_process_format_code(rct_drawpixelinfo *dpi, const utf8 *t
|
||||
break;
|
||||
case FORMAT_INLINE_SPRITE:
|
||||
{
|
||||
nextCh += 4;
|
||||
uint32 imageId = *((uint32*)(nextCh - 3));
|
||||
uint32 imageId = *((uint32*)(nextCh));
|
||||
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;
|
||||
nextCh += 4;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -1528,16 +1203,17 @@ static const utf8 *ttf_process_glyph_run(rct_drawpixelinfo *dpi, const utf8 *tex
|
||||
{
|
||||
utf8 buffer[512];
|
||||
const utf8 *ch = text;
|
||||
const utf8 *lastCh;
|
||||
int codepoint;
|
||||
|
||||
do {
|
||||
codepoint = utf8_get_next(ch, &ch);
|
||||
} while (!utf8_is_format_code(codepoint));
|
||||
while (!utf8_is_format_code(codepoint = utf8_get_next(ch, &lastCh))) {
|
||||
ch = lastCh;
|
||||
}
|
||||
if (codepoint == 0) {
|
||||
ttf_draw_string_raw(dpi, text, info);
|
||||
return ch - 1;
|
||||
return ch;
|
||||
} else {
|
||||
int length = ch - text - 1;
|
||||
int length = ch - text;
|
||||
memcpy(buffer, text, length);
|
||||
buffer[length] = 0;
|
||||
ttf_draw_string_raw(dpi, buffer, info);
|
||||
@@ -1550,9 +1226,16 @@ static void ttf_process_string(rct_drawpixelinfo *dpi, const utf8 *text, text_dr
|
||||
const utf8 *ch = text;
|
||||
const utf8 *nextCh;
|
||||
int codepoint;
|
||||
|
||||
bool isTTF = info->flags & TEXT_DRAW_FLAG_TTF;
|
||||
|
||||
while ((codepoint = utf8_get_next(ch, &nextCh)) != 0) {
|
||||
if (utf8_is_format_code(codepoint)) {
|
||||
ch = ttf_process_format_code(dpi, ch, info);
|
||||
} else if (isTTF && utf8_should_use_sprite_for_codepoint(codepoint)) {
|
||||
info->flags &= ~TEXT_DRAW_FLAG_TTF;
|
||||
ch = ttf_process_glyph_run(dpi, ch, info);
|
||||
info->flags |= TEXT_DRAW_FLAG_TTF;
|
||||
} else {
|
||||
ch = ttf_process_glyph_run(dpi, ch, info);
|
||||
}
|
||||
@@ -1616,15 +1299,17 @@ static void ttf_draw_string(rct_drawpixelinfo *dpi, char *text, int colour, int
|
||||
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.startX = x;
|
||||
info.startY = x;
|
||||
info.x = x;
|
||||
info.y = y;
|
||||
|
||||
info.flags |= TEXT_DRAW_FLAG_TTF;
|
||||
|
||||
memset(info.palette, 0, sizeof(info.palette));
|
||||
if (gUseTrueTypeFont) info.flags |= TEXT_DRAW_FLAG_TTF;
|
||||
|
||||
memcpy(info.palette, text_palette, sizeof(info.palette));
|
||||
ttf_process_initial_colour(colour, &info);
|
||||
ttf_process_string(dpi, text, &info);
|
||||
memcpy(text_palette, info.palette, sizeof(info.palette));
|
||||
|
||||
gLastDrawStringX = info.x;
|
||||
gLastDrawStringY = info.y;
|
||||
@@ -1635,11 +1320,13 @@ static int ttf_get_string_width(const utf8 *text)
|
||||
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.startX = 0;
|
||||
info.startY = 0;
|
||||
info.x = 0;
|
||||
info.y = 0;
|
||||
|
||||
info.flags |= TEXT_DRAW_FLAG_TTF;
|
||||
info.flags |= TEXT_DRAW_FLAG_NO_DRAW;
|
||||
if (gUseTrueTypeFont) info.flags |= TEXT_DRAW_FLAG_TTF;
|
||||
|
||||
ttf_process_string(NULL, text, &info);
|
||||
|
||||
|
||||
@@ -848,10 +848,10 @@ static void widget_scroll_draw(rct_drawpixelinfo *dpi, rct_window *w, int widget
|
||||
window_event_scroll_paint_call(w, &scroll_dpi, scrollIndex);
|
||||
}
|
||||
|
||||
static utf8 BlackUpArrowString[] = { 0xC2, 0x8E, 0xC2, 0xA0, 0x00 };
|
||||
static utf8 BlackDownArrowString[] = { 0xC2, 0x8E, 0xC2, 0xAA, 0x00 };
|
||||
static utf8 BlackLeftArrowString[] = { 0xC2, 0x8E, 0xC2, 0xBE, 0x00 };
|
||||
static utf8 BlackRightArrowString[] = { 0xC2, 0x8E, 0xC2, 0xAF, 0x00 };
|
||||
static utf8 BlackUpArrowString[] = { 0xC2, 0x8E, 0xE2, 0x96, 0xB2, 0x00 };
|
||||
static utf8 BlackDownArrowString[] = { 0xC2, 0x8E, 0xE2, 0x96, 0xBC, 0x00 };
|
||||
static utf8 BlackLeftArrowString[] = { 0xC2, 0x8E, 0xE2, 0x96, 0x80, 0x00 };
|
||||
static utf8 BlackRightArrowString[] = { 0xC2, 0x8E, 0xE2, 0x96, 0xB6, 0x00 };
|
||||
|
||||
static void widget_hscrollbar_draw(rct_drawpixelinfo *dpi, rct_scroll *scroll, int l, int t, int r, int b, int colour)
|
||||
{
|
||||
|
||||
@@ -21,14 +21,14 @@
|
||||
#include "currency.h"
|
||||
|
||||
const rct_currency_spec g_currency_specs[CURRENCY_END] = {
|
||||
{ 10 , "\xA3" , CURRENCY_PREFIX }, // British Pound
|
||||
{ 10 , "\x24" , CURRENCY_PREFIX }, // US Dollar
|
||||
{ 10 , "F" , CURRENCY_SUFFIX }, // French Franc
|
||||
{ 10 , "DM" , CURRENCY_PREFIX }, // Deutsche Mark
|
||||
{ 1000 , "\xA5" , CURRENCY_PREFIX }, // Japanese Yen
|
||||
{ 10 , "Pts" , CURRENCY_SUFFIX }, // Spanish Peseta
|
||||
{ 1000 , "L" , CURRENCY_PREFIX }, // Italian Lira
|
||||
{ 10 , "fl. " , CURRENCY_PREFIX }, // Dutch Guilder
|
||||
{ 10 , "kr." , CURRENCY_SUFFIX }, // Swedish Krona
|
||||
{ 10 , "\xb5" , CURRENCY_PREFIX }, // Euro
|
||||
{ 10 , "\xC2\xA3" , CURRENCY_PREFIX }, // British Pound
|
||||
{ 10 , "$" , CURRENCY_PREFIX }, // US Dollar
|
||||
{ 10 , "F" , CURRENCY_SUFFIX }, // French Franc
|
||||
{ 10 , "DM" , CURRENCY_PREFIX }, // Deutsche Mark
|
||||
{ 1000 , "\xC2\xA5" , CURRENCY_PREFIX }, // Japanese Yen
|
||||
{ 10 , "Pts" , CURRENCY_SUFFIX }, // Spanish Peseta
|
||||
{ 1000 , "L" , CURRENCY_PREFIX }, // Italian Lira
|
||||
{ 10 , "fl. " , CURRENCY_PREFIX }, // Dutch Guilder
|
||||
{ 10 , "kr." , CURRENCY_SUFFIX }, // Swedish Krona
|
||||
{ 10 , "\xE2\x82\xAC" , CURRENCY_PREFIX }, // Euro
|
||||
};
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#ifndef CURRENCY_H
|
||||
#define CURRENCY_H
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
// List of currencies
|
||||
typedef enum {
|
||||
CURRENCY_POUNDS, // British Pound
|
||||
@@ -46,7 +48,7 @@ typedef enum {
|
||||
typedef struct {
|
||||
// Rate is relative to 0.1 GBP
|
||||
int rate;
|
||||
char symbol[8];
|
||||
utf8 symbol[8];
|
||||
int affix;
|
||||
} rct_currency_spec;
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
#ifndef _FORMAT_CODES_H_
|
||||
#define _FORMAT_CODES_H_
|
||||
|
||||
char format_get_code(const char *token);
|
||||
const char *format_get_token(char code);
|
||||
uint32 format_get_code(const char *token);
|
||||
const char *format_get_token(uint32 code);
|
||||
|
||||
enum {
|
||||
// Font format codes
|
||||
@@ -56,9 +56,6 @@ enum {
|
||||
// The next 4 bytes specify the sprite
|
||||
FORMAT_INLINE_SPRITE = 23,
|
||||
|
||||
// Non ascii-characters
|
||||
FORMAT_ENDQUOTES = 34,
|
||||
|
||||
// Argument format codes
|
||||
FORMAT_ARGUMENT_CODE_START = 123,
|
||||
FORMAT_COMMA32 = 123,
|
||||
@@ -101,27 +98,34 @@ enum {
|
||||
|
||||
// Extra non-ascii characters
|
||||
FORMAT_AMINUSCULE = 159,
|
||||
FORMAT_UP,
|
||||
FORMAT_POUND = 163,
|
||||
FORMAT_YEN = 165,
|
||||
FORMAT_COPYRIGHT = 169,
|
||||
FORMAT_DOWN,
|
||||
FORMAT_LEFTGUILLEMET,
|
||||
FORMAT_TICK,
|
||||
FORMAT_CROSS,
|
||||
FORMAT_RIGHT = 175,
|
||||
FORMAT_DEGREE,
|
||||
FORMAT_LEFTGUILLEMET = 171,
|
||||
FORMAT_DEGREE = 176,
|
||||
FORMAT_SQUARED = 178,
|
||||
FORMAT_OPENQUOTES = 180,
|
||||
FORMAT_EURO = 181,
|
||||
FORMAT_APPROX = 184,
|
||||
FORMAT_POWERNEGATIVEONE,
|
||||
FORMAT_BULLET,
|
||||
FORMAT_RIGHTGUILLEMET,
|
||||
FORMAT_SMALLUP,
|
||||
FORMAT_SMALLDOWN,
|
||||
FORMAT_LEFT,
|
||||
FORMAT_INVERTEDQUESTION
|
||||
FORMAT_RIGHTGUILLEMET = 187,
|
||||
FORMAT_INVERTEDQUESTION = 191,
|
||||
|
||||
FORMAT_OPENQUOTES = 8220,
|
||||
FORMAT_ENDQUOTES = 8221,
|
||||
|
||||
FORMAT_BULLET = 8226,
|
||||
FORMAT_POWERNEGATIVEONE = 8315,
|
||||
FORMAT_EURO = 8364,
|
||||
|
||||
FORMAT_APPROX = 8776,
|
||||
|
||||
FORMAT_UP = 9650,
|
||||
FORMAT_RIGHT = 9654,
|
||||
FORMAT_DOWN = 9660,
|
||||
FORMAT_LEFT = 9664,
|
||||
|
||||
FORMAT_SMALLUP = 9652,
|
||||
FORMAT_SMALLDOWN = 9662,
|
||||
|
||||
FORMAT_TICK = 10003,
|
||||
FORMAT_CROSS = 10005,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -33,39 +33,25 @@ typedef struct {
|
||||
char *string_data;
|
||||
} 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
|
||||
"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
|
||||
"chinese_traditional" // LANGUAGE_CHINESE_TRADITIONAL
|
||||
const language_descriptor LanguagesDescriptors[LANGUAGE_COUNT] = {
|
||||
{ "", "", "", "", FONT_OPENRCT2_SPRITE }, // LANGUAGE_UNDEFINED
|
||||
{ "en-GB", "English (UK)", "English (UK)", "english_uk", FONT_OPENRCT2_SPRITE }, // LANGUAGE_ENGLISH_UK
|
||||
{ "en-US", "English (US)", "English (US)", "english_us", FONT_OPENRCT2_SPRITE }, // LANGUAGE_ENGLISH_US
|
||||
{ "de-DE", "German", "Deutsch", "german", FONT_OPENRCT2_SPRITE }, // LANGUAGE_GERMAN
|
||||
{ "nl-NL", "Dutch", "Nederlands", "dutch", FONT_OPENRCT2_SPRITE }, // LANGUAGE_DUTCH
|
||||
{ "fr-FR", "French", "Fran\xC3\xA7" "ais", "french", FONT_OPENRCT2_SPRITE }, // LANGUAGE_FRENCH
|
||||
{ "hu-HU", "Hungarian", "Magyar", "hungarian", FONT_OPENRCT2_SPRITE }, // LANGUAGE_HUNGARIAN
|
||||
{ "pl-PL", "Polish", "Polski", "polish", FONT_OPENRCT2_SPRITE }, // LANGUAGE_POLISH
|
||||
{ "es-ES", "Spanish", "Espa\xC3\xB1ol", "spanish_sp", FONT_OPENRCT2_SPRITE }, // LANGUAGE_SPANISH
|
||||
{ "sv-SE", "Swedish", "Svenska", "swedish", FONT_OPENRCT2_SPRITE }, // LANGUAGE_SWEDISH
|
||||
{ "it-IT", "Italian", "Italiano", "italian", FONT_OPENRCT2_SPRITE }, // LANGUAGE_ITALIAN
|
||||
{ "pt-BR", "Portuguese (BR)", "Portug\xC3\xAAs (BR)", "portuguese_br", FONT_OPENRCT2_SPRITE }, // LANGUAGE_PORTUGUESE_BR
|
||||
{ "zh-Hant", "Chinese (Traditional)", "Chinese (Traditional)", "chinese_traditional", "msjh.ttc" }, // LANGUAGE_CHINESE_TRADITIONAL
|
||||
};
|
||||
|
||||
int gCurrentLanguage = LANGUAGE_UNDEFINED;
|
||||
bool gUseTrueTypeFont = false;
|
||||
const utf8 *gTrueTypeFontPath;
|
||||
|
||||
language_data _languageFallback = { 0 };
|
||||
language_data _languageCurrent = { 0 };
|
||||
@@ -154,19 +140,27 @@ int language_open(int id)
|
||||
return 1;
|
||||
|
||||
if (id != LANGUAGE_ENGLISH_UK) {
|
||||
sprintf(filename, languagePath, gExePath, language_filenames[LANGUAGE_ENGLISH_UK]);
|
||||
sprintf(filename, languagePath, gExePath, LanguagesDescriptors[LANGUAGE_ENGLISH_UK].path);
|
||||
if (language_open_file(filename, &_languageFallback)) {
|
||||
_languageFallback.id = LANGUAGE_ENGLISH_UK;
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(filename, languagePath, gExePath, language_filenames[id]);
|
||||
sprintf(filename, languagePath, gExePath, LanguagesDescriptors[id].path);
|
||||
if (language_open_file(filename, &_languageCurrent)) {
|
||||
_languageCurrent.id = id;
|
||||
gCurrentLanguage = id;
|
||||
|
||||
if (!ttf_initialise()) {
|
||||
log_warning("Unable to initialise TrueType fonts.");
|
||||
if (LanguagesDescriptors[id].font == FONT_OPENRCT2_SPRITE) {
|
||||
gUseTrueTypeFont = false;
|
||||
gTrueTypeFontPath = NULL;
|
||||
ttf_dispose();
|
||||
} else {
|
||||
gUseTrueTypeFont = true;
|
||||
gTrueTypeFontPath = LanguagesDescriptors[id].font;
|
||||
if (!ttf_initialise()) {
|
||||
log_warning("Unable to initialise TrueType fonts.");
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -274,10 +268,13 @@ static int language_open_file(const char *filename, language_data *language)
|
||||
int tokenLength = min(src - token, sizeof(tokenBuffer) - 1);
|
||||
memcpy(tokenBuffer, token, tokenLength);
|
||||
tokenBuffer[tokenLength] = 0;
|
||||
uint8 code = (uint8)format_get_code(tokenBuffer);
|
||||
if (code == 0)
|
||||
uint32 code = format_get_code(tokenBuffer);
|
||||
if (code == 0) {
|
||||
code = atoi(tokenBuffer);
|
||||
dst = utf8_write_codepoint(dst, code);
|
||||
*dst++ = code & 0xFF;
|
||||
} else {
|
||||
dst = utf8_write_codepoint(dst, code);
|
||||
}
|
||||
mode = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -40,8 +40,21 @@ enum {
|
||||
LANGUAGE_COUNT
|
||||
};
|
||||
|
||||
extern const char *language_names[LANGUAGE_COUNT];
|
||||
#define FONT_OPENRCT2_SPRITE NULL
|
||||
|
||||
typedef struct {
|
||||
const char *locale;
|
||||
const utf8 *english_name;
|
||||
const utf8 *native_name;
|
||||
const utf8 *path;
|
||||
const utf8 *font;
|
||||
} language_descriptor;
|
||||
|
||||
extern const language_descriptor LanguagesDescriptors[LANGUAGE_COUNT];
|
||||
|
||||
extern int gCurrentLanguage;
|
||||
extern bool gUseTrueTypeFont;
|
||||
extern const utf8 *gTrueTypeFontPath;
|
||||
|
||||
const char *language_get_string(rct_string_id id);
|
||||
int language_open(int id);
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
#pragma region Format codes
|
||||
|
||||
typedef struct {
|
||||
char code;
|
||||
char *token;
|
||||
uint32 code;
|
||||
const char *token;
|
||||
} format_code_token;
|
||||
|
||||
format_code_token format_code_tokens[] = {
|
||||
@@ -107,7 +107,7 @@ format_code_token format_code_tokens[] = {
|
||||
{ FORMAT_INVERTEDQUESTION, "INVERTEDQUESTION" }
|
||||
};
|
||||
|
||||
char format_get_code(const char *token)
|
||||
uint32 format_get_code(const char *token)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < countof(format_code_tokens); i++)
|
||||
@@ -116,7 +116,7 @@ char format_get_code(const char *token)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *format_get_token(char code)
|
||||
const char *format_get_token(uint32 code)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < countof(format_code_tokens); i++)
|
||||
@@ -125,6 +125,66 @@ const char *format_get_token(char code)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool utf8_is_format_code(int codepoint)
|
||||
{
|
||||
if (codepoint < 32) return true;
|
||||
if (codepoint >= 123 && codepoint <= 155) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool utf8_should_use_sprite_for_codepoint(int codepoint)
|
||||
{
|
||||
switch (codepoint) {
|
||||
case FORMAT_UP:
|
||||
case FORMAT_DOWN:
|
||||
case FORMAT_LEFTGUILLEMET:
|
||||
case FORMAT_TICK:
|
||||
case FORMAT_CROSS:
|
||||
case FORMAT_RIGHT:
|
||||
case FORMAT_RIGHTGUILLEMET:
|
||||
case FORMAT_SMALLUP:
|
||||
case FORMAT_SMALLDOWN:
|
||||
case FORMAT_LEFT:
|
||||
case FORMAT_OPENQUOTES:
|
||||
case FORMAT_ENDQUOTES:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int utf8_get_sprite_offset_for_codepoint(int codepoint)
|
||||
{
|
||||
switch (codepoint) {
|
||||
case FORMAT_AMINUSCULE: return 159 - 32;
|
||||
case FORMAT_POUND: return 163 - 32;
|
||||
case FORMAT_YEN: return 165 - 32;
|
||||
case FORMAT_COPYRIGHT: return 169 - 32;
|
||||
case FORMAT_LEFTGUILLEMET: return 171 - 32;
|
||||
case FORMAT_DEGREE: return 176 - 32;
|
||||
case FORMAT_SQUARED: return 178 - 32;
|
||||
case FORMAT_RIGHTGUILLEMET: return 187 - 32;
|
||||
case FORMAT_INVERTEDQUESTION: return 191 - 32;
|
||||
case FORMAT_OPENQUOTES: return 180 - 32;
|
||||
case FORMAT_ENDQUOTES: return 34 - 32;
|
||||
case FORMAT_BULLET: return 186 - 32;
|
||||
case FORMAT_POWERNEGATIVEONE: return 185 - 32;
|
||||
case FORMAT_EURO: return 181 - 32;
|
||||
case FORMAT_APPROX: return 184 - 32;
|
||||
case FORMAT_UP: return 160 - 32;
|
||||
case FORMAT_RIGHT: return 175 - 32;
|
||||
case FORMAT_DOWN: return 170 - 32;
|
||||
case FORMAT_LEFT: return 190 - 32;
|
||||
case FORMAT_SMALLUP: return 188 - 32;
|
||||
case FORMAT_SMALLDOWN: return 189 - 32;
|
||||
case FORMAT_TICK: return 172 - 32;
|
||||
case FORMAT_CROSS: return 173 - 32;
|
||||
default:
|
||||
if (codepoint > 224) codepoint = ' ';
|
||||
return codepoint - 32;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
void format_string_part_from_raw(char **dest, const char *src, char **args);
|
||||
@@ -312,7 +372,7 @@ void format_currency(char **dest, long long value)
|
||||
}
|
||||
|
||||
// Currency symbol
|
||||
const char *symbol = currencySpec->symbol;
|
||||
const utf8 *symbol = currencySpec->symbol;
|
||||
|
||||
// Prefix
|
||||
if (currencySpec->affix == CURRENCY_PREFIX) {
|
||||
@@ -343,7 +403,7 @@ void format_currency_2dp(char **dest, long long value)
|
||||
}
|
||||
|
||||
// Currency symbol
|
||||
const char *symbol = currencySpec->symbol;
|
||||
const utf8 *symbol = currencySpec->symbol;
|
||||
|
||||
// Prefix
|
||||
if (currencySpec->affix == CURRENCY_PREFIX) {
|
||||
@@ -743,53 +803,34 @@ void generate_string_file()
|
||||
*
|
||||
* buffer (esi)
|
||||
*/
|
||||
int get_string_length(char* buffer)
|
||||
int get_string_length(const utf8* text)
|
||||
{
|
||||
// Length of string
|
||||
int length = 0;
|
||||
int codepoint;
|
||||
const utf8 *ch = text;
|
||||
|
||||
for (uint8* curr_char = (uint8*)buffer; *curr_char != (uint8)0; curr_char++) {
|
||||
length++;
|
||||
if (*curr_char >= 0x20) {
|
||||
continue;
|
||||
}
|
||||
switch (*curr_char) {
|
||||
case FORMAT_MOVE_X:
|
||||
case FORMAT_ADJUST_PALETTE:
|
||||
case 3:
|
||||
case 4:
|
||||
curr_char++;
|
||||
length++;
|
||||
break;
|
||||
case FORMAT_NEWLINE:
|
||||
case FORMAT_NEWLINE_SMALLER:
|
||||
case FORMAT_TINYFONT:
|
||||
case FORMAT_BIGFONT:
|
||||
case FORMAT_MEDIUMFONT:
|
||||
case FORMAT_SMALLFONT:
|
||||
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:
|
||||
length += 4;
|
||||
curr_char += 4;
|
||||
break;
|
||||
default:
|
||||
if (*curr_char <= 0x16) { //case 0x11? FORMAT_NEW_LINE_X_Y
|
||||
length += 2;
|
||||
curr_char += 2;
|
||||
continue;
|
||||
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;
|
||||
}
|
||||
length += 4;
|
||||
curr_char += 4;//never happens?
|
||||
break;
|
||||
}
|
||||
}
|
||||
return length;
|
||||
return ch - text - 1;
|
||||
}
|
||||
|
||||
int win1252_to_utf8(utf8string dst, const char *src, int maxBufferLength)
|
||||
|
||||
@@ -26,12 +26,16 @@
|
||||
#include "language.h"
|
||||
#include "string_ids.h"
|
||||
|
||||
bool utf8_is_format_code(int codepoint);
|
||||
bool utf8_should_use_sprite_for_codepoint(int codepoint);
|
||||
int utf8_get_sprite_offset_for_codepoint(int codepoint);
|
||||
|
||||
void format_string(char *dest, rct_string_id format, void *args);
|
||||
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);
|
||||
int get_string_length(char* buffer);
|
||||
int get_string_length(const utf8* buffer);
|
||||
|
||||
void user_string_clear_all();
|
||||
rct_string_id user_string_allocate(int base, const char *text);
|
||||
|
||||
@@ -759,7 +759,7 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget*
|
||||
case WIDX_LANGUAGE_DROPDOWN:
|
||||
for (i = 1; i < LANGUAGE_COUNT; i++) {
|
||||
gDropdownItemsFormat[i - 1] = 2777;
|
||||
gDropdownItemsArgs[i - 1] = (sint32)language_names[i];
|
||||
gDropdownItemsArgs[i - 1] = (sint32)LanguagesDescriptors[i].native_name;
|
||||
}
|
||||
window_options_show_dropdown(w, widget, LANGUAGE_COUNT - 1);
|
||||
gDropdownItemsChecked = 1 << (gCurrentLanguage - 1);
|
||||
@@ -1289,7 +1289,7 @@ static void window_options_paint(rct_window *w, rct_drawpixelinfo *dpi)
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224;
|
||||
gfx_draw_string(
|
||||
dpi,
|
||||
(char*)language_names[gCurrentLanguage],
|
||||
(char*)LanguagesDescriptors[gCurrentLanguage].native_name,
|
||||
w->colours[1],
|
||||
w->x + window_options_culture_widgets[WIDX_LANGUAGE].left + 1,
|
||||
w->y + window_options_culture_widgets[WIDX_LANGUAGE].top
|
||||
|
||||
Reference in New Issue
Block a user