Word Wrap function not working

Started by
35 comments, last by Dandi8 13 years, 9 months ago
Hey guys, I've made a text class using one of LazyFoo's tutorials and now I'm trying to make it go to a new line each time it reaches a certain wrapWidth (word wrapping, essentially).

The thing is, it seems to have problems with getting the 'next word' and counting its length. That much I have gathered from testing. But why doesn't the word length counting part work? I'm guessing I must be getting the word in a wrong way but I just can't figure it out. Please help? Code below.

void TextSystem::DrawWrapped(std::string text, int x, int y, int wrapWidth, int charWidth, GLfloat colorR, GLfloat colorG, GLfloat colorB){	int X = x, Y = y;	//If the font has been built	if( FontTex.Texture != NULL ){		//Go through the text		for( int show = 0; text[ show ] != '\0'; show++ )		{			//If the current character is a space			if( text[ show ] == ' ' ){ //Problems start about here				string nextWord = text.substr(show, text.find_first_of(' ', show));				int wordWidth;				wordWidth=0;				for( int showWord = 0; nextWord[ showWord ] != '\0'; showWord++ ){					int ascii = (unsigned char)nextWord[ showWord ];					int charW=32;					wordWidth+=charW;				} //Problems end about here				if(X+wordWidth > wrapWidth){					Y += (  charWidth / ( float(FontTex.Width)/16 )  ) *newLine;					X = x;				}				else				//Move over				X += space;			}			//If the current character is a newline			else if( text[ show ] == '\n' ){				//Move down				Y += (  charWidth / ( float(FontTex.Width)/16 )  ) *newLine;				//Move back				X = x;			}			else			{				//Get the ASCII value of the character				int ascii = (unsigned char)text[ show ];				//Show the character				int charW=(  charWidth / ( float(FontTex.Width)/16 )  ) *chars[ascii].w; //chars[ascii].w;				int charH=(  charWidth / ( float(FontTex.Width)/16 )  ) *chars[ascii].h;//chars[ascii].h;				int charSpace=(  charWidth / ( float(FontTex.Width)/16 )  ) *characterSpace;				Graphics.DrawTexturePart(FontTex, X, Y, charW, charH, chars[ascii].x, chars[ascii].y, chars[ascii].w, chars[ascii].h, colorR, colorG, colorB);				//Move over the width of the character with one pixel of padding				X += charW+charSpace;//+10;//chars[ ascii ].w + 10;			}		}	}}


[Edited by - Dandi8 on July 11, 2010 2:31:46 PM]
Advertisement
First of all (I haven't taken a look at the code yet) you have to calculate the length of the next word in advance.
The code always has to be a word in front of the actual print.

EDIT: the logic I use (pseudo-code):
//input: strpos = 0;i = 0;line_width = 0;while( str ){    pos = i;    if( str == '\n' )    {	newline = true;	line_width = 0;	i++;    }    while( 1 )    {        if( str == ' ' || str == '\n' || !str )        {            word_width = measure_width(str+pos,i-pos);             // first param:string, second param: number of chars to measure            line_width += word_width;            if( line_width > MAX_WIDTH ) // a new line has to be started            {                line_width = word_width;                newline = true;            }            if( str == ' ' ) // a new line has to be started            {                line_width += width_of_space;                i++;            }            break;        }        i++;    }    if( newline = true )    {   Position_back_to_new_line();        newline = false;    }    Print_the_portion_of_the_string(str+pos,i-pos);     // first param:start of string, second param: number of chars to print}


EDITED: don't ask why the code is so strange. It was long ago when I made this. I always reuse it.

EDIT FINISHED.

[Edited by - szecs on July 11, 2010 2:45:39 PM]
Yes, I know. That's what I'm doing, am I not?
Edited the post.
I suggest to use a while instead of for, if you ad new features (newline character, coloured string etc) it's better to increase/manipulate the counter explicitly inside the loop.
Did you notice that you calculate nextWord, but never actually do anything with it?
Okay, I actually took a look at the code. Are you sure you have proportional string? I mean so all the characters have the same width?

To be honest, it's pretty hard to read your code.
I'll have to take another look at it...
You seem to have a problem with your logic:
you look for a space, and if you find it and the string is wider than it should be, you start a new line.

BUT that's too late! The word already exceeds the allowed width! Otherwise it wouldn't trigger the new line. But the newline will only affect the next word, not the word that triggers it.

That's why I said you have to look one word after the actually printed word.

That's why my logic has an inner loop.
That actually means a word is looped through twice: once when checked, and once when it's printed.

You can't avoid this double check, because you have to know in advance, if a word will exceed the allowed width or not.

I hope that helps.
It's kinda hard to read it because LazyFoo's stuff is itself hard to read and I yet have to do some major overhaul to make the code more readable.

@Sicrane:
Wow, how could I have missed that...!?
Updated the code (also in the post). Unfortunately, the problem is still the same :(

EDIT:
I AM checking the word in advance and it's inside a separate loop so then the reading is supposed to go normally (as if there was no check at all) after the line break.

for( int showWord = 0; nextWord[ showWord ] != '\0'; showWord++ ){					int ascii = (unsigned char)nextWord[ showWord ];					int charW=32;//(  charWidth / ( float(FontTex.Width)/16 )  ) *chars[ascii].w;					wordWidth+=charW;				}

This is the part of the code where there is a problem. Notice that I'm using a loop that uses showWord. After that the code continues with the normal 'show' loop.
Read my above post + some info about my logic.

The checking for '\n' is done in front of the loop, because it affects the characters/word after the '\n'.

The checking for space and word wrap is done this way, because it affects the word before the space.
Oh, I guess I'm blind.
Sorry.

This topic is closed to new replies.

Advertisement