Index: third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp |
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp |
index 8238bf2bff88459dae29504f1c0fcacc4a134c02..495ccd553791c65849e9f5f39fe29226201d4105 100644 |
--- a/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp |
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp |
@@ -427,8 +427,39 @@ void LayoutBlockFlow::setMarginsForRubyRun(BidiRun* run, LayoutRubyRun* layoutRu |
setMarginEndForChild(*layoutRubyRun, LayoutUnit(-endOverhang)); |
} |
+static inline size_t findWordMeasurement(LineLayoutText layoutText, int offset, |
+ WordMeasurements& wordMeasurements, size_t lastIndex) |
+{ |
+ // In LTR, lastIndex should match since the order of BidiRun (visual) and |
+ // WordMeasurement (logical) are the same. |
+ size_t size = wordMeasurements.size(); |
+ if (lastIndex < size) { |
+ const WordMeasurement& wordMeasurement = wordMeasurements[lastIndex]; |
+ if (wordMeasurement.layoutText == layoutText && wordMeasurement.startOffset == offset) |
+ return lastIndex; |
+ } |
+ |
+ // In RTL, scan the whole array because they are not the same. |
+ for (size_t i = 0; i < size; ++i) { |
+ const WordMeasurement& wordMeasurement = wordMeasurements[i]; |
+ if (wordMeasurement.layoutText != layoutText) |
+ continue; |
+ if (wordMeasurement.startOffset == offset) |
+ return i; |
+ if (wordMeasurement.startOffset > offset) |
+ break; |
+ } |
+ |
+ // In RTL with space collpasing or in LTR/RTL mixed lines, there can be no |
+ // matches because spaces are handled differently in BidiRun and |
+ // WordMeasurement. This can cause slight performance hit and slight |
+ // differences in glyph positions since we re-measure the whole run. |
+ return size; |
+} |
+ |
static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* run, LineLayoutText layoutText, LayoutUnit xPos, const LineInfo& lineInfo, |
- GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache, WordMeasurements& wordMeasurements) |
+ GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache, WordMeasurements& wordMeasurements, |
+ size_t& wordMeasurementsIndex) |
{ |
HashSet<const SimpleFontData*> fallbackFonts; |
GlyphOverflow glyphOverflow; |
@@ -454,12 +485,13 @@ static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* ru |
if (canUseCachedWordMeasurements) { |
int lastEndOffset = run->m_start; |
- for (size_t i = 0, size = wordMeasurements.size(); i < size && lastEndOffset < run->m_stop; ++i) { |
+ size_t i = findWordMeasurement(layoutText, lastEndOffset, wordMeasurements, wordMeasurementsIndex); |
+ for (size_t size = wordMeasurements.size(); i < size && lastEndOffset < run->m_stop; ++i) { |
const WordMeasurement& wordMeasurement = wordMeasurements[i]; |
if (wordMeasurement.startOffset == wordMeasurement.endOffset) |
continue; |
if (wordMeasurement.layoutText != layoutText || wordMeasurement.startOffset != lastEndOffset || wordMeasurement.endOffset > run->m_stop) |
- continue; |
+ break; |
lastEndOffset = wordMeasurement.endOffset; |
if (kerningIsEnabled && lastEndOffset == run->m_stop) { |
@@ -479,6 +511,7 @@ static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* ru |
fallbackFonts.add(*it); |
} |
} |
+ wordMeasurementsIndex = i; |
if (lastEndOffset != run->m_stop) { |
// If we don't have enough cached data, we'll measure the run again. |
canUseCachedWordMeasurements = false; |
@@ -620,6 +653,7 @@ BidiRun* LayoutBlockFlow::computeInlineDirectionPositionsForSegment(RootInlineBo |
TextJustify textJustify = style()->getTextJustify(); |
BidiRun* r = firstRun; |
+ size_t wordMeasurementsIndex = 0; |
for (; r; r = r->next()) { |
if (!r->m_box || r->m_lineLayoutItem.isOutOfFlowPositioned() || r->m_box->isLineBreak()) { |
continue; // Positioned objects are only participating to figure out their |
@@ -640,7 +674,7 @@ BidiRun* LayoutBlockFlow::computeInlineDirectionPositionsForSegment(RootInlineBo |
needsWordSpacing = !isSpaceOrNewline(rt.characterAt(r->m_stop - 1)); |
} |
- setLogicalWidthForTextRun(lineBox, r, rt, totalLogicalWidth, lineInfo, textBoxDataMap, verticalPositionCache, wordMeasurements); |
+ setLogicalWidthForTextRun(lineBox, r, rt, totalLogicalWidth, lineInfo, textBoxDataMap, verticalPositionCache, wordMeasurements, wordMeasurementsIndex); |
} else { |
isAfterExpansion = false; |
if (!r->m_lineLayoutItem.isLayoutInline()) { |