00001 #include "gui_text.hpp"
00002 #include "gui_font.hpp"
00003 #include "gui_sprite.hpp"
00004 #include "gui_material.hpp"
00005 #include "gui_manager.hpp"
00006 #include "gui_out.hpp"
00007
00008 typedef unsigned char uchar;
00009
00010 inline utils::ustring U(const std::string& s)
00011 {
00012 return utils::UTF8_to_unicode(s);
00013 }
00014
00015 namespace gui
00016 {
00017 text::text(manager* pManager, const std::string& sFileName, float fSize) :
00018 pManager_(pManager), sFileName_(sFileName), bReady_(false), fSize_(fSize), fTracking_(0.0f),
00019 fLineSpacing_(1.5f), fSpaceWidth_(0.0f), bRemoveStartingSpaces_(false), bWordWrap_(true),
00020 bAddEllipsis_(false), mColor_(color::WHITE), bForceColor_(false), bFormattingEnabled_(false),
00021 fW_(0.0f), fH_(0.0f), fX_(std::numeric_limits<float>::infinity()),
00022 fY_(std::numeric_limits<float>::infinity()), fBoxW_(std::numeric_limits<float>::infinity()),
00023 fBoxH_(std::numeric_limits<float>::infinity()), mAlign_(ALIGN_LEFT), mVertAlign_(ALIGN_MIDDLE),
00024 bUpdateCache_(false), bUpdateQuads_(false)
00025
00026 {
00027 pFont_ = pManager_->create_font(sFileName_, fSize_);
00028 if (!pFont_)
00029 {
00030 gui::out << gui::error << "gui::text : "
00031 "Error initializing \"" << sFileName << "\" (size : " << fSize << ")." << std::endl;
00032 return;
00033 }
00034
00035 fSpaceWidth_ = pFont_->get_character_width(32);
00036 pSprite_ = pManager_->create_sprite(pFont_->get_texture().lock());
00037
00038 bReady_ = true;
00039 }
00040
00041 text::~text()
00042 {
00043 }
00044
00045 const std::string& text::get_font_name() const
00046 {
00047 return sFileName_;
00048 }
00049
00050 float text::get_font_size() const
00051 {
00052 return fSize_;
00053 }
00054
00055 float text::get_line_height() const
00056 {
00057 return fSize_;
00058 }
00059
00060 void text::set_text(const std::string& sText)
00061 {
00062 if (sText_ != sText)
00063 {
00064 sText_ = sText;
00065 sUnicodeText_ = utils::UTF8_to_unicode(sText_);
00066 bUpdateCache_ = true;
00067 }
00068 }
00069
00070 const std::string& text::get_text() const
00071 {
00072 return sText_;
00073 }
00074
00075 const utils::ustring& text::get_unicode_text() const
00076 {
00077 return sUnicodeText_;
00078 }
00079
00080 void text::set_color(const color& mColor, bool bForceColor)
00081 {
00082 if (mColor_ != mColor || bForceColor_ != bForceColor)
00083 {
00084 mColor_ = mColor;
00085 bForceColor_ = bForceColor;
00086 bUpdateQuads_ = true;
00087 }
00088 }
00089
00090 const color& text::get_color() const
00091 {
00092 return mColor_;
00093 }
00094
00095 void text::set_dimensions(float fW, float fH)
00096 {
00097 if (fBoxW_ != fW && fBoxH_ != fH)
00098 {
00099 fBoxW_ = fW; fBoxH_ = fH;
00100 bUpdateCache_ = true;
00101 }
00102 }
00103
00104 void text::set_box_width(float fBoxW)
00105 {
00106 if (fBoxW_ != fBoxW)
00107 {
00108 fBoxW_ = fBoxW;
00109 bUpdateCache_ = true;
00110 }
00111 }
00112
00113 void text::set_box_height(float fBoxH)
00114 {
00115 if (fBoxH_ != fBoxH)
00116 {
00117 fBoxH_ = fBoxH;
00118 bUpdateCache_ = true;
00119 }
00120 }
00121
00122 float text::get_width()
00123 {
00124 update();
00125
00126 return fW_;
00127 }
00128
00129 float text::get_height()
00130 {
00131 update();
00132
00133 return fH_;
00134 }
00135
00136 float text::get_box_width() const
00137 {
00138 return fBoxW_;
00139 }
00140
00141 float text::get_box_height() const
00142 {
00143 return fBoxH_;
00144 }
00145
00146 float text::get_text_width() const
00147 {
00148 float fWidth = 0.0f;
00149 float fMaxWidth = std::numeric_limits<float>::infinity();
00150
00151 if (bReady_)
00152 {
00153 utils::ustring::const_iterator iterChar, iterNext;
00154 foreach (iterChar, sUnicodeText_)
00155 {
00156 iterNext = iterChar + 1;
00157 if (*iterChar == '\n')
00158 {
00159 if (fWidth > fMaxWidth)
00160 fMaxWidth = fWidth;
00161
00162 fWidth = 0.0f;
00163 }
00164 else
00165 {
00166 fWidth += get_character_width((uint)(uchar)*iterChar) + fTracking_;
00167 if (iterNext != sUnicodeText_.end() && *iterChar != ' ' && *iterNext != ' ' && *iterNext != '\n')
00168 fWidth += get_character_kerning((uint)(uchar)*iterChar, (uint)(uchar)*iterNext);
00169 }
00170 }
00171 }
00172
00173 return fWidth;
00174 }
00175
00176 float text::get_text_height() const
00177 {
00178 float fHeight = 0.0f;
00179
00180 if (bReady_)
00181 {
00182 uint count = 0;
00183 size_t pos = sText_.find("\n");
00184 while (pos != sText_.npos)
00185 pos = sText_.find("\n", pos+1);
00186
00187 fHeight = (1.0f + count*fLineSpacing_)*get_line_height();
00188 }
00189
00190 return fHeight;
00191 }
00192
00193 float text::get_string_width(const std::string& sString) const
00194 {
00195 return get_string_width(utils::UTF8_to_unicode(sString));
00196 }
00197
00198 float text::get_string_width(const utils::ustring& sString) const
00199 {
00200 float fWidth = 0.0f;
00201 float fMaxWidth = std::numeric_limits<float>::infinity();
00202 if (bReady_)
00203 {
00204 utils::ustring::const_iterator iterChar, iterNext;
00205 foreach (iterChar, sString)
00206 {
00207 iterNext = iterChar + 1;
00208 if (*iterChar == ' ')
00209 fWidth += fSpaceWidth_ + fTracking_;
00210 else if (*iterChar == '\t')
00211 fWidth += 4*fSpaceWidth_ + fTracking_;
00212 else if (*iterChar == '\n')
00213 {
00214 if (fWidth > fMaxWidth)
00215 fMaxWidth = fWidth;
00216 fWidth = 0.0f;
00217 }
00218 else
00219 {
00220 fWidth += get_character_width((uint)(uchar)*iterChar) + fTracking_;
00221 if (iterNext != sString.end())
00222 {
00223 if (*iterNext != ' ' && *iterNext != '\n')
00224 fWidth += get_character_kerning((uint)(uchar)*iterChar, (uint)(uchar)*iterNext);
00225 }
00226 }
00227 }
00228 }
00229
00230 return fWidth;
00231 }
00232
00233 float text::get_character_width(uint uiChar) const
00234 {
00235 if (bReady_)
00236 {
00237 if (uiChar == 32)
00238 return fSpaceWidth_;
00239 else if (uiChar == 9)
00240 return 4.0f*fSpaceWidth_;
00241 else
00242 return pFont_->get_character_width(uiChar);
00243 }
00244 else
00245 return 0.0f;
00246 }
00247
00248 float text::get_character_kerning(uint uiChar1, uint uiChar2) const
00249 {
00250 return pFont_->get_character_kerning(uiChar1, uiChar2);
00251 }
00252
00253 void text::set_alignment(const text::alignment& mAlign)
00254 {
00255 if (mAlign_ != mAlign)
00256 {
00257 mAlign_ = mAlign;
00258 bUpdateCache_ = true;
00259 }
00260 }
00261
00262 void text::set_vertical_alignment(const text::vertical_alignment& mVertAlign)
00263 {
00264 if (mVertAlign_ != mVertAlign)
00265 {
00266 mVertAlign_ = mVertAlign;
00267 bUpdateCache_ = true;
00268 }
00269 }
00270
00271 const text::alignment& text::get_alignment() const
00272 {
00273 return mAlign_;
00274 }
00275
00276 const text::vertical_alignment& text::get_vertical_alignment() const
00277 {
00278 return mVertAlign_;
00279 }
00280
00281 void text::set_tracking(float fTracking)
00282 {
00283 if (fTracking_ != fTracking)
00284 {
00285 fTracking_ = fTracking;
00286 bUpdateCache_ = true;
00287 }
00288 }
00289
00290 float text::get_tracking() const
00291 {
00292 return fTracking_;
00293 }
00294
00295 void text::set_line_spacing(float fLineSpacing)
00296 {
00297 if (fLineSpacing_ != fLineSpacing)
00298 {
00299 fLineSpacing_ = fLineSpacing;
00300 bUpdateCache_ = true;
00301 }
00302 }
00303
00304 float text::get_line_spacing() const
00305 {
00306 return fLineSpacing_;
00307 }
00308
00309 void text::set_remove_starting_spaces(bool bRemoveStartingSpaces)
00310 {
00311 if (bRemoveStartingSpaces_ != bRemoveStartingSpaces)
00312 {
00313 bRemoveStartingSpaces_ = bRemoveStartingSpaces;
00314 bUpdateCache_ = true;
00315 }
00316 }
00317
00318 bool text::get_remove_starting_spaces() const
00319 {
00320 return bRemoveStartingSpaces_;
00321 }
00322
00323 void text::enable_word_wrap(bool bWrap, bool bAddEllipsis)
00324 {
00325 if (bWordWrap_ != bWrap || bAddEllipsis_ != bAddEllipsis)
00326 {
00327 bWordWrap_ = bWrap;
00328 bAddEllipsis_ = bAddEllipsis;
00329 bUpdateCache_ = true;
00330 }
00331 }
00332
00333 bool text::is_word_wrap_enabled() const
00334 {
00335 return bWordWrap_;
00336 }
00337
00338 void text::enable_formatting(bool bFormatting)
00339 {
00340 if (bFormattingEnabled_ != bFormatting)
00341 {
00342 bFormattingEnabled_ = bFormatting;
00343 bUpdateCache_ = true;
00344 }
00345 }
00346
00347 void text::render(float fX, float fY)
00348 {
00349 if (bReady_)
00350 {
00351 update();
00352
00353 if (fX != fX_ || fY != fY_)
00354 bUpdateQuads_ = true;
00355
00356 if (bUpdateQuads_)
00357 {
00358 fX_ = fX;
00359 fY_ = fY;
00360
00361 lQuadList_.clear();
00362
00363 std::array<vertex,4> lVertexList;
00364
00365 if (!bFormattingEnabled_)
00366 {
00367 for (uint i = 0; i < 4; ++i)
00368 lVertexList[i].col = mColor_;
00369 }
00370
00371 std::vector<letter>::iterator iterLetter;
00372 foreach (iterLetter, lLetterCache_)
00373 {
00374 if (iterLetter->bNoRender)
00375 continue;
00376
00377 float fX1 = iterLetter->fX1+fX;
00378 float fY1 = iterLetter->fY1+fY;
00379 float fX2 = iterLetter->fX2+fX;
00380 float fY2 = iterLetter->fY2+fY;
00381
00382 lVertexList[0].pos = vector2f(fX1, fY1);
00383 lVertexList[1].pos = vector2f(fX2, fY1);
00384 lVertexList[2].pos = vector2f(fX2, fY2);
00385 lVertexList[3].pos = vector2f(fX1, fY2);
00386
00387 lVertexList[0].uvs = vector2f(iterLetter->fU1, iterLetter->fV1);
00388 lVertexList[1].uvs = vector2f(iterLetter->fU2, iterLetter->fV1);
00389 lVertexList[2].uvs = vector2f(iterLetter->fU2, iterLetter->fV2);
00390 lVertexList[3].uvs = vector2f(iterLetter->fU1, iterLetter->fV2);
00391
00392 if (bFormattingEnabled_)
00393 {
00394 if (iterLetter->mColor != color::EMPTY && !bForceColor_)
00395 {
00396 for (uint i = 0; i < 4; ++i)
00397 lVertexList[i].col = iterLetter->mColor;
00398 }
00399 else
00400 {
00401 for (uint i = 0; i < 4; ++i)
00402 lVertexList[i].col = mColor_;
00403 }
00404 }
00405
00406 lQuadList_.push_back(lVertexList);
00407 }
00408
00409 bUpdateQuads_ = false;
00410 }
00411
00412 pSprite_->render_quads(lQuadList_);
00413 }
00414 }
00415
00416 void text::update()
00417 {
00418
00419 #define DEBUG_LOG(msg)
00420
00421 if (bReady_ && bUpdateCache_)
00422 {
00423 DEBUG_LOG(" Update lines");
00424 update_lines_();
00425 DEBUG_LOG(" Update cache");
00426 update_cache_();
00427 DEBUG_LOG(" .");
00428 bUpdateCache_ = false;
00429 bUpdateQuads_ = true;
00430 }
00431 }
00432
00433 void get_format(utils::ustring::iterator& iterChar, text::format& mFormat)
00434 {
00435 if (*iterChar == 'r')
00436 {
00437 mFormat.mColorAction = text::COLOR_ACTION_RESET;
00438 }
00439 else if (*iterChar == 'c')
00440 {
00441 std::string sColorPart;
00442 ++iterChar;
00443 sColorPart += *iterChar; ++iterChar;
00444 sColorPart += *iterChar; ++iterChar;
00445 float fA = utils::hex_to_uint(sColorPart)/255.0f;
00446 sColorPart.clear();
00447 sColorPart += *iterChar; ++iterChar;
00448 sColorPart += *iterChar; ++iterChar;
00449 float fR = utils::hex_to_uint(sColorPart)/255.0f;
00450 sColorPart.clear();
00451 sColorPart += *iterChar; ++iterChar;
00452 sColorPart += *iterChar; ++iterChar;
00453 float fG = utils::hex_to_uint(sColorPart)/255.0f;
00454 sColorPart.clear();
00455 sColorPart += *iterChar; ++iterChar;
00456 sColorPart += *iterChar;
00457 float fB = utils::hex_to_uint(sColorPart)/255.0f;
00458
00459 mFormat.mColorAction = text::COLOR_ACTION_SET;
00460 mFormat.mColor = color(fR, fG, fB, fA);
00461 }
00462 }
00463
00464 void text::update_lines_()
00465 {
00466
00467 lLineList_.clear();
00468 lFormatList_.clear();
00469
00470 DEBUG_LOG(" Get max line nbr");
00471 uint uiMaxLineNbr, uiCounter = 0;
00472 if (fBoxH_ != 0.0f && !std::isinf(fBoxH_))
00473 {
00474 if (fBoxH_ < get_line_height())
00475 {
00476 uiMaxLineNbr = 0;
00477 return;
00478 }
00479 else
00480 {
00481 float fRemaining = fBoxH_ - get_line_height();
00482 uiMaxLineNbr = 1 + floor(fRemaining/(get_line_height()*fLineSpacing_));
00483 }
00484 }
00485 else
00486 uiMaxLineNbr = uint(-1);
00487
00488 if (uiMaxLineNbr != 0)
00489 {
00490 std::vector<utils::ustring> lManualLineList = utils::cut_each(sUnicodeText_, U("\n"));
00491 std::vector<utils::ustring>::iterator iterManual;
00492 foreach (iterManual, lManualLineList)
00493 {
00494 DEBUG_LOG(" Line : '" + utils::unicode_to_UTF8(*iterManual) + "'");
00495
00496 std::vector<line> lLines;
00497 line mLine; mLine.fWidth = 0.0f;
00498 std::map<uint, format> lTempFormatList;
00499
00500 DEBUG_LOG(" Read chars");
00501 utils::ustring::iterator iterChar1;
00502 foreach (iterChar1, *iterManual)
00503 {
00504 DEBUG_LOG(" char '" + utils::to_string(*iterChar1) + "'");
00505 DEBUG_LOG(" Read format");
00506
00507 if (*iterChar1 == '|' && bFormattingEnabled_)
00508 {
00509 ++iterChar1;
00510 if (iterChar1 != iterManual->end())
00511 {
00512 if (*iterChar1 == '|')
00513 {
00514 }
00515 else
00516 {
00517 get_format(iterChar1, lTempFormatList[uiCounter+mLine.sCaption.size()]);
00518 continue;
00519 }
00520 }
00521 else
00522 break;
00523 }
00524
00525 DEBUG_LOG(" Get width");
00526 if (*iterChar1 == ' ')
00527 mLine.fWidth += fSpaceWidth_ + fTracking_;
00528 else if (*iterChar1 == '\t')
00529 mLine.fWidth += 4*fSpaceWidth_ + fTracking_;
00530 else
00531 {
00532 mLine.fWidth += get_character_width((uint)(uchar)*iterChar1) + fTracking_;
00533 utils::ustring::iterator iterNext = iterChar1 + 1;
00534 if (iterNext != iterManual->end())
00535 {
00536 if (*iterNext != ' ')
00537 mLine.fWidth += get_character_kerning((uint)(uchar)*iterChar1, (uint)(uchar)*iterNext);
00538 }
00539 }
00540
00541 mLine.sCaption += *iterChar1;
00542
00543 if (mLine.fWidth > fBoxW_)
00544 {
00545 DEBUG_LOG(" Box break " + utils::to_string(mLine.fWidth) + " > " + utils::to_string(fBoxW_));
00546
00547 if (mLine.sCaption.find(U(" ")) != mLine.sCaption.npos && bWordWrap_)
00548 {
00549 DEBUG_LOG(" Spaced");
00550
00551
00552 utils::ustring::iterator iterChar2 = mLine.sCaption.end();
00553 utils::ustring sErasedString;
00554 uint uiCharToErase = 0;
00555 float fErasedWidth = 0.0f;
00556 bool bLastWasWord = false;
00557 while (mLine.fWidth > fBoxW_ && iterChar2 != mLine.sCaption.begin())
00558 {
00559 --iterChar2;
00560 if (*iterChar2 == ' ')
00561 {
00562 if (!bLastWasWord || bRemoveStartingSpaces_ || mLine.fWidth - fErasedWidth > fBoxW_)
00563 {
00564 mLine.fWidth -= fErasedWidth + fSpaceWidth_ + fTracking_;
00565 sErasedString.insert(sErasedString.begin(), *iterChar2);
00566 fErasedWidth = 0.0f;
00567 ++uiCharToErase;
00568 }
00569 else
00570 break;
00571 }
00572 else
00573 {
00574 fErasedWidth += get_character_width((uint)(uchar)*iterChar2) + fTracking_;
00575 sErasedString.insert(sErasedString.begin(), *iterChar2);
00576 ++uiCharToErase;
00577 bLastWasWord = true;
00578 }
00579 }
00580
00581 if (bRemoveStartingSpaces_)
00582 {
00583 while (*iterChar2 == ' ')
00584 {
00585 --uiCharToErase;
00586 sErasedString.erase(0, 1);
00587 ++iterChar2;
00588 }
00589 }
00590
00591 mLine.sCaption.erase(mLine.sCaption.size() - uiCharToErase, uiCharToErase);
00592
00593 lLines.push_back(mLine);
00594 std::map<uint, format>::iterator iterFormat;
00595 foreach (iterFormat, lTempFormatList)
00596 lFormatList_[iterFormat->first] = iterFormat->second;
00597
00598 lTempFormatList.clear();
00599 uiCounter += mLine.sCaption.size();
00600 mLine.fWidth = get_string_width(sErasedString);
00601 mLine.sCaption = sErasedString;
00602 }
00603 else
00604 {
00605 DEBUG_LOG(" Single word");
00606
00607
00608
00609
00610 if (bAddEllipsis_)
00611 {
00612 DEBUG_LOG(" Ellipsis");
00613 float fWordWidth = 3.0f*(get_character_width((uint)(uchar)'.') + fTracking_);
00614 utils::ustring::iterator iterChar2 = mLine.sCaption.end();
00615 uint uiCharToErase = 0;
00616 while ((mLine.fWidth + fWordWidth > fBoxW_) && (iterChar2 != mLine.sCaption.begin()))
00617 {
00618 --iterChar2;
00619 mLine.fWidth -= get_character_width((uint)(uchar)*iterChar2) + fTracking_;
00620 ++uiCharToErase;
00621 }
00622
00623 DEBUG_LOG(" Char to erase : " + utils::to_string(uiCharToErase) + " / "
00624 + utils::to_string(mLine.sCaption.size()));
00625
00626 mLine.sCaption.erase(mLine.sCaption.size() - uiCharToErase, uiCharToErase);
00627 mLine.sCaption += U("...");
00628 }
00629 else
00630 {
00631 DEBUG_LOG(" Truncate");
00632 utils::ustring::iterator iterChar2 = mLine.sCaption.end();
00633 uint uiCharToErase = 0;
00634 while (mLine.fWidth > fBoxW_ && iterChar2 != mLine.sCaption.begin())
00635 {
00636 --iterChar2;
00637 mLine.fWidth -= get_character_width((uint)(uchar)*iterChar2) + fTracking_;
00638 ++uiCharToErase;
00639 }
00640 mLine.sCaption.erase(mLine.sCaption.size() - uiCharToErase, uiCharToErase);
00641 }
00642
00643 if (!bWordWrap_)
00644 {
00645 DEBUG_LOG(" Display single line");
00646
00647
00648 lLineList_.push_back(mLine);
00649 std::map<uint, format>::iterator iterFormat;
00650 foreach (iterFormat, lTempFormatList)
00651 lFormatList_[iterFormat->first] = iterFormat->second;
00652
00653 return;
00654 }
00655
00656 DEBUG_LOG(" Continue");
00657 utils::ustring::iterator iterTemp = iterChar1;
00658 size_t pos = iterManual->find(U(" "), iterChar1 - iterManual->begin());
00659 if (pos == iterManual->npos)
00660 iterChar1 = iterManual->end();
00661 else
00662 iterChar1 = iterManual->begin() + pos;
00663
00664 if (iterChar1 != iterManual->end())
00665 {
00666
00667 if (bFormattingEnabled_)
00668 {
00669 while (iterTemp != iterChar1)
00670 {
00671 if (*iterTemp == '|')
00672 {
00673 ++iterTemp;
00674 if (iterTemp != iterChar1 && *iterTemp != '|')
00675 get_format(iterTemp, lTempFormatList[uiCounter+mLine.sCaption.size()]);
00676 }
00677 ++iterTemp;
00678 }
00679 }
00680
00681
00682 while (iterChar1 != iterManual->end())
00683 {
00684 if ((*iterChar1) == ' ')
00685 ++iterChar1;
00686 else
00687 break;
00688 }
00689
00690
00691 if (iterChar1 != iterManual->end())
00692 {
00693 --iterChar1;
00694 lLines.push_back(mLine);
00695 uiCounter += mLine.sCaption.size();
00696
00697 std::map<uint, format>::iterator iterFormat;
00698 foreach (iterFormat, lTempFormatList)
00699 lFormatList_[iterFormat->first] = iterFormat->second;
00700
00701 lTempFormatList.clear();
00702 mLine.fWidth = 0.0f;
00703 mLine.sCaption.clear();
00704 }
00705 else
00706 break;
00707 }
00708 else
00709 break;
00710 }
00711 }
00712 }
00713
00714 DEBUG_LOG(" End");
00715
00716 if (iterManual != lManualLineList.end() - 1)
00717 mLine.sCaption += U("\n");
00718
00719 lLines.push_back(mLine);
00720 std::map<uint, format>::iterator iterFormat;
00721 foreach (iterFormat, lTempFormatList)
00722 lFormatList_[iterFormat->first] = iterFormat->second;
00723
00724 lTempFormatList.clear();
00725 uiCounter += mLine.sCaption.size() - 1;
00726
00727
00728 std::vector<line>::iterator iterLine;
00729 foreach (iterLine, lLines)
00730 {
00731 lLineList_.push_back(*iterLine);
00732 if (lLineList_.size() == uiMaxLineNbr)
00733 return;
00734 }
00735 DEBUG_LOG(" .");
00736 }
00737 }
00738 }
00739
00740 void text::update_cache_()
00741 {
00742 lLetterCache_.clear();
00743
00744 if (!lLineList_.empty())
00745 {
00746 if (fBoxW_ == 0.0f || std::isinf(fBoxW_))
00747 {
00748 fW_ = 0.0f;
00749 std::vector<line>::iterator iterLine;
00750 foreach (iterLine, lLineList_)
00751 fW_ = std::max(fW_, iterLine->fWidth);
00752 }
00753 else
00754 fW_ = fBoxW_;
00755
00756 fH_ = (1.0f + (lLineList_.size() - 1)*fLineSpacing_)*get_line_height();
00757
00758 float fX = 0.0f, fY = 0.0f;
00759 float fX0 = 0.0f;
00760
00761 if (fBoxW_ != 0.0f && !std::isinf(fBoxW_))
00762 {
00763 switch (mAlign_)
00764 {
00765 case ALIGN_LEFT :
00766 fX0 = 0.0f;
00767 break;
00768 case ALIGN_CENTER :
00769 fX0 = floor(fBoxW_*0.5f);
00770 break;
00771 case ALIGN_RIGHT :
00772 fX0 = fBoxW_;
00773 break;
00774 }
00775 }
00776 else
00777 fX0 = 0.0f;
00778
00779 if (!std::isinf(fBoxH_))
00780 {
00781 switch (mVertAlign_)
00782 {
00783 case ALIGN_TOP :
00784 fY = 0.0f;
00785 break;
00786 case ALIGN_MIDDLE :
00787 fY = floor((fBoxH_ - fH_)*0.5f);
00788 break;
00789 case ALIGN_BOTTOM :
00790 fY = (fBoxH_ - fH_);
00791 break;
00792 }
00793 }
00794 else
00795 {
00796 switch (mVertAlign_)
00797 {
00798 case ALIGN_TOP :
00799 fY = 0.0f;
00800 break;
00801 case ALIGN_MIDDLE :
00802 fY = -floor(fH_*0.5f);
00803 break;
00804 case ALIGN_BOTTOM :
00805 fY = -fH_;
00806 break;
00807 }
00808 }
00809
00810 uint uiCounter = 0;
00811
00812 letter mLetter;
00813
00814 color mColor = color::EMPTY;
00815
00816 std::vector<line>::iterator iterLine;
00817 foreach (iterLine, lLineList_)
00818 {
00819 switch (mAlign_)
00820 {
00821 case ALIGN_LEFT :
00822 fX = fX0;
00823 break;
00824 case ALIGN_CENTER :
00825 fX = fX0 - floor(iterLine->fWidth*0.5f);
00826 break;
00827 case ALIGN_RIGHT :
00828 fX = fX0 - iterLine->fWidth;
00829 break;
00830 }
00831
00832 utils::ustring::iterator iterChar, iterNext;
00833 foreach (iterChar, iterLine->sCaption)
00834 {
00835
00836 if (bFormattingEnabled_ && lFormatList_.find(uiCounter) != lFormatList_.end())
00837 {
00838 const format& mFormat = lFormatList_[uiCounter];
00839 switch (mFormat.mColorAction)
00840 {
00841 case COLOR_ACTION_SET :
00842 mColor = mFormat.mColor;
00843 break;
00844 case COLOR_ACTION_RESET :
00845 mColor = color::EMPTY;
00846 break;
00847 default : break;
00848 }
00849 }
00850
00851 float fCharWidth, fCharHeight;
00852
00853
00854 if (*iterChar == '\n')
00855 {
00856 std::array<float,4> lUVs = pFont_->get_character_uvs((uint)(uchar)'_');
00857 fCharHeight = (lUVs[3] - lUVs[1])*pFont_->get_texture()->get_height();
00858 float fYOffset = floor(fSize_/2.0f + fSize_/8.0f - fCharHeight/2.0f);
00859
00860 mLetter.fX1 = fX; mLetter.fY1 = fY+fYOffset;
00861 mLetter.fX2 = fX; mLetter.fY2 = fY+fYOffset+fCharHeight;
00862
00863 mLetter.bNoRender = true;
00864
00865 lLetterCache_.push_back(mLetter);
00866
00867 continue;
00868 }
00869 else if (*iterChar == ' ' || *iterChar == '\t')
00870 {
00871 std::array<float,4> lUVs = pFont_->get_character_uvs(33);
00872 fCharWidth = fSpaceWidth_;
00873 if (*iterChar == '\t')
00874 fCharWidth *= 4;
00875 fCharHeight = (lUVs[3] - lUVs[1])*pFont_->get_texture()->get_height();
00876 float fYOffset = floor(fSize_/2.0f + fSize_/8.0f - fCharHeight/2.0f);
00877
00878 mLetter.fX1 = fX; mLetter.fY1 = fY+fYOffset;
00879 mLetter.fX2 = fX+fCharWidth; mLetter.fY2 = fY+fYOffset+fCharHeight;
00880
00881 mLetter.bNoRender = true;
00882
00883 lLetterCache_.push_back(mLetter);
00884 }
00885 else
00886 {
00887 std::array<float,4> lUVs = pFont_->get_character_uvs(*iterChar);
00888 fCharWidth = get_character_width((uint)(uchar)*iterChar);
00889 fCharHeight = (lUVs[3] - lUVs[1])*pFont_->get_texture()->get_height();
00890 float fYOffset = floor(fSize_/2.0f + fSize_/8.0f - fCharHeight/2.0f);
00891
00892 mLetter.fX1 = fX; mLetter.fY1 = fY+fYOffset;
00893 mLetter.fX2 = fX+fCharWidth; mLetter.fY2 = fY+fYOffset+fCharHeight;
00894
00895 mLetter.fU1 = lUVs[0]; mLetter.fV1 = lUVs[1];
00896 mLetter.fU2 = lUVs[2]; mLetter.fV2 = lUVs[3];
00897
00898 mLetter.mColor = mColor;
00899 mLetter.bNoRender = false;
00900
00901 lLetterCache_.push_back(mLetter);
00902 }
00903
00904 iterNext = iterChar + 1;
00905
00906 float fKerning = 0.0f;
00907 if (iterNext != iterLine->sCaption.end() && *iterNext != ' ' && *iterChar != ' ')
00908 fKerning = get_character_kerning((uint)(uchar)*iterChar, (uint)(uchar)*iterNext);
00909
00910 fX += fCharWidth + fKerning + fTracking_;
00911 ++uiCounter;
00912 }
00913
00914 fY += get_line_height()*fLineSpacing_;
00915 }
00916 }
00917 else
00918 {
00919 fW_ = 0.0f;
00920 fH_ = 0.0f;
00921 }
00922 }
00923
00924 utils::refptr<sprite> text::create_sprite(uint uiChar) const
00925 {
00926 std::array<float,4> lUVs = pFont_->get_character_uvs(uiChar);
00927
00928 float fWidth = get_character_width(uiChar);
00929 float fHeight = (lUVs[3] - lUVs[1])*pFont_->get_texture()->get_height();
00930
00931 utils::refptr<sprite> pSprite = pManager_->create_sprite(pFont_->get_texture().lock(), fWidth, fHeight);
00932 pSprite->set_texture_rect(lUVs, true);
00933
00934 pSprite->set_color(mColor_);
00935
00936 return pSprite;
00937 }
00938
00939 const std::vector<text::letter>& text::get_letter_cache()
00940 {
00941 update();
00942 return lLetterCache_;
00943 }
00944 }