aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llrender/llfontgl.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2009-04-30 13:04:20 -0500
committerJacek Antonelli2009-04-30 13:07:16 -0500
commitca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e (patch)
tree8348301d0ac44a524f1819b777686bf086907d76 /linden/indra/llrender/llfontgl.cpp
parentSecond Life viewer sources 1.22.11 (diff)
downloadmeta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.zip
meta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.tar.gz
meta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.tar.bz2
meta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.tar.xz
Second Life viewer sources 1.23.0-RC
Diffstat (limited to '')
-rw-r--r--linden/indra/llrender/llfontgl.cpp673
1 files changed, 184 insertions, 489 deletions
diff --git a/linden/indra/llrender/llfontgl.cpp b/linden/indra/llrender/llfontgl.cpp
index 526f1a9..beecb6b 100644
--- a/linden/indra/llrender/llfontgl.cpp
+++ b/linden/indra/llrender/llfontgl.cpp
@@ -17,7 +17,8 @@
17 * There are special exceptions to the terms and conditions of the GPL as 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 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 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception 20 * online at
21 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 22 *
22 * By copying, modifying or distributing this software, you acknowledge 23 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 24 * that you have read and understood your obligations described above,
@@ -35,6 +36,8 @@
35 36
36#include "llfont.h" 37#include "llfont.h"
37#include "llfontgl.h" 38#include "llfontgl.h"
39#include "llfontbitmapcache.h"
40#include "llfontregistry.h"
38#include "llgl.h" 41#include "llgl.h"
39#include "llrender.h" 42#include "llrender.h"
40#include "v4color.h" 43#include "v4color.h"
@@ -50,32 +53,19 @@ F32 LLFontGL::sScaleY = 1.f;
50BOOL LLFontGL::sDisplayFont = TRUE ; 53BOOL LLFontGL::sDisplayFont = TRUE ;
51std::string LLFontGL::sAppDir; 54std::string LLFontGL::sAppDir;
52 55
53LLFontGL* LLFontGL::sMonospace = NULL;
54LLFontGL* LLFontGL::sSansSerifSmall = NULL;
55LLFontGL* LLFontGL::sSansSerif = NULL;
56LLFontGL* LLFontGL::sSansSerifBig = NULL;
57LLFontGL* LLFontGL::sSansSerifHuge = NULL;
58LLFontGL* LLFontGL::sSansSerifBold = NULL;
59LLFontList* LLFontGL::sMonospaceFallback = NULL;
60LLFontList* LLFontGL::sSSFallback = NULL;
61LLFontList* LLFontGL::sSSSmallFallback = NULL;
62LLFontList* LLFontGL::sSSBigFallback = NULL;
63LLFontList* LLFontGL::sSSHugeFallback = NULL;
64LLFontList* LLFontGL::sSSBoldFallback = NULL;
65LLColor4 LLFontGL::sShadowColor(0.f, 0.f, 0.f, 1.f); 56LLColor4 LLFontGL::sShadowColor(0.f, 0.f, 0.f, 1.f);
57LLFontRegistry* LLFontGL::sFontRegistry = NULL;
66 58
67LLCoordFont LLFontGL::sCurOrigin; 59LLCoordFont LLFontGL::sCurOrigin;
68std::vector<LLCoordFont> LLFontGL::sOriginStack; 60std::vector<LLCoordFont> LLFontGL::sOriginStack;
69 61
70LLFontGL*& gExtCharFont = LLFontGL::sSansSerif;
71
72const F32 EXT_X_BEARING = 1.f; 62const F32 EXT_X_BEARING = 1.f;
73const F32 EXT_Y_BEARING = 0.f; 63const F32 EXT_Y_BEARING = 0.f;
74const F32 EXT_KERNING = 1.f; 64const F32 EXT_KERNING = 1.f;
75const F32 PIXEL_BORDER_THRESHOLD = 0.0001f; 65const F32 PIXEL_BORDER_THRESHOLD = 0.0001f;
76const F32 PIXEL_CORRECTION_DISTANCE = 0.01f; 66const F32 PIXEL_CORRECTION_DISTANCE = 0.01f;
77 67
78const F32 PAD_AMT = 0.5f; 68const F32 PAD_UVY = 0.5f; // half of vertical padding between glyphs in the glyph texture
79const F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f; 69const F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f;
80 70
81F32 llfont_round_x(F32 x) 71F32 llfont_round_x(F32 x)
@@ -126,7 +116,6 @@ U8 LLFontGL::getStyleFromString(const std::string &style)
126LLFontGL::LLFontGL() 116LLFontGL::LLFontGL()
127 : LLFont() 117 : LLFont()
128{ 118{
129 init();
130 clearEmbeddedChars(); 119 clearEmbeddedChars();
131} 120}
132 121
@@ -137,32 +126,30 @@ LLFontGL::LLFontGL(const LLFontGL &source)
137 126
138LLFontGL::~LLFontGL() 127LLFontGL::~LLFontGL()
139{ 128{
140 mImageGLp = NULL;
141 mRawImageGLp = NULL;
142 clearEmbeddedChars(); 129 clearEmbeddedChars();
143} 130}
144 131
145void LLFontGL::init() 132void LLFontGL::reset()
146{ 133{
147 if (mImageGLp.isNull()) 134 if (!mIsFallback)
148 {
149 mImageGLp = new LLImageGL(FALSE);
150 //RN: use nearest mipmap filtering to obviate the need to do pixel-accurate positioning
151 gGL.getTexUnit(0)->bind(mImageGLp);
152 // we allow bilinear filtering to get sub-pixel positioning for drop shadows
153 //mImageGLp->setMipFilterNearest(TRUE, TRUE);
154 }
155 if (mRawImageGLp.isNull())
156 { 135 {
157 mRawImageGLp = new LLImageRaw; // Note LLFontGL owns the image, not LLFont. 136 // This is the head of the list - need to rebuild ourself and all fallbacks.
137 loadFace(mName,mPointSize,sVertDPI,sHorizDPI,mFontBitmapCachep->getNumComponents(),mIsFallback);
138 if (mFallbackFontp==NULL)
139 {
140 llwarns << "LLFontGL::reset(), no fallback fonts present" << llendl;
141 }
142 else
143 {
144 for (LLFontList::iterator it = mFallbackFontp->begin();
145 it != mFallbackFontp->end();
146 ++it)
147 {
148 (*it)->reset();
149 }
150 }
158 } 151 }
159 setRawImage( mRawImageGLp ); 152 resetBitmapCache();
160}
161
162void LLFontGL::reset()
163{
164 init();
165 resetBitmap();
166} 153}
167 154
168// static 155// static
@@ -219,243 +206,48 @@ std::string LLFontGL::getFontPathLocal()
219 return local_path; 206 return local_path;
220} 207}
221 208
222//static 209bool findOrCreateFont(LLFontGL*& fontp, const LLFontDescriptor& desc)
223bool LLFontGL::loadFaceFallback(LLFontList *fontlistp, const std::string& fontname, const F32 point_size)
224{ 210{
225 std::string local_path = getFontPathLocal(); 211 // Don't delete existing fonts, if any, here, because they've
226 std::string sys_path = getFontPathSystem(); 212 // already been deleted by LLFontRegistry::clear()
227 213 fontp = LLFontGL::getFont(desc);
228 // The fontname string may contain multiple font file names separated by semicolons. 214 return (fontp != NULL);
229 // Break it apart and try loading each one, in order.
230 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
231 boost::char_separator<char> sep(";");
232 tokenizer tokens(fontname, sep);
233 tokenizer::iterator token_iter;
234
235 for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
236 {
237 LLFont *fontp = new LLFont();
238 std::string font_path = local_path + *token_iter;
239 if (!fontp->loadFace(font_path, point_size, sVertDPI, sHorizDPI, 2, TRUE))
240 {
241 font_path = sys_path + *token_iter;
242 if (!fontp->loadFace(font_path, point_size, sVertDPI, sHorizDPI, 2, TRUE))
243 {
244 LL_INFOS_ONCE("ViewerImages") << "Couldn't load font " << *token_iter << LL_ENDL;
245 delete fontp;
246 fontp = NULL;
247 }
248 }
249
250 if(fontp)
251 {
252 fontlistp->addAtEnd(fontp);
253 }
254 }
255
256 // We want to return true if at least one fallback font loaded correctly.
257 return (fontlistp->size() > 0);
258} 215}
259 216
260//static
261bool LLFontGL::loadFace(LLFontGL *fontp, const std::string& fontname, const F32 point_size, LLFontList *fallback_fontp)
262{
263 std::string local_path = getFontPathLocal();
264 std::string font_path = local_path + fontname;
265 if (!fontp->loadFace(font_path, point_size, sVertDPI, sHorizDPI, 2, FALSE))
266 {
267 std::string sys_path = getFontPathSystem();
268 font_path = sys_path + fontname;
269 if (!fontp->loadFace(font_path, point_size, sVertDPI, sHorizDPI, 2, FALSE))
270 {
271 LL_WARNS("ViewerImages") << "Couldn't load font " << fontname << LL_ENDL;
272 return false;
273 }
274 }
275
276 fontp->setFallbackFont(fallback_fontp);
277 return true;
278}
279
280
281// static 217// static
282BOOL LLFontGL::initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale, 218BOOL LLFontGL::initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale,
283 const std::string& monospace_file, F32 monospace_size, 219 const std::string& app_dir,
284 const std::string& sansserif_file, 220 const std::vector<std::string>& xui_paths)
285 const std::string& sanserif_fallback_file, F32 ss_fallback_scale,
286 F32 small_size, F32 medium_size, F32 big_size, F32 huge_size,
287 const std::string& sansserif_bold_file, F32 bold_size,
288 const std::string& app_dir)
289{ 221{
290 BOOL failed = FALSE; 222 bool succ = true;
291 sVertDPI = (F32)llfloor(screen_dpi * y_scale); 223 sVertDPI = (F32)llfloor(screen_dpi * y_scale);
292 sHorizDPI = (F32)llfloor(screen_dpi * x_scale); 224 sHorizDPI = (F32)llfloor(screen_dpi * x_scale);
293 sScaleX = x_scale; 225 sScaleX = x_scale;
294 sScaleY = y_scale; 226 sScaleY = y_scale;
295 sAppDir = app_dir; 227 sAppDir = app_dir;
296 228
297 // 229 // Font registry init
298 // Monospace font 230 if (!sFontRegistry)
299 //
300
301 if (!sMonospace)
302 { 231 {
303 sMonospace = new LLFontGL(); 232 sFontRegistry = new LLFontRegistry(xui_paths);
233 sFontRegistry->parseFontInfo("fonts.xml");
304 } 234 }
305 else 235 else
306 { 236 {
307 sMonospace->reset(); 237 sFontRegistry->reset();
308 }
309
310 if (sMonospaceFallback)
311 {
312 delete sMonospaceFallback;
313 }
314 sMonospaceFallback = new LLFontList();
315 if (!loadFaceFallback(
316 sMonospaceFallback,
317 sanserif_fallback_file,
318 monospace_size * ss_fallback_scale))
319 {
320 delete sMonospaceFallback;
321 sMonospaceFallback = NULL;
322 } 238 }
323 239
324 failed |= !loadFace(sMonospace, monospace_file, monospace_size, sMonospaceFallback); 240 // Force standard fonts to get generated up front.
325 241 // This is primarily for error detection purposes.
326 // 242 succ &= (NULL != getFontSansSerifSmall());
327 // Sans-serif fonts 243 succ &= (NULL != getFontSansSerif());
328 // 244 succ &= (NULL != getFontSansSerifBig());
329 if(!sSansSerifHuge) 245 succ &= (NULL != getFontSansSerifHuge());
330 { 246 succ &= (NULL != getFontSansSerifBold());
331 sSansSerifHuge = new LLFontGL(); 247 succ &= (NULL != getFontMonospace());
332 } 248 succ &= (NULL != getFontExtChar());
333 else 249
334 { 250 return succ;
335 sSansSerifHuge->reset();
336 }
337
338 if (sSSHugeFallback)
339 {
340 delete sSSHugeFallback;
341 }
342 sSSHugeFallback = new LLFontList();
343 if (!loadFaceFallback(
344 sSSHugeFallback,
345 sanserif_fallback_file,
346 huge_size*ss_fallback_scale))
347 {
348 delete sSSHugeFallback;
349 sSSHugeFallback = NULL;
350 }
351
352 failed |= !loadFace(sSansSerifHuge, sansserif_file, huge_size, sSSHugeFallback);
353
354
355 if(!sSansSerifBig)
356 {
357 sSansSerifBig = new LLFontGL();
358 }
359 else
360 {
361 sSansSerifBig->reset();
362 }
363
364 if (sSSBigFallback)
365 {
366 delete sSSBigFallback;
367 }
368 sSSBigFallback = new LLFontList();
369 if (!loadFaceFallback(
370 sSSBigFallback,
371 sanserif_fallback_file,
372 big_size*ss_fallback_scale))
373 {
374 delete sSSBigFallback;
375 sSSBigFallback = NULL;
376 }
377
378 failed |= !loadFace(sSansSerifBig, sansserif_file, big_size, sSSBigFallback);
379
380
381 if(!sSansSerif)
382 {
383 sSansSerif = new LLFontGL();
384 }
385 else
386 {
387 sSansSerif->reset();
388 }
389
390 if (sSSFallback)
391 {
392 delete sSSFallback;
393 }
394 sSSFallback = new LLFontList();
395 if (!loadFaceFallback(
396 sSSFallback,
397 sanserif_fallback_file,
398 medium_size*ss_fallback_scale))
399 {
400 delete sSSFallback;
401 sSSFallback = NULL;
402 }
403 failed |= !loadFace(sSansSerif, sansserif_file, medium_size, sSSFallback);
404
405
406 if(!sSansSerifSmall)
407 {
408 sSansSerifSmall = new LLFontGL();
409 }
410 else
411 {
412 sSansSerifSmall->reset();
413 }
414
415 if(sSSSmallFallback)
416 {
417 delete sSSSmallFallback;
418 }
419 sSSSmallFallback = new LLFontList();
420 if (!loadFaceFallback(
421 sSSSmallFallback,
422 sanserif_fallback_file,
423 small_size*ss_fallback_scale))
424 {
425 delete sSSSmallFallback;
426 sSSSmallFallback = NULL;
427 }
428 failed |= !loadFace(sSansSerifSmall, sansserif_file, small_size, sSSSmallFallback);
429
430
431 //
432 // Sans-serif bold
433 //
434 if(!sSansSerifBold)
435 {
436 sSansSerifBold = new LLFontGL();
437 }
438 else
439 {
440 sSansSerifBold->reset();
441 }
442
443 if (sSSBoldFallback)
444 {
445 delete sSSBoldFallback;
446 }
447 sSSBoldFallback = new LLFontList();
448 if (!loadFaceFallback(
449 sSSBoldFallback,
450 sanserif_fallback_file,
451 medium_size*ss_fallback_scale))
452 {
453 delete sSSBoldFallback;
454 sSSBoldFallback = NULL;
455 }
456 failed |= !loadFace(sSansSerifBold, sansserif_bold_file, medium_size, sSSBoldFallback);
457
458 return !failed;
459} 251}
460 252
461 253
@@ -463,57 +255,23 @@ BOOL LLFontGL::initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale,
463// static 255// static
464void LLFontGL::destroyDefaultFonts() 256void LLFontGL::destroyDefaultFonts()
465{ 257{
466 delete sMonospace; 258 // Remove the actual fonts.
467 sMonospace = NULL; 259 delete sFontRegistry;
468 260 sFontRegistry = NULL;
469 delete sSansSerifHuge;
470 sSansSerifHuge = NULL;
471
472 delete sSansSerifBig;
473 sSansSerifBig = NULL;
474
475 delete sSansSerif;
476 sSansSerif = NULL;
477
478 delete sSansSerifSmall;
479 sSansSerifSmall = NULL;
480
481 delete sSansSerifBold;
482 sSansSerifBold = NULL;
483
484 delete sMonospaceFallback;
485 sMonospaceFallback = NULL;
486
487 delete sSSHugeFallback;
488 sSSHugeFallback = NULL;
489
490 delete sSSBigFallback;
491 sSSBigFallback = NULL;
492
493 delete sSSFallback;
494 sSSFallback = NULL;
495
496 delete sSSSmallFallback;
497 sSSSmallFallback = NULL;
498
499 delete sSSBoldFallback;
500 sSSBoldFallback = NULL;
501} 261}
502 262
503//static 263//static
504void LLFontGL::destroyGL() 264void LLFontGL::destroyAllGL()
505{ 265{
506 if (!sMonospace) 266 if (sFontRegistry)
507 { 267 {
508 // Already all destroyed. 268 sFontRegistry->destroyGL();
509 return;
510 } 269 }
511 sMonospace->mImageGLp->destroyGLTexture(); 270}
512 sSansSerifHuge->mImageGLp->destroyGLTexture(); 271
513 sSansSerifSmall->mImageGLp->destroyGLTexture(); 272void LLFontGL::destroyGL()
514 sSansSerif->mImageGLp->destroyGLTexture(); 273{
515 sSansSerifBig->mImageGLp->destroyGLTexture(); 274 mFontBitmapCachep->destroyGL();
516 sSansSerifBold->mImageGLp->destroyGLTexture();
517} 275}
518 276
519 277
@@ -532,13 +290,58 @@ BOOL LLFontGL::loadFace(const std::string& filename,
532 { 290 {
533 return FALSE; 291 return FALSE;
534 } 292 }
535 mImageGLp->createGLTexture(0, mRawImageGLp);
536 gGL.getTexUnit(0)->bind(mImageGLp);
537 mImageGLp->setMipFilterNearest(TRUE, TRUE);
538 return TRUE; 293 return TRUE;
539} 294}
540 295
541BOOL LLFontGL::addChar(const llwchar wch) 296//static
297LLFontGL* LLFontGL::getFontMonospace()
298{
299 return getFont(LLFontDescriptor("Monospace","Monospace",0));
300}
301
302//static
303LLFontGL* LLFontGL::getFontSansSerifSmall()
304{
305 return getFont(LLFontDescriptor("SansSerif","Small",0));
306}
307
308//static
309LLFontGL* LLFontGL::getFontSansSerif()
310{
311 return getFont(LLFontDescriptor("SansSerif","Medium",0));
312}
313
314//static
315LLFontGL* LLFontGL::getFontSansSerifBig()
316{
317 return getFont(LLFontDescriptor("SansSerif","Large",0));
318}
319
320//static
321LLFontGL* LLFontGL::getFontSansSerifHuge()
322{
323 return getFont(LLFontDescriptor("SansSerif","Huge",0));
324}
325
326//static
327LLFontGL* LLFontGL::getFontSansSerifBold()
328{
329 return getFont(LLFontDescriptor("SansSerif","Medium",BOLD));
330}
331
332//static
333LLFontGL* LLFontGL::getFontExtChar()
334{
335 return getFontSansSerif();
336}
337
338//static
339LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc)
340{
341 return sFontRegistry->getFont(desc);
342}
343
344BOOL LLFontGL::addChar(const llwchar wch) const
542{ 345{
543 if (!LLFont::addChar(wch)) 346 if (!LLFont::addChar(wch))
544 { 347 {
@@ -546,10 +349,12 @@ BOOL LLFontGL::addChar(const llwchar wch)
546 } 349 }
547 350
548 stop_glerror(); 351 stop_glerror();
549 mImageGLp->setSubImage(mRawImageGLp, 0, 0, mImageGLp->getWidth(), mImageGLp->getHeight()); 352
550 gGL.getTexUnit(0)->bind(mImageGLp); 353 LLFontGlyphInfo *glyph_info = getGlyphInfo(wch);
551 mImageGLp->setMipFilterNearest(TRUE, TRUE); 354 U32 bitmap_num = glyph_info->mBitmapNum;
552 stop_glerror(); 355 LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_num);
356 LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num);
357 image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight());
553 return TRUE; 358 return TRUE;
554} 359}
555 360
@@ -564,7 +369,7 @@ S32 LLFontGL::renderUTF8(const std::string &text, const S32 offset,
564 BOOL use_ellipses) const 369 BOOL use_ellipses) const
565{ 370{
566 LLWString wstr = utf8str_to_wstring(text); 371 LLWString wstr = utf8str_to_wstring(text);
567 return render(wstr, offset, x, y, color, halign, valign, style, max_chars, max_pixels, right_x, use_ellipses); 372 return render(wstr, offset, x, y, color, halign, valign, style, max_chars, max_pixels, right_x, FALSE, use_ellipses);
568} 373}
569 374
570S32 LLFontGL::render(const LLWString &wstr, 375S32 LLFontGL::render(const LLWString &wstr,
@@ -583,30 +388,17 @@ S32 LLFontGL::render(const LLWString &wstr,
583 return wstr.length() ; 388 return wstr.length() ;
584 } 389 }
585 390
586 gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
587
588 if (wstr.empty()) 391 if (wstr.empty())
589 { 392 {
590 return 0; 393 return 0;
591 } 394 }
592 395
396 gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
397
593 S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); 398 S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX);
594 399
595 // HACK for better bolding 400 // Strip off any style bits that are already accounted for by the font.
596 if (style & BOLD) 401 style = style & (~getFontDesc().getStyle());
597 {
598 if (this == LLFontGL::sSansSerif)
599 {
600 return LLFontGL::sSansSerifBold->render(
601 wstr, begin_offset,
602 x, y,
603 color,
604 halign, valign,
605 (style & ~BOLD),
606 max_chars, max_pixels,
607 right_x, use_embedded);
608 }
609 }
610 402
611 F32 drop_shadow_strength = 0.f; 403 F32 drop_shadow_strength = 0.f;
612 if (style & (DROP_SHADOW | DROP_SHADOW_SOFT)) 404 if (style & (DROP_SHADOW | DROP_SHADOW_SOFT))
@@ -623,25 +415,12 @@ S32 LLFontGL::render(const LLWString &wstr,
623 gGL.pushMatrix(); 415 gGL.pushMatrix();
624 glLoadIdentity(); 416 glLoadIdentity();
625 gGL.translatef(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ); 417 gGL.translatef(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ);
626 //glScalef(sScaleX, sScaleY, 1.0f); 418
627 419 // this code snaps the text origin to a pixel grid to start with
628 // avoid half pixels 420 F32 pixel_offset_x = llround((F32)sCurOrigin.mX) - (sCurOrigin.mX);
629 // RN: if we're going to this trouble, might as well snap to nearest pixel all the time 421 F32 pixel_offset_y = llround((F32)sCurOrigin.mY) - (sCurOrigin.mY);
630 // but the plan is to get rid of this so that fonts "just work" 422 gGL.translatef(-pixel_offset_x, -pixel_offset_y, 0.f);
631 //F32 half_pixel_distance = llabs(fmodf(sCurOrigin.mX * sScaleX, 1.f) - 0.5f); 423
632 //if (half_pixel_distance < PIXEL_BORDER_THRESHOLD)
633 //{
634 gGL.translatef(PIXEL_CORRECTION_DISTANCE*sScaleX, 0.f, 0.f);
635 //}
636
637 // this code would just snap to pixel grid, although it seems to introduce more jitter
638 //F32 pixel_offset_x = llround(sCurOrigin.mX * sScaleX) - (sCurOrigin.mX * sScaleX);
639 //F32 pixel_offset_y = llround(sCurOrigin.mY * sScaleY) - (sCurOrigin.mY * sScaleY);
640 //gGL.translatef(-pixel_offset_x, -pixel_offset_y, 0.f);
641
642 // scale back to native pixel size
643 //glScalef(1.f / sScaleX, 1.f / sScaleY, 1.f);
644 //glScaled(1.0 / (F64) sScaleX, 1.0 / (F64) sScaleY, 1.0f);
645 LLFastTimer t(LLFastTimer::FTM_RENDER_FONTS); 424 LLFastTimer t(LLFastTimer::FTM_RENDER_FONTS);
646 425
647 gGL.color4fv( color.mV ); 426 gGL.color4fv( color.mV );
@@ -661,10 +440,6 @@ S32 LLFontGL::render(const LLWString &wstr,
661 440
662 F32 cur_x, cur_y, cur_render_x, cur_render_y; 441 F32 cur_x, cur_y, cur_render_x, cur_render_y;
663 442
664 // Bind the font texture
665
666 gGL.getTexUnit(0)->bind(mImageGLp);
667
668 // Not guaranteed to be set correctly 443 // Not guaranteed to be set correctly
669 gGL.setSceneBlendType(LLRender::BT_ALPHA); 444 gGL.setSceneBlendType(LLRender::BT_ALPHA);
670 445
@@ -704,17 +479,13 @@ S32 LLFontGL::render(const LLWString &wstr,
704 break; 479 break;
705 } 480 }
706 481
707 // Round properly.
708 //cur_render_y = (F32)llfloor(cur_y/sScaleY + 0.5f)*sScaleY;
709 //cur_render_x = (F32)llfloor(cur_x/sScaleX + 0.5f)*sScaleX;
710
711 cur_render_y = cur_y; 482 cur_render_y = cur_y;
712 cur_render_x = cur_x; 483 cur_render_x = cur_x;
713 484
714 F32 start_x = cur_x; 485 F32 start_x = cur_x;
715 486
716 F32 inv_width = 1.f / mImageGLp->getWidth(); 487 F32 inv_width = 1.f / mFontBitmapCachep->getBitmapWidth();
717 F32 inv_height = 1.f / mImageGLp->getHeight(); 488 F32 inv_height = 1.f / mFontBitmapCachep->getBitmapHeight();
718 489
719 const S32 LAST_CHARACTER = LLFont::LAST_CHAR_FULL; 490 const S32 LAST_CHARACTER = LLFont::LAST_CHAR_FULL;
720 491
@@ -733,6 +504,9 @@ S32 LLFontGL::render(const LLWString &wstr,
733 } 504 }
734 505
735 506
507 // Remember last-used texture to avoid unnecesssary bind calls.
508 LLImageGL *last_bound_texture = NULL;
509
736 for (i = begin_offset; i < begin_offset + length; i++) 510 for (i = begin_offset; i < begin_offset + length; i++)
737 { 511 {
738 llwchar wch = wstr[i]; 512 llwchar wch = wstr[i];
@@ -752,7 +526,7 @@ S32 LLFontGL::render(const LLWString &wstr,
752 526
753 if (!label.empty()) 527 if (!label.empty())
754 { 528 {
755 ext_advance += (EXT_X_BEARING + gExtCharFont->getWidthF32( label.c_str() )) * sScaleX; 529 ext_advance += (EXT_X_BEARING + getFontExtChar()->getWidthF32( label.c_str() )) * sScaleX;
756 } 530 }
757 531
758 if (start_x + scaled_max_pixels < cur_x + ext_advance) 532 if (start_x + scaled_max_pixels < cur_x + ext_advance)
@@ -761,9 +535,15 @@ S32 LLFontGL::render(const LLWString &wstr,
761 break; 535 break;
762 } 536 }
763 537
764 gGL.getTexUnit(0)->bind(ext_image); 538 if (last_bound_texture != ext_image)
765 const F32 ext_x = cur_render_x + (EXT_X_BEARING * sScaleX); 539 {
766 const F32 ext_y = cur_render_y + (EXT_Y_BEARING * sScaleY + mAscender - mLineHeight); 540 gGL.getTexUnit(0)->bind(ext_image);
541 last_bound_texture = ext_image;
542 }
543
544 // snap origin to whole screen pixel
545 const F32 ext_x = (F32)llround(cur_render_x + (EXT_X_BEARING * sScaleX));
546 const F32 ext_y = (F32)llround(cur_render_y + (EXT_Y_BEARING * sScaleY + mAscender - mLineHeight));
767 547
768 LLRectf uv_rect(0.f, 1.f, 1.f, 0.f); 548 LLRectf uv_rect(0.f, 1.f, 1.f, 0.f);
769 LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y); 549 LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y);
@@ -775,7 +555,7 @@ S32 LLFontGL::render(const LLWString &wstr,
775 //glLoadIdentity(); 555 //glLoadIdentity();
776 //gGL.translatef(sCurOrigin.mX, sCurOrigin.mY, 0.0f); 556 //gGL.translatef(sCurOrigin.mX, sCurOrigin.mY, 0.0f);
777 //glScalef(sScaleX, sScaleY, 1.f); 557 //glScalef(sScaleX, sScaleY, 1.f);
778 gExtCharFont->render(label, 0, 558 getFontExtChar()->render(label, 0,
779 /*llfloor*/((ext_x + (F32)ext_image->getWidth() + EXT_X_BEARING) / sScaleX), 559 /*llfloor*/((ext_x + (F32)ext_image->getWidth() + EXT_X_BEARING) / sScaleX),
780 /*llfloor*/(cur_y / sScaleY), 560 /*llfloor*/(cur_y / sScaleY),
781 color, 561 color,
@@ -793,15 +573,12 @@ S32 LLFontGL::render(const LLWString &wstr,
793 cur_x += EXT_KERNING * sScaleX; 573 cur_x += EXT_KERNING * sScaleX;
794 } 574 }
795 cur_render_x = cur_x; 575 cur_render_x = cur_x;
796
797 // Bind the font texture
798 gGL.getTexUnit(0)->bind(mImageGLp);
799 } 576 }
800 else 577 else
801 { 578 {
802 if (!hasGlyph(wch)) 579 if (!hasGlyph(wch))
803 { 580 {
804 (const_cast<LLFontGL*>(this))->addChar(wch); 581 addChar(wch);
805 } 582 }
806 583
807 const LLFontGlyphInfo* fgi= getGlyphInfo(wch); 584 const LLFontGlyphInfo* fgi= getGlyphInfo(wch);
@@ -810,6 +587,14 @@ S32 LLFontGL::render(const LLWString &wstr,
810 llerrs << "Missing Glyph Info" << llendl; 587 llerrs << "Missing Glyph Info" << llendl;
811 break; 588 break;
812 } 589 }
590 // Per-glyph bitmap texture.
591 LLImageGL *image_gl = mFontBitmapCachep->getImageGL(fgi->mBitmapNum);
592 if (last_bound_texture != image_gl)
593 {
594 gGL.getTexUnit(0)->bind(image_gl);
595 last_bound_texture = image_gl;
596 }
597
813 if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth)) 598 if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth))
814 { 599 {
815 // Not enough room for this character. 600 // Not enough room for this character.
@@ -818,15 +603,16 @@ S32 LLFontGL::render(const LLWString &wstr,
818 603
819 // Draw the text at the appropriate location 604 // Draw the text at the appropriate location
820 //Specify vertices and texture coordinates 605 //Specify vertices and texture coordinates
821 LLRectf uv_rect((fgi->mXBitmapOffset - PAD_AMT) * inv_width, 606 LLRectf uv_rect((fgi->mXBitmapOffset) * inv_width,
822 (fgi->mYBitmapOffset + fgi->mHeight + PAD_AMT) * inv_height, 607 (fgi->mYBitmapOffset + fgi->mHeight + PAD_UVY) * inv_height,
823 (fgi->mXBitmapOffset + fgi->mWidth + PAD_AMT) * inv_width, 608 (fgi->mXBitmapOffset + fgi->mWidth) * inv_width,
824 (fgi->mYBitmapOffset - PAD_AMT) * inv_height); 609 (fgi->mYBitmapOffset - PAD_UVY) * inv_height);
825 LLRectf screen_rect(cur_render_x + (F32)fgi->mXBearing - PAD_AMT, 610 // snap glyph origin to whole screen pixel
826 cur_render_y + (F32)fgi->mYBearing + PAD_AMT, 611 LLRectf screen_rect(llround(cur_render_x + (F32)fgi->mXBearing),
827 cur_render_x + (F32)fgi->mXBearing + (F32)fgi->mWidth + PAD_AMT, 612 llround(cur_render_y + (F32)fgi->mYBearing),
828 cur_render_y + (F32)fgi->mYBearing - (F32)fgi->mHeight - PAD_AMT); 613 llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth,
829 614 llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight);
615
830 drawGlyph(screen_rect, uv_rect, color, style, drop_shadow_strength); 616 drawGlyph(screen_rect, uv_rect, color, style, drop_shadow_strength);
831 617
832 chars_drawn++; 618 chars_drawn++;
@@ -839,7 +625,7 @@ S32 LLFontGL::render(const LLWString &wstr,
839 // Kern this puppy. 625 // Kern this puppy.
840 if (!hasGlyph(next_char)) 626 if (!hasGlyph(next_char))
841 { 627 {
842 (const_cast<LLFontGL*>(this))->addChar(next_char); 628 addChar(next_char);
843 } 629 }
844 cur_x += getXKerning(wch, next_char); 630 cur_x += getXKerning(wch, next_char);
845 } 631 }
@@ -896,11 +682,6 @@ S32 LLFontGL::render(const LLWString &wstr,
896 return chars_drawn; 682 return chars_drawn;
897} 683}
898 684
899
900LLImageGL *LLFontGL::getImageGL() const
901{
902 return mImageGLp;
903}
904 685
905S32 LLFontGL::getWidth(const std::string& utf8text) const 686S32 LLFontGL::getWidth(const std::string& utf8text) const
906{ 687{
@@ -1118,59 +899,32 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
1118 llwchar wch = wchars[i]; 899 llwchar wch = wchars[i];
1119 900
1120 const embedded_data_t* ext_data = getEmbeddedCharData(wch); 901 const embedded_data_t* ext_data = getEmbeddedCharData(wch);
1121 if (ext_data) 902 F32 char_width = ext_data ? getEmbeddedCharAdvance(ext_data) : getXAdvance(wch);
1122 {
1123 F32 char_width = getEmbeddedCharAdvance(ext_data);
1124
1125 if( scaled_max_pixels < (total_width + char_width) )
1126 {
1127 break;
1128 }
1129 903
1130 total_width += char_width; 904 if( scaled_max_pixels < (total_width + char_width) )
1131
1132 drawable_chars++;
1133 if( max_chars >= 0 && drawable_chars >= max_chars )
1134 {
1135 break;
1136 }
1137
1138 if ( i > 0 )
1139 {
1140 total_width += EXT_KERNING * sScaleX;
1141 }
1142
1143 // Round after kerning.
1144 total_width = (F32)llfloor(total_width + 0.5f);
1145 }
1146 else
1147 { 905 {
1148 F32 char_width = getXAdvance(wch); 906 break;
1149 if( scaled_max_pixels < (total_width + char_width) ) 907 }
1150 {
1151 break;
1152 }
1153
1154 total_width += char_width;
1155 908
1156 drawable_chars++; 909 total_width += char_width;
1157 if( max_chars >= 0 && drawable_chars >= max_chars ) 910 drawable_chars++;
1158 {
1159 break;
1160 }
1161 911
1162 if ( i > 0 ) 912 if( max_chars >= 0 && drawable_chars >= max_chars )
1163 { 913 {
1164 // Kerning 914 break;
1165 total_width += getXKerning(wchars[i-1], wch); 915 }
1166 }
1167 916
1168 // Round after kerning. 917 if ( i > 0 )
1169 total_width = (F32)llfloor(total_width + 0.5f); 918 {
919 // kerning
920 total_width += ext_data ? (EXT_KERNING * sScaleX) : getXKerning(wchars[i-1], wch);
1170 } 921 }
922
923 // Round after kerning.
924 total_width = llround(total_width);
1171 } 925 }
1172 926
1173 return text_len - drawable_chars; 927 return start_pos - drawable_chars;
1174} 928}
1175 929
1176 930
@@ -1299,7 +1053,7 @@ F32 LLFontGL::getEmbeddedCharAdvance(const embedded_data_t* ext_data) const
1299 F32 ext_width = (F32)ext_image->getWidth(); 1053 F32 ext_width = (F32)ext_image->getWidth();
1300 if( !label.empty() ) 1054 if( !label.empty() )
1301 { 1055 {
1302 ext_width += (EXT_X_BEARING + gExtCharFont->getWidthF32(label.c_str())) * sScaleX; 1056 ext_width += (EXT_X_BEARING + getFontExtChar()->getWidthF32(label.c_str())) * sScaleX;
1303 } 1057 }
1304 1058
1305 return (EXT_X_BEARING * sScaleX) + ext_width; 1059 return (EXT_X_BEARING * sScaleX) + ext_width;
@@ -1312,19 +1066,19 @@ void LLFontGL::clearEmbeddedChars()
1312 mEmbeddedChars.clear(); 1066 mEmbeddedChars.clear();
1313} 1067}
1314 1068
1315void LLFontGL::addEmbeddedChar( llwchar wc, LLImageGL* image, const std::string& label ) 1069void LLFontGL::addEmbeddedChar( llwchar wc, LLImageGL* image, const std::string& label ) const
1316{ 1070{
1317 LLWString wlabel = utf8str_to_wstring(label); 1071 LLWString wlabel = utf8str_to_wstring(label);
1318 addEmbeddedChar(wc, image, wlabel); 1072 addEmbeddedChar(wc, image, wlabel);
1319} 1073}
1320 1074
1321void LLFontGL::addEmbeddedChar( llwchar wc, LLImageGL* image, const LLWString& wlabel ) 1075void LLFontGL::addEmbeddedChar( llwchar wc, LLImageGL* image, const LLWString& wlabel ) const
1322{ 1076{
1323 embedded_data_t* ext_data = new embedded_data_t(image, wlabel); 1077 embedded_data_t* ext_data = new embedded_data_t(image, wlabel);
1324 mEmbeddedChars[wc] = ext_data; 1078 mEmbeddedChars[wc] = ext_data;
1325} 1079}
1326 1080
1327void LLFontGL::removeEmbeddedChar( llwchar wc ) 1081void LLFontGL::removeEmbeddedChar( llwchar wc ) const
1328{ 1082{
1329 embedded_map_t::iterator iter = mEmbeddedChars.find(wc); 1083 embedded_map_t::iterator iter = mEmbeddedChars.find(wc);
1330 if (iter != mEmbeddedChars.end()) 1084 if (iter != mEmbeddedChars.end())
@@ -1428,68 +1182,9 @@ void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, con
1428 gGL.end(); 1182 gGL.end();
1429} 1183}
1430 1184
1431// static
1432std::string LLFontGL::nameFromFont(const LLFontGL* fontp) 1185std::string LLFontGL::nameFromFont(const LLFontGL* fontp)
1433{ 1186{
1434 if (fontp == sSansSerifHuge) 1187 return fontp->getFontDesc().getName();
1435 {
1436 return std::string("SansSerifHuge");
1437 }
1438 else if (fontp == sSansSerifSmall)
1439 {
1440 return std::string("SansSerifSmall");
1441 }
1442 else if (fontp == sSansSerif)
1443 {
1444 return std::string("SansSerif");
1445 }
1446 else if (fontp == sSansSerifBig)
1447 {
1448 return std::string("SansSerifBig");
1449 }
1450 else if (fontp == sSansSerifBold)
1451 {
1452 return std::string("SansSerifBold");
1453 }
1454 else if (fontp == sMonospace)
1455 {
1456 return std::string("Monospace");
1457 }
1458 else
1459 {
1460 return std::string();
1461 }
1462}
1463
1464// static
1465LLFontGL* LLFontGL::fontFromName(const std::string& font_name)
1466{
1467 LLFontGL* gl_font = NULL;
1468 if (font_name == "SansSerifHuge")
1469 {
1470 gl_font = LLFontGL::sSansSerifHuge;
1471 }
1472 else if (font_name == "SansSerifSmall")
1473 {
1474 gl_font = LLFontGL::sSansSerifSmall;
1475 }
1476 else if (font_name == "SansSerif")
1477 {
1478 gl_font = LLFontGL::sSansSerif;
1479 }
1480 else if (font_name == "SansSerifBig")
1481 {
1482 gl_font = LLFontGL::sSansSerifBig;
1483 }
1484 else if (font_name == "SansSerifBold")
1485 {
1486 gl_font = LLFontGL::sSansSerifBold;
1487 }
1488 else if (font_name == "Monospace")
1489 {
1490 gl_font = LLFontGL::sMonospace;
1491 }
1492 return gl_font;
1493} 1188}
1494 1189
1495// static 1190// static