Browse Source

Move wrapping to Font::getWrap and make printf use that (fixes issue #230)

Bart van Strien 14 years ago
parent
commit
190e11d016

+ 43 - 32
src/modules/graphics/opengl/Font.cpp

@@ -28,6 +28,8 @@
 #include <common/Matrix.h>
 #include <math.h>
 
+#include <sstream>
+
 #include <algorithm> // 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<std::string> 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<float>(getWidth(' '));
+		vector<string> lines_to_draw;
 		int maxw = 0;
-		int linen = 1;
-		int temp = 0;
-		std::string text;
-		Glyph * g;
 
-		
-		utf8::iterator<std::string::const_iterator> i (line.begin(), line.begin(), line.end());
-		utf8::iterator<std::string::const_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<string> words;
+			istringstream word_iss(line);
+			copy(istream_iterator<string>(word_iss), istream_iterator<string>(),
+					back_inserter< vector<string> >(words));
+
+			// put words back together until a wrap occurs
+			float width = 0.0f;
+			float oldwidth = 0.0f;
+			ostringstream string_builder;
+			vector<string>::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<float>(getWidth( word ));
+				}
+				string_builder << word << " ";
+				width += width_space;
+				oldwidth = width;
 			}
-			int c = *i++;
-			g = glyphs[c];
-			if (!g) g = addGlyph(c);
-			temp += static_cast<int>(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;
-
-		return maxw;
-	}
+		if (max_width)
+			*max_width = 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)

+ 4 - 4
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<std::string> 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,

+ 1 - 35
src/modules/graphics/opengl/Graphics.cpp

@@ -803,41 +803,7 @@ namespace opengl
 
 		using namespace std;
 		string text(str);
-		const float width_space = static_cast<float>(currentFont->getWidth(' '));
-		vector<string> lines_to_draw;
-
-		//split text at newlines
-		istringstream iss( text );
-		string line;
-		while (getline(iss, line, '\n')) {
-			// split line into words
-			vector<string> words;
-			istringstream word_iss(line);
-			copy(istream_iterator<string>(word_iss), istream_iterator<string>(),
-					back_inserter< vector<string> >(words));
-
-			// put words back together until a wrap occurs
-			float width = 0.0f;
-			float oldwidth = 0.0f;
-			ostringstream string_builder;
-			vector<string>::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<float>(currentFont->getWidth( word ));
-				}
-				string_builder << word << " ";
-				width += width_space;
-				oldwidth = width;
-			}
-			// push last line
-			lines_to_draw.push_back( string_builder.str() );
-		}
+		vector<string> lines_to_draw = currentFont->getWrap(text, wrap);
 
 		// now for the actual printing
 		vector<string>::const_iterator line_iter, line_end = lines_to_draw.end();

+ 4 - 3
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<std::string> lines = t->getWrap(str, wrap, &max_width);
+		lua_pushinteger(L, max_width);
+		lua_pushinteger(L, lines.size());
 		return 2;
 	}