Title: [158196] trunk/Source/WebCore
Revision
158196
Author
[email protected]
Date
2013-10-29 10:00:42 -0700 (Tue, 29 Oct 2013)

Log Message

Multiple runs per line on simple line path
https://bugs.webkit.org/show_bug.cgi?id=123446

Reviewed by Andreas Kling.

By allowing multiple runs per line we can support text flows with consecutive whitespaces in the middle.

* rendering/SimpleLineLayout.cpp:
(WebCore::SimpleLineLayout::canUseFor):
        
    Remove space test.
    The improved test coverage found a few more cases that we need to disallow.

(WebCore::SimpleLineLayout::adjustRunOffsets):
            
    Round the run positions and widths so they match line boxes.
    Adjust for text-align.

(WebCore::SimpleLineLayout::create):
        
    Split lines with consecutive spaces into runs.

* rendering/SimpleLineLayout.h:
(WebCore::SimpleLineLayout::Run::Run):
* rendering/SimpleLineLayoutFunctions.cpp:
(WebCore::SimpleLineLayout::hitTestFlow):
(WebCore::SimpleLineLayout::collectFlowOverflow):
(WebCore::SimpleLineLayout::computeTextBoundingBox):
* rendering/SimpleLineLayoutResolver.h:
(WebCore::SimpleLineLayout::RunResolver::Iterator::resolver):
(WebCore::SimpleLineLayout::RunResolver::Iterator::lineIndex):
(WebCore::SimpleLineLayout::RunResolver::Run::Run):
(WebCore::SimpleLineLayout::RunResolver::Run::rect):
(WebCore::SimpleLineLayout::RunResolver::Run::baseline):
(WebCore::SimpleLineLayout::RunResolver::Run::text):
(WebCore::SimpleLineLayout::RunResolver::Run::lineIndex):
(WebCore::SimpleLineLayout::RunResolver::Iterator::Iterator):
(WebCore::SimpleLineLayout::RunResolver::Iterator::operator++):
        
    Removed unnecessary operators.

(WebCore::SimpleLineLayout::RunResolver::Iterator::operator==):
(WebCore::SimpleLineLayout::RunResolver::Iterator::operator!=):
(WebCore::SimpleLineLayout::RunResolver::Iterator::operator*):
(WebCore::SimpleLineLayout::RunResolver::Iterator::simpleRun):
(WebCore::SimpleLineLayout::RunResolver::RunResolver):
(WebCore::SimpleLineLayout::RunResolver::begin):
(WebCore::SimpleLineLayout::RunResolver::end):
        
    Resolver -> RunResolver

(WebCore::SimpleLineLayout::LineResolver::Iterator::Iterator):
(WebCore::SimpleLineLayout::LineResolver::Iterator::operator++):
(WebCore::SimpleLineLayout::LineResolver::Iterator::operator==):
(WebCore::SimpleLineLayout::LineResolver::Iterator::operator!=):
(WebCore::SimpleLineLayout::LineResolver::Iterator::operator*):
(WebCore::SimpleLineLayout::LineResolver::LineResolver):
(WebCore::SimpleLineLayout::LineResolver::begin):
(WebCore::SimpleLineLayout::LineResolver::end):
        
    Add LineResolver around RunResolver. It resolves the line rectangles.

(WebCore::SimpleLineLayout::runResolver):
(WebCore::SimpleLineLayout::lineResolver):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (158195 => 158196)


