From ab7a4c1cf77e176e5bc40192fe0ef1f7bf8d7be4 Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Fri, 15 Aug 2014 03:32:32 +0200 Subject: [PATCH] Have Font::write return the width of the drawn text This avoids having to do separate getTextWidth calls in several places. More getTextWidth calls could be saved by splitting the rendering of the font to an off-screen buffer from the final composition onto the destination surface: the routines that draw text inside a box have to compute the width before they can draw the box and currently the box has to be drawn before the text. --- src/font.cpp | 34 +++++++++++++++++++--------------- src/font.h | 12 ++++++++++-- src/gmenu2x.cpp | 13 ++++++------- 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/font.cpp b/src/font.cpp index e8fa7de..31bb273 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -6,6 +6,7 @@ #include #include +#include #include /* TODO: Let the theme choose the font and font size */ @@ -197,38 +198,38 @@ int Font::getTextHeight(const string &text) return nLines * getLineSpacing(); } -void Font::write(Surface& surface, const string &text, +int Font::write(Surface& surface, const string &text, int x, int y, HAlign halign, VAlign valign) { if (!font) { - return; + return 0; } size_t pos = text.find('\n', 0); if (pos == string::npos) { - writeLine(surface, text, x, y, halign, valign); + return writeLine(surface, text, x, y, halign, valign); } else { + int maxWidth = 0; size_t prev = 0; do { - writeLine(surface, text.substr(prev, pos - prev), - x, y, halign, valign); + maxWidth = max(maxWidth, + writeLine(surface, text.substr(prev, pos - prev), + x, y, halign, valign)); y += lineSpacing; prev = pos + 1; pos = text.find('\n', prev); } while (pos != string::npos); - writeLine(surface, text.substr(prev), x, y, halign, valign); + return max(maxWidth, + writeLine(surface, text.substr(prev), x, y, halign, valign)); } } -void Font::writeLine(Surface& surface, std::string const& text, +int Font::writeLine(Surface& surface, std::string const& text, int x, int y, HAlign halign, VAlign valign) { - if (!font) { - return; - } if (text.empty()) { // SDL_ttf will return a nullptr when rendering the empty string. - return; + return 0; } switch (valign) { @@ -246,17 +247,18 @@ void Font::writeLine(Surface& surface, std::string const& text, SDL_Surface *s = TTF_RenderUTF8_Blended(font, text.c_str(), color); if (!s) { ERROR("Font rendering failed for text \"%s\"\n", text.c_str()); - return; + return 0; } + const int width = s->w; switch (halign) { case HAlignLeft: break; case HAlignCenter: - x -= s->w / 2; + x -= width / 2; break; case HAlignRight: - x -= s->w; + x -= width; break; } @@ -287,8 +289,10 @@ void Font::writeLine(Surface& surface, std::string const& text, s = TTF_RenderUTF8_Blended(font, text.c_str(), color); if (!s) { ERROR("Font rendering failed for text \"%s\"\n", text.c_str()); - return; + return width; } SDL_BlitSurface(s, NULL, surface.raw, &rect); SDL_FreeSurface(s); + + return width; } diff --git a/src/font.h b/src/font.h index 1c2552e..3cc2e9e 100644 --- a/src/font.h +++ b/src/font.h @@ -38,7 +38,11 @@ public: return lineSpacing; } - void write(Surface& surface, + /** + * Draws a text on a surface in this font. + * @return The width of the text in pixels. + */ + int write(Surface& surface, const std::string &text, int x, int y, HAlign halign = HAlignLeft, VAlign valign = VAlignTop); @@ -48,7 +52,11 @@ private: std::string wordWrapSingleLine(const std::string &text, size_t start, size_t end, int width); - void writeLine(Surface& surface, std::string const& text, + /** + * Draws a single line of text on a surface in this font. + * @return The width of the text in pixels. + */ + int writeLine(Surface& surface, std::string const& text, int x, int y, HAlign halign, VAlign valign); TTF_Font *font; diff --git a/src/gmenu2x.cpp b/src/gmenu2x.cpp index 9c9c7da..b84a239 100644 --- a/src/gmenu2x.cpp +++ b/src/gmenu2x.cpp @@ -321,10 +321,9 @@ void GMenu2X::initBG() { if (sd) sd->blit(*bgmain, 3, bottomBarIconY); } - string df = getDiskFree(getHome().c_str()); - font->write(*bgmain, df, 22, bottomBarTextY, Font::HAlignLeft, Font::VAlignMiddle); + cpuX = 32 + font->write(*bgmain, getDiskFree(getHome().c_str()), + 22, bottomBarTextY, Font::HAlignLeft, Font::VAlignMiddle); - cpuX = font->getTextWidth(df) + 32; #ifdef ENABLE_CPUFREQ { auto cpu = OffscreenSurface::loadImage( @@ -1044,8 +1043,8 @@ int GMenu2X::drawButton(Surface& s, const string &btn, const string &text, int x if (sc.skinRes("imgs/buttons/"+btn+".png") != NULL) { sc["imgs/buttons/"+btn+".png"]->blit(s, x, y-7); re.w = sc["imgs/buttons/"+btn+".png"]->width() + 3; - font->write(s, text, x+re.w, y, Font::HAlignLeft, Font::VAlignMiddle); - re.w += font->getTextWidth(text); + re.w += font->write( + s, text, x+re.w, y, Font::HAlignLeft, Font::VAlignMiddle); } return x+re.w+6; } @@ -1056,8 +1055,8 @@ int GMenu2X::drawButtonRight(Surface& s, const string &btn, const string &text, x -= 16; sc["imgs/buttons/"+btn+".png"]->blit(s, x, y-7); x -= 3; - font->write(s, text, x, y, Font::HAlignRight, Font::VAlignMiddle); - return x-6-font->getTextWidth(text); + return x-6 - font->write( + s, text, x, y, Font::HAlignRight, Font::VAlignMiddle); } return x-6; }