diff options
Diffstat (limited to 'linden/indra/llrender/llfontgl.cpp')
-rw-r--r-- | linden/indra/llrender/llfontgl.cpp | 194 |
1 files changed, 112 insertions, 82 deletions
diff --git a/linden/indra/llrender/llfontgl.cpp b/linden/indra/llrender/llfontgl.cpp index f72a7de..7ee89c7 100644 --- a/linden/indra/llrender/llfontgl.cpp +++ b/linden/indra/llrender/llfontgl.cpp | |||
@@ -4,6 +4,7 @@ | |||
4 | * | 4 | * |
5 | * Copyright (c) 2001-2007, Linden Research, Inc. | 5 | * Copyright (c) 2001-2007, Linden Research, Inc. |
6 | * | 6 | * |
7 | * Second Life Viewer Source Code | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | 8 | * The source code in this file ("Source Code") is provided by Linden Lab |
8 | * to you under the terms of the GNU General Public License, version 2.0 | 9 | * to you under the terms of the GNU General Public License, version 2.0 |
9 | * ("GPL"), unless you have obtained a separate licensing agreement | 10 | * ("GPL"), unless you have obtained a separate licensing agreement |
@@ -69,6 +70,7 @@ const F32 PIXEL_BORDER_THRESHOLD = 0.0001f; | |||
69 | const F32 PIXEL_CORRECTION_DISTANCE = 0.01f; | 70 | const F32 PIXEL_CORRECTION_DISTANCE = 0.01f; |
70 | 71 | ||
71 | const F32 PAD_AMT = 0.5f; | 72 | const F32 PAD_AMT = 0.5f; |
73 | const F32 DROP_SHADOW_STRENGTH = 0.3f; | ||
72 | 74 | ||
73 | F32 llfont_round_x(F32 x) | 75 | F32 llfont_round_x(F32 x) |
74 | { | 76 | { |
@@ -133,7 +135,8 @@ void LLFontGL::init() | |||
133 | mImageGLp = new LLImageGL(FALSE); | 135 | mImageGLp = new LLImageGL(FALSE); |
134 | //RN: use nearest mipmap filtering to obviate the need to do pixel-accurate positioning | 136 | //RN: use nearest mipmap filtering to obviate the need to do pixel-accurate positioning |
135 | mImageGLp->bind(); | 137 | mImageGLp->bind(); |
136 | mImageGLp->setMipFilterNearest(TRUE, TRUE); | 138 | // we allow bilinear filtering to get sub-pixel positioning for drop shadows |
139 | //mImageGLp->setMipFilterNearest(TRUE, TRUE); | ||
137 | } | 140 | } |
138 | if (mRawImageGLp.isNull()) | 141 | if (mRawImageGLp.isNull()) |
139 | { | 142 | { |
@@ -549,28 +552,8 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
549 | return 0; | 552 | return 0; |
550 | } | 553 | } |
551 | 554 | ||
552 | if (style & DROP_SHADOW) | ||
553 | { | ||
554 | LLColor4 shadow_color = sShadowColor; | ||
555 | shadow_color[3] = color[3]; | ||
556 | render(wstr, begin_offset, | ||
557 | x + 1.f / sScaleX, | ||
558 | y - 1.f / sScaleY, | ||
559 | shadow_color, | ||
560 | halign, | ||
561 | valign, | ||
562 | style & (~DROP_SHADOW), | ||
563 | max_chars, | ||
564 | max_pixels, | ||
565 | right_x, | ||
566 | use_embedded, | ||
567 | use_ellipses); | ||
568 | } | ||
569 | |||
570 | S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); | 555 | S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); |
571 | 556 | ||
572 | BOOL render_bold = FALSE; | ||
573 | |||
574 | // HACK for better bolding | 557 | // HACK for better bolding |
575 | if (style & BOLD) | 558 | if (style & BOLD) |
576 | { | 559 | { |
@@ -585,9 +568,17 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
585 | max_chars, max_pixels, | 568 | max_chars, max_pixels, |
586 | right_x, use_embedded); | 569 | right_x, use_embedded); |
587 | } | 570 | } |
588 | else | 571 | } |
572 | |||
573 | F32 drop_shadow_strength = 0.f; | ||
574 | if (style & DROP_SHADOW) | ||
575 | { | ||
576 | F32 luminance; | ||
577 | color.calcHSL(NULL, NULL, &luminance); | ||
578 | drop_shadow_strength = clamp_rescale(luminance, 0.35f, 0.6f, 0.f, DROP_SHADOW_STRENGTH); | ||
579 | if (luminance < 0.35f) | ||
589 | { | 580 | { |
590 | render_bold = TRUE; | 581 | style = style & ~DROP_SHADOW; |
591 | } | 582 | } |
592 | } | 583 | } |
593 | 584 | ||
@@ -631,9 +622,6 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
631 | } | 622 | } |
632 | 623 | ||
633 | F32 cur_x, cur_y, cur_render_x, cur_render_y; | 624 | F32 cur_x, cur_y, cur_render_x, cur_render_y; |
634 | F32 slant_offset; | ||
635 | |||
636 | slant_offset = ((style & ITALIC) ? ( -mAscender * 0.25f) : 0.f); | ||
637 | 625 | ||
638 | // Bind the font texture | 626 | // Bind the font texture |
639 | 627 | ||
@@ -696,7 +684,7 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
696 | if (use_ellipses && halign == LEFT) | 684 | if (use_ellipses && halign == LEFT) |
697 | { | 685 | { |
698 | // check for too long of a string | 686 | // check for too long of a string |
699 | if (getWidthF32(wstr.c_str(), 0, max_chars) > scaled_max_pixels) | 687 | if (getWidthF32(wstr.c_str(), 0, max_chars) * sScaleX > scaled_max_pixels) |
700 | { | 688 | { |
701 | // use four dots for ellipsis width to generate padding | 689 | // use four dots for ellipsis width to generate padding |
702 | const LLWString dots(utf8str_to_wstring(LLString("...."))); | 690 | const LLWString dots(utf8str_to_wstring(LLString("...."))); |
@@ -706,7 +694,6 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
706 | } | 694 | } |
707 | 695 | ||
708 | 696 | ||
709 | glBegin(GL_QUADS); | ||
710 | for (i = begin_offset; i < begin_offset + length; i++) | 697 | for (i = begin_offset; i < begin_offset + length; i++) |
711 | { | 698 | { |
712 | llwchar wch = wstr[i]; | 699 | llwchar wch = wstr[i]; |
@@ -735,36 +722,13 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
735 | break; | 722 | break; |
736 | } | 723 | } |
737 | 724 | ||
738 | glEnd(); | ||
739 | |||
740 | glColor3f(1.f, 1.f, 1.f); | ||
741 | |||
742 | ext_image->bind(); | 725 | ext_image->bind(); |
743 | const F32 ext_x = cur_render_x + (EXT_X_BEARING * sScaleX); | 726 | const F32 ext_x = cur_render_x + (EXT_X_BEARING * sScaleX); |
744 | const F32 ext_y = cur_render_y + (EXT_Y_BEARING * sScaleY + mAscender - mLineHeight); | 727 | const F32 ext_y = cur_render_y + (EXT_Y_BEARING * sScaleY + mAscender - mLineHeight); |
745 | 728 | ||
746 | glBegin(GL_QUADS); | 729 | LLRectf uv_rect(0.f, 1.f, 1.f, 0.f); |
747 | { | 730 | LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y); |
748 | S32 num_passes = render_bold ? 2 : 1; | 731 | drawGlyph(screen_rect, uv_rect, LLColor4::white, style, drop_shadow_strength); |
749 | for (S32 pass = 0; pass < num_passes; pass++) | ||
750 | { | ||
751 | glTexCoord2f(1.f, 1.f); | ||
752 | glVertex2f(llfont_round_x(ext_x + ext_width + (F32)(pass * BOLD_OFFSET)), | ||
753 | llfont_round_y(ext_y + ext_height)); | ||
754 | |||
755 | glTexCoord2f(0.f, 1.f); | ||
756 | glVertex2f(llfont_round_x(ext_x + (F32)(pass * BOLD_OFFSET)), | ||
757 | llfont_round_y(ext_y + ext_height)); | ||
758 | |||
759 | glTexCoord2f(0.f, 0.f); | ||
760 | glVertex2f(llfont_round_x(ext_x + (F32)(pass * BOLD_OFFSET)), llfont_round_y(ext_y)); | ||
761 | |||
762 | glTexCoord2f(1.f, 0.f); | ||
763 | glVertex2f(llfont_round_x(ext_x + ext_width + (F32)(pass * BOLD_OFFSET)), | ||
764 | llfont_round_y(ext_y)); | ||
765 | } | ||
766 | } | ||
767 | glEnd(); | ||
768 | 732 | ||
769 | if (!label.empty()) | 733 | if (!label.empty()) |
770 | { | 734 | { |
@@ -793,15 +757,12 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
793 | 757 | ||
794 | // Bind the font texture | 758 | // Bind the font texture |
795 | mImageGLp->bind(); | 759 | mImageGLp->bind(); |
796 | glBegin(GL_QUADS); | ||
797 | } | 760 | } |
798 | else | 761 | else |
799 | { | 762 | { |
800 | if (!hasGlyph(wch)) | 763 | if (!hasGlyph(wch)) |
801 | { | 764 | { |
802 | glEnd(); | ||
803 | (const_cast<LLFontGL*>(this))->addChar(wch); | 765 | (const_cast<LLFontGL*>(this))->addChar(wch); |
804 | glBegin(GL_QUADS); | ||
805 | } | 766 | } |
806 | 767 | ||
807 | const LLFontGlyphInfo* fgi= getGlyphInfo(wch); | 768 | const LLFontGlyphInfo* fgi= getGlyphInfo(wch); |
@@ -817,40 +778,28 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
817 | 778 | ||
818 | // Draw the text at the appropriate location | 779 | // Draw the text at the appropriate location |
819 | //Specify vertices and texture coordinates | 780 | //Specify vertices and texture coordinates |
820 | S32 num_passes = render_bold ? 2 : 1; | 781 | LLRectf uv_rect((fgi->mXBitmapOffset - PAD_AMT) * inv_width, |
821 | for (S32 pass = 0; pass < num_passes; pass++) | 782 | (fgi->mYBitmapOffset + fgi->mHeight + PAD_AMT) * inv_height, |
822 | { | 783 | (fgi->mXBitmapOffset + fgi->mWidth + PAD_AMT) * inv_width, |
823 | glTexCoord2f((fgi->mXBitmapOffset - PAD_AMT) * inv_width, | 784 | (fgi->mYBitmapOffset - PAD_AMT) * inv_height); |
824 | (fgi->mYBitmapOffset + fgi->mHeight + PAD_AMT) * inv_height); | 785 | LLRectf screen_rect(cur_render_x + (F32)fgi->mXBearing - PAD_AMT, |
825 | glVertex2f(llfont_round_x(cur_render_x + (F32)fgi->mXBearing + (F32)(pass * BOLD_OFFSET) - PAD_AMT), | 786 | cur_render_y + (F32)fgi->mYBearing + PAD_AMT, |
826 | llfont_round_y(cur_render_y + (F32)fgi->mYBearing + PAD_AMT)); | 787 | cur_render_x + (F32)fgi->mXBearing + (F32)fgi->mWidth + PAD_AMT, |
827 | glTexCoord2f((fgi->mXBitmapOffset - PAD_AMT) * inv_width, | 788 | cur_render_y + (F32)fgi->mYBearing - (F32)fgi->mHeight - PAD_AMT); |
828 | (fgi->mYBitmapOffset - PAD_AMT) * inv_height); | ||
829 | glVertex2f(llfont_round_x(cur_render_x + (F32)fgi->mXBearing + slant_offset + (F32)(pass * BOLD_OFFSET) - PAD_AMT), | ||
830 | llfont_round_y(cur_render_y + (F32)fgi->mYBearing - (F32)fgi->mHeight - PAD_AMT)); | ||
831 | glTexCoord2f((fgi->mXBitmapOffset + fgi->mWidth + PAD_AMT) * inv_width, | ||
832 | (fgi->mYBitmapOffset - PAD_AMT) * inv_height); | ||
833 | glVertex2f(llfont_round_x(cur_render_x + (F32)fgi->mXBearing + slant_offset + (F32)fgi->mWidth + (F32)(pass * BOLD_OFFSET) + PAD_AMT), | ||
834 | llfont_round_y(cur_render_y + (F32)fgi->mYBearing - (F32)fgi->mHeight - PAD_AMT)); | ||
835 | glTexCoord2f((fgi->mXBitmapOffset + fgi->mWidth + PAD_AMT) * inv_width, | ||
836 | (fgi->mYBitmapOffset + fgi->mHeight + PAD_AMT) * inv_height); | ||
837 | glVertex2f(llfont_round_x(cur_render_x + (F32)fgi->mXBearing + (F32)fgi->mWidth + (F32)(pass * BOLD_OFFSET) + PAD_AMT), | ||
838 | llfont_round_y(cur_render_y + (F32)fgi->mYBearing + PAD_AMT)); | ||
839 | } | ||
840 | 789 | ||
841 | chars_drawn++; | 790 | drawGlyph(screen_rect, uv_rect, color, style, drop_shadow_strength); |
842 | 791 | ||
792 | chars_drawn++; | ||
843 | cur_x += fgi->mXAdvance; | 793 | cur_x += fgi->mXAdvance; |
844 | cur_y += fgi->mYAdvance; | 794 | cur_y += fgi->mYAdvance; |
795 | |||
845 | llwchar next_char = wstr[i+1]; | 796 | llwchar next_char = wstr[i+1]; |
846 | if (next_char && (next_char < LAST_CHARACTER)) | 797 | if (next_char && (next_char < LAST_CHARACTER)) |
847 | { | 798 | { |
848 | // Kern this puppy. | 799 | // Kern this puppy. |
849 | if (!hasGlyph(next_char)) | 800 | if (!hasGlyph(next_char)) |
850 | { | 801 | { |
851 | glEnd(); | ||
852 | (const_cast<LLFontGL*>(this))->addChar(next_char); | 802 | (const_cast<LLFontGL*>(this))->addChar(next_char); |
853 | glBegin(GL_QUADS); | ||
854 | } | 803 | } |
855 | cur_x += getXKerning(wch, next_char); | 804 | cur_x += getXKerning(wch, next_char); |
856 | } | 805 | } |
@@ -867,8 +816,6 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
867 | } | 816 | } |
868 | } | 817 | } |
869 | 818 | ||
870 | glEnd(); | ||
871 | |||
872 | if (right_x) | 819 | if (right_x) |
873 | { | 820 | { |
874 | *right_x = cur_x / sScaleX; | 821 | *right_x = cur_x / sScaleX; |
@@ -1347,6 +1294,89 @@ void LLFontGL::removeEmbeddedChar( llwchar wc ) | |||
1347 | } | 1294 | } |
1348 | } | 1295 | } |
1349 | 1296 | ||
1297 | |||
1298 | void LLFontGL::renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const | ||
1299 | { | ||
1300 | glTexCoord2f(uv_rect.mRight, uv_rect.mTop); | ||
1301 | glVertex2f(llfont_round_x(screen_rect.mRight), | ||
1302 | llfont_round_y(screen_rect.mTop)); | ||
1303 | |||
1304 | glTexCoord2f(uv_rect.mLeft, uv_rect.mTop); | ||
1305 | glVertex2f(llfont_round_x(screen_rect.mLeft), | ||
1306 | llfont_round_y(screen_rect.mTop)); | ||
1307 | |||
1308 | glTexCoord2f(uv_rect.mLeft, uv_rect.mBottom); | ||
1309 | glVertex2f(llfont_round_x(screen_rect.mLeft + slant_amt), | ||
1310 | llfont_round_y(screen_rect.mBottom)); | ||
1311 | |||
1312 | glTexCoord2f(uv_rect.mRight, uv_rect.mBottom); | ||
1313 | glVertex2f(llfont_round_x(screen_rect.mRight + slant_amt), | ||
1314 | llfont_round_y(screen_rect.mBottom)); | ||
1315 | } | ||
1316 | |||
1317 | void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, F32 drop_shadow_strength) const | ||
1318 | { | ||
1319 | F32 slant_offset; | ||
1320 | slant_offset = ((style & ITALIC) ? ( -mAscender * 0.2f) : 0.f); | ||
1321 | |||
1322 | glBegin(GL_QUADS); | ||
1323 | { | ||
1324 | //FIXME: bold and drop shadow are mutually exclusive only for convenience | ||
1325 | //Allow both when we need them. | ||
1326 | if (style & BOLD) | ||
1327 | { | ||
1328 | glColor4fv(color.mV); | ||
1329 | for (S32 pass = 0; pass < 2; pass++) | ||
1330 | { | ||
1331 | LLRectf screen_rect_offset = screen_rect; | ||
1332 | |||
1333 | screen_rect_offset.translate((F32)(pass * BOLD_OFFSET), 0.f); | ||
1334 | renderQuad(screen_rect_offset, uv_rect, slant_offset); | ||
1335 | } | ||
1336 | } | ||
1337 | else if (style & DROP_SHADOW) | ||
1338 | { | ||
1339 | LLColor4 shadow_color = LLFontGL::sShadowColor; | ||
1340 | shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength; | ||
1341 | glColor4fv(shadow_color.mV); | ||
1342 | for (S32 pass = 0; pass < 5; pass++) | ||
1343 | { | ||
1344 | LLRectf screen_rect_offset = screen_rect; | ||
1345 | |||
1346 | switch(pass) | ||
1347 | { | ||
1348 | case 0: | ||
1349 | screen_rect_offset.translate(-1.f, -1.f); | ||
1350 | break; | ||
1351 | case 1: | ||
1352 | screen_rect_offset.translate(1.f, -1.f); | ||
1353 | break; | ||
1354 | case 2: | ||
1355 | screen_rect_offset.translate(1.f, 1.f); | ||
1356 | break; | ||
1357 | case 3: | ||
1358 | screen_rect_offset.translate(-1.f, 1.f); | ||
1359 | break; | ||
1360 | case 4: | ||
1361 | screen_rect_offset.translate(0, -2.f); | ||
1362 | break; | ||
1363 | } | ||
1364 | |||
1365 | renderQuad(screen_rect_offset, uv_rect, slant_offset); | ||
1366 | } | ||
1367 | glColor4fv(color.mV); | ||
1368 | renderQuad(screen_rect, uv_rect, slant_offset); | ||
1369 | } | ||
1370 | else // normal rendering | ||
1371 | { | ||
1372 | glColor4fv(color.mV); | ||
1373 | renderQuad(screen_rect, uv_rect, slant_offset); | ||
1374 | } | ||
1375 | |||
1376 | } | ||
1377 | glEnd(); | ||
1378 | } | ||
1379 | |||
1350 | // static | 1380 | // static |
1351 | LLString LLFontGL::nameFromFont(const LLFontGL* fontp) | 1381 | LLString LLFontGL::nameFromFont(const LLFontGL* fontp) |
1352 | { | 1382 | { |