Bug 1114297 - Improve performance of nsTreeBodyFrame::AdjustForCellText for very long strings; r=smontagu
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -5116,16 +5116,38 @@ nsLayoutUtils::AppUnitWidthOfStringBidi(
}
aFontMetrics.SetTextRunRTL(false);
aFontMetrics.SetVertical(aFrame->GetWritingMode().IsVertical());
aFontMetrics.SetTextOrientation(aFrame->StyleVisibility()->mTextOrientation);
return nsLayoutUtils::AppUnitWidthOfString(aString, aLength, aFontMetrics,
aContext);
}
+bool
+nsLayoutUtils::StringWidthIsGreaterThan(const nsString& aString,
+ nsFontMetrics& aFontMetrics,
+ nsRenderingContext& aContext,
+ nscoord aWidth)
+{
+ const char16_t *string = aString.get();
+ uint32_t length = aString.Length();
+ uint32_t maxChunkLength = GetMaxChunkLength(aFontMetrics);
+ nscoord width = 0;
+ while (length > 0) {
+ int32_t len = FindSafeLength(string, length, maxChunkLength);
+ width += aFontMetrics.GetWidth(string, len, &aContext);
+ if (width > aWidth) {
+ return true;
+ }
+ length -= len;
+ string += len;
+ }
+ return false;
+}
+
nsBoundingMetrics
nsLayoutUtils::AppUnitBoundsOfString(const char16_t* aString,
uint32_t aLength,
nsFontMetrics& aFontMetrics,
nsRenderingContext& aContext)
{
uint32_t maxChunkLength = GetMaxChunkLength(aFontMetrics);
int32_t len = FindSafeLength(aString, aLength, maxChunkLength);
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -1481,16 +1481,21 @@ public:
aFontMetrics, aContext);
}
static nscoord AppUnitWidthOfStringBidi(const char16_t* aString,
uint32_t aLength,
const nsIFrame* aFrame,
nsFontMetrics& aFontMetrics,
nsRenderingContext& aContext);
+ static bool StringWidthIsGreaterThan(const nsString& aString,
+ nsFontMetrics& aFontMetrics,
+ nsRenderingContext& aContext,
+ nscoord aWidth);
+
static nsBoundingMetrics AppUnitBoundsOfString(const char16_t* aString,
uint32_t aLength,
nsFontMetrics& aFontMetrics,
nsRenderingContext& aContext);
static void DrawString(const nsIFrame* aFrame,
nsFontMetrics& aFontMetrics,
nsRenderingContext* aContext,
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -1314,25 +1314,26 @@ void
nsTreeBodyFrame::AdjustForCellText(nsAutoString& aText,
int32_t aRowIndex, nsTreeColumn* aColumn,
nsRenderingContext& aRenderingContext,
nsFontMetrics& aFontMetrics,
nsRect& aTextRect)
{
NS_PRECONDITION(aColumn && aColumn->GetFrame(), "invalid column passed");
- nscoord width = nsLayoutUtils::AppUnitWidthOfStringBidi(aText, this,
- aFontMetrics,
- aRenderingContext);
nscoord maxWidth = aTextRect.width;
+ bool widthIsGreater = nsLayoutUtils::StringWidthIsGreaterThan(aText,
+ aFontMetrics,
+ aRenderingContext,
+ maxWidth);
if (aColumn->Overflow()) {
DebugOnly<nsresult> rv;
nsTreeColumn* nextColumn = aColumn->GetNext();
- while (nextColumn && width > maxWidth) {
+ while (nextColumn && widthIsGreater) {
while (nextColumn) {
nscoord width;
rv = nextColumn->GetWidthInTwips(this, &width);
NS_ASSERTION(NS_SUCCEEDED(rv), "nextColumn is invalid");
if (width != 0)
break;
@@ -1346,27 +1347,32 @@ nsTreeBodyFrame::AdjustForCellText(nsAut
// bidi-ness
if (nextText.Length() == 0) {
nscoord width;
rv = nextColumn->GetWidthInTwips(this, &width);
NS_ASSERTION(NS_SUCCEEDED(rv), "nextColumn is invalid");
maxWidth += width;
+ widthIsGreater = nsLayoutUtils::StringWidthIsGreaterThan(aText,
+ aFontMetrics,
+ aRenderingContext,
+ maxWidth);
nextColumn = nextColumn->GetNext();
}
else {
nextColumn = nullptr;
}
}
}
}
- if (width > maxWidth) {
+ nscoord width;
+ if (widthIsGreater) {
// See if the width is even smaller than the ellipsis
// If so, clear the text completely.
const nsDependentString& kEllipsis = nsContentUtils::GetLocalizedEllipsis();
aFontMetrics.SetTextRunRTL(false);
nscoord ellipsisWidth =
nsLayoutUtils::AppUnitWidthOfString(kEllipsis, aFontMetrics,
aRenderingContext);
@@ -1453,21 +1459,21 @@ nsTreeBodyFrame::AdjustForCellText(nsAut
}
aText = leftStr;
aText.Append(kEllipsis);
aText += rightStr;
}
break;
}
}
-
- width = nsLayoutUtils::AppUnitWidthOfStringBidi(aText, this, aFontMetrics,
- aRenderingContext);
}
+ width = nsLayoutUtils::AppUnitWidthOfStringBidi(aText, this, aFontMetrics,
+ aRenderingContext);
+
switch (aColumn->GetTextAlignment()) {
case NS_STYLE_TEXT_ALIGN_RIGHT: {
aTextRect.x += aTextRect.width - width;
}
break;
case NS_STYLE_TEXT_ALIGN_CENTER: {
aTextRect.x += (aTextRect.width - width) / 2;
}