|
[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
|
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 |
Henrique Rocha
Member #13,042
July 2011
|
That's painful but I'll try. Thanks
|
J-Gamer
Member #12,491
January 2011
|
No problem. " There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
kazzmir
Member #1,786
December 2001
|
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. 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
|
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 |
jmasterx
Member #11,410
October 2009
|
From Agui (works with Unicode) 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 }
Agui GUI API -> https://github.com/jmasterx/Agui |
Henrique Rocha
Member #13,042
July 2011
|
Thanks this is my result, with some extras like beginning from downside and a black background. 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
|
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 |
Henrique Rocha
Member #13,042
July 2011
|
Yup
|
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! Agui GUI API -> https://github.com/jmasterx/Agui |
ImLeftFooted
Member #3,935
October 2003
|
Looks like a fun project! Good times. |
|