/indra/llrender/llfontgl.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 1236 lines · 915 code · 187 blank · 134 comment · 170 complexity · 41f0ae47e53d507bc520923ee1d98e41 MD5 · raw file

  1. /**
  2. * @file llfontgl.cpp
  3. * @brief Wrapper around FreeType
  4. *
  5. * $LicenseInfo:firstyear=2001&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 "linden_common.h"
  27. #include "llfontgl.h"
  28. // Linden library includes
  29. #include "llfontfreetype.h"
  30. #include "llfontbitmapcache.h"
  31. #include "llfontregistry.h"
  32. #include "llgl.h"
  33. #include "llimagegl.h"
  34. #include "llrender.h"
  35. #include "llstl.h"
  36. #include "v4color.h"
  37. #include "lltexture.h"
  38. #include "lldir.h"
  39. // Third party library includes
  40. #include <boost/tokenizer.hpp>
  41. const S32 BOLD_OFFSET = 1;
  42. // static class members
  43. F32 LLFontGL::sVertDPI = 96.f;
  44. F32 LLFontGL::sHorizDPI = 96.f;
  45. F32 LLFontGL::sScaleX = 1.f;
  46. F32 LLFontGL::sScaleY = 1.f;
  47. BOOL LLFontGL::sDisplayFont = TRUE ;
  48. std::string LLFontGL::sAppDir;
  49. LLColor4 LLFontGL::sShadowColor(0.f, 0.f, 0.f, 1.f);
  50. LLFontRegistry* LLFontGL::sFontRegistry = NULL;
  51. LLCoordFont LLFontGL::sCurOrigin;
  52. std::vector<LLCoordFont> LLFontGL::sOriginStack;
  53. const F32 EXT_X_BEARING = 1.f;
  54. const F32 EXT_Y_BEARING = 0.f;
  55. const F32 EXT_KERNING = 1.f;
  56. const F32 PIXEL_BORDER_THRESHOLD = 0.0001f;
  57. const F32 PIXEL_CORRECTION_DISTANCE = 0.01f;
  58. const F32 PAD_UVY = 0.5f; // half of vertical padding between glyphs in the glyph texture
  59. const F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f;
  60. static F32 llfont_round_x(F32 x)
  61. {
  62. //return llfloor((x-LLFontGL::sCurOrigin.mX)/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleX+LLFontGL::sCurOrigin.mX;
  63. //return llfloor(x/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleY;
  64. return x;
  65. }
  66. static F32 llfont_round_y(F32 y)
  67. {
  68. //return llfloor((y-LLFontGL::sCurOrigin.mY)/LLFontGL::sScaleY+0.5f)*LLFontGL::sScaleY+LLFontGL::sCurOrigin.mY;
  69. //return llfloor(y+0.5f);
  70. return y;
  71. }
  72. LLFontGL::LLFontGL()
  73. {
  74. }
  75. LLFontGL::~LLFontGL()
  76. {
  77. }
  78. void LLFontGL::reset()
  79. {
  80. mFontFreetype->reset(sVertDPI, sHorizDPI);
  81. }
  82. void LLFontGL::destroyGL()
  83. {
  84. mFontFreetype->destroyGL();
  85. }
  86. BOOL LLFontGL::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback)
  87. {
  88. if(mFontFreetype == reinterpret_cast<LLFontFreetype*>(NULL))
  89. {
  90. mFontFreetype = new LLFontFreetype;
  91. }
  92. return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, components, is_fallback);
  93. }
  94. static LLFastTimer::DeclareTimer FTM_RENDER_FONTS("Fonts");
  95. S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRect& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
  96. ShadowType shadow, S32 max_chars, F32* right_x, BOOL use_ellipses) const
  97. {
  98. F32 x = rect.mLeft;
  99. F32 y = 0.f;
  100. switch(valign)
  101. {
  102. case TOP:
  103. y = rect.mTop;
  104. break;
  105. case VCENTER:
  106. y = rect.getCenterY();
  107. break;
  108. case BASELINE:
  109. case BOTTOM:
  110. y = rect.mBottom;
  111. break;
  112. default:
  113. y = rect.mBottom;
  114. break;
  115. }
  116. return render(wstr, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, rect.getWidth(), right_x, use_ellipses);
  117. }
  118. S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
  119. ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const
  120. {
  121. LLFastTimer _(FTM_RENDER_FONTS);
  122. if(!sDisplayFont) //do not display texts
  123. {
  124. return wstr.length() ;
  125. }
  126. if (wstr.empty())
  127. {
  128. return 0;
  129. }
  130. gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
  131. S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX);
  132. // determine which style flags need to be added programmatically by stripping off the
  133. // style bits that are drawn by the underlying Freetype font
  134. U8 style_to_add = (style | mFontDescriptor.getStyle()) & ~mFontFreetype->getStyle();
  135. F32 drop_shadow_strength = 0.f;
  136. if (shadow != NO_SHADOW)
  137. {
  138. F32 luminance;
  139. color.calcHSL(NULL, NULL, &luminance);
  140. drop_shadow_strength = clamp_rescale(luminance, 0.35f, 0.6f, 0.f, 1.f);
  141. if (luminance < 0.35f)
  142. {
  143. shadow = NO_SHADOW;
  144. }
  145. }
  146. gGL.pushUIMatrix();
  147. gGL.loadUIIdentity();
  148. //gGL.translateUI(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ);
  149. // this code snaps the text origin to a pixel grid to start with
  150. //F32 pixel_offset_x = llround((F32)sCurOrigin.mX) - (sCurOrigin.mX);
  151. //F32 pixel_offset_y = llround((F32)sCurOrigin.mY) - (sCurOrigin.mY);
  152. //gGL.translateUI(-pixel_offset_x, -pixel_offset_y, 0.f);
  153. LLVector2 origin(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY));
  154. // snap the text origin to a pixel grid to start with
  155. origin.mV[VX] -= llround((F32)sCurOrigin.mX) - (sCurOrigin.mX);
  156. origin.mV[VY] -= llround((F32)sCurOrigin.mY) - (sCurOrigin.mY);
  157. // Depth translation, so that floating text appears 'inworld'
  158. // and is correclty occluded.
  159. gGL.translatef(0.f,0.f,sCurOrigin.mZ);
  160. S32 chars_drawn = 0;
  161. S32 i;
  162. S32 length;
  163. if (-1 == max_chars)
  164. {
  165. length = (S32)wstr.length() - begin_offset;
  166. }
  167. else
  168. {
  169. length = llmin((S32)wstr.length() - begin_offset, max_chars );
  170. }
  171. F32 cur_x, cur_y, cur_render_x, cur_render_y;
  172. // Not guaranteed to be set correctly
  173. gGL.setSceneBlendType(LLRender::BT_ALPHA);
  174. cur_x = ((F32)x * sScaleX) + origin.mV[VX];
  175. cur_y = ((F32)y * sScaleY) + origin.mV[VY];
  176. // Offset y by vertical alignment.
  177. switch (valign)
  178. {
  179. case TOP:
  180. cur_y -= mFontFreetype->getAscenderHeight();
  181. break;
  182. case BOTTOM:
  183. cur_y += mFontFreetype->getDescenderHeight();
  184. break;
  185. case VCENTER:
  186. cur_y -= (mFontFreetype->getAscenderHeight() - mFontFreetype->getDescenderHeight()) / 2.f;
  187. break;
  188. case BASELINE:
  189. // Baseline, do nothing.
  190. break;
  191. default:
  192. break;
  193. }
  194. switch (halign)
  195. {
  196. case LEFT:
  197. break;
  198. case RIGHT:
  199. cur_x -= llmin(scaled_max_pixels, llround(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX));
  200. break;
  201. case HCENTER:
  202. cur_x -= llmin(scaled_max_pixels, llround(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX)) / 2;
  203. break;
  204. default:
  205. break;
  206. }
  207. cur_render_y = cur_y;
  208. cur_render_x = cur_x;
  209. F32 start_x = llround(cur_x);
  210. const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache();
  211. F32 inv_width = 1.f / font_bitmap_cache->getBitmapWidth();
  212. F32 inv_height = 1.f / font_bitmap_cache->getBitmapHeight();
  213. const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL;
  214. BOOL draw_ellipses = FALSE;
  215. if (use_ellipses)
  216. {
  217. // check for too long of a string
  218. S32 string_width = llround(getWidthF32(wstr.c_str(), begin_offset, max_chars) * sScaleX);
  219. if (string_width > scaled_max_pixels)
  220. {
  221. // use four dots for ellipsis width to generate padding
  222. const LLWString dots(utf8str_to_wstring(std::string("....")));
  223. scaled_max_pixels = llmax(0, scaled_max_pixels - llround(getWidthF32(dots.c_str())));
  224. draw_ellipses = TRUE;
  225. }
  226. }
  227. const LLFontGlyphInfo* next_glyph = NULL;
  228. const S32 GLYPH_BATCH_SIZE = 30;
  229. LLVector3 vertices[GLYPH_BATCH_SIZE * 4];
  230. LLVector2 uvs[GLYPH_BATCH_SIZE * 4];
  231. LLColor4U colors[GLYPH_BATCH_SIZE * 4];
  232. LLColor4U text_color(color);
  233. S32 bitmap_num = -1;
  234. S32 glyph_count = 0;
  235. for (i = begin_offset; i < begin_offset + length; i++)
  236. {
  237. llwchar wch = wstr[i];
  238. const LLFontGlyphInfo* fgi = next_glyph;
  239. next_glyph = NULL;
  240. if(!fgi)
  241. {
  242. fgi = mFontFreetype->getGlyphInfo(wch);
  243. }
  244. if (!fgi)
  245. {
  246. llerrs << "Missing Glyph Info" << llendl;
  247. break;
  248. }
  249. // Per-glyph bitmap texture.
  250. S32 next_bitmap_num = fgi->mBitmapNum;
  251. if (next_bitmap_num != bitmap_num)
  252. {
  253. // Actually draw the queued glyphs before switching their texture;
  254. // otherwise the queued glyphs will be taken from wrong textures.
  255. if (glyph_count > 0)
  256. {
  257. gGL.begin(LLRender::QUADS);
  258. {
  259. gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4);
  260. }
  261. gGL.end();
  262. glyph_count = 0;
  263. }
  264. bitmap_num = next_bitmap_num;
  265. LLImageGL *font_image = font_bitmap_cache->getImageGL(bitmap_num);
  266. gGL.getTexUnit(0)->bind(font_image);
  267. }
  268. if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth))
  269. {
  270. // Not enough room for this character.
  271. break;
  272. }
  273. // Draw the text at the appropriate location
  274. //Specify vertices and texture coordinates
  275. LLRectf uv_rect((fgi->mXBitmapOffset) * inv_width,
  276. (fgi->mYBitmapOffset + fgi->mHeight + PAD_UVY) * inv_height,
  277. (fgi->mXBitmapOffset + fgi->mWidth) * inv_width,
  278. (fgi->mYBitmapOffset - PAD_UVY) * inv_height);
  279. // snap glyph origin to whole screen pixel
  280. LLRectf screen_rect(llround(cur_render_x + (F32)fgi->mXBearing),
  281. llround(cur_render_y + (F32)fgi->mYBearing),
  282. llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth,
  283. llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight);
  284. if (glyph_count >= GLYPH_BATCH_SIZE)
  285. {
  286. gGL.begin(LLRender::QUADS);
  287. {
  288. gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4);
  289. }
  290. gGL.end();
  291. glyph_count = 0;
  292. }
  293. drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect, text_color, style_to_add, shadow, drop_shadow_strength);
  294. chars_drawn++;
  295. cur_x += fgi->mXAdvance;
  296. cur_y += fgi->mYAdvance;
  297. llwchar next_char = wstr[i+1];
  298. if (next_char && (next_char < LAST_CHARACTER))
  299. {
  300. // Kern this puppy.
  301. next_glyph = mFontFreetype->getGlyphInfo(next_char);
  302. cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
  303. }
  304. // Round after kerning.
  305. // Must do this to cur_x, not just to cur_render_x, otherwise you
  306. // will squish sub-pixel kerned characters too close together.
  307. // For example, "CCCCC" looks bad.
  308. cur_x = (F32)llround(cur_x);
  309. //cur_y = (F32)llround(cur_y);
  310. cur_render_x = cur_x;
  311. cur_render_y = cur_y;
  312. }
  313. gGL.begin(LLRender::QUADS);
  314. {
  315. gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4);
  316. }
  317. gGL.end();
  318. if (right_x)
  319. {
  320. *right_x = (cur_x - origin.mV[VX]) / sScaleX;
  321. }
  322. //FIXME: add underline as glyph?
  323. if (style_to_add & UNDERLINE)
  324. {
  325. F32 descender = mFontFreetype->getDescenderHeight();
  326. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  327. gGL.begin(LLRender::LINES);
  328. gGL.vertex2f(start_x, cur_y - (descender));
  329. gGL.vertex2f(cur_x, cur_y - (descender));
  330. gGL.end();
  331. }
  332. if (draw_ellipses)
  333. {
  334. // recursively render ellipses at end of string
  335. // we've already reserved enough room
  336. gGL.pushUIMatrix();
  337. renderUTF8(std::string("..."),
  338. 0,
  339. (cur_x - origin.mV[VX]) / sScaleX, (F32)y,
  340. color,
  341. LEFT, valign,
  342. style_to_add,
  343. shadow,
  344. S32_MAX, max_pixels,
  345. right_x,
  346. FALSE);
  347. gGL.popUIMatrix();
  348. }
  349. gGL.popUIMatrix();
  350. return chars_drawn;
  351. }
  352. S32 LLFontGL::render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const
  353. {
  354. return render(text, begin_offset, x, y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
  355. }
  356. S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const
  357. {
  358. return render(utf8str_to_wstring(text), begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses);
  359. }
  360. S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const
  361. {
  362. return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
  363. }
  364. S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow) const
  365. {
  366. return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, halign, valign, style, shadow, S32_MAX, S32_MAX, NULL, FALSE);
  367. }
  368. // font metrics - override for LLFontFreetype that returns units of virtual pixels
  369. F32 LLFontGL::getLineHeight() const
  370. {
  371. return (F32)llround(mFontFreetype->getLineHeight() / sScaleY);
  372. }
  373. F32 LLFontGL::getAscenderHeight() const
  374. {
  375. return (F32)llround(mFontFreetype->getAscenderHeight() / sScaleY);
  376. }
  377. F32 LLFontGL::getDescenderHeight() const
  378. {
  379. return (F32)llround(mFontFreetype->getDescenderHeight() / sScaleY);
  380. }
  381. S32 LLFontGL::getWidth(const std::string& utf8text) const
  382. {
  383. LLWString wtext = utf8str_to_wstring(utf8text);
  384. return getWidth(wtext.c_str(), 0, S32_MAX);
  385. }
  386. S32 LLFontGL::getWidth(const llwchar* wchars) const
  387. {
  388. return getWidth(wchars, 0, S32_MAX);
  389. }
  390. S32 LLFontGL::getWidth(const std::string& utf8text, S32 begin_offset, S32 max_chars) const
  391. {
  392. LLWString wtext = utf8str_to_wstring(utf8text);
  393. return getWidth(wtext.c_str(), begin_offset, max_chars);
  394. }
  395. S32 LLFontGL::getWidth(const llwchar* wchars, S32 begin_offset, S32 max_chars) const
  396. {
  397. F32 width = getWidthF32(wchars, begin_offset, max_chars);
  398. return llround(width);
  399. }
  400. F32 LLFontGL::getWidthF32(const std::string& utf8text) const
  401. {
  402. LLWString wtext = utf8str_to_wstring(utf8text);
  403. return getWidthF32(wtext.c_str(), 0, S32_MAX);
  404. }
  405. F32 LLFontGL::getWidthF32(const llwchar* wchars) const
  406. {
  407. return getWidthF32(wchars, 0, S32_MAX);
  408. }
  409. F32 LLFontGL::getWidthF32(const std::string& utf8text, S32 begin_offset, S32 max_chars ) const
  410. {
  411. LLWString wtext = utf8str_to_wstring(utf8text);
  412. return getWidthF32(wtext.c_str(), begin_offset, max_chars);
  413. }
  414. F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars) const
  415. {
  416. const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL;
  417. F32 cur_x = 0;
  418. const S32 max_index = begin_offset + max_chars;
  419. const LLFontGlyphInfo* next_glyph = NULL;
  420. F32 width_padding = 0.f;
  421. for (S32 i = begin_offset; i < max_index && wchars[i] != 0; i++)
  422. {
  423. llwchar wch = wchars[i];
  424. const LLFontGlyphInfo* fgi = next_glyph;
  425. next_glyph = NULL;
  426. if(!fgi)
  427. {
  428. fgi = mFontFreetype->getGlyphInfo(wch);
  429. }
  430. F32 advance = mFontFreetype->getXAdvance(fgi);
  431. // for the last character we want to measure the greater of its width and xadvance values
  432. // so keep track of the difference between these values for the each character we measure
  433. // so we can fix things up at the end
  434. width_padding = llmax( 0.f, // always use positive padding amount
  435. width_padding - advance, // previous padding left over after advance of current character
  436. (F32)(fgi->mWidth + fgi->mXBearing) - advance); // difference between width of this character and advance to next character
  437. cur_x += advance;
  438. llwchar next_char = wchars[i+1];
  439. if (((i + 1) < begin_offset + max_chars)
  440. && next_char
  441. && (next_char < LAST_CHARACTER))
  442. {
  443. // Kern this puppy.
  444. next_glyph = mFontFreetype->getGlyphInfo(next_char);
  445. cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
  446. }
  447. // Round after kerning.
  448. cur_x = (F32)llround(cur_x);
  449. }
  450. // add in extra pixels for last character's width past its xadvance
  451. cur_x += width_padding;
  452. return cur_x / sScaleX;
  453. }
  454. // Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels
  455. S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars, EWordWrapStyle end_on_word_boundary) const
  456. {
  457. if (!wchars || !wchars[0] || max_chars == 0)
  458. {
  459. return 0;
  460. }
  461. llassert(max_pixels >= 0.f);
  462. llassert(max_chars >= 0);
  463. BOOL clip = FALSE;
  464. F32 cur_x = 0;
  465. F32 drawn_x = 0;
  466. S32 start_of_last_word = 0;
  467. BOOL in_word = FALSE;
  468. // avoid S32 overflow when max_pixels == S32_MAX by staying in floating point
  469. F32 scaled_max_pixels = max_pixels * sScaleX;
  470. F32 width_padding = 0.f;
  471. LLFontGlyphInfo* next_glyph = NULL;
  472. S32 i;
  473. for (i=0; (i < max_chars); i++)
  474. {
  475. llwchar wch = wchars[i];
  476. if(wch == 0)
  477. {
  478. // Null terminator. We're done.
  479. break;
  480. }
  481. if (in_word)
  482. {
  483. if (iswspace(wch))
  484. {
  485. if(wch !=(0x00A0))
  486. {
  487. in_word = FALSE;
  488. }
  489. }
  490. if (iswindividual(wch))
  491. {
  492. if (iswpunct(wchars[i+1]))
  493. {
  494. in_word=TRUE;
  495. }
  496. else
  497. {
  498. in_word=FALSE;
  499. start_of_last_word = i;
  500. }
  501. }
  502. }
  503. else
  504. {
  505. start_of_last_word = i;
  506. if (!iswspace(wch)||!iswindividual(wch))
  507. {
  508. in_word = TRUE;
  509. }
  510. }
  511. LLFontGlyphInfo* fgi = next_glyph;
  512. next_glyph = NULL;
  513. if(!fgi)
  514. {
  515. fgi = mFontFreetype->getGlyphInfo(wch);
  516. }
  517. // account for glyphs that run beyond the starting point for the next glyphs
  518. width_padding = llmax( 0.f, // always use positive padding amount
  519. width_padding - fgi->mXAdvance, // previous padding left over after advance of current character
  520. (F32)(fgi->mWidth + fgi->mXBearing) - fgi->mXAdvance); // difference between width of this character and advance to next character
  521. cur_x += fgi->mXAdvance;
  522. // clip if current character runs past scaled_max_pixels (using width_padding)
  523. if (scaled_max_pixels < cur_x + width_padding)
  524. {
  525. clip = TRUE;
  526. break;
  527. }
  528. if (((i+1) < max_chars) && wchars[i+1])
  529. {
  530. // Kern this puppy.
  531. next_glyph = mFontFreetype->getGlyphInfo(wchars[i+1]);
  532. cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
  533. }
  534. // Round after kerning.
  535. cur_x = llround(cur_x);
  536. drawn_x = cur_x;
  537. }
  538. if( clip )
  539. {
  540. switch (end_on_word_boundary)
  541. {
  542. case ONLY_WORD_BOUNDARIES:
  543. i = start_of_last_word;
  544. break;
  545. case WORD_BOUNDARY_IF_POSSIBLE:
  546. if (start_of_last_word != 0)
  547. {
  548. i = start_of_last_word;
  549. }
  550. break;
  551. default:
  552. case ANYWHERE:
  553. // do nothing
  554. break;
  555. }
  556. }
  557. return i;
  558. }
  559. S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos, S32 max_chars) const
  560. {
  561. if (!wchars || !wchars[0] || max_chars == 0)
  562. {
  563. return 0;
  564. }
  565. F32 total_width = 0.0;
  566. S32 drawable_chars = 0;
  567. F32 scaled_max_pixels = max_pixels * sScaleX;
  568. S32 start = llmin(start_pos, text_len - 1);
  569. for (S32 i = start; i >= 0; i--)
  570. {
  571. llwchar wch = wchars[i];
  572. const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
  573. // last character uses character width, since the whole character needs to be visible
  574. // other characters just use advance
  575. F32 width = (i == start)
  576. ? (F32)(fgi->mWidth + fgi->mXBearing) // use actual width for last character
  577. : fgi->mXAdvance; // use advance for all other characters
  578. if( scaled_max_pixels < (total_width + width) )
  579. {
  580. break;
  581. }
  582. total_width += width;
  583. drawable_chars++;
  584. if( max_chars >= 0 && drawable_chars >= max_chars )
  585. {
  586. break;
  587. }
  588. if ( i > 0 )
  589. {
  590. // kerning
  591. total_width += mFontFreetype->getXKerning(wchars[i-1], wch);
  592. }
  593. // Round after kerning.
  594. total_width = llround(total_width);
  595. }
  596. if (drawable_chars == 0)
  597. {
  598. return start_pos; // just draw last character
  599. }
  600. else
  601. {
  602. // if only 1 character is drawable, we want to return start_pos as the first character to draw
  603. // if 2 are drawable, return start_pos and character before start_pos, etc.
  604. return start_pos + 1 - drawable_chars;
  605. }
  606. }
  607. S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 target_x, F32 max_pixels, S32 max_chars, BOOL round) const
  608. {
  609. if (!wchars || !wchars[0] || max_chars == 0)
  610. {
  611. return 0;
  612. }
  613. F32 cur_x = 0;
  614. target_x *= sScaleX;
  615. // max_chars is S32_MAX by default, so make sure we don't get overflow
  616. const S32 max_index = begin_offset + llmin(S32_MAX - begin_offset, max_chars - 1);
  617. F32 scaled_max_pixels = max_pixels * sScaleX;
  618. const LLFontGlyphInfo* next_glyph = NULL;
  619. S32 pos;
  620. for (pos = begin_offset; pos < max_index; pos++)
  621. {
  622. llwchar wch = wchars[pos];
  623. if (!wch)
  624. {
  625. break; // done
  626. }
  627. const LLFontGlyphInfo* glyph = next_glyph;
  628. next_glyph = NULL;
  629. if(!glyph)
  630. {
  631. glyph = mFontFreetype->getGlyphInfo(wch);
  632. }
  633. F32 char_width = mFontFreetype->getXAdvance(glyph);
  634. if (round)
  635. {
  636. // Note: if the mouse is on the left half of the character, the pick is to the character's left
  637. // If it's on the right half, the pick is to the right.
  638. if (target_x < cur_x + char_width*0.5f)
  639. {
  640. break;
  641. }
  642. }
  643. else if (target_x < cur_x + char_width)
  644. {
  645. break;
  646. }
  647. if (scaled_max_pixels < cur_x + char_width)
  648. {
  649. break;
  650. }
  651. cur_x += char_width;
  652. if (((pos + 1) < max_index)
  653. && (wchars[(pos + 1)]))
  654. {
  655. // Kern this puppy.
  656. next_glyph = mFontFreetype->getGlyphInfo(wchars[pos + 1]);
  657. cur_x += mFontFreetype->getXKerning(glyph, next_glyph);
  658. }
  659. // Round after kerning.
  660. cur_x = llround(cur_x);
  661. }
  662. return llmin(max_chars, pos - begin_offset);
  663. }
  664. const LLFontDescriptor& LLFontGL::getFontDesc() const
  665. {
  666. return mFontDescriptor;
  667. }
  668. // static
  669. void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector<std::string>& xui_paths, bool create_gl_textures)
  670. {
  671. sVertDPI = (F32)llfloor(screen_dpi * y_scale);
  672. sHorizDPI = (F32)llfloor(screen_dpi * x_scale);
  673. sScaleX = x_scale;
  674. sScaleY = y_scale;
  675. sAppDir = app_dir;
  676. // Font registry init
  677. if (!sFontRegistry)
  678. {
  679. sFontRegistry = new LLFontRegistry(xui_paths, create_gl_textures);
  680. sFontRegistry->parseFontInfo("fonts.xml");
  681. }
  682. else
  683. {
  684. sFontRegistry->reset();
  685. }
  686. }
  687. // Force standard fonts to get generated up front.
  688. // This is primarily for error detection purposes.
  689. // Don't do this during initClass because it can be slow and we want to get
  690. // the viewer window on screen first. JC
  691. // static
  692. bool LLFontGL::loadDefaultFonts()
  693. {
  694. bool succ = true;
  695. succ &= (NULL != getFontSansSerifSmall());
  696. succ &= (NULL != getFontSansSerif());
  697. succ &= (NULL != getFontSansSerifBig());
  698. succ &= (NULL != getFontSansSerifHuge());
  699. succ &= (NULL != getFontSansSerifBold());
  700. succ &= (NULL != getFontMonospace());
  701. succ &= (NULL != getFontExtChar());
  702. return succ;
  703. }
  704. // static
  705. void LLFontGL::destroyDefaultFonts()
  706. {
  707. // Remove the actual fonts.
  708. delete sFontRegistry;
  709. sFontRegistry = NULL;
  710. }
  711. //static
  712. void LLFontGL::destroyAllGL()
  713. {
  714. if (sFontRegistry)
  715. {
  716. sFontRegistry->destroyGL();
  717. }
  718. }
  719. // static
  720. U8 LLFontGL::getStyleFromString(const std::string &style)
  721. {
  722. S32 ret = 0;
  723. if (style.find("NORMAL") != style.npos)
  724. {
  725. ret |= NORMAL;
  726. }
  727. if (style.find("BOLD") != style.npos)
  728. {
  729. ret |= BOLD;
  730. }
  731. if (style.find("ITALIC") != style.npos)
  732. {
  733. ret |= ITALIC;
  734. }
  735. if (style.find("UNDERLINE") != style.npos)
  736. {
  737. ret |= UNDERLINE;
  738. }
  739. return ret;
  740. }
  741. // static
  742. std::string LLFontGL::getStringFromStyle(U8 style)
  743. {
  744. std::string style_string;
  745. if (style & NORMAL)
  746. {
  747. style_string += "|NORMAL";
  748. }
  749. if (style & BOLD)
  750. {
  751. style_string += "|BOLD";
  752. }
  753. if (style & ITALIC)
  754. {
  755. style_string += "|ITALIC";
  756. }
  757. if (style & UNDERLINE)
  758. {
  759. style_string += "|UNDERLINE";
  760. }
  761. return style_string;
  762. }
  763. // static
  764. std::string LLFontGL::nameFromFont(const LLFontGL* fontp)
  765. {
  766. return fontp->mFontDescriptor.getName();
  767. }
  768. // static
  769. std::string LLFontGL::sizeFromFont(const LLFontGL* fontp)
  770. {
  771. return fontp->mFontDescriptor.getSize();
  772. }
  773. // static
  774. std::string LLFontGL::nameFromHAlign(LLFontGL::HAlign align)
  775. {
  776. if (align == LEFT) return std::string("left");
  777. else if (align == RIGHT) return std::string("right");
  778. else if (align == HCENTER) return std::string("center");
  779. else return std::string();
  780. }
  781. // static
  782. LLFontGL::HAlign LLFontGL::hAlignFromName(const std::string& name)
  783. {
  784. LLFontGL::HAlign gl_hfont_align = LLFontGL::LEFT;
  785. if (name == "left")
  786. {
  787. gl_hfont_align = LLFontGL::LEFT;
  788. }
  789. else if (name == "right")
  790. {
  791. gl_hfont_align = LLFontGL::RIGHT;
  792. }
  793. else if (name == "center")
  794. {
  795. gl_hfont_align = LLFontGL::HCENTER;
  796. }
  797. //else leave left
  798. return gl_hfont_align;
  799. }
  800. // static
  801. std::string LLFontGL::nameFromVAlign(LLFontGL::VAlign align)
  802. {
  803. if (align == TOP) return std::string("top");
  804. else if (align == VCENTER) return std::string("center");
  805. else if (align == BASELINE) return std::string("baseline");
  806. else if (align == BOTTOM) return std::string("bottom");
  807. else return std::string();
  808. }
  809. // static
  810. LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name)
  811. {
  812. LLFontGL::VAlign gl_vfont_align = LLFontGL::BASELINE;
  813. if (name == "top")
  814. {
  815. gl_vfont_align = LLFontGL::TOP;
  816. }
  817. else if (name == "center")
  818. {
  819. gl_vfont_align = LLFontGL::VCENTER;
  820. }
  821. else if (name == "baseline")
  822. {
  823. gl_vfont_align = LLFontGL::BASELINE;
  824. }
  825. else if (name == "bottom")
  826. {
  827. gl_vfont_align = LLFontGL::BOTTOM;
  828. }
  829. //else leave baseline
  830. return gl_vfont_align;
  831. }
  832. //static
  833. LLFontGL* LLFontGL::getFontMonospace()
  834. {
  835. static LLFontGL* fontp = getFont(LLFontDescriptor("Monospace","Monospace",0));
  836. return fontp;
  837. }
  838. //static
  839. LLFontGL* LLFontGL::getFontSansSerifSmall()
  840. {
  841. static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Small",0));
  842. return fontp;
  843. }
  844. //static
  845. LLFontGL* LLFontGL::getFontSansSerif()
  846. {
  847. static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Medium",0));
  848. return fontp;
  849. }
  850. //static
  851. LLFontGL* LLFontGL::getFontSansSerifBig()
  852. {
  853. static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Large",0));
  854. return fontp;
  855. }
  856. //static
  857. LLFontGL* LLFontGL::getFontSansSerifHuge()
  858. {
  859. static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Large",0));
  860. return fontp;
  861. }
  862. //static
  863. LLFontGL* LLFontGL::getFontSansSerifBold()
  864. {
  865. static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Medium",BOLD));
  866. return fontp;
  867. }
  868. //static
  869. LLFontGL* LLFontGL::getFontExtChar()
  870. {
  871. return getFontSansSerif();
  872. }
  873. //static
  874. LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc)
  875. {
  876. return sFontRegistry->getFont(desc);
  877. }
  878. //static
  879. LLFontGL* LLFontGL::getFontByName(const std::string& name)
  880. {
  881. // check for most common fonts first
  882. if (name == "SANSSERIF")
  883. {
  884. return getFontSansSerif();
  885. }
  886. else if (name == "SANSSERIF_SMALL")
  887. {
  888. return getFontSansSerifSmall();
  889. }
  890. else if (name == "SANSSERIF_BIG")
  891. {
  892. return getFontSansSerifBig();
  893. }
  894. else if (name == "SMALL" || name == "OCRA")
  895. {
  896. // *BUG: Should this be "MONOSPACE"? Do we use "OCRA" anymore?
  897. // Does "SMALL" mean "SERIF"?
  898. return getFontMonospace();
  899. }
  900. else
  901. {
  902. return NULL;
  903. }
  904. }
  905. //static
  906. LLFontGL* LLFontGL::getFontDefault()
  907. {
  908. return getFontSansSerif(); // Fallback to sans serif as default font
  909. }
  910. // static
  911. std::string LLFontGL::getFontPathSystem()
  912. {
  913. std::string system_path;
  914. // Try to figure out where the system's font files are stored.
  915. char *system_root = NULL;
  916. #if LL_WINDOWS
  917. system_root = getenv("SystemRoot"); /* Flawfinder: ignore */
  918. if (!system_root)
  919. {
  920. llwarns << "SystemRoot not found, attempting to load fonts from default path." << llendl;
  921. }
  922. #endif
  923. if (system_root)
  924. {
  925. system_path = llformat("%s/fonts/", system_root);
  926. }
  927. else
  928. {
  929. #if LL_WINDOWS
  930. // HACK for windows 98/Me
  931. system_path = "/WINDOWS/FONTS/";
  932. #elif LL_DARWIN
  933. // HACK for Mac OS X
  934. system_path = "/System/Library/Fonts/";
  935. #endif
  936. }
  937. return system_path;
  938. }
  939. // static
  940. std::string LLFontGL::getFontPathLocal()
  941. {
  942. std::string local_path;
  943. // Backup files if we can't load from system fonts directory.
  944. // We could store this in an end-user writable directory to allow
  945. // end users to switch fonts.
  946. if (LLFontGL::sAppDir.length())
  947. {
  948. // use specified application dir to look for fonts
  949. local_path = LLFontGL::sAppDir + "/fonts/";
  950. }
  951. else
  952. {
  953. // assume working directory is executable directory
  954. local_path = "./fonts/";
  955. }
  956. return local_path;
  957. }
  958. LLFontGL::LLFontGL(const LLFontGL &source)
  959. {
  960. llerrs << "Not implemented!" << llendl;
  961. }
  962. LLFontGL &LLFontGL::operator=(const LLFontGL &source)
  963. {
  964. llerrs << "Not implemented" << llendl;
  965. return *this;
  966. }
  967. void LLFontGL::renderQuad(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const
  968. {
  969. S32 index = 0;
  970. vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mRight), llfont_round_y(screen_rect.mTop), 0.f);
  971. uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
  972. colors_out[index] = color;
  973. index++;
  974. vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mLeft), llfont_round_y(screen_rect.mTop), 0.f);
  975. uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
  976. colors_out[index] = color;
  977. index++;
  978. vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mLeft), llfont_round_y(screen_rect.mBottom), 0.f);
  979. uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
  980. colors_out[index] = color;
  981. index++;
  982. vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mRight), llfont_round_y(screen_rect.mBottom), 0.f);
  983. uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
  984. colors_out[index] = color;
  985. }
  986. void LLFontGL::drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const
  987. {
  988. F32 slant_offset;
  989. slant_offset = ((style & ITALIC) ? ( -mFontFreetype->getAscenderHeight() * 0.2f) : 0.f);
  990. //FIXME: bold and drop shadow are mutually exclusive only for convenience
  991. //Allow both when we need them.
  992. if (style & BOLD)
  993. {
  994. for (S32 pass = 0; pass < 2; pass++)
  995. {
  996. LLRectf screen_rect_offset = screen_rect;
  997. screen_rect_offset.translate((F32)(pass * BOLD_OFFSET), 0.f);
  998. renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_offset, uv_rect, color, slant_offset);
  999. glyph_count++;
  1000. }
  1001. }
  1002. else if (shadow == DROP_SHADOW_SOFT)
  1003. {
  1004. LLColor4U shadow_color = LLFontGL::sShadowColor;
  1005. shadow_color.mV[VALPHA] = U8(color.mV[VALPHA] * drop_shadow_strength * DROP_SHADOW_SOFT_STRENGTH);
  1006. for (S32 pass = 0; pass < 5; pass++)
  1007. {
  1008. LLRectf screen_rect_offset = screen_rect;
  1009. switch(pass)
  1010. {
  1011. case 0:
  1012. screen_rect_offset.translate(-1.f, -1.f);
  1013. break;
  1014. case 1:
  1015. screen_rect_offset.translate(1.f, -1.f);
  1016. break;
  1017. case 2:
  1018. screen_rect_offset.translate(1.f, 1.f);
  1019. break;
  1020. case 3:
  1021. screen_rect_offset.translate(-1.f, 1.f);
  1022. break;
  1023. case 4:
  1024. screen_rect_offset.translate(0, -2.f);
  1025. break;
  1026. }
  1027. renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_offset, uv_rect, shadow_color, slant_offset);
  1028. glyph_count++;
  1029. }
  1030. renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset);
  1031. glyph_count++;
  1032. }
  1033. else if (shadow == DROP_SHADOW)
  1034. {
  1035. LLColor4U shadow_color = LLFontGL::sShadowColor;
  1036. shadow_color.mV[VALPHA] = U8(color.mV[VALPHA] * drop_shadow_strength);
  1037. LLRectf screen_rect_shadow = screen_rect;
  1038. screen_rect_shadow.translate(1.f, -1.f);
  1039. renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_shadow, uv_rect, shadow_color, slant_offset);
  1040. glyph_count++;
  1041. renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset);
  1042. glyph_count++;
  1043. }
  1044. else // normal rendering
  1045. {
  1046. renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset);
  1047. glyph_count++;
  1048. }
  1049. }