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