llfontgl.cpp 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825
  1. /**
  2. * @file llfontgl.cpp
  3. * @brief Wrapper around FreeType
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "linden_common.h"
  33. #include <utility>
  34. #include "boost/tokenizer.hpp"
  35. #include "llfontgl.h"
  36. #include "llfasttimer.h"
  37. #include "llfontbitmapcache.h"
  38. #include "llfontfreetype.h"
  39. #include "llgl.h"
  40. #include "llgltexture.h"
  41. #include "llrender.h"
  42. #include "llstl.h"
  43. #include "llcolor4.h"
  44. // This defines the max number of glyphs per batch
  45. constexpr S32 GLYPH_BATCH_SIZE = 48;
  46. // If you change drawGlyph() or renderQuad(), you may have to change this
  47. // number:
  48. constexpr S32 MAX_VERT_PER_GLYPH = 36; // 6 vertices * 6 passes max
  49. constexpr S32 BOLD_OFFSET = 1;
  50. constexpr U8 HAS_SHADOW = LLFontGL::DROP_SHADOW | LLFontGL::DROP_SHADOW_SOFT;
  51. constexpr U8 NO_SHADOW = ~HAS_SHADOW;
  52. // Static class members
  53. F32 LLFontGL::sVertDPI = 96.f;
  54. F32 LLFontGL::sHorizDPI = 96.f;
  55. F32 LLFontGL::sScaleX = 1.f;
  56. F32 LLFontGL::sScaleY = 1.f;
  57. bool LLFontGL::sDisplayFont = true;
  58. bool LLFontGL::sAllowColorUse = true;
  59. LLColor4 LLFontGL::sShadowColor(0.f, 0.f, 0.f, 1.f);
  60. LLColor4U LLFontGL::sShadowColorU(0, 0, 0, 255);
  61. LLFontRegistry* LLFontGL::sFontRegistry = NULL;
  62. LLCoordGL LLFontGL::sCurOrigin;
  63. F32 LLFontGL::sCurDepth;
  64. std::vector<std::pair<LLCoordGL, F32> > LLFontGL::sOriginStack;
  65. constexpr F32 EXT_X_BEARING = 1.f;
  66. constexpr F32 EXT_Y_BEARING = 0.f;
  67. constexpr F32 EXT_KERNING = 1.f;
  68. // Half of vertical padding between glyphs in the glyph texture:
  69. constexpr F32 PAD_UVY = 0.5f;
  70. constexpr F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f;
  71. LLFontGL::~LLFontGL()
  72. {
  73. mEmbeddedChars.clear();
  74. }
  75. void LLFontGL::reset()
  76. {
  77. mFontFreetype->reset(sVertDPI, sHorizDPI);
  78. }
  79. void LLFontGL::destroyGL()
  80. {
  81. mFontFreetype->destroyGL();
  82. }
  83. bool LLFontGL::loadFace(const std::string& filename, F32 point_size,
  84. F32 vert_dpi, F32 horz_dpi, bool is_fallback)
  85. {
  86. if (!mFontFreetype)
  87. {
  88. mFontFreetype = new LLFontFreetype;
  89. }
  90. return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi,
  91. is_fallback);
  92. }
  93. S32 LLFontGL::render(const LLWString& text, S32 begin_offset, F32 x, F32 y,
  94. const LLColor4& color, HAlign halign, VAlign valign,
  95. U8 style, S32 max_chars, S32 max_pixels, F32* right_x,
  96. bool use_embedded, bool use_ellipses,
  97. bool use_color) const
  98. {
  99. if (!sDisplayFont || text.empty())
  100. {
  101. return text.length();
  102. }
  103. gGL.flush();
  104. // We dispatch to either the legacy, glyph by glyph renderer or to the new,
  105. // batched glyphs renderer depending whether we need support for embedded
  106. // items or not (i.e. only the notecards and the text editors allowing
  107. // embedded items still use the legacy renderer to render the said embedded
  108. // items, and only them). HB
  109. if (use_embedded)
  110. {
  111. return oldrender(text, begin_offset, x, y, color, halign, valign,
  112. style, max_chars, max_pixels, right_x, use_ellipses);
  113. }
  114. return newrender(text, begin_offset, x, y, color, halign, valign, style,
  115. max_chars, max_pixels, right_x, use_ellipses, use_color);
  116. }
  117. S32 LLFontGL::newrender(const LLWString& wstr, S32 begin_offset, F32 x, F32 y,
  118. const LLColor4& color, HAlign halign, VAlign valign,
  119. U8 style, S32 max_chars, S32 max_pixels, F32* right_x,
  120. bool use_ellipses, bool use_color) const
  121. {
  122. LL_FAST_TIMER(FTM_RENDER_FONTS_BATCHED);
  123. if (!sAllowColorUse)
  124. {
  125. use_color = false;
  126. }
  127. LLTexUnit* unit0 = gGL.getTexUnit(0);
  128. unit0->enable(LLTexUnit::TT_TEXTURE);
  129. S32 scaled_max_pixels =
  130. max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX);
  131. // Strip off any style bits that are already accounted for by the font.
  132. style = (style | mFontDescriptor.getStyle()) & ~mFontFreetype->getStyle();
  133. F32 drop_shadow_strength = 0.f;
  134. if (style & HAS_SHADOW)
  135. {
  136. F32 luminance;
  137. color.calcHSL(NULL, NULL, &luminance);
  138. drop_shadow_strength = clamp_rescale(luminance, 0.35f, 0.6f, 0.f, 1.f);
  139. if (luminance < 0.35f)
  140. {
  141. style = style & NO_SHADOW;
  142. }
  143. }
  144. gGL.pushUIMatrix();
  145. gGL.loadUIIdentity();
  146. // Depth translation, so that floating text appears 'in-world' and is
  147. // correctly occluded.
  148. gGL.translatef(0.f, 0.f, sCurDepth);
  149. S32 length = (S32)wstr.length() - begin_offset;
  150. if (max_chars != -1 && length > max_chars)
  151. {
  152. length = max_chars;
  153. }
  154. // Not guaranteed to be set correctly
  155. gGL.setSceneBlendType(LLRender::BT_ALPHA);
  156. F32 origin_x = floorf(sCurOrigin.mX * sScaleX);
  157. F32 origin_y = floorf(sCurOrigin.mY * sScaleY);
  158. F32 cur_x = (F32)x * sScaleX + origin_x;
  159. F32 cur_y = (F32)y * sScaleY + origin_y;
  160. // Offset y by vertical alignment; use unscaled font metrics here
  161. switch (valign)
  162. {
  163. case BASELINE: // Baseline, do nothing.
  164. break;
  165. case TOP:
  166. cur_y -= llceil(mFontFreetype->getAscenderHeight());
  167. break;
  168. case BOTTOM:
  169. cur_y += llceil(mFontFreetype->getDescenderHeight());
  170. break;
  171. case VCENTER:
  172. cur_y -= llceil((llceil(mFontFreetype->getAscenderHeight()) -
  173. llceil(mFontFreetype->getDescenderHeight())) *
  174. 0.5f);
  175. break;
  176. default:
  177. break;
  178. }
  179. switch (halign)
  180. {
  181. case LEFT:
  182. break;
  183. case RIGHT:
  184. cur_x -= llmin(scaled_max_pixels,
  185. ll_roundp(getWidthF32(wstr.c_str(), 0, length) *
  186. sScaleX));
  187. break;
  188. case HCENTER:
  189. cur_x -= llmin(scaled_max_pixels,
  190. ll_roundp(getWidthF32(wstr.c_str(), 0, length) *
  191. sScaleX)) / 2;
  192. break;
  193. default:
  194. break;
  195. }
  196. F32 cur_render_y = cur_y;
  197. F32 cur_render_x = cur_x;
  198. F32 start_x = ll_round(cur_x);
  199. const LLFontBitmapCache* bitmap_cachep =
  200. mFontFreetype->getFontBitmapCache();
  201. F32 inv_width = 1.f / bitmap_cachep->getBitmapWidth();
  202. F32 inv_height = 1.f / bitmap_cachep->getBitmapHeight();
  203. constexpr S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL;
  204. bool draw_ellipses = false;
  205. if (use_ellipses && halign == LEFT)
  206. {
  207. // Check for too long of a string
  208. if (getWidthF32(wstr.c_str(), 0, max_chars) * sScaleX > scaled_max_pixels)
  209. {
  210. // Use four dots for ellipsis width to generate padding
  211. static const LLWString dots(utf8str_to_wstring(std::string("....")));
  212. scaled_max_pixels = scaled_max_pixels -
  213. ll_roundp(getWidthF32(dots.c_str()));
  214. if (scaled_max_pixels < 0)
  215. {
  216. scaled_max_pixels = 0;
  217. }
  218. draw_ellipses = true;
  219. }
  220. }
  221. const LLFontGlyphInfo* next_glyph = NULL;
  222. static LLVector3 vertices[GLYPH_BATCH_SIZE * MAX_VERT_PER_GLYPH];
  223. static LLVector2 uvs[GLYPH_BATCH_SIZE * MAX_VERT_PER_GLYPH];
  224. static LLColor4U colors[GLYPH_BATCH_SIZE * MAX_VERT_PER_GLYPH];
  225. LLColor4U text_color = LLColor4U(color);
  226. // Preserve the transparency to render fading emojis in fading text (e.g.
  227. // for the chat console)... HB
  228. LLColor4U emoji_color(255, 255, 255, text_color.mV[VW]);
  229. U32 b_type = use_color ? EFontGlyphType::Color : EFontGlyphType::Grayscale;
  230. std::pair<U32, S32> bitmap_entry = std::make_pair(b_type, -1);
  231. S32 glyph_count = 0;
  232. S32 chars_drawn = 0;
  233. for (S32 i = begin_offset; i < begin_offset + length; ++i)
  234. {
  235. llwchar wch = wstr[i];
  236. const LLFontGlyphInfo* fgi = next_glyph;
  237. next_glyph = NULL;
  238. if (!fgi)
  239. {
  240. fgi = mFontFreetype->getGlyphInfo(wch, b_type);
  241. }
  242. if (!fgi)
  243. {
  244. llerrs << "Missing Glyph Info" << llendl;
  245. break;
  246. }
  247. // Per-glyph bitmap texture.
  248. std::pair<U32, S32> next_bitmap_entry = fgi->mBitmapEntry;
  249. if (next_bitmap_entry != bitmap_entry)
  250. {
  251. // Actually draw the queued glyphs before switching their texture;
  252. // otherwise the queued glyphs will be taken from wrong textures.
  253. if (glyph_count > 0)
  254. {
  255. gGL.begin(LLRender::TRIANGLES);
  256. gGL.vertexBatchPreTransformed(vertices, uvs, colors,
  257. glyph_count * 6);
  258. gGL.end();
  259. glyph_count = 0;
  260. }
  261. bitmap_entry = next_bitmap_entry;
  262. LLImageGL* impagep =
  263. bitmap_cachep->getImageGL(bitmap_entry.first,
  264. bitmap_entry.second);
  265. unit0->bind(impagep);
  266. }
  267. if (start_x + scaled_max_pixels < cur_x + fgi->mXBearing + fgi->mWidth)
  268. {
  269. // Not enough room for this character.
  270. break;
  271. }
  272. // Draw the text at the appropriate location
  273. //Specify vertices and texture coordinates
  274. LLRectf uv_rect((fgi->mXBitmapOffset) * inv_width,
  275. (fgi->mYBitmapOffset + fgi->mHeight + PAD_UVY) *
  276. 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(ll_round(cur_render_x + (F32)fgi->mXBearing),
  281. ll_round(cur_render_y + (F32)fgi->mYBearing),
  282. ll_round(cur_render_x + (F32)fgi->mXBearing) +
  283. fgi->mWidth,
  284. ll_round(cur_render_y + (F32)fgi->mYBearing) -
  285. fgi->mHeight);
  286. if (glyph_count >= GLYPH_BATCH_SIZE)
  287. {
  288. gGL.begin(LLRender::TRIANGLES);
  289. gGL.vertexBatchPreTransformed(vertices, uvs, colors,
  290. glyph_count * 6);
  291. gGL.end();
  292. glyph_count = 0;
  293. }
  294. const LLColor4U& col =
  295. bitmap_entry.first == EFontGlyphType::Grayscale ? text_color
  296. : emoji_color;
  297. drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect,
  298. col, style, drop_shadow_strength);
  299. ++chars_drawn;
  300. cur_x += fgi->mXAdvance;
  301. cur_y += fgi->mYAdvance;
  302. llwchar next_char = wstr[i + 1];
  303. if (next_char && next_char < LAST_CHARACTER)
  304. {
  305. // Kern this puppy.
  306. next_glyph = mFontFreetype->getGlyphInfo(next_char, b_type);
  307. cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
  308. }
  309. // Round after kerning. Must do this to cur_x, not just to
  310. // cur_render_x, otherwise you will squish sub-pixel kerned characters
  311. // too close together. For example, "CCCCC" looks bad.
  312. cur_x = ll_round(cur_x);
  313. #if 0
  314. cur_y = ll_round(cur_y);
  315. #endif
  316. cur_render_x = cur_x;
  317. cur_render_y = cur_y;
  318. }
  319. gGL.begin(LLRender::TRIANGLES);
  320. gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 6);
  321. gGL.end();
  322. if (right_x)
  323. {
  324. *right_x = (cur_x - origin_x) / sScaleX;
  325. }
  326. // FIXME: add underline as glyph ?
  327. if (style & UNDERLINE)
  328. {
  329. F32 descender = mFontFreetype->getDescenderHeight();
  330. unit0->unbind(LLTexUnit::TT_TEXTURE);
  331. gGL.begin(LLRender::LINES);
  332. gGL.vertex2f(start_x, cur_y - descender);
  333. gGL.vertex2f(cur_x, cur_y - descender);
  334. gGL.end();
  335. }
  336. if (draw_ellipses)
  337. {
  338. // Recursively render ellipses at end of string; we've already reserved
  339. // enough room
  340. gGL.pushUIMatrix();
  341. static const LLWString elipse = utf8str_to_wstring(std::string("..."));
  342. newrender(elipse, 0, (cur_x - origin_x) / sScaleX, (F32)y, color, LEFT,
  343. valign, style, S32_MAX, max_pixels, right_x, false, false);
  344. gGL.popUIMatrix();
  345. }
  346. gGL.popUIMatrix();
  347. gGL.flush();
  348. return chars_drawn;
  349. }
  350. S32 LLFontGL::oldrender(const LLWString& wstr, S32 begin_offset, F32 x, F32 y,
  351. const LLColor4& color, HAlign halign, VAlign valign,
  352. U8 style, S32 max_chars, S32 max_pixels, F32* right_x,
  353. bool use_ellipses) const
  354. {
  355. LL_FAST_TIMER(FTM_RENDER_FONTS_SERIALIZED);
  356. LLTexUnit* unit0 = gGL.getTexUnit(0);
  357. unit0->enable(LLTexUnit::TT_TEXTURE);
  358. S32 scaled_max_pixels =
  359. max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX);
  360. // Strip off any style bits that are already accounted for by the font.
  361. style = (style | mFontDescriptor.getStyle()) & ~mFontFreetype->getStyle();
  362. F32 drop_shadow_strength = 0.f;
  363. if (style & HAS_SHADOW)
  364. {
  365. F32 luminance;
  366. color.calcHSL(NULL, NULL, &luminance);
  367. drop_shadow_strength = clamp_rescale(luminance, 0.35f, 0.6f, 0.f, 1.f);
  368. if (luminance < 0.35f)
  369. {
  370. style = style & NO_SHADOW;
  371. }
  372. }
  373. gGL.pushUIMatrix();
  374. gGL.loadUIIdentity();
  375. // Depth translation, so that floating text appears 'in-world' and is
  376. // correctly occluded.
  377. gGL.translatef(0.f, 0.f, sCurDepth);
  378. gGL.color4fv(color.mV);
  379. S32 length = (S32)wstr.length() - begin_offset;
  380. if (max_chars != -1 && length > max_chars)
  381. {
  382. length = max_chars;
  383. }
  384. // Not guaranteed to be set correctly
  385. gGL.setSceneBlendType(LLRender::BT_ALPHA);
  386. F32 origin_x = floorf(sCurOrigin.mX * sScaleX);
  387. F32 origin_y = floorf(sCurOrigin.mY * sScaleY);
  388. F32 cur_x = (F32)x * sScaleX + origin_x;
  389. // Offset x by horizontal alignment.
  390. if (halign == RIGHT)
  391. {
  392. cur_x -= llmin(scaled_max_pixels,
  393. ll_roundp(getWidthF32(wstr.c_str(), 0, length) *
  394. sScaleX));
  395. }
  396. else if (halign == HCENTER)
  397. {
  398. cur_x -= llmin(scaled_max_pixels,
  399. ll_roundp(getWidthF32(wstr.c_str(), 0, length) *
  400. sScaleX)) / 2;
  401. }
  402. F32 cur_y = (F32)y * sScaleY + origin_y;
  403. // Offset y by vertical alignment.
  404. if (valign == TOP)
  405. {
  406. cur_y -= llceil(mFontFreetype->getAscenderHeight());
  407. }
  408. else if (valign == BOTTOM)
  409. {
  410. cur_y += llceil(mFontFreetype->getDescenderHeight());
  411. }
  412. else if (valign == VCENTER)
  413. {
  414. cur_y -= llceil((llceil(mFontFreetype->getAscenderHeight()) -
  415. llceil(mFontFreetype->getDescenderHeight())) * 0.5f);
  416. }
  417. F32 cur_render_y = cur_y;
  418. F32 cur_render_x = cur_x;
  419. F32 start_x = ll_round(cur_x);
  420. const LLFontBitmapCache* bitmap_cachep =
  421. mFontFreetype->getFontBitmapCache();
  422. F32 inv_width = 1.f / bitmap_cachep->getBitmapWidth();
  423. F32 inv_height = 1.f / bitmap_cachep->getBitmapHeight();
  424. constexpr S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL;
  425. bool draw_ellipses = false;
  426. if (use_ellipses && halign == LEFT)
  427. {
  428. // Check for too long of a string
  429. if (getWidthF32(wstr.c_str(), 0,
  430. max_chars) * sScaleX > scaled_max_pixels)
  431. {
  432. // Use four dots for ellipsis width to generate padding
  433. static const LLWString dots(utf8str_to_wstring(std::string("....")));
  434. scaled_max_pixels = llmax(0, scaled_max_pixels -
  435. ll_roundp(getWidthF32(dots.c_str())));
  436. draw_ellipses = true;
  437. }
  438. }
  439. // Remember last-used texture to avoid unnecesssary bind calls.
  440. LLImageGL* last_bound_texp = NULL;
  441. static LLFontGL* label_fontp = getFontSansSerif();
  442. S32 chars_drawn = 0;
  443. for (S32 i = begin_offset; i < begin_offset + length; ++i)
  444. {
  445. llwchar wch = wstr[i];
  446. // Handle embedded characters first, if they are enabled. Embedded
  447. // characters are a hack for notecards
  448. const embedded_data_t* ext_data = getEmbeddedCharData(wch);
  449. if (ext_data)
  450. {
  451. LLImageGL* ext_image = ext_data->mImage;
  452. const LLWString& label = ext_data->mLabel;
  453. F32 ext_height = (F32)ext_image->getHeight() * sScaleY;
  454. F32 image_width = ext_image->getWidth();
  455. F32 ext_width = image_width * sScaleX;
  456. F32 ext_advance = (EXT_X_BEARING * sScaleX) + ext_width;
  457. if (!label.empty())
  458. {
  459. ext_advance += (EXT_X_BEARING +
  460. label_fontp->getWidthF32(label.c_str())) *
  461. sScaleX;
  462. }
  463. if (start_x + scaled_max_pixels < cur_x + ext_advance)
  464. {
  465. // Not enough room for this character.
  466. break;
  467. }
  468. if (last_bound_texp != ext_image)
  469. {
  470. unit0->bind(ext_image);
  471. last_bound_texp = ext_image;
  472. }
  473. // Snap origin to whole screen pixel
  474. const F32 ext_x = ll_round(cur_render_x + EXT_X_BEARING * sScaleX);
  475. const F32 ext_y = ll_round(cur_render_y + EXT_Y_BEARING * sScaleY +
  476. mFontFreetype->getAscenderHeight() -
  477. mFontFreetype->getLineHeight());
  478. LLRectf uv_rect(0.f, 1.f, 1.f, 0.f);
  479. LLRectf screen_rect(ext_x, ext_y + ext_height,
  480. ext_x + ext_width, ext_y);
  481. drawGlyph(screen_rect, uv_rect, LLColor4::white, style,
  482. drop_shadow_strength);
  483. if (!label.empty())
  484. {
  485. gGL.pushMatrix();
  486. label_fontp->render(label, 0,
  487. ext_x / sScaleX + image_width +
  488. EXT_X_BEARING - sCurOrigin.mX,
  489. cur_render_y / sScaleY - sCurOrigin.mY,
  490. color, halign, BASELINE, NORMAL, S32_MAX,
  491. S32_MAX, NULL, true);
  492. gGL.popMatrix();
  493. }
  494. gGL.color4fv(color.mV);
  495. ++chars_drawn;
  496. cur_x += ext_advance;
  497. if (i + 1 < length && wstr[i + 1])
  498. {
  499. cur_x += EXT_KERNING * sScaleX;
  500. }
  501. cur_render_x = cur_x;
  502. }
  503. else
  504. {
  505. const LLFontGlyphInfo* fgi = mFontFreetype->getGlyphInfo(wch);
  506. if (!fgi)
  507. {
  508. llerrs << "Missing glyph info" << llendl;
  509. break;
  510. }
  511. // Per-glyph bitmap texture.
  512. LLImageGL* glimagep =
  513. bitmap_cachep->getImageGL(fgi->mBitmapEntry.first,
  514. fgi->mBitmapEntry.second);
  515. if (last_bound_texp != glimagep)
  516. {
  517. unit0->bind(glimagep);
  518. last_bound_texp = glimagep;
  519. }
  520. if (start_x + scaled_max_pixels <
  521. cur_x + fgi->mXBearing + fgi->mWidth)
  522. {
  523. // Not enough room for this character.
  524. break;
  525. }
  526. // Draw the text at the appropriate location
  527. // Specify vertices and texture coordinates
  528. LLRectf uv_rect((fgi->mXBitmapOffset) * inv_width,
  529. (fgi->mYBitmapOffset + fgi->mHeight + PAD_UVY) *
  530. inv_height,
  531. (fgi->mXBitmapOffset + fgi->mWidth) * inv_width,
  532. (fgi->mYBitmapOffset - PAD_UVY) * inv_height);
  533. // Snap glyph origin to whole screen pixel
  534. LLRectf screen_rect(ll_round(cur_render_x + (F32)fgi->mXBearing),
  535. ll_round(cur_render_y + (F32)fgi->mYBearing),
  536. ll_round(cur_render_x + (F32)fgi->mXBearing) +
  537. (F32)fgi->mWidth,
  538. ll_round(cur_render_y + (F32)fgi->mYBearing) -
  539. (F32)fgi->mHeight);
  540. drawGlyph(screen_rect, uv_rect, color, style,
  541. drop_shadow_strength);
  542. ++chars_drawn;
  543. cur_x += fgi->mXAdvance;
  544. cur_y += fgi->mYAdvance;
  545. llwchar next_char = wstr[i + 1];
  546. if (next_char && next_char < LAST_CHARACTER)
  547. {
  548. // Kern this puppy.
  549. const LLFontGlyphInfo* next_glyph =
  550. mFontFreetype->getGlyphInfo(next_char);
  551. cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
  552. }
  553. // Round after kerning. Must do this to cur_x, not just to
  554. // cur_render_x, otherwise you will squish sub-pixel kerned
  555. // characters too close together. For example, "CCCCC" looks bad.
  556. cur_x = ll_round(cur_x);
  557. #if 0
  558. cur_y = ll_round(cur_y);
  559. #endif
  560. cur_render_x = cur_x;
  561. cur_render_y = cur_y;
  562. }
  563. }
  564. if (right_x)
  565. {
  566. *right_x = (cur_x - origin_x) / sScaleX;
  567. }
  568. if (style & UNDERLINE)
  569. {
  570. unit0->unbind(LLTexUnit::TT_TEXTURE);
  571. gGL.begin(LLRender::LINES);
  572. F32 descender = mFontFreetype->getDescenderHeight();
  573. gGL.vertex2f(start_x, cur_y - descender);
  574. gGL.vertex2f(cur_x, cur_y - descender);
  575. gGL.end();
  576. }
  577. // *FIXME: get this working in all alignment cases, etc.
  578. if (draw_ellipses)
  579. {
  580. // Recursively render ellipses at end of string; we've already reserved
  581. // enough room
  582. gGL.pushUIMatrix();
  583. static const LLWString elipse = utf8str_to_wstring(std::string("..."));
  584. oldrender(elipse, 0, (cur_x - origin_x) / sScaleX, (F32)y, color, LEFT,
  585. valign, style, S32_MAX, max_pixels, right_x, false);
  586. gGL.popUIMatrix();
  587. }
  588. gGL.popUIMatrix();
  589. gGL.flush();
  590. return chars_drawn;
  591. }
  592. S32 LLFontGL::render(const LLWString& text, S32 begin_offset, F32 x, F32 y,
  593. const LLColor4& color) const
  594. {
  595. if (!sDisplayFont || text.empty())
  596. {
  597. return text.length();
  598. }
  599. gGL.flush();
  600. return newrender(text, begin_offset, x, y, color, LEFT, BASELINE,
  601. NORMAL, S32_MAX, S32_MAX, NULL, false, true);
  602. }
  603. S32 LLFontGL::renderUTF8(const std::string& text, S32 offset, F32 x, F32 y,
  604. const LLColor4& color, const HAlign halign,
  605. const VAlign valign, U8 style, S32 max_chars,
  606. S32 max_pixels, F32* right_x, bool use_ellipses) const
  607. {
  608. if (!sDisplayFont || text.empty())
  609. {
  610. return text.length();
  611. }
  612. return newrender(utf8str_to_wstring(text), offset, x, y, color, halign,
  613. valign, style, max_chars, max_pixels, right_x,
  614. use_ellipses, true);
  615. }
  616. S32 LLFontGL::renderUTF8(const std::string& text, S32 begin_offset, S32 x,
  617. S32 y, const LLColor4& color) const
  618. {
  619. if (!sDisplayFont || text.empty())
  620. {
  621. return text.length();
  622. }
  623. return newrender(utf8str_to_wstring(text), begin_offset, (F32)x,
  624. (F32)y, color, LEFT, BASELINE, NORMAL, S32_MAX,
  625. S32_MAX, NULL, false, true);
  626. }
  627. S32 LLFontGL::renderUTF8(const std::string& text, S32 begin_offset, S32 x,
  628. S32 y, const LLColor4& color, HAlign halign,
  629. VAlign valign, U8 style) const
  630. {
  631. if (!sDisplayFont || text.empty())
  632. {
  633. return text.length();
  634. }
  635. return newrender(utf8str_to_wstring(text), begin_offset, (F32)x, (F32)y,
  636. color, halign, valign, style, S32_MAX, S32_MAX, NULL,
  637. false, true);
  638. }
  639. // font metrics - override for LLFontFreetype that returns units of virtual pixels
  640. F32 LLFontGL::getAscenderHeight() const
  641. {
  642. return mFontFreetype->getAscenderHeight() / sScaleY;
  643. }
  644. F32 LLFontGL::getDescenderHeight() const
  645. {
  646. return mFontFreetype->getDescenderHeight() / sScaleY;
  647. }
  648. F32 LLFontGL::getLineHeight() const
  649. {
  650. return llceil((mFontFreetype->getAscenderHeight() +
  651. mFontFreetype->getDescenderHeight()) / sScaleY);
  652. }
  653. S32 LLFontGL::getWidth(const std::string& utf8text) const
  654. {
  655. LLWString wtext = utf8str_to_wstring(utf8text);
  656. return getWidth(wtext.c_str(), 0, S32_MAX);
  657. }
  658. S32 LLFontGL::getWidth(const llwchar* wchars) const
  659. {
  660. return getWidth(wchars, 0, S32_MAX);
  661. }
  662. S32 LLFontGL::getWidth(const std::string& utf8text, S32 begin_offset,
  663. S32 max_chars) const
  664. {
  665. LLWString wtext = utf8str_to_wstring(utf8text);
  666. return getWidth(wtext.c_str(), begin_offset, max_chars);
  667. }
  668. S32 LLFontGL::getWidth(const llwchar* wchars, S32 begin_offset,
  669. S32 max_chars, bool use_embedded) const
  670. {
  671. F32 width = getWidthF32(wchars, begin_offset, max_chars, use_embedded);
  672. return ll_roundp(width);
  673. }
  674. F32 LLFontGL::getWidthF32(const std::string& utf8text) const
  675. {
  676. LLWString wtext = utf8str_to_wstring(utf8text);
  677. return getWidthF32(wtext.c_str(), 0, S32_MAX);
  678. }
  679. F32 LLFontGL::getWidthF32(const llwchar* wchars) const
  680. {
  681. return getWidthF32(wchars, 0, S32_MAX);
  682. }
  683. F32 LLFontGL::getWidthF32(const std::string& utf8text, S32 begin_offset,
  684. S32 max_chars) const
  685. {
  686. LLWString wtext = utf8str_to_wstring(utf8text);
  687. return getWidthF32(wtext.c_str(), begin_offset, max_chars);
  688. }
  689. F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset,
  690. S32 max_chars, bool use_embedded) const
  691. {
  692. constexpr S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL;
  693. F32 cur_x = 0;
  694. const S32 max_index = begin_offset + max_chars;
  695. if (use_embedded)
  696. {
  697. for (S32 i = begin_offset; i < max_index; ++i)
  698. {
  699. const llwchar wch = wchars[i];
  700. if (!wch)
  701. {
  702. break; // Done
  703. }
  704. const embedded_data_t* ext_data = getEmbeddedCharData(wch);
  705. if (ext_data)
  706. {
  707. // Handle crappy embedded hack
  708. cur_x += getEmbeddedCharAdvance(ext_data);
  709. if (i + 1 < max_chars && i + 1 < max_index)
  710. {
  711. cur_x += EXT_KERNING * sScaleX;
  712. }
  713. }
  714. else
  715. {
  716. cur_x += mFontFreetype->getXAdvance(wch);
  717. llwchar next_char = wchars[i + 1];
  718. if (i + 1 < max_chars && next_char && next_char < LAST_CHARACTER)
  719. {
  720. // Kern this puppy.
  721. cur_x += mFontFreetype->getXKerning(wch, next_char);
  722. }
  723. }
  724. // Round after kerning.
  725. cur_x = (F32)llfloor(cur_x + 0.5f);
  726. }
  727. return cur_x / sScaleX;
  728. }
  729. for (S32 i = begin_offset; i < max_index; ++i)
  730. {
  731. const llwchar wch = wchars[i];
  732. if (!wch)
  733. {
  734. break; // Done
  735. }
  736. cur_x += mFontFreetype->getXAdvance(wch);
  737. llwchar next_char = wchars[i + 1];
  738. if (i + 1 < max_chars && next_char && next_char < LAST_CHARACTER)
  739. {
  740. // Kern this puppy.
  741. cur_x += mFontFreetype->getXKerning(wch, next_char);
  742. }
  743. // Round after kerning.
  744. cur_x = (F32)llfloor(cur_x + 0.5f);
  745. }
  746. return cur_x / sScaleX;
  747. }
  748. void LLFontGL::generateASCIIglyphs()
  749. {
  750. for (U32 i = 32; i < 127; ++i)
  751. {
  752. mFontFreetype->getGlyphInfo(i);
  753. }
  754. }
  755. // Returns the max number of complete characters from text (up to max_chars)
  756. // that can be drawn in max_pixels
  757. S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels,
  758. S32 max_chars, bool end_on_word_boundary,
  759. bool use_embedded, F32* drawn_pixels) const
  760. {
  761. if (!wchars || !wchars[0] || max_chars <= 0)
  762. {
  763. return 0;
  764. }
  765. llassert(max_pixels >= 0.f);
  766. llassert(max_chars >= 0);
  767. bool clip = false;
  768. F32 cur_x = 0;
  769. F32 drawn_x = 0;
  770. S32 start_of_last_word = 0;
  771. bool in_word = false;
  772. F32 scaled_max_pixels = (F32)llceil(max_pixels * sScaleX);
  773. S32 i = 0;
  774. if (use_embedded)
  775. {
  776. for (i = 0; i < max_chars; ++i)
  777. {
  778. llwchar wch = wchars[i];
  779. if (!wch)
  780. {
  781. break; // Done
  782. }
  783. const embedded_data_t* ext_data = getEmbeddedCharData(wch);
  784. if (ext_data)
  785. {
  786. if (in_word)
  787. {
  788. in_word = false;
  789. }
  790. else
  791. {
  792. start_of_last_word = i;
  793. }
  794. cur_x += getEmbeddedCharAdvance(ext_data);
  795. if (scaled_max_pixels < cur_x)
  796. {
  797. clip = true;
  798. break;
  799. }
  800. if (i + 1 < max_chars && wchars[i + 1])
  801. {
  802. cur_x += EXT_KERNING * sScaleX;
  803. }
  804. if (scaled_max_pixels < cur_x)
  805. {
  806. clip = true;
  807. break;
  808. }
  809. }
  810. else
  811. {
  812. if (in_word)
  813. {
  814. if (iswspace(wch))
  815. {
  816. in_word = false;
  817. }
  818. }
  819. else
  820. {
  821. start_of_last_word = i;
  822. if (!iswspace(wch))
  823. {
  824. in_word = true;
  825. }
  826. }
  827. cur_x += mFontFreetype->getXAdvance(wch);
  828. if (scaled_max_pixels < cur_x)
  829. {
  830. clip = true;
  831. break;
  832. }
  833. if (i + 1 < max_chars && wchars[i + 1])
  834. {
  835. // Kern this puppy.
  836. cur_x += mFontFreetype->getXKerning(wch, wchars[i + 1]);
  837. }
  838. }
  839. // Round after kerning.
  840. cur_x = (F32)llfloor(cur_x + 0.5f);
  841. drawn_x = cur_x;
  842. }
  843. }
  844. else
  845. {
  846. for (i = 0; i < max_chars; ++i)
  847. {
  848. llwchar wch = wchars[i];
  849. if (!wch)
  850. {
  851. break; // Done
  852. }
  853. if (in_word)
  854. {
  855. if (iswspace(wch))
  856. {
  857. in_word = false;
  858. }
  859. }
  860. else
  861. {
  862. start_of_last_word = i;
  863. if (!iswspace(wch))
  864. {
  865. in_word = true;
  866. }
  867. }
  868. cur_x += mFontFreetype->getXAdvance(wch);
  869. if (scaled_max_pixels < cur_x)
  870. {
  871. clip = true;
  872. break;
  873. }
  874. if (i + 1 < max_chars && wchars[i + 1])
  875. {
  876. // Kern this puppy.
  877. cur_x += mFontFreetype->getXKerning(wch, wchars[i + 1]);
  878. }
  879. }
  880. // Round after kerning.
  881. cur_x = (F32)llfloor(cur_x + 0.5f);
  882. drawn_x = cur_x;
  883. }
  884. if (clip && end_on_word_boundary && start_of_last_word != 0)
  885. {
  886. i = start_of_last_word;
  887. }
  888. if (drawn_pixels)
  889. {
  890. *drawn_pixels = drawn_x;
  891. }
  892. return i;
  893. }
  894. S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels,
  895. S32 text_len, S32 start_pos,
  896. S32 max_chars) const
  897. {
  898. if (!wchars || !wchars[0] || max_chars <= 0)
  899. {
  900. return 0;
  901. }
  902. F32 total_width = 0.0;
  903. S32 drawable_chars = 0;
  904. F32 scaled_max_pixels = max_pixels * sScaleX;
  905. S32 start = llmin(start_pos, text_len - 1);
  906. for (S32 i = start; i >= 0; --i)
  907. {
  908. llwchar wch = wchars[i];
  909. const embedded_data_t* ext_data = getEmbeddedCharData(wch);
  910. F32 char_width = ext_data ? getEmbeddedCharAdvance(ext_data)
  911. : mFontFreetype->getXAdvance(wch);
  912. if (scaled_max_pixels < total_width + char_width)
  913. {
  914. break;
  915. }
  916. total_width += char_width;
  917. ++drawable_chars;
  918. if (max_chars >= 0 && drawable_chars >= max_chars)
  919. {
  920. break;
  921. }
  922. if (i > 0)
  923. {
  924. // Kerning
  925. total_width += ext_data ? EXT_KERNING * sScaleX
  926. : mFontFreetype->getXKerning(wchars[i - 1], wch);
  927. }
  928. // Round after kerning.
  929. total_width = ll_roundp(total_width);
  930. }
  931. return start_pos - drawable_chars;
  932. }
  933. S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset,
  934. F32 target_x, F32 max_pixels, S32 max_chars,
  935. bool round, bool use_embedded) const
  936. {
  937. if (!wchars || !wchars[0] || max_chars == 0)
  938. {
  939. return 0;
  940. }
  941. F32 cur_x = 0;
  942. S32 pos = 0;
  943. target_x *= sScaleX;
  944. // max_chars is S32_MAX by default, so make sure we do not get overflow
  945. const S32 max_index = begin_offset +
  946. llmin(S32_MAX - begin_offset, max_chars);
  947. F32 scaled_max_pixels = max_pixels * sScaleX;
  948. if (use_embedded)
  949. {
  950. for (S32 i = begin_offset; i < max_index; ++i)
  951. {
  952. llwchar wch = wchars[i];
  953. if (!wch)
  954. {
  955. break; // Done
  956. }
  957. const embedded_data_t* ext_data = getEmbeddedCharData(wch);
  958. if (ext_data)
  959. {
  960. F32 ext_advance = getEmbeddedCharAdvance(ext_data);
  961. if (round)
  962. {
  963. // Note: if the mouse is on the left half of the character,
  964. // the pick is to the character's left. If it is on the
  965. // right half, the pick is to the right.
  966. if (target_x < cur_x + ext_advance * 0.5f)
  967. {
  968. break;
  969. }
  970. }
  971. else if (target_x < cur_x + ext_advance)
  972. {
  973. break;
  974. }
  975. if (scaled_max_pixels < cur_x + ext_advance)
  976. {
  977. break;
  978. }
  979. ++pos;
  980. cur_x += ext_advance;
  981. if (i + 1 < max_index && wchars[i + 1])
  982. {
  983. cur_x += EXT_KERNING * sScaleX;
  984. }
  985. // Round after kerning.
  986. cur_x = (F32)llfloor(cur_x + 0.5f);
  987. }
  988. else
  989. {
  990. F32 char_width = mFontFreetype->getXAdvance(wch);
  991. if (round)
  992. {
  993. // Note: if the mouse is on the left half of the character,
  994. // the pick is to the character's left. If it is on the
  995. // right half, the pick is to the right.
  996. if (target_x < cur_x + char_width * 0.5f)
  997. {
  998. break;
  999. }
  1000. }
  1001. else if (target_x < cur_x + char_width)
  1002. {
  1003. break;
  1004. }
  1005. if (scaled_max_pixels < cur_x + char_width)
  1006. {
  1007. break;
  1008. }
  1009. ++pos;
  1010. cur_x += char_width;
  1011. if (i + 1 < max_index && wchars[i + 1])
  1012. {
  1013. llwchar next_char = wchars[i + 1];
  1014. // Kern this puppy.
  1015. cur_x += mFontFreetype->getXKerning(wch, next_char);
  1016. }
  1017. // Round after kerning.
  1018. cur_x = (F32)llfloor(cur_x + 0.5f);
  1019. }
  1020. }
  1021. return pos;
  1022. }
  1023. for (S32 i = begin_offset; i < max_index; ++i)
  1024. {
  1025. llwchar wch = wchars[i];
  1026. if (!wch)
  1027. {
  1028. break; // Done
  1029. }
  1030. F32 char_width = mFontFreetype->getXAdvance(wch);
  1031. if (round)
  1032. {
  1033. // Note: if the mouse is on the left half of the character, the
  1034. // pick is to the character's left. If it is on the right half,
  1035. // the pick is to the right.
  1036. if (target_x < cur_x + char_width * 0.5f)
  1037. {
  1038. break;
  1039. }
  1040. }
  1041. else if (target_x < cur_x + char_width)
  1042. {
  1043. break;
  1044. }
  1045. if (scaled_max_pixels < cur_x + char_width)
  1046. {
  1047. break;
  1048. }
  1049. ++pos;
  1050. cur_x += char_width;
  1051. if (i + 1 < max_index && wchars[i + 1])
  1052. {
  1053. llwchar next_char = wchars[i + 1];
  1054. // Kern this puppy.
  1055. cur_x += mFontFreetype->getXKerning(wch, next_char);
  1056. }
  1057. // Round after kerning.
  1058. cur_x = (F32)llfloor(cur_x + 0.5f);
  1059. }
  1060. return pos;
  1061. }
  1062. //static
  1063. void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale,
  1064. const std::vector<std::string>& xui_paths,
  1065. bool create_gl_textures)
  1066. {
  1067. sVertDPI = (F32)llfloor(screen_dpi * y_scale);
  1068. sHorizDPI = (F32)llfloor(screen_dpi * x_scale);
  1069. sScaleX = x_scale;
  1070. sScaleY = y_scale;
  1071. // Font registry init
  1072. if (sFontRegistry)
  1073. {
  1074. sFontRegistry->reset();
  1075. }
  1076. else
  1077. {
  1078. sFontRegistry = new LLFontRegistry(xui_paths, create_gl_textures);
  1079. sFontRegistry->parseFontInfo("fonts.xml");
  1080. }
  1081. LLFontGL::loadDefaultFonts();
  1082. }
  1083. // Force standard fonts to get generated up front. This is primarily for error
  1084. // detection purposes. Do not do this during initClass because it can be slow
  1085. // and we want to get the viewer window on screen first. JC
  1086. //static
  1087. bool LLFontGL::loadDefaultFonts()
  1088. {
  1089. // Force standard fonts to get generated up front. This is primarily for
  1090. // error detection purposes.
  1091. return getFontSansSerifSmall() != NULL && getFontSansSerif() != NULL &&
  1092. getFontSansSerifLarge() != NULL && getFontSansSerifHuge() != NULL &&
  1093. getFontSansSerifBold() != NULL && getFontMonospace() != NULL &&
  1094. getFontEmoji() != NULL;
  1095. }
  1096. //static
  1097. void LLFontGL::destroyDefaultFonts()
  1098. {
  1099. // Remove the actual fonts.
  1100. delete sFontRegistry;
  1101. sFontRegistry = NULL;
  1102. }
  1103. //static
  1104. void LLFontGL::destroyAllGL()
  1105. {
  1106. if (sFontRegistry)
  1107. {
  1108. sFontRegistry->destroyGL();
  1109. }
  1110. }
  1111. //static
  1112. U8 LLFontGL::getStyleFromString(const std::string& style)
  1113. {
  1114. S32 ret = 0;
  1115. if (style.find("BOLD") != std::string::npos)
  1116. {
  1117. ret |= BOLD;
  1118. }
  1119. if (style.find("ITALIC") != std::string::npos)
  1120. {
  1121. ret |= ITALIC;
  1122. }
  1123. if (style.find("UNDERLINE") != std::string::npos)
  1124. {
  1125. ret |= UNDERLINE;
  1126. }
  1127. if (style.find("SHADOW") != std::string::npos)
  1128. {
  1129. ret |= DROP_SHADOW;
  1130. }
  1131. if (style.find("SOFT_SHADOW") != std::string::npos)
  1132. {
  1133. ret |= DROP_SHADOW_SOFT;
  1134. }
  1135. return ret;
  1136. }
  1137. //static
  1138. std::string LLFontGL::nameFromFont(const LLFontGL* fontp)
  1139. {
  1140. return fontp->getFontDesc().getName();
  1141. }
  1142. //static
  1143. const std::string& LLFontGL::nameFromHAlign(HAlign align)
  1144. {
  1145. static const std::string& hleft("left");
  1146. static const std::string& hright("right");
  1147. static const std::string& hcenter("center");
  1148. switch (align)
  1149. {
  1150. case LEFT:
  1151. return hleft;
  1152. case RIGHT:
  1153. return hright;
  1154. case HCENTER:
  1155. return hcenter;
  1156. default:
  1157. return LLStringUtil::null;
  1158. }
  1159. }
  1160. //static
  1161. LLFontGL::HAlign LLFontGL::hAlignFromName(const std::string& name)
  1162. {
  1163. if (name == "right")
  1164. {
  1165. return LLFontGL::RIGHT;
  1166. }
  1167. if (name == "center")
  1168. {
  1169. return LLFontGL::HCENTER;
  1170. }
  1171. return LLFontGL::LEFT;
  1172. }
  1173. //static
  1174. const std::string& LLFontGL::nameFromVAlign(LLFontGL::VAlign align)
  1175. {
  1176. static const std::string& vtop("top");
  1177. static const std::string& vcenter("center");
  1178. static const std::string& vbaseline("baseline");
  1179. static const std::string& vbottom("bottom");
  1180. switch (align)
  1181. {
  1182. case TOP:
  1183. return vtop;
  1184. case VCENTER:
  1185. return vcenter;
  1186. case BASELINE:
  1187. return vbaseline;
  1188. case BOTTOM:
  1189. return vbottom;
  1190. default:
  1191. return LLStringUtil::null;
  1192. }
  1193. }
  1194. //static
  1195. LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name)
  1196. {
  1197. if (name == "top")
  1198. {
  1199. return LLFontGL::TOP;
  1200. }
  1201. if (name == "center")
  1202. {
  1203. return LLFontGL::VCENTER;
  1204. }
  1205. if (name == "bottom")
  1206. {
  1207. return LLFontGL::BOTTOM;
  1208. }
  1209. return LLFontGL::BASELINE;
  1210. }
  1211. //static
  1212. LLFontGL* LLFontGL::getFontMonospace()
  1213. {
  1214. static const LLFontDescriptor desc("Monospace", "Monospace");
  1215. return getFont(desc, false);
  1216. }
  1217. //static
  1218. LLFontGL* LLFontGL::getFontSansSerifSmall()
  1219. {
  1220. static const LLFontDescriptor desc("SansSerif", "Small");
  1221. return getFont(desc, false);
  1222. }
  1223. //static
  1224. LLFontGL* LLFontGL::getFontSansSerif()
  1225. {
  1226. static const LLFontDescriptor desc("SansSerif", "Medium");
  1227. return getFont(desc, false);
  1228. }
  1229. //static
  1230. LLFontGL* LLFontGL::getFontSansSerifLarge()
  1231. {
  1232. static const LLFontDescriptor desc("SansSerif", "Large");
  1233. return getFont(desc, false);
  1234. }
  1235. //static
  1236. LLFontGL* LLFontGL::getFontSansSerifHuge()
  1237. {
  1238. static const LLFontDescriptor desc("SansSerif", "Huge");
  1239. return getFont(desc, false);
  1240. }
  1241. //static
  1242. LLFontGL* LLFontGL::getFontSansSerifBold()
  1243. {
  1244. static const LLFontDescriptor desc("SansSerif", "Medium", BOLD);
  1245. return getFont(desc, false);
  1246. }
  1247. //static
  1248. LLFontGL* LLFontGL::getFontEmoji()
  1249. {
  1250. static const LLFontDescriptor desc("Emoji", "Large");
  1251. return getFont(desc, false);
  1252. }
  1253. //static
  1254. LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc, bool normalize)
  1255. {
  1256. return sFontRegistry->getFont(desc, normalize);
  1257. }
  1258. //static
  1259. LLFontGL* LLFontGL::getFont(const char* name, const char* size, U8 style)
  1260. {
  1261. if (!name || !*name)
  1262. {
  1263. return NULL;
  1264. }
  1265. const LLFontDescriptor desc(name, size ? size : "Medium", style);
  1266. LLFontGL* fontp = getFont(desc, true);
  1267. if (fontp)
  1268. {
  1269. return fontp;
  1270. }
  1271. return getFont(desc, false);
  1272. }
  1273. //static
  1274. LLFontGL* LLFontGL::getFont(const std::string& name)
  1275. {
  1276. // Check for most common fonts first
  1277. if (name.empty())
  1278. {
  1279. return NULL;
  1280. }
  1281. if (name == "SANSSERIF")
  1282. {
  1283. return getFontSansSerif();
  1284. }
  1285. if (name == "SANSSERIF_SMALL")
  1286. {
  1287. return getFontSansSerifSmall();
  1288. }
  1289. if (name == "SMALL" || name == "MONOSPACE")
  1290. {
  1291. return getFontMonospace();
  1292. }
  1293. if (name == "SANSSERIF_LARGE" || name == "SANSSERIF_BIG")
  1294. {
  1295. return getFontSansSerifLarge();
  1296. }
  1297. if (name == "EMOJI")
  1298. {
  1299. return getFontEmoji();
  1300. }
  1301. llwarns << "Unknown font specification: " << name << llendl;
  1302. return NULL;
  1303. }
  1304. //static
  1305. LLFontGL* LLFontGL::getFont(S32 font_id)
  1306. {
  1307. static std::vector<LLFontGL*> fonts_cache;
  1308. if (fonts_cache.empty())
  1309. {
  1310. // IMPORTANT: must be pushed in LLFONT_ID order !
  1311. fonts_cache.push_back(getFontSansSerif());
  1312. fonts_cache.push_back(getFontSansSerifSmall());
  1313. fonts_cache.push_back(getFontSansSerifLarge());
  1314. fonts_cache.push_back(getFontMonospace());
  1315. fonts_cache.push_back(getFontEmoji());
  1316. }
  1317. if (font_id >= 0 && (size_t)font_id < fonts_cache.size())
  1318. {
  1319. return fonts_cache[font_id];
  1320. }
  1321. llwarns << "Unknown font Id: " << font_id << ". Expect a crash !"
  1322. << llendl;
  1323. llassert(false);
  1324. return NULL;
  1325. }
  1326. ///////////////////////////////////////////////////////////////////////////////
  1327. // These are the new, optimized routines to use for texts without embbeded
  1328. // items.
  1329. ///////////////////////////////////////////////////////////////////////////////
  1330. void LLFontGL::renderQuad(LLVector3* vertex_out, LLVector2* uv_out,
  1331. LLColor4U* colors_out,
  1332. const LLRectf& screen_rect, const LLRectf& uv_rect,
  1333. const LLColor4U& color, F32 slant_amt) const
  1334. {
  1335. S32 index = 0;
  1336. vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 0.f);
  1337. uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
  1338. colors_out[index++] = color;
  1339. vertex_out[index] = LLVector3(screen_rect.mLeft + slant_amt,
  1340. screen_rect.mBottom, 0.f);
  1341. uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
  1342. colors_out[index++] = color;
  1343. vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mTop, 0.f);
  1344. uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
  1345. colors_out[index++] = color;
  1346. vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mTop, 0.f);
  1347. uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
  1348. colors_out[index++] = color;
  1349. vertex_out[index] = LLVector3(screen_rect.mLeft + slant_amt,
  1350. screen_rect.mBottom, 0.f);
  1351. uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
  1352. colors_out[index++] = color;
  1353. vertex_out[index] = LLVector3(screen_rect.mRight + slant_amt,
  1354. screen_rect.mBottom, 0.f);
  1355. uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
  1356. colors_out[index] = color;
  1357. }
  1358. void LLFontGL::drawGlyph(S32& glyph_count, LLVector3* vertex_out,
  1359. LLVector2* uv_out, LLColor4U* colors_out,
  1360. const LLRectf& screen_rect, const LLRectf& uv_rect,
  1361. const LLColor4U& color, U8 style,
  1362. F32 drop_shadow_strength) const
  1363. {
  1364. F32 slant_offset = 0.f;
  1365. if (style & ITALIC)
  1366. {
  1367. slant_offset = -mFontFreetype->getAscenderHeight() * 0.2f;
  1368. }
  1369. // *FIXME: bold and drop shadow are mutually exclusive only for
  1370. // convenience. Allow both when we need them.
  1371. if (style & BOLD)
  1372. {
  1373. for (S32 pass = 0; pass < 2; ++pass)
  1374. {
  1375. LLRectf screen_rect_offset = screen_rect;
  1376. const U32 idx = glyph_count * 6;
  1377. screen_rect_offset.translate((F32)(pass * BOLD_OFFSET), 0.f);
  1378. renderQuad(&vertex_out[idx], &uv_out[idx], &colors_out[idx],
  1379. screen_rect_offset, uv_rect, color, slant_offset);
  1380. ++glyph_count;
  1381. }
  1382. }
  1383. else if (style & DROP_SHADOW_SOFT)
  1384. {
  1385. LLColor4U shadow_color = sShadowColorU;
  1386. shadow_color.mV[VALPHA] = U8(color.mV[VALPHA] * drop_shadow_strength *
  1387. DROP_SHADOW_SOFT_STRENGTH);
  1388. for (S32 pass = 0; pass < 5; ++pass)
  1389. {
  1390. LLRectf screen_rect_offset = screen_rect;
  1391. switch (pass)
  1392. {
  1393. case 0:
  1394. screen_rect_offset.translate(-1.f, -1.f);
  1395. break;
  1396. case 1:
  1397. screen_rect_offset.translate(1.f, -1.f);
  1398. break;
  1399. case 2:
  1400. screen_rect_offset.translate(1.f, 1.f);
  1401. break;
  1402. case 3:
  1403. screen_rect_offset.translate(-1.f, 1.f);
  1404. break;
  1405. case 4:
  1406. screen_rect_offset.translate(0, -2.f);
  1407. }
  1408. const U32 idx = glyph_count * 6;
  1409. renderQuad(&vertex_out[idx], &uv_out[idx], &colors_out[idx],
  1410. screen_rect_offset, uv_rect, shadow_color,
  1411. slant_offset);
  1412. ++glyph_count;
  1413. }
  1414. const U32 idx = glyph_count * 6;
  1415. renderQuad(&vertex_out[idx], &uv_out[idx], &colors_out[idx],
  1416. screen_rect, uv_rect, color, slant_offset);
  1417. ++glyph_count;
  1418. }
  1419. else if (style & DROP_SHADOW)
  1420. {
  1421. LLColor4U shadow_color = sShadowColorU;
  1422. shadow_color.mV[VALPHA] = U8(color.mV[VALPHA] * drop_shadow_strength);
  1423. LLRectf screen_rect_shadow = screen_rect;
  1424. screen_rect_shadow.translate(1.f, -1.f);
  1425. U32 idx = glyph_count * 6;
  1426. renderQuad(&vertex_out[idx], &uv_out[idx], &colors_out[idx],
  1427. screen_rect_shadow, uv_rect, shadow_color, slant_offset);
  1428. idx = ++glyph_count * 6;
  1429. renderQuad(&vertex_out[idx], &uv_out[idx], &colors_out[idx],
  1430. screen_rect, uv_rect, color, slant_offset);
  1431. ++glyph_count;
  1432. }
  1433. else // Normal rendering
  1434. {
  1435. const U32 idx = glyph_count * 6;
  1436. renderQuad(&vertex_out[idx], &uv_out[idx], &colors_out[idx],
  1437. screen_rect, uv_rect, color, slant_offset);
  1438. ++glyph_count;
  1439. }
  1440. }
  1441. ///////////////////////////////////////////////////////////////////////////////
  1442. // These are the old, slower routines to use for texts with embbeded items.
  1443. ///////////////////////////////////////////////////////////////////////////////
  1444. void LLFontGL::renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect,
  1445. F32 slant_amt) const
  1446. {
  1447. gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
  1448. gGL.vertex2f(screen_rect.mLeft, screen_rect.mTop);
  1449. gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
  1450. gGL.vertex2f(screen_rect.mLeft + slant_amt, screen_rect.mBottom);
  1451. gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
  1452. gGL.vertex2f(screen_rect.mRight, screen_rect.mTop);
  1453. gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
  1454. gGL.vertex2f(screen_rect.mRight, screen_rect.mTop);
  1455. gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
  1456. gGL.vertex2f(screen_rect.mLeft + slant_amt, screen_rect.mBottom);
  1457. gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
  1458. gGL.vertex2f(screen_rect.mRight + slant_amt, screen_rect.mBottom);
  1459. }
  1460. void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect,
  1461. const LLColor4& color, U8 style,
  1462. F32 drop_shadow_strength) const
  1463. {
  1464. F32 slant_offset = 0.f;
  1465. if (style & ITALIC)
  1466. {
  1467. slant_offset = -mFontFreetype->getAscenderHeight() * 0.2f;
  1468. }
  1469. gGL.begin(LLRender::TRIANGLES);
  1470. // *FIXME: bold and drop shadow are mutually exclusive only for
  1471. // convenience. Allow both when we need them.
  1472. if (style & BOLD)
  1473. {
  1474. gGL.color4fv(color.mV);
  1475. for (S32 pass = 0; pass < 2; ++pass)
  1476. {
  1477. LLRectf screen_rect_offset = screen_rect;
  1478. screen_rect_offset.translate((F32)(pass * BOLD_OFFSET), 0.f);
  1479. renderQuad(screen_rect_offset, uv_rect, slant_offset);
  1480. }
  1481. }
  1482. else if (style & DROP_SHADOW_SOFT)
  1483. {
  1484. LLColor4 shadow_color = sShadowColor;
  1485. shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength *
  1486. DROP_SHADOW_SOFT_STRENGTH;
  1487. gGL.color4fv(shadow_color.mV);
  1488. for (S32 pass = 0; pass < 5; ++pass)
  1489. {
  1490. LLRectf screen_rect_offset = screen_rect;
  1491. switch (pass)
  1492. {
  1493. case 0:
  1494. screen_rect_offset.translate(-1.f, -1.f);
  1495. break;
  1496. case 1:
  1497. screen_rect_offset.translate(1.f, -1.f);
  1498. break;
  1499. case 2:
  1500. screen_rect_offset.translate(1.f, 1.f);
  1501. break;
  1502. case 3:
  1503. screen_rect_offset.translate(-1.f, 1.f);
  1504. break;
  1505. case 4:
  1506. screen_rect_offset.translate(0, -2.f);
  1507. }
  1508. renderQuad(screen_rect_offset, uv_rect, slant_offset);
  1509. }
  1510. gGL.color4fv(color.mV);
  1511. renderQuad(screen_rect, uv_rect, slant_offset);
  1512. }
  1513. else if (style & DROP_SHADOW)
  1514. {
  1515. LLColor4 shadow_color = sShadowColor;
  1516. shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength;
  1517. gGL.color4fv(shadow_color.mV);
  1518. LLRectf screen_rect_shadow = screen_rect;
  1519. screen_rect_shadow.translate(1.f, -1.f);
  1520. renderQuad(screen_rect_shadow, uv_rect, slant_offset);
  1521. gGL.color4fv(color.mV);
  1522. renderQuad(screen_rect, uv_rect, slant_offset);
  1523. }
  1524. else // Normal rendering
  1525. {
  1526. gGL.color4fv(color.mV);
  1527. renderQuad(screen_rect, uv_rect, slant_offset);
  1528. }
  1529. gGL.end();
  1530. }
  1531. const LLFontGL::embedded_data_t* LLFontGL::getEmbeddedCharData(llwchar wch) const
  1532. {
  1533. // Handle crappy embedded hack
  1534. embedded_map_t::const_iterator iter = mEmbeddedChars.find(wch);
  1535. return iter != mEmbeddedChars.end() ? &iter->second : NULL;
  1536. }
  1537. F32 LLFontGL::getEmbeddedCharAdvance(const embedded_data_t* ext_data) const
  1538. {
  1539. const LLWString& label = ext_data->mLabel;
  1540. LLImageGL* ext_image = ext_data->mImage;
  1541. F32 ext_width = (F32)ext_image->getWidth();
  1542. if (!label.empty())
  1543. {
  1544. ext_width += (EXT_X_BEARING +
  1545. getFontSansSerif()->getWidthF32(label.c_str())) *
  1546. sScaleX;
  1547. }
  1548. return EXT_X_BEARING * sScaleX + ext_width;
  1549. }
  1550. void LLFontGL::addEmbeddedChar(llwchar wc, LLGLTexture* image,
  1551. const std::string& label) const
  1552. {
  1553. mEmbeddedChars.emplace(std::piecewise_construct,
  1554. std::forward_as_tuple(wc),
  1555. std::forward_as_tuple(image->getGLImage(),
  1556. utf8str_to_wstring(label)));
  1557. }
  1558. void LLFontGL::addEmbeddedChar(llwchar wc, LLGLTexture* image,
  1559. const LLWString& wlabel) const
  1560. {
  1561. mEmbeddedChars.emplace(std::piecewise_construct,
  1562. std::forward_as_tuple(wc),
  1563. std::forward_as_tuple(image->getGLImage(), wlabel));
  1564. }
  1565. void LLFontGL::removeEmbeddedChar(llwchar wc) const
  1566. {
  1567. mEmbeddedChars.erase(wc);
  1568. }