summaryrefslogtreecommitdiff
path: root/indra/llrender/llfontgl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llrender/llfontgl.cpp')
-rwxr-xr-x[-rw-r--r--]indra/llrender/llfontgl.cpp411
1 files changed, 232 insertions, 179 deletions
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index d9e1976341..53ca080d66 100644..100755
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -2,31 +2,25 @@
* @file llfontgl.cpp
* @brief Wrapper around FreeType
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -35,6 +29,7 @@
#include "llfontgl.h"
// Linden library includes
+#include "llfasttimer.h"
#include "llfontfreetype.h"
#include "llfontbitmapcache.h"
#include "llfontregistry.h"
@@ -62,32 +57,13 @@ std::string LLFontGL::sAppDir;
LLColor4 LLFontGL::sShadowColor(0.f, 0.f, 0.f, 1.f);
LLFontRegistry* LLFontGL::sFontRegistry = NULL;
-LLCoordFont LLFontGL::sCurOrigin;
-std::vector<LLCoordFont> LLFontGL::sOriginStack;
-
-const F32 EXT_X_BEARING = 1.f;
-const F32 EXT_Y_BEARING = 0.f;
-const F32 EXT_KERNING = 1.f;
-const F32 PIXEL_BORDER_THRESHOLD = 0.0001f;
-const F32 PIXEL_CORRECTION_DISTANCE = 0.01f;
+LLCoordGL LLFontGL::sCurOrigin;
+F32 LLFontGL::sCurDepth;
+std::vector<std::pair<LLCoordGL, F32> > LLFontGL::sOriginStack;
const F32 PAD_UVY = 0.5f; // half of vertical padding between glyphs in the glyph texture
const F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f;
-static F32 llfont_round_x(F32 x)
-{
- //return llfloor((x-LLFontGL::sCurOrigin.mX)/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleX+LLFontGL::sCurOrigin.mX;
- //return llfloor(x/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleY;
- return x;
-}
-
-static F32 llfont_round_y(F32 y)
-{
- //return llfloor((y-LLFontGL::sCurOrigin.mY)/LLFontGL::sScaleY+0.5f)*LLFontGL::sScaleY+LLFontGL::sCurOrigin.mY;
- //return llfloor(y+0.5f);
- return y;
-}
-
LLFontGL::LLFontGL()
{
}
@@ -116,11 +92,39 @@ BOOL LLFontGL::loadFace(const std::string& filename, F32 point_size, F32 vert_dp
return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, components, is_fallback);
}
-static LLFastTimer::DeclareTimer FTM_RENDER_FONTS("Fonts");
+static LLTrace::BlockTimerStatHandle FTM_RENDER_FONTS("Fonts");
+
+S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRect& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
+ ShadowType shadow, S32 max_chars, F32* right_x, BOOL use_ellipses) const
+{
+ F32 x = (F32)rect.mLeft;
+ F32 y = 0.f;
+
+ switch(valign)
+ {
+ case TOP:
+ y = (F32)rect.mTop;
+ break;
+ case VCENTER:
+ y = (F32)rect.getCenterY();
+ break;
+ case BASELINE:
+ case BOTTOM:
+ y = (F32)rect.mBottom;
+ break;
+ default:
+ y = (F32)rect.mBottom;
+ break;
+ }
+ return render(wstr, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, rect.getWidth(), right_x, use_ellipses);
+}
+
S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const
{
+ LL_RECORD_BLOCK_TIME(FTM_RENDER_FONTS);
+
if(!sDisplayFont) //do not display texts
{
return wstr.length() ;
@@ -155,16 +159,11 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
gGL.loadUIIdentity();
- gGL.translateUI(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ);
-
- // this code snaps the text origin to a pixel grid to start with
- F32 pixel_offset_x = llround((F32)sCurOrigin.mX) - (sCurOrigin.mX);
- F32 pixel_offset_y = llround((F32)sCurOrigin.mY) - (sCurOrigin.mY);
- gGL.translateUI(-pixel_offset_x, -pixel_offset_y, 0.f);
-
- LLFastTimer t(FTM_RENDER_FONTS);
+ LLVector2 origin(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY));
- gGL.color4fv( color.mV );
+ // Depth translation, so that floating text appears 'in-world'
+ // and is correctly occluded.
+ gGL.translatef(0.f,0.f,sCurDepth);
S32 chars_drawn = 0;
S32 i;
@@ -184,20 +183,21 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
// Not guaranteed to be set correctly
gGL.setSceneBlendType(LLRender::BT_ALPHA);
- cur_x = ((F32)x * sScaleX);
- cur_y = ((F32)y * sScaleY);
+ cur_x = ((F32)x * sScaleX) + origin.mV[VX];
+ cur_y = ((F32)y * sScaleY) + origin.mV[VY];
// Offset y by vertical alignment.
+ // use unscaled font metrics here
switch (valign)
{
case TOP:
- cur_y -= mFontFreetype->getAscenderHeight();
+ cur_y -= llceil(mFontFreetype->getAscenderHeight());
break;
case BOTTOM:
- cur_y += mFontFreetype->getDescenderHeight();
+ cur_y += llceil(mFontFreetype->getDescenderHeight());
break;
case VCENTER:
- cur_y -= (mFontFreetype->getAscenderHeight() - mFontFreetype->getDescenderHeight()) / 2.f;
+ cur_y -= llceil((llceil(mFontFreetype->getAscenderHeight()) - llceil(mFontFreetype->getDescenderHeight())) / 2.f);
break;
case BASELINE:
// Baseline, do nothing.
@@ -211,10 +211,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
case LEFT:
break;
case RIGHT:
- cur_x -= llmin(scaled_max_pixels, llround(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX));
+ cur_x -= llmin(scaled_max_pixels, ll_round(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX));
break;
case HCENTER:
- cur_x -= llmin(scaled_max_pixels, llround(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX)) / 2;
+ cur_x -= llmin(scaled_max_pixels, ll_round(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX)) / 2;
break;
default:
break;
@@ -223,7 +223,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
cur_render_y = cur_y;
cur_render_x = cur_x;
- F32 start_x = llround(cur_x);
+ F32 start_x = (F32)ll_round(cur_x);
const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache();
@@ -237,19 +237,27 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
if (use_ellipses)
{
// check for too long of a string
- S32 string_width = llround(getWidthF32(wstr.c_str(), begin_offset, max_chars) * sScaleX);
+ S32 string_width = ll_round(getWidthF32(wstr.c_str(), begin_offset, max_chars) * sScaleX);
if (string_width > scaled_max_pixels)
{
// use four dots for ellipsis width to generate padding
const LLWString dots(utf8str_to_wstring(std::string("....")));
- scaled_max_pixels = llmax(0, scaled_max_pixels - llround(getWidthF32(dots.c_str())));
+ scaled_max_pixels = llmax(0, scaled_max_pixels - ll_round(getWidthF32(dots.c_str())));
draw_ellipses = TRUE;
}
}
-
const LLFontGlyphInfo* next_glyph = NULL;
+ const S32 GLYPH_BATCH_SIZE = 30;
+ LLVector3 vertices[GLYPH_BATCH_SIZE * 4];
+ LLVector2 uvs[GLYPH_BATCH_SIZE * 4];
+ LLColor4U colors[GLYPH_BATCH_SIZE * 4];
+
+ LLColor4U text_color(color);
+
+ S32 bitmap_num = -1;
+ S32 glyph_count = 0;
for (i = begin_offset; i < begin_offset + length; i++)
{
llwchar wch = wstr[i];
@@ -262,12 +270,29 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
}
if (!fgi)
{
- llerrs << "Missing Glyph Info" << llendl;
+ LL_ERRS() << "Missing Glyph Info" << LL_ENDL;
break;
}
// Per-glyph bitmap texture.
- LLImageGL *image_gl = mFontFreetype->getFontBitmapCache()->getImageGL(fgi->mBitmapNum);
- gGL.getTexUnit(0)->bind(image_gl);
+ S32 next_bitmap_num = fgi->mBitmapNum;
+ if (next_bitmap_num != bitmap_num)
+ {
+ // Actually draw the queued glyphs before switching their texture;
+ // otherwise the queued glyphs will be taken from wrong textures.
+ if (glyph_count > 0)
+ {
+ gGL.begin(LLRender::QUADS);
+ {
+ gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4);
+ }
+ gGL.end();
+ glyph_count = 0;
+ }
+
+ bitmap_num = next_bitmap_num;
+ LLImageGL *font_image = font_bitmap_cache->getImageGL(bitmap_num);
+ gGL.getTexUnit(0)->bind(font_image);
+ }
if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth))
{
@@ -282,12 +307,23 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
(fgi->mXBitmapOffset + fgi->mWidth) * inv_width,
(fgi->mYBitmapOffset - PAD_UVY) * inv_height);
// snap glyph origin to whole screen pixel
- LLRectf screen_rect(llround(cur_render_x + (F32)fgi->mXBearing),
- llround(cur_render_y + (F32)fgi->mYBearing),
- llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth,
- llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight);
+ LLRectf screen_rect((F32)ll_round(cur_render_x + (F32)fgi->mXBearing),
+ (F32)ll_round(cur_render_y + (F32)fgi->mYBearing),
+ (F32)ll_round(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth,
+ (F32)ll_round(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight);
- drawGlyph(screen_rect, uv_rect, color, style_to_add, shadow, drop_shadow_strength);
+ if (glyph_count >= GLYPH_BATCH_SIZE)
+ {
+ gGL.begin(LLRender::QUADS);
+ {
+ gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4);
+ }
+ gGL.end();
+
+ glyph_count = 0;
+ }
+
+ drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect, text_color, style_to_add, shadow, drop_shadow_strength);
chars_drawn++;
cur_x += fgi->mXAdvance;
@@ -305,26 +341,34 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
// Must do this to cur_x, not just to cur_render_x, otherwise you
// will squish sub-pixel kerned characters too close together.
// For example, "CCCCC" looks bad.
- cur_x = (F32)llround(cur_x);
- //cur_y = (F32)llround(cur_y);
+ cur_x = (F32)ll_round(cur_x);
+ //cur_y = (F32)ll_round(cur_y);
cur_render_x = cur_x;
cur_render_y = cur_y;
}
+ gGL.begin(LLRender::QUADS);
+ {
+ gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4);
+ }
+ gGL.end();
+
+
if (right_x)
{
- *right_x = cur_x / sScaleX;
+ *right_x = (cur_x - origin.mV[VX]) / sScaleX;
}
+ //FIXME: add underline as glyph?
if (style_to_add & UNDERLINE)
{
- F32 descender = mFontFreetype->getDescenderHeight();
+ F32 descender = (F32)llfloor(mFontFreetype->getDescenderHeight());
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.begin(LLRender::LINES);
- gGL.vertex2f(start_x, cur_y - (descender));
- gGL.vertex2f(cur_x, cur_y - (descender));
+ gGL.vertex2f(start_x, cur_y - descender);
+ gGL.vertex2f(cur_x, cur_y - descender);
gGL.end();
}
@@ -336,7 +380,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
gGL.pushUIMatrix();
renderUTF8(std::string("..."),
0,
- cur_x / sScaleX, (F32)y,
+ (cur_x - origin.mV[VX]) / sScaleX, (F32)y,
color,
LEFT, valign,
style_to_add,
@@ -373,19 +417,19 @@ S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y
}
// font metrics - override for LLFontFreetype that returns units of virtual pixels
-F32 LLFontGL::getLineHeight() const
+F32 LLFontGL::getAscenderHeight() const
{
- return (F32)llround(mFontFreetype->getLineHeight() / sScaleY);
+ return mFontFreetype->getAscenderHeight() / sScaleY;
}
-F32 LLFontGL::getAscenderHeight() const
+F32 LLFontGL::getDescenderHeight() const
{
- return (F32)llround(mFontFreetype->getAscenderHeight() / sScaleY);
+ return mFontFreetype->getDescenderHeight() / sScaleY;
}
-F32 LLFontGL::getDescenderHeight() const
+S32 LLFontGL::getLineHeight() const
{
- return (F32)llround(mFontFreetype->getDescenderHeight() / sScaleY);
+ return llceil(mFontFreetype->getAscenderHeight() / sScaleY) + llceil(mFontFreetype->getDescenderHeight() / sScaleY);
}
S32 LLFontGL::getWidth(const std::string& utf8text) const
@@ -408,7 +452,7 @@ S32 LLFontGL::getWidth(const std::string& utf8text, S32 begin_offset, S32 max_ch
S32 LLFontGL::getWidth(const llwchar* wchars, S32 begin_offset, S32 max_chars) const
{
F32 width = getWidthF32(wchars, begin_offset, max_chars);
- return llround(width);
+ return ll_round(width);
}
F32 LLFontGL::getWidthF32(const std::string& utf8text) const
@@ -470,7 +514,7 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars
cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
}
// Round after kerning.
- cur_x = (F32)llround(cur_x);
+ cur_x = (F32)ll_round(cur_x);
}
// add in extra pixels for last character's width past its xadvance
@@ -492,13 +536,12 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
BOOL clip = FALSE;
F32 cur_x = 0;
- F32 drawn_x = 0;
S32 start_of_last_word = 0;
BOOL in_word = FALSE;
// avoid S32 overflow when max_pixels == S32_MAX by staying in floating point
- F32 scaled_max_pixels = ceil(max_pixels * sScaleX);
+ F32 scaled_max_pixels = max_pixels * sScaleX;
F32 width_padding = 0.f;
LLFontGlyphInfo* next_glyph = NULL;
@@ -550,6 +593,11 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
if(!fgi)
{
fgi = mFontFreetype->getGlyphInfo(wch);
+
+ if (NULL == fgi)
+ {
+ return 0;
+ }
}
// account for glyphs that run beyond the starting point for the next glyphs
@@ -574,8 +622,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
}
// Round after kerning.
- cur_x = llround(cur_x);
- drawn_x = cur_x;
+ cur_x = (F32)ll_round(cur_x);
}
if( clip )
@@ -645,7 +692,7 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
}
// Round after kerning.
- total_width = llround(total_width);
+ total_width = (F32)ll_round(total_width);
}
if (drawable_chars == 0)
@@ -728,7 +775,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t
// Round after kerning.
- cur_x = llround(cur_x);
+ cur_x = (F32)ll_round(cur_x);
}
return llmin(max_chars, pos - begin_offset);
@@ -740,7 +787,7 @@ const LLFontDescriptor& LLFontGL::getFontDesc() const
}
// static
-void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector<std::string>& xui_paths, bool create_gl_textures)
+void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, bool create_gl_textures)
{
sVertDPI = (F32)llfloor(screen_dpi * y_scale);
sHorizDPI = (F32)llfloor(screen_dpi * x_scale);
@@ -751,7 +798,7 @@ void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::st
// Font registry init
if (!sFontRegistry)
{
- sFontRegistry = new LLFontRegistry(xui_paths, create_gl_textures);
+ sFontRegistry = new LLFontRegistry(create_gl_textures);
sFontRegistry->parseFontInfo("fonts.xml");
}
else
@@ -920,37 +967,43 @@ LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name)
//static
LLFontGL* LLFontGL::getFontMonospace()
{
- return getFont(LLFontDescriptor("Monospace","Monospace",0));
+ static LLFontGL* fontp = getFont(LLFontDescriptor("Monospace","Monospace",0));
+ return fontp;
}
//static
LLFontGL* LLFontGL::getFontSansSerifSmall()
{
- return getFont(LLFontDescriptor("SansSerif","Small",0));
+ static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Small",0));
+ return fontp;
}
//static
LLFontGL* LLFontGL::getFontSansSerif()
{
- return getFont(LLFontDescriptor("SansSerif","Medium",0));
+ static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Medium",0));
+ return fontp;
}
//static
LLFontGL* LLFontGL::getFontSansSerifBig()
{
- return getFont(LLFontDescriptor("SansSerif","Large",0));
+ static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Large",0));
+ return fontp;
}
//static
LLFontGL* LLFontGL::getFontSansSerifHuge()
{
- return getFont(LLFontDescriptor("SansSerif","Huge",0));
+ static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Large",0));
+ return fontp;
}
//static
LLFontGL* LLFontGL::getFontSansSerifBold()
{
- return getFont(LLFontDescriptor("SansSerif","Medium",BOLD));
+ static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Medium",BOLD));
+ return fontp;
}
//static
@@ -1011,7 +1064,7 @@ std::string LLFontGL::getFontPathSystem()
system_root = getenv("SystemRoot"); /* Flawfinder: ignore */
if (!system_root)
{
- llwarns << "SystemRoot not found, attempting to load fonts from default path." << llendl;
+ LL_WARNS() << "SystemRoot not found, attempting to load fonts from default path." << LL_ENDL;
}
#endif
@@ -1056,104 +1109,104 @@ std::string LLFontGL::getFontPathLocal()
LLFontGL::LLFontGL(const LLFontGL &source)
{
- llerrs << "Not implemented!" << llendl;
+ LL_ERRS() << "Not implemented!" << LL_ENDL;
}
LLFontGL &LLFontGL::operator=(const LLFontGL &source)
{
- llerrs << "Not implemented" << llendl;
+ LL_ERRS() << "Not implemented" << LL_ENDL;
return *this;
}
-void LLFontGL::renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const
+void LLFontGL::renderQuad(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const
{
- gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
- gGL.vertex2f(llfont_round_x(screen_rect.mRight),
- llfont_round_y(screen_rect.mTop));
-
- gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
- gGL.vertex2f(llfont_round_x(screen_rect.mLeft),
- llfont_round_y(screen_rect.mTop));
-
- gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
- gGL.vertex2f(llfont_round_x(screen_rect.mLeft + slant_amt),
- llfont_round_y(screen_rect.mBottom));
-
- gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
- gGL.vertex2f(llfont_round_x(screen_rect.mRight + slant_amt),
- llfont_round_y(screen_rect.mBottom));
+ S32 index = 0;
+
+ vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mTop, 0.f);
+ uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
+ colors_out[index] = color;
+ index++;
+
+ vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 0.f);
+ uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
+ colors_out[index] = color;
+ index++;
+
+ vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 0.f);
+ uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
+ colors_out[index] = color;
+ index++;
+
+ vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 0.f);
+ uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
+ colors_out[index] = color;
}
-void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const
+void LLFontGL::drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const
{
F32 slant_offset;
slant_offset = ((style & ITALIC) ? ( -mFontFreetype->getAscenderHeight() * 0.2f) : 0.f);
- gGL.begin(LLRender::QUADS);
+ //FIXME: bold and drop shadow are mutually exclusive only for convenience
+ //Allow both when we need them.
+ if (style & BOLD)
{
- //FIXME: bold and drop shadow are mutually exclusive only for convenience
- //Allow both when we need them.
- if (style & BOLD)
+ for (S32 pass = 0; pass < 2; pass++)
{
- gGL.color4fv(color.mV);
- for (S32 pass = 0; pass < 2; pass++)
- {
- LLRectf screen_rect_offset = screen_rect;
+ LLRectf screen_rect_offset = screen_rect;
- screen_rect_offset.translate((F32)(pass * BOLD_OFFSET), 0.f);
- renderQuad(screen_rect_offset, uv_rect, slant_offset);
- }
+ screen_rect_offset.translate((F32)(pass * BOLD_OFFSET), 0.f);
+ renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_offset, uv_rect, color, slant_offset);
+ glyph_count++;
}
- else if (shadow == DROP_SHADOW_SOFT)
+ }
+ else if (shadow == DROP_SHADOW_SOFT)
+ {
+ LLColor4U shadow_color = LLFontGL::sShadowColor;
+ shadow_color.mV[VALPHA] = U8(color.mV[VALPHA] * drop_shadow_strength * DROP_SHADOW_SOFT_STRENGTH);
+ for (S32 pass = 0; pass < 5; pass++)
{
- LLColor4 shadow_color = LLFontGL::sShadowColor;
- shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength * DROP_SHADOW_SOFT_STRENGTH;
- gGL.color4fv(shadow_color.mV);
- for (S32 pass = 0; pass < 5; pass++)
- {
- LLRectf screen_rect_offset = screen_rect;
+ LLRectf screen_rect_offset = screen_rect;
- switch(pass)
- {
- case 0:
- screen_rect_offset.translate(-1.f, -1.f);
- break;
- case 1:
- screen_rect_offset.translate(1.f, -1.f);
- break;
- case 2:
- screen_rect_offset.translate(1.f, 1.f);
- break;
- case 3:
- screen_rect_offset.translate(-1.f, 1.f);
- break;
- case 4:
- screen_rect_offset.translate(0, -2.f);
- break;
- }
-
- renderQuad(screen_rect_offset, uv_rect, slant_offset);
+ switch(pass)
+ {
+ case 0:
+ screen_rect_offset.translate(-1.f, -1.f);
+ break;
+ case 1:
+ screen_rect_offset.translate(1.f, -1.f);
+ break;
+ case 2:
+ screen_rect_offset.translate(1.f, 1.f);
+ break;
+ case 3:
+ screen_rect_offset.translate(-1.f, 1.f);
+ break;
+ case 4:
+ screen_rect_offset.translate(0, -2.f);
+ break;
}
- gGL.color4fv(color.mV);
- renderQuad(screen_rect, uv_rect, slant_offset);
- }
- else if (shadow == DROP_SHADOW)
- {
- LLColor4 shadow_color = LLFontGL::sShadowColor;
- shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength;
- gGL.color4fv(shadow_color.mV);
- LLRectf screen_rect_shadow = screen_rect;
- screen_rect_shadow.translate(1.f, -1.f);
- renderQuad(screen_rect_shadow, uv_rect, slant_offset);
- gGL.color4fv(color.mV);
- renderQuad(screen_rect, uv_rect, slant_offset);
- }
- else // normal rendering
- {
- gGL.color4fv(color.mV);
- renderQuad(screen_rect, uv_rect, slant_offset);
+
+ renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_offset, uv_rect, shadow_color, slant_offset);
+ glyph_count++;
}
-
+ renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset);
+ glyph_count++;
+ }
+ else if (shadow == DROP_SHADOW)
+ {
+ LLColor4U shadow_color = LLFontGL::sShadowColor;
+ shadow_color.mV[VALPHA] = U8(color.mV[VALPHA] * drop_shadow_strength);
+ LLRectf screen_rect_shadow = screen_rect;
+ screen_rect_shadow.translate(1.f, -1.f);
+ renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_shadow, uv_rect, shadow_color, slant_offset);
+ glyph_count++;
+ renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset);
+ glyph_count++;
+ }
+ else // normal rendering
+ {
+ renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset);
+ glyph_count++;
}
- gGL.end();
}