--- trunk/Source/WebCore/ChangeLog	2013-10-29 16:40:08 UTC (rev 158195)
+++ trunk/Source/WebCore/ChangeLog	2013-10-29 17:00:42 UTC (rev 158196)
@@ -1,3 +1,70 @@
+2013-10-29  Antti Koivisto  <[email protected]>
+
+        Multiple runs per line on simple line path
+        https://bugs.webkit.org/show_bug.cgi?id=123446
+
+        Reviewed by Andreas Kling.
+
+        By allowing multiple runs per line we can support text flows with consecutive whitespaces in the middle.
+
+        * rendering/SimpleLineLayout.cpp:
+        (WebCore::SimpleLineLayout::canUseFor):
+        
+            Remove space test.
+            The improved test coverage found a few more cases that we need to disallow.
+
+        (WebCore::SimpleLineLayout::adjustRunOffsets):
+            
+            Round the run positions and widths so they match line boxes.
+            Adjust for text-align.
+
+        (WebCore::SimpleLineLayout::create):
+        
+            Split lines with consecutive spaces into runs.
+
+        * rendering/SimpleLineLayout.h:
+        (WebCore::SimpleLineLayout::Run::Run):
+        * rendering/SimpleLineLayoutFunctions.cpp:
+        (WebCore::SimpleLineLayout::hitTestFlow):
+        (WebCore::SimpleLineLayout::collectFlowOverflow):
+        (WebCore::SimpleLineLayout::computeTextBoundingBox):
+        * rendering/SimpleLineLayoutResolver.h:
+        (WebCore::SimpleLineLayout::RunResolver::Iterator::resolver):
+        (WebCore::SimpleLineLayout::RunResolver::Iterator::lineIndex):
+        (WebCore::SimpleLineLayout::RunResolver::Run::Run):
+        (WebCore::SimpleLineLayout::RunResolver::Run::rect):
+        (WebCore::SimpleLineLayout::RunResolver::Run::baseline):
+        (WebCore::SimpleLineLayout::RunResolver::Run::text):
+        (WebCore::SimpleLineLayout::RunResolver::Run::lineIndex):
+        (WebCore::SimpleLineLayout::RunResolver::Iterator::Iterator):
+        (WebCore::SimpleLineLayout::RunResolver::Iterator::operator++):
+        
+            Removed unnecessary operators.
+
+        (WebCore::SimpleLineLayout::RunResolver::Iterator::operator==):
+        (WebCore::SimpleLineLayout::RunResolver::Iterator::operator!=):
+        (WebCore::SimpleLineLayout::RunResolver::Iterator::operator*):
+        (WebCore::SimpleLineLayout::RunResolver::Iterator::simpleRun):
+        (WebCore::SimpleLineLayout::RunResolver::RunResolver):
+        (WebCore::SimpleLineLayout::RunResolver::begin):
+        (WebCore::SimpleLineLayout::RunResolver::end):
+        
+            Resolver -> RunResolver
+
+        (WebCore::SimpleLineLayout::LineResolver::Iterator::Iterator):
+        (WebCore::SimpleLineLayout::LineResolver::Iterator::operator++):
+        (WebCore::SimpleLineLayout::LineResolver::Iterator::operator==):
+        (WebCore::SimpleLineLayout::LineResolver::Iterator::operator!=):
+        (WebCore::SimpleLineLayout::LineResolver::Iterator::operator*):
+        (WebCore::SimpleLineLayout::LineResolver::LineResolver):
+        (WebCore::SimpleLineLayout::LineResolver::begin):
+        (WebCore::SimpleLineLayout::LineResolver::end):
+        
+            Add LineResolver around RunResolver. It resolves the line rectangles.
+
+        (WebCore::SimpleLineLayout::runResolver):
+        (WebCore::SimpleLineLayout::lineResolver):
+
 2013-10-29  Chris Fleizach  <[email protected]>
 
         AX: elements with explicit tabindex should expose AXFocused as writable, since mouse clicks can focus it

Modified: trunk/Source/WebCore/rendering/SimpleLineLayout.cpp (158195 => 158196)


--- trunk/Source/WebCore/rendering/SimpleLineLayout.cpp	2013-10-29 16:40:08 UTC (rev 158195)
+++ trunk/Source/WebCore/rendering/SimpleLineLayout.cpp	2013-10-29 17:00:42 UTC (rev 158196)
@@ -78,6 +78,8 @@
         return false;
     if (flow.isRubyText() || flow.isRubyBase())
         return false;
