PageRenderTime 35ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/llhudtext.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 639 lines | 458 code | 97 blank | 84 comment | 58 complexity | cec944d1374a2efbfcb32cce5f43ada8 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llhudtext.cpp
  3. * @brief Floating text above objects, set via script with llSetText()
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llhudtext.h"
  28. #include "llrender.h"
  29. #include "llagent.h"
  30. #include "llviewercontrol.h"
  31. #include "llcriticaldamp.h"
  32. #include "lldrawable.h"
  33. #include "llfontgl.h"
  34. #include "llglheaders.h"
  35. #include "llhudrender.h"
  36. #include "llui.h"
  37. #include "llviewercamera.h"
  38. #include "llviewertexturelist.h"
  39. #include "llviewerobject.h"
  40. #include "llvovolume.h"
  41. #include "llviewerwindow.h"
  42. #include "llstatusbar.h"
  43. #include "llmenugl.h"
  44. #include "pipeline.h"
  45. #include <boost/tokenizer.hpp>
  46. const F32 SPRING_STRENGTH = 0.7f;
  47. const F32 RESTORATION_SPRING_TIME_CONSTANT = 0.1f;
  48. const F32 HORIZONTAL_PADDING = 15.f;
  49. const F32 VERTICAL_PADDING = 12.f;
  50. const F32 BUFFER_SIZE = 2.f;
  51. const F32 MIN_EDGE_OVERLAP = 3.f;
  52. const F32 HUD_TEXT_MAX_WIDTH = 190.f;
  53. const F32 HUD_TEXT_MAX_WIDTH_NO_BUBBLE = 1000.f;
  54. const F32 RESIZE_TIME = 0.f;
  55. const S32 NUM_OVERLAP_ITERATIONS = 10;
  56. const F32 NEIGHBOR_FORCE_FRACTION = 1.f;
  57. const F32 POSITION_DAMPING_TC = 0.2f;
  58. const F32 MAX_STABLE_CAMERA_VELOCITY = 0.1f;
  59. //const F32 LOD_0_SCREEN_COVERAGE = 0.15f;
  60. //const F32 LOD_1_SCREEN_COVERAGE = 0.30f;
  61. //const F32 LOD_2_SCREEN_COVERAGE = 0.40f;
  62. std::set<LLPointer<LLHUDText> > LLHUDText::sTextObjects;
  63. std::vector<LLPointer<LLHUDText> > LLHUDText::sVisibleTextObjects;
  64. std::vector<LLPointer<LLHUDText> > LLHUDText::sVisibleHUDTextObjects;
  65. BOOL LLHUDText::sDisplayText = TRUE ;
  66. bool lltextobject_further_away::operator()(const LLPointer<LLHUDText>& lhs, const LLPointer<LLHUDText>& rhs) const
  67. {
  68. return lhs->getDistance() > rhs->getDistance();
  69. }
  70. LLHUDText::LLHUDText(const U8 type) :
  71. LLHUDObject(type),
  72. mOnHUDAttachment(FALSE),
  73. // mVisibleOffScreen(FALSE),
  74. mWidth(0.f),
  75. mHeight(0.f),
  76. mFontp(LLFontGL::getFontSansSerifSmall()),
  77. mBoldFontp(LLFontGL::getFontSansSerifBold()),
  78. mMass(1.f),
  79. mMaxLines(10),
  80. mOffsetY(0),
  81. mTextAlignment(ALIGN_TEXT_CENTER),
  82. mVertAlignment(ALIGN_VERT_CENTER),
  83. // mLOD(0),
  84. mHidden(FALSE)
  85. {
  86. mColor = LLColor4(1.f, 1.f, 1.f, 1.f);
  87. mDoFade = TRUE;
  88. mFadeDistance = 8.f;
  89. mFadeRange = 4.f;
  90. mZCompare = TRUE;
  91. mOffscreen = FALSE;
  92. mRadius = 0.1f;
  93. LLPointer<LLHUDText> ptr(this);
  94. sTextObjects.insert(ptr);
  95. }
  96. LLHUDText::~LLHUDText()
  97. {
  98. }
  99. void LLHUDText::render()
  100. {
  101. if (!mOnHUDAttachment && sDisplayText)
  102. {
  103. LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
  104. renderText();
  105. }
  106. }
  107. void LLHUDText::renderText()
  108. {
  109. if (!mVisible || mHidden)
  110. {
  111. return;
  112. }
  113. gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
  114. LLGLState gls_blend(GL_BLEND, TRUE);
  115. LLGLState gls_alpha(GL_ALPHA_TEST, TRUE);
  116. LLColor4 shadow_color(0.f, 0.f, 0.f, 1.f);
  117. F32 alpha_factor = 1.f;
  118. LLColor4 text_color = mColor;
  119. if (mDoFade)
  120. {
  121. if (mLastDistance > mFadeDistance)
  122. {
  123. alpha_factor = llmax(0.f, 1.f - (mLastDistance - mFadeDistance)/mFadeRange);
  124. text_color.mV[3] = text_color.mV[3]*alpha_factor;
  125. }
  126. }
  127. if (text_color.mV[3] < 0.01f)
  128. {
  129. return;
  130. }
  131. shadow_color.mV[3] = text_color.mV[3];
  132. mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f));
  133. // *TODO: cache this image
  134. LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square");
  135. // *TODO: make this a per-text setting
  136. LLColor4 bg_color = LLUIColorTable::instance().getColor("ObjectBubbleColor");
  137. bg_color.setAlpha(gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor);
  138. const S32 border_height = 16;
  139. const S32 border_width = 16;
  140. // *TODO move this into helper function
  141. F32 border_scale = 1.f;
  142. if (border_height * 2 > mHeight)
  143. {
  144. border_scale = (F32)mHeight / ((F32)border_height * 2.f);
  145. }
  146. if (border_width * 2 > mWidth)
  147. {
  148. border_scale = llmin(border_scale, (F32)mWidth / ((F32)border_width * 2.f));
  149. }
  150. // scale screen size of borders down
  151. //RN: for now, text on hud objects is never occluded
  152. LLVector3 x_pixel_vec;
  153. LLVector3 y_pixel_vec;
  154. if (mOnHUDAttachment)
  155. {
  156. x_pixel_vec = LLVector3::y_axis / (F32)gViewerWindow->getWorldViewWidthRaw();
  157. y_pixel_vec = LLVector3::z_axis / (F32)gViewerWindow->getWorldViewHeightRaw();
  158. }
  159. else
  160. {
  161. LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
  162. }
  163. LLVector2 border_scale_vec((F32)border_width / (F32)imagep->getTextureWidth(), (F32)border_height / (F32)imagep->getTextureHeight());
  164. LLVector3 width_vec = mWidth * x_pixel_vec;
  165. LLVector3 height_vec = mHeight * y_pixel_vec;
  166. LLVector3 scaled_border_width = (F32)llfloor(border_scale * (F32)border_width) * x_pixel_vec;
  167. LLVector3 scaled_border_height = (F32)llfloor(border_scale * (F32)border_height) * y_pixel_vec;
  168. mRadius = (width_vec + height_vec).magVec() * 0.5f;
  169. LLVector2 screen_offset;
  170. screen_offset = mPositionOffset;
  171. LLVector3 render_position = mPositionAgent
  172. + (x_pixel_vec * screen_offset.mV[VX])
  173. + (y_pixel_vec * screen_offset.mV[VY]);
  174. F32 y_offset = (F32)mOffsetY;
  175. // Render label
  176. {
  177. gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
  178. }
  179. // Render text
  180. {
  181. // -1 mMaxLines means unlimited lines.
  182. S32 start_segment;
  183. S32 max_lines = getMaxLines();
  184. if (max_lines < 0)
  185. {
  186. start_segment = 0;
  187. }
  188. else
  189. {
  190. start_segment = llmax((S32)0, (S32)mTextSegments.size() - max_lines);
  191. }
  192. for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin() + start_segment;
  193. segment_iter != mTextSegments.end(); ++segment_iter )
  194. {
  195. const LLFontGL* fontp = segment_iter->mFont;
  196. y_offset -= fontp->getLineHeight();
  197. U8 style = segment_iter->mStyle;
  198. LLFontGL::ShadowType shadow = LLFontGL::DROP_SHADOW;
  199. F32 x_offset;
  200. if (mTextAlignment== ALIGN_TEXT_CENTER)
  201. {
  202. x_offset = -0.5f*segment_iter->getWidth(fontp);
  203. }
  204. else // ALIGN_LEFT
  205. {
  206. x_offset = -0.5f * mWidth + (HORIZONTAL_PADDING / 2.f);
  207. }
  208. text_color = segment_iter->mColor;
  209. text_color.mV[VALPHA] *= alpha_factor;
  210. hud_render_text(segment_iter->getText(), render_position, *fontp, style, shadow, x_offset, y_offset, text_color, mOnHUDAttachment);
  211. }
  212. }
  213. /// Reset the default color to white. The renderer expects this to be the default.
  214. gGL.color4f(1.0f, 1.0f, 1.0f, 1.0f);
  215. }
  216. void LLHUDText::setString(const std::string &text_utf8)
  217. {
  218. mTextSegments.clear();
  219. addLine(text_utf8, mColor);
  220. }
  221. void LLHUDText::clearString()
  222. {
  223. mTextSegments.clear();
  224. }
  225. void LLHUDText::addLine(const std::string &text_utf8,
  226. const LLColor4& color,
  227. const LLFontGL::StyleFlags style,
  228. const LLFontGL* font)
  229. {
  230. LLWString wline = utf8str_to_wstring(text_utf8);
  231. if (!wline.empty())
  232. {
  233. // use default font for segment if custom font not specified
  234. if (!font)
  235. {
  236. font = mFontp;
  237. }
  238. typedef boost::tokenizer<boost::char_separator<llwchar>, LLWString::const_iterator, LLWString > tokenizer;
  239. LLWString seps(utf8str_to_wstring("\r\n"));
  240. boost::char_separator<llwchar> sep(seps.c_str());
  241. tokenizer tokens(wline, sep);
  242. tokenizer::iterator iter = tokens.begin();
  243. while (iter != tokens.end())
  244. {
  245. U32 line_length = 0;
  246. do
  247. {
  248. F32 max_pixels = HUD_TEXT_MAX_WIDTH_NO_BUBBLE;
  249. S32 segment_length = font->maxDrawableChars(iter->substr(line_length).c_str(), max_pixels, wline.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
  250. LLHUDTextSegment segment(iter->substr(line_length, segment_length), style, color, font);
  251. mTextSegments.push_back(segment);
  252. line_length += segment_length;
  253. }
  254. while (line_length != iter->size());
  255. ++iter;
  256. }
  257. }
  258. }
  259. void LLHUDText::setZCompare(const BOOL zcompare)
  260. {
  261. mZCompare = zcompare;
  262. }
  263. void LLHUDText::setFont(const LLFontGL* font)
  264. {
  265. mFontp = font;
  266. }
  267. void LLHUDText::setColor(const LLColor4 &color)
  268. {
  269. mColor = color;
  270. for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin();
  271. segment_iter != mTextSegments.end(); ++segment_iter )
  272. {
  273. segment_iter->mColor = color;
  274. }
  275. }
  276. void LLHUDText::setAlpha(F32 alpha)
  277. {
  278. mColor.mV[VALPHA] = alpha;
  279. for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin();
  280. segment_iter != mTextSegments.end(); ++segment_iter )
  281. {
  282. segment_iter->mColor.mV[VALPHA] = alpha;
  283. }
  284. }
  285. void LLHUDText::setDoFade(const BOOL do_fade)
  286. {
  287. mDoFade = do_fade;
  288. }
  289. void LLHUDText::updateVisibility()
  290. {
  291. if (mSourceObject)
  292. {
  293. mSourceObject->updateText();
  294. }
  295. mPositionAgent = gAgent.getPosAgentFromGlobal(mPositionGlobal);
  296. if (!mSourceObject)
  297. {
  298. //llwarns << "LLHUDText::updateScreenPos -- mSourceObject is NULL!" << llendl;
  299. mVisible = TRUE;
  300. if (mOnHUDAttachment)
  301. {
  302. sVisibleHUDTextObjects.push_back(LLPointer<LLHUDText> (this));
  303. }
  304. else
  305. {
  306. sVisibleTextObjects.push_back(LLPointer<LLHUDText> (this));
  307. }
  308. return;
  309. }
  310. // Not visible if parent object is dead
  311. if (mSourceObject->isDead())
  312. {
  313. mVisible = FALSE;
  314. return;
  315. }
  316. // for now, all text on hud objects is visible
  317. if (mOnHUDAttachment)
  318. {
  319. mVisible = TRUE;
  320. sVisibleHUDTextObjects.push_back(LLPointer<LLHUDText> (this));
  321. mLastDistance = mPositionAgent.mV[VX];
  322. return;
  323. }
  324. // push text towards camera by radius of object, but not past camera
  325. LLVector3 vec_from_camera = mPositionAgent - LLViewerCamera::getInstance()->getOrigin();
  326. LLVector3 dir_from_camera = vec_from_camera;
  327. dir_from_camera.normVec();
  328. if (dir_from_camera * LLViewerCamera::getInstance()->getAtAxis() <= 0.f)
  329. { //text is behind camera, don't render
  330. mVisible = FALSE;
  331. return;
  332. }
  333. if (vec_from_camera * LLViewerCamera::getInstance()->getAtAxis() <= LLViewerCamera::getInstance()->getNear() + 0.1f + mSourceObject->getVObjRadius())
  334. {
  335. mPositionAgent = LLViewerCamera::getInstance()->getOrigin() + vec_from_camera * ((LLViewerCamera::getInstance()->getNear() + 0.1f) / (vec_from_camera * LLViewerCamera::getInstance()->getAtAxis()));
  336. }
  337. else
  338. {
  339. mPositionAgent -= dir_from_camera * mSourceObject->getVObjRadius();
  340. }
  341. mLastDistance = (mPositionAgent - LLViewerCamera::getInstance()->getOrigin()).magVec();
  342. if (!mTextSegments.size() || (mDoFade && (mLastDistance > mFadeDistance + mFadeRange)))
  343. {
  344. mVisible = FALSE;
  345. return;
  346. }
  347. LLVector3 x_pixel_vec;
  348. LLVector3 y_pixel_vec;
  349. LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
  350. LLVector3 render_position = mPositionAgent +
  351. (x_pixel_vec * mPositionOffset.mV[VX]) +
  352. (y_pixel_vec * mPositionOffset.mV[VY]);
  353. mOffscreen = FALSE;
  354. if (!LLViewerCamera::getInstance()->sphereInFrustum(render_position, mRadius))
  355. {
  356. // if (!mVisibleOffScreen)
  357. // {
  358. mVisible = FALSE;
  359. return;
  360. // }
  361. // else
  362. // {
  363. // mOffscreen = TRUE;
  364. // }
  365. }
  366. mVisible = TRUE;
  367. sVisibleTextObjects.push_back(LLPointer<LLHUDText> (this));
  368. }
  369. LLVector2 LLHUDText::updateScreenPos(LLVector2 &offset)
  370. {
  371. LLCoordGL screen_pos;
  372. LLVector2 screen_pos_vec;
  373. LLVector3 x_pixel_vec;
  374. LLVector3 y_pixel_vec;
  375. LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
  376. LLVector3 world_pos = mPositionAgent + (offset.mV[VX] * x_pixel_vec) + (offset.mV[VY] * y_pixel_vec);
  377. // if (!LLViewerCamera::getInstance()->projectPosAgentToScreen(world_pos, screen_pos, FALSE) && mVisibleOffScreen)
  378. // {
  379. // // bubble off-screen, so find a spot for it along screen edge
  380. // LLViewerCamera::getInstance()->projectPosAgentToScreenEdge(world_pos, screen_pos);
  381. // }
  382. screen_pos_vec.setVec((F32)screen_pos.mX, (F32)screen_pos.mY);
  383. LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
  384. S32 bottom = world_rect.mBottom + STATUS_BAR_HEIGHT;
  385. LLVector2 screen_center;
  386. screen_center.mV[VX] = llclamp((F32)screen_pos_vec.mV[VX], (F32)world_rect.mLeft + mWidth * 0.5f, (F32)world_rect.mRight - mWidth * 0.5f);
  387. if(mVertAlignment == ALIGN_VERT_TOP)
  388. {
  389. screen_center.mV[VY] = llclamp((F32)screen_pos_vec.mV[VY],
  390. (F32)bottom,
  391. (F32)world_rect.mTop - mHeight - (F32)MENU_BAR_HEIGHT);
  392. mSoftScreenRect.setLeftTopAndSize(screen_center.mV[VX] - (mWidth + BUFFER_SIZE) * 0.5f,
  393. screen_center.mV[VY] + (mHeight + BUFFER_SIZE), mWidth + BUFFER_SIZE, mHeight + BUFFER_SIZE);
  394. }
  395. else
  396. {
  397. screen_center.mV[VY] = llclamp((F32)screen_pos_vec.mV[VY],
  398. (F32)bottom + mHeight * 0.5f,
  399. (F32)world_rect.mTop - mHeight * 0.5f - (F32)MENU_BAR_HEIGHT);
  400. mSoftScreenRect.setCenterAndSize(screen_center.mV[VX], screen_center.mV[VY], mWidth + BUFFER_SIZE, mHeight + BUFFER_SIZE);
  401. }
  402. return offset + (screen_center - LLVector2((F32)screen_pos.mX, (F32)screen_pos.mY));
  403. }
  404. void LLHUDText::updateSize()
  405. {
  406. F32 height = 0.f;
  407. F32 width = 0.f;
  408. S32 max_lines = getMaxLines();
  409. //S32 lines = (max_lines < 0) ? (S32)mTextSegments.size() : llmin((S32)mTextSegments.size(), max_lines);
  410. //F32 height = (F32)mFontp->getLineHeight() * (lines + mLabelSegments.size());
  411. S32 start_segment;
  412. if (max_lines < 0) start_segment = 0;
  413. else start_segment = llmax((S32)0, (S32)mTextSegments.size() - max_lines);
  414. std::vector<LLHUDTextSegment>::iterator iter = mTextSegments.begin() + start_segment;
  415. while (iter != mTextSegments.end())
  416. {
  417. const LLFontGL* fontp = iter->mFont;
  418. height += fontp->getLineHeight();
  419. width = llmax(width, llmin(iter->getWidth(fontp), HUD_TEXT_MAX_WIDTH));
  420. ++iter;
  421. }
  422. if (width == 0.f)
  423. {
  424. return;
  425. }
  426. width += HORIZONTAL_PADDING;
  427. height += VERTICAL_PADDING;
  428. // *TODO: Could do some sort of timer-based resize logic here
  429. F32 u = 1.f;
  430. mWidth = llmax(width, lerp(mWidth, (F32)width, u));
  431. mHeight = llmax(height, lerp(mHeight, (F32)height, u));
  432. }
  433. void LLHUDText::updateAll()
  434. {
  435. // iterate over all text objects, calculate their restoration forces,
  436. // and add them to the visible set if they are on screen and close enough
  437. sVisibleTextObjects.clear();
  438. sVisibleHUDTextObjects.clear();
  439. TextObjectIterator text_it;
  440. for (text_it = sTextObjects.begin(); text_it != sTextObjects.end(); ++text_it)
  441. {
  442. LLHUDText* textp = (*text_it);
  443. textp->mTargetPositionOffset.clearVec();
  444. textp->updateSize();
  445. textp->updateVisibility();
  446. }
  447. // sort back to front for rendering purposes
  448. std::sort(sVisibleTextObjects.begin(), sVisibleTextObjects.end(), lltextobject_further_away());
  449. std::sort(sVisibleHUDTextObjects.begin(), sVisibleHUDTextObjects.end(), lltextobject_further_away());
  450. }
  451. //void LLHUDText::setLOD(S32 lod)
  452. //{
  453. // mLOD = lod;
  454. // //RN: uncomment this to visualize LOD levels
  455. // //std::string label = llformat("%d", lod);
  456. // //setLabel(label);
  457. //}
  458. S32 LLHUDText::getMaxLines()
  459. {
  460. return mMaxLines;
  461. //switch(mLOD)
  462. //{
  463. //case 0:
  464. // return mMaxLines;
  465. //case 1:
  466. // return mMaxLines > 0 ? mMaxLines / 2 : 5;
  467. //case 2:
  468. // return mMaxLines > 0 ? mMaxLines / 3 : 2;
  469. //default:
  470. // // label only
  471. // return 0;
  472. //}
  473. }
  474. void LLHUDText::markDead()
  475. {
  476. sTextObjects.erase(LLPointer<LLHUDText>(this));
  477. LLHUDObject::markDead();
  478. }
  479. void LLHUDText::renderAllHUD()
  480. {
  481. LLGLState::checkStates();
  482. LLGLState::checkTextureChannels();
  483. LLGLState::checkClientArrays();
  484. {
  485. LLGLEnable color_mat(GL_COLOR_MATERIAL);
  486. LLGLDepthTest depth(GL_FALSE, GL_FALSE);
  487. VisibleTextObjectIterator text_it;
  488. for (text_it = sVisibleHUDTextObjects.begin(); text_it != sVisibleHUDTextObjects.end(); ++text_it)
  489. {
  490. (*text_it)->renderText();
  491. }
  492. }
  493. LLVertexBuffer::unbind();
  494. LLVertexBuffer::unbind();
  495. LLGLState::checkStates();
  496. LLGLState::checkTextureChannels();
  497. LLGLState::checkClientArrays();
  498. }
  499. void LLHUDText::shiftAll(const LLVector3& offset)
  500. {
  501. TextObjectIterator text_it;
  502. for (text_it = sTextObjects.begin(); text_it != sTextObjects.end(); ++text_it)
  503. {
  504. LLHUDText *textp = text_it->get();
  505. textp->shift(offset);
  506. }
  507. }
  508. void LLHUDText::shift(const LLVector3& offset)
  509. {
  510. mPositionAgent += offset;
  511. }
  512. //static
  513. // called when UI scale changes, to flush font width caches
  514. void LLHUDText::reshape()
  515. {
  516. TextObjectIterator text_it;
  517. for (text_it = sTextObjects.begin(); text_it != sTextObjects.end(); ++text_it)
  518. {
  519. LLHUDText* textp = (*text_it);
  520. std::vector<LLHUDTextSegment>::iterator segment_iter;
  521. for (segment_iter = textp->mTextSegments.begin();
  522. segment_iter != textp->mTextSegments.end(); ++segment_iter )
  523. {
  524. segment_iter->clearFontWidthMap();
  525. }
  526. }
  527. }
  528. //============================================================================
  529. F32 LLHUDText::LLHUDTextSegment::getWidth(const LLFontGL* font)
  530. {
  531. std::map<const LLFontGL*, F32>::iterator iter = mFontWidthMap.find(font);
  532. if (iter != mFontWidthMap.end())
  533. {
  534. return iter->second;
  535. }
  536. else
  537. {
  538. F32 width = font->getWidthF32(mText.c_str());
  539. mFontWidthMap[font] = width;
  540. return width;
  541. }
  542. }