Merge remote-tracking branch 'singu/master'

This commit is contained in:
Aleric Inglewood
2013-11-20 15:13:25 +01:00
11 changed files with 392 additions and 359 deletions

View File

@@ -98,9 +98,7 @@ LLFontGlyphInfo::LLFontGlyphInfo(U32 index)
mYBitmapOffset(0), // Offset to the origin in the bitmap
mXBearing(0), // Distance from baseline to left in pixels
mYBearing(0), // Distance from baseline to top in pixels
mBitmapNum(0), // Which bitmap in the bitmap cache contains this glyph
mIsRendered(FALSE),
mMetricsValid(FALSE)
mBitmapNum(0) // Which bitmap in the bitmap cache contains this glyph
{
}
@@ -239,16 +237,12 @@ F32 LLFontFreetype::getXAdvance(const llwchar wch) const
if (mFTFace == NULL)
return 0.0;
llassert(!mIsFallback);
//U32 glyph_index;
// Return existing info only if it is current
LLFontGlyphInfo* gi = getGlyphInfo(wch);
if (gi && gi->mMetricsValid)
if (gi)
{
return gi->mXAdvance;
}
//new
else
{
char_glyph_info_map_t::iterator found_it = mCharGlyphInfoMap.find((llwchar)0);
@@ -257,73 +251,29 @@ F32 LLFontFreetype::getXAdvance(const llwchar wch) const
return found_it->second->mXAdvance;
}
}
/*const LLFontFreetype* fontp = this;
// Initialize char to glyph map
glyph_index = FT_Get_Char_Index(mFTFace, wch);
if (glyph_index == 0)
{
font_vector_t::const_iterator iter;
for(iter = mFallbackFonts.begin(); iter != mFallbackFonts.end(); iter++)
{
glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch);
if (glyph_index)
{
fontp = *iter;
}
}
}
if (glyph_index)
{
// This font has this glyph
fontp->renderGlyph(glyph_index);
// Create the entry if it's not there
char_glyph_info_map_t::iterator iter2 = mCharGlyphInfoMap.find(wch);
if (iter2 == mCharGlyphInfoMap.end())
{
gi = new LLFontGlyphInfo(glyph_index);
insertGlyphInfo(wch, gi);
}
else
{
gi = iter2->second;
}
gi->mWidth = fontp->mFTFace->glyph->bitmap.width;
gi->mHeight = fontp->mFTFace->glyph->bitmap.rows;
// Convert these from 26.6 units to float pixels.
gi->mXAdvance = fontp->mFTFace->glyph->advance.x / 64.f;
gi->mYAdvance = fontp->mFTFace->glyph->advance.y / 64.f;
gi->mMetricsValid = TRUE;
//gi->mIsRendered = TRUE;
return gi->mXAdvance;
}
else
{
gi = get_if_there(mCharGlyphInfoMap, (llwchar)0, (LLFontGlyphInfo*)NULL);
if (gi)
{
return gi->mXAdvance;
}
}*/
// Last ditch fallback - no glyphs defined at all.
return (F32)mFontBitmapCachep->getMaxCharWidth();
}
F32 LLFontFreetype::getXKerning(const llwchar char_left, const llwchar char_right) const
F32 LLFontFreetype::getXAdvance(const LLFontGlyphInfo* glyph) const
{
if (mFTFace == NULL)
return 0.0;
llassert(!mIsFallback);
LLFontGlyphInfo* left_glyph_info = get_if_there(mCharGlyphInfoMap, char_left, (LLFontGlyphInfo*)NULL);
return glyph->mXAdvance;
}
F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
{
if (mFTFace == NULL)
return 0.0;
//llassert(!mIsFallback);
LLFontGlyphInfo* left_glyph_info = getGlyphInfo(char_left);;
U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0;
// Kern this puppy.
LLFontGlyphInfo* right_glyph_info = get_if_there(mCharGlyphInfoMap, char_right, (LLFontGlyphInfo*)NULL);
LLFontGlyphInfo* right_glyph_info = getGlyphInfo(char_right);
U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0;
FT_Vector delta;
@@ -333,22 +283,28 @@ F32 LLFontFreetype::getXKerning(const llwchar char_left, const llwchar char_righ
return delta.x*(1.f/64.f);
}
BOOL LLFontFreetype::hasGlyph(const llwchar wch) const
F32 LLFontFreetype::getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const
{
if (mFTFace == NULL)
return 0.0;
U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0;
U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0;
FT_Vector delta;
llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta));
return delta.x*(1.f/64.f);
}
BOOL LLFontFreetype::hasGlyph(llwchar wch) const
{
llassert(!mIsFallback);
return(mCharGlyphInfoMap.find(wch) != mCharGlyphInfoMap.end());
/*const LLFontGlyphInfo* gi = getGlyphInfo(wch);
if (gi && gi->mIsRendered)
{
return TRUE;
}
else
{
return FALSE;
}*/
}
BOOL LLFontFreetype::addGlyph(const llwchar wch) const
LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch) const
{
if (mFTFace == NULL)
return FALSE;
@@ -369,24 +325,23 @@ BOOL LLFontFreetype::addGlyph(const llwchar wch) const
glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch);
if (glyph_index)
{
addGlyphFromFont(*iter, wch, glyph_index);
return TRUE;
return addGlyphFromFont(*iter, wch, glyph_index);
}
}
}
char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch);
if (iter == mCharGlyphInfoMap.end() || !(iter->second->mIsRendered))
if (iter == mCharGlyphInfoMap.end())
{
return addGlyphFromFont(this, wch, glyph_index);
}
return FALSE;
return NULL;
}
BOOL LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, const llwchar wch, const U32 glyph_index) const
LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const
{
if (mFTFace == NULL)
return FALSE;
return NULL;
//llassert(!mIsFallback);
fontp->renderGlyph(glyph_index);
@@ -409,8 +364,6 @@ BOOL LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, const llwchar
// Convert these from 26.6 units to float pixels.
gi->mXAdvance = fontp->mFTFace->glyph->advance.x / 64.f;
gi->mYAdvance = fontp->mFTFace->glyph->advance.y / 64.f;
gi->mIsRendered = TRUE;
gi->mMetricsValid = TRUE;
insertGlyphInfo(wch, gi);
@@ -481,31 +434,25 @@ BOOL LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, const llwchar
// omit it from the font-image.
}
//new
LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_num);
LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num);
image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight());
return TRUE;
return gi;
}
LLFontGlyphInfo* LLFontFreetype::getGlyphInfo(const llwchar wch) const
LLFontGlyphInfo* LLFontFreetype::getGlyphInfo(llwchar wch) const
{
char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch);
if (iter != mCharGlyphInfoMap.end())
{
return iter->second;
}
else if(addGlyph(wch))//new
else
{
// this glyph doesn't yet exist, so render it and return the result
char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch);
if (iter != mCharGlyphInfoMap.end())
{
return iter->second;
}
return addGlyph(wch);
}
return NULL;
}
void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const
@@ -536,7 +483,6 @@ void LLFontFreetype::renderGlyph(const U32 glyph_index) const
void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)
{
//new
resetBitmapCache();
loadFace(mName,mPointSize,vert_dpi,horz_dpi,mFontBitmapCachep->getNumComponents(),mIsFallback);
if (!mIsFallback)
@@ -557,21 +503,10 @@ void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)
}
}
}
//resetBitmapCache();
}
void LLFontFreetype::resetBitmapCache()
{
// Iterate through glyphs and clear the mIsRendered flag
/*for (char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.begin();
iter != mCharGlyphInfoMap.end(); ++iter)
{
iter->second->mIsRendered = FALSE;
//FIXME: this is only strictly necessary when resetting the entire font,
//not just flushing the bitmap
iter->second->mMetricsValid = FALSE;
}*/
//new
for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer());
mCharGlyphInfoMap.clear();

