summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llfloater.cpp13
-rw-r--r--indra/llui/llkeywords.cpp82
-rw-r--r--indra/llui/llkeywords.h29
-rw-r--r--indra/llui/llresizehandle.cpp81
4 files changed, 160 insertions, 45 deletions
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 0199fe3f57..3e0c5ced1a 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -2387,10 +2387,17 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
LLRect new_rect;
new_rect.setLeftTopAndSize(view_rect.mLeft,view_rect.mTop,new_width, new_height);
- floater->reshape( new_width, new_height, TRUE );
- floater->setRect(new_rect);
+ floater->setShape(new_rect);
- floater->translateIntoRect( getLocalRect(), false );
+ if (floater->followsRight())
+ {
+ floater->translate(old_width - new_width, 0);
+ }
+
+ if (floater->followsTop())
+ {
+ floater->translate(0, old_height - new_height);
+ }
}
}
diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp
index ede32084d0..75342afbe2 100644
--- a/indra/llui/llkeywords.cpp
+++ b/indra/llui/llkeywords.cpp
@@ -218,6 +218,86 @@ void LLKeywords::addToken(LLKeywordToken::TOKEN_TYPE type,
llassert(0);
}
}
+LLKeywords::WStringMapIndex::WStringMapIndex(const WStringMapIndex& other)
+{
+ if(other.mOwner)
+ {
+ copyData(other.mData, other.mLength);
+ }
+ else
+ {
+ mOwner = false;
+ mLength = other.mLength;
+ mData = other.mData;
+ }
+}
+
+LLKeywords::WStringMapIndex::WStringMapIndex(const LLWString& str)
+{
+ copyData(str.data(), str.size());
+}
+
+LLKeywords::WStringMapIndex::WStringMapIndex(const llwchar *start, size_t length):
+mData(start), mLength(length), mOwner(false)
+{
+}
+
+LLKeywords::WStringMapIndex::~WStringMapIndex()
+{
+ if(mOwner)
+ delete[] mData;
+}
+
+void LLKeywords::WStringMapIndex::copyData(const llwchar *start, size_t length)
+{
+ llwchar *data = new llwchar[length];
+ memcpy((void*)data, (const void*)start, length * sizeof(llwchar));
+
+ mOwner = true;
+ mLength = length;
+ mData = data;
+}
+
+bool LLKeywords::WStringMapIndex::operator<(const LLKeywords::WStringMapIndex &other) const
+{
+ // NOTE: Since this is only used to organize a std::map, it doesn't matter if it uses correct collate order or not.
+ // The comparison only needs to strictly order all possible strings, and be stable.
+
+ bool result = false;
+ const llwchar* self_iter = mData;
+ const llwchar* self_end = mData + mLength;
+ const llwchar* other_iter = other.mData;
+ const llwchar* other_end = other.mData + other.mLength;
+
+ while(true)
+ {
+ if(other_iter >= other_end)
+ {
+ // We've hit the end of other.
+ // This covers two cases: other being shorter than self, or the strings being equal.
+ // In either case, we want to return false.
+ result = false;
+ break;
+ }
+ else if(self_iter >= self_end)
+ {
+ // self is shorter than other.
+ result = true;
+ break;
+ }
+ else if(*self_iter != *other_iter)
+ {
+ // The current character differs. The strings are not equal.
+ result = *self_iter < *other_iter;
+ break;
+ }
+
+ self_iter++;
+ other_iter++;
+ }
+
+ return result;
+}
LLColor3 LLKeywords::readColor( const std::string& s )
{
@@ -429,7 +509,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
S32 seg_len = p - cur;
if( seg_len > 0 )
{
- LLWString word( cur, 0, seg_len );
+ WStringMapIndex word( cur, seg_len );
word_token_map_t::iterator map_iter = mWordTokenMap.find(word);
if( map_iter != mWordTokenMap.end() )
{
diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h
index 53377869ca..e5b66dfa56 100644
--- a/indra/llui/llkeywords.h
+++ b/indra/llui/llkeywords.h
@@ -92,8 +92,33 @@ public:
const std::string& key,
const LLColor3& color,
const std::string& tool_tip = LLStringUtil::null);
-
- typedef std::map<LLWString, LLKeywordToken*> word_token_map_t;
+
+ // This class is here as a performance optimization.
+ // The word token map used to be defined as std::map<LLWString, LLKeywordToken*>.
+ // This worked, but caused a performance bottleneck due to memory allocation and string copies
+ // because it's not possible to search such a map without creating an LLWString.
+ // Using this class as the map index instead allows us to search using segments of an existing
+ // text run without copying them first, which greatly reduces overhead in LLKeywords::findSegments().
+ class WStringMapIndex
+ {
+ public:
+ // copy constructor
+ WStringMapIndex(const WStringMapIndex& other);
+ // constructor from a string (copies the string's data into the new object)
+ WStringMapIndex(const LLWString& str);
+ // constructor from pointer and length
+ // NOTE: does NOT copy data, caller must ensure that the lifetime of the pointer exceeds that of the new object!
+ WStringMapIndex(const llwchar *start, size_t length);
+ ~WStringMapIndex();
+ bool operator<(const WStringMapIndex &other) const;
+ private:
+ void copyData(const llwchar *start, size_t length);
+ const llwchar *mData;
+ size_t mLength;
+ bool mOwner;
+ };
+
+ typedef std::map<WStringMapIndex, LLKeywordToken*> word_token_map_t;
typedef word_token_map_t::const_iterator keyword_iterator_t;
keyword_iterator_t begin() const { return mWordTokenMap.begin(); }
keyword_iterator_t end() const { return mWordTokenMap.end(); }
diff --git a/indra/llui/llresizehandle.cpp b/indra/llui/llresizehandle.cpp
index 367666efbd..00214d451c 100644
--- a/indra/llui/llresizehandle.cpp
+++ b/indra/llui/llresizehandle.cpp
@@ -124,7 +124,7 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
{
// Make sure the mouse in still over the application. We don't want to make the parent
// so big that we can't see the resize handle any more.
-
+
S32 screen_x;
S32 screen_y;
localPointToScreen(x, y, &screen_x, &screen_y);
@@ -147,61 +147,68 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
LLRect scaled_rect = orig_rect;
S32 delta_x = screen_x - mDragLastScreenX;
S32 delta_y = screen_y - mDragLastScreenY;
-
- if(delta_x == 0 && delta_y == 0)
- return FALSE;
-
LLCoordGL mouse_dir;
// use hysteresis on mouse motion to preserve user intent when mouse stops moving
mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX;
mouse_dir.mY = (screen_y == mLastMouseScreenY) ? mLastMouseDir.mY : screen_y - mLastMouseScreenY;
-
mLastMouseScreenX = screen_x;
mLastMouseScreenY = screen_y;
mLastMouseDir = mouse_dir;
- S32 new_width = orig_rect.getWidth();
- S32 new_height = orig_rect.getHeight();
+ S32 x_multiple = 1;
+ S32 y_multiple = 1;
+ switch( mCorner )
+ {
+ case LEFT_TOP:
+ x_multiple = -1;
+ y_multiple = 1;
+ break;
+ case LEFT_BOTTOM:
+ x_multiple = -1;
+ y_multiple = -1;
+ break;
+ case RIGHT_TOP:
+ x_multiple = 1;
+ y_multiple = 1;
+ break;
+ case RIGHT_BOTTOM:
+ x_multiple = 1;
+ y_multiple = -1;
+ break;
+ }
- S32 new_pos_x = orig_rect.mLeft;
- S32 new_pos_y = orig_rect.mTop;
+ S32 new_width = orig_rect.getWidth() + x_multiple * delta_x;
+ if( new_width < mMinWidth )
+ {
+ new_width = mMinWidth;
+ delta_x = x_multiple * (mMinWidth - orig_rect.getWidth());
+ }
+
+ S32 new_height = orig_rect.getHeight() + y_multiple * delta_y;
+ if( new_height < mMinHeight )
+ {
+ new_height = mMinHeight;
+ delta_y = y_multiple * (mMinHeight - orig_rect.getHeight());
+ }
switch( mCorner )
{
- case LEFT_TOP:
- new_width-=delta_x;
- new_height+=delta_y;
- new_pos_x+=delta_x;
- new_pos_y+=delta_y;
+ case LEFT_TOP:
+ scaled_rect.translate(delta_x, 0);
break;
case LEFT_BOTTOM:
- new_width-=delta_x;
- new_height-=delta_y;
- new_pos_x+=delta_x;
+ scaled_rect.translate(delta_x, delta_y);
break;
case RIGHT_TOP:
- new_width+=delta_x;
- new_height+=delta_y;
- new_pos_y+=delta_y;
break;
case RIGHT_BOTTOM:
- new_width+=delta_x;
- new_height-=delta_y;
+ scaled_rect.translate(0, delta_y);
break;
}
- new_width = llmax(new_width,mMinWidth);
- new_height = llmax(new_height,mMinHeight);
-
- LLRect::tCoordType screen_width = resizing_view->getParent()->getSnapRect().getWidth();
- LLRect::tCoordType screen_height = resizing_view->getParent()->getSnapRect().getHeight();
-
- new_width = llmin(new_width, screen_width);
- new_height = llmin(new_height, screen_height);
-
// temporarily set new parent rect
- scaled_rect.setLeftTopAndSize(new_pos_x,new_pos_y,new_width,new_height);
-
+ scaled_rect.mRight = scaled_rect.mLeft + new_width;
+ scaled_rect.mTop = scaled_rect.mBottom + new_height;
resizing_view->setRect(scaled_rect);
LLView* snap_view = NULL;
@@ -252,11 +259,7 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
resizing_view->setRect(orig_rect);
// translate and scale to new shape
- resizing_view->reshape(scaled_rect.getWidth(),scaled_rect.getHeight());
- resizing_view->setRect(scaled_rect);
- //set shape to handle dependent floaters...
- resizing_view->handleReshape(scaled_rect, false);
-
+ resizing_view->setShape(scaled_rect, true);
// update last valid mouse cursor position based on resized view's actual size
LLRect new_rect = resizing_view->getRect();