1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-16 11:33:03 +01:00

implement utf8, part 8

This commit is contained in:
IntelOrca
2015-07-27 17:21:21 +01:00
parent f14187f89d
commit c6815b6eec
3 changed files with 97 additions and 180 deletions

View File

@@ -105,7 +105,6 @@ void gfx_load_character_widths(){
}
}
/* rct2: 0x006C23B1 */
int gfx_get_string_width_new_lined(char* buffer){
// Current font sprites
@@ -177,7 +176,6 @@ int gfx_get_string_width_new_lined(char* buffer){
return max_width;
}
/**
* Return the width of the string in buffer
*
@@ -198,93 +196,43 @@ int gfx_get_string_width(char* buffer)
*/
int gfx_clip_string(utf8 *text, int width)
{
rct_g1_element g1_element;
uint16 fontSpriteBase;
int maxWidth;
int clippedWidth;
if (width < 6) {
*text = 0;
return 0;
}
fontSpriteBase = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16);
int dotCharacterWidth = _spriteFontCharacterWidths[fontSpriteBase + ('.' - ' ')];
int elipsisCharacterWidth = dotCharacterWidth * 3;
maxWidth = width - elipsisCharacterWidth;
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:
clippedWidth = *ch++;
break;
case FORMAT_ADJUST_PALETTE:
case 3:
case 4:
ch++;
break;
case FORMAT_NEWLINE:
case FORMAT_NEWLINE_SMALLER:
break;
case FORMAT_TINYFONT:
fontSpriteBase = 448;
break;
case FORMAT_SMALLFONT:
fontSpriteBase = 0;
break;
case FORMAT_MEDIUMFONT:
fontSpriteBase = 224;
break;
case FORMAT_BIGFONT:
fontSpriteBase = 672;
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:
g1_element = g1Elements[*((uint32*)(ch - 1)) & 0x7FFFF];
clippedWidth += g1_element.width;
ch += 4;
break;
default:
if (codepoint >= FORMAT_COLOUR_CODE_START || codepoint <= FORMAT_COLOUR_CODE_END) {
break;
}
if (codepoint <= 22) { //case 0x11? FORMAT_NEW_LINE_X_Y
ch += 2;
} else {
ch += 4;//never happens?
}
break;
}
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;
}
}
clippedWidth = gfx_get_string_width(text);
if (clippedWidth <= width) {
return clippedWidth;
}
return clippedWidth;
}
utf8 backup[4];
utf8 *ch = text;
utf8 *nextCh = text;
utf8 *clipCh = text;
int codepoint;
while ((codepoint = utf8_get_next(ch, &nextCh)) != 0) {
for (int i = 0; i < 4; i++) { backup[i] = nextCh[i]; };
for (int i = 0; i < 3; i++) { nextCh[i] = '.'; }
nextCh[3] = 0;
int queryWidth = gfx_get_string_width(text);
if (queryWidth < width) {
clipCh = nextCh;
clippedWidth = queryWidth;
} else {
for (int i = 0; i < 3; i++) { clipCh[i] = '.'; }
clipCh[3] = 0;
return clippedWidth;
}
for (int i = 0; i < 4; i++) { nextCh[i] = backup[i]; };
ch = nextCh;
}
return gfx_get_string_width(text);
}
/**
* Wrap the text in buffer to width, returns width of longest line.
@@ -299,112 +247,62 @@ int gfx_clip_string(utf8 *text, int width)
* num_lines (edi) - out
* font_height (ebx) - out
*/
int gfx_wrap_string(utf8 *text, int width, int *num_lines, int *font_height)
int gfx_wrap_string(utf8 *text, int width, int *outNumLines, int *outFontHeight)
{
int lineWidth = 0;
int maxWidth = 0;
rct_g1_element g1Element;
*num_lines = 0;
*font_height = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16);
*outNumLines = 0;
// Pointer to the start of the current word
utf8 *currentWord = NULL;
// Width of line up to current word
int currentWidth;
utf8 *ch = text;
utf8 *firstCh = 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 (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;
}
uint8 saveCh = *lastCh;
*lastCh = 0;
lineWidth = gfx_get_string_width(firstCh);
*lastCh = saveCh;
if (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);
(*outNumLines)++;
lineWidth = 0;
currentWord = NULL;
firstCh = ch;
} 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;
ch = currentWord;
*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;
}
maxWidth = max(maxWidth, currentWidth);
(*outNumLines)++;
lineWidth = 0;
currentWord = NULL;
firstCh = ch;
}
}
*outFontHeight = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16);
return maxWidth == 0 ? lineWidth : maxWidth;
}
/**
* Draws i formatted text string left aligned at i specified position but clips
* the text with an elipsis if the text width exceeds the specified width.

View File

@@ -98,6 +98,7 @@ enum {
// Extra non-ascii characters
FORMAT_AMINUSCULE = 159,
FORMAT_CENT = 162,
FORMAT_POUND = 163,
FORMAT_YEN = 165,
FORMAT_COPYRIGHT = 169,
@@ -126,6 +127,12 @@ enum {
FORMAT_TICK = 10003,
FORMAT_CROSS = 10005,
// Format codes that need suitable unicode allocations
FORMAT_SYMBOL_i = 20000,
FORMAT_SYMBOL_RAILWAY = 20001,
FORMAT_SYMBOL_ROAD = 20002,
FORMAT_SYMBOL_FLAG = 20003,
};
#endif

View File

@@ -156,31 +156,43 @@ bool utf8_should_use_sprite_for_codepoint(int codepoint)
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_AMINUSCULE: return 159 - 32;
case FORMAT_UP: return 160 - 32;
case FORMAT_RIGHT: return 175 - 32;
case FORMAT_SYMBOL_i: return 160 - 32;
case FORMAT_CENT: return 162 - 32;
case FORMAT_POUND: return 163 - 32;
case FORMAT_YEN: return 165 - 32;
case FORMAT_COPYRIGHT: return 169 - 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_LEFTGUILLEMET: return 171 - 32;
case FORMAT_TICK: return 172 - 32;
case FORMAT_CROSS: return 173 - 32;
case FORMAT_RIGHT: return 175 - 32;
case FORMAT_DEGREE: return 176 - 32;
case FORMAT_SYMBOL_RAILWAY: return 177 - 32;
case FORMAT_SQUARED: return 178 - 32;
case FORMAT_OPENQUOTES: return 180 - 32;
case FORMAT_EURO: return 181 - 32;
case FORMAT_SYMBOL_ROAD: return 182 - 32;
case FORMAT_SYMBOL_FLAG: return 183 - 32;
case FORMAT_APPROX: return 184 - 32;
case FORMAT_POWERNEGATIVEONE: return 185 - 32;
case FORMAT_BULLET: return 186 - 32;
case FORMAT_RIGHTGUILLEMET: return 187 - 32;
case FORMAT_SMALLUP: return 188 - 32;
case FORMAT_SMALLDOWN: return 189 - 32;
case FORMAT_LEFT: return 190 - 32;
case FORMAT_INVERTEDQUESTION: return 191 - 32;
default:
if (codepoint > 224) codepoint = 'W';
if (codepoint < 32 || codepoint >= 256) codepoint = '?';
return codepoint - 32;
}
}