View File

@@ -27,7 +27,7 @@
#ifndef LL_LLFONTFREETYPE_H
#define LL_LLFONTFREETYPE_H
#include <map>
#include <boost/unordered_map.hpp>
#include "llpointer.h"
#include "llstl.h"
@@ -67,10 +67,8 @@ struct LLFontGlyphInfo
S32 mHeight; // In pixels
F32 mXAdvance; // In pixels
F32 mYAdvance; // In pixels
BOOL mMetricsValid; // We have up-to-date metrics for this glyph
// Information for actually rendering
BOOL mIsRendered; // We actually have rendered this glyph
S32 mXBitmapOffset; // Offset to the origin in the bitmap
S32 mYBitmapOffset; // Offset to the origin in the bitmap
S32 mXBearing; // Distance from baseline to left in pixels
@@ -129,9 +127,10 @@ public:
LAST_CHAR_FULL = 255
};
const LLFontGlyphInfo &getMetrics(const llwchar wc) const;
F32 getXAdvance(const llwchar wc) const;
F32 getXKerning(const llwchar char_left, const llwchar char_right) const; // Get the kerning between the two characters
F32 getXAdvance(llwchar wc) const;
F32 getXAdvance(const LLFontGlyphInfo* glyph) const;
F32 getXKerning(llwchar char_left, llwchar char_right) const; // Get the kerning between the two characters
F32 getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const; // Get the kerning between the two characters
LLFontGlyphInfo* getGlyphInfo(const llwchar wch) const;
void reset(F32 vert_dpi, F32 horz_dpi);
@@ -147,13 +146,10 @@ public:
private:
void resetBitmapCache();
void setSubImageLuminanceAlpha(const U32 x, const U32 y, const U32 bitmap_num, const U32 width, const U32 height, const U8 *data, S32 stride = 0) const;
public:
BOOL hasGlyph(const llwchar wch) const; // Has a glyph for this character
BOOL addGlyph(const llwchar wch) const; // Add a new character to the font if necessary
private:
BOOL addGlyphFromFont(const LLFontFreetype *fontp, const llwchar wch, const U32 glyph_index) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found)
void renderGlyph(const U32 glyph_index) const;
BOOL hasGlyph(llwchar wch) const; // Has a glyph for this character
LLFontGlyphInfo* addGlyph(llwchar wch) const; // Add a new character to the font if necessary
LLFontGlyphInfo* addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found)
void renderGlyph(U32 glyph_index) const;
void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const;
std::string mName;
@@ -170,7 +166,7 @@ private:
BOOL mValid;
typedef std::map<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t;
typedef boost::unordered_map<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t;
mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap
mutable LLPointer<LLFontBitmapCache> mFontBitmapCachep;

