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

Unified Diff: third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp

Issue 2285053002: Fix O(n!) in setLogicalWidthForTextRun (LayoutBlockFlowLine) (Closed)
Patch Set: Comments and perf tests updated Created 4 years, 4 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 | « third_party/WebKit/PerformanceTests/Layout/long-line-nowrap-spans-collapse.html ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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()) {
« no previous file with comments | « third_party/WebKit/PerformanceTests/Layout/long-line-nowrap-spans-collapse.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698