Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [A5] Breaking lines when drawing text

Credits go to J-Gamer, jmasterx, and kazzmir for helping out!
This thread is locked; no one can reply to it. rss feed Print
[A5] Breaking lines when drawing text
Henrique Rocha
Member #13,042
July 2011

Is there any way to break the line in al_draw_textf when the text width exceeds a certain width?

And another question, if the text is according to the rule that I said above, what is the height of the text?

Thanks for helping ;)

J-Gamer
Member #12,491
January 2011
avatar

You'd have to calculate everything yourself... You can use sprintf to print what you want to a char*, and then use al_get_text_width to find out where you need to break your lines. Then put every line in another char* array or std::string and print those.

" There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo
"If your body was a business, thought would be like micro-management and emotions would be like macro-management. If you primarily live your life with emotions, then you are prone to error on the details. If you over-think things all the time you tend to lose scope of priorities." - Mark Oates

Henrique Rocha
Member #13,042
July 2011

That's painful but I'll try.

Thanks ;)

J-Gamer
Member #12,491
January 2011
avatar

No problem.

" There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo
"If your body was a business, thought would be like micro-management and emotions would be like macro-management. If you primarily live your life with emotions, then you are prone to error on the details. If you over-think things all the time you tend to lose scope of priorities." - Mark Oates

kazzmir
Member #1,786
December 2001
avatar

Here is some code I use to wrap lines. It wraps at the character level so it might put part of a word on the first line and the rest of the word on the next line.

#SelectExpand
1 2static vector< string > wrapStrings( const string & left, const string & right, const Font & font, int max, vector< string > accum ){ 3 if ( left == "" ){ 4 return accum; 5 } 6 7 int length = font.textLength(left.c_str()); 8 9 if (length >= max){ 10 return wrapStrings( left.substr( 0, left.length() / 2 ), left.substr( left.length() / 2 ) + right, font, max, accum ); 11 } else if ( length >= max - font.textLength( "E" ) || right == "" ){ 12 accum.push_back( left ); 13 return wrapStrings( right, "", font, max, accum ); 14 } else { 15 return wrapStrings( left + right.substr( 0, 1 ), right.substr( 1 ), font, max, accum ); 16 } 17} 18 19void Font::printfWrapLine(int x, int & y, Graphics::Color color, const Graphics::Bitmap & work, int maxWidth, const char * line) const { 20 vector< string > all; 21 all = wrapStrings(string(line), "", *this, maxWidth, all ); 22 for ( vector< string >::iterator str = all.begin(); str != all.end(); str++ ){ 23 printf(x, y, color, work, *str, 0); 24 y += getHeight(); 25 } 26 y += getHeight() / 2; 27}

J-Gamer
Member #12,491
January 2011
avatar

When I did this, I had a function that returned a "std::vector<std::string> words" from a string holding a text. To do this, I searched for spaces and cut accordingly.

" There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo
"If your body was a business, thought would be like micro-management and emotions would be like macro-management. If you primarily live your life with emotions, then you are prone to error on the details. If you over-think things all the time you tend to lose scope of priorities." - Mark Oates

jmasterx
Member #11,410
October 2009

From Agui (works with Unicode)