+    if (flow.parent()->isDeprecatedFlexibleBox())
+        return false;
     // These tests only works during layout. Outside layout this function may give false positives.
     if (flow.view().layoutState()) {
 #if ENABLE(CSS_SHAPES)
@@ -154,18 +156,10 @@
         return false;
 
     unsigned length = textRenderer.textLength();
-    unsigned consecutiveSpaceCount = 0;
     for (unsigned i = 0; i < length; ++i) {
-        // This rejects anything with more than one consecutive whitespace, except at the beginning or end.
-        // This is because we don't currently do subruns within lines. Fixing this would improve coverage significantly.
         UChar character = textRenderer.characterAt(i);
-        if (isWhitespace(character)) {
-            ++consecutiveSpaceCount;
+        if (character == ' ')
             continue;
-        }
-        if (consecutiveSpaceCount != i && consecutiveSpaceCount > 1)
-            return false;
-        consecutiveSpaceCount = 0;
 
         // These would be easy to support.
         if (character == noBreakSpace)
@@ -173,14 +167,12 @@
         if (character == softHyphen)
             return false;
 
-        static const UChar lowestRTLCharacter = 0x590;
-        if (character >= lowestRTLCharacter) {
-            UCharDirection direction = u_charDirection(character);
-            if (direction == U_RIGHT_TO_LEFT || direction == U_RIGHT_TO_LEFT_ARABIC
-                || direction == U_RIGHT_TO_LEFT_EMBEDDING || direction == U_RIGHT_TO_LEFT_OVERRIDE
-                || direction == U_LEFT_TO_RIGHT_EMBEDDING || direction == U_LEFT_TO_RIGHT_OVERRIDE)
-                return false;
-        }
+        UCharDirection direction = u_charDirection(character);
+        if (direction == U_RIGHT_TO_LEFT || direction == U_RIGHT_TO_LEFT_ARABIC
+            || direction == U_RIGHT_TO_LEFT_EMBEDDING || direction == U_RIGHT_TO_LEFT_OVERRIDE
+            || direction == U_LEFT_TO_RIGHT_EMBEDDING || direction == U_LEFT_TO_RIGHT_OVERRIDE
+            || direction == U_POP_DIRECTIONAL_FORMAT || direction == U_BOUNDARY_NEUTRAL)
+            return false;
 
         if (!primaryFontData.glyphForCharacter(character))
             return false;
@@ -231,6 +223,17 @@
     return 0;
 }
 
+static void adjustRunOffsets(Vector<Run, 4>& lineRuns, ETextAlign textAlign, float lineWidth, float availableWidth)
+{
+    float lineLeft = computeLineLeft(textAlign, availableWidth - lineWidth);
+    for (unsigned i = 0; i < lineRuns.size(); ++i) {
+        float adjustedLeft = floor(lineLeft + lineRuns[i].left);
+        float adjustedRight = ceil(lineLeft + lineRuns[i].left + lineRuns[i].width);
+        lineRuns[i].left = adjustedLeft;
+        lineRuns[i].width = adjustedRight - adjustedLeft;
+    }
+}
+
 std::unique_ptr<Layout> create(RenderBlockFlow& flow)
 {
     auto layout = std::make_unique<Layout>();
@@ -251,54 +254,73 @@
     while (lineEndOffset < textLength) {
         lineEndOffset = skipWhitespaces(textRenderer, lineEndOffset, textLength);
         unsigned lineStartOffset = lineEndOffset;
-        unsigned runEndOffset = lineEndOffset;
+        unsigned wordEndOffset = lineEndOffset;
         LineWidth lineWidth(flow, false, DoNotIndentText);
-        while (runEndOffset < textLength) {
-            ASSERT(!isWhitespace(textRenderer.characterAt(runEndOffset)));
 
-            bool previousWasSpaceBetweenRuns = runEndOffset > lineStartOffset && isWhitespace(textRenderer.characterAt(runEndOffset - 1));
-            unsigned runStartOffset = previousWasSpaceBetweenRuns ? runEndOffset - 1 : runEndOffset;
+        Vector<Run, 4> lineRuns;
+        lineRuns.uncheckedAppend(Run(lineStartOffset, 0));
 
-            ++runEndOffset;
-            while (runEndOffset < textLength) {
-                if (runEndOffset > lineStartOffset && isBreakable(lineBreakIterator, runEndOffset, nextBreakable, false))
+        while (wordEndOffset < textLength) {
+            ASSERT(!isWhitespace(textRenderer.characterAt(wordEndOffset)));
+
+            bool previousWasSpaceBetweenWords = wordEndOffset > lineStartOffset && isWhitespace(textRenderer.characterAt(wordEndOffset - 1));
+            unsigned wordStartOffset = previousWasSpaceBetweenWords ? wordEndOffset - 1 : wordEndOffset;
+
+            ++wordEndOffset;
+            while (wordEndOffset < textLength) {
+                if (wordEndOffset > lineStartOffset && isBreakable(lineBreakIterator, wordEndOffset, nextBreakable, false))
                     break;
-                ++runEndOffset;
+                ++wordEndOffset;
             }
 
-            unsigned runLength = runEndOffset - runStartOffset;
-            bool includeEndSpace = runEndOffset < textLength && textRenderer.characterAt(runEndOffset) == ' ';
+            unsigned wordLength = wordEndOffset - wordStartOffset;
+            bool includeEndSpace = wordEndOffset < textLength && textRenderer.characterAt(wordEndOffset) == ' ';
             float wordWidth;
             if (includeEndSpace)
-                wordWidth = textWidth(textRenderer, runStartOffset, runLength + 1, lineWidth.committedWidth(), style) - wordTrailingSpaceWidth;
+                wordWidth = textWidth(textRenderer, wordStartOffset, wordLength + 1, lineWidth.committedWidth(), style) - wordTrailingSpaceWidth;
             else
-                wordWidth = textWidth(textRenderer, runStartOffset, runLength, lineWidth.committedWidth(), style);
+                wordWidth = textWidth(textRenderer, wordStartOffset, wordLength, lineWidth.committedWidth(), style);
 
             lineWidth.addUncommittedWidth(wordWidth);
+
+            // Move to the next line if the current one is full and we have something on it.
+            if (!lineWidth.fitsOnLine() && lineWidth.committedWidth())
+                break;
+
+            if (wordStartOffset > lineEndOffset) {
+                // There were more than one consecutive whitespace.
+                ASSERT(previousWasSpaceBetweenWords);
+                // Include space to the end of the previous run.
+                lineRuns.last().textLength++;
+                lineRuns.last().width += wordTrailingSpaceWidth;
+                // Start a new run on the same line.
+                float previousRight = lineRuns.last().left + lineRuns.last().width;
+                lineRuns.append(Run(wordStartOffset + 1, previousRight));
+            }
+
+            lineWidth.commit();
+
+            lineRuns.last().width = lineWidth.committedWidth() - lineRuns.last().left;
+            lineRuns.last().textLength = wordEndOffset - lineRuns.last().textOffset;
+
+            lineEndOffset = wordEndOffset;
+            wordEndOffset = skipWhitespaces(textRenderer, wordEndOffset, textLength);
+
             if (!lineWidth.fitsOnLine()) {
-                if (!lineWidth.committedWidth()) {
-                    lineWidth.commit();
-                    lineEndOffset = runEndOffset;
-                }
+                // The first run on the line overflows.
+                ASSERT(lineRuns.size() == 1);
                 break;
             }
-            lineWidth.commit();
-            lineEndOffset = runEndOffset;
-            runEndOffset = skipWhitespaces(textRenderer, runEndOffset, textLength);
         }
         if (lineStartOffset == lineEndOffset)
             continue;
 
-        float alignedLeft = computeLineLeft(textAlign, lineWidth.availableWidth() - lineWidth.committedWidth());
-        float alignedRight = alignedLeft + lineWidth.committedWidth();
+        adjustRunOffsets(lineRuns, textAlign, lineWidth.committedWidth(), lineWidth.availableWidth());
 
-        Run run;
-        run.textOffset = lineStartOffset;
-        run.textLength = lineEndOffset - lineStartOffset;
-        run.left = floor(alignedLeft);
-        run.width = ceil(alignedRight) - run.left;
+        for (unsigned i = 0; i < lineRuns.size(); ++i)
+            layout->runs.append(lineRuns[i]);
 
-        layout->runs.append(run);
+        layout->runs.last().isEndOfLine = true;
         layout->lineCount++;
     }
 

Modified: trunk/Source/WebCore/rendering/SimpleLineLayout.h (158195 => 158196)


--- trunk/Source/WebCore/rendering/SimpleLineLayout.h	2013-10-29 16:40:08 UTC (rev 158195)
+++ trunk/Source/WebCore/rendering/SimpleLineLayout.h	2013-10-29 17:00:42 UTC (rev 158196)
@@ -38,8 +38,17 @@
 bool canUseFor(const RenderBlockFlow&);
 
 struct Run {
+    Run(unsigned textOffset, float left)
+        : textOffset(textOffset)
+        , textLength(0)
+        , isEndOfLine(false)
+        , left(left)
+        , width(0)
+    { }
+
     unsigned textOffset;
-    unsigned textLength;
+    unsigned textLength : 31;
+    unsigned isEndOfLine : 1;
     float left;
     float width;
 };

Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutFunctions.cpp (158195 => 158196)


--- trunk/Source/WebCore/rendering/SimpleLineLayoutFunctions.cpp	2013-10-29 16:40:08 UTC (rev 158195)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutFunctions.cpp	2013-10-29 17:00:42 UTC (rev 158196)
@@ -85,8 +85,7 @@
 
     auto resolver = lineResolver(flow, layout);
     for (auto it = resolver.begin(), end = resolver.end(); it != end; ++it) {
-        auto line = *it;
-        auto lineRect = line.rect();
+        auto lineRect = *it;
         lineRect.moveBy(accumulatedOffset);
         if (!locationInContainer.intersects(lineRect))
             continue;
@@ -102,8 +101,7 @@
 {
     auto resolver = lineResolver(flow, layout);
     for (auto it = resolver.begin(), end = resolver.end(); it != end; ++it) {
-        auto line = *it;
-        auto rect = line.rect();
+        auto rect = *it;
         flow.addLayoutOverflow(rect);
         flow.addVisualOverflow(rect);
     }
@@ -116,21 +114,23 @@
     auto end = resolver.end();
     if (it == end)
         return IntRect();
-    auto firstLineRect = (*it).rect();
+    auto firstLineRect = *it;
     float left = firstLineRect.x();
     float right = firstLineRect.maxX();
+    float bottom = firstLineRect.maxY();
     for (++it; it != end; ++it) {
-        auto line = *it;
-        auto rect = line.rect();
+        auto rect = *it;
         if (rect.x() < left)
             left = rect.x();
         if (rect.maxX() > right)
             right = rect.maxX();
+        if (rect.maxY() > bottom)
+            bottom = rect.maxY();
     }
     float x = firstLineRect.x();
     float y = firstLineRect.y();
     float width = right - left;
-    float height = (*resolver.last()).rect().maxY() - y;
+    float height = bottom - y;
     return enclosingIntRect(FloatRect(x, y, width, height));
 }
 

Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.h (158195 => 158196)


--- trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.h	2013-10-29 16:40:08 UTC (rev 158195)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.h	2013-10-29 17:00:42 UTC (rev 158196)
@@ -36,47 +36,48 @@
 namespace WebCore {
 namespace SimpleLineLayout {
 
-class Resolver {
+class RunResolver {
 public:
     class Iterator;
 
     class Run {
     public:
-        Run(const Resolver&, unsigned lineIndex);
+        explicit Run(const Iterator&);
 
         LayoutRect rect() const;
         LayoutPoint baseline() const;
         String text() const;
 
+        unsigned lineIndex() const;
+
     private:
-        const Resolver& m_resolver;
-        unsigned m_lineIndex;
+        const Iterator& m_iterator;
     };
 
     class Iterator {
     public:
-        Iterator(const Resolver&, unsigned lineIndex);
+        Iterator(const RunResolver&, unsigned lineIndex);
 
         Iterator& operator++();
-        Iterator& operator--();
         bool operator==(const Iterator&) const;
         bool operator!=(const Iterator&) const;
 
         Run operator*() const;
 
+        const RunResolver& resolver() const { return m_resolver; }
+        const SimpleLineLayout::Run& simpleRun() const;
+        unsigned lineIndex() const { return m_lineIndex; }
+
     private:
-        const Resolver& m_resolver;
+        const RunResolver& m_resolver;
+        unsigned m_runIndex;
         unsigned m_lineIndex;
     };
 
-    Resolver(const RenderBlockFlow&, const Layout&);
+    RunResolver(const RenderBlockFlow&, const Layout&);
 
-    unsigned size() const;
-
     Iterator begin() const;
     Iterator end() const;
-    Iterator last() const;
-    Iterator operator[](unsigned) const;
 
 private:
     const Layout& m_layout;
@@ -88,73 +89,110 @@
     const LayoutPoint m_contentOffset;
 };
 
-Resolver runResolver(const RenderBlockFlow&, const Layout&);
-Resolver lineResolver(const RenderBlockFlow&, const Layout&);
+class LineResolver {
+public:
+    class Iterator;
 
-inline Resolver::Run::Run(const Resolver& resolver, unsigned lineIndex)
-    : m_resolver(resolver)
-    , m_lineIndex(lineIndex)
+    class Iterator {
+    public:
+        explicit Iterator(RunResolver::Iterator);
+
+        Iterator& operator++();
+        bool operator==(const Iterator&) const;
+        bool operator!=(const Iterator&) const;
+
+        const LayoutRect operator*() const;
+
+    private:
+        RunResolver::Iterator m_runIterator;
+        LayoutRect m_rect;
+    };
+
+    LineResolver(const RenderBlockFlow&, const Layout&);
+
+    Iterator begin() const;
+    Iterator end() const;
+
+private:
+    RunResolver m_runResolver;
+};
+
+RunResolver runResolver(const RenderBlockFlow&, const Layout&);
+LineResolver lineResolver(const RenderBlockFlow&, const Layout&);
+
+inline RunResolver::Run::Run(const Iterator& iterator)
+    : m_iterator(iterator)
 {
 }
 
-inline LayoutRect Resolver::Run::rect() const
+inline LayoutRect RunResolver::Run::rect() const
 {
-    auto& run = m_resolver.m_layout.runs[m_lineIndex];
+    auto& resolver = m_iterator.resolver();
+    auto& run = m_iterator.simpleRun();
 
-    LayoutPoint linePosition(run.left, m_resolver.m_lineHeight * m_lineIndex + m_resolver.m_baseline - m_resolver.m_ascent);
-    LayoutSize lineSize(run.width, m_resolver.m_ascent + m_resolver.m_descent);
-    return LayoutRect(linePosition + m_resolver.m_contentOffset, lineSize);
+    LayoutPoint linePosition(run.left, resolver.m_lineHeight * m_iterator.lineIndex() + resolver.m_baseline - resolver.m_ascent);
+    LayoutSize lineSize(run.width, resolver.m_ascent + resolver.m_descent);
+    return LayoutRect(linePosition + resolver.m_contentOffset, lineSize);
 }
 
-inline LayoutPoint Resolver::Run::baseline() const
+inline LayoutPoint RunResolver::Run::baseline() const
 {
-    auto& run = m_resolver.m_layout.runs[m_lineIndex];
+    auto& resolver = m_iterator.resolver();
+    auto& run = m_iterator.simpleRun();
 
-    float baselineY = m_resolver.m_lineHeight * m_lineIndex + m_resolver.m_baseline;
-    return LayoutPoint(run.left, baselineY) + m_resolver.m_contentOffset;
+    float baselineY = resolver.m_lineHeight * m_iterator.lineIndex() + resolver.m_baseline;
+    return LayoutPoint(run.left, baselineY) + resolver.m_contentOffset;
 }
 
-inline String Resolver::Run::text() const
+inline String RunResolver::Run::text() const
 {
-    auto& run = m_resolver.m_layout.runs[m_lineIndex];
-    return m_resolver.m_string.substringSharingImpl(run.textOffset, run.textLength);
+    auto& resolver = m_iterator.resolver();
+    auto& run = m_iterator.simpleRun();
+    return resolver.m_string.substringSharingImpl(run.textOffset, run.textLength);
 }
 
-inline Resolver::Iterator::Iterator(const Resolver& resolver, unsigned lineIndex)
-    : m_resolver(resolver)
-    , m_lineIndex(lineIndex)
+inline unsigned RunResolver::Run::lineIndex() const
 {
+    return m_iterator.lineIndex();
 }
 
-inline Resolver::Iterator& Resolver::Iterator::operator++()
+inline RunResolver::Iterator::Iterator(const RunResolver& resolver, unsigned runIndex)
+    : m_resolver(resolver)
+    , m_runIndex(runIndex)
+    , m_lineIndex(0)
 {
-    ++m_lineIndex;
-    return *this;
 }
 
-inline Resolver::Iterator& Resolver::Iterator::operator--()
+inline RunResolver::Iterator& RunResolver::Iterator::operator++()
 {
-    --m_lineIndex;
+    if (simpleRun().isEndOfLine)
+        ++m_lineIndex;
+    ++m_runIndex;
     return *this;
 }
 
-inline bool Resolver::Iterator::operator==(const Iterator& other) const
+inline bool RunResolver::Iterator::operator==(const Iterator& other) const
 {
     ASSERT(&m_resolver == &other.m_resolver);
-    return m_lineIndex == other.m_lineIndex;
+    return m_runIndex == other.m_runIndex;
 }
 
-inline bool Resolver::Iterator::operator!=(const Iterator& other) const
+inline bool RunResolver::Iterator::operator!=(const Iterator& other) const
 {
     return !(*this == other);
 }
 
-inline Resolver::Run Resolver::Iterator::operator*() const
+inline RunResolver::Run RunResolver::Iterator::operator*() const
 {
-    return Run(m_resolver, m_lineIndex);
+    return Run(*this);
 }
 
-inline Resolver::Resolver(const RenderBlockFlow& flow, const Layout& layout)
+inline const SimpleLineLayout::Run& RunResolver::Iterator::simpleRun() const
+{
+    return m_resolver.m_layout.runs[m_runIndex];
+}
+
+inline RunResolver::RunResolver(const RenderBlockFlow& flow, const Layout& layout)
     : m_layout(layout)
     , m_string(toRenderText(*flow.firstChild()).text())
     , m_lineHeight(lineHeightFromFlow(flow))
@@ -165,44 +203,76 @@
 {
 }
 
-inline unsigned Resolver::size() const
+inline RunResolver::Iterator RunResolver::begin() const
 {
-    return m_layout.runs.size();
+    return Iterator(*this, 0);
 }
 
-inline Resolver::Iterator Resolver::begin() const
+inline RunResolver::Iterator RunResolver::end() const
 {
-    return Iterator(*this, 0);
+    return Iterator(*this, m_layout.runs.size());
 }
 
-inline Resolver::Iterator Resolver::end() const
+inline LineResolver::Iterator::Iterator(RunResolver::Iterator runIterator)
+    : m_runIterator(runIterator)
 {
-    return Iterator(*this, size());
 }
 
-inline Resolver::Iterator Resolver::last() const
+inline LineResolver::Iterator& LineResolver::Iterator::operator++()
 {
-    ASSERT(size());
-    return Iterator(*this, size() - 1);
+    unsigned previousLine = m_runIterator.lineIndex();
+    while ((++m_runIterator).lineIndex() == previousLine) { }
+
+    return *this;
 }
 
-inline Resolver::Iterator Resolver::operator[](unsigned index) const
+inline bool LineResolver::Iterator::operator==(const Iterator& other) const
 {
-    ASSERT(index < size());
-    return Iterator(*this, index);
+    return m_runIterator == other.m_runIterator;
 }
 
-inline Resolver runResolver(const RenderBlockFlow& flow, const Layout& layout)
+inline bool LineResolver::Iterator::operator!=(const Iterator& other) const
 {
-    return Resolver(flow, layout);
+    return m_runIterator != other.m_runIterator;
 }
 
-inline Resolver lineResolver(const RenderBlockFlow& flow, const Layout& layout)
+inline const LayoutRect LineResolver::Iterator::operator*() const
 {
-    return Resolver(flow, layout);
+    unsigned currentLine = m_runIterator.lineIndex();
+    auto it = m_runIterator;
+    LayoutRect rect = (*it).rect();
+    while ((++it).lineIndex() == currentLine)
+        rect.unite((*it).rect());
+
+    return rect;
 }
 
+inline LineResolver::LineResolver(const RenderBlockFlow& flow, const Layout& layout)
+    : m_runResolver(flow, layout)
+{
 }
+
+inline LineResolver::Iterator LineResolver::begin() const
+{
+    return Iterator(m_runResolver.begin());
 }
 
+inline LineResolver::Iterator LineResolver::end() const
+{
+    return Iterator(m_runResolver.end());
+}
+
+inline RunResolver runResolver(const RenderBlockFlow& flow, const Layout& layout)
+{
+    return RunResolver(flow, layout);
+}
+
+inline LineResolver lineResolver(const RenderBlockFlow& flow, const Layout& layout)
+{
+    return LineResolver(flow, layout);
+}
+
+}
+}
+
 #endif
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to