textbox.cpp

Go to the documentation of this file.
00001 
00002 //            Copyright (C) 2004-2007 by The Allacrost Project
00003 //                         All Rights Reserved
00004 //
00005 // This code is licensed under the GNU GPL version 2. It is free software
00006 // and you may modify it and/or redistribute it under the terms of this license.
00007 // See http://www.gnu.org/copyleft/gpl.html for details.
00009 
00010 #include <sstream>
00011 
00012 #include "utils.h"
00013 #include "video.h"
00014 #include "textbox.h"
00015 #include "menu_window.h"
00016 
00017 using namespace std;
00018 using namespace hoa_utils;
00019 using namespace hoa_video;
00020 using namespace hoa_video::private_video;
00021 
00022 namespace hoa_video {
00023 
00024 TextBox::TextBox() 
00025 : _width(0.0f),
00026   _height(0.0f),
00027   _display_speed(0.0f),
00028   _text_xalign(VIDEO_X_LEFT),
00029   _text_yalign(VIDEO_Y_BOTTOM),
00030   _num_chars(0),
00031   _finished(false),
00032   _current_time(0),
00033   _mode(VIDEO_TEXT_INSTANT),
00034   _text_color(Color::white)
00035 {
00036   _initialized = false;
00037 }
00038 
00039 TextBox::TextBox(float x, float y, float width, float height, const TEXT_DISPLAY_MODE &mode)
00040 : _width(width),
00041   _height(height),
00042   _display_speed(0.0f),
00043   _text_xalign(VIDEO_X_LEFT),
00044   _text_yalign(VIDEO_Y_BOTTOM),
00045   _num_chars(0),
00046   _finished(false),
00047   _current_time(0),
00048   _mode(mode),
00049   _text_color(Color::white)
00050 {
00051   SetPosition(x, y);
00052   _initialized = false;
00053 }
00054 
00055 
00056 TextBox::~TextBox() {
00057   // Does nothing since TextBox doesn't allocate any memory
00058 }
00059 
00060 
00061 
00062 void TextBox::ClearText() {
00063   _finished = true;
00064   _text.clear();
00065   _num_chars = 0;
00066 }
00067 
00068 
00069 
00070 void TextBox::Update(uint32 time) {
00071   _current_time += time;
00072 
00073   if (_text.empty() == false && _current_time > _end_time)
00074     _finished = true;
00075 }
00076 
00077 
00078 
00079 void TextBox::Draw() {
00080   if (_text.empty())
00081     return;
00082 
00083   if (_initialized == false) {
00084     if (VIDEO_DEBUG)
00085       cerr << "VIDEO WARNING: TextBox::Draw() failed because the textbox was not initialized:\n" << _initialization_errors << endl;
00086     return;
00087   }
00088 
00089   // Take the following steps to draw the text:
00090   //  (1): Save the video engine's context and enable appropriate draw settings
00091   //  (2): Determine the coordinates of the textbox rectangle to draw
00092   //  (3): Create a ScreenRect for the textbox area and apply scissoring if its enabled
00093   //  (4): Determine the text draw position from the alignment flags
00094   //  (5): Draw each line of text to the screen
00095   //  (6): Restore the original video engine context
00096   VideoManager->_PushContext();
00097 
00098   VideoManager->SetDrawFlags(_xalign, _yalign, VIDEO_BLEND, 0);
00099   VideoManager->SetFont(_font);
00100 
00101   // Stores the positions of the four sides of the rectangle
00102   float left   = 0.0f;
00103   float right  = _width;
00104   float bottom = 0.0f;
00105   float top    = _height;
00106 
00107   CalculateAlignedRect(left, right, bottom, top);
00108 
00109   // Create a screen rectangle for the position and apply any scissoring
00110   int32 x, y, w, h;
00111 
00112   x = static_cast<int32>(left < right ? left : right);
00113   y = static_cast<int32>(top < bottom ? top : bottom);
00114   w = static_cast<int32>(right - left);
00115   h = static_cast<int32>(top - bottom);
00116 
00117   if (w < 0)
00118     w = -w;
00119   if (h < 0)
00120     h = -h;
00121 
00122   ScreenRect rect(x, y, w, h);
00123 
00124   /* XXX: Disabled buggy
00125   if (_owner) {
00126     rect.Intersect(_owner->GetScissorRect());
00127   }
00128   rect.Intersect(VideoManager->GetScissorRect());
00129   VideoManager->EnableScissoring(_owner || VideoManager->IsScissoringEnabled());
00130   if (VideoManager->IsScissoringEnabled()) {
00131     VideoManager->SetScissorRect(rect);
00132   }
00133   */
00134 
00135   // Holds the height of the text to be drawn
00136   float text_height = static_cast<float>(_CalculateTextHeight());
00137   // Holds the x and y position where the text should be drawn
00138   float text_xpos, text_ypos;
00139 
00140   // Determine the vertical position of the text based on the alignment
00141   if (_yalign == VIDEO_Y_TOP) {
00142     text_ypos = top;
00143   }
00144   else if (_yalign == VIDEO_Y_CENTER) {
00145     text_ypos = top - (VideoManager->_coord_sys.GetVerticalDirection() * (_height - text_height) * 0.5f);
00146   }
00147   else { // (_yalign == VIDEO_Y_BOTTOM)
00148     text_ypos = top - (VideoManager->_coord_sys.GetVerticalDirection() * (_height - text_height));
00149   }
00150 
00151   // Determine the horizontal position of the text based on the alignment
00152   if (_text_xalign == VIDEO_X_LEFT) {
00153     text_xpos = left;
00154   }
00155   else if (_text_xalign == VIDEO_X_CENTER) {
00156     text_xpos = (left + right) * 0.5f;
00157   }
00158   else { // (_text_xalign == VIDEO_X_RIGHT)
00159     text_xpos = right;
00160   }
00161 
00162   // Set the draw cursor, draw flags, and draw the text
00163   VideoManager->Move(0.0f, text_ypos);
00164   VideoManager->SetDrawFlags(VIDEO_X_LEFT, VIDEO_Y_TOP, VIDEO_BLEND, 0);
00165   Color oldColor = VideoManager->GetTextColor();
00166   VideoManager->SetTextColor(_text_color);
00167   _DrawTextLines(text_xpos, text_ypos, rect);
00168   VideoManager->SetTextColor(oldColor);
00169 
00170   VideoManager->_PopContext();
00171 } // void TextBox::Draw()
00172 
00173 
00174 
00175 void TextBox::SetDimensions(float w, float h) {
00176   if (w <= 0.0f || w > 1024.0f) {
00177     if (VIDEO_DEBUG)
00178       cerr << "VIDEO WARNING: TextBox::SetDimensions() failed, invalid width: " << w << endl;
00179     return;
00180   }
00181 
00182   if (h <= 0.0f || h > 768.0f) {
00183     if (VIDEO_DEBUG)
00184       cerr << "VIDEO WARNING: TextBox::SetDimensions() failed, invalid height: " << h << endl;
00185     return;
00186   }
00187 
00188   _width = w;
00189   _height = h;
00190   _ReformatText();
00191 }
00192 
00193 
00194 
00195 
00196 void TextBox::SetTextAlignment(int32 xalign, int32 yalign) {
00197   _text_xalign = xalign;
00198   _text_yalign = yalign;
00199 }
00200 
00201 
00202 
00203 void TextBox::SetFont(const string& font_name) {
00204   _font_properties = VideoManager->GetFontProperties(font_name);
00205   if (_font_properties == NULL) {
00206     if (VIDEO_DEBUG)
00207       cerr << "VIDEO WARNING: TextBox::SetFont() failed because it was passed an invalid font name: " << font_name << endl;
00208     return;
00209   }
00210 
00211   _font = font_name;
00212   _ReformatText();
00213   _initialized = true;
00214 }
00215 
00216 
00217 
00218 void TextBox::SetDisplayMode(const TEXT_DISPLAY_MODE &mode) {
00219   if (mode < VIDEO_TEXT_INSTANT || mode >= VIDEO_TEXT_TOTAL) {
00220     cerr << "VIDEO WARNING: TextBox::SetDisplayMode() failed because of an invalid mode argument: " << mode << endl;
00221     return;
00222   }
00223 
00224   _mode = mode;
00225 }
00226 
00227 
00228 
00229 void TextBox::SetDisplaySpeed(float display_speed) {
00230   if (display_speed <= 0.0f) {
00231     if (VIDEO_DEBUG)
00232       cerr << "VIDEO WARNING: TextBox::SetDisplaySpeed() failed due to an invalid display speed: " << display_speed << endl;
00233     return;
00234   }
00235 
00236   _display_speed = display_speed;
00237 }
00238 
00239 
00240 
00241 void TextBox::SetDisplayText(const ustring& text) {
00242   if (_initialized == false) {
00243     if (VIDEO_DEBUG)
00244       cerr << "VIDEO WARNING: TextBox::SetDisplayText() failed because the textbox was not initialized:\n" << _initialization_errors << endl;
00245     return;
00246   }
00247 
00248   _text_save = text;
00249   _ReformatText();
00250 
00251   // Reset the timer since new text has been set
00252   _current_time = 0;
00253 
00254   // (3): Determine how much time the text will take to display depending on the display mode, speed, and size of the text
00255   _finished = false;
00256   switch(_mode) {
00257     case VIDEO_TEXT_INSTANT:
00258       _end_time = 0;
00259       // (4): Set finished to true only if the display mode is VIDEO_TEXT_INSTANT
00260       _finished = true;
00261       break;
00262 
00263     case VIDEO_TEXT_CHAR:     // All three of these modes display one character at a time
00264     case VIDEO_TEXT_FADECHAR:
00265     case VIDEO_TEXT_REVEAL:
00266       // We desire the total number of milliseconds to render the string.
00267       // Display speed is in character per second, so cancel the character term and multiply by 1000 to get ms
00268       _end_time = static_cast<int32>(1000.0f * _num_chars / _display_speed);
00269       break;
00270 
00271     case VIDEO_TEXT_FADELINE:   // Displays one line at a time
00272       // Instead of _num_chars in the other calculation, we use number of lines times CHARS_PER_LINE
00273       _end_time = static_cast<int32>(1000.0f * (_text.size() * CHARS_PER_LINE) / _display_speed);
00274       break;
00275 
00276     default:
00277       _end_time = 0;
00278       if (VIDEO_DEBUG)
00279         cerr << "VIDEO WARNING: unknown display mode was set in TextBox::SetDisplayText(): " << _mode << endl;
00280       break;
00281   };
00282 
00283 } // void TextBox::SetDisplayText(const ustring& text)
00284 
00285 
00286 void TextBox::_ReformatText() {
00287   // (1): Go through the text ustring and determine where the newline characters can be found, examining one line at a time and adding it to the _text vector.
00288   size_t newline_pos;
00289   ustring temp_str = _text_save;
00290   _text.clear();
00291   _num_chars = 0;
00292 
00293 
00294   // If font not set, return (leave _text vector empty)
00295   if (!_font_properties) {
00296     if (VIDEO_DEBUG) {
00297       cerr << "VIDEO WARNING: TextBox::_ReformatText() with invalid font." << endl;
00298     }
00299     return;
00300   }
00301 
00302   while (true) {
00303     newline_pos = temp_str.find(NEWLINE_CHARACTER);
00304 
00305     // If the end of the string has been reached, add the new line and exit
00306     if (newline_pos == ustring::npos) {
00307       _AddLine(temp_str);
00308       break;
00309     }
00310     // Otherwise, add the new line segment and proceed to find the next
00311     else {
00312       _AddLine(temp_str.substr(0, newline_pos));
00313       temp_str = temp_str.substr(newline_pos + 1, temp_str.length() - newline_pos);
00314     }
00315   }
00316 
00317   // (2): Calculate the height of the text and check it against the height of the textbox.
00318   int32 text_height = _CalculateTextHeight();
00319 
00320   if (text_height > _height) {
00321     if (VIDEO_DEBUG) {
00322       cerr << "VIDEO WARNING: In TextBox::_ReformatText() tried to display text of height (";
00323       cerr << text_height << ") in a window of lower height (" << _height << ")" << endl;
00324     }
00325   }
00326 
00327 
00328 } // void TextBox::_ReformatText()
00329 
00330 void TextBox::SetDisplayText(const string &text) {
00331   ustring wstr = MakeUnicodeString(text);
00332   SetDisplayText(wstr);
00333 }
00334 
00335 
00336 
00337 bool TextBox::IsInitialized(string& errors) {
00338   errors.clear();
00339   ostringstream stream;
00340 
00341 
00342   // Check font
00343   if (_font.empty())
00344     stream << "* Invalid font: no font has been set" << endl;
00345   else if (VideoManager->IsValidFont(_font) == false)
00346     stream << "* Invalid font: " << _font << endl;
00347 
00348   errors = stream.str();
00349 
00350   if (errors.empty()) {
00351     _initialized = true;
00352   }
00353   else {
00354     _initialized = false;
00355   }
00356 
00357   return _initialized;
00358 } // bool TextBox::IsInitialized(string& errors)
00359 
00360 
00361 
00362 int32 TextBox::_CalculateTextHeight() {
00363   if (_text.empty())
00364     return 0;
00365   else
00366     return _font_properties->height + _font_properties->line_skip * (static_cast<int32>(_text.size()) - 1);
00367 }
00368 
00369 
00370 
00371 void TextBox::_AddLine(const ustring& line) {
00372   // perform word wrapping in a loop until all the text is added
00373 
00374   ustring temp_line = line;
00375 
00376   while (temp_line.empty() == false) {
00377     int32 text_width = VideoManager->CalculateTextWidth(_font, line);
00378 
00379     // If the text can fit in the text box, add the whole line and return
00380     if (text_width < _width) {
00381       _text.push_back(temp_line);
00382       _num_chars += static_cast<int32>(temp_line.size());
00383       return;
00384     }
00385 
00386     // Otherwise, find the maximum number of words which can fit and make that substring a line
00387     // Word boundaries are found by calling the _IsCharacterBreakable() method
00388     ustring wrapped_line;
00389     int32 num_wrapped_chars = 0;
00390     int32 last_breakable_index = -1;
00391     int32 line_length = static_cast<int32>(temp_line.length());
00392 
00393     while (num_wrapped_chars < line_length) {
00394       wrapped_line += temp_line[num_wrapped_chars];
00395 
00396       if (_IsBreakableChar(temp_line[num_wrapped_chars])) {
00397         int32 text_width = VideoManager->CalculateTextWidth(_font, wrapped_line);
00398 
00399         if (text_width < _width) {
00400           // We haven't gone past the breaking point: mark this as a possible breaking point
00401           last_breakable_index = num_wrapped_chars;
00402         }
00403         else {
00404           // We exceeded the maximum width, so go back to the previous breaking point.
00405           // If there was no previous breaking point (== -1), then just break it off at
00406           // the current character position.
00407           if (last_breakable_index != -1)
00408             num_wrapped_chars = last_breakable_index;
00409           break;
00410         }
00411       } // (_IsBreakableChar(temp_line[num_wrapped_chars]))
00412       ++num_wrapped_chars;
00413     } // while (num_wrapped_chars < line_length)
00414 
00415     // Figure out the number of characters in the wrapped line and construct the wrapped line
00416     text_width = VideoManager->CalculateTextWidth(_font, wrapped_line);
00417     if (text_width >= _width && last_breakable_index != -1) {
00418       num_wrapped_chars = last_breakable_index;
00419     }
00420     wrapped_line = temp_line.substr(0, num_wrapped_chars);
00421 
00422     // Add the new wrapped line to the text.
00423     _text.push_back(wrapped_line);
00424     _num_chars += static_cast<int32>(wrapped_line.size());
00425 
00426     // If there is no more text remaining, we are finished.
00427     if (num_wrapped_chars == line_length)
00428       return;
00429     // Otherwise, we need to grab the rest of the text that remains to be added and loop again
00430     else
00431       temp_line = temp_line.substr(num_wrapped_chars + 1, line_length - num_wrapped_chars);
00432   } // while (temp_line.empty() == false)
00433 } // void TextBox::_AddLine(const ustring& line)
00434 
00435 
00436 
00437 bool TextBox::_IsBreakableChar(uint16 character) {
00438   if (character == 0x20)
00439     return true;
00440 
00441   return false;
00442 }
00443 
00444 
00445 
00446 void TextBox::_DrawTextLines(float text_x, float text_y, ScreenRect scissor_rect) {
00447   int32 num_chars_drawn = 0;
00448 //  // A quick
00449 //  TEXT_DISPLAY_MODE mode = _mode;
00450 //
00451 //  if (_finished)
00452 //    mode = VIDEO_TEXT_INSTANT;
00453 
00454   // Calculate the fraction of the text to display
00455   float percent_complete;
00456   if (_finished)
00457     percent_complete = 1.0f;
00458   else
00459     percent_complete = static_cast<float>(_current_time) / static_cast<float>(_end_time);
00460 
00461   // Iterate through the loop for every line of text and draw it
00462   for (int32 line = 0; line < static_cast<int32>(_text.size()); ++line) {
00463     // (1): Calculate the x draw offset for this line and move to that position
00464     float line_width = static_cast<float>(VideoManager->CalculateTextWidth(_font, _text[line]));
00465     int32 x_align = VideoManager->_ConvertXAlign(_text_xalign);
00466     float x_offset = text_x + ((x_align + 1) * line_width) * 0.5f * VideoManager->_coord_sys.GetHorizontalDirection();
00467     VideoManager->MoveRelative(x_offset, 0.0f);
00468 
00469     int32 line_size = static_cast<int32>(_text[line].size());
00470 
00471     // (2): Draw the text depending on the display mode and whether or not the gradual display is finished
00472     if (_finished || _mode == VIDEO_TEXT_INSTANT) {
00473       VideoManager->DrawText(_text[line]);
00474     }
00475 
00476     else if (_mode == VIDEO_TEXT_CHAR) {
00477       // Determine which character is currently being rendered
00478       int32 cur_char = static_cast<int32>(percent_complete * _num_chars);
00479 
00480       // If the current character to draw is after this line, render the entire line
00481       if (num_chars_drawn + line_size < cur_char) {
00482         VideoManager->DrawText(_text[line]);
00483       }
00484       // The current character to draw is on this line: figure out which characters on this line should be drawn
00485       else {
00486         int32 num_completed_chars = cur_char - num_chars_drawn;
00487         if (num_completed_chars > 0) {
00488           ustring substring = _text[line].substr(0, num_completed_chars);
00489           VideoManager->DrawText(substring);
00490         }
00491       }
00492     } // else if (_mode == VIDEO_TEXT_CHAR)
00493 
00494     else if (_mode == VIDEO_TEXT_FADECHAR) {
00495       // Figure out which character is currently being rendered
00496       float fade_cur_char = percent_complete * _num_chars;
00497       int32 cur_char = static_cast<int32>(fade_cur_char);
00498       float cur_percent = fade_cur_char - cur_char;
00499 
00500       // If the current character to draw is after this line, draw the whole line
00501       if (num_chars_drawn + line_size <= cur_char) {
00502         VideoManager->DrawText(_text[line]);
00503       }
00504       // The current character is on this line: draw any previous characters on this line as well as the current character
00505       else {
00506         int32 num_completed_chars = cur_char - num_chars_drawn;
00507 
00508         // Continue only if this line has at least one character that should be drawn
00509         if (num_completed_chars >= 0) {
00510           ustring substring;
00511 
00512           // Draw any fully completed characters at full opacity
00513           if (num_completed_chars > 0) {
00514             substring = _text[line].substr(0, num_completed_chars);
00515             VideoManager->DrawText(substring);
00516           }
00517 
00518           // Draw the current character that is being faded in at the appropriate alpha level
00519           Color old_color = VideoManager->GetTextColor();
00520           Color new_color = old_color;
00521           new_color[3] *= cur_percent;
00522 
00523           VideoManager->SetTextColor(new_color);
00524           VideoManager->MoveRelative(static_cast<float>(VideoManager->CalculateTextWidth(_font, substring)), 0.0f);
00525           VideoManager->DrawText(_text[line].substr(num_completed_chars, 1));
00526           VideoManager->SetTextColor(old_color);
00527         }
00528       }
00529     } // else if (_mode == VIDEO_TEXT_FADECHAR)
00530 
00531     else if (_mode == VIDEO_TEXT_FADELINE) {
00532       // Deteremine which line is currently being rendered
00533       float fade_lines = percent_complete * _text.size();
00534       int32 lines = static_cast<int32>(fade_lines);
00535       float cur_percent = fade_lines - lines;
00536 
00537       // If this line comes before the line being rendered, simply draw the line and be done with it
00538       if (line < lines) {
00539         VideoManager->DrawText(_text[line]);
00540       }
00541       // Otherwise if this is the line being rendered, determine the amount of alpha for the line being faded in and draw it
00542       else if (line == lines) {
00543         Color old_color = VideoManager->GetTextColor();
00544         Color new_color = old_color;
00545         new_color[3] *= cur_percent;
00546 
00547         VideoManager->SetTextColor(new_color);
00548         VideoManager->DrawText(_text[line]);
00549         VideoManager->SetTextColor(old_color);
00550       }
00551     } // else if (_mode == VIDEO_TEXT_FADELINE)
00552 
00553     else if (_mode == VIDEO_TEXT_REVEAL) {
00554       // Determine which character is currently being rendered
00555       float fade_cur_char = percent_complete * _num_chars;
00556       int32 cur_char = static_cast<int32>(fade_cur_char);
00557       float cur_percent = fade_cur_char - cur_char;
00558       int32 num_completed_chars = cur_char - num_chars_drawn;
00559 
00560       // If the current character comes after this line, simply render the entire line
00561       if (num_chars_drawn + line_size <= cur_char) {
00562         VideoManager->DrawText(_text[line]);
00563       }
00564       // If the line contains the current character, draw all previous characters as well as the current one
00565       else if (num_completed_chars >= 0) {
00566         ustring substring;
00567 
00568         // If there are already completed characters on this line, draw them in full
00569         if (num_completed_chars > 0) {
00570           substring = _text[line].substr(0, num_completed_chars);
00571           VideoManager->DrawText(substring);
00572         }
00573 
00574         // Now draw the current character from the line, partially scissored according to the amount that is complete
00575         ustring cur_char_string = _text[line].substr(num_completed_chars, 1);
00576 
00577         // Create a rectangle for the current character, in window coordinates
00578         int32 char_x, char_y, char_w, char_h;
00579         char_x = static_cast<int32>(x_offset + VideoManager->_coord_sys.GetHorizontalDirection()
00580           * VideoManager->CalculateTextWidth(_font, substring));
00581         char_y = static_cast<int32>(text_y - VideoManager->_coord_sys.GetVerticalDirection()
00582           * (_font_properties->height + _font_properties->descent));
00583 
00584         if (VideoManager->_coord_sys.GetHorizontalDirection() < 0.0f)
00585           char_y = static_cast<int32>(VideoManager->_coord_sys.GetBottom()) - char_y;
00586 
00587         if (VideoManager->_coord_sys.GetVerticalDirection() < 0.0f)
00588           char_x = static_cast<int32>(VideoManager->_coord_sys.GetLeft()) - char_x;
00589 
00590         char_w = VideoManager->CalculateTextWidth(_font, cur_char_string);
00591         char_h = _font_properties->height;
00592 
00593         // Multiply the width by percentage done to determine the scissoring dimensions
00594         char_w = static_cast<int32>(cur_percent * char_w);
00595         VideoManager->MoveRelative(VideoManager->_coord_sys.GetHorizontalDirection()
00596           * VideoManager->CalculateTextWidth(_font, substring), 0.0f);
00597 
00598         // Construct the scissor rectangle using the character dimensions and draw the revealing character
00599         VideoManager->PushState();
00600         ScreenRect char_scissor_rect(char_x, char_y, char_w, char_h);
00601         scissor_rect.Intersect(char_scissor_rect);
00602         VideoManager->EnableScissoring(true);
00603         VideoManager->SetScissorRect(scissor_rect);
00604         VideoManager->DrawText(cur_char_string);
00605         VideoManager->PopState();
00606       }
00607       // In the else case, the current character is before the line, so we don't draw anything for this line at all
00608     } // else if (_mode == VIDEO_TEXT_REVEAL)
00609 
00610     else {
00611       // Invalid display mode: just render the text instantly
00612       VideoManager->DrawText(_text[line]);
00613       if (VIDEO_DEBUG) {
00614         cerr << "VIDEO WARNING: In TextBox::_DrawTextLines, an unsupported text display mode was active: " << _mode << endl;
00615       }
00616     }
00617 
00618     // (3): Prepare to draw the next line and move the draw cursor appropriately
00619     num_chars_drawn += line_size;
00620 //    VideoManager->MoveRelative(-xOffset, _font_properties.line_skip * -cs._vertical_direction);
00621     text_y += _font_properties->line_skip * -VideoManager->_coord_sys.GetVerticalDirection();
00622     VideoManager->Move(0.0f, text_y);
00623   } // for (int32 line = 0; line < static_cast<int32>(_text.size()); ++line)
00624 } // void TextBox::_DrawTextLines(float text_x, float text_y, ScreenRect scissor_rect)
00625 
00626 
00627 }  // namespace hoa_video

Generated on Fri Jul 6 23:11:25 2007 for Hero of Allacrost by  doxygen 1.5.1