From c6815b6eec7e27ddacc17b70df382ebef971be9f Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Mon, 27 Jul 2015 17:21:21 +0100 Subject: [PATCH] implement utf8, part 8 --- src/drawing/string.c | 220 +++++++++----------------------- src/localisation/format_codes.h | 7 + src/localisation/localisation.c | 50 +++++--- 3 files changed, 97 insertions(+), 180 deletions(-) diff --git a/src/drawing/string.c b/src/drawing/string.c index 81aa881a24..43bae07a32 100644 --- a/src/drawing/string.c +++ b/src/drawing/string.c @@ -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. diff --git a/src/localisation/format_codes.h b/src/localisation/format_codes.h index ff82440447..0100520671 100644 --- a/src/localisation/format_codes.h +++ b/src/localisation/format_codes.h @@ -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 \ No newline at end of file diff --git a/src/localisation/localisation.c b/src/localisation/localisation.c index 4a8f966855..3eb79b2e19 100644 --- a/src/localisation/localisation.c +++ b/src/localisation/localisation.c @@ -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; } }