View File

@@ -150,7 +150,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
return wstr.length() ;
}
if (wstr.empty())
if (wstr.empty() || !max_pixels)
{
return 0;
}
@@ -266,10 +266,17 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
}
}
const LLFontGlyphInfo* next_glyph = NULL;
// Remember last-used texture to avoid unnecesssary bind calls.
LLImageGL *last_bound_texture = NULL;
const S32 GLYPH_BATCH_SIZE = 30;
static LL_ALIGN_16(LLVector4a vertices[GLYPH_BATCH_SIZE * 4]);
static LLVector2 uvs[GLYPH_BATCH_SIZE * 4];
static 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];
@@ -298,11 +305,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
break;
}
if (last_bound_texture != ext_image)
{
gGL.getTexUnit(0)->bind(ext_image);
last_bound_texture = ext_image;
}
gGL.getTexUnit(0)->bind(ext_image);
// snap origin to whole screen pixel
const F32 ext_x = (F32)llround(cur_render_x + (EXT_X_BEARING * sScaleX));
@@ -310,7 +313,23 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
LLRectf uv_rect(0.f, 1.f, 1.f, 0.f);
LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y);
drawGlyph(screen_rect, uv_rect, LLColor4::white, style, shadow, drop_shadow_strength);
if (glyph_count > 0)
{
gGL.begin(LLRender::QUADS);
{
gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4);
}
gGL.end();
glyph_count = 0;
}
renderQuad(vertices, uvs, colors, screen_rect, uv_rect, LLColor4U::white, 0);
//No batching here. It will never happen.
gGL.begin(LLRender::QUADS);
{
gGL.vertexBatchPreTransformed(vertices, uvs, colors, 4);
}
gGL.end();
if (!label.empty())
{
@@ -319,13 +338,11 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
/*llfloor*/(ext_x / sScaleX) + ext_image->getWidth() + EXT_X_BEARING - sCurOrigin.mX,
/*llfloor*/(cur_render_y / sScaleY) - sCurOrigin.mY,
color,
halign, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL,
halign, BASELINE, UNDERLINE, NO_SHADOW, S32_MAX, S32_MAX, NULL,
TRUE );
gGL.popMatrix();
}
gGL.color4fv(color.mV);
chars_drawn++;
cur_x += ext_advance;
if (((i + 1) < length) && wstr[i+1])
@@ -336,24 +353,36 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
}
else
{
//new
/*if (!mFontFreetype->hasGlyph(wch))
const LLFontGlyphInfo* fgi = next_glyph;
next_glyph = NULL;
if(!fgi)
{
addChar(wch);
}*/
const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
fgi = mFontFreetype->getGlyphInfo(wch);
}
if (!fgi)
{
llerrs << "Missing Glyph Info" << llendl;
break;
}
// Per-glyph bitmap texture.
LLImageGL *image_gl = font_bitmap_cache->getImageGL(fgi->mBitmapNum);
if (last_bound_texture != image_gl)
S32 next_bitmap_num = fgi->mBitmapNum;
if (next_bitmap_num != bitmap_num)
{
gGL.getTexUnit(0)->bind(image_gl);
last_bound_texture = image_gl;
// 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))
@@ -368,13 +397,24 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
(fgi->mYBitmapOffset + fgi->mHeight + PAD_UVY) * inv_height,
(fgi->mXBitmapOffset + fgi->mWidth) * inv_width,
(fgi->mYBitmapOffset - PAD_UVY) * inv_height);
// snap glyph origin to whole screen pixel
LLRectf screen_rect((F32)llround(cur_render_x + (F32)fgi->mXBearing),
// snap glyph origin to whole screen pixel
LLRectf screen_rect((F32)llround(cur_render_x + (F32)fgi->mXBearing),
(F32)llround(cur_render_y + (F32)fgi->mYBearing),
(F32)llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth,
(F32)llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight);
drawGlyph(screen_rect, uv_rect, color, style, 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, shadow, drop_shadow_strength);
chars_drawn++;
cur_x += fgi->mXAdvance;
@@ -384,13 +424,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
if (next_char && (next_char < LAST_CHARACTER))
{
// Kern this puppy.
//new
/*if (!mFontFreetype->hasGlyph(next_char))
{
addChar(next_char);
}*/
mFontFreetype->getGlyphInfo(next_char);
cur_x += mFontFreetype->getXKerning(wch, next_char);
next_glyph = mFontFreetype->getGlyphInfo(next_char);
cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
}
// Round after kerning.
@@ -405,6 +440,16 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
}
}
if(glyph_count)
{
gGL.begin(LLRender::QUADS);
{
gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4);
}
gGL.end();
}
if (right_x)
{
*right_x = (cur_x - origin.mV[VX]) / sScaleX;
@@ -527,13 +572,13 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S
F32 cur_x = 0;
const S32 max_index = begin_offset + max_chars;
for (S32 i = begin_offset; i < max_index; i++)
const LLFontGlyphInfo* next_glyph = NULL;
F32 width_padding = 0.f;
for (S32 i = begin_offset; i < max_index && wchars[i] != 0; i++)
{
const llwchar wch = wchars[i];
if (wch == 0)
{
break; // done
}
const embedded_data_t* ext_data = use_embedded ? getEmbeddedCharData(wch) : NULL;
if (ext_data)
{
@@ -547,7 +592,23 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S
}
else
{
cur_x += mFontFreetype->getXAdvance(wch);
const LLFontGlyphInfo* fgi = next_glyph;
next_glyph = NULL;
if(!fgi)
{
fgi = mFontFreetype->getGlyphInfo(wch);
}
F32 advance = mFontFreetype->getXAdvance(fgi);
// for the last character we want to measure the greater of its width and xadvance values
// so keep track of the difference between these values for the each character we measure
// so we can fix things up at the end
width_padding = llmax( 0.f, // always use positive padding amount
width_padding - advance, // previous padding left over after advance of current character
(F32)(fgi->mWidth + fgi->mXBearing) - advance); // difference between width of this character and advance to next character
cur_x += advance;
llwchar next_char = wchars[i+1];
if (((i + 1) < begin_offset + max_chars)
@@ -555,13 +616,17 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S
&& (next_char < LAST_CHARACTER))
{
// Kern this puppy.
cur_x += mFontFreetype->getXKerning(wch, next_char);
next_glyph = mFontFreetype->getGlyphInfo(next_char);
cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
}
// Round after kerning.
cur_x = (F32)llround(cur_x);
}
// Round after kerning.
cur_x = (F32)llround(cur_x);
}
// add in extra pixels for last character's width past its xadvance
cur_x += width_padding;
return cur_x / sScaleX;
}
@@ -590,7 +655,11 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
S32 start_of_last_word = 0;
BOOL in_word = FALSE;
F32 scaled_max_pixels = (F32)llceil(max_pixels * sScaleX);
// avoid S32 overflow when max_pixels == S32_MAX by staying in floating point
F32 scaled_max_pixels = max_pixels * sScaleX;
F32 width_padding = 0.f;
LLFontGlyphInfo* next_glyph = NULL;
S32 i;
for (i=0; (i < max_chars); i++)
@@ -651,9 +720,22 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
}
}
cur_x += mFontFreetype->getXAdvance(wch);
if (scaled_max_pixels < cur_x)
LLFontGlyphInfo* fgi = next_glyph;
next_glyph = NULL;
if(!fgi)
{
fgi = mFontFreetype->getGlyphInfo(wch);
}
// account for glyphs that run beyond the starting point for the next glyphs
width_padding = llmax( 0.f, // always use positive padding amount
width_padding - fgi->mXAdvance, // previous padding left over after advance of current character
(F32)(fgi->mWidth + fgi->mXBearing) - fgi->mXAdvance); // difference between width of this character and advance to next character
cur_x += fgi->mXAdvance;
// clip if current character runs past scaled_max_pixels (using width_padding)
if (scaled_max_pixels < cur_x + width_padding)
{
clip = TRUE;
break;
@@ -662,7 +744,8 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
if (((i+1) < max_chars) && wchars[i+1])
{
// Kern this puppy.
cur_x += mFontFreetype->getXKerning(wch, wchars[i+1]);
next_glyph = mFontFreetype->getGlyphInfo(wchars[i+1]);
cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
}
}
// Round after kerning.
@@ -717,34 +800,29 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
llwchar wch = wchars[i];
const embedded_data_t* ext_data = getEmbeddedCharData(wch);
F32 char_width = 0;
F32 width = 0;
if(ext_data)
{
char_width = getEmbeddedCharAdvance(ext_data);
width = getEmbeddedCharAdvance(ext_data);
}
else
{
//new
const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
// last character uses character width, since the whole character needs to be visible
// other characters just use advance
char_width = (i == start)
width = (i == start)
? (F32)(fgi->mWidth + fgi->mXBearing) // use actual width for last character
: fgi->mXAdvance; // use advance for all other characters
//old
//const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
//mFontFreetype->getXAdvance(wch);
: fgi->mXAdvance; // use advance for all other characters
}
if( scaled_max_pixels < (total_width + char_width) )
if( scaled_max_pixels < (total_width + width) )
{
break;
}
total_width += char_width;
total_width += width;
drawable_chars++;
if( max_chars >= 0 && drawable_chars >= max_chars )
@@ -759,10 +837,20 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
}
// Round after kerning.
total_width = llround(total_width);
total_width = (F32)llround(total_width);
}
return start_pos - drawable_chars;
if (drawable_chars == 0)
{
return start_pos; // just draw last character
}
else
{
// if only 1 character is drawable, we want to return start_pos as the first character to draw
// if 2 are drawable, return start_pos and character before start_pos, etc.
return start_pos + 1 - drawable_chars;
}
}
@@ -781,6 +869,8 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset,
const S32 max_index = begin_offset + llmin(S32_MAX - begin_offset, max_chars);
F32 scaled_max_pixels = max_pixels * sScaleX;
const LLFontGlyphInfo* next_glyph = NULL;
S32 pos;
for (pos = begin_offset; pos < max_index; pos++)
@@ -790,83 +880,60 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset,
{
break; // done
}
const embedded_data_t* ext_data = use_embedded ? getEmbeddedCharData(wch) : NULL;
if (ext_data)
const LLFontGlyphInfo* glyph = next_glyph;
next_glyph = NULL;
if(!glyph && !ext_data)
{
F32 ext_advance = getEmbeddedCharAdvance(ext_data);
glyph = mFontFreetype->getGlyphInfo(wch);
}
F32 char_width = ext_data ? getEmbeddedCharAdvance(ext_data) : mFontFreetype->getXAdvance(glyph);
if (round)
{
// Note: if the mouse is on the left half of the character, the pick is to the character's left
// If it's on the right half, the pick is to the right.
if (target_x < cur_x + ext_advance/2)
{
break;
}
}
else
{
if (target_x < cur_x + ext_advance)
{
break;
}
}
if (scaled_max_pixels < cur_x + ext_advance)
if (round)
{
// Note: if the mouse is on the left half of the character, the pick is to the character's left
// If it's on the right half, the pick is to the right.
if (target_x < cur_x + char_width*0.5f)
{
break;
}
}
else if (target_x < cur_x + char_width)
{
break;
}
pos++;
cur_x += ext_advance;
if (scaled_max_pixels < cur_x + char_width)
{
break;
}
if (((pos + 1) < max_index)
&& (wchars[(pos + 1)]))
cur_x += char_width;
if (((pos + 1) < max_index)
&& (wchars[(pos + 1)]))
{
if(ext_data)
{
cur_x += EXT_KERNING * sScaleX;
}
// Round after kerning.
cur_x = (F32)llfloor(cur_x + 0.5f);
else
{
next_glyph = mFontFreetype->getGlyphInfo(wchars[pos + 1]);
cur_x += mFontFreetype->getXKerning(glyph, next_glyph);
}
}
else
{
F32 char_width = mFontFreetype->getXAdvance(wch);
if (round)
{
// Note: if the mouse is on the left half of the character, the pick is to the character's left
// If it's on the right half, the pick is to the right.
if (target_x < cur_x + char_width*0.5f)
{
break;
}
}
else if (target_x < cur_x + char_width)
{
break;
}
if (scaled_max_pixels < cur_x + char_width)
{
break;
}
pos++;
cur_x += char_width;
if (((pos + 1) < max_index)
&& (wchars[(pos + 1)]))
{
// Kern this puppy.
cur_x += mFontFreetype->getXKerning(wch, wchars[pos + 1]);
}
// Round after kerning.
cur_x = (F32)llround(cur_x);
}
// Round after kerning.
cur_x = (F32)llround(cur_x);
}
return pos;
return llmin(max_chars, pos - begin_offset);
}
const LLFontDescriptor& LLFontGL::getFontDesc() const
@@ -1226,95 +1293,95 @@ LLFontGL &LLFontGL::operator=(const LLFontGL &source)
return *this;
}
void LLFontGL::renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const
void LLFontGL::renderQuad(LLVector4a* 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));
S32 index = 0;
gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
gGL.vertex2f(llfont_round_x(screen_rect.mLeft),
llfont_round_y(screen_rect.mTop));
vertex_out[index].set(screen_rect.mRight, screen_rect.mTop, 0.f);
uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
colors_out[index] = color;
index++;
gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
gGL.vertex2f(llfont_round_x(screen_rect.mLeft + slant_amt),
llfont_round_y(screen_rect.mBottom));
vertex_out[index].set(screen_rect.mLeft, screen_rect.mTop, 0.f);
uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
colors_out[index] = color;
index++;
gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
gGL.vertex2f(llfont_round_x(screen_rect.mRight + slant_amt),
llfont_round_y(screen_rect.mBottom));
vertex_out[index].set(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].set(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, LLVector4a* 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)
{
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;
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);
}
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);
}
}
gGL.end();
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++)
{
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(&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++;
}
}

