Cleanup in llfontgl, as well as more aggressive bounds checking.

This commit is contained in:
Shyotl
2015-02-15 21:45:33 -06:00
parent 7c636c6c17
commit b7454f5f43
6 changed files with 78 additions and 140 deletions

View File

@@ -155,6 +155,12 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
return 0; return 0;
} }
if (max_chars == -1)
max_chars = S32_MAX;
const S32 max_index = llmin(begin_offset + max_chars, S32(wstr.length()));
if (max_index <= 0 || begin_offset >= max_index || max_pixels <= 0)
return 0;
gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX);
@@ -186,16 +192,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
S32 chars_drawn = 0; S32 chars_drawn = 0;
S32 i; S32 i;
S32 length; S32 length = max_index - begin_offset;
if (-1 == max_chars)
{
length = (S32)wstr.length() - begin_offset;
}
else
{
length = llmin((S32)wstr.length() - begin_offset, max_chars );
}
F32 cur_x, cur_y, cur_render_x, cur_render_y; F32 cur_x, cur_y, cur_render_x, cur_render_y;
@@ -256,7 +253,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
if (use_ellipses && halign == LEFT) if (use_ellipses && halign == LEFT)
{ {
// check for too long of a string // check for too long of a string
S32 string_width = llmath::llround(getWidthF32(wstr.c_str(), begin_offset, max_chars) * sScaleX); S32 string_width = llmath::llround(getWidthF32(wstr, begin_offset, max_chars) * sScaleX);
if (string_width > scaled_max_pixels) if (string_width > scaled_max_pixels)
{ {
// use four dots for ellipsis width to generate padding // use four dots for ellipsis width to generate padding
@@ -490,26 +487,11 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
return chars_drawn; return chars_drawn;
} }
S32 LLFontGL::render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const
{
return render(text, begin_offset, x, y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
}
S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const
{ {
return render(utf8str_to_wstring(text), begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses); return render(utf8str_to_wstring(text), begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses);
} }
S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const
{
return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
}
S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow) const
{
return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, halign, valign, style, shadow, S32_MAX, S32_MAX, NULL, FALSE);
}
// font metrics - override for LLFontFreetype that returns units of virtual pixels // font metrics - override for LLFontFreetype that returns units of virtual pixels
F32 LLFontGL::getAscenderHeight() const F32 LLFontGL::getAscenderHeight() const
{ {
@@ -526,66 +508,45 @@ F32 LLFontGL::getLineHeight() const
return (F32)llmath::llround(mFontFreetype->getLineHeight() / sScaleY); return (F32)llmath::llround(mFontFreetype->getLineHeight() / sScaleY);
} }
S32 LLFontGL::getWidth(const std::string& utf8text) const S32 LLFontGL::getWidth(const std::string& utf8text, const S32 begin_offset, const S32 max_chars, BOOL use_embedded) const
{ {
LLWString wtext = utf8str_to_wstring(utf8text); return getWidth(utf8str_to_wstring(utf8text), begin_offset, max_chars, use_embedded);
return getWidth(wtext.c_str(), 0, S32_MAX);
} }
S32 LLFontGL::getWidth(const llwchar* wchars) const S32 LLFontGL::getWidth(const LLWString& utf32text, const S32 begin_offset, const S32 max_chars, BOOL use_embedded) const
{ {
return getWidth(wchars, 0, S32_MAX); F32 width = getWidthF32(utf32text, begin_offset, max_chars, use_embedded);
}
S32 LLFontGL::getWidth(const std::string& utf8text, const S32 begin_offset, const S32 max_chars) const
{
LLWString wtext = utf8str_to_wstring(utf8text);
return getWidth(wtext.c_str(), begin_offset, max_chars);
}
S32 LLFontGL::getWidth(const llwchar* wchars, const S32 begin_offset, const S32 max_chars, BOOL use_embedded) const
{
F32 width = getWidthF32(wchars, begin_offset, max_chars, use_embedded);
return llmath::llround(width); return llmath::llround(width);
} }
F32 LLFontGL::getWidthF32(const std::string& utf8text) const F32 LLFontGL::getWidthF32(const std::string& utf8text, const S32 begin_offset, const S32 max_chars, BOOL use_embedded) const
{ {
LLWString wtext = utf8str_to_wstring(utf8text); return getWidthF32(utf8str_to_wstring(utf8text), begin_offset, max_chars, use_embedded);
return getWidthF32(wtext.c_str(), 0, S32_MAX);
} }
F32 LLFontGL::getWidthF32(const llwchar* wchars) const F32 LLFontGL::getWidthF32(const LLWString& utf32text, const S32 begin_offset, const S32 max_chars, BOOL use_embedded) const
{
return getWidthF32(wchars, 0, S32_MAX);
}
F32 LLFontGL::getWidthF32(const std::string& utf8text, const S32 begin_offset, const S32 max_chars ) const
{
LLWString wtext = utf8str_to_wstring(utf8text);
return getWidthF32(wtext.c_str(), begin_offset, max_chars);
}
F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S32 max_chars, BOOL use_embedded) const
{ {
const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL; const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL;
const S32 max_index = llmin(begin_offset + max_chars, S32(utf32text.length()));
if (max_index <= 0 || begin_offset >= max_index)
return 0;
F32 cur_x = 0; F32 cur_x = 0;
const S32 max_index = begin_offset + max_chars;
const LLFontGlyphInfo* next_glyph = NULL; const LLFontGlyphInfo* next_glyph = NULL;
F32 width_padding = 0.f; F32 width_padding = 0.f;
for (S32 i = begin_offset; i < max_index && wchars[i] != 0; i++) for (S32 i = begin_offset; i < max_index; i++)
{ {
const llwchar wch = wchars[i]; const llwchar wch = utf32text[i];
const embedded_data_t* ext_data = use_embedded ? getEmbeddedCharData(wch) : NULL; const embedded_data_t* ext_data = use_embedded ? getEmbeddedCharData(wch) : NULL;
if (ext_data) if (ext_data)
{ {
// Handle crappy embedded hack // Handle crappy embedded hack
cur_x += getEmbeddedCharAdvance(ext_data); cur_x += getEmbeddedCharAdvance(ext_data);
if( ((i+1) < max_chars) && (i+1 < max_index)) if( ((i+1) < max_index) && (i+1 < max_index))
{ {
cur_x += EXT_KERNING * sScaleX; cur_x += EXT_KERNING * sScaleX;
} }
@@ -609,15 +570,15 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S
(F32)(fgi->mWidth + fgi->mXBearing) - advance); // difference between width of this character and advance to next character (F32)(fgi->mWidth + fgi->mXBearing) - advance); // difference between width of this character and advance to next character
cur_x += advance; cur_x += advance;
llwchar next_char = wchars[i+1]; if ((i + 1) < max_index)
if (((i + 1) < begin_offset + max_chars)
&& next_char
&& (next_char < LAST_CHARACTER))
{ {
// Kern this puppy. llwchar next_char = utf32text[i+1];
next_glyph = mFontFreetype->getGlyphInfo(next_char); if (next_char < LAST_CHARACTER)
cur_x += mFontFreetype->getXKerning(fgi, next_glyph); {
// Kern this puppy.
next_glyph = mFontFreetype->getGlyphInfo(next_char);
cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
}
} }
// Round after kerning. // Round after kerning.
cur_x = (F32)llmath::llround(cur_x); cur_x = (F32)llmath::llround(cur_x);
@@ -633,20 +594,13 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S
// Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels // Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels
S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars, S32 LLFontGL::maxDrawableChars(const LLWString& utf32text, F32 max_pixels, S32 max_chars,
EWordWrapStyle end_on_word_boundary, const BOOL use_embedded, EWordWrapStyle end_on_word_boundary, const BOOL use_embedded,
F32* drawn_pixels) const F32* drawn_pixels) const
{ {
if (!wchars || !wchars[0] || max_chars == 0) const S32 max_index = llmin(max_chars, S32(utf32text.length()));
{ if (max_index <= 0 || max_pixels <= 0.f)
return 0; return 0;
}
//llassert(max_pixels >= 0.f);
//llassert(max_chars >= 0);
if(max_pixels < 0.f || max_chars < 0) {
return 0;
}
BOOL clip = FALSE; BOOL clip = FALSE;
F32 cur_x = 0; F32 cur_x = 0;
@@ -662,15 +616,9 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
LLFontGlyphInfo* next_glyph = NULL; LLFontGlyphInfo* next_glyph = NULL;
S32 i; S32 i;
for (i=0; (i < max_chars); i++) for (i=0; (i < max_index); i++)
{ {
llwchar wch = wchars[i]; llwchar wch = utf32text[i];
if(wch == 0)
{
// Null terminator. We're done.
break;
}
const embedded_data_t* ext_data = use_embedded ? getEmbeddedCharData(wch) : NULL; const embedded_data_t* ext_data = use_embedded ? getEmbeddedCharData(wch) : NULL;
if (ext_data) if (ext_data)
@@ -691,7 +639,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
break; break;
} }
if (((i+1) < max_chars) && wchars[i+1]) if ((i+1) < max_index)
{ {
cur_x += EXT_KERNING * sScaleX; cur_x += EXT_KERNING * sScaleX;
} }
@@ -741,10 +689,10 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
break; break;
} }
if (((i+1) < max_chars) && wchars[i+1]) if ((i+1) < max_index)
{ {
// Kern this puppy. // Kern this puppy.
next_glyph = mFontFreetype->getGlyphInfo(wchars[i+1]); next_glyph = mFontFreetype->getGlyphInfo(utf32text[i + 1]);
cur_x += mFontFreetype->getXKerning(fgi, next_glyph); cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
} }
} }
@@ -782,22 +730,21 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
} }
S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos, S32 max_chars) const S32 LLFontGL::firstDrawableChar(const LLWString& utf32text, F32 max_pixels, S32 start_pos, S32 max_chars) const
{ {
if (!wchars || !wchars[0] || max_chars == 0) const S32 max_index = llmin(max_chars, S32(utf32text.length()));
{ if (max_index <= 0 || start_pos >= max_index || max_pixels <= 0.f || start_pos < 0)
return 0; return 0;
}
F32 total_width = 0.0; F32 total_width = 0.0;
S32 drawable_chars = 0; S32 drawable_chars = 0;
F32 scaled_max_pixels = max_pixels * sScaleX; F32 scaled_max_pixels = max_pixels * sScaleX;
S32 start = llmin(start_pos, text_len - 1); S32 start = llmin(start_pos, max_index - 1);
for (S32 i = start; i >= 0; i--) for (S32 i = start; i >= 0; i--)
{ {
llwchar wch = wchars[i]; llwchar wch = utf32text[i];
const embedded_data_t* ext_data = getEmbeddedCharData(wch); const embedded_data_t* ext_data = getEmbeddedCharData(wch);
F32 width = 0; F32 width = 0;
@@ -825,7 +772,7 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
total_width += width; total_width += width;
drawable_chars++; drawable_chars++;
if( max_chars >= 0 && drawable_chars >= max_chars ) if( max_index >= 0 && drawable_chars >= max_index )
{ {
break; break;
} }
@@ -833,7 +780,7 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
if ( i > 0 ) if ( i > 0 )
{ {
// kerning // kerning
total_width += ext_data ? (EXT_KERNING * sScaleX) : mFontFreetype->getXKerning(wchars[i-1], wch); total_width += ext_data ? (EXT_KERNING * sScaleX) : mFontFreetype->getXKerning(utf32text[i - 1], wch);
} }
// Round after kerning. // Round after kerning.
@@ -854,20 +801,16 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
} }
S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset, F32 target_x, F32 max_pixels, S32 max_chars, BOOL round, BOOL use_embedded) const S32 LLFontGL::charFromPixelOffset(const LLWString& utf32text, const S32 begin_offset, F32 target_x, F32 max_pixels, S32 max_chars, BOOL round, BOOL use_embedded) const
{ {
if (!wchars || !wchars[0] || max_chars == 0) const S32 max_index = llmin(begin_offset + max_chars, S32(utf32text.length()));
{ if (max_index <= 0 || begin_offset >= max_index || max_pixels <= 0.f)
return 0; return 0;
}
F32 cur_x = 0; F32 cur_x = 0;
target_x *= sScaleX; target_x *= sScaleX;
// max_chars is S32_MAX by default, so make sure we don't get overflow
const S32 max_index = begin_offset + llmin(S32_MAX - begin_offset, max_chars);
F32 scaled_max_pixels = max_pixels * sScaleX; F32 scaled_max_pixels = max_pixels * sScaleX;
const LLFontGlyphInfo* next_glyph = NULL; const LLFontGlyphInfo* next_glyph = NULL;
@@ -875,7 +818,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset,
S32 pos; S32 pos;
for (pos = begin_offset; pos < max_index; pos++) for (pos = begin_offset; pos < max_index; pos++)
{ {
llwchar wch = wchars[pos]; llwchar wch = utf32text[pos];
if (!wch) if (!wch)
{ {
break; // done break; // done
@@ -912,8 +855,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset,
cur_x += char_width; cur_x += char_width;
if (((pos + 1) < max_index) if ((pos + 1) < max_index)
&& (wchars[(pos + 1)]))
{ {
if(ext_data) if(ext_data)
@@ -922,7 +864,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset,
} }
else else
{ {
next_glyph = mFontFreetype->getGlyphInfo(wchars[pos + 1]); next_glyph = mFontFreetype->getGlyphInfo(utf32text[pos + 1]);
cur_x += mFontFreetype->getXKerning(glyph, next_glyph); cur_x += mFontFreetype->getXKerning(glyph, next_glyph);
} }
} }
@@ -933,7 +875,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset,
} }
return llmin(max_chars, pos - begin_offset); return pos - begin_offset;
} }
const LLFontDescriptor& LLFontGL::getFontDesc() const const LLFontDescriptor& LLFontGL::getFontDesc() const

View File

@@ -111,27 +111,19 @@ public:
BOOL use_embedded = FALSE, BOOL use_embedded = FALSE,
BOOL use_ellipses = FALSE) const; BOOL use_ellipses = FALSE) const;
S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const;
// renderUTF8 does a conversion, so is slower! // renderUTF8 does a conversion, so is slower!
S32 renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const; S32 renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign = LEFT, VAlign valign = BASELINE, U8 style = NORMAL, ShadowType shadow = NO_SHADOW, S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX, F32* right_x = NULL, BOOL use_ellipses = FALSE) const;
S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const;
S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const;
// font metrics - override for LLFont that returns units of virtual pixels // font metrics - override for LLFont that returns units of virtual pixels
F32 getAscenderHeight() const; F32 getAscenderHeight() const;
F32 getDescenderHeight() const; F32 getDescenderHeight() const;
F32 getLineHeight() const; F32 getLineHeight() const;
S32 getWidth(const std::string& utf8text) const; S32 getWidth(const std::string& utf8str, const S32 offset = 0, const S32 max_chars = S32_MAX, BOOL use_embedded = FALSE) const;
S32 getWidth(const llwchar* wchars) const; S32 getWidth(const LLWString& utf32str, const S32 offset = 0, const S32 max_chars = S32_MAX, BOOL use_embedded = FALSE) const;
S32 getWidth(const std::string& utf8text, const S32 offset, const S32 max_chars ) const;
S32 getWidth(const llwchar* wchars, const S32 offset, const S32 max_chars, BOOL use_embedded = FALSE) const;
F32 getWidthF32(const std::string& utf8text) const; F32 getWidthF32(const std::string& utf8str, const S32 offset = 0, const S32 max_chars = S32_MAX, BOOL use_embedded = FALSE) const;
F32 getWidthF32(const llwchar* wchars) const; F32 getWidthF32(const LLWString& utf32str, const S32 offset = 0, const S32 max_chars = S32_MAX, BOOL use_embedded = FALSE) const;
F32 getWidthF32(const std::string& text, const S32 offset, const S32 max_chars ) const;
F32 getWidthF32(const llwchar* wchars, const S32 offset, const S32 max_chars, BOOL use_embedded = FALSE ) const;
// The following are called often, frequently with large buffers, so do not use a string interface // The following are called often, frequently with large buffers, so do not use a string interface
@@ -142,15 +134,15 @@ public:
WORD_BOUNDARY_IF_POSSIBLE, WORD_BOUNDARY_IF_POSSIBLE,
ANYWHERE ANYWHERE
} EWordWrapStyle ; } EWordWrapStyle ;
S32 maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars = S32_MAX, EWordWrapStyle end_on_word_boundary = ANYWHERE, S32 maxDrawableChars(const LLWString& utf32str, F32 max_pixels = F32_MAX, S32 max_chars = S32_MAX, EWordWrapStyle end_on_word_boundary = ANYWHERE,
const BOOL use_embedded = FALSE, F32* drawn_pixels = NULL) const; const BOOL use_embedded = FALSE, F32* drawn_pixels = NULL) const;
// Returns the index of the first complete characters from text that can be drawn in max_pixels // Returns the index of the first complete characters from text that can be drawn in max_pixels
// given that the character at start_pos should be the last character (or as close to last as possible). // given that the character at start_pos should be the last character (or as close to last as possible).
S32 firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos=S32_MAX, S32 max_chars = S32_MAX) const; S32 firstDrawableChar(const LLWString& utf32str, F32 max_pixels = F32_MAX, S32 start_pos = S32_MAX, S32 max_chars = S32_MAX) const;
// Returns the index of the character closest to pixel position x (ignoring text to the right of max_pixels and max_chars) // Returns the index of the character closest to pixel position x (ignoring text to the right of max_pixels and max_chars)
S32 charFromPixelOffset(const llwchar* wchars, const S32 char_offset, F32 x, F32 max_pixels=F32_MAX, S32 max_chars = S32_MAX, BOOL round = TRUE, BOOL use_embedded = FALSE) const; S32 charFromPixelOffset(const LLWString& utf32str, const S32 char_offset, F32 x, F32 max_pixels = F32_MAX, S32 max_chars = S32_MAX, BOOL round = TRUE, BOOL use_embedded = FALSE) const;
const LLFontDescriptor& getFontDesc() const; const LLFontDescriptor& getFontDesc() const;

