viewer#2411 Use font buffer in text segments

master
Andrey Kleshchev 2024-09-04 13:42:11 +03:00 committed by Andrey Kleshchev
parent 49abe2c8bc
commit 238a2a64b3
7 changed files with 143 additions and 56 deletions

View File

@ -42,6 +42,8 @@ LLFontVertexBuffer::~LLFontVertexBuffer()
void LLFontVertexBuffer::reset()
{
// Todo: some form of debug only frequecy check&assert to see if this is happening too often.
// Regenerating this list is expensive
mBufferList.clear();
}

View File

@ -948,7 +948,6 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s
S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length)
{
beforeValueChange();
segment_set_t::iterator seg_iter = getSegIterContaining(pos);
while(seg_iter != mSegments.end())
@ -1325,6 +1324,7 @@ void LLTextBase::reshape(S32 width, S32 height, bool called_from_parent)
//virtual
void LLTextBase::draw()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
// reflow if needed, on demand
reflow();
@ -2586,6 +2586,11 @@ const LLWString& LLTextBase::getWText() const
return getViewModel()->getDisplay();
}
S32 LLTextBase::getTextGeneration() const
{
return getViewModel()->getDisplayGeneration();
}
// If round is true, if the position is on the right half of a character, the cursor
// will be put to its right. If round is false, the cursor will always be put to the
// character's left.
@ -3280,7 +3285,8 @@ LLNormalTextSegment::LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 e
: LLTextSegment(start, end),
mStyle( style ),
mToken(NULL),
mEditor(editor)
mEditor(editor),
mLastGeneration(-1)
{
mFontHeight = mStyle->getFont()->getLineHeight();
@ -3294,7 +3300,8 @@ LLNormalTextSegment::LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 e
LLNormalTextSegment::LLNormalTextSegment( const LLUIColor& color, S32 start, S32 end, LLTextBase& editor, bool is_visible)
: LLTextSegment(start, end),
mToken(NULL),
mEditor(editor)
mEditor(editor),
mLastGeneration(-1)
{
mStyle = new LLStyle(LLStyle::Params().visible(is_visible).color(color));
@ -3313,22 +3320,38 @@ F32 LLNormalTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selec
{
return drawClippedSegment( getStart() + start, getStart() + end, selection_start, selection_end, draw_rect);
}
else
{
mFontBufferPreSelection.reset();
mFontBufferSelection.reset();
mFontBufferPostSelection.reset();
}
return draw_rect.mLeft;
}
// Draws a single text segment, reversing the color for selection if needed.
F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, LLRectf rect)
{
F32 alpha = LLViewDrawContext::getCurrentContext().mAlpha;
const LLWString &text = getWText();
F32 right_x = rect.mLeft;
if (!mStyle->isVisible())
{
return right_x;
}
F32 alpha = LLViewDrawContext::getCurrentContext().mAlpha;
const LLWString& text = getWText();
S32 text_gen = mEditor.getTextGeneration();
if (text_gen != mLastGeneration)
{
mLastGeneration = text_gen;
mFontBufferPreSelection.reset();
mFontBufferSelection.reset();
mFontBufferPostSelection.reset();
}
const LLFontGL* font = mStyle->getFont();
LLColor4 color = (mEditor.getReadOnly() ? mStyle->getReadOnlyColor() : mStyle->getColor()) % (alpha * mStyle->getAlpha());
@ -3339,7 +3362,8 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
S32 start = seg_start;
S32 end = llmin( selection_start, seg_end );
S32 length = end - start;
font->render(text, start,
mFontBufferPreSelection.render(font,
text, start,
rect,
color,
LLFontGL::LEFT, mEditor.mTextVAlign,
@ -3359,7 +3383,8 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
S32 end = llmin( selection_end, seg_end );
S32 length = end - start;
font->render(text, start,
mFontBufferSelection.render(font,
text, start,
rect,
mStyle->getSelectedColor().get(),
LLFontGL::LEFT, mEditor.mTextVAlign,
@ -3377,7 +3402,8 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
S32 start = llmax( selection_end, seg_start );
S32 end = seg_end;
S32 length = end - start;
font->render(text, start,
mFontBufferPostSelection.render(font,
text, start,
rect,
color,
LLFontGL::LEFT, mEditor.mTextVAlign,
@ -3573,6 +3599,15 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
return num_chars;
}
void LLNormalTextSegment::updateLayout(const class LLTextBase& editor)
{
LLTextSegment::updateLayout(editor);
mFontBufferPreSelection.reset();
mFontBufferSelection.reset();
mFontBufferPostSelection.reset();
}
void LLNormalTextSegment::dump() const
{
LL_INFOS() << "Segment [" <<

View File

@ -30,6 +30,7 @@
#include "v4color.h"
#include "lleditmenuhandler.h"
#include "llfontvertexbuffer.h"
#include "llspellcheckmenuhandler.h"
#include "llstyle.h"
#include "llkeywords.h"
@ -131,6 +132,7 @@ public:
/*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;
/*virtual*/ S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const;
/*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const;
/*virtual*/ void updateLayout(const class LLTextBase& editor);
/*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
/*virtual*/ bool canEdit() const { return true; }
/*virtual*/ const LLUIColor& getColor() const { return mStyle->getColor(); }
@ -161,6 +163,12 @@ protected:
LLKeywordToken* mToken;
std::string mTooltip;
boost::signals2::connection mImageLoadedConnection;
// font rendering
LLFontVertexBuffer mFontBufferPreSelection;
LLFontVertexBuffer mFontBufferSelection;
LLFontVertexBuffer mFontBufferPostSelection;
S32 mLastGeneration = -1;
};
// This text segment is the same as LLNormalTextSegment, the only difference
@ -432,6 +440,7 @@ public:
// wide-char versions
void setWText(const LLWString& text);
const LLWString& getWText() const;
S32 getTextGeneration() const;
void appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params = LLStyle::Params());

View File

@ -82,11 +82,20 @@ void LLTextViewModel::setValue(const LLSD& value)
// approximate LLSD storage usage
LLViewModel::setValue(value);
mDisplay = utf8str_to_wstring(mStringValue = value.asString());
mDisplayGeneration++;
// mDisplay and mValue agree
mUpdateFromDisplay = false;
}
LLWString& LLTextViewModel::getEditableDisplay()
{
mDirty = true;
mDisplayGeneration++;
mUpdateFromDisplay = true;
return mDisplay;
}
void LLTextViewModel::setDisplay(const LLWString& value)
{
// This is the strange way to alter the value. Normally we'd setValue()
@ -94,6 +103,7 @@ void LLTextViewModel::setDisplay(const LLWString& value)
// value. But a text editor might want to edit the display string
// directly, then convert back to UTF8 on commit.
mDisplay = value;
mDisplayGeneration++;
mDirty = true;
// Don't immediately convert to UTF8 -- do it lazily -- we expect many
// more setDisplay() calls than getValue() calls. Just flag that it needs

View File

@ -105,7 +105,8 @@ public:
// New functions
/// Get the stored value in string form
const LLWString& getDisplay() const { return mDisplay; }
LLWString& getEditableDisplay() { mDirty = true; mUpdateFromDisplay = true; return mDisplay; }
S32 getDisplayGeneration() const { return mDisplayGeneration; }
LLWString& getEditableDisplay();
/**
* Set the display string directly (see LLTextEditor). What the user is
@ -120,6 +121,7 @@ private:
/// To avoid converting every widget's stored value from LLSD to LLWString
/// every frame, cache the converted value
LLWString mDisplay;
S32 mDisplayGeneration = -1;
/// As the user edits individual characters (setDisplay()), defer
/// LLWString-to-UTF8 conversions until s/he's done.

View File

@ -963,59 +963,87 @@ void LLPanelMainInventory::draw()
void LLPanelMainInventory::updateItemcountText()
{
if(mItemCount != gInventory.getItemCount())
bool update = false;
if (mSingleFolderMode)
{
mItemCount = gInventory.getItemCount();
mItemCountString = "";
LLLocale locale(LLLocale::USER_LOCALE);
LLResMgr::getInstance()->getIntegerString(mItemCountString, mItemCount);
}
LLInventoryModel::cat_array_t* cats;
LLInventoryModel::item_array_t* items;
if(mCategoryCount != gInventory.getCategoryCount())
{
mCategoryCount = gInventory.getCategoryCount();
mCategoryCountString = "";
LLLocale locale(LLLocale::USER_LOCALE);
LLResMgr::getInstance()->getIntegerString(mCategoryCountString, mCategoryCount);
}
gInventory.getDirectDescendentsOf(getCurrentSFVRoot(), cats, items);
S32 item_count = items ? (S32)items->size() : 0;
S32 cat_count = cats ? (S32)cats->size() : 0;
LLStringUtil::format_map_t string_args;
string_args["[ITEM_COUNT]"] = mItemCountString;
string_args["[CATEGORY_COUNT]"] = mCategoryCountString;
string_args["[FILTER]"] = getFilterText();
std::string text = "";
if (LLInventoryModelBackgroundFetch::instance().folderFetchActive())
{
text = getString("ItemcountFetching", string_args);
}
else if (LLInventoryModelBackgroundFetch::instance().isEverythingFetched())
{
text = getString("ItemcountCompleted", string_args);
if (mItemCount != item_count)
{
mItemCount = item_count;
update = true;
}
if (mCategoryCount != cat_count)
{
mCategoryCount = cat_count;
update = true;
}
}
else
{
text = getString("ItemcountUnknown", string_args);
}
if (mSingleFolderMode)
{
LLInventoryModel::cat_array_t *cats;
LLInventoryModel::item_array_t *items;
gInventory.getDirectDescendentsOf(getCurrentSFVRoot(), cats, items);
if (items && cats)
if (mItemCount != gInventory.getItemCount())
{
string_args["[ITEM_COUNT]"] = llformat("%d", items->size());
string_args["[CATEGORY_COUNT]"] = llformat("%d", cats->size());
text = getString("ItemcountCompleted", string_args);
mItemCount = gInventory.getItemCount();
update = true;
}
if (mCategoryCount != gInventory.getCategoryCount())
{
mCategoryCount = gInventory.getCategoryCount();
update = true;
}
}
mCounterCtrl->setValue(text);
mCounterCtrl->setToolTip(text);
if (mLastFilterText != getFilterText())
{
mLastFilterText = getFilterText();
update = true;
}
if (update)
{
mItemCountString = "";
LLLocale locale(LLLocale::USER_LOCALE);
LLResMgr::getInstance()->getIntegerString(mItemCountString, mItemCount);
mCategoryCountString = "";
LLResMgr::getInstance()->getIntegerString(mCategoryCountString, mCategoryCount);
LLStringUtil::format_map_t string_args;
string_args["[ITEM_COUNT]"] = mItemCountString;
string_args["[CATEGORY_COUNT]"] = mCategoryCountString;
string_args["[FILTER]"] = mLastFilterText;
std::string text = "";
if (mSingleFolderMode)
{
text = getString("ItemcountCompleted", string_args);
}
else
{
if (LLInventoryModelBackgroundFetch::instance().folderFetchActive())
{
text = getString("ItemcountFetching", string_args);
}
else if (LLInventoryModelBackgroundFetch::instance().isEverythingFetched())
{
text = getString("ItemcountCompleted", string_args);
}
else
{
text = getString("ItemcountUnknown", string_args);
}
}
mCounterCtrl->setValue(text);
mCounterCtrl->setToolTip(text);
}
}
void LLPanelMainInventory::onFocusReceived()

View File

@ -196,9 +196,10 @@ private:
LLSaveFolderState* mSavedFolderState;
std::string mFilterText;
std::string mFilterSubString;
S32 mItemCount;
S32 mItemCount = 0;
std::string mLastFilterText;
std::string mItemCountString;
S32 mCategoryCount;
S32 mCategoryCount = 0;
std::string mCategoryCountString;
LLComboBox* mSearchTypeCombo;