diff --git a/genworld_gui.c b/genworld_gui.c --- a/genworld_gui.c +++ b/genworld_gui.c @@ -304,7 +304,7 @@ void GenerateLandscapeWndProc(Window *w, DrawString( 12, 91, STR_HEIGHTMAP_NAME, 0x10); SetDParam(0, _heightmap_str); - DrawStringTruncated(114, 91, STR_ORANGE, 0x10, 326 - 114 - GetStringWidth(buffer) - 5); + DrawStringTruncated(114, 91, STR_ORANGE, 0x10, 326 - 114 - GetStringBoundingBox(buffer).width - 5); /* TODO -- Remove next 2 lines if 32 widget limit is removed */ DrawFrameRect(114, 196, 219, 207, 12, 0); diff --git a/gfx.c b/gfx.c --- a/gfx.c +++ b/gfx.c @@ -358,7 +358,7 @@ int DrawStringRightAligned(int x, int y, int w; GetString(buffer, str); - w = GetStringWidth(buffer); + w = GetStringBoundingBox(buffer).width; DoDrawString(buffer, x - w, y, color); return w; @@ -369,7 +369,7 @@ void DrawStringRightAlignedTruncated(int char buffer[512]; TruncateStringID(str, buffer, maxw); - DoDrawString(buffer, x - GetStringWidth(buffer), y, color); + DoDrawString(buffer, x - GetStringBoundingBox(buffer).width, y, color); } void DrawStringRightAlignedUnderline(int x, int y, StringID str, uint16 color) @@ -386,7 +386,7 @@ int DrawStringCentered(int x, int y, Str GetString(buffer, str); - w = GetStringWidth(buffer); + w = GetStringBoundingBox(buffer).width; DoDrawString(buffer, x - w / 2, y, color); return w; @@ -401,7 +401,7 @@ int DrawStringCenteredTruncated(int xl, int DoDrawStringCentered(int x, int y, const char *str, uint16 color) { - int w = GetStringWidth(str); + int w = GetStringBoundingBox(str).width; DoDrawString(str, x - w / 2, y, color); return w; } @@ -478,7 +478,7 @@ void DrawStringMultiCenter(int x, int y, src = buffer; for (;;) { - w = GetStringWidth(src); + w = GetStringBoundingBox(src).width; DoDrawString(src, x - (w>>1), y, 0xFE); _cur_fontsize = _last_fontsize; @@ -539,26 +539,47 @@ void DrawStringMultiLine(int x, int y, S } } -int GetStringWidth(const char *str) +/** Return the string dimension in pixels. The height and width are returned + * in a single BoundingRect value. TINYFONT, BIGFONT modifiers are only + * supported as the first character of the string. The returned dimensions + * are therefore a rough estimation correct for all the current strings + * but not every possible combination + * @param str string to calculate pixel-width + * @return string width and height in pixels */ +BoundingRect GetStringBoundingBox(const char *str) { FontSize size = _cur_fontsize; - int w, max_w; + BoundingRect br; + int max_width; byte c; - w = max_w = 0; + br.width = br.height = max_width = 0; for (c = *str; c != '\0'; c = *(++str)) { if (c >= ASCII_LETTERSTART) { - w += GetCharacterWidth(size, c); + br.width += GetCharacterWidth(size, c); } else { - if (c == ASCII_SETX) str++; - else if (c == ASCII_SETXY) str += 2; - else if (c == ASCII_TINYFONT) size = FS_SMALL; - else if (c == ASCII_BIGFONT) size = FS_LARGE; - else if (c == ASCII_NL && w > max_w) {max_w = w; w = 0;} + switch (c) { + case ASCII_SETX: br.width += (byte)*str++; break; + case ASCII_SETXY: + br.width += (byte)*str++; + br.height += (byte)*str++; + break; + case ASCII_TINYFONT: size = FS_SMALL; break; + case ASCII_BIGFONT: size = FS_LARGE; break; + case ASCII_NL: + br.height += GetCharacterHeight(size); + if (br.width > max_width) { + max_width = br.width; + br.width = 0; + } + break; + } } } + br.height += GetCharacterHeight(size); - return max(w, max_w); + br.width = max(br.width, max_width); + return br; } diff --git a/gfx.h b/gfx.h --- a/gfx.h +++ b/gfx.h @@ -67,7 +67,7 @@ void DrawStringRightAlignedUnderline(int void GfxFillRect(int left, int top, int right, int bottom, int color); void GfxDrawLine(int left, int top, int right, int bottom, int color); -int GetStringWidth(const char *str); +BoundingRect GetStringBoundingBox(const char *str); void LoadStringWidthTable(void); void DrawStringMultiCenter(int x, int y, StringID str, int maxw); void DrawStringMultiLine(int x, int y, StringID str, int maxw); diff --git a/misc_gui.c b/misc_gui.c --- a/misc_gui.c +++ b/misc_gui.c @@ -666,7 +666,7 @@ void GuiShowTooltips(StringID string_id) GetString(buffer, string_id); - right = GetStringWidth(buffer) + 6; + right = GetStringBoundingBox(buffer).width + 6; /* Cut tooltip length to 200 pixels max, wrap to new line if longer */ bottom = 14; @@ -1776,7 +1776,7 @@ static void CheatsWndProc(Window *w, Win case STR_CHEAT_CHANGE_PLAYER: SetDParam(0, val); GetString(buf, STR_CHEAT_CHANGE_PLAYER); - DrawPlayerIcon(_current_player, 60 + GetStringWidth(buf), y + 2); + DrawPlayerIcon(_current_player, 60 + GetStringBoundingBox(buf).width, y + 2); break; /* Set correct string for switch climate cheat */ case STR_CHEAT_SWITCH_CLIMATE: val += STR_TEMPERATE_LANDSCAPE; diff --git a/openttd.h b/openttd.h --- a/openttd.h +++ b/openttd.h @@ -12,6 +12,11 @@ typedef struct Rect { int left,top,right,bottom; } Rect; +typedef struct BoundingRect { + int width; + int height; +} BoundingRect; + typedef struct Point { int x,y; } Point; diff --git a/players.c b/players.c --- a/players.c +++ b/players.c @@ -344,7 +344,7 @@ verify_name:; } GetString(buffer, str); - if (strlen(buffer) >= 32 || GetStringWidth(buffer) >= 150) + if (strlen(buffer) >= 32 || GetStringBoundingBox(buffer).width >= 150) goto bad_town_name; set_name:; @@ -451,7 +451,7 @@ restart:; SetDParam(0, p->president_name_2); GetString(buffer, p->president_name_1); - if (strlen(buffer) >= 32 || GetStringWidth(buffer) >= 94) + if (strlen(buffer) >= 32 || GetStringBoundingBox(buffer).width >= 94) continue; FOR_ALL_PLAYERS(pp) { diff --git a/texteff.c b/texteff.c --- a/texteff.c +++ b/texteff.c @@ -70,7 +70,7 @@ void CDECL AddTextMessage(uint16 color, /* Cut the message till it fits inside the chatbox */ length = strlen(buf); - while (GetStringWidth(buf) > _textmessage_width - 9) buf[--length] = '\0'; + while (GetStringBoundingBox(buf).width > _textmessage_width - 9) buf[--length] = '\0'; /* Find an empty spot and put the message there */ for (i = 0; i < MAX_CHAT_MESSAGES; i++) { @@ -247,7 +247,7 @@ void AddTextEffect(StringID msg, int x, te->params_2 = GetDParam(4); GetString(buffer, msg); - w = GetStringWidth(buffer); + w = GetStringBoundingBox(buffer).width; te->x = x - (w >> 1); te->right = x + (w >> 1) - 1; diff --git a/town_cmd.c b/town_cmd.c --- a/town_cmd.c +++ b/town_cmd.c @@ -889,7 +889,7 @@ restart: GetString(buf1, townnametype); // Check size and width - if (strlen(buf1) >= 31 || GetStringWidth(buf1) > 130) continue; + if (strlen(buf1) >= 31 || GetStringBoundingBox(buf1).width > 130) continue; FOR_ALL_TOWNS(t2) { // We can't just compare the numbers since diff --git a/viewport.c b/viewport.c --- a/viewport.c +++ b/viewport.c @@ -1018,13 +1018,13 @@ void UpdateViewportSignPos(ViewportSign sign->top = top; GetString(buffer, str); - w = GetStringWidth(buffer) + 3; + w = GetStringBoundingBox(buffer).width + 3; sign->width_1 = w; sign->left = left - w / 2; - // zoomed out version + /* zoomed out version */ _cur_fontsize = FS_SMALL; - w = GetStringWidth(buffer) + 3; + w = GetStringBoundingBox(buffer).width + 3; _cur_fontsize = FS_NORMAL; sign->width_2 = w; }