Reviewed by Sam Weinig.
- fix <rdar://problem/5842247> Single long breakable word takes O(n^2) to lay out
Cache the next breakable position for text nodes in InlineIterator.
* rendering/bidi.cpp:
(WebCore::InlineIterator::InlineIterator):
(WebCore::InlineIterator::increment):
(WebCore::RenderBlock::findNextLineBreak):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@36447 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 6b43af2..b4042c3 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,16 @@
+2008-09-15 Dan Bernstein <mitz@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ - fix <rdar://problem/5842247> Single long breakable word takes O(n^2) to lay out
+
+ Cache the next breakable position for text nodes in InlineIterator.
+
+ * rendering/bidi.cpp:
+ (WebCore::InlineIterator::InlineIterator):
+ (WebCore::InlineIterator::increment):
+ (WebCore::RenderBlock::findNextLineBreak):
+
2008-09-15 Simon Fraser <simon.fraser@apple.com>
Reviewed by Dan Bernstein
diff --git a/WebCore/rendering/bidi.cpp b/WebCore/rendering/bidi.cpp
index f1d3d5d..a64d632 100644
--- a/WebCore/rendering/bidi.cpp
+++ b/WebCore/rendering/bidi.cpp
@@ -52,6 +52,7 @@
: block(0)
, obj(0)
, pos(0)
+ , nextBreakablePosition(-1)
{
}
@@ -59,6 +60,7 @@
: block(b)
, obj(o)
, pos(p)
+ , nextBreakablePosition(-1)
{
}
@@ -71,6 +73,7 @@
RenderBlock* block;
RenderObject* obj;
unsigned pos;
+ int nextBreakablePosition;
};
// Midpoint globals. The goal is not to do any allocation when dealing with
@@ -270,10 +273,12 @@
if (pos >= static_cast<RenderText*>(obj)->textLength()) {
obj = bidiNext(block, obj, resolver);
pos = 0;
+ nextBreakablePosition = -1;
}
} else {
obj = bidiNext(block, obj, resolver);
pos = 0;
+ nextBreakablePosition = -1;
}
}
@@ -1582,6 +1587,7 @@
RenderObject *o = resolver.position().obj;
RenderObject *last = o;
unsigned pos = resolver.position().pos;
+ int nextBreakable = resolver.position().nextBreakablePosition;
bool atStart = true;
bool prevLineBrokeCleanly = previousLineBrokeCleanly;
@@ -1616,6 +1622,7 @@
if (w + tmpW <= width) {
lBreak.obj = o;
lBreak.pos = 0;
+ lBreak.nextBreakablePosition = -1;
lBreak.increment();
// A <br> always breaks a line, so don't let the line be collapsed
@@ -1717,6 +1724,7 @@
tmpW = 0;
lBreak.obj = o;
lBreak.pos = 0;
+ lBreak.nextBreakablePosition = -1;
}
if (ignoringSpaces)
@@ -1758,7 +1766,6 @@
int wrapW = tmpW + inlineWidth(o, !appliedStartWidth, true);
int charWidth = 0;
- int nextBreakable = -1;
bool breakNBSP = autoWrap && o->style()->nbspMode() == SPACE;
// Auto-wrapping text should wrap in the middle of a word only if it could not wrap before the word,
// which is only possible if the word is the first thing on the line, that is, if |w| is zero.
@@ -1771,6 +1778,7 @@
tmpW = 0;
lBreak.obj = o;
lBreak.pos = 0;
+ lBreak.nextBreakablePosition = -1;
ASSERT(!len);
}
@@ -1876,6 +1884,7 @@
lineWasTooWide = true;
lBreak.obj = o;
lBreak.pos = pos;
+ lBreak.nextBreakablePosition = nextBreakable;
skipTrailingWhitespace(lBreak);
}
}
@@ -1907,6 +1916,7 @@
}
lBreak.obj = o;
lBreak.pos = pos;
+ lBreak.nextBreakablePosition = nextBreakable;
lBreak.increment();
previousLineBrokeCleanly = true;
return lBreak;
@@ -1918,6 +1928,7 @@
tmpW = 0;
lBreak.obj = o;
lBreak.pos = pos;
+ lBreak.nextBreakablePosition = nextBreakable;
// Auto-wrapping text should not wrap in the middle of a word once it has had an
// opportunity to break after a word.
breakWords = false;
@@ -1928,6 +1939,7 @@
// adding the end width forces a break.
lBreak.obj = o;
lBreak.pos = pos;
+ lBreak.nextBreakablePosition = nextBreakable;
midWordBreak &= (breakWords || breakAll);
}
@@ -1967,6 +1979,7 @@
if (autoWrap && o->style()->breakOnlyAfterWhiteSpace()) {
lBreak.obj = o;
lBreak.pos = pos;
+ lBreak.nextBreakablePosition = nextBreakable;
}
}
@@ -2018,6 +2031,7 @@
tmpW = 0;
lBreak.obj = next;
lBreak.pos = 0;
+ lBreak.nextBreakablePosition = -1;
}
}
}
@@ -2047,10 +2061,12 @@
tmpW = 0;
lBreak.obj = next;
lBreak.pos = 0;
+ lBreak.nextBreakablePosition = -1;
}
}
o = next;
+ nextBreakable = -1;
// Clear out our character space bool, since inline <pre>s don't collapse whitespace
// with adjacent inline normal/nowrap spans.
@@ -2065,6 +2081,7 @@
if (w + tmpW <= width || lastWS == NOWRAP) {
lBreak.obj = 0;
lBreak.pos = 0;
+ lBreak.nextBreakablePosition = -1;
}
end:
@@ -2079,18 +2096,21 @@
} else {
lBreak.obj = last;
lBreak.pos = last->isText() ? last->length() : 0;
+ lBreak.nextBreakablePosition = -1;
}
} else if (lBreak.obj) {
if (last != o && !last->isListMarker()) {
// better to break between object boundaries than in the middle of a word (except for list markers)
lBreak.obj = o;
lBreak.pos = 0;
+ lBreak.nextBreakablePosition = -1;
} else {
// Don't ever break in the middle of a word if we can help it.
// There's no room at all. We just have to be on this line,
// even though we'll spill out.
lBreak.obj = o;
lBreak.pos = pos;
+ lBreak.nextBreakablePosition = -1;
}
}
}