More font cleanup and updating.
This commit is contained in:
@@ -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,26 +325,25 @@ 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);
|
||||
llassert(!mIsFallback);
|
||||
fontp->renderGlyph(glyph_index);
|
||||
S32 width = fontp->mFTFace->glyph->bitmap.width;
|
||||
S32 height = fontp->mFTFace->glyph->bitmap.rows;
|
||||
@@ -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();
|
||||
|
||||
@@ -605,7 +540,7 @@ void LLFontFreetype::setSubImageLuminanceAlpha(const U32 x, const U32 y, const U
|
||||
{
|
||||
LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num);
|
||||
|
||||
//llassert(!mIsFallback);
|
||||
llassert(!mIsFallback);
|
||||
llassert(image_raw && (image_raw->getComponents() == 2));
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -266,6 +266,7 @@ 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;
|
||||
@@ -336,13 +337,12 @@ 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;
|
||||
@@ -384,13 +384,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.
|
||||
@@ -527,13 +522,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 +542,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 +566,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 +605,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 +670,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 +694,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 +750,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 +787,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 +819,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 +830,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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user