View File

@@ -396,15 +396,16 @@ void LLLineEditor::setCursor( S32 pos )
S32 pixels_after_scroll = findPixelNearestPos(); S32 pixels_after_scroll = findPixelNearestPos();
if( pixels_after_scroll > mMaxHPixels ) if( pixels_after_scroll > mMaxHPixels )
{ {
S32 width_chars_to_left = mGLFont->getWidth(mText.getWString().c_str(), 0, mScrollHPos); const LLWString& utf32text = mText.getWString();
S32 last_visible_char = mGLFont->maxDrawableChars(mText.getWString().c_str(), llmax(0.f, (F32)(mMaxHPixels - mMinHPixels + width_chars_to_left))); S32 width_chars_to_left = mGLFont->getWidth(utf32text, 0, mScrollHPos);
S32 last_visible_char = mGLFont->maxDrawableChars(utf32text, llmax(0.f, (F32)(mMaxHPixels - mMinHPixels + width_chars_to_left)));
// character immediately to left of cursor should be last one visible (SCROLL_INCREMENT_ADD will scroll in more characters) // character immediately to left of cursor should be last one visible (SCROLL_INCREMENT_ADD will scroll in more characters)
// or first character if cursor is at beginning // or first character if cursor is at beginning
S32 new_last_visible_char = llmax(0, getCursor() - 1); S32 new_last_visible_char = llmax(0, getCursor() - 1);
S32 min_scroll = mGLFont->firstDrawableChar(mText.getWString().c_str(), (F32)(mMaxHPixels - mMinHPixels - UI_LINEEDITOR_CURSOR_THICKNESS - UI_LINEEDITOR_H_PAD), mText.length(), new_last_visible_char); S32 min_scroll = mGLFont->firstDrawableChar(utf32text, (F32)(mMaxHPixels - mMinHPixels - UI_LINEEDITOR_CURSOR_THICKNESS - UI_LINEEDITOR_H_PAD), new_last_visible_char);
if (old_cursor_pos == last_visible_char) if (old_cursor_pos == last_visible_char)
{ {
mScrollHPos = llmin(mText.length(), llmax(min_scroll, mScrollHPos + SCROLL_INCREMENT_ADD)); mScrollHPos = llmin(utf32text.length(), LLWString::size_type(llmax(min_scroll, mScrollHPos + SCROLL_INCREMENT_ADD)));
} }
else else
{ {

View File

@@ -564,8 +564,9 @@ void LLMenuItemGL::draw( void )
std::string::size_type offset = upper_case_label.find(mJumpKey); std::string::size_type offset = upper_case_label.find(mJumpKey);
if (offset != std::string::npos) if (offset != std::string::npos)
{ {
S32 x_begin = LEFT_PLAIN_PIXELS + mFont->getWidth(mLabel, 0, offset); const LLWString& utf32text = mLabel.getWString();
S32 x_end = LEFT_PLAIN_PIXELS + mFont->getWidth(mLabel, 0, offset + 1); S32 x_begin = LEFT_PLAIN_PIXELS + mFont->getWidth(utf32text, 0, offset);
S32 x_end = LEFT_PLAIN_PIXELS + mFont->getWidth(utf32text, 0, offset + 1);
gl_line_2d(x_begin, (MENU_ITEM_PADDING / 2) + 1, x_end, (MENU_ITEM_PADDING / 2) + 1); gl_line_2d(x_begin, (MENU_ITEM_PADDING / 2) + 1, x_end, (MENU_ITEM_PADDING / 2) + 1);
} }
} }
@@ -1826,9 +1827,10 @@ void LLMenuItemBranchDownGL::draw( void )
std::string::size_type offset = upper_case_label.find(getJumpKey()); std::string::size_type offset = upper_case_label.find(getJumpKey());
if (offset != std::string::npos) if (offset != std::string::npos)
{ {
S32 x_offset = llmath::llround((F32)getRect().getWidth() / 2.f - getFont()->getWidthF32(mLabel.getString(), 0, S32_MAX) / 2.f); const LLWString& utf32text = mLabel.getWString();
S32 x_begin = x_offset + getFont()->getWidth(mLabel, 0, offset); S32 x_offset = llmath::llround((F32)getRect().getWidth() / 2.f - getFont()->getWidthF32(utf32text, 0, S32_MAX) / 2.f);
S32 x_end = x_offset + getFont()->getWidth(mLabel, 0, offset + 1); S32 x_begin = x_offset + getFont()->getWidth(utf32text, 0, offset);
S32 x_end = x_offset + getFont()->getWidth(utf32text, 0, offset + 1);
gl_line_2d(x_begin, LABEL_BOTTOM_PAD_PIXELS, x_end, LABEL_BOTTOM_PAD_PIXELS); gl_line_2d(x_begin, LABEL_BOTTOM_PAD_PIXELS, x_end, LABEL_BOTTOM_PAD_PIXELS);
} }
} }