#SelectExpand
1void TextBox::makeLinesFromWordWrap() 2 { 3 textRows.clear(); 4 textRows.push_back(""); 5 std::string curStr; 6 std::string curWord; 7 8 int curWordWidth = 0; 9 int curLetterWidth = 0; 10 int curLineWidth = 0; 11 12 bool isVscroll = pChildVScroll->isVisible(); 13 int voffset = 0; 14 if(isVscroll) 15 { 16 voffset = pChildVScroll->getWidth(); 17 } 18 int AdjWidthMinusVoffset = getAdjustedWidth() - voffset; 19 int len = getTextLength(); 20 int bytesSkipped = 0; 21 int letterLength = 0; 22 size_t ind = 0; 23 24 for(int i = 0; i < len; ++i) 25 { 26 27 //get the unicode character 28 letterLength = unicodeFunctions.bringToNextUnichar(ind,getText()); 29 curStr = getText().substr(bytesSkipped,letterLength); 30 31 32 bytesSkipped += letterLength; 33 34 curLetterWidth = getTextWidth(curStr); 35 36 //push a new line 37 if(curStr[0] == '\n') 38 { 39 textRows.back() += curWord; 40 curWord = ""; 41 curLetterWidth = 0; 42 curWordWidth = 0; 43 curLineWidth = 0; 44 textRows.push_back(""); 45 continue; 46 } 47 48 49 50 //ensure word is not longer than the width 51 if(curWordWidth + curLetterWidth >= AdjWidthMinusVoffset) 52 { 53 textRows.back() += curWord; 54 55 textRows.push_back(""); 56 curWord = ""; 57 curWordWidth = 0; 58 curLineWidth = 0; 59 } 60 61 //add letter to word 62 curWord += curStr; 63 curWordWidth += curLetterWidth; 64 65 66 //if we need a Vscroll bar start over 67 if(!isVscroll && isVScrollNeeded()) 68 { 69 isVscroll = true; 70 voffset = pChildVScroll->getWidth(); 71 AdjWidthMinusVoffset = getAdjustedWidth() - voffset; 72 i = -1; 73 curWord = ""; 74 curStr = ""; 75 textRows.clear(); 76 textRows.push_back(""); 77 ind = 0; 78 79 curWordWidth = 0; 80 curLetterWidth = 0; 81 curLineWidth = 0; 82 83 bytesSkipped = 0; 84 continue; 85 } 86 87 if(curLineWidth + curWordWidth >= 88 AdjWidthMinusVoffset && textRows.back().length() >= 1) 89 { 90 textRows.push_back(""); 91 curLineWidth = 0; 92 } 93 94 if(isSplittingWords()) 95 { 96 if(curStr[0] == ' ' || curStr[0] == '-') 97 { 98 textRows.back() += curWord; 99 curLineWidth += curWordWidth; 100 curWord = ""; 101 curWordWidth = 0; 102 } 103 } 104 105 } 106 107 if(curWord != "") 108 { 109 textRows.back() += curWord; 110 } 111 updateWidestLine(); 112 113 lineOffset.clear(); 114 for(size_t i = 0; i < textRows.size(); ++i) 115 { 116 switch(getTextAlignment()) 117 { 118 case ALIGN_LEFT: 119 lineOffset.push_back(0); 120 break; 121 case ALIGN_CENTER: 122 lineOffset.push_back((AdjWidthMinusVoffset - 123 getTextWidth(textRows[i])) / 2); 124 break; 125 case ALIGN_RIGHT: 126 lineOffset.push_back(AdjWidthMinusVoffset - 127 getTextWidth(textRows[i])); 128 break; 129 } 130 131 } 132 }

Henrique Rocha
Member #13,042
July 2011

Thanks ;) this is my result, with some extras like beginning from downside and a black background.
{"name":"snapshot2vc.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/6\/2\/62728419b04e5a00edc3d29ca1932fcd.png","w":1600,"h":797,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/6\/2\/62728419b04e5a00edc3d29ca1932fcd"}snapshot2vc.png

#SelectExpand
1int era_draw_textf_width(ALLEGRO_FONT * f, ALLEGRO_COLOR color,int x, int y, int align, char * text, int width){ 2 ALLEGRO_BITMAP * target_bu = al_get_target_bitmap(); 3 int ly = al_get_font_line_height(f); 4 char * word = NULL; 5 char * text_cpy = (char*) malloc ((strlen(text)+1)*(sizeof (char))); 6 char * test_line = (char*) malloc (width*(sizeof (char))); 7 char * line = (char*) malloc (width*(sizeof (char))); 8 9 LIST * all_lines = NULL; 10 char * push_line = NULL; 11 LIST * ptr_line = NULL; 12 int box_sz; 13 int lines = 0; 14 ALLEGRO_BITMAP * box; 15 16 strcpy(text_cpy,text); 17 strcpy(line," \0"); 18 strcpy(test_line," \0"); 19 20 word = strtok (text_cpy," \0"); 21 while(word!=NULL){ 22 strcat(test_line,word); 23 strcat(test_line," "); 24 if(al_get_text_width(f, test_line)<width){ 25 strcat(line,word); 26 strcat(line," "); 27 } 28 else{ 29 push_line = (char*) malloc (width*(sizeof (char))); 30 strcpy(push_line,line); 31 push(&all_lines,push_line); 32 sprintf(test_line," %s ",word); 33 sprintf(line," %s ",word); 34 } 35 word = strtok (NULL," \0"); 36 } 37 push_line = (char*) malloc (width*(sizeof (char))); 38 strcpy(push_line,line); 39 push(&all_lines,push_line); 40 41 lines = sizeof_list(all_lines); 42 box_sz = lines*al_get_font_line_height(f); 43 44 box = al_create_bitmap(width, box_sz); 45 al_set_target_bitmap(box); 46 al_clear_to_color(BLACK); 47 48 al_set_target_bitmap(target_bu); 49 50 al_draw_tinted_bitmap(box,ALPHA_07,x, y-box_sz,0); 51 for(ptr_line=all_lines; ptr_line!=NULL; ptr_line = ptr_line->next){ 52 al_draw_textf(f,color, x, y-ly,align,"%s",(char*)ptr_line->info); 53 ly += al_get_font_line_height(f); 54 } 55 56 apaga_list(&all_lines); 57 free(line); 58 free(test_line); 59 free(text_cpy); 60 return box_sz; 61}

J-Gamer
Member #12,491
January 2011
avatar

Looks like AoE to me :p

But well done!

" There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo
"If your body was a business, thought would be like micro-management and emotions would be like macro-management. If you primarily live your life with emotions, then you are prone to error on the details. If you over-think things all the time you tend to lose scope of priorities." - Mark Oates

Henrique Rocha
Member #13,042
July 2011

Yup ;D

jmasterx
Member #11,410
October 2009

Just a couple of things.

If you have not done so, you should comment your function since certain things like a call to strtok might not be so obvious in a few months.

I also noticed you have an 'f' at the end of text (textf) in your function name but you do not use string formatting (see printf) so I'd find the f misleading unless your game uses it as part of its naming convention.

Other than that, looks great!

ImLeftFooted
Member #3,935
October 2003
avatar

Looks like a fun project! Good times. :D

Go to: