Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1312)

Unified Diff: Source/core/layout/LayoutText.cpp

Issue 1179723002: Store glyph bounds in WordMeasurement to avoid slow path width calc (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebase Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/layout/LayoutText.h ('k') | Source/core/layout/LayoutTextCombine.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/layout/LayoutText.cpp
diff --git a/Source/core/layout/LayoutText.cpp b/Source/core/layout/LayoutText.cpp
index 7d991cba5497a25dd23964a20ed8221d791fa261..e6fcba133d1681440e6746f2d223ba77f6b999b3 100644
--- a/Source/core/layout/LayoutText.cpp
+++ b/Source/core/layout/LayoutText.cpp
@@ -38,6 +38,7 @@
#include "core/layout/TextRunConstructor.h"
#include "core/layout/line/AbstractInlineTextBox.h"
#include "core/layout/line/EllipsisBox.h"
+#include "core/layout/line/GlyphOverflow.h"
#include "core/layout/line/InlineTextBox.h"
#include "core/paint/DeprecatedPaintLayer.h"
#include "platform/fonts/Character.h"
@@ -707,7 +708,7 @@ LayoutRect LayoutText::localCaretRect(InlineBox* inlineBox, int caretOffset, Lay
return LayoutRect(style()->isHorizontalWritingMode() ? IntRect(left, top, caretWidth(), height) : IntRect(top, left, height, caretWidth()));
}
-ALWAYS_INLINE float LayoutText::widthFromCache(const Font& f, int start, int len, float xPos, TextDirection textDirection, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
+ALWAYS_INLINE float LayoutText::widthFromFont(const Font& f, int start, int len, float leadWidth, float textWidthSoFar, TextDirection textDirection, HashSet<const SimpleFontData*>* fallbackFonts, FloatRect* glyphBoundsAccumulation) const
{
if (style()->hasTextCombine() && isCombineText()) {
const LayoutTextCombine* combineText = toLayoutTextCombine(this);
@@ -720,8 +721,15 @@ ALWAYS_INLINE float LayoutText::widthFromCache(const Font& f, int start, int len
ASSERT(run.charactersLength() >= run.length());
run.setCodePath(canUseSimpleFontCodePath() ? TextRun::ForceSimple : TextRun::ForceComplex);
run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize());
- run.setXPos(xPos);
- return f.width(run, fallbackFonts, glyphOverflow);
+ run.setXPos(leadWidth + textWidthSoFar);
+
+ FloatRect newGlyphBounds;
+ float result = f.width(run, fallbackFonts, glyphBoundsAccumulation ? &newGlyphBounds : nullptr);
+ if (glyphBoundsAccumulation) {
+ newGlyphBounds.move(textWidthSoFar, 0);
+ glyphBoundsAccumulation->unite(newGlyphBounds);
+ }
+ return result;
}
void LayoutText::trimmedPrefWidths(LayoutUnit leadWidthLayoutUnit,
@@ -801,7 +809,7 @@ void LayoutText::trimmedPrefWidths(LayoutUnit leadWidthLayoutUnit,
linelen++;
if (linelen) {
- lastLineMaxWidth = widthFromCache(f, i, linelen, leadWidth + lastLineMaxWidth, direction, 0, 0);
+ lastLineMaxWidth = widthFromFont(f, i, linelen, leadWidth, lastLineMaxWidth.toFloat(), direction, nullptr, nullptr);
if (firstLine) {
firstLine = false;
leadWidth = 0.f;
@@ -845,12 +853,8 @@ float LayoutText::maxLogicalWidth() const
void LayoutText::computePreferredLogicalWidths(float leadWidth)
{
HashSet<const SimpleFontData*> fallbackFonts;
- GlyphOverflow glyphOverflow;
- computePreferredLogicalWidths(leadWidth, fallbackFonts, glyphOverflow);
-
- // We shouldn't change our mind once we "know".
- ASSERT(!m_knownToHaveNoOverflowAndNoFallbackFonts || (fallbackFonts.isEmpty() && glyphOverflow.isZero()));
- m_knownToHaveNoOverflowAndNoFallbackFonts = fallbackFonts.isEmpty() && glyphOverflow.isZero();
+ FloatRect glyphBounds;
+ computePreferredLogicalWidths(leadWidth, fallbackFonts, glyphBounds);
}
static inline float hyphenWidth(LayoutText* layoutObject, const Font& font, TextDirection direction)
@@ -859,7 +863,7 @@ static inline float hyphenWidth(LayoutText* layoutObject, const Font& font, Text
return font.width(constructTextRun(layoutObject, font, style.hyphenString().string(), style, direction));
}
-void LayoutText::computePreferredLogicalWidths(float leadWidth, HashSet<const SimpleFontData*>& fallbackFonts, GlyphOverflow& glyphOverflow)
+void LayoutText::computePreferredLogicalWidths(float leadWidth, HashSet<const SimpleFontData*>& fallbackFonts, FloatRect& glyphBounds)
{
ASSERT(m_hasTab || preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflowAndNoFallbackFonts);
@@ -894,8 +898,6 @@ void LayoutText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
int lastWordBoundary = 0;
float cachedWordTrailingSpaceWidth[2] = { 0, 0 }; // LTR, RTL
- int firstGlyphLeftOverflow = -1;
-
bool breakAll = (styleToUse.wordBreak() == BreakAllWordBreak || styleToUse.wordBreak() == BreakWordBreak) && styleToUse.autoWrap();
bool keepAll = styleToUse.wordBreak() == KeepAllWordBreak && styleToUse.autoWrap();
@@ -973,9 +975,7 @@ void LayoutText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
continue;
}
if (c == softHyphenCharacter) {
- currMaxWidth += widthFromCache(f, lastWordBoundary, i - lastWordBoundary, leadWidth + currMaxWidth, textDirection, &fallbackFonts, &glyphOverflow);
- if (firstGlyphLeftOverflow < 0)
- firstGlyphLeftOverflow = glyphOverflow.left;
+ currMaxWidth += widthFromFont(f, lastWordBoundary, i - lastWordBoundary, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBounds);
lastWordBoundary = i + 1;
continue;
}
@@ -1015,21 +1015,19 @@ void LayoutText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
float w;
if (wordTrailingSpaceWidth && isSpace) {
- w = widthFromCache(f, i, wordLen + 1, leadWidth + currMaxWidth, textDirection, &fallbackFonts, &glyphOverflow) - wordTrailingSpaceWidth;
+ w = widthFromFont(f, i, wordLen + 1, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBounds) - wordTrailingSpaceWidth;
} else {
- w = widthFromCache(f, i, wordLen, leadWidth + currMaxWidth, textDirection, &fallbackFonts, &glyphOverflow);
+ w = widthFromFont(f, i, wordLen, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBounds);
if (c == softHyphenCharacter)
currMinWidth += hyphenWidth(this, f, textDirection);
}
- if (firstGlyphLeftOverflow < 0)
- firstGlyphLeftOverflow = glyphOverflow.left;
currMinWidth += w;
if (betweenWords) {
if (lastWordBoundary == i)
currMaxWidth += w;
else
- currMaxWidth += widthFromCache(f, lastWordBoundary, j - lastWordBoundary, leadWidth + currMaxWidth, textDirection, &fallbackFonts, &glyphOverflow);
+ currMaxWidth += widthFromFont(f, lastWordBoundary, j - lastWordBoundary, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBounds);
lastWordBoundary = j;
}
@@ -1088,7 +1086,6 @@ void LayoutText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
run.setXPos(leadWidth + currMaxWidth);
currMaxWidth += f.width(run);
- glyphOverflow.right = 0;
needsWordSpacing = isSpace && !previousCharacterIsSpace && i == len - 1;
}
ASSERT(lastWordBoundary == i);
@@ -1098,9 +1095,6 @@ void LayoutText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
if (run)
bidiResolver.runs().deleteRuns();
- if (firstGlyphLeftOverflow > 0)
- glyphOverflow.left = firstGlyphLeftOverflow;
-
if ((needsWordSpacing && len > 1) || (ignoringSpaces && !firstWord))
currMaxWidth += wordSpacing;
@@ -1116,6 +1110,17 @@ void LayoutText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
m_lastLineLineMinWidth = currMaxWidth;
}
+ if (styleToUse.lineBoxContain() & LineBoxContainGlyphs) {
+ // We shouldn't change our mind once we "know".
+ ASSERT(!m_knownToHaveNoOverflowAndNoFallbackFonts);
+ } else {
+ GlyphOverflow glyphOverflow;
+ glyphOverflow.setFromBounds(glyphBounds, f.fontMetrics().floatAscent(), f.fontMetrics().floatDescent(), m_maxWidth);
+ // We shouldn't change our mind once we "know".
+ ASSERT(!m_knownToHaveNoOverflowAndNoFallbackFonts || (fallbackFonts.isEmpty() && glyphOverflow.isZero()));
+ m_knownToHaveNoOverflowAndNoFallbackFonts = fallbackFonts.isEmpty() && glyphOverflow.isZero();
+ }
+
clearPreferredLogicalWidthsDirty();
}
@@ -1460,7 +1465,7 @@ void LayoutText::positionLineBox(InlineBox* box)
m_containsReversedText |= !s->isLeftToRightDirection();
}
-float LayoutText::width(unsigned from, unsigned len, LayoutUnit xPos, TextDirection textDirection, bool firstLine, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
+float LayoutText::width(unsigned from, unsigned len, LayoutUnit xPos, TextDirection textDirection, bool firstLine, HashSet<const SimpleFontData*>* fallbackFonts, FloatRect* glyphBounds) const
{
if (from >= textLength())
return 0;
@@ -1468,10 +1473,10 @@ float LayoutText::width(unsigned from, unsigned len, LayoutUnit xPos, TextDirect
if (from + len > textLength())
len = textLength() - from;
- return width(from, len, style(firstLine)->font(), xPos, textDirection, fallbackFonts, glyphOverflow);
+ return width(from, len, style(firstLine)->font(), xPos, textDirection, fallbackFonts, glyphBounds);
}
-float LayoutText::width(unsigned from, unsigned len, const Font& f, LayoutUnit xPos, TextDirection textDirection, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
+float LayoutText::width(unsigned from, unsigned len, const Font& f, LayoutUnit xPos, TextDirection textDirection, HashSet<const SimpleFontData*>* fallbackFonts, FloatRect* glyphBounds) const
{
ASSERT(from + len <= textLength());
if (!textLength())
@@ -1479,22 +1484,19 @@ float LayoutText::width(unsigned from, unsigned len, const Font& f, LayoutUnit x
float w;
if (&f == &style()->font()) {
- if (!style()->preserveNewline() && !from && len == textLength() && (!glyphOverflow || !glyphOverflow->computeBounds)) {
+ if (!style()->preserveNewline() && !from && len == textLength()) {
if (fallbackFonts) {
- ASSERT(glyphOverflow);
- if (preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflowAndNoFallbackFonts) {
- const_cast<LayoutText*>(this)->computePreferredLogicalWidths(0, *fallbackFonts, *glyphOverflow);
- // We shouldn't change our mind once we "know".
- ASSERT(!m_knownToHaveNoOverflowAndNoFallbackFonts
- || (fallbackFonts->isEmpty() && glyphOverflow->isZero()));
- m_knownToHaveNoOverflowAndNoFallbackFonts = fallbackFonts->isEmpty() && glyphOverflow->isZero();
- }
+ ASSERT(glyphBounds);
+ if (preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflowAndNoFallbackFonts)
+ const_cast<LayoutText*>(this)->computePreferredLogicalWidths(0, *fallbackFonts, *glyphBounds);
+ else
+ *glyphBounds = FloatRect(0, -f.fontMetrics().floatAscent(), m_maxWidth, f.fontMetrics().floatHeight());
w = m_maxWidth;
} else {
w = maxLogicalWidth();
}
} else {
- w = widthFromCache(f, from, len, xPos.toFloat(), textDirection, fallbackFonts, glyphOverflow);
+ w = widthFromFont(f, from, len, xPos.toFloat(), 0, textDirection, fallbackFonts, glyphBounds);
}
} else {
TextRun run = constructTextRun(const_cast<LayoutText*>(this), f, this, from, len, styleRef(), textDirection);
@@ -1504,7 +1506,7 @@ float LayoutText::width(unsigned from, unsigned len, const Font& f, LayoutUnit x
run.setCodePath(canUseSimpleFontCodePath() ? TextRun::ForceSimple : TextRun::ForceComplex);
run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize());
run.setXPos(xPos.toFloat());
- w = f.width(run, fallbackFonts, glyphOverflow);
+ w = f.width(run, fallbackFonts, glyphBounds);
}
return w;
« no previous file with comments | « Source/core/layout/LayoutText.h ('k') | Source/core/layout/LayoutTextCombine.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698