From 190e11d0168b1e225cb73595d15e291d29513e3a Mon Sep 17 00:00:00 2001 From: Bart van Strien Date: Sat, 3 Sep 2011 14:31:31 +0200 Subject: [PATCH] Move wrapping to Font::getWrap and make printf use that (fixes issue #230) --- src/modules/graphics/opengl/Font.cpp | 75 +++++++++++++---------- src/modules/graphics/opengl/Font.h | 8 +-- src/modules/graphics/opengl/Graphics.cpp | 36 +---------- src/modules/graphics/opengl/wrap_Font.cpp | 7 ++- 4 files changed, 52 insertions(+), 74 deletions(-) diff --git a/src/modules/graphics/opengl/Font.cpp b/src/modules/graphics/opengl/Font.cpp index a713bdee3..2859ed49b 100644 --- a/src/modules/graphics/opengl/Font.cpp +++ b/src/modules/graphics/opengl/Font.cpp @@ -28,6 +28,8 @@ #include #include +#include + #include // for max namespace love @@ -221,45 +223,54 @@ namespace opengl return g->spacing; } - int Font::getWrap(const std::string & line, float wrap, int * lines) + std::vector Font::getWrap(const std::string text, float wrap, int * max_width) { - if(line.size() == 0) return 0; + using namespace std; + const float width_space = static_cast(getWidth(' ')); + vector lines_to_draw; int maxw = 0; - int linen = 1; - int temp = 0; - std::string text; - Glyph * g; - - utf8::iterator i (line.begin(), line.begin(), line.end()); - utf8::iterator end (line.end(), line.begin(), line.end()); - while (i != end) { - if(temp > wrap && text.find(" ") != std::string::npos) - { - unsigned int space = text.find_last_of(' '); - std::string tmp = text.substr(0, space); - int w = getWidth(tmp); - if(w > maxw) maxw = w; - text = text.substr(space+1); - temp = getWidth(text); - linen++; + //split text at newlines + istringstream iss( text ); + string line; + while (getline(iss, line, '\n')) { + // split line into words + vector words; + istringstream word_iss(line); + copy(istream_iterator(word_iss), istream_iterator(), + back_inserter< vector >(words)); + + // put words back together until a wrap occurs + float width = 0.0f; + float oldwidth = 0.0f; + ostringstream string_builder; + vector::const_iterator word_iter; + for (word_iter = words.begin(); word_iter != words.end(); ++word_iter) { + string word( *word_iter ); + width += getWidth( word ); + + // on wordwrap, push line to line buffer and clear string builder + if (width >= wrap && oldwidth > 0) { + if (width > maxw) + maxw = width; + lines_to_draw.push_back( string_builder.str() ); + string_builder.str( "" ); + width = static_cast(getWidth( word )); + } + string_builder << word << " "; + width += width_space; + oldwidth = width; } - int c = *i++; - g = glyphs[c]; - if (!g) g = addGlyph(c); - temp += static_cast(g->spacing * mSpacing); - utf8::append(c, text.end()); + // push last line + if (width > maxw) + maxw = width; + lines_to_draw.push_back( string_builder.str() ); } - if(temp > maxw) maxw = temp; - if(lines) *lines = linen; + if (max_width) + *max_width = maxw; - return maxw; - } - - int Font::getWrap(const char * line, float wrap, int * lines) - { - return getWrap(std::string(line), wrap, lines); + return lines_to_draw; } void Font::setLineHeight(float height) diff --git a/src/modules/graphics/opengl/Font.h b/src/modules/graphics/opengl/Font.h index 8e64929f2..ef4d44a8e 100644 --- a/src/modules/graphics/opengl/Font.h +++ b/src/modules/graphics/opengl/Font.h @@ -135,12 +135,12 @@ namespace opengl * Returns the maximal width of a wrapped string * and optionally the number of lines * - * @param line A line of text + * @param text The input text * @param wrap The number of pixels to wrap at - * @param lines Optional output of the number of lines needed + * @param max_width Optional output of the maximum width + * Returns a vector with the lines. **/ - int getWrap(const std::string & line, float wrap, int *lines = 0); - int getWrap(const char * line, float wrap, int *lines = 0); + std::vector getWrap(const std::string text, float wrap, int * max_width = 0); /** * Sets the line height (which should be a number to multiply the font size by, diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 4a166caab..a8935ed7a 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -803,41 +803,7 @@ namespace opengl using namespace std; string text(str); - const float width_space = static_cast(currentFont->getWidth(' ')); - vector lines_to_draw; - - //split text at newlines - istringstream iss( text ); - string line; - while (getline(iss, line, '\n')) { - // split line into words - vector words; - istringstream word_iss(line); - copy(istream_iterator(word_iss), istream_iterator(), - back_inserter< vector >(words)); - - // put words back together until a wrap occurs - float width = 0.0f; - float oldwidth = 0.0f; - ostringstream string_builder; - vector::const_iterator word_iter; - for (word_iter = words.begin(); word_iter != words.end(); ++word_iter) { - string word( *word_iter ); - width += currentFont->getWidth( word ); - - // on wordwrap, push line to line buffer and clear string builder - if (width >= wrap && oldwidth > 0) { - lines_to_draw.push_back( string_builder.str() ); - string_builder.str( "" ); - width = static_cast(currentFont->getWidth( word )); - } - string_builder << word << " "; - width += width_space; - oldwidth = width; - } - // push last line - lines_to_draw.push_back( string_builder.str() ); - } + vector lines_to_draw = currentFont->getWrap(text, wrap); // now for the actual printing vector::const_iterator line_iter, line_end = lines_to_draw.end(); diff --git a/src/modules/graphics/opengl/wrap_Font.cpp b/src/modules/graphics/opengl/wrap_Font.cpp index 9d391b0bf..d7efb23b0 100644 --- a/src/modules/graphics/opengl/wrap_Font.cpp +++ b/src/modules/graphics/opengl/wrap_Font.cpp @@ -52,9 +52,10 @@ namespace opengl Font * t = luax_checkfont(L, 1); const char * str = luaL_checkstring(L, 2); float wrap = (float) luaL_checknumber(L, 3); - int lines = 0; - lua_pushinteger(L, t->getWrap(str, wrap, &lines)); - lua_pushinteger(L, lines); + int max_width = 0; + std::vector lines = t->getWrap(str, wrap, &max_width); + lua_pushinteger(L, max_width); + lua_pushinteger(L, lines.size()); return 2; }