View File

@@ -572,7 +572,7 @@ S32 LLScrollListCtrl::calcMaxContentWidth()
{ {
mColumnWidthsDirty = false; mColumnWidthsDirty = false;
// update max content width for this column, by looking at all items // update max content width for this column, by looking at all items
column->mMaxContentWidth = column->mHeader ? LLFontGL::getFontSansSerifSmall()->getWidth(column->mLabel) + mColumnPadding + HEADING_TEXT_PADDING : 0; column->mMaxContentWidth = column->mHeader ? LLFontGL::getFontSansSerifSmall()->getWidth(column->mLabel.getWString()) + mColumnPadding + HEADING_TEXT_PADDING : 0;
item_list::iterator iter; item_list::iterator iter;
for (iter = mItemList.begin(); iter != mItemList.end(); iter++) for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
{ {

View File

@@ -3462,12 +3462,12 @@ void LLTextEditor::drawText()
{ {
const LLFontGL *num_font = LLFontGL::getFontMonospace(); const LLFontGL *num_font = LLFontGL::getFontMonospace();
F32 y_top = text_y + ((F32)llmath::llround(num_font->getLineHeight()) / 2); F32 y_top = text_y + ((F32)llmath::llround(num_font->getLineHeight()) / 2);
const LLWString ltext = utf8str_to_wstring(llformat("%*d", UI_TEXTEDITOR_LINE_NUMBER_DIGITS, cur_line_num ));
BOOL is_cur_line = getCurrentLine() == cur_line_num; BOOL is_cur_line = getCurrentLine() == cur_line_num;
const U8 style = is_cur_line ? LLFontGL::BOLD : LLFontGL::NORMAL; const U8 style = is_cur_line ? LLFontGL::BOLD : LLFontGL::NORMAL;
const LLColor4 fg_color = is_cur_line ? mCursorColor : mReadOnlyFgColor; const LLColor4 fg_color = is_cur_line ? mCursorColor : mReadOnlyFgColor;
num_font->render(
ltext, // string to draw num_font->renderUTF8(
llformat("%*d", UI_TEXTEDITOR_LINE_NUMBER_DIGITS, cur_line_num), // string to draw
0, // begin offset 0, // begin offset
3., // x 3., // x
y_top, // y y_top, // y
@@ -3477,7 +3477,8 @@ void LLTextEditor::drawText()
style, style,
LLFontGL::NO_SHADOW, LLFontGL::NO_SHADOW,
S32_MAX, // max chars S32_MAX, // max chars
UI_TEXTEDITOR_LINE_NUMBER_MARGIN); // max pixels UI_TEXTEDITOR_LINE_NUMBER_MARGIN,
NULL); // max pixels
} }
S32 seg_start = line_start; S32 seg_start = line_start;