summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llbadge.cpp12
-rw-r--r--indra/llui/llfloater.cpp24
-rw-r--r--indra/llui/llfolderview.cpp2
-rw-r--r--indra/llui/llfolderviewitem.cpp138
-rw-r--r--indra/llui/llfolderviewitem.h17
-rw-r--r--indra/llui/llfolderviewmodel.h1
-rw-r--r--indra/llui/lllineeditor.cpp60
-rw-r--r--indra/llui/lllineeditor.h5
-rw-r--r--indra/llui/llstatbar.cpp10
-rw-r--r--indra/llui/lltextbase.cpp269
-rw-r--r--indra/llui/lltextbase.h27
-rw-r--r--indra/llui/lltexteditor.h2
-rw-r--r--indra/llui/lltrans.cpp20
-rw-r--r--indra/llui/lltrans.h18
-rw-r--r--indra/llui/llurlentry.cpp36
-rw-r--r--indra/llui/llurlentry.h4
-rw-r--r--indra/llui/llview.cpp6
-rw-r--r--indra/llui/llviewereventrecorder.cpp2
-rw-r--r--indra/llui/llviewmodel.cpp10
-rw-r--r--indra/llui/llviewmodel.h4
20 files changed, 474 insertions, 193 deletions
diff --git a/indra/llui/llbadge.cpp b/indra/llui/llbadge.cpp
index c6654ee0aa..42b6f1f07b 100644
--- a/indra/llui/llbadge.cpp
+++ b/indra/llui/llbadge.cpp
@@ -204,13 +204,13 @@ void renderBadgeBackground(F32 centerX, F32 centerY, F32 width, F32 height, cons
(F32)ll_round(x) + width,
(F32)ll_round(y) + height);
- LLVector3 vertices[4];
- vertices[0] = LLVector3(screen_rect.mRight, screen_rect.mTop, 1.0f);
- vertices[1] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 1.0f);
- vertices[2] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 1.0f);
- vertices[3] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 1.0f);
+ LLVector4a vertices[4];
+ vertices[0].set(screen_rect.mLeft, screen_rect.mTop, 1.0f);
+ vertices[1].set(screen_rect.mRight, screen_rect.mTop, 1.0f);
+ vertices[2].set(screen_rect.mLeft, screen_rect.mBottom, 1.0f);
+ vertices[3].set(screen_rect.mRight, screen_rect.mBottom, 1.0f);
- gGL.begin(LLRender::QUADS);
+ gGL.begin(LLRender::TRIANGLE_STRIP);
{
gGL.vertexBatchPreTransformed(vertices, 4);
}
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 92fb4b75bf..4b904f09e0 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -2275,36 +2275,28 @@ void LLFloater::drawConeToOwner(F32 &context_cone_opacity,
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
LLGLEnable(GL_CULL_FACE);
- gGL.begin(LLRender::QUADS);
+ gGL.begin(LLRender::TRIANGLE_STRIP);
{
gGL.color4f(0.f, 0.f, 0.f, contex_cone_in_alpha * context_cone_opacity);
gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop);
- gGL.vertex2i(owner_rect.mRight, owner_rect.mTop);
- gGL.color4f(0.f, 0.f, 0.f, contex_cone_out_alpha * context_cone_opacity);
- gGL.vertex2i(local_rect.mRight, local_rect.mTop);
- gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-
gGL.color4f(0.f, 0.f, 0.f, contex_cone_out_alpha * context_cone_opacity);
gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
- gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
gGL.color4f(0.f, 0.f, 0.f, contex_cone_in_alpha * context_cone_opacity);
- gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom);
- gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop);
-
+ gGL.vertex2i(owner_rect.mRight, owner_rect.mTop);
gGL.color4f(0.f, 0.f, 0.f, contex_cone_out_alpha * context_cone_opacity);
- gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
gGL.vertex2i(local_rect.mRight, local_rect.mTop);
gGL.color4f(0.f, 0.f, 0.f, contex_cone_in_alpha * context_cone_opacity);
- gGL.vertex2i(owner_rect.mRight, owner_rect.mTop);
gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom);
-
-
gGL.color4f(0.f, 0.f, 0.f, contex_cone_out_alpha * context_cone_opacity);
- gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
gGL.color4f(0.f, 0.f, 0.f, contex_cone_in_alpha * context_cone_opacity);
- gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom);
gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom);
+ gGL.color4f(0.f, 0.f, 0.f, contex_cone_out_alpha * context_cone_opacity);
+ gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
+ gGL.color4f(0.f, 0.f, 0.f, contex_cone_in_alpha * context_cone_opacity);
+ gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop);
+ gGL.color4f(0.f, 0.f, 0.f, contex_cone_out_alpha * context_cone_opacity);
+ gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
}
gGL.end();
}
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index 388dc5b1ac..42a9e267d2 100644
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -1649,7 +1649,7 @@ void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constr
{
LLRect local_rect = item->getLocalRect();
S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight();
- S32 label_height = getLabelFontForStyle(mLabelStyle)->getLineHeight();
+ S32 label_height = getLabelFont()->getLineHeight();
// when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder
S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + item->getIconPad()) : local_rect.getHeight();
diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index e4f5664908..18bde344a0 100644
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -48,7 +48,6 @@ static LLDefaultChildRegistry::Register<LLFolderViewItem> r("folder_view_item");
// statics
std::map<U8, LLFontGL*> LLFolderViewItem::sFonts; // map of styles to fonts
-bool LLFolderViewItem::sColorSetInitialized = false;
LLUIColor LLFolderViewItem::sFgColor;
LLUIColor LLFolderViewItem::sHighlightBgColor;
LLUIColor LLFolderViewItem::sFlashBgColor;
@@ -58,6 +57,10 @@ LLUIColor LLFolderViewItem::sFilterBGColor;
LLUIColor LLFolderViewItem::sFilterTextColor;
LLUIColor LLFolderViewItem::sSuffixColor;
LLUIColor LLFolderViewItem::sSearchStatusColor;
+S32 LLFolderViewItem::sTopPad = 0;
+LLUIImagePtr LLFolderViewItem::sFolderArrowImg;
+LLUIImagePtr LLFolderViewItem::sSelectionImg;
+LLFontGL* LLFolderViewItem::sSuffixFont = nullptr;
// only integers can be initialized in header
const F32 LLFolderViewItem::FOLDER_CLOSE_TIME_CONSTANT = 0.02f;
@@ -83,15 +86,42 @@ LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style)
return rtn;
}
+
+const LLFontGL* LLFolderViewItem::getLabelFont()
+{
+ if (!pLabelFont)
+ {
+ pLabelFont = getLabelFontForStyle(mLabelStyle);
+ }
+ return pLabelFont;
+}
//static
void LLFolderViewItem::initClass()
{
+ const Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>();
+ sTopPad = default_params.item_top_pad;
+ sFolderArrowImg = default_params.folder_arrow_image;
+ sSelectionImg = default_params.selection_image;
+ sSuffixFont = getLabelFontForStyle(LLFontGL::NORMAL);
+
+ sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE);
+ sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE);
+ sFlashBgColor = LLUIColorTable::instance().getColor("MenuItemFlashBgColor", DEFAULT_WHITE);
+ sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE);
+ sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE);
+ sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE);
+ sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE);
+ sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE);
+ sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE);
}
//static
void LLFolderViewItem::cleanupClass()
{
sFonts.clear();
+ sFolderArrowImg = nullptr;
+ sSelectionImg = nullptr;
+ sSuffixFont = nullptr;
}
@@ -134,6 +164,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
mIsItemCut(false),
mCutGeneration(0),
mLabelStyle( LLFontGL::NORMAL ),
+ pLabelFont(nullptr),
mHasVisibleChildren(false),
mLocalIndentation(p.folder_indentation),
mIndentation(0),
@@ -158,20 +189,6 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
mMaxFolderItemOverlap(p.max_folder_item_overlap),
mDoubleClickOverride(p.double_click_override)
{
- if (!sColorSetInitialized)
- {
- sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE);
- sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE);
- sFlashBgColor = LLUIColorTable::instance().getColor("MenuItemFlashBgColor", DEFAULT_WHITE);
- sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE);
- sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE);
- sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE);
- sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE);
- sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE);
- sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE);
- sColorSetInitialized = true;
- }
-
if (mViewModelItem)
{
mViewModelItem->setFolderViewItem(this);
@@ -307,6 +324,7 @@ void LLFolderViewItem::refresh()
LLFolderViewModelItem& vmi = *getViewModelItem();
mLabel = utf8str_to_wstring(vmi.getDisplayName());
+ mLabelFontBuffer.reset();
setToolTip(vmi.getName());
// icons are slightly expensive to get, can be optimized
// see LLInventoryIcon::getIcon()
@@ -319,7 +337,9 @@ void LLFolderViewItem::refresh()
// Very Expensive!
// Can do a number of expensive checks, like checking active motions, wearables or friend list
mLabelStyle = vmi.getLabelStyle();
+ pLabelFont = nullptr; // refresh can be called from a coro, don't use getLabelFontForStyle, coro trips font list tread safety
mLabelSuffix = utf8str_to_wstring(vmi.getLabelSuffix());
+ mSuffixFontBuffer.reset();
}
// Dirty the filter flag of the model from the view (CHUI-849)
@@ -344,6 +364,7 @@ void LLFolderViewItem::refreshSuffix()
// Very Expensive!
// Can do a number of expensive checks, like checking active motions, wearables or friend list
mLabelStyle = vmi->getLabelStyle();
+ pLabelFont = nullptr;
mLabelSuffix = utf8str_to_wstring(vmi->getLabelSuffix());
}
@@ -736,19 +757,17 @@ bool LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop,
return handled;
}
-void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const LLUIColor& fg_color)
+void LLFolderViewItem::drawOpenFolderArrow()
{
//--------------------------------------------------------------------------------//
// Draw open folder arrow
//
- const S32 TOP_PAD = default_params.item_top_pad;
if (hasVisibleChildren() || !isFolderComplete())
{
- LLUIImage* arrow_image = default_params.folder_arrow_image;
gl_draw_scaled_rotated_image(
- mIndentation, getRect().getHeight() - mArrowSize - mTextPad - TOP_PAD,
- mArrowSize, mArrowSize, mControlLabelRotation, arrow_image->getImage(), fg_color);
+ mIndentation, getRect().getHeight() - mArrowSize - mTextPad - sTopPad,
+ mArrowSize, mArrowSize, mControlLabelRotation, sFolderArrowImg->getImage(), sFgColor);
}
}
@@ -764,7 +783,7 @@ void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const L
/*virtual*/ bool LLFolderViewItem::isFadeItem()
{
- LLClipboard& clipboard = LLClipboard::instance();
+ static const LLClipboard& clipboard = LLClipboard::instance(); // Make it a 'simpleton'?
if (mCutGeneration != clipboard.getGeneration())
{
mCutGeneration = clipboard.getGeneration();
@@ -775,8 +794,9 @@ void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const L
return mIsItemCut;
}
-void LLFolderViewItem::drawHighlight(const bool showContent, const bool hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor,
- const LLUIColor &focusOutlineColor, const LLUIColor &mouseOverColor)
+void LLFolderViewItem::drawHighlight(bool showContent, bool hasKeyboardFocus,
+ const LLUIColor& selectColor, const LLUIColor& flashColor,
+ const LLUIColor& focusOutlineColor, const LLUIColor& mouseOverColor)
{
const S32 focus_top = getRect().getHeight();
const S32 focus_bottom = getRect().getHeight() - mItemHeight;
@@ -784,7 +804,7 @@ void LLFolderViewItem::drawHighlight(const bool showContent, const bool hasKeybo
const S32 FOCUS_LEFT = 1;
// Determine which background color to use for highlighting
- const LLUIColor& bgColor = (isFlashing() ? flashColor : selectColor);
+ const LLUIColor& bgColor = isFlashing() ? flashColor : selectColor;
//--------------------------------------------------------------------------------//
// Draw highlight for selected items
@@ -792,7 +812,6 @@ void LLFolderViewItem::drawHighlight(const bool showContent, const bool hasKeybo
// items if mShowSingleSelection is false.
//
if (isHighlightAllowed())
-
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
@@ -801,7 +820,7 @@ void LLFolderViewItem::drawHighlight(const bool showContent, const bool hasKeybo
{
LLColor4 bg_color = bgColor;
// do time-based fade of extra objects
- F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f);
+ F32 fade_time = getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.f;
if (getRoot() && getRoot()->getShowSingleSelection())
{
// fading out
@@ -890,7 +909,7 @@ void LLFolderViewItem::drawLabel(const LLFontGL * font, const F32 x, const F32 y
//--------------------------------------------------------------------------------//
// Draw the actual label text
//
- font->render(mLabel, 0, x, y, color,
+ mLabelFontBuffer.render(font, mLabel, 0, x, y, color,
LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
S32_MAX, getRect().getWidth() - (S32) x - mLabelPaddingRight, &right_x, /*use_ellipses*/true);
}
@@ -900,16 +919,14 @@ void LLFolderViewItem::draw()
const bool show_context = (getRoot() ? getRoot()->getShowSelectionContext() : false);
const bool filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : false); // If we have keyboard focus, draw selection filled
- const Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>();
- const S32 TOP_PAD = default_params.item_top_pad;
-
- const LLFontGL* font = getLabelFontForStyle(mLabelStyle);
+ const LLFontGL* font = getLabelFont();
+ S32 line_height = font->getLineHeight();
getViewModelItem()->update();
- if(!mSingleFolderMode)
+ if (!mSingleFolderMode)
{
- drawOpenFolderArrow(default_params, sFgColor);
+ drawOpenFolderArrow();
}
drawHighlight(show_context, filled, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor);
@@ -918,18 +935,19 @@ void LLFolderViewItem::draw()
// Draw open icon
//
const S32 icon_x = mIndentation + mArrowSize + mTextPad;
+ const S32 rect_height = getRect().getHeight();
if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) // For open folders
{
- mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1);
+ mIconOpen->draw(icon_x, rect_height - mIconOpen->getHeight() - sTopPad + 1);
}
else if (mIcon)
{
- mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1);
+ mIcon->draw(icon_x, rect_height - mIcon->getHeight() - sTopPad + 1);
}
if (mIconOverlay && getRoot()->showItemLinkOverlays())
{
- mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1);
+ mIconOverlay->draw(icon_x, rect_height - mIcon->getHeight() - sTopPad + 1);
}
//--------------------------------------------------------------------------------//
@@ -940,26 +958,24 @@ void LLFolderViewItem::draw()
return;
}
- auto filter_string_length = mViewModelItem->hasFilterStringMatch() ? static_cast<S32>(mViewModelItem->getFilterStringSize()) : 0;
+ S32 filter_string_length = mViewModelItem->hasFilterStringMatch() ? (S32)mViewModelItem->getFilterStringSize() : 0;
F32 right_x = 0;
- F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD;
+ F32 y = (F32)rect_height - line_height - (F32)mTextPad - (F32)sTopPad;
F32 text_left = (F32)getLabelXPos();
LLWString combined_string = mLabel + mLabelSuffix;
- const LLFontGL* suffix_font = getLabelFontForStyle(LLFontGL::NORMAL);
S32 filter_offset = static_cast<S32>(mViewModelItem->getFilterStringOffset());
if (filter_string_length > 0)
{
- S32 bottom = getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD;
- S32 top = getRect().getHeight() - TOP_PAD;
- if(mLabelSuffix.empty() || (font == suffix_font))
+ S32 bottom = rect_height - line_height - 3 - sTopPad;
+ S32 top = rect_height - sTopPad;
+ if(mLabelSuffix.empty() || (font == sSuffixFont))
{
- S32 left = ll_round(text_left) + font->getWidth(combined_string.c_str(), 0, static_cast<S32>(mViewModelItem->getFilterStringOffset())) - 2;
- S32 right = left + font->getWidth(combined_string.c_str(), static_cast<S32>(mViewModelItem->getFilterStringOffset()), filter_string_length) + 2;
+ S32 left = ll_round(text_left) + font->getWidth(combined_string.c_str(), 0, filter_offset) - 2;
+ S32 right = left + font->getWidth(combined_string.c_str(), filter_offset, filter_string_length) + 2;
- LLUIImage* box_image = default_params.selection_image;
- LLRect box_rect(left, top, right, bottom);
- box_image->draw(box_rect, sFilterBGColor);
+ LLRect box_rect(left, top, right, bottom);
+ sSelectionImg->draw(box_rect, sFilterBGColor);
}
else
{
@@ -968,19 +984,17 @@ void LLFolderViewItem::draw()
{
S32 left = (S32)(ll_round(text_left) + font->getWidthF32(mLabel.c_str(), 0, llmin(filter_offset, (S32)mLabel.size()))) - 2;
S32 right = left + (S32)font->getWidthF32(mLabel.c_str(), filter_offset, label_filter_length) + 2;
- LLUIImage* box_image = default_params.selection_image;
LLRect box_rect(left, top, right, bottom);
- box_image->draw(box_rect, sFilterBGColor);
+ sSelectionImg->draw(box_rect, sFilterBGColor);
}
S32 suffix_filter_length = label_filter_length > 0 ? filter_string_length - label_filter_length : filter_string_length;
if(suffix_filter_length > 0)
{
S32 suffix_offset = llmax(0, filter_offset - (S32)mLabel.size());
- S32 left = (S32)(ll_round(text_left) + font->getWidthF32(mLabel.c_str(), 0, static_cast<S32>(mLabel.size())) + suffix_font->getWidthF32(mLabelSuffix.c_str(), 0, suffix_offset)) - 2;
- S32 right = left + (S32)suffix_font->getWidthF32(mLabelSuffix.c_str(), suffix_offset, suffix_filter_length) + 2;
- LLUIImage* box_image = default_params.selection_image;
+ S32 left = (S32)(ll_round(text_left) + font->getWidthF32(mLabel.c_str(), 0, static_cast<S32>(mLabel.size())) + sSuffixFont->getWidthF32(mLabelSuffix.c_str(), 0, suffix_offset)) - 2;
+ S32 right = left + (S32)sSuffixFont->getWidthF32(mLabelSuffix.c_str(), suffix_offset, suffix_filter_length) + 2;
LLRect box_rect(left, top, right, bottom);
- box_image->draw(box_rect, sFilterBGColor);
+ sSelectionImg->draw(box_rect, sFilterBGColor);
}
}
}
@@ -999,9 +1013,9 @@ void LLFolderViewItem::draw()
//
if (!mLabelSuffix.empty())
{
- suffix_font->render( mLabelSuffix, 0, right_x, y, isFadeItem() ? color : sSuffixColor.get(),
- LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
- S32_MAX, S32_MAX, &right_x);
+ mSuffixFontBuffer.render(sSuffixFont, mLabelSuffix, 0, right_x, y, isFadeItem() ? color : sSuffixColor.get(),
+ LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
+ S32_MAX, S32_MAX, &right_x);
}
//--------------------------------------------------------------------------------//
@@ -1009,10 +1023,10 @@ void LLFolderViewItem::draw()
//
if (filter_string_length > 0)
{
- if(mLabelSuffix.empty() || (font == suffix_font))
+ if(mLabelSuffix.empty() || (font == sSuffixFont))
{
F32 match_string_left = text_left + font->getWidthF32(combined_string.c_str(), 0, filter_offset + filter_string_length) - font->getWidthF32(combined_string.c_str(), filter_offset, filter_string_length);
- F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD;
+ F32 yy = (F32)rect_height - line_height - (F32)mTextPad - (F32)sTopPad;
font->render(combined_string, filter_offset, match_string_left, yy,
sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
filter_string_length, S32_MAX, &right_x);
@@ -1023,7 +1037,7 @@ void LLFolderViewItem::draw()
if(label_filter_length > 0)
{
F32 match_string_left = text_left + font->getWidthF32(mLabel.c_str(), 0, filter_offset + label_filter_length) - font->getWidthF32(mLabel.c_str(), filter_offset, label_filter_length);
- F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD;
+ F32 yy = (F32)rect_height - line_height - (F32)mTextPad - (F32)sTopPad;
font->render(mLabel, filter_offset, match_string_left, yy,
sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
label_filter_length, S32_MAX, &right_x);
@@ -1033,9 +1047,9 @@ void LLFolderViewItem::draw()
if(suffix_filter_length > 0)
{
S32 suffix_offset = llmax(0, filter_offset - (S32)mLabel.size());
- F32 match_string_left = text_left + font->getWidthF32(mLabel.c_str(), 0, static_cast<S32>(mLabel.size())) + suffix_font->getWidthF32(mLabelSuffix.c_str(), 0, suffix_offset + suffix_filter_length) - suffix_font->getWidthF32(mLabelSuffix.c_str(), suffix_offset, suffix_filter_length);
- F32 yy = (F32)getRect().getHeight() - suffix_font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD;
- suffix_font->render(mLabelSuffix, suffix_offset, match_string_left, yy, sFilterTextColor,
+ F32 match_string_left = text_left + font->getWidthF32(mLabel.c_str(), 0, static_cast<S32>(mLabel.size())) + sSuffixFont->getWidthF32(mLabelSuffix.c_str(), 0, suffix_offset + suffix_filter_length) - sSuffixFont->getWidthF32(mLabelSuffix.c_str(), suffix_offset, suffix_filter_length);
+ F32 yy = (F32)rect_height - sSuffixFont->getLineHeight() - (F32)mTextPad - (F32)sTopPad;
+ sSuffixFont->render(mLabelSuffix, suffix_offset, match_string_left, yy, sFilterTextColor,
LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
suffix_filter_length, S32_MAX, &right_x);
}
diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h
index 60cdac3ab9..cc8a7d934c 100644
--- a/indra/llui/llfolderviewitem.h
+++ b/indra/llui/llfolderviewitem.h
@@ -29,6 +29,7 @@
#include "llflashtimer.h"
#include "llview.h"
#include "lluiimage.h"
+#include "llfontvertexbuffer.h"
class LLFolderView;
class LLFolderViewModelItem;
@@ -134,7 +135,6 @@ protected:
LLUIColor mFontHighlightColor;
// For now assuming all colors are the same in derived classes.
- static bool sColorSetInitialized;
static LLUIColor sFgColor;
static LLUIColor sFgDisabledColor;
static LLUIColor sHighlightBgColor;
@@ -157,6 +157,7 @@ protected:
virtual void setFlashState(bool) { }
static LLFontGL* getLabelFontForStyle(U8 style);
+ const LLFontGL* getLabelFont();
bool mIsSelected;
@@ -296,9 +297,9 @@ public:
// virtual void handleDropped();
virtual void draw();
- void drawOpenFolderArrow(const Params& default_params, const LLUIColor& fg_color);
- void drawHighlight(const bool showContent, const bool hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor, const LLUIColor &outlineColor, const LLUIColor &mouseOverColor);
- void drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x);
+ void drawOpenFolderArrow();
+ void drawHighlight(bool showContent, bool hasKeyboardFocus, const LLUIColor& selectColor, const LLUIColor& flashColor, const LLUIColor& outlineColor, const LLUIColor& mouseOverColor);
+ void drawLabel(const LLFontGL* font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x);
virtual bool handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop,
EDragAndDropType cargo_type,
void* cargo_data,
@@ -307,6 +308,14 @@ public:
private:
static std::map<U8, LLFontGL*> sFonts; // map of styles to fonts
+ static S32 sTopPad;
+ static LLUIImagePtr sFolderArrowImg;
+ static LLUIImagePtr sSelectionImg;
+ static LLFontGL* sSuffixFont;
+
+ LLFontVertexBuffer mLabelFontBuffer;
+ LLFontVertexBuffer mSuffixFontBuffer;
+ LLFontGL* pLabelFont{nullptr};
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h
index b8d6d89971..9372818ca5 100644
--- a/indra/llui/llfolderviewmodel.h
+++ b/indra/llui/llfolderviewmodel.h
@@ -292,6 +292,7 @@ public:
dirtyFilter();
requestSort();
}
+
virtual void removeChild(LLFolderViewModelItem* child)
{
mChildren.remove(child);
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 60b6115b34..66b274c33f 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -436,6 +436,9 @@ void LLLineEditor::setText(const LLStringExplicit &new_text, bool use_size_limit
{
mText.assign(utf8str_symbol_truncate(truncated_utf8, mMaxLengthChars));
}
+ mFontBufferPreSelection.reset();
+ mFontBufferSelection.reset();
+ mFontBufferPostSelection.reset();
if (all_selected)
{
@@ -617,6 +620,10 @@ void LLLineEditor::replaceWithSuggestion(U32 index)
mText.insert(it->first, suggestion);
setCursor(it->first + (S32)suggestion.length());
+ mFontBufferPreSelection.reset();
+ mFontBufferSelection.reset();
+ mFontBufferPostSelection.reset();
+
break;
}
}
@@ -969,6 +976,10 @@ void LLLineEditor::removeChar()
mText.erase(getCursor() - 1, 1);
setCursor(getCursor() - 1);
+
+ mFontBufferPreSelection.reset();
+ mFontBufferSelection.reset();
+ mFontBufferPostSelection.reset();
}
else
{
@@ -992,6 +1003,10 @@ void LLLineEditor::addChar(const llwchar uni_char)
return;
mText.erase(getCursor(), 1);
+
+ mFontBufferPreSelection.reset();
+ mFontBufferSelection.reset();
+ mFontBufferPostSelection.reset();
}
S32 cur_bytes = static_cast<S32>(mText.getString().size());
@@ -1022,6 +1037,10 @@ void LLLineEditor::addChar(const llwchar uni_char)
mText.insert(getCursor(), w_buf);
setCursor(getCursor() + 1);
+
+ mFontBufferPreSelection.reset();
+ mFontBufferSelection.reset();
+ mFontBufferPostSelection.reset();
}
else
{
@@ -1186,6 +1205,10 @@ void LLLineEditor::deleteSelection()
mText.erase(left_pos, selection_length);
deselect();
setCursor(left_pos);
+
+ mFontBufferPreSelection.reset();
+ mFontBufferSelection.reset();
+ mFontBufferPostSelection.reset();
}
}
@@ -1346,6 +1369,10 @@ void LLLineEditor::pasteHelper(bool is_primary)
setCursor( getCursor() + (S32)clean_string.length() );
deselect();
+ mFontBufferPreSelection.reset();
+ mFontBufferSelection.reset();
+ mFontBufferPostSelection.reset();
+
// Validate new string and rollback the if needed.
bool need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString());
if (need_to_rollback)
@@ -1506,6 +1533,10 @@ bool LLLineEditor::handleSpecialKey(KEY key, MASK mask)
{
mText.assign(*(--mCurrentHistoryLine));
setCursorToEnd();
+
+ mFontBufferPreSelection.reset();
+ mFontBufferSelection.reset();
+ mFontBufferPostSelection.reset();
}
else
{
@@ -1523,6 +1554,10 @@ bool LLLineEditor::handleSpecialKey(KEY key, MASK mask)
{
mText.assign( *(++mCurrentHistoryLine) );
setCursorToEnd();
+
+ mFontBufferPreSelection.reset();
+ mFontBufferSelection.reset();
+ mFontBufferPostSelection.reset();
}
else
{
@@ -1897,7 +1932,8 @@ void LLLineEditor::draw()
if( select_left > mScrollHPos )
{
// unselected, left side
- rendered_text = mGLFont->render(
+ rendered_text = mFontBufferPreSelection.render(
+ mGLFont,
mText, mScrollHPos,
rendered_pixels_right, text_bottom,
text_color,
@@ -1919,7 +1955,8 @@ void LLLineEditor::draw()
gl_rect_2d(ll_round(rendered_pixels_right), cursor_top, ll_round(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(
+ rendered_text += mFontBufferSelection.render(
+ mGLFont,
mText, mScrollHPos + rendered_text,
rendered_pixels_right, text_bottom,
tmp_color,
@@ -1934,7 +1971,8 @@ void LLLineEditor::draw()
if( (rendered_pixels_right < (F32)mTextRightEdge) && (rendered_text < text_len) )
{
// unselected, right side
- rendered_text += mGLFont->render(
+ rendered_text += mFontBufferPostSelection.render(
+ mGLFont,
mText, mScrollHPos + rendered_text,
rendered_pixels_right, text_bottom,
text_color,
@@ -1948,7 +1986,8 @@ void LLLineEditor::draw()
}
else
{
- rendered_text = mGLFont->render(
+ rendered_text = mFontBufferPreSelection.render(
+ mGLFont,
mText, mScrollHPos,
rendered_pixels_right, text_bottom,
text_color,
@@ -2108,7 +2147,8 @@ void LLLineEditor::draw()
//to give indication that it is not text you typed in
if (0 == mText.length() && (mReadOnly || mShowLabelFocused))
{
- mGLFont->render(mLabel.getWString(), 0,
+ mFontBufferLabel.render(mGLFont,
+ mLabel.getWString(), 0,
(F32)mTextLeftEdge, (F32)text_bottom,
label_color,
LLFontGL::LEFT,
@@ -2133,7 +2173,8 @@ void LLLineEditor::draw()
// draw label if no text provided
if (0 == mText.length())
{
- mGLFont->render(mLabel.getWString(), 0,
+ mFontBufferLabel.render(mGLFont,
+ mLabel.getWString(), 0,
(F32)mTextLeftEdge, (F32)text_bottom,
label_color,
LLFontGL::LEFT,
@@ -2404,12 +2445,16 @@ void LLLineEditor::setKeystrokeCallback(callback_t callback, void* user_data)
bool LLLineEditor::setTextArg( const std::string& key, const LLStringExplicit& text )
{
mText.setArg(key, text);
+ mFontBufferPreSelection.reset();
+ mFontBufferSelection.reset();
+ mFontBufferPostSelection.reset();
return true;
}
bool LLLineEditor::setLabelArg( const std::string& key, const LLStringExplicit& text )
{
mLabel.setArg(key, text);
+ mFontBufferLabel.reset();
return true;
}
@@ -2508,6 +2553,9 @@ void LLLineEditor::updatePreedit(const LLWString &preedit_string,
mPreeditOverwrittenWString.clear();
}
mText.insert(insert_preedit_at, mPreeditWString);
+ mFontBufferPreSelection.reset();
+ mFontBufferSelection.reset();
+ mFontBufferPostSelection.reset();
mPreeditStandouts = preedit_standouts;
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index cdd22413e7..12fe800acb 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -40,6 +40,7 @@
#include "llframetimer.h"
#include "lleditmenuhandler.h"
+#include "llfontvertexbuffer.h"
#include "llspellcheckmenuhandler.h"
#include "lluictrl.h"
#include "lluiimage.h"
@@ -344,6 +345,10 @@ protected:
LLViewBorder* mBorder;
const LLFontGL* mGLFont;
+ LLFontVertexBuffer mFontBufferPreSelection;
+ LLFontVertexBuffer mFontBufferSelection;
+ LLFontVertexBuffer mFontBufferPostSelection;
+ LLFontVertexBuffer mFontBufferLabel;
S32 mMaxLengthBytes; // Max length of the UTF8 string in bytes
S32 mMaxLengthChars; // Maximum number of characters in the string
S32 mCursorPos; // I-beam is just after the mCursorPos-th character.
diff --git a/indra/llui/llstatbar.cpp b/indra/llui/llstatbar.cpp
index 2693243eb1..62c0401869 100644
--- a/indra/llui/llstatbar.cpp
+++ b/indra/llui/llstatbar.cpp
@@ -460,7 +460,7 @@ void LLStatBar::draw()
max_value = 0.f;
gGL.color4f(1.f, 0.f, 0.f, 1.f);
- gGL.begin( LLRender::QUADS );
+ gGL.begin(LLRender::TRIANGLES);
const S32 max_frame = llmin(num_frames, num_values);
U32 num_samples = 0;
for (S32 i = 1; i <= max_frame; i++)
@@ -498,6 +498,9 @@ void LLStatBar::draw()
gGL.vertex2f((F32)bar_rect.mRight - offset, max);
gGL.vertex2f((F32)bar_rect.mRight - offset, min);
gGL.vertex2f((F32)bar_rect.mRight - offset - 1, min);
+
+ gGL.vertex2f((F32)bar_rect.mRight - offset, max);
+ gGL.vertex2f((F32)bar_rect.mRight - offset - 1, min);
gGL.vertex2f((F32)bar_rect.mRight - offset - 1, max);
}
else
@@ -505,7 +508,10 @@ void LLStatBar::draw()
gGL.vertex2f(min, (F32)bar_rect.mBottom + offset + 1);
gGL.vertex2f(min, (F32)bar_rect.mBottom + offset);
gGL.vertex2f(max, (F32)bar_rect.mBottom + offset);
- gGL.vertex2f(max, (F32)bar_rect.mBottom + offset + 1 );
+
+ gGL.vertex2f(min, (F32)bar_rect.mBottom + offset + 1);
+ gGL.vertex2f(max, (F32)bar_rect.mBottom + offset);
+ gGL.vertex2f(max, (F32)bar_rect.mBottom + offset + 1);
}
}
gGL.end();
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 0aebf7543c..cbbf83d679 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -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();
@@ -2368,6 +2368,34 @@ S32 LLTextBase::removeFirstLine()
return 0;
}
+// virtual
+void LLTextBase::copyContents(const LLTextBase* source)
+{
+ llassert(source);
+ if (!source)
+ return;
+
+ beforeValueChange();
+ deselect();
+
+ mSegments.clear();
+ for (const LLTextSegmentPtr& segp : source->mSegments)
+ {
+ mSegments.emplace(segp->clone(*this));
+ }
+
+ mLineInfoList.clear();
+ for (const line_info& li : mLineInfoList)
+ {
+ mLineInfoList.push_back(line_info(li));
+ }
+
+ getViewModel()->setDisplay(source->getViewModel()->getDisplay());
+
+ onValueChange(0, getLength());
+ needsReflow();
+}
+
void LLTextBase::appendLineBreakSegment(const LLStyle::Params& style_params)
{
segment_vec_t segments;
@@ -2586,6 +2614,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.
@@ -3228,6 +3261,24 @@ boost::signals2::connection LLTextBase::setIsObjectBlockedCallback(const is_bloc
LLTextSegment::~LLTextSegment()
{}
+// static
+LLStyleSP LLTextSegment::cloneStyle(LLTextBase& target, const LLStyle* source)
+{
+ // Take most params from target
+ LLStyle::Params params = target.getStyleParams();
+ LLStyle* style = new LLStyle(params);
+
+ // Take some params from source
+ style->setLinkHREF(source->getLinkHREF());
+ if (source->isImage())
+ {
+ style->setImage(source->getImage()->getName());
+ }
+
+ return style;
+}
+
+
bool LLTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const { width = 0; height = 0; return false; }
bool LLTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const
{
@@ -3280,7 +3331,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 +3346,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,25 +3366,41 @@ 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;
}
- const LLFontGL* font = mStyle->getFont();
+ 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());
+ bool use_font_buffers = useFontBuffers();
if( selection_start > seg_start )
{
@@ -3339,16 +3408,40 @@ 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,
- rect,
- color,
- LLFontGL::LEFT, mEditor.mTextVAlign,
- LLFontGL::NORMAL,
- mStyle->getShadowType(),
- length,
- &right_x,
- mEditor.getUseEllipses(),
- mEditor.getUseColor());
+ if (use_font_buffers)
+ {
+ mFontBufferPreSelection.render(
+ font,
+ text, start,
+ rect,
+ color,
+ LLFontGL::LEFT, mEditor.mTextVAlign,
+ LLFontGL::NORMAL,
+ mStyle->getShadowType(),
+ length,
+ &right_x,
+ mEditor.getUseEllipses(),
+ mEditor.getUseColor());
+ }
+ else
+ {
+ // Font buffer doesn't do well with changes and huge notecard with a bunch
+ // of segments will see a lot of buffer updates, so instead use derect
+ // rendering to cache.
+ // Todo: instead of mLastGeneration make buffer invalidation more fine grained
+ // like string hash of a given segment.
+ font->render(
+ text, start,
+ rect,
+ color,
+ LLFontGL::LEFT, mEditor.mTextVAlign,
+ LLFontGL::NORMAL,
+ mStyle->getShadowType(),
+ length,
+ &right_x,
+ mEditor.getUseEllipses(),
+ mEditor.getUseColor());
+ }
}
rect.mLeft = right_x;
@@ -3359,16 +3452,35 @@ 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,
- rect,
- mStyle->getSelectedColor().get(),
- LLFontGL::LEFT, mEditor.mTextVAlign,
- LLFontGL::NORMAL,
- LLFontGL::NO_SHADOW,
- length,
- &right_x,
- mEditor.getUseEllipses(),
- mEditor.getUseColor());
+ if (use_font_buffers)
+ {
+ mFontBufferSelection.render(
+ font,
+ text, start,
+ rect,
+ mStyle->getSelectedColor().get(),
+ LLFontGL::LEFT, mEditor.mTextVAlign,
+ LLFontGL::NORMAL,
+ LLFontGL::NO_SHADOW,
+ length,
+ &right_x,
+ mEditor.getUseEllipses(),
+ mEditor.getUseColor());
+ }
+ else
+ {
+ font->render(
+ text, start,
+ rect,
+ mStyle->getSelectedColor().get(),
+ LLFontGL::LEFT, mEditor.mTextVAlign,
+ LLFontGL::NORMAL,
+ LLFontGL::NO_SHADOW,
+ length,
+ &right_x,
+ mEditor.getUseEllipses(),
+ mEditor.getUseColor());
+ }
}
rect.mLeft = right_x;
if( selection_end < seg_end )
@@ -3377,16 +3489,36 @@ 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,
- rect,
- color,
- LLFontGL::LEFT, mEditor.mTextVAlign,
- LLFontGL::NORMAL,
- mStyle->getShadowType(),
- length,
- &right_x,
- mEditor.getUseEllipses(),
- mEditor.getUseColor());
+ if (use_font_buffers)
+ {
+ mFontBufferPostSelection.render(
+ font,
+ text, start,
+ rect,
+ color,
+ LLFontGL::LEFT, mEditor.mTextVAlign,
+ LLFontGL::NORMAL,
+ mStyle->getShadowType(),
+ length,
+ &right_x,
+ mEditor.getUseEllipses(),
+ mEditor.getUseColor());
+ }
+ else
+ {
+ font->render(
+ text, start,
+ rect,
+ color,
+ LLFontGL::LEFT, mEditor.mTextVAlign,
+ LLFontGL::NORMAL,
+ mStyle->getShadowType(),
+ length,
+ &right_x,
+ mEditor.getUseEllipses(),
+ mEditor.getUseColor());
+
+ }
}
return right_x;
}
@@ -3488,6 +3620,13 @@ void LLNormalTextSegment::setToolTip(const std::string& tooltip)
mTooltip = tooltip;
}
+// virtual
+LLTextSegmentPtr LLNormalTextSegment::clone(LLTextBase& target) const
+{
+ LLStyleConstSP sp(cloneStyle(target, mStyle));
+ return new LLNormalTextSegment(sp, mStart, mEnd, target);
+}
+
bool LLNormalTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const
{
height = 0;
@@ -3573,6 +3712,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 [" <<
@@ -3606,6 +3754,13 @@ LLLabelTextSegment::LLLabelTextSegment( const LLUIColor& color, S32 start, S32 e
{
}
+// virtual
+LLTextSegmentPtr LLLabelTextSegment::clone(LLTextBase& target) const
+{
+ LLStyleConstSP sp(cloneStyle(target, mStyle));
+ return new LLLabelTextSegment(sp, mStart, mEnd, target);
+}
+
/*virtual*/
const LLWString& LLLabelTextSegment::getWText() const
{
@@ -3630,6 +3785,13 @@ LLEmojiTextSegment::LLEmojiTextSegment(const LLUIColor& color, S32 start, S32 en
{
}
+// virtual
+LLTextSegmentPtr LLEmojiTextSegment::clone(LLTextBase& target) const
+{
+ LLStyleConstSP sp(cloneStyle(target, mStyle));
+ return new LLEmojiTextSegment(sp, mStart, mEnd, target);
+}
+
bool LLEmojiTextSegment::handleToolTip(S32 x, S32 y, MASK mask)
{
if (mTooltip.empty())
@@ -3653,6 +3815,14 @@ LLOnHoverChangeableTextSegment::LLOnHoverChangeableTextSegment( LLStyleConstSP s
mHoveredStyle(style),
mNormalStyle(normal_style){}
+// virtual
+LLTextSegmentPtr LLOnHoverChangeableTextSegment::clone(LLTextBase& target) const
+{
+ LLStyleConstSP hsp(cloneStyle(target, mHoveredStyle));
+ LLStyleConstSP nsp(cloneStyle(target, mNormalStyle));
+ return new LLOnHoverChangeableTextSegment(hsp, nsp, mStart, mEnd, target);
+}
+
/*virtual*/
F32 LLOnHoverChangeableTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect)
{
@@ -3692,6 +3862,13 @@ LLInlineViewSegment::~LLInlineViewSegment()
mView->die();
}
+// virtual
+LLTextSegmentPtr LLInlineViewSegment::clone(LLTextBase& target) const
+{
+ llassert_always_msg(false, "NOT SUPPORTED");
+ return nullptr;
+}
+
bool LLInlineViewSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const
{
if (first_char == 0 && num_chars == 0)
@@ -3779,6 +3956,14 @@ LLLineBreakTextSegment::LLLineBreakTextSegment(LLStyleConstSP style,S32 pos):LLT
LLLineBreakTextSegment::~LLLineBreakTextSegment()
{
}
+
+// virtual
+LLTextSegmentPtr LLLineBreakTextSegment::clone(LLTextBase& target) const
+{
+ LLLineBreakTextSegment* copy = new LLLineBreakTextSegment(mStart);
+ copy->mFontHeight = mFontHeight;
+ return copy;
+}
bool LLLineBreakTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const
{
width = 0;
@@ -3806,8 +3991,16 @@ LLImageTextSegment::~LLImageTextSegment()
{
}
+// virtual
+LLTextSegmentPtr LLImageTextSegment::clone(LLTextBase& target) const
+{
+ LLStyleConstSP sp(cloneStyle(target, mStyle));
+ return new LLImageTextSegment(sp, mStart, target);
+}
+
static const S32 IMAGE_HPAD = 3;
+// virtual
bool LLImageTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const
{
width = 0;
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 00cf66b134..76d4e160af 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -30,6 +30,7 @@
#include "v4color.h"
#include "lleditmenuhandler.h"
+#include "llfontvertexbuffer.h"
#include "llspellcheckmenuhandler.h"
#include "llstyle.h"
#include "llkeywords.h"
@@ -44,6 +45,7 @@
class LLScrollContainer;
class LLContextMenu;
class LLUrlMatch;
+class LLTextBase;
///
/// A text segment is used to specify a subsection of a text string
@@ -61,6 +63,9 @@ public:
mEnd(end)
{}
virtual ~LLTextSegment();
+ virtual LLTextSegmentPtr clone(LLTextBase& terget) const { return new LLTextSegment(mStart, mEnd); }
+ static LLStyleSP cloneStyle(LLTextBase& target, const LLStyle* source);
+
bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const;
virtual bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;
@@ -127,10 +132,12 @@ public:
LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor );
LLNormalTextSegment( const LLUIColor& color, S32 start, S32 end, LLTextBase& editor, bool is_visible = true);
virtual ~LLNormalTextSegment();
+ /*virtual*/ LLTextSegmentPtr clone(LLTextBase& target) const;
/*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(); }
@@ -149,6 +156,7 @@ public:
/*virtual*/ bool handleToolTip(S32 x, S32 y, MASK mask);
protected:
+ virtual bool useFontBuffers() const { return true; }
F32 drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, LLRectf rect);
virtual const LLWString& getWText() const;
@@ -161,6 +169,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
@@ -171,6 +185,7 @@ class LLLabelTextSegment : public LLNormalTextSegment
public:
LLLabelTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor );
LLLabelTextSegment( const LLUIColor& color, S32 start, S32 end, LLTextBase& editor, bool is_visible = true);
+ /*virtual*/ LLTextSegmentPtr clone(LLTextBase& target) const;
protected:
@@ -185,6 +200,7 @@ class LLEmojiTextSegment : public LLNormalTextSegment
public:
LLEmojiTextSegment(LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor);
LLEmojiTextSegment(const LLUIColor& color, S32 start, S32 end, LLTextBase& editor, bool is_visible = true);
+ /*virtual*/ LLTextSegmentPtr clone(LLTextBase& target) const override;
bool canEdit() const override { return false; }
bool handleToolTip(S32 x, S32 y, MASK mask) override;
@@ -195,6 +211,7 @@ class LLOnHoverChangeableTextSegment : public LLNormalTextSegment
{
public:
LLOnHoverChangeableTextSegment( LLStyleConstSP style, LLStyleConstSP normal_style, S32 start, S32 end, LLTextBase& editor );
+ /*virtual*/ LLTextSegmentPtr clone(LLTextBase& target) const;
/*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
/*virtual*/ bool handleHover(S32 x, S32 y, MASK mask);
protected:
@@ -209,6 +226,7 @@ class LLIndexSegment : public LLTextSegment
{
public:
LLIndexSegment() : LLTextSegment(0, 0) {}
+ /*virtual*/ LLTextSegmentPtr clone(LLTextBase& target) const { return new LLIndexSegment(); }
};
class LLInlineViewSegment : public LLTextSegment
@@ -226,6 +244,8 @@ public:
LLInlineViewSegment(const Params& p, S32 start, S32 end);
~LLInlineViewSegment();
+ /*virtual*/ LLTextSegmentPtr clone(LLTextBase& target) const;
+
/*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) 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);
@@ -250,6 +270,7 @@ public:
LLLineBreakTextSegment(LLStyleConstSP style,S32 pos);
LLLineBreakTextSegment(S32 pos);
~LLLineBreakTextSegment();
+ /*virtual*/ LLTextSegmentPtr clone(LLTextBase& target) const;
/*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;
S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const;
F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
@@ -263,6 +284,8 @@ class LLImageTextSegment : public LLTextSegment
public:
LLImageTextSegment(LLStyleConstSP style,S32 pos,class LLTextBase& editor);
~LLImageTextSegment();
+ /*virtual*/ LLTextSegmentPtr clone(LLTextBase& target) const;
+
/*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;
S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 char_offset, S32 max_chars, S32 line_ind) const;
F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
@@ -432,6 +455,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());
@@ -475,7 +499,7 @@ public:
LLRect getDocRectFromDocIndex(S32 pos) const;
void setReadOnly(bool read_only) { mReadOnly = read_only; }
- bool getReadOnly() { return mReadOnly; }
+ bool getReadOnly() const { return mReadOnly; }
void setSkipLinkUnderline(bool skip_link_underline) { mSkipLinkUnderline = skip_link_underline; }
bool getSkipLinkUnderline() { return mSkipLinkUnderline; }
@@ -500,6 +524,7 @@ public:
const LLFontGL* getFont() const override { return mFont; }
+ virtual void copyContents(const LLTextBase* source);
virtual void appendLineBreakSegment(const LLStyle::Params& style_params);
virtual void appendImageSegment(const LLStyle::Params& style_params);
virtual void appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo);
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 0b5acf19a1..e9e7070414 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -271,6 +271,8 @@ protected:
virtual bool getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const;
virtual S32 getPreeditFontSize() const;
virtual LLWString getPreeditString() const { return getWText(); }
+
+ virtual bool useFontBuffers() const { return getReadOnly(); }
//
// Protected data
//
diff --git a/indra/llui/lltrans.cpp b/indra/llui/lltrans.cpp
index 8410031653..0c6c5b64e4 100644
--- a/indra/llui/lltrans.cpp
+++ b/indra/llui/lltrans.cpp
@@ -28,12 +28,8 @@
#include "lltrans.h"
-#include "llfasttimer.h" // for call count statistics
#include "llxuiparser.h"
#include "llsd.h"
-#include "llxmlnode.h"
-
-#include <map>
LLTrans::template_map_t LLTrans::sStringTemplates;
LLTrans::template_map_t LLTrans::sDefaultStringTemplates;
@@ -59,7 +55,7 @@ struct StringTable : public LLInitParam::Block<StringTable>
};
//static
-bool LLTrans::parseStrings(LLXMLNodePtr &root, const std::set<std::string>& default_args)
+bool LLTrans::parseStrings(LLXMLNodePtr& root, const std::set<std::string>& default_args)
{
std::string xml_filename = "(strings file)";
if (!root->hasName("strings"))
@@ -107,7 +103,7 @@ bool LLTrans::parseStrings(LLXMLNodePtr &root, const std::set<std::string>& defa
//static
-bool LLTrans::parseLanguageStrings(LLXMLNodePtr &root)
+bool LLTrans::parseLanguageStrings(LLXMLNodePtr& root)
{
std::string xml_filename = "(language strings file)";
if (!root->hasName("strings"))
@@ -138,10 +134,6 @@ bool LLTrans::parseLanguageStrings(LLXMLNodePtr &root)
return true;
}
-
-
-static LLTrace::BlockTimerStatHandle FTM_GET_TRANS("Translate string");
-
//static
std::string LLTrans::getString(std::string_view xml_desc, const LLStringUtil::format_map_t& msg_args, bool def_string)
{
@@ -235,7 +227,7 @@ std::string LLTrans::getDefString(std::string_view xml_desc, const LLSD& msg_arg
}
//static
-bool LLTrans::findString(std::string &result, std::string_view xml_desc, const LLStringUtil::format_map_t& msg_args)
+bool LLTrans::findString(std::string& result, std::string_view xml_desc, const LLStringUtil::format_map_t& msg_args)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
@@ -257,7 +249,7 @@ bool LLTrans::findString(std::string &result, std::string_view xml_desc, const L
}
//static
-bool LLTrans::findString(std::string &result, std::string_view xml_desc, const LLSD& msg_args)
+bool LLTrans::findString(std::string& result, std::string_view xml_desc, const LLSD& msg_args)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
@@ -277,7 +269,7 @@ bool LLTrans::findString(std::string &result, std::string_view xml_desc, const L
}
//static
-std::string LLTrans::getCountString(const std::string& language, const std::string& xml_desc, S32 count)
+std::string LLTrans::getCountString(std::string_view language, std::string_view xml_desc, S32 count)
{
// Compute which string identifier to use
const char* form = "";
@@ -337,7 +329,7 @@ std::string LLTrans::getCountString(const std::string& language, const std::stri
args["[COUNT]"] = llformat("%d", count);
// Look up "AgeYearsB" or "AgeWeeksC" including the "form"
- std::string key = llformat("%s%s", xml_desc.c_str(), form);
+ std::string key = llformat("%s%s", xml_desc.data(), form);
return getString(key, args);
}
diff --git a/indra/llui/lltrans.h b/indra/llui/lltrans.h
index 3492ed0169..c5d01e6f8d 100644
--- a/indra/llui/lltrans.h
+++ b/indra/llui/lltrans.h
@@ -30,10 +30,8 @@
#include <map>
#include <set>
-#include "llpointer.h"
#include "llstring.h"
-
-class LLXMLNode;
+#include "llxmlnode.h"
class LLSD;
@@ -58,17 +56,17 @@ public:
class LLTrans
{
public:
- LLTrans();
+ LLTrans() = default;
/**
* @brief Parses the xml root that holds the strings. Used once on startup
-// *FIXME * @param xml_filename Filename to parse
+ * @param root xml root node to parse
* @param default_args Set of strings (expected to be in the file) to use as default replacement args, e.g. "SECOND_LIFE"
* @returns true if the file was parsed successfully, true if something went wrong
*/
- static bool parseStrings(LLPointer<LLXMLNode> & root, const std::set<std::string>& default_args);
+ static bool parseStrings(LLXMLNodePtr& root, const std::set<std::string>& default_args);
- static bool parseLanguageStrings(LLPointer<LLXMLNode> & root);
+ static bool parseLanguageStrings(LLXMLNodePtr& root);
/**
* @brief Returns a translated string
@@ -80,14 +78,14 @@ public:
static std::string getDefString(std::string_view xml_desc, const LLStringUtil::format_map_t& args);
static std::string getString(std::string_view xml_desc, const LLSD& args, bool def_string = false);
static std::string getDefString(std::string_view xml_desc, const LLSD& args);
- static bool findString(std::string &result, std::string_view xml_desc, const LLStringUtil::format_map_t& args);
- static bool findString(std::string &result, std::string_view xml_desc, const LLSD& args);
+ static bool findString(std::string& result, std::string_view xml_desc, const LLStringUtil::format_map_t& args);
+ static bool findString(std::string& result, std::string_view xml_desc, const LLSD& args);
// Returns translated string with [COUNT] replaced with a number, following
// special per-language logic for plural nouns. For example, some languages
// may have different plurals for 0, 1, 2 and > 2.
// See "AgeWeeksA", "AgeWeeksB", etc. in strings.xml for examples.
- static std::string getCountString(const std::string& language, const std::string& xml_desc, S32 count);
+ static std::string getCountString(std::string_view language, std::string_view xml_desc, S32 count);
/**
* @brief Returns a translated string
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 79d2fcd049..3cc0c05ffa 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -600,15 +600,15 @@ void LLUrlEntryAgent::callObservers(const std::string &id,
void LLUrlEntryAgent::onAvatarNameCache(const LLUUID& id,
const LLAvatarName& av_name)
{
- avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.find(id);
- if (it != mAvatarNameCacheConnections.end())
+ auto range = mAvatarNameCacheConnections.equal_range(id);
+ for (avatar_name_cache_connection_map_t::iterator it = range.first; it != range.second; ++it)
{
if (it->second.connected())
{
it->second.disconnect();
}
- mAvatarNameCacheConnections.erase(it);
}
+ mAvatarNameCacheConnections.erase(range.first, range.second);
std::string label = av_name.getCompleteName();
@@ -695,16 +695,7 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa
}
else
{
- avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.find(agent_id);
- if (it != mAvatarNameCacheConnections.end())
- {
- if (it->second.connected())
- {
- it->second.disconnect();
- }
- mAvatarNameCacheConnections.erase(it);
- }
- mAvatarNameCacheConnections[agent_id] = LLAvatarNameCache::get(agent_id, boost::bind(&LLUrlEntryAgent::onAvatarNameCache, this, _1, _2));
+ mAvatarNameCacheConnections.emplace(agent_id, LLAvatarNameCache::get(agent_id, boost::bind(&LLUrlEntryAgent::onAvatarNameCache, this, _1, _2)));
addObserver(agent_id_string, url, cb);
return LLTrans::getString("LoadingData");
@@ -770,17 +761,17 @@ LLUrlEntryAgentName::LLUrlEntryAgentName()
{}
void LLUrlEntryAgentName::onAvatarNameCache(const LLUUID& id,
- const LLAvatarName& av_name)
+ const LLAvatarName& av_name)
{
- avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.find(id);
- if (it != mAvatarNameCacheConnections.end())
+ auto range = mAvatarNameCacheConnections.equal_range(id);
+ for (avatar_name_cache_connection_map_t::iterator it = range.first; it != range.second; ++it)
{
if (it->second.connected())
{
it->second.disconnect();
}
- mAvatarNameCacheConnections.erase(it);
}
+ mAvatarNameCacheConnections.erase(range.first, range.second);
std::string label = getName(av_name);
// received the agent name from the server - tell our observers
@@ -815,16 +806,7 @@ std::string LLUrlEntryAgentName::getLabel(const std::string &url, const LLUrlLab
}
else
{
- avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.find(agent_id);
- if (it != mAvatarNameCacheConnections.end())
- {
- if (it->second.connected())
- {
- it->second.disconnect();
- }
- mAvatarNameCacheConnections.erase(it);
- }
- mAvatarNameCacheConnections[agent_id] = LLAvatarNameCache::get(agent_id, boost::bind(&LLUrlEntryAgentName::onAvatarNameCache, this, _1, _2));
+ mAvatarNameCacheConnections.emplace(agent_id, LLAvatarNameCache::get(agent_id, boost::bind(&LLUrlEntryAgentName::onAvatarNameCache, this, _1, _2)));
addObserver(agent_id_string, url, cb);
return LLTrans::getString("LoadingData");
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index 84ff278942..fffee88496 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -232,7 +232,7 @@ protected:
private:
void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
- typedef std::map<LLUUID, boost::signals2::connection> avatar_name_cache_connection_map_t;
+ typedef std::multimap<LLUUID, boost::signals2::connection> avatar_name_cache_connection_map_t;
avatar_name_cache_connection_map_t mAvatarNameCacheConnections;
};
@@ -264,7 +264,7 @@ protected:
private:
void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
- typedef std::map<LLUUID, boost::signals2::connection> avatar_name_cache_connection_map_t;
+ typedef std::multimap<LLUUID, boost::signals2::connection> avatar_name_cache_connection_map_t;
avatar_name_cache_connection_map_t mAvatarNameCacheConnections;
};
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 7d6c937b85..0206e46b57 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -1370,8 +1370,10 @@ void LLView::drawDebugRect()
y = rect_height - LINE_HEIGHT * (depth % lines + 1);
- std::string debug_text = llformat("%s (%d x %d)", getName().c_str(),
- debug_rect.getWidth(), debug_rect.getHeight());
+ std::string debug_text = llformat("%s [%d, %d] + (%d x %d) = [%d, %d]", getName().c_str(),
+ debug_rect.mLeft, mParentView->getRect().getHeight() - debug_rect.mTop,
+ debug_rect.getWidth(), debug_rect.getHeight(),
+ debug_rect.mRight, mParentView->getRect().getHeight() - debug_rect.mBottom);
LLFontGL::getFontSansSerifSmall()->renderUTF8(debug_text, 0, (F32)x, (F32)y, border_color,
LLFontGL::HCENTER, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW);
}
diff --git a/indra/llui/llviewereventrecorder.cpp b/indra/llui/llviewereventrecorder.cpp
index e5e0545dad..6d907d7e45 100644
--- a/indra/llui/llviewereventrecorder.cpp
+++ b/indra/llui/llviewereventrecorder.cpp
@@ -261,7 +261,7 @@ void LLViewerEventRecorder::logKeyUnicodeEvent(llwchar uni_char) {
event.insert("event",LLSD("keyDown"));
- LL_DEBUGS() << "[VITA] unicode key: " << uni_char << LL_ENDL;
+ LL_DEBUGS() << "[VITA] unicode key: " << (int)uni_char << LL_ENDL;
LL_DEBUGS() << "[VITA] dumpxml " << LLSDXMLStreamer(event) << "\n" << LL_ENDL;
diff --git a/indra/llui/llviewmodel.cpp b/indra/llui/llviewmodel.cpp
index 93106b344f..35963c2b99 100644
--- a/indra/llui/llviewmodel.cpp
+++ b/indra/llui/llviewmodel.cpp
@@ -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
diff --git a/indra/llui/llviewmodel.h b/indra/llui/llviewmodel.h
index 6cf2200a81..16b0800ce2 100644
--- a/indra/llui/llviewmodel.h
+++ b/indra/llui/llviewmodel.h
@@ -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.