Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp (176527 => 176528)
--- trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp 2014-11-25 00:10:17 UTC (rev 176527)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp 2014-11-25 00:15:46 UTC (rev 176528)
@@ -52,7 +52,7 @@
unsigned startPosition = 0;
for (auto& textChild : childrenOfType<RenderText>(flow)) {
unsigned textLength = textChild.text()->length();
- segments.append(FlowContents::Segment { startPosition, startPosition + textLength, textChild });
+ segments.append(FlowContents::Segment { startPosition, startPosition + textLength, textChild.text(), textChild });
startPosition += textLength;
}
return segments;
@@ -61,28 +61,55 @@
FlowContents::FlowContents(const RenderBlockFlow& flow)
: m_style(flow.style())
, m_segments(initializeSegments(flow))
- , m_lineBreakIterator(downcast<RenderText>(*flow.firstChild()).text(), flow.style().locale())
+ , m_lineBreakIterator(m_segments[0].text, flow.style().locale())
, m_lastSegmentIndex(0)
{
}
unsigned FlowContents::findNextBreakablePosition(unsigned position) const
{
- String string = m_lineBreakIterator.string();
- unsigned breakablePosition = nextBreakablePositionNonLoosely<LChar, NBSPBehavior::IgnoreNBSP>(m_lineBreakIterator, string.characters8(), string.length(), position);
- if (appendNextRendererContentIfNeeded(breakablePosition))
- return findNextBreakablePosition(position);
- ASSERT(breakablePosition >= position);
- return breakablePosition;
+ while (!isEnd(position)) {
+ auto& segment = segmentForPosition(position);
+ if (segment.text.impl() != m_lineBreakIterator.string().impl()) {
+ UChar lastCharacter = segment.start > 0 ? characterAt(segment.start - 1) : 0;
+ UChar secondToLastCharacter = segment.start > 1 ? characterAt(segment.start - 2) : 0;
+ m_lineBreakIterator.setPriorContext(lastCharacter, secondToLastCharacter);
+ m_lineBreakIterator.resetStringAndReleaseIterator(segment.text, m_style.locale, LineBreakIteratorModeUAX14);
+ }
+
+ auto* characters = segment.text.characters8();
+ unsigned segmentLength = segment.end - segment.start;
+ unsigned segmentPosition = position - segment.start;
+ unsigned breakable = nextBreakablePositionNonLoosely<LChar, NBSPBehavior::IgnoreNBSP>(m_lineBreakIterator, characters, segmentLength, segmentPosition);
+ position = segment.start + breakable;
+ if (position < segment.end)
+ break;
+ }
+ return position;
}
+static bool findNextNonWhitespace(const FlowContents::Segment& segment, const FlowContents::Style& style, unsigned& position, unsigned& spaceCount)
+{
+ const LChar* text = segment.text.characters8();
+ for (; position < segment.end; ++position) {
+ auto character = text[position - segment.start];
+ bool isSpace = character == ' ';
+ bool isWhitespace = isSpace || character == '\t' || (!style.preserveNewline && character == '\n');
+ if (!isWhitespace)
+ return true;
+ if (isSpace)
+ ++spaceCount;
+ }
+ return false;
+}
+
unsigned FlowContents::findNextNonWhitespacePosition(unsigned position, unsigned& spaceCount) const
{
- unsigned nonWhitespacePosition = nextNonWhitespacePosition(position, spaceCount);
- if (appendNextRendererContentIfNeeded(nonWhitespacePosition))
- return findNextNonWhitespacePosition(position, spaceCount);
- ASSERT(nonWhitespacePosition >= position);
- return nonWhitespacePosition;
+ for (unsigned i = segmentIndexForPosition(position); i < m_segments.size(); ++i) {
+ if (findNextNonWhitespace(m_segments[i], m_style, position, spaceCount))
+ break;
+ }
+ return position;
}
float FlowContents::textWidth(unsigned from, unsigned to, float xPosition) const
@@ -97,7 +124,7 @@
unsigned fragmentEnd = 0;
while (true) {
fragmentEnd = std::min(to, segment->end);
- textWidth += runWidth(segment->renderer, from - segment->start, fragmentEnd - segment->start, xPosition + textWidth);
+ textWidth += runWidth(segment->text, from - segment->start, fragmentEnd - segment->start, xPosition + textWidth);
if (fragmentEnd == to)
break;
from = fragmentEnd;
@@ -107,14 +134,15 @@
return textWidth;
}
-const FlowContents::Segment& FlowContents::segmentForPositionSlow(unsigned position) const
+unsigned FlowContents::segmentIndexForPositionSlow(unsigned position) const
{
auto it = std::lower_bound(m_segments.begin(), m_segments.end(), position, [](const Segment& segment, unsigned position) {
return segment.end <= position;
});
ASSERT(it != m_segments.end());
- m_lastSegmentIndex = it - m_segments.begin();
- return *it;
+ auto index = it - m_segments.begin();
+ m_lastSegmentIndex = index;
+ return index;
}
const FlowContents::Segment& FlowContents::segmentForRenderer(const RenderText& renderer) const
@@ -127,45 +155,13 @@
return m_segments.last();
}
-bool FlowContents::appendNextRendererContentIfNeeded(unsigned position) const
+float FlowContents::runWidth(const String& text, unsigned from, unsigned to, float xPosition) const
{
- if (isEnd(position))
- return false;
- String string = m_lineBreakIterator.string();
- if (position < string.length())
- return false;
-
- // Content needs to be requested sequentially.
- ASSERT(position == string.length());
- auto& segment = segmentForPosition(position);
-
- m_lineBreakIterator.resetStringAndReleaseIterator(string + String(segment.renderer.text()), m_style.locale, LineBreakIteratorModeUAX14);
- return true;
-}
-
-unsigned FlowContents::nextNonWhitespacePosition(unsigned position, unsigned& spaceCount) const
-{
- String string = m_lineBreakIterator.string();
- unsigned length = string.length();
- const LChar* text = string.characters8();
- for (; position < length; ++position) {
- bool isSpace = text[position] == ' ';
- if (!(isSpace || text[position] == '\t' || (!m_style.preserveNewline && text[position] == '\n')))
- return position;
- if (isSpace)
- ++spaceCount;
- }
- return length;
-}
-
-float FlowContents::runWidth(const RenderText& renderer, unsigned from, unsigned to, float xPosition) const
-{
ASSERT(from < to);
- String string = renderer.text();
- bool measureWithEndSpace = m_style.collapseWhitespace && to < string.length() && string[to] == ' ';
+ bool measureWithEndSpace = m_style.collapseWhitespace && to < text.length() && text[to] == ' ';
if (measureWithEndSpace)
++to;
- TextRun run(string.characters8() + from, to - from);
+ TextRun run(text.characters8() + from, to - from);
run.setXPos(xPosition);
run.setTabSize(!!m_style.tabWidth, m_style.tabWidth);
float width = m_style.font.width(run);
Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.h (176527 => 176528)
--- trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.h 2014-11-25 00:10:17 UTC (rev 176527)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.h 2014-11-25 00:15:46 UTC (rev 176528)
@@ -51,6 +51,7 @@
struct Segment {
unsigned start;
unsigned end;
+ String text;
const RenderText& renderer;
};
const Segment& segmentForPosition(unsigned) const;
@@ -75,11 +76,12 @@
const Style& style() const { return m_style; }
private:
- const Segment& segmentForPositionSlow(unsigned) const;
- bool appendNextRendererContentIfNeeded(unsigned position) const;
- unsigned nextNonWhitespacePosition(unsigned position, unsigned& spaceCount) const;
- float runWidth(const RenderText&, unsigned from, unsigned to, float xPosition) const;
+ unsigned segmentIndexForPosition(unsigned position) const;
+ unsigned segmentIndexForPositionSlow(unsigned position) const;
+ UChar characterAt(unsigned position) const;
+ float runWidth(const String&, unsigned from, unsigned to, float xPosition) const;
+
const Style m_style;
const Vector<Segment, 8> m_segments;
@@ -87,11 +89,15 @@
mutable unsigned m_lastSegmentIndex;
};
+inline UChar FlowContents::characterAt(unsigned position) const
+{
+ auto& segment = segmentForPosition(position);
+ return segment.text[position - segment.start];
+}
+
inline bool FlowContents::isNewlineCharacter(unsigned position) const
{
- appendNextRendererContentIfNeeded(position);
- ASSERT(position < m_lineBreakIterator.string().length());
- return m_lineBreakIterator.string().at(position) == '\n';
+ return characterAt(position) == '\n';
}
inline bool FlowContents::isEnd(unsigned position) const
@@ -99,17 +105,21 @@
return position >= length();
}
-inline const FlowContents::Segment& FlowContents::segmentForPosition(unsigned position) const
+inline unsigned FlowContents::segmentIndexForPosition(unsigned position) const
{
ASSERT(!isEnd(position));
-
auto& lastSegment = m_segments[m_lastSegmentIndex];
if (lastSegment.start <= position && position < lastSegment.end)
- return lastSegment;
- return segmentForPositionSlow(position);
+ return m_lastSegmentIndex;
+ return segmentIndexForPositionSlow(position);
}
+inline const FlowContents::Segment& FlowContents::segmentForPosition(unsigned position) const
+{
+ return m_segments[segmentIndexForPosition(position)];
}
+
}
+}
#endif