View File

@@ -232,8 +232,8 @@ protected:
LLFontDescriptor mFontDescriptor;
LLPointer<LLFontFreetype> mFontFreetype;
void renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const;
void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const;
void renderQuad(LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const;
void drawGlyph(S32& glyph_count, LLVector4a* 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_fade) const;
// Registry holds all instantiated fonts.
static LLFontRegistry* sFontRegistry;

View File

@@ -480,6 +480,8 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
result->mFontFreetype->setFallbackFonts(fontlist);
}
norm_desc.setStyle(match_desc->getStyle());
if (result)
{
result->mFontDescriptor = desc;

View File

@@ -398,7 +398,10 @@ void LLLineEditor::setCursor( S32 pos )
{
S32 width_chars_to_left = mGLFont->getWidth(mText.getWString().c_str(), 0, mScrollHPos);
S32 last_visible_char = mGLFont->maxDrawableChars(mText.getWString().c_str(), llmax(0.f, (F32)(mMaxHPixels - mMinHPixels + width_chars_to_left)));
S32 min_scroll = mGLFont->firstDrawableChar(mText.getWString().c_str(), (F32)(mMaxHPixels - mMinHPixels - UI_LINEEDITOR_CURSOR_THICKNESS - UI_LINEEDITOR_H_PAD), mText.length(), getCursor());
// 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
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);
if (old_cursor_pos == last_visible_char)
{
mScrollHPos = llmin(mText.length(), llmax(min_scroll, mScrollHPos + SCROLL_INCREMENT_ADD));
@@ -1887,14 +1890,14 @@ void LLLineEditor::draw()
{
S32 select_left;
S32 select_right;
if( mSelectionStart < getCursor() )
if (mSelectionStart < mSelectionEnd)
{
select_left = mSelectionStart;
select_right = getCursor();
select_right = mSelectionEnd;
}
else
{
select_left = getCursor();
select_left = mSelectionEnd;
select_right = mSelectionStart;
}
@@ -1921,10 +1924,11 @@ void LLLineEditor::draw()
width = llmin(width, mMaxHPixels - llround(rendered_pixels_right));
gl_rect_2d(llround(rendered_pixels_right), cursor_top, llround(rendered_pixels_right)+width, cursor_bottom, color);
LLColor4 tmp_color( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha );
rendered_text += mGLFont->render(
mText, mScrollHPos + rendered_text,
rendered_pixels_right, text_bottom,
LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha ),
tmp_color,
LLFontGL::LEFT, LLFontGL::BOTTOM,
LLFontGL::NORMAL,
LLFontGL::NO_SHADOW,
@@ -1936,7 +1940,7 @@ void LLLineEditor::draw()
if( (rendered_pixels_right < (F32)mMaxHPixels) && (rendered_text < text_len) )
{
// unselected, right side
mGLFont->render(
rendered_text += mGLFont->render(
mText, mScrollHPos + rendered_text,
rendered_pixels_right, text_bottom,
text_color,
@@ -1950,7 +1954,7 @@ void LLLineEditor::draw()
}
else
{
mGLFont->render(
rendered_text = mGLFont->render(
mText, mScrollHPos,
rendered_pixels_right, text_bottom,
text_color,
@@ -1993,8 +1997,9 @@ void LLLineEditor::draw()
cursor_right, cursor_bottom, text_color);
if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection())
{
LLColor4 tmp_color( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha );
mGLFont->render(mText, getCursor(), (F32)(cursor_left + UI_LINEEDITOR_CURSOR_THICKNESS / 2), text_bottom,
LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha ),
tmp_color,
LLFontGL::LEFT, LLFontGL::BOTTOM,
LLFontGL::NORMAL,
LLFontGL::NO_SHADOW,
@@ -2787,13 +2792,19 @@ void LLLineEditor::updateAllowingLanguageInput()
// fine on 1.15.0.2, since all prevalidate func reject any
// non-ASCII characters. I'm not sure on future versions,
// however...
LLWindow* window = getWindow();
if (!window)
{
// test app, no window available
return;
}
if (hasFocus() && !mReadOnly && !mDrawAsterixes && mPrevalidateFunc == NULL)
{
getWindow()->allowLanguageTextInput(this, TRUE);
window->allowLanguageTextInput(this, TRUE);
}
else
{
getWindow()->allowLanguageTextInput(this, FALSE);
window->allowLanguageTextInput(this, FALSE);
}
}

View File

@@ -2,7 +2,7 @@
<array>
<map>
<key>default_grids_version</key><string>21</string>
<key>default_grids_version</key><string>22</string>
</map>
<!-- Second Life -->
@@ -20,6 +20,7 @@
<key>render_compat</key><boolean>1</boolean>
<key>inventory_links</key><boolean>1</boolean>
<key>auto_update</key><boolean>0</boolean>
<key>locked</key><boolean>1</boolean>
</map>
<map>

View File

@@ -57,6 +57,7 @@ HippoGridInfo::HippoGridInfo(const std::string& gridName) :
mRenderCompat(true),
mInvLinks(false),
mAutoUpdate(false),
mLocked(false),
mMaxAgentGroups(-1),
mCurrencySymbol("OS$"),
mCurrencyText("OS Dollars"),
@@ -174,10 +175,12 @@ void HippoGridInfo::setLoginUri(const std::string& loginUri)
{
mIsInProductionGrid = true;
useHttps();
setPlatform(PLATFORM_SECONDLIFE);
}
if (utf8str_tolower(LLURI(mLoginUri).hostName()) == "login.aditi.lindenlab.com")
{
useHttps();
setPlatform(PLATFORM_SECONDLIFE);
}
if (utf8str_tolower(LLURI(mLoginUri).hostName()) == "login.avination.com" ||
utf8str_tolower(LLURI(mLoginUri).hostName()) == "login.avination.net")
@@ -654,11 +657,6 @@ bool HippoGridInfo::getAutoUpdate()
return mAutoUpdate;
}
void HippoGridInfo::setAutoUpdate(bool b)
{
mAutoUpdate = b;
}
bool HippoGridInfo::getUPCSupported()
{
if(isSecondLife())
@@ -1014,7 +1012,8 @@ void HippoGridManager::parseData(LLSD &gridInfo, bool mergeIfNewer)
if (gridMap.has("search")) grid->setSearchUrl(gridMap["search"]);
if (gridMap.has("render_compat")) grid->setRenderCompat(gridMap["render_compat"]);
if (gridMap.has("inventory_links")) grid->setSupportsInvLinks(gridMap["inventory_links"]);
if (gridMap.has("auto_update")) grid->setAutoUpdate(gridMap["auto_update"]);
if (gridMap.has("auto_update")) grid->mAutoUpdate = gridMap["auto_update"];
if (gridMap.has("locked")) grid->mLocked = gridMap["locked"];
if (newGrid) addGrid(grid);
}
}
@@ -1051,6 +1050,7 @@ void HippoGridManager::saveFile()
gridInfo[i]["render_compat"] = grid->isRenderCompat();
gridInfo[i]["inventory_links"] = grid->supportsInvLinks();
gridInfo[i]["auto_update"] = grid->getAutoUpdate();
gridInfo[i]["locked"] = grid->getLocked();
}
// write client grid info file

View File

@@ -22,6 +22,7 @@ class LLSD;
class HippoGridInfo
{
friend class HippoGridManager;
public:
enum Platform {
PLATFORM_OTHER = 0,
@@ -96,7 +97,7 @@ public:
bool supportsInvLinks();
void setSupportsInvLinks(bool b);
bool getAutoUpdate();
void setAutoUpdate(bool b);
bool getLocked() { return mLocked; }
void getGridInfo();
@@ -124,6 +125,7 @@ private:
bool mRenderCompat;
bool mInvLinks;
bool mAutoUpdate;
bool mLocked;
bool mUPCSupported;
int mMaxAgentGroups;

View File

@@ -61,6 +61,7 @@ class HippoPanelGridsImpl : public HippoPanelGrids
enum State { NORMAL, ADD_NEW, ADD_COPY };
State mState;
std::string mCurGrid;
bool mIsEditable;
void loadCurGrid();
bool saveCurGrid();
@@ -78,6 +79,8 @@ class HippoPanelGridsImpl : public HippoPanelGrids
static void onClickGridInfo(void *data);
static void onClickHelpRenderCompat(void *data);
static void onClickAdvanced(void *data);
void enableEditing(bool);
};
@@ -103,7 +106,7 @@ HippoPanelGrids *HippoPanelGrids::create()
HippoPanelGridsImpl::HippoPanelGridsImpl() :
mState(NORMAL)
mState(NORMAL), mIsEditable(true)
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_preferences_grids.xml");
}
@@ -194,27 +197,10 @@ void HippoPanelGridsImpl::refresh()
childSetTextArg("default_grid", "[DEFAULT]", (defaultGrid != "")? defaultGrid: " ");
childSetEnabled("btn_delete", (selectIndex >= 0));
childSetEnabled("btn_delete", (selectIndex >= 0) && mIsEditable );
childSetEnabled("btn_copy", (mState == NORMAL) && (selectIndex >= 0));
childSetEnabled("btn_default", (mState == NORMAL) && (selectIndex > 0));
childSetEnabled("gridname", (mState == ADD_NEW) || (mState == ADD_COPY));
if (childGetValue("platform").asString() == "SecondLife") {
// disable platform selector, if logged into the grid edited and it is SL
// so object export restrictions cannot be circumvented by changing the platform
bool enablePlatform = (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP) ||
(mCurGrid != gHippoGridManager->getConnectedGrid()->getGridName());
childSetEnabled("platform", enablePlatform);
childSetEnabled("search", false);
childSetText("search", LLStringExplicit(""));
childSetEnabled("render_compat", false);
childSetValue("render_compat", false);
} else {
childSetEnabled("platform", true);
childSetEnabled("search", true);
childSetText("search", gHippoGridManager->getConnectedGrid()->getSearchUrl());
childSetEnabled("render_compat", true);
}
childSetEnabled("gridname", (mState == ADD_NEW) || (mState == ADD_COPY));
}
@@ -256,9 +242,11 @@ void HippoPanelGridsImpl::loadCurGrid()
childSetText("helperuri", gridInfo->getHelperUri());
childSetText("website", gridInfo->getWebSite());
childSetText("support", gridInfo->getSupportUrl());
childSetText("search", gridInfo->getSearchUrl());
childSetText("register", gridInfo->getRegisterUrl());
childSetText("password", gridInfo->getPasswordUrl());
childSetValue("render_compat", gridInfo->isRenderCompat());
enableEditing(!gridInfo->getLocked());
} else {
std::string empty = "";
LLComboBox *platform = getChild<LLComboBox>("platform");
@@ -269,10 +257,11 @@ void HippoPanelGridsImpl::loadCurGrid()
childSetText("helperuri", empty);
childSetText("website", empty);
childSetText("support", empty);
childSetText("search", empty);
childSetText("register", empty);
childSetText("password", empty);
childSetEnabled("render_compat", true);
childSetValue("render_compat", true);
enableEditing(true);
}
if (mState == ADD_NEW) {
@@ -281,6 +270,7 @@ void HippoPanelGridsImpl::loadCurGrid()
childSetText("loginuri", required);
} else if (mState == ADD_COPY) {
childSetText("gridname", std::string("<required>"));
enableEditing(true);
} else if (mState != NORMAL) {
llwarns << "Illegal state " << mState << '.' << llendl;
}
@@ -574,3 +564,31 @@ void HippoPanelGridsImpl::onClickHelpRenderCompat(void *data)
{
LLNotificationsUtil::add("HelpRenderCompat");
}
void HippoPanelGridsImpl::enableEditing(bool b)
{
static const char * elements [] = {
"platform",
"gridname",
"loginuri",
"loginpage",
"helperuri",
"website",
"support",
"register",
"password",
"search",
"btn_delete",
"btn_gridinfo",
"render_compat",
"gridmessage",
0
};
for(int i = 0; elements[i]; ++i ) {
this->childSetEnabled(elements[i], b);
}
mIsEditable = b;
}

View File

@@ -45,7 +45,8 @@ typedef std::map<std::string, std::string> controller_map_t;
typedef std::map<std::string, F32> default_controller_map_t;
#define MIN_REQUIRED_PIXEL_AREA_AVATAR_PHYSICS_MOTION 0.f
#define TIME_ITERATION_STEP 0.1f
#define TIME_ITERATION_STEP 0.05f
#define MINIMUM_UPDATE_TIMESTEP 0.025f
inline F64 llsgn(const F64 a)
{
@@ -592,7 +593,7 @@ BOOL LLPhysicsMotion::onUpdate(F32 time)
const F32 time_delta = time - mLastTime;
// Don't update too frequently, to avoid precision errors from small time slices.
if (time_delta <= .01)
if (time_delta <= MINIMUM_UPDATE_TIMESTEP)
{
return FALSE;
}
@@ -889,4 +890,4 @@ void LLPhysicsMotion::reset()
mCharacter->setVisualParamWeight((*iter).mParam,(*iter).mParam->getDefaultWeight());
}
}
}
}