Title: [181171] trunk/Source/WebCore
Revision
181171
Author
mmaxfi...@apple.com
Date
2015-03-06 11:06:30 -0800 (Fri, 06 Mar 2015)

Log Message

Rename BreakingContextInlineHeaders.h to BreakingContext.h
https://bugs.webkit.org/show_bug.cgi?id=142404

Reviewed by Simon Fraser.

No point naming it "InlineHeaders" when there are no non-inline-headers files.

No new tests because this is just a rename of a file.

* WebCore.vcxproj/WebCore.vcxproj:
* WebCore.vcxproj/WebCore.vcxproj.filters:
* WebCore.xcodeproj/project.pbxproj:
* rendering/RenderBlockLineLayout.cpp:
* rendering/line/BreakingContext.h: Renamed from Source/WebCore/rendering/line/BreakingContextInlineHeaders.h.
(WebCore::WordMeasurement::WordMeasurement):
(WebCore::BreakingContext::BreakingContext):
(WebCore::BreakingContext::currentObject):
(WebCore::BreakingContext::lineBreak):
(WebCore::BreakingContext::lineWidth):
(WebCore::BreakingContext::atEnd):
(WebCore::BreakingContext::clearLineBreakIfFitsOnLine):
(WebCore::BreakingContext::commitLineBreakAtCurrentWidth):
(WebCore::BreakingContext::InlineIteratorHistory::InlineIteratorHistory):
(WebCore::BreakingContext::InlineIteratorHistory::push):
(WebCore::BreakingContext::InlineIteratorHistory::update):
(WebCore::BreakingContext::InlineIteratorHistory::renderer):
(WebCore::BreakingContext::InlineIteratorHistory::offset):
(WebCore::BreakingContext::InlineIteratorHistory::atTextParagraphSeparator):
(WebCore::BreakingContext::InlineIteratorHistory::previousInSameNode):
(WebCore::BreakingContext::InlineIteratorHistory::get):
(WebCore::BreakingContext::InlineIteratorHistory::current):
(WebCore::BreakingContext::InlineIteratorHistory::historyLength):
(WebCore::BreakingContext::InlineIteratorHistory::moveTo):
(WebCore::BreakingContext::InlineIteratorHistory::increment):
(WebCore::BreakingContext::InlineIteratorHistory::clear):
(WebCore::BreakingContext::initializeForCurrentObject):
(WebCore::BreakingContext::increment):
(WebCore::BreakingContext::handleBR):
(WebCore::borderPaddingMarginStart):
(WebCore::borderPaddingMarginEnd):
(WebCore::shouldAddBorderPaddingMargin):
(WebCore::previousInFlowSibling):
(WebCore::inlineLogicalWidth):
(WebCore::BreakingContext::handleOutOfFlowPositioned):
(WebCore::BreakingContext::handleFloat):
(WebCore::shouldSkipWhitespaceAfterStartObject):
(WebCore::BreakingContext::handleEmptyInline):
(WebCore::BreakingContext::handleReplaced):
(WebCore::firstPositiveWidth):
(WebCore::iteratorIsBeyondEndOfRenderCombineText):
(WebCore::nextCharacter):
(WebCore::updateCounterIfNeeded):
(WebCore::measureHyphenWidth):
(WebCore::textWidth):
(WebCore::ensureCharacterGetsLineBox):
(WebCore::tryHyphenating):
(WebCore::BreakingContext::handleText):
(WebCore::textBeginsWithBreakablePosition):
(WebCore::BreakingContext::canBreakAtThisPosition):
(WebCore::BreakingContext::commitAndUpdateLineBreakIfNeeded):
(WebCore::checkMidpoints):
(WebCore::BreakingContext::handleEndOfLine):
(WebCore::BreakingContext::optimalLineBreakLocationForTrailingWord):
* rendering/line/LineBreaker.cpp:

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (181170 => 181171)


--- trunk/Source/WebCore/ChangeLog	2015-03-06 18:47:28 UTC (rev 181170)
+++ trunk/Source/WebCore/ChangeLog	2015-03-06 19:06:30 UTC (rev 181171)
@@ -1,3 +1,70 @@
+2015-03-06  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        Rename BreakingContextInlineHeaders.h to BreakingContext.h
+        https://bugs.webkit.org/show_bug.cgi?id=142404
+
+        Reviewed by Simon Fraser.
+
+        No point naming it "InlineHeaders" when there are no non-inline-headers files.
+
+        No new tests because this is just a rename of a file.
+
+        * WebCore.vcxproj/WebCore.vcxproj:
+        * WebCore.vcxproj/WebCore.vcxproj.filters:
+        * WebCore.xcodeproj/project.pbxproj:
+        * rendering/RenderBlockLineLayout.cpp:
+        * rendering/line/BreakingContext.h: Renamed from Source/WebCore/rendering/line/BreakingContextInlineHeaders.h.
+        (WebCore::WordMeasurement::WordMeasurement):
+        (WebCore::BreakingContext::BreakingContext):
+        (WebCore::BreakingContext::currentObject):
+        (WebCore::BreakingContext::lineBreak):
+        (WebCore::BreakingContext::lineWidth):
+        (WebCore::BreakingContext::atEnd):
+        (WebCore::BreakingContext::clearLineBreakIfFitsOnLine):
+        (WebCore::BreakingContext::commitLineBreakAtCurrentWidth):
+        (WebCore::BreakingContext::InlineIteratorHistory::InlineIteratorHistory):
+        (WebCore::BreakingContext::InlineIteratorHistory::push):
+        (WebCore::BreakingContext::InlineIteratorHistory::update):
+        (WebCore::BreakingContext::InlineIteratorHistory::renderer):
+        (WebCore::BreakingContext::InlineIteratorHistory::offset):
+        (WebCore::BreakingContext::InlineIteratorHistory::atTextParagraphSeparator):
+        (WebCore::BreakingContext::InlineIteratorHistory::previousInSameNode):
+        (WebCore::BreakingContext::InlineIteratorHistory::get):
+        (WebCore::BreakingContext::InlineIteratorHistory::current):
+        (WebCore::BreakingContext::InlineIteratorHistory::historyLength):
+        (WebCore::BreakingContext::InlineIteratorHistory::moveTo):
+        (WebCore::BreakingContext::InlineIteratorHistory::increment):
+        (WebCore::BreakingContext::InlineIteratorHistory::clear):
+        (WebCore::BreakingContext::initializeForCurrentObject):
+        (WebCore::BreakingContext::increment):
+        (WebCore::BreakingContext::handleBR):
+        (WebCore::borderPaddingMarginStart):
+        (WebCore::borderPaddingMarginEnd):
+        (WebCore::shouldAddBorderPaddingMargin):
+        (WebCore::previousInFlowSibling):
+        (WebCore::inlineLogicalWidth):
+        (WebCore::BreakingContext::handleOutOfFlowPositioned):
+        (WebCore::BreakingContext::handleFloat):
+        (WebCore::shouldSkipWhitespaceAfterStartObject):
+        (WebCore::BreakingContext::handleEmptyInline):
+        (WebCore::BreakingContext::handleReplaced):
+        (WebCore::firstPositiveWidth):
+        (WebCore::iteratorIsBeyondEndOfRenderCombineText):
+        (WebCore::nextCharacter):
+        (WebCore::updateCounterIfNeeded):
+        (WebCore::measureHyphenWidth):
+        (WebCore::textWidth):
+        (WebCore::ensureCharacterGetsLineBox):
+        (WebCore::tryHyphenating):
+        (WebCore::BreakingContext::handleText):
+        (WebCore::textBeginsWithBreakablePosition):
+        (WebCore::BreakingContext::canBreakAtThisPosition):
+        (WebCore::BreakingContext::commitAndUpdateLineBreakIfNeeded):
+        (WebCore::checkMidpoints):
+        (WebCore::BreakingContext::handleEndOfLine):
+        (WebCore::BreakingContext::optimalLineBreakLocationForTrailingWord):
+        * rendering/line/LineBreaker.cpp:
+
 2015-03-06  Dan Bernstein  <m...@apple.com>
 
         Expose some of the functionality of extract-localizable-strings.pl as a module

Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj (181170 => 181171)


--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj	2015-03-06 18:47:28 UTC (rev 181170)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj	2015-03-06 19:06:30 UTC (rev 181171)
@@ -20345,7 +20345,7 @@
     <ClInclude Include="..\rendering\RenderSelectionInfo.h" />
     <ClInclude Include="..\rendering\RenderSlider.h" />
     <ClInclude Include="..\rendering\RenderSnapshottedPlugIn.h" />
-    <ClInclude Include="..\rendering\line\BreakingContextInlineHeaders.h" />
+    <ClInclude Include="..\rendering\line\BreakingContext.h" />
     <ClInclude Include="..\rendering\line\LineBreaker.h" />
     <ClInclude Include="..\rendering\line\LineInfo.h" />
     <ClInclude Include="..\rendering\line\LineInlineHeaders.h" />

Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters (181170 => 181171)


--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters	2015-03-06 18:47:28 UTC (rev 181170)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters	2015-03-06 19:06:30 UTC (rev 181171)
@@ -14408,7 +14408,7 @@
     <ClInclude Include="..\rendering\BorderEdge.h">
       <Filter>rendering</Filter>
     </ClInclude>
-    <ClInclude Include="..\rendering\line\BreakingContextInlineHeaders.h">
+    <ClInclude Include="..\rendering\line\BreakingContext.h">
       <Filter>rendering\line</Filter>
     </ClInclude>
     <ClInclude Include="..\page\ContextMenuContext.h">

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (181170 => 181171)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2015-03-06 18:47:28 UTC (rev 181170)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2015-03-06 19:06:30 UTC (rev 181171)
@@ -14363,7 +14363,7 @@
 		FF945ECA161F7F3600971BC8 /* PseudoElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PseudoElement.h; sourceTree = "<group>"; };
 		FFAC30FC184FB145008C4F1E /* TrailingObjects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrailingObjects.h; sourceTree = "<group>"; };
 		FFAC30FD184FB145008C4F1E /* TrailingObjects.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrailingObjects.cpp; sourceTree = "<group>"; };
-		FFB698C91832F10B00158A31 /* BreakingContextInlineHeaders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BreakingContextInlineHeaders.h; sourceTree = "<group>"; };
+		FFB698C91832F10B00158A31 /* BreakingContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BreakingContext.h; sourceTree = "<group>"; };
 		FFB698CA1833EC3800158A31 /* LineBreaker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LineBreaker.cpp; sourceTree = "<group>"; };
 		FFB698CB1833EC3800158A31 /* LineBreaker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LineBreaker.h; sourceTree = "<group>"; };
 		FFB698CD1833F17600158A31 /* LineInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LineInfo.cpp; sourceTree = "<group>"; };
@@ -23453,7 +23453,7 @@
 		FFB698C81832F10B00158A31 /* line */ = {
 			isa = PBXGroup;
 			children = (
-				FFB698C91832F10B00158A31 /* BreakingContextInlineHeaders.h */,
+				FFB698C91832F10B00158A31 /* BreakingContext.h */,
 				FFB698CA1833EC3800158A31 /* LineBreaker.cpp */,
 				FFB698CB1833EC3800158A31 /* LineBreaker.h */,
 				FFB698CD1833F17600158A31 /* LineInfo.cpp */,

Modified: trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp (181170 => 181171)


--- trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp	2015-03-06 18:47:28 UTC (rev 181170)
+++ trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp	2015-03-06 19:06:30 UTC (rev 181171)
@@ -26,7 +26,7 @@
 
 #include "AXObjectCache.h"
 #include "BidiResolver.h"
-#include "BreakingContextInlineHeaders.h"
+#include "BreakingContext.h"
 #include "FloatingObjects.h"
 #include "InlineElementBox.h"
 #include "InlineIterator.h"

Copied: trunk/Source/WebCore/rendering/line/BreakingContext.h (from rev 181170, trunk/Source/WebCore/rendering/line/BreakingContextInlineHeaders.h) (0 => 181171)


--- trunk/Source/WebCore/rendering/line/BreakingContext.h	                        (rev 0)
+++ trunk/Source/WebCore/rendering/line/BreakingContext.h	2015-03-06 19:06:30 UTC (rev 181171)
@@ -0,0 +1,1202 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (kn...@kde.org)
+ * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All right reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2013 ChangSeok Oh <shivami...@gmail.com>
+ * Copyright (C) 2013 Adobe Systems Inc. All right reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BreakingContext_h
+#define BreakingContext_h
+
+#include "Hyphenation.h"
+#include "LineBreaker.h"
+#include "LineInfo.h"
+#include "LineWidth.h"
+#include "RenderCombineText.h"
+#include "RenderCounter.h"
+#include "RenderInline.h"
+#include "RenderLineBreak.h"
+#include "RenderListMarker.h"
+#include "RenderRubyRun.h"
+#include "RenderSVGInlineText.h"
+#include "TrailingObjects.h"
+#include "break_lines.h"
+#include <wtf/text/StringView.h>
+#include <wtf/unicode/CharacterNames.h>
+
+namespace WebCore {
+
+// We don't let our line box tree for a single line get any deeper than this.
+const unsigned cMaxLineDepth = 200;
+
+struct WordMeasurement {
+    WordMeasurement()
+        : renderer(0)
+        , width(0)
+        , startOffset(0)
+        , endOffset(0)
+    {
+    }
+
+    RenderText* renderer;
+    float width;
+    int startOffset;
+    int endOffset;
+    HashSet<const Font*> fallbackFonts;
+};
+
+class BreakingContext {
+public:
+    BreakingContext(LineBreaker& lineBreaker, InlineBidiResolver& resolver, LineInfo& inLineInfo, LineWidth& lineWidth, RenderTextInfo& inRenderTextInfo, FloatingObject* inLastFloatFromPreviousLine, bool appliedStartWidth, RenderBlockFlow& block)
+        : m_lineBreaker(lineBreaker)
+        , m_resolver(resolver)
+        , m_current(resolver.position())
+#if ENABLE(CSS_TRAILING_WORD)
+        , m_lineBreakHistory(InlineIterator(resolver.position()), block.style().trailingWord() == TrailingWord::PartiallyBalanced ? 5 : 1)
+#else
+        , m_lineBreakHistory(InlineIterator(resolver.position()), 1)
+#endif
+        , m_block(block)
+        , m_lastObject(m_current.renderer())
+        , m_nextObject(nullptr)
+        , m_currentStyle(nullptr)
+        , m_blockStyle(block.style())
+        , m_lineInfo(inLineInfo)
+        , m_renderTextInfo(inRenderTextInfo)
+        , m_lastFloatFromPreviousLine(inLastFloatFromPreviousLine)
+        , m_width(lineWidth)
+        , m_currWS(NORMAL)
+        , m_lastWS(NORMAL)
+        , m_preservesNewline(false)
+        , m_atStart(true)
+        , m_ignoringSpaces(false)
+        , m_currentCharacterIsSpace(false)
+        , m_currentCharacterIsWS(false)
+        , m_appliedStartWidth(appliedStartWidth)
+        , m_includeEndWidth(true)
+        , m_autoWrap(false)
+        , m_autoWrapWasEverTrueOnLine(false)
+        , m_floatsFitOnLine(true)
+        , m_collapseWhiteSpace(false)
+        , m_startingNewParagraph(m_lineInfo.previousLineBrokeCleanly())
+        , m_allowImagesToBreak(!block.document().inQuirksMode() || !block.isTableCell() || !m_blockStyle.logicalWidth().isIntrinsicOrAuto())
+        , m_atEnd(false)
+        , m_hadUncommittedWidthBeforeCurrent(false)
+        , m_lineMidpointState(resolver.midpointState())
+    {
+        m_lineInfo.setPreviousLineBrokeCleanly(false);
+    }
+
+    RenderObject* currentObject() { return m_current.renderer(); }
+    InlineIterator lineBreak() { return m_lineBreakHistory.current(); }
+    LineWidth& lineWidth() { return m_width; }
+    bool atEnd() { return m_atEnd; }
+
+    void initializeForCurrentObject();
+
+    void increment();
+
+    void handleBR(EClear&);
+    void handleOutOfFlowPositioned(Vector<RenderBox*>& positionedObjects);
+    void handleFloat();
+    void handleEmptyInline();
+    void handleReplaced();
+    bool handleText(WordMeasurements&, bool& hyphenated, unsigned& consecutiveHyphenatedLines);
+    bool canBreakAtThisPosition();
+    void commitAndUpdateLineBreakIfNeeded();
+    InlineIterator handleEndOfLine();
+#if ENABLE(CSS_TRAILING_WORD)
+    InlineIterator optimalLineBreakLocationForTrailingWord();
+#endif
+
+    void clearLineBreakIfFitsOnLine(bool ignoringTrailingSpace = false)
+    {
+        if (m_width.fitsOnLine(ignoringTrailingSpace) || m_lastWS == NOWRAP)
+            m_lineBreakHistory.clear();
+    }
+
+    void commitLineBreakAtCurrentWidth(RenderObject& object, unsigned offset = 0, int nextBreak = -1)
+    {
+        m_width.commit();
+        m_lineBreakHistory.moveTo(&object, offset, nextBreak);
+    }
+
+private:
+    // This class keeps a sliding window of the past n locations for an InlineIterator.
+    class InlineIteratorHistory : private Vector<InlineIterator, 1> {
+    public:
+        InlineIteratorHistory() = delete;
+        InlineIteratorHistory(const InlineIterator& initial, size_t capacity)
+            : m_capacity(capacity)
+        {
+            ASSERT(capacity > 0);
+            this->append(initial);
+        }
+
+        void push(std::function<void(InlineIterator& modifyMe)> updater)
+        {
+            ASSERT(!this->isEmpty());
+            if (m_capacity != 1)
+                this->insert(0, InlineIterator(this->at(0)));
+            updater(this->at(0));
+            if (m_capacity != 1)
+                this->resize(m_capacity);
+        }
+
+        void update(std::function<void(InlineIterator& modifyMe)> updater)
+        {
+            ASSERT(!this->isEmpty());
+            updater(this->at(0));
+        }
+
+        RenderObject* renderer() const { return this->at(0).renderer(); }
+        unsigned offset() const { return this->at(0).offset(); }
+        bool atTextParagraphSeparator() const { return this->at(0).atTextParagraphSeparator(); }
+        UChar previousInSameNode() const { return this->at(0).previousInSameNode(); }
+        const InlineIterator& get(size_t i) const { return this->at(i); };
+        const InlineIterator& current() const { return get(0); }
+        size_t historyLength() const { return this->size(); }
+
+        void moveTo(RenderObject* object, unsigned offset, int nextBreak = -1)
+        {
+            push([&](InlineIterator& modifyMe) {
+                modifyMe.moveTo(object, offset, nextBreak);
+            });
+        }
+
+        void increment()
+        {
+            update([](InlineIterator& modifyMe) {
+                modifyMe.increment();
+            });
+        }
+
+        void clear()
+        {
+            push([](InlineIterator& modifyMe) {
+                modifyMe.clear();
+            });
+        }
+
+    private:
+        const size_t m_capacity;
+    };
+
+    LineBreaker& m_lineBreaker;
+    InlineBidiResolver& m_resolver;
+
+    InlineIterator m_current;
+    InlineIteratorHistory m_lineBreakHistory;
+    InlineIterator m_startOfIgnoredSpaces;
+
+    RenderBlockFlow& m_block;
+    RenderObject* m_lastObject;
+    RenderObject* m_nextObject;
+
+    const RenderStyle* m_currentStyle;
+
+    // Firefox and Opera will allow a table cell to grow to fit an image inside it under
+    // very specific circumstances (in order to match common WinIE renderings).
+    // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.)
+    RenderStyle& m_blockStyle;
+
+    LineInfo& m_lineInfo;
+
+    RenderTextInfo& m_renderTextInfo;
+
+    FloatingObject* m_lastFloatFromPreviousLine;
+
+    LineWidth m_width;
+
+    EWhiteSpace m_currWS;
+    EWhiteSpace m_lastWS;
+
+    bool m_preservesNewline;
+    bool m_atStart;
+
+    // This variable is used only if whitespace isn't set to PRE, and it tells us whether
+    // or not we are currently ignoring whitespace.
+    bool m_ignoringSpaces;
+
+    // This variable tracks whether the very last character we saw was a space. We use
+    // this to detect when we encounter a second space so we know we have to terminate
+    // a run.
+    bool m_currentCharacterIsSpace;
+    bool m_currentCharacterIsWS;
+    bool m_appliedStartWidth;
+    bool m_includeEndWidth;
+    bool m_autoWrap;
+    bool m_autoWrapWasEverTrueOnLine;
+    bool m_floatsFitOnLine;
+    bool m_collapseWhiteSpace;
+    bool m_startingNewParagraph;
+    bool m_allowImagesToBreak;
+    bool m_atEnd;
+    bool m_hadUncommittedWidthBeforeCurrent;
+
+    LineMidpointState& m_lineMidpointState;
+
+    TrailingObjects m_trailingObjects;
+};
+
+inline void BreakingContext::initializeForCurrentObject()
+{
+    m_hadUncommittedWidthBeforeCurrent = !!m_width.uncommittedWidth();
+
+    m_currentStyle = &m_current.renderer()->style(); // FIXME: Should this be &lineStyle(*m_current.renderer(), m_lineInfo); ?
+
+    ASSERT(m_currentStyle);
+
+    m_nextObject = bidiNextSkippingEmptyInlines(m_block, m_current.renderer());
+    if (m_nextObject && m_nextObject->parent() && !m_nextObject->parent()->isDescendantOf(m_current.renderer()->parent()))
+        m_includeEndWidth = true;
+
+    m_currWS = m_current.renderer()->isReplaced() ? m_current.renderer()->parent()->style().whiteSpace() : m_currentStyle->whiteSpace();
+    m_lastWS = m_lastObject->isReplaced() ? m_lastObject->parent()->style().whiteSpace() : m_lastObject->style().whiteSpace();
+
+    m_autoWrap = RenderStyle::autoWrap(m_currWS);
+    m_autoWrapWasEverTrueOnLine = m_autoWrapWasEverTrueOnLine || m_autoWrap;
+
+    m_preservesNewline = m_current.renderer()->isSVGInlineText() ? false : RenderStyle::preserveNewline(m_currWS);
+
+    m_collapseWhiteSpace = RenderStyle::collapseWhiteSpace(m_currWS);
+}
+
+inline void BreakingContext::increment()
+{
+    // Clear out our character space bool, since inline <pre>s don't collapse whitespace
+    // with adjacent inline normal/nowrap spans.
+    if (!m_collapseWhiteSpace)
+        m_currentCharacterIsSpace = false;
+
+    m_current.moveToStartOf(m_nextObject);
+    m_atStart = false;
+}
+
+inline void BreakingContext::handleBR(EClear& clear)
+{
+    if (m_width.fitsOnLine()) {
+        RenderObject* br = m_current.renderer();
+        m_lineBreakHistory.push([&](InlineIterator& modifyMe) {
+            modifyMe.moveToStartOf(br);
+            modifyMe.increment();
+        });
+
+        // A <br> always breaks a line, so don't let the line be collapsed
+        // away. Also, the space at the end of a line with a <br> does not
+        // get collapsed away. It only does this if the previous line broke
+        // cleanly. Otherwise the <br> has no effect on whether the line is
+        // empty or not.
+        if (m_startingNewParagraph)
+            m_lineInfo.setEmpty(false, &m_block, &m_width);
+        m_trailingObjects.clear();
+        m_lineInfo.setPreviousLineBrokeCleanly(true);
+
+        // A <br> with clearance always needs a linebox in case the lines below it get dirtied later and
+        // need to check for floats to clear - so if we're ignoring spaces, stop ignoring them and add a
+        // run for this object.
+        if (m_ignoringSpaces && m_currentStyle->clear() != CNONE)
+            m_lineMidpointState.ensureLineBoxInsideIgnoredSpaces(br);
+        // If we were preceded by collapsing space and are in a right-aligned container we need to ensure the space gets
+        // collapsed away so that it doesn't push the text out from the container's right-hand edge.
+        // FIXME: Do this regardless of the container's alignment - will require rebaselining a lot of test results.
+        else if (m_ignoringSpaces && (m_blockStyle.textAlign() == RIGHT || m_blockStyle.textAlign() == WEBKIT_RIGHT))
+            m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.renderer(), m_current.offset()));
+
+        if (!m_lineInfo.isEmpty())
+            clear = m_currentStyle->clear();
+    }
+    m_atEnd = true;
+}
+
+inline LayoutUnit borderPaddingMarginStart(const RenderInline& child)
+{
+    return child.marginStart() + child.paddingStart() + child.borderStart();
+}
+
+inline LayoutUnit borderPaddingMarginEnd(const RenderInline& child)
+{
+    return child.marginEnd() + child.paddingEnd() + child.borderEnd();
+}
+
+inline bool shouldAddBorderPaddingMargin(RenderObject* child)
+{
+    if (!child)
+        return true;
+    // When deciding whether we're at the edge of an inline, adjacent collapsed whitespace is the same as no sibling at all.
+    if (is<RenderText>(*child) && !downcast<RenderText>(*child).textLength())
+        return true;
+#if ENABLE(CSS_BOX_DECORATION_BREAK)
+    if (is<RenderLineBreak>(*child) && child->parent()->style().boxDecorationBreak() == DCLONE)
+        return true;
+#endif
+    return false;
+}
+
+inline RenderObject* previousInFlowSibling(RenderObject* child)
+{
+    do {
+        child = child->previousSibling();
+    } while (child && child->isOutOfFlowPositioned());
+    return child;
+}
+
+inline LayoutUnit inlineLogicalWidth(RenderObject* child, bool checkStartEdge = true, bool checkEndEdge = true)
+{
+    unsigned lineDepth = 1;
+    LayoutUnit extraWidth = 0;
+    RenderElement* parent = child->parent();
+    while (is<RenderInline>(*parent) && lineDepth++ < cMaxLineDepth) {
+        const auto& parentAsRenderInline = downcast<RenderInline>(*parent);
+        if (!isEmptyInline(parentAsRenderInline)) {
+            checkStartEdge = checkStartEdge && shouldAddBorderPaddingMargin(previousInFlowSibling(child));
+            if (checkStartEdge)
+                extraWidth += borderPaddingMarginStart(parentAsRenderInline);
+            checkEndEdge = checkEndEdge && shouldAddBorderPaddingMargin(child->nextSibling());
+            if (checkEndEdge)
+                extraWidth += borderPaddingMarginEnd(parentAsRenderInline);
+            if (!checkStartEdge && !checkEndEdge)
+                return extraWidth;
+        }
+        child = parent;
+        parent = child->parent();
+    }
+    return extraWidth;
+}
+
+inline void BreakingContext::handleOutOfFlowPositioned(Vector<RenderBox*>& positionedObjects)
+{
+    // If our original display wasn't an inline type, then we can
+    // go ahead and determine our static inline position now.
+    auto& box = downcast<RenderBox>(*m_current.renderer());
+    bool isInlineType = box.style().isOriginalDisplayInlineType();
+    if (!isInlineType)
+        m_block.setStaticInlinePositionForChild(box, m_block.logicalHeight(), m_block.startOffsetForContent(m_block.logicalHeight()));
+    else {
+        // If our original display was an INLINE type, then we can go ahead
+        // and determine our static y position now.
+        box.layer()->setStaticBlockPosition(m_block.logicalHeight());
+    }
+
+    // If we're ignoring spaces, we have to stop and include this object and
+    // then start ignoring spaces again.
+    if (isInlineType || box.container()->isRenderInline()) {
+        if (m_ignoringSpaces)
+            m_lineMidpointState.ensureLineBoxInsideIgnoredSpaces(&box);
+        m_trailingObjects.appendBoxIfNeeded(&box);
+    } else
+        positionedObjects.append(&box);
+
+    m_width.addUncommittedWidth(inlineLogicalWidth(&box));
+    // Reset prior line break context characters.
+    m_renderTextInfo.m_lineBreakIterator.resetPriorContext();
+}
+
+inline void BreakingContext::handleFloat()
+{
+    auto& floatBox = downcast<RenderBox>(*m_current.renderer());
+    FloatingObject* floatingObject = m_lineBreaker.insertFloatingObject(floatBox);
+    // check if it fits in the current line.
+    // If it does, position it now, otherwise, position
+    // it after moving to next line (in clearFloats() func)
+    if (m_floatsFitOnLine && m_width.fitsOnLineExcludingTrailingWhitespace(m_block.logicalWidthForFloat(floatingObject))) {
+        m_lineBreaker.positionNewFloatOnLine(floatingObject, m_lastFloatFromPreviousLine, m_lineInfo, m_width);
+        if (m_lineBreakHistory.renderer() == m_current.renderer()) {
+            ASSERT(!m_lineBreakHistory.offset());
+            m_lineBreakHistory.increment();
+        }
+    } else
+        m_floatsFitOnLine = false;
+    // Update prior line break context characters, using U+FFFD (OBJECT REPLACEMENT CHARACTER) for floating element.
+    m_renderTextInfo.m_lineBreakIterator.updatePriorContext(replacementCharacter);
+}
+
+// This is currently just used for list markers and inline flows that have line boxes. Neither should
+// have an effect on whitespace at the start of the line.
+inline bool shouldSkipWhitespaceAfterStartObject(RenderBlockFlow& block, RenderObject* o, LineMidpointState& lineMidpointState)
+{
+    RenderObject* next = bidiNextSkippingEmptyInlines(block, o);
+    while (next && next->isFloatingOrOutOfFlowPositioned())
+        next = bidiNextSkippingEmptyInlines(block, next);
+
+    if (is<RenderText>(next) && downcast<RenderText>(*next).textLength() > 0) {
+        RenderText& nextText = downcast<RenderText>(*next);
+        UChar nextChar = nextText.characterAt(0);
+        if (nextText.style().isCollapsibleWhiteSpace(nextChar)) {
+            lineMidpointState.startIgnoringSpaces(InlineIterator(nullptr, o, 0));
+            return true;
+        }
+    }
+
+    return false;
+}
+
+inline void BreakingContext::handleEmptyInline()
+{
+    RenderInline& flowBox = downcast<RenderInline>(*m_current.renderer());
+
+    // This should only end up being called on empty inlines
+    ASSERT(isEmptyInline(flowBox));
+
+    // Now that some inline flows have line boxes, if we are already ignoring spaces, we need
+    // to make sure that we stop to include this object and then start ignoring spaces again.
+    // If this object is at the start of the line, we need to behave like list markers and
+    // start ignoring spaces.
+    bool requiresLineBox = alwaysRequiresLineBox(flowBox);
+    if (requiresLineBox || requiresLineBoxForContent(flowBox, m_lineInfo)) {
+        // An empty inline that only has line-height, vertical-align or font-metrics will only get a
+        // line box to affect the height of the line if the rest of the line is not empty.
+        if (requiresLineBox)
+            m_lineInfo.setEmpty(false, &m_block, &m_width);
+        if (m_ignoringSpaces) {
+            m_trailingObjects.clear();
+            m_lineMidpointState.ensureLineBoxInsideIgnoredSpaces(m_current.renderer());
+        } else if (m_blockStyle.collapseWhiteSpace() && m_resolver.position().renderer() == m_current.renderer()
+            && shouldSkipWhitespaceAfterStartObject(m_block, m_current.renderer(), m_lineMidpointState)) {
+            // Like with list markers, we start ignoring spaces to make sure that any
+            // additional spaces we see will be discarded.
+            m_currentCharacterIsSpace = true;
+            m_currentCharacterIsWS = true;
+            m_ignoringSpaces = true;
+        } else
+            m_trailingObjects.appendBoxIfNeeded(&flowBox);
+    }
+
+    m_width.addUncommittedWidth(inlineLogicalWidth(m_current.renderer()) + borderPaddingMarginStart(flowBox) + borderPaddingMarginEnd(flowBox));
+}
+
+inline void BreakingContext::handleReplaced()
+{
+    auto& replacedBox = downcast<RenderBox>(*m_current.renderer());
+
+    if (m_atStart)
+        m_width.updateAvailableWidth(replacedBox.logicalHeight());
+
+    // Break on replaced elements if either has normal white-space.
+    if ((m_autoWrap || RenderStyle::autoWrap(m_lastWS)) && (!m_current.renderer()->isImage() || m_allowImagesToBreak)
+        && (!m_current.renderer()->isRubyRun() || downcast<RenderRubyRun>(m_current.renderer())->canBreakBefore(m_renderTextInfo.m_lineBreakIterator))) {
+        commitLineBreakAtCurrentWidth(*m_current.renderer());
+    }
+
+    if (m_ignoringSpaces)
+        m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.renderer(), 0));
+
+    m_lineInfo.setEmpty(false, &m_block, &m_width);
+    m_ignoringSpaces = false;
+    m_currentCharacterIsSpace = false;
+    m_currentCharacterIsWS = false;
+    m_trailingObjects.clear();
+
+    // Optimize for a common case. If we can't find whitespace after the list
+    // item, then this is all moot.
+    LayoutUnit replacedLogicalWidth = m_block.logicalWidthForChild(replacedBox) + m_block.marginStartForChild(replacedBox) + m_block.marginEndForChild(replacedBox) + inlineLogicalWidth(m_current.renderer());
+    if (is<RenderListMarker>(*m_current.renderer())) {
+        if (m_blockStyle.collapseWhiteSpace() && shouldSkipWhitespaceAfterStartObject(m_block, m_current.renderer(), m_lineMidpointState)) {
+            // Like with inline flows, we start ignoring spaces to make sure that any
+            // additional spaces we see will be discarded.
+            m_currentCharacterIsSpace = true;
+            m_currentCharacterIsWS = false;
+            m_ignoringSpaces = true;
+        }
+        if (downcast<RenderListMarker>(*m_current.renderer()).isInside())
+            m_width.addUncommittedWidth(replacedLogicalWidth);
+    } else
+        m_width.addUncommittedWidth(replacedLogicalWidth);
+    if (is<RenderRubyRun>(*m_current.renderer())) {
+        m_width.applyOverhang(downcast<RenderRubyRun>(m_current.renderer()), m_lastObject, m_nextObject);
+        downcast<RenderRubyRun>(m_current.renderer())->updatePriorContextFromCachedBreakIterator(m_renderTextInfo.m_lineBreakIterator);
+    } else {
+        // Update prior line break context characters, using U+FFFD (OBJECT REPLACEMENT CHARACTER) for replaced element.
+        m_renderTextInfo.m_lineBreakIterator.updatePriorContext(replacementCharacter);
+    }
+}
+
+inline float firstPositiveWidth(const WordMeasurements& wordMeasurements)
+{
+    for (size_t i = 0; i < wordMeasurements.size(); ++i) {
+        if (wordMeasurements[i].width > 0)
+            return wordMeasurements[i].width;
+    }
+    return 0;
+}
+
+inline bool iteratorIsBeyondEndOfRenderCombineText(const InlineIterator& iter, RenderCombineText& renderer)
+{
+    return iter.renderer() == &renderer && iter.offset() >= renderer.textLength();
+}
+
+inline void nextCharacter(UChar& currentCharacter, UChar& lastCharacter, UChar& secondToLastCharacter)
+{
+    secondToLastCharacter = lastCharacter;
+    lastCharacter = currentCharacter;
+}
+
+// FIXME: Don't let counters mark themselves as needing pref width recalcs during layout
+// so we don't need this hack.
+inline void updateCounterIfNeeded(RenderText& renderText)
+{
+    if (!renderText.preferredLogicalWidthsDirty() || !is<RenderCounter>(renderText))
+        return;
+    downcast<RenderCounter>(renderText).updateCounter();
+}
+
+inline float measureHyphenWidth(RenderText& renderer, const FontCascade& font, HashSet<const Font*>* fallbackFonts = 0)
+{
+    const RenderStyle& style = renderer.style();
+    return font.width(RenderBlock::constructTextRun(&renderer, font, style.hyphenString().string(), style), fallbackFonts);
+}
+
+ALWAYS_INLINE float textWidth(RenderText& text, unsigned from, unsigned len, const FontCascade& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace, HashSet<const Font*>& fallbackFonts, TextLayout* layout = nullptr)
+{
+    const RenderStyle& style = text.style();
+
+    GlyphOverflow glyphOverflow;
+    if (isFixedPitch || (!from && len == text.textLength()) || style.hasTextCombine())
+        return text.width(from, len, font, xPos, &fallbackFonts, &glyphOverflow);
+
+    if (layout)
+        return FontCascade::width(*layout, from, len, &fallbackFonts);
+
+    TextRun run = RenderBlock::constructTextRun(&text, font, &text, from, len, style);
+    run.setCharactersLength(text.textLength() - from);
+    ASSERT(run.charactersLength() >= run.length());
+
+    run.setCharacterScanForCodePath(!text.canUseSimpleFontCodePath());
+    run.setTabSize(!collapseWhiteSpace, style.tabSize());
+    run.setXPos(xPos);
+    return font.width(run, &fallbackFonts, &glyphOverflow);
+}
+
+// Adding a pair of midpoints before a character will split it out into a new line box.
+inline void ensureCharacterGetsLineBox(LineMidpointState& lineMidpointState, InlineIterator& textParagraphSeparator)
+{
+    InlineIterator midpoint(0, textParagraphSeparator.renderer(), textParagraphSeparator.offset());
+    lineMidpointState.startIgnoringSpaces(InlineIterator(0, textParagraphSeparator.renderer(), textParagraphSeparator.offset() - 1));
+    lineMidpointState.stopIgnoringSpaces(InlineIterator(0, textParagraphSeparator.renderer(), textParagraphSeparator.offset()));
+}
+
+inline void tryHyphenating(RenderText& text, const FontCascade& font, const AtomicString& localeIdentifier, unsigned consecutiveHyphenatedLines, int consecutiveHyphenatedLinesLimit, int minimumPrefixLimit, int minimumSuffixLimit, unsigned lastSpace, unsigned pos, float xPos, int availableWidth, bool isFixedPitch, bool collapseWhiteSpace, int lastSpaceWordSpacing, InlineIterator& lineBreak, int nextBreakable, bool& hyphenated)
+{
+    // Map 'hyphenate-limit-{before,after}: auto;' to 2.
+    unsigned minimumPrefixLength;
+    unsigned minimumSuffixLength;
+
+    if (minimumPrefixLimit < 0)
+        minimumPrefixLength = 2;
+    else
+        minimumPrefixLength = static_cast<unsigned>(minimumPrefixLimit);
+
+    if (minimumSuffixLimit < 0)
+        minimumSuffixLength = 2;
+    else
+        minimumSuffixLength = static_cast<unsigned>(minimumSuffixLimit);
+
+    if (pos - lastSpace <= minimumSuffixLength)
+        return;
+
+    if (consecutiveHyphenatedLinesLimit >= 0 && consecutiveHyphenatedLines >= static_cast<unsigned>(consecutiveHyphenatedLinesLimit))
+        return;
+
+    int hyphenWidth = measureHyphenWidth(text, font);
+
+    float maxPrefixWidth = availableWidth - xPos - hyphenWidth - lastSpaceWordSpacing;
+    // If the maximum width available for the prefix before the hyphen is small, then it is very unlikely
+    // that an hyphenation opportunity exists, so do not bother to look for it.
+    if (maxPrefixWidth <= font.pixelSize() * 5 / 4)
+        return;
+
+    const RenderStyle& style = text.style();
+    TextRun run = RenderBlock::constructTextRun(&text, font, &text, lastSpace, pos - lastSpace, style);
+    run.setCharactersLength(text.textLength() - lastSpace);
+    ASSERT(run.charactersLength() >= run.length());
+
+    run.setTabSize(!collapseWhiteSpace, style.tabSize());
+    run.setXPos(xPos + lastSpaceWordSpacing);
+
+    unsigned prefixLength = font.offsetForPosition(run, maxPrefixWidth, false);
+    if (prefixLength < minimumPrefixLength)
+        return;
+
+    prefixLength = lastHyphenLocation(StringView(text.text()).substring(lastSpace, pos - lastSpace), std::min(prefixLength, pos - lastSpace - minimumSuffixLength) + 1, localeIdentifier);
+    if (!prefixLength || prefixLength < minimumPrefixLength)
+        return;
+
+    // When lastSpace is a space, which it always is except sometimes at the beginning of a line or after collapsed
+    // space, it should not count towards hyphenate-limit-before.
+    if (prefixLength == minimumPrefixLength) {
+        UChar characterAtLastSpace = text.characterAt(lastSpace);
+        if (characterAtLastSpace == ' ' || characterAtLastSpace == '\n' || characterAtLastSpace == '\t' || characterAtLastSpace == noBreakSpace)
+            return;
+    }
+
+    ASSERT(pos - lastSpace - prefixLength >= minimumSuffixLength);
+
+#if !ASSERT_DISABLED
+    HashSet<const Font*> fallbackFonts;
+    float prefixWidth = hyphenWidth + textWidth(text, lastSpace, prefixLength, font, xPos, isFixedPitch, collapseWhiteSpace, fallbackFonts) + lastSpaceWordSpacing;
+    ASSERT(xPos + prefixWidth <= availableWidth);
+#else
+    UNUSED_PARAM(isFixedPitch);
+#endif
+
+    lineBreak.moveTo(&text, lastSpace + prefixLength, nextBreakable);
+    hyphenated = true;
+}
+
+inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool& hyphenated,  unsigned& consecutiveHyphenatedLines)
+{
+    if (!m_current.offset())
+        m_appliedStartWidth = false;
+
+    RenderText& renderText = downcast<RenderText>(*m_current.renderer());
+
+    bool isSVGText = renderText.isSVGInlineText();
+
+    // If we have left a no-wrap inline and entered an autowrap inline while ignoring spaces
+    // then we need to mark the start of the autowrap inline as a potential linebreak now.
+    if (m_autoWrap && !RenderStyle::autoWrap(m_lastWS) && m_ignoringSpaces)
+        commitLineBreakAtCurrentWidth(renderText);
+
+    if (renderText.style().hasTextCombine() && is<RenderCombineText>(*m_current.renderer()) && !downcast<RenderCombineText>(*m_current.renderer()).isCombined()) {
+        auto& combineRenderer = downcast<RenderCombineText>(*m_current.renderer());
+        combineRenderer.combineText();
+        // The length of the renderer's text may have changed. Increment stale iterator positions
+        if (iteratorIsBeyondEndOfRenderCombineText(m_lineBreakHistory.current(), combineRenderer)) {
+            ASSERT(iteratorIsBeyondEndOfRenderCombineText(m_resolver.position(), combineRenderer));
+            m_lineBreakHistory.increment();
+            m_resolver.increment();
+        }
+    }
+
+    const RenderStyle& style = lineStyle(renderText, m_lineInfo);
+    const FontCascade& font = style.fontCascade();
+    bool isFixedPitch = font.isFixedPitch();
+    bool canHyphenate = style.hyphens() == HyphensAuto && WebCore::canHyphenate(style.locale());
+
+    unsigned lastSpace = m_current.offset();
+    float wordSpacing = m_currentStyle->fontCascade().wordSpacing();
+    float lastSpaceWordSpacing = 0;
+    float wordSpacingForWordMeasurement = 0;
+
+    float wrapW = m_width.uncommittedWidth() + inlineLogicalWidth(m_current.renderer(), !m_appliedStartWidth, true);
+    float charWidth = 0;
+    bool breakNBSP = m_autoWrap && m_currentStyle->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.
+    bool breakWords = m_currentStyle->breakWords() && ((m_autoWrap && !m_width.committedWidth()) || m_currWS == PRE);
+    bool midWordBreak = false;
+    bool breakAll = m_currentStyle->wordBreak() == BreakAllWordBreak && m_autoWrap;
+    float hyphenWidth = 0;
+    bool isLooseCJKMode = false;
+
+    if (isSVGText) {
+        breakWords = false;
+        breakAll = false;
+    }
+
+    if (m_renderTextInfo.m_text != &renderText) {
+        updateCounterIfNeeded(renderText);
+        m_renderTextInfo.m_text = &renderText;
+        m_renderTextInfo.m_font = &font;
+        m_renderTextInfo.m_layout = font.createLayout(&renderText, m_width.currentWidth(), m_collapseWhiteSpace);
+        m_renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(renderText.text(), style.locale(), mapLineBreakToIteratorMode(m_blockStyle.lineBreak()));
+        isLooseCJKMode = m_renderTextInfo.m_lineBreakIterator.isLooseCJKMode();
+    } else if (m_renderTextInfo.m_layout && m_renderTextInfo.m_font != &font) {
+        m_renderTextInfo.m_font = &font;
+        m_renderTextInfo.m_layout = font.createLayout(&renderText, m_width.currentWidth(), m_collapseWhiteSpace);
+    }
+
+    TextLayout* textLayout = m_renderTextInfo.m_layout.get();
+
+    // Non-zero only when kerning is enabled and TextLayout isn't used, in which case we measure
+    // words with their trailing space, then subtract its width.
+    HashSet<const Font*> fallbackFonts;
+    float wordTrailingSpaceWidth = (font.typesettingFeatures() & Kerning) && !textLayout ? font.width(RenderBlock::constructTextRun(&renderText, font, &space, 1, style), &fallbackFonts) + wordSpacing : 0;
+
+    UChar lastCharacter = m_renderTextInfo.m_lineBreakIterator.lastCharacter();
+    UChar secondToLastCharacter = m_renderTextInfo.m_lineBreakIterator.secondToLastCharacter();
+    for (; m_current.offset() < renderText.textLength(); m_current.fastIncrementInTextNode()) {
+        bool previousCharacterIsSpace = m_currentCharacterIsSpace;
+        bool previousCharacterIsWS = m_currentCharacterIsWS;
+        UChar c = m_current.current();
+        m_currentCharacterIsSpace = c == ' ' || c == '\t' || (!m_preservesNewline && (c == '\n'));
+
+        if (!m_collapseWhiteSpace || !m_currentCharacterIsSpace)
+            m_lineInfo.setEmpty(false, &m_block, &m_width);
+
+        if (c == softHyphen && m_autoWrap && !hyphenWidth && style.hyphens() != HyphensNone) {
+            hyphenWidth = measureHyphenWidth(renderText, font, &fallbackFonts);
+            m_width.addUncommittedWidth(hyphenWidth);
+        }
+
+        bool applyWordSpacing = false;
+
+        m_currentCharacterIsWS = m_currentCharacterIsSpace || (breakNBSP && c == noBreakSpace);
+
+        if ((breakAll || breakWords) && !midWordBreak && (!m_currentCharacterIsSpace || style.whiteSpace() != PRE_WRAP)) {
+            wrapW += charWidth;
+            bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && m_current.offset() + 1 < renderText.textLength() && U16_IS_TRAIL(renderText[m_current.offset() + 1]);
+            charWidth = textWidth(renderText, m_current.offset(), midWordBreakIsBeforeSurrogatePair ? 2 : 1, font, m_width.committedWidth() + wrapW, isFixedPitch, m_collapseWhiteSpace, fallbackFonts, textLayout);
+            midWordBreak = m_width.committedWidth() + wrapW + charWidth > m_width.availableWidth();
+        }
+
+        int nextBreakablePosition = m_current.nextBreakablePosition();
+        bool betweenWords = c == '\n' || (m_currWS != PRE && !m_atStart && isBreakable(m_renderTextInfo.m_lineBreakIterator, m_current.offset(), nextBreakablePosition, breakNBSP, isLooseCJKMode)
+            && (style.hyphens() != HyphensNone || (m_current.previousInSameNode() != softHyphen)));
+        m_current.setNextBreakablePosition(nextBreakablePosition);
+
+        if (betweenWords || midWordBreak) {
+            bool stoppedIgnoringSpaces = false;
+            if (m_ignoringSpaces) {
+                lastSpaceWordSpacing = 0;
+                if (!m_currentCharacterIsSpace) {
+                    // Stop ignoring spaces and begin at this
+                    // new point.
+                    m_ignoringSpaces = false;
+                    wordSpacingForWordMeasurement = 0;
+                    lastSpace = m_current.offset(); // e.g., "Foo    goo", don't add in any of the ignored spaces.
+                    m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.renderer(), m_current.offset()));
+                    stoppedIgnoringSpaces = true;
+                } else {
+                    // Just keep ignoring these spaces.
+                    nextCharacter(c, lastCharacter, secondToLastCharacter);
+                    continue;
+                }
+            }
+
+            wordMeasurements.grow(wordMeasurements.size() + 1);
+            WordMeasurement& wordMeasurement = wordMeasurements.last();
+
+            wordMeasurement.renderer = &renderText;
+            wordMeasurement.endOffset = m_current.offset();
+            wordMeasurement.startOffset = lastSpace;
+
+            float additionalTempWidth;
+            if (wordTrailingSpaceWidth && c == ' ')
+                additionalTempWidth = textWidth(renderText, lastSpace, m_current.offset() + 1 - lastSpace, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, wordMeasurement.fallbackFonts, textLayout) - wordTrailingSpaceWidth;
+            else
+                additionalTempWidth = textWidth(renderText, lastSpace, m_current.offset() - lastSpace, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, wordMeasurement.fallbackFonts, textLayout);
+
+            if (wordMeasurement.fallbackFonts.isEmpty() && !fallbackFonts.isEmpty())
+                wordMeasurement.fallbackFonts.swap(fallbackFonts);
+            fallbackFonts.clear();
+
+            wordMeasurement.width = additionalTempWidth + wordSpacingForWordMeasurement;
+            additionalTempWidth += lastSpaceWordSpacing;
+            m_width.addUncommittedWidth(additionalTempWidth);
+
+            if (m_collapseWhiteSpace && previousCharacterIsSpace && m_currentCharacterIsSpace && additionalTempWidth)
+                m_width.setTrailingWhitespaceWidth(additionalTempWidth);
+
+            if (!m_appliedStartWidth) {
+                m_width.addUncommittedWidth(inlineLogicalWidth(m_current.renderer(), true, false));
+                m_appliedStartWidth = true;
+            }
+
+            applyWordSpacing = wordSpacing && m_currentCharacterIsSpace;
+
+            if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine())
+                m_width.fitBelowFloats(m_lineInfo.isFirstLine());
+
+            if (m_autoWrap || breakWords) {
+                // If we break only after white-space, consider the current character
+                // as candidate width for this line.
+                bool lineWasTooWide = false;
+                if (m_width.fitsOnLine() && m_currentCharacterIsWS && m_currentStyle->breakOnlyAfterWhiteSpace() && !midWordBreak) {
+                    float charWidth = textWidth(renderText, m_current.offset(), 1, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, wordMeasurement.fallbackFonts, textLayout) + (applyWordSpacing ? wordSpacing : 0);
+                    // Check if line is too big even without the extra space
+                    // at the end of the line. If it is not, do nothing.
+                    // If the line needs the extra whitespace to be too long,
+                    // then move the line break to the space and skip all
+                    // additional whitespace.
+                    if (!m_width.fitsOnLineIncludingExtraWidth(charWidth)) {
+                        lineWasTooWide = true;
+                        m_lineBreakHistory.push([&](InlineIterator& modifyMe) {
+                            modifyMe.moveTo(m_current.renderer(), m_current.offset(), m_current.nextBreakablePosition());
+                            m_lineBreaker.skipTrailingWhitespace(modifyMe, m_lineInfo);
+                        });
+                    }
+                }
+                if (lineWasTooWide || !m_width.fitsOnLine()) {
+                    if (canHyphenate && !m_width.fitsOnLine()) {
+                        m_lineBreakHistory.push([&](InlineIterator& modifyMe) {
+                            tryHyphenating(renderText, font, style.locale(), consecutiveHyphenatedLines, m_blockStyle.hyphenationLimitLines(), style.hyphenationLimitBefore(), style.hyphenationLimitAfter(), lastSpace, m_current.offset(), m_width.currentWidth() - additionalTempWidth, m_width.availableWidth(), isFixedPitch, m_collapseWhiteSpace, lastSpaceWordSpacing, modifyMe, m_current.nextBreakablePosition(), m_lineBreaker.m_hyphenated);
+                        });
+                        if (m_lineBreaker.m_hyphenated) {
+                            m_atEnd = true;
+                            return false;
+                        }
+                    }
+                    if (m_lineBreakHistory.atTextParagraphSeparator()) {
+                        if (!stoppedIgnoringSpaces && m_current.offset() > 0)
+                            ensureCharacterGetsLineBox(m_lineMidpointState, m_current);
+                        m_lineBreakHistory.increment();
+                        m_lineInfo.setPreviousLineBrokeCleanly(true);
+                        wordMeasurement.endOffset = m_lineBreakHistory.offset();
+                    }
+                    if (m_lineBreakHistory.offset() && downcast<RenderText>(m_lineBreakHistory.renderer()) && downcast<RenderText>(*m_lineBreakHistory.renderer()).textLength() && downcast<RenderText>(*m_lineBreakHistory.renderer()).characterAt(m_lineBreakHistory.offset() - 1) == softHyphen && style.hyphens() != HyphensNone)
+                        hyphenated = true;
+                    if (m_lineBreakHistory.offset() && m_lineBreakHistory.offset() != (unsigned)wordMeasurement.endOffset && !wordMeasurement.width) {
+                        if (charWidth) {
+                            wordMeasurement.endOffset = m_lineBreakHistory.offset();
+                            wordMeasurement.width = charWidth;
+                        }
+                    }
+                    // Didn't fit. Jump to the end unless there's still an opportunity to collapse whitespace.
+                    if (m_ignoringSpaces || !m_collapseWhiteSpace || !m_currentCharacterIsSpace || !previousCharacterIsSpace) {
+                        m_atEnd = true;
+                        return false;
+                    }
+                } else {
+                    if (!betweenWords || (midWordBreak && !m_autoWrap))
+                        m_width.addUncommittedWidth(-additionalTempWidth);
+                    if (hyphenWidth) {
+                        // Subtract the width of the soft hyphen out since we fit on a line.
+                        m_width.addUncommittedWidth(-hyphenWidth);
+                        hyphenWidth = 0;
+                    }
+                }
+            }
+
+            if (c == '\n' && m_preservesNewline) {
+                if (!stoppedIgnoringSpaces && m_current.offset())
+                    ensureCharacterGetsLineBox(m_lineMidpointState, m_current);
+                commitLineBreakAtCurrentWidth(*m_current.renderer(), m_current.offset(), m_current.nextBreakablePosition());
+                m_lineBreakHistory.increment();
+                m_lineInfo.setPreviousLineBrokeCleanly(true);
+                return true;
+            }
+
+            if (m_autoWrap && betweenWords) {
+                commitLineBreakAtCurrentWidth(*m_current.renderer(), m_current.offset(), m_current.nextBreakablePosition());
+                wrapW = 0;
+                // 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;
+            }
+
+            if (midWordBreak && !U16_IS_TRAIL(c) && !(U_GET_GC_MASK(c) & U_GC_M_MASK)) {
+                // Remember this as a breakable position in case
+                // adding the end width forces a break.
+                m_lineBreakHistory.moveTo(m_current.renderer(), m_current.offset(), m_current.nextBreakablePosition());
+                midWordBreak &= (breakWords || breakAll);
+            }
+
+            if (betweenWords) {
+                lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
+                wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurement.width) ? wordSpacing : 0;
+                lastSpace = m_current.offset();
+            }
+
+            if (!m_ignoringSpaces && m_currentStyle->collapseWhiteSpace()) {
+                // If we encounter a newline, or if we encounter a
+                // second space, we need to go ahead and break up this
+                // run and enter a mode where we start collapsing spaces.
+                if (m_currentCharacterIsSpace && previousCharacterIsSpace) {
+                    m_ignoringSpaces = true;
+
+                    // We just entered a mode where we are ignoring
+                    // spaces. Create a midpoint to terminate the run
+                    // before the second space.
+                    m_lineMidpointState.startIgnoringSpaces(m_startOfIgnoredSpaces);
+                    m_trailingObjects.updateMidpointsForTrailingBoxes(m_lineMidpointState, InlineIterator(), TrailingObjects::DoNotCollapseFirstSpace);
+                }
+            }
+        } else if (m_ignoringSpaces) {
+            // Stop ignoring spaces and begin at this
+            // new point.
+            m_ignoringSpaces = false;
+            lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
+            wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurements.last().width) ? wordSpacing : 0;
+            lastSpace = m_current.offset(); // e.g., "Foo    goo", don't add in any of the ignored spaces.
+            m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.renderer(), m_current.offset()));
+        }
+
+        if (isSVGText && m_current.offset()) {
+            // Force creation of new InlineBoxes for each absolute positioned character (those that start new text chunks).
+            if (downcast<RenderSVGInlineText>(renderText).characterStartsNewTextChunk(m_current.offset()))
+                ensureCharacterGetsLineBox(m_lineMidpointState, m_current);
+        }
+
+        if (m_currentCharacterIsSpace && !previousCharacterIsSpace) {
+            m_startOfIgnoredSpaces.setRenderer(m_current.renderer());
+            m_startOfIgnoredSpaces.setOffset(m_current.offset());
+            // Spaces after right-aligned text and before a line-break get collapsed away completely so that the trailing
+            // space doesn't seem to push the text out from the right-hand edge.
+            // FIXME: Do this regardless of the container's alignment - will require rebaselining a lot of test results.
+            if (m_nextObject && m_startOfIgnoredSpaces.offset() && m_nextObject->isBR() && (m_blockStyle.textAlign() == RIGHT || m_blockStyle.textAlign() == WEBKIT_RIGHT)) {
+                m_startOfIgnoredSpaces.setOffset(m_startOfIgnoredSpaces.offset() - 1);
+                // If there's just a single trailing space start ignoring it now so it collapses away.
+                if (m_current.offset() == renderText.textLength() - 1)
+                    m_lineMidpointState.startIgnoringSpaces(m_startOfIgnoredSpaces);
+            }
+        }
+
+        if (!m_currentCharacterIsWS && previousCharacterIsWS) {
+            if (m_autoWrap && m_currentStyle->breakOnlyAfterWhiteSpace())
+                m_lineBreakHistory.moveTo(m_current.renderer(), m_current.offset(), m_current.nextBreakablePosition());
+        }
+
+        if (m_collapseWhiteSpace && m_currentCharacterIsSpace && !m_ignoringSpaces)
+            m_trailingObjects.setTrailingWhitespace(downcast<RenderText>(m_current.renderer()));
+        else if (!m_currentStyle->collapseWhiteSpace() || !m_currentCharacterIsSpace)
+            m_trailingObjects.clear();
+
+        m_atStart = false;
+        nextCharacter(c, lastCharacter, secondToLastCharacter);
+    }
+
+    m_renderTextInfo.m_lineBreakIterator.setPriorContext(lastCharacter, secondToLastCharacter);
+
+    wordMeasurements.grow(wordMeasurements.size() + 1);
+    WordMeasurement& wordMeasurement = wordMeasurements.last();
+    wordMeasurement.renderer = &renderText;
+
+    // IMPORTANT: current.m_pos is > length here!
+    float additionalTempWidth = m_ignoringSpaces ? 0 : textWidth(renderText, lastSpace, m_current.offset() - lastSpace, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, wordMeasurement.fallbackFonts, textLayout);
+    wordMeasurement.startOffset = lastSpace;
+    wordMeasurement.endOffset = m_current.offset();
+    wordMeasurement.width = m_ignoringSpaces ? 0 : additionalTempWidth + wordSpacingForWordMeasurement;
+    additionalTempWidth += lastSpaceWordSpacing;
+
+    float inlineLogicalTempWidth = inlineLogicalWidth(m_current.renderer(), !m_appliedStartWidth, m_includeEndWidth);
+    m_width.addUncommittedWidth(additionalTempWidth + inlineLogicalTempWidth);
+
+    if (wordMeasurement.fallbackFonts.isEmpty() && !fallbackFonts.isEmpty())
+        wordMeasurement.fallbackFonts.swap(fallbackFonts);
+    fallbackFonts.clear();
+
+    if (m_collapseWhiteSpace && m_currentCharacterIsSpace && additionalTempWidth)
+        m_width.setTrailingWhitespaceWidth(additionalTempWidth, inlineLogicalTempWidth);
+
+    m_includeEndWidth = false;
+
+    if (!m_width.fitsOnLine()) {
+        if (canHyphenate) {
+            m_lineBreakHistory.push([&](InlineIterator& modifyMe) {
+                tryHyphenating(renderText, font, style.locale(), consecutiveHyphenatedLines, m_blockStyle.hyphenationLimitLines(), style.hyphenationLimitBefore(), style.hyphenationLimitAfter(), lastSpace, m_current.offset(), m_width.currentWidth() - additionalTempWidth, m_width.availableWidth(), isFixedPitch, m_collapseWhiteSpace, lastSpaceWordSpacing, modifyMe, m_current.nextBreakablePosition(), m_lineBreaker.m_hyphenated);
+            });
+        }
+
+        if (!hyphenated && m_lineBreakHistory.previousInSameNode() == softHyphen && style.hyphens() != HyphensNone) {
+            hyphenated = true;
+            m_atEnd = true;
+        }
+    }
+    return false;
+}
+
+inline bool textBeginsWithBreakablePosition(RenderText& nextText)
+{
+    UChar c = nextText.characterAt(0);
+    return c == ' ' || c == '\t' || (c == '\n' && !nextText.preservesNewline());
+}
+
+inline bool BreakingContext::canBreakAtThisPosition()
+{
+    // If we are no-wrap and have found a line-breaking opportunity already then we should take it.
+    if (m_width.committedWidth() && !m_width.fitsOnLine(m_currentCharacterIsSpace) && m_currWS == NOWRAP)
+        return true;
+
+    // Avoid breaking on empty inlines.
+    if (is<RenderInline>(*m_current.renderer()) && isEmptyInline(downcast<RenderInline>(*m_current.renderer())))
+        return false;
+
+    // Avoid breaking before empty inlines (as long as the current object isn't replaced).
+    if (!m_current.renderer()->isReplaced() && is<RenderInline>(m_nextObject) && isEmptyInline(downcast<RenderInline>(*m_nextObject)))
+        return false;
+
+    // Return early if we autowrap and the current character is a space as we will always want to break at such a position.
+    if (m_autoWrap && m_currentCharacterIsSpace)
+        return true;
+
+    if (m_nextObject && m_nextObject->isLineBreakOpportunity())
+        return m_autoWrap;
+
+    bool nextIsAutoWrappingText = is<RenderText>(m_nextObject) && (m_autoWrap || m_nextObject->style().autoWrap());
+    if (!nextIsAutoWrappingText)
+        return m_autoWrap;
+    RenderText& nextRenderText = downcast<RenderText>(*m_nextObject);
+    bool currentIsTextOrEmptyInline = is<RenderText>(*m_current.renderer()) || (is<RenderInline>(*m_current.renderer()) && isEmptyInline(downcast<RenderInline>(*m_current.renderer())));
+    if (!currentIsTextOrEmptyInline)
+        return m_autoWrap && !m_current.renderer()->isRubyRun();
+
+    bool canBreakHere = !m_currentCharacterIsSpace && textBeginsWithBreakablePosition(nextRenderText);
+
+    // See if attempting to fit below floats creates more available width on the line.
+    if (!m_width.fitsOnLine() && !m_width.committedWidth())
+        m_width.fitBelowFloats(m_lineInfo.isFirstLine());
+
+    bool canPlaceOnLine = m_width.fitsOnLine() || !m_autoWrapWasEverTrueOnLine;
+
+    if (canPlaceOnLine && canBreakHere)
+        commitLineBreakAtCurrentWidth(nextRenderText);
+
+    return canBreakHere;
+}
+
+inline void BreakingContext::commitAndUpdateLineBreakIfNeeded()
+{
+    bool checkForBreak = canBreakAtThisPosition();
+
+    if (checkForBreak && !m_width.fitsOnLine(m_ignoringSpaces)) {
+        // if we have floats, try to get below them.
+        if (m_currentCharacterIsSpace && !m_ignoringSpaces && m_currentStyle->collapseWhiteSpace())
+            m_trailingObjects.clear();
+
+        if (m_width.committedWidth()) {
+            m_atEnd = true;
+            return;
+        }
+
+        m_width.fitBelowFloats(m_lineInfo.isFirstLine());
+
+        // |width| may have been adjusted because we got shoved down past a float (thus
+        // giving us more room), so we need to retest, and only jump to
+        // the end label if we still don't fit on the line. -dwh
+        if (!m_width.fitsOnLine(m_ignoringSpaces)) {
+            m_atEnd = true;
+            return;
+        }
+    } else if (m_blockStyle.autoWrap() && !m_width.fitsOnLine() && !m_width.committedWidth()) {
+        // If the container autowraps but the current child does not then we still need to ensure that it
+        // wraps and moves below any floats.
+        m_width.fitBelowFloats(m_lineInfo.isFirstLine());
+    }
+
+    if (!m_current.renderer()->isFloatingOrOutOfFlowPositioned()) {
+        m_lastObject = m_current.renderer();
+        if (m_lastObject->isReplaced() && m_autoWrap && !m_lastObject->isRubyRun() && (!m_lastObject->isImage() || m_allowImagesToBreak) && (!is<RenderListMarker>(*m_lastObject) || downcast<RenderListMarker>(*m_lastObject).isInside()))
+            commitLineBreakAtCurrentWidth(*m_nextObject);
+    }
+}
+
+inline TrailingObjects::CollapseFirstSpaceOrNot checkMidpoints(LineMidpointState& lineMidpointState, const InlineIterator& lBreak)
+{
+    // Check to see if our last midpoint is a start point beyond the line break. If so,
+    // shave it off the list, and shave off a trailing space if the previous end point doesn't
+    // preserve whitespace.
+    if (lBreak.renderer() && lineMidpointState.numMidpoints() && !(lineMidpointState.numMidpoints() % 2)) {
+        InlineIterator* midpoints = lineMidpointState.midpoints().data();
+        InlineIterator& endpoint = midpoints[lineMidpointState.numMidpoints() - 2];
+        const InlineIterator& startpoint = midpoints[lineMidpointState.numMidpoints() - 1];
+        InlineIterator currpoint = endpoint;
+        while (!currpoint.atEnd() && currpoint != startpoint && currpoint != lBreak)
+            currpoint.increment();
+        if (currpoint == lBreak) {
+            // We hit the line break before the start point. Shave off the start point.
+            lineMidpointState.decreaseNumMidpoints();
+            if (endpoint.renderer()->style().collapseWhiteSpace() && endpoint.renderer()->isText()) {
+                endpoint.fastDecrement();
+                return TrailingObjects::DoNotCollapseFirstSpace;
+            }
+        }
+    }
+    return TrailingObjects::CollapseFirstSpace;
+}
+
+inline InlineIterator BreakingContext::handleEndOfLine()
+{
+    if (m_lineBreakHistory.current() == m_resolver.position()) {
+        if (!m_lineBreakHistory.renderer() || !m_lineBreakHistory.renderer()->isBR()) {
+            // we just add as much as possible
+            if (m_blockStyle.whiteSpace() == PRE && !m_current.offset())
+                commitLineBreakAtCurrentWidth(*m_lastObject, m_lastObject->isText() ? m_lastObject->length() : 0);
+            else if (m_lineBreakHistory.renderer()) {
+                // 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.
+                commitLineBreakAtCurrentWidth(*m_current.renderer(), m_current.offset());
+            }
+        }
+        // make sure we consume at least one char/object.
+        if (m_lineBreakHistory.current() == m_resolver.position())
+            m_lineBreakHistory.increment();
+    } else if (!m_current.offset() && !m_width.committedWidth() && m_width.uncommittedWidth() && !m_hadUncommittedWidthBeforeCurrent) {
+        // Do not push the current object to the next line, when this line has some content, but it is still considered empty.
+        // Empty inline elements like <span></span> can produce such lines and now we just ignore these break opportunities
+        // at the start of a line, if no width has been committed yet.
+        // Behave as if it was actually empty and consume at least one object.
+        m_lineBreakHistory.increment();
+    }
+
+    // Sanity check our midpoints.
+    TrailingObjects::CollapseFirstSpaceOrNot collapsed = checkMidpoints(m_lineMidpointState, m_lineBreakHistory.current());
+
+    m_trailingObjects.updateMidpointsForTrailingBoxes(m_lineMidpointState, m_lineBreakHistory.current(), collapsed);
+
+    // We might have made lineBreak an iterator that points past the end
+    // of the object. Do this adjustment to make it point to the start
+    // of the next object instead to avoid confusing the rest of the
+    // code.
+    if (m_lineBreakHistory.offset()) {
+        m_lineBreakHistory.update([](InlineIterator& modifyMe) {
+            modifyMe.setOffset(modifyMe.offset() - 1);
+            modifyMe.increment();
+        });
+    }
+
+#if ENABLE(CSS_TRAILING_WORD)
+    if (m_blockStyle.trailingWord() == TrailingWord::PartiallyBalanced)
+        return optimalLineBreakLocationForTrailingWord();
+#endif
+    return m_lineBreakHistory.current();
+}
+
+#if ENABLE(CSS_TRAILING_WORD)
+inline InlineIterator BreakingContext::optimalLineBreakLocationForTrailingWord()
+{
+    const unsigned longTrailingWordLength = 20;
+    const float optimalTrailingLineRatio = 0.1;
+    InlineIterator lineBreak = m_lineBreakHistory.current();
+    if (!lineBreak.renderer() || !m_lineInfo.isFirstLine() || bidiNextSkippingEmptyInlines(*lineBreak.root(), lineBreak.renderer()) || !is<RenderText>(lineBreak.renderer()))
+        return lineBreak;
+    RenderText& renderText = downcast<RenderText>(*lineBreak.renderer());
+    // Don't even bother measuring if our remaining line has many characters
+    if (renderText.textLength() == lineBreak.offset() || renderText.textLength() - lineBreak.offset() > longTrailingWordLength)
+        return lineBreak;
+    bool isLooseCJKMode = m_renderTextInfo.m_text != &renderText && m_renderTextInfo.m_lineBreakIterator.isLooseCJKMode();
+    bool breakNBSP = m_autoWrap && m_currentStyle->nbspMode() == SPACE;
+    int nextBreakablePosition = lineBreak.nextBreakablePosition();
+    isBreakable(m_renderTextInfo.m_lineBreakIterator, lineBreak.offset() + 1, nextBreakablePosition, breakNBSP, isLooseCJKMode);
+    if (nextBreakablePosition < 0 || static_cast<unsigned>(nextBreakablePosition) != renderText.textLength())
+        return lineBreak;
+    const RenderStyle& style = lineStyle(renderText, m_lineInfo);
+    const FontCascade& font = style.fontCascade();
+    HashSet<const Font*> dummyFonts;
+    InlineIterator best = lineBreak;
+    for (size_t i = 1; i < m_lineBreakHistory.historyLength(); ++i) {
+        const InlineIterator& candidate = m_lineBreakHistory.get(i);
+        if (candidate.renderer() != lineBreak.renderer())
+            return best;
+        float width = textWidth(renderText, candidate.offset(), renderText.textLength() - candidate.offset(), font, 0, font.isFixedPitch(), m_collapseWhiteSpace, dummyFonts);
+        if (width > m_width.availableWidth())
+            return best;
+        if (width / m_width.availableWidth() > optimalTrailingLineRatio) // Subsequent line is long enough
+            return candidate;
+        best = candidate;
+    }
+    return best;
+}
+#endif
+
+}
+
+#endif // BreakingContext_h

Deleted: trunk/Source/WebCore/rendering/line/BreakingContextInlineHeaders.h (181170 => 181171)


--- trunk/Source/WebCore/rendering/line/BreakingContextInlineHeaders.h	2015-03-06 18:47:28 UTC (rev 181170)
+++ trunk/Source/WebCore/rendering/line/BreakingContextInlineHeaders.h	2015-03-06 19:06:30 UTC (rev 181171)
@@ -1,1202 +0,0 @@
-/*
- * Copyright (C) 2000 Lars Knoll (kn...@kde.org)
- * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All right reserved.
- * Copyright (C) 2010 Google Inc. All rights reserved.
- * Copyright (C) 2013 ChangSeok Oh <shivami...@gmail.com>
- * Copyright (C) 2013 Adobe Systems Inc. All right reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef BreakingContextInlineHeaders_h
-#define BreakingContextInlineHeaders_h
-
-#include "Hyphenation.h"
-#include "LineBreaker.h"
-#include "LineInfo.h"
-#include "LineWidth.h"
-#include "RenderCombineText.h"
-#include "RenderCounter.h"
-#include "RenderInline.h"
-#include "RenderLineBreak.h"
-#include "RenderListMarker.h"
-#include "RenderRubyRun.h"
-#include "RenderSVGInlineText.h"
-#include "TrailingObjects.h"
-#include "break_lines.h"
-#include <wtf/text/StringView.h>
-#include <wtf/unicode/CharacterNames.h>
-
-namespace WebCore {
-
-// We don't let our line box tree for a single line get any deeper than this.
-const unsigned cMaxLineDepth = 200;
-
-struct WordMeasurement {
-    WordMeasurement()
-        : renderer(0)
-        , width(0)
-        , startOffset(0)
-        , endOffset(0)
-    {
-    }
-
-    RenderText* renderer;
-    float width;
-    int startOffset;
-    int endOffset;
-    HashSet<const Font*> fallbackFonts;
-};
-
-class BreakingContext {
-public:
-    BreakingContext(LineBreaker& lineBreaker, InlineBidiResolver& resolver, LineInfo& inLineInfo, LineWidth& lineWidth, RenderTextInfo& inRenderTextInfo, FloatingObject* inLastFloatFromPreviousLine, bool appliedStartWidth, RenderBlockFlow& block)
-        : m_lineBreaker(lineBreaker)
-        , m_resolver(resolver)
-        , m_current(resolver.position())
-#if ENABLE(CSS_TRAILING_WORD)
-        , m_lineBreakHistory(InlineIterator(resolver.position()), block.style().trailingWord() == TrailingWord::PartiallyBalanced ? 5 : 1)
-#else
-        , m_lineBreakHistory(InlineIterator(resolver.position()), 1)
-#endif
-        , m_block(block)
-        , m_lastObject(m_current.renderer())
-        , m_nextObject(nullptr)
-        , m_currentStyle(nullptr)
-        , m_blockStyle(block.style())
-        , m_lineInfo(inLineInfo)
-        , m_renderTextInfo(inRenderTextInfo)
-        , m_lastFloatFromPreviousLine(inLastFloatFromPreviousLine)
-        , m_width(lineWidth)
-        , m_currWS(NORMAL)
-        , m_lastWS(NORMAL)
-        , m_preservesNewline(false)
-        , m_atStart(true)
-        , m_ignoringSpaces(false)
-        , m_currentCharacterIsSpace(false)
-        , m_currentCharacterIsWS(false)
-        , m_appliedStartWidth(appliedStartWidth)
-        , m_includeEndWidth(true)
-        , m_autoWrap(false)
-        , m_autoWrapWasEverTrueOnLine(false)
-        , m_floatsFitOnLine(true)
-        , m_collapseWhiteSpace(false)
-        , m_startingNewParagraph(m_lineInfo.previousLineBrokeCleanly())
-        , m_allowImagesToBreak(!block.document().inQuirksMode() || !block.isTableCell() || !m_blockStyle.logicalWidth().isIntrinsicOrAuto())
-        , m_atEnd(false)
-        , m_hadUncommittedWidthBeforeCurrent(false)
-        , m_lineMidpointState(resolver.midpointState())
-    {
-        m_lineInfo.setPreviousLineBrokeCleanly(false);
-    }
-
-    RenderObject* currentObject() { return m_current.renderer(); }
-    InlineIterator lineBreak() { return m_lineBreakHistory.current(); }
-    LineWidth& lineWidth() { return m_width; }
-    bool atEnd() { return m_atEnd; }
-
-    void initializeForCurrentObject();
-
-    void increment();
-
-    void handleBR(EClear&);
-    void handleOutOfFlowPositioned(Vector<RenderBox*>& positionedObjects);
-    void handleFloat();
-    void handleEmptyInline();
-    void handleReplaced();
-    bool handleText(WordMeasurements&, bool& hyphenated, unsigned& consecutiveHyphenatedLines);
-    bool canBreakAtThisPosition();
-    void commitAndUpdateLineBreakIfNeeded();
-    InlineIterator handleEndOfLine();
-#if ENABLE(CSS_TRAILING_WORD)
-    InlineIterator optimalLineBreakLocationForTrailingWord();
-#endif
-
-    void clearLineBreakIfFitsOnLine(bool ignoringTrailingSpace = false)
-    {
-        if (m_width.fitsOnLine(ignoringTrailingSpace) || m_lastWS == NOWRAP)
-            m_lineBreakHistory.clear();
-    }
-
-    void commitLineBreakAtCurrentWidth(RenderObject& object, unsigned offset = 0, int nextBreak = -1)
-    {
-        m_width.commit();
-        m_lineBreakHistory.moveTo(&object, offset, nextBreak);
-    }
-
-private:
-    // This class keeps a sliding window of the past n locations for an InlineIterator.
-    class InlineIteratorHistory : private Vector<InlineIterator, 1> {
-    public:
-        InlineIteratorHistory() = delete;
-        InlineIteratorHistory(const InlineIterator& initial, size_t capacity)
-            : m_capacity(capacity)
-        {
-            ASSERT(capacity > 0);
-            this->append(initial);
-        }
-
-        void push(std::function<void(InlineIterator& modifyMe)> updater)
-        {
-            ASSERT(!this->isEmpty());
-            if (m_capacity != 1)
-                this->insert(0, InlineIterator(this->at(0)));
-            updater(this->at(0));
-            if (m_capacity != 1)
-                this->resize(m_capacity);
-        }
-
-        void update(std::function<void(InlineIterator& modifyMe)> updater)
-        {
-            ASSERT(!this->isEmpty());
-            updater(this->at(0));
-        }
-
-        RenderObject* renderer() const { return this->at(0).renderer(); }
-        unsigned offset() const { return this->at(0).offset(); }
-        bool atTextParagraphSeparator() const { return this->at(0).atTextParagraphSeparator(); }
-        UChar previousInSameNode() const { return this->at(0).previousInSameNode(); }
-        const InlineIterator& get(size_t i) const { return this->at(i); };
-        const InlineIterator& current() const { return get(0); }
-        size_t historyLength() const { return this->size(); }
-
-        void moveTo(RenderObject* object, unsigned offset, int nextBreak = -1)
-        {
-            push([&](InlineIterator& modifyMe) {
-                modifyMe.moveTo(object, offset, nextBreak);
-            });
-        }
-
-        void increment()
-        {
-            update([](InlineIterator& modifyMe) {
-                modifyMe.increment();
-            });
-        }
-
-        void clear()
-        {
-            push([](InlineIterator& modifyMe) {
-                modifyMe.clear();
-            });
-        }
-
-    private:
-        const size_t m_capacity;
-    };
-
-    LineBreaker& m_lineBreaker;
-    InlineBidiResolver& m_resolver;
-
-    InlineIterator m_current;
-    InlineIteratorHistory m_lineBreakHistory;
-    InlineIterator m_startOfIgnoredSpaces;
-
-    RenderBlockFlow& m_block;
-    RenderObject* m_lastObject;
-    RenderObject* m_nextObject;
-
-    const RenderStyle* m_currentStyle;
-
-    // Firefox and Opera will allow a table cell to grow to fit an image inside it under
-    // very specific circumstances (in order to match common WinIE renderings).
-    // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.)
-    RenderStyle& m_blockStyle;
-
-    LineInfo& m_lineInfo;
-
-    RenderTextInfo& m_renderTextInfo;
-
-    FloatingObject* m_lastFloatFromPreviousLine;
-
-    LineWidth m_width;
-
-    EWhiteSpace m_currWS;
-    EWhiteSpace m_lastWS;
-
-    bool m_preservesNewline;
-    bool m_atStart;
-
-    // This variable is used only if whitespace isn't set to PRE, and it tells us whether
-    // or not we are currently ignoring whitespace.
-    bool m_ignoringSpaces;
-
-    // This variable tracks whether the very last character we saw was a space. We use
-    // this to detect when we encounter a second space so we know we have to terminate
-    // a run.
-    bool m_currentCharacterIsSpace;
-    bool m_currentCharacterIsWS;
-    bool m_appliedStartWidth;
-    bool m_includeEndWidth;
-    bool m_autoWrap;
-    bool m_autoWrapWasEverTrueOnLine;
-    bool m_floatsFitOnLine;
-    bool m_collapseWhiteSpace;
-    bool m_startingNewParagraph;
-    bool m_allowImagesToBreak;
-    bool m_atEnd;
-    bool m_hadUncommittedWidthBeforeCurrent;
-
-    LineMidpointState& m_lineMidpointState;
-
-    TrailingObjects m_trailingObjects;
-};
-
-inline void BreakingContext::initializeForCurrentObject()
-{
-    m_hadUncommittedWidthBeforeCurrent = !!m_width.uncommittedWidth();
-
-    m_currentStyle = &m_current.renderer()->style(); // FIXME: Should this be &lineStyle(*m_current.renderer(), m_lineInfo); ?
-
-    ASSERT(m_currentStyle);
-
-    m_nextObject = bidiNextSkippingEmptyInlines(m_block, m_current.renderer());
-    if (m_nextObject && m_nextObject->parent() && !m_nextObject->parent()->isDescendantOf(m_current.renderer()->parent()))
-        m_includeEndWidth = true;
-
-    m_currWS = m_current.renderer()->isReplaced() ? m_current.renderer()->parent()->style().whiteSpace() : m_currentStyle->whiteSpace();
-    m_lastWS = m_lastObject->isReplaced() ? m_lastObject->parent()->style().whiteSpace() : m_lastObject->style().whiteSpace();
-
-    m_autoWrap = RenderStyle::autoWrap(m_currWS);
-    m_autoWrapWasEverTrueOnLine = m_autoWrapWasEverTrueOnLine || m_autoWrap;
-
-    m_preservesNewline = m_current.renderer()->isSVGInlineText() ? false : RenderStyle::preserveNewline(m_currWS);
-
-    m_collapseWhiteSpace = RenderStyle::collapseWhiteSpace(m_currWS);
-}
-
-inline void BreakingContext::increment()
-{
-    // Clear out our character space bool, since inline <pre>s don't collapse whitespace
-    // with adjacent inline normal/nowrap spans.
-    if (!m_collapseWhiteSpace)
-        m_currentCharacterIsSpace = false;
-
-    m_current.moveToStartOf(m_nextObject);
-    m_atStart = false;
-}
-
-inline void BreakingContext::handleBR(EClear& clear)
-{
-    if (m_width.fitsOnLine()) {
-        RenderObject* br = m_current.renderer();
-        m_lineBreakHistory.push([&](InlineIterator& modifyMe) {
-            modifyMe.moveToStartOf(br);
-            modifyMe.increment();
-        });
-
-        // A <br> always breaks a line, so don't let the line be collapsed
-        // away. Also, the space at the end of a line with a <br> does not
-        // get collapsed away. It only does this if the previous line broke
-        // cleanly. Otherwise the <br> has no effect on whether the line is
-        // empty or not.
-        if (m_startingNewParagraph)
-            m_lineInfo.setEmpty(false, &m_block, &m_width);
-        m_trailingObjects.clear();
-        m_lineInfo.setPreviousLineBrokeCleanly(true);
-
-        // A <br> with clearance always needs a linebox in case the lines below it get dirtied later and
-        // need to check for floats to clear - so if we're ignoring spaces, stop ignoring them and add a
-        // run for this object.
-        if (m_ignoringSpaces && m_currentStyle->clear() != CNONE)
-            m_lineMidpointState.ensureLineBoxInsideIgnoredSpaces(br);
-        // If we were preceded by collapsing space and are in a right-aligned container we need to ensure the space gets
-        // collapsed away so that it doesn't push the text out from the container's right-hand edge.
-        // FIXME: Do this regardless of the container's alignment - will require rebaselining a lot of test results.
-        else if (m_ignoringSpaces && (m_blockStyle.textAlign() == RIGHT || m_blockStyle.textAlign() == WEBKIT_RIGHT))
-            m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.renderer(), m_current.offset()));
-
-        if (!m_lineInfo.isEmpty())
-            clear = m_currentStyle->clear();
-    }
-    m_atEnd = true;
-}
-
-inline LayoutUnit borderPaddingMarginStart(const RenderInline& child)
-{
-    return child.marginStart() + child.paddingStart() + child.borderStart();
-}
-
-inline LayoutUnit borderPaddingMarginEnd(const RenderInline& child)
-{
-    return child.marginEnd() + child.paddingEnd() + child.borderEnd();
-}
-
-inline bool shouldAddBorderPaddingMargin(RenderObject* child)
-{
-    if (!child)
-        return true;
-    // When deciding whether we're at the edge of an inline, adjacent collapsed whitespace is the same as no sibling at all.
-    if (is<RenderText>(*child) && !downcast<RenderText>(*child).textLength())
-        return true;
-#if ENABLE(CSS_BOX_DECORATION_BREAK)
-    if (is<RenderLineBreak>(*child) && child->parent()->style().boxDecorationBreak() == DCLONE)
-        return true;
-#endif
-    return false;
-}
-
-inline RenderObject* previousInFlowSibling(RenderObject* child)
-{
-    do {
-        child = child->previousSibling();
-    } while (child && child->isOutOfFlowPositioned());
-    return child;
-}
-
-inline LayoutUnit inlineLogicalWidth(RenderObject* child, bool checkStartEdge = true, bool checkEndEdge = true)
-{
-    unsigned lineDepth = 1;
-    LayoutUnit extraWidth = 0;
-    RenderElement* parent = child->parent();
-    while (is<RenderInline>(*parent) && lineDepth++ < cMaxLineDepth) {
-        const auto& parentAsRenderInline = downcast<RenderInline>(*parent);
-        if (!isEmptyInline(parentAsRenderInline)) {
-            checkStartEdge = checkStartEdge && shouldAddBorderPaddingMargin(previousInFlowSibling(child));
-            if (checkStartEdge)
-                extraWidth += borderPaddingMarginStart(parentAsRenderInline);
-            checkEndEdge = checkEndEdge && shouldAddBorderPaddingMargin(child->nextSibling());
-            if (checkEndEdge)
-                extraWidth += borderPaddingMarginEnd(parentAsRenderInline);
-            if (!checkStartEdge && !checkEndEdge)
-                return extraWidth;
-        }
-        child = parent;
-        parent = child->parent();
-    }
-    return extraWidth;
-}
-
-inline void BreakingContext::handleOutOfFlowPositioned(Vector<RenderBox*>& positionedObjects)
-{
-    // If our original display wasn't an inline type, then we can
-    // go ahead and determine our static inline position now.
-    auto& box = downcast<RenderBox>(*m_current.renderer());
-    bool isInlineType = box.style().isOriginalDisplayInlineType();
-    if (!isInlineType)
-        m_block.setStaticInlinePositionForChild(box, m_block.logicalHeight(), m_block.startOffsetForContent(m_block.logicalHeight()));
-    else {
-        // If our original display was an INLINE type, then we can go ahead
-        // and determine our static y position now.
-        box.layer()->setStaticBlockPosition(m_block.logicalHeight());
-    }
-
-    // If we're ignoring spaces, we have to stop and include this object and
-    // then start ignoring spaces again.
-    if (isInlineType || box.container()->isRenderInline()) {
-        if (m_ignoringSpaces)
-            m_lineMidpointState.ensureLineBoxInsideIgnoredSpaces(&box);
-        m_trailingObjects.appendBoxIfNeeded(&box);
-    } else
-        positionedObjects.append(&box);
-
-    m_width.addUncommittedWidth(inlineLogicalWidth(&box));
-    // Reset prior line break context characters.
-    m_renderTextInfo.m_lineBreakIterator.resetPriorContext();
-}
-
-inline void BreakingContext::handleFloat()
-{
-    auto& floatBox = downcast<RenderBox>(*m_current.renderer());
-    FloatingObject* floatingObject = m_lineBreaker.insertFloatingObject(floatBox);
-    // check if it fits in the current line.
-    // If it does, position it now, otherwise, position
-    // it after moving to next line (in clearFloats() func)
-    if (m_floatsFitOnLine && m_width.fitsOnLineExcludingTrailingWhitespace(m_block.logicalWidthForFloat(floatingObject))) {
-        m_lineBreaker.positionNewFloatOnLine(floatingObject, m_lastFloatFromPreviousLine, m_lineInfo, m_width);
-        if (m_lineBreakHistory.renderer() == m_current.renderer()) {
-            ASSERT(!m_lineBreakHistory.offset());
-            m_lineBreakHistory.increment();
-        }
-    } else
-        m_floatsFitOnLine = false;
-    // Update prior line break context characters, using U+FFFD (OBJECT REPLACEMENT CHARACTER) for floating element.
-    m_renderTextInfo.m_lineBreakIterator.updatePriorContext(replacementCharacter);
-}
-
-// This is currently just used for list markers and inline flows that have line boxes. Neither should
-// have an effect on whitespace at the start of the line.
-inline bool shouldSkipWhitespaceAfterStartObject(RenderBlockFlow& block, RenderObject* o, LineMidpointState& lineMidpointState)
-{
-    RenderObject* next = bidiNextSkippingEmptyInlines(block, o);
-    while (next && next->isFloatingOrOutOfFlowPositioned())
-        next = bidiNextSkippingEmptyInlines(block, next);
-
-    if (is<RenderText>(next) && downcast<RenderText>(*next).textLength() > 0) {
-        RenderText& nextText = downcast<RenderText>(*next);
-        UChar nextChar = nextText.characterAt(0);
-        if (nextText.style().isCollapsibleWhiteSpace(nextChar)) {
-            lineMidpointState.startIgnoringSpaces(InlineIterator(nullptr, o, 0));
-            return true;
-        }
-    }
-
-    return false;
-}
-
-inline void BreakingContext::handleEmptyInline()
-{
-    RenderInline& flowBox = downcast<RenderInline>(*m_current.renderer());
-
-    // This should only end up being called on empty inlines
-    ASSERT(isEmptyInline(flowBox));
-
-    // Now that some inline flows have line boxes, if we are already ignoring spaces, we need
-    // to make sure that we stop to include this object and then start ignoring spaces again.
-    // If this object is at the start of the line, we need to behave like list markers and
-    // start ignoring spaces.
-    bool requiresLineBox = alwaysRequiresLineBox(flowBox);
-    if (requiresLineBox || requiresLineBoxForContent(flowBox, m_lineInfo)) {
-        // An empty inline that only has line-height, vertical-align or font-metrics will only get a
-        // line box to affect the height of the line if the rest of the line is not empty.
-        if (requiresLineBox)
-            m_lineInfo.setEmpty(false, &m_block, &m_width);
-        if (m_ignoringSpaces) {
-            m_trailingObjects.clear();
-            m_lineMidpointState.ensureLineBoxInsideIgnoredSpaces(m_current.renderer());
-        } else if (m_blockStyle.collapseWhiteSpace() && m_resolver.position().renderer() == m_current.renderer()
-            && shouldSkipWhitespaceAfterStartObject(m_block, m_current.renderer(), m_lineMidpointState)) {
-            // Like with list markers, we start ignoring spaces to make sure that any
-            // additional spaces we see will be discarded.
-            m_currentCharacterIsSpace = true;
-            m_currentCharacterIsWS = true;
-            m_ignoringSpaces = true;
-        } else
-            m_trailingObjects.appendBoxIfNeeded(&flowBox);
-    }
-
-    m_width.addUncommittedWidth(inlineLogicalWidth(m_current.renderer()) + borderPaddingMarginStart(flowBox) + borderPaddingMarginEnd(flowBox));
-}
-
-inline void BreakingContext::handleReplaced()
-{
-    auto& replacedBox = downcast<RenderBox>(*m_current.renderer());
-
-    if (m_atStart)
-        m_width.updateAvailableWidth(replacedBox.logicalHeight());
-
-    // Break on replaced elements if either has normal white-space.
-    if ((m_autoWrap || RenderStyle::autoWrap(m_lastWS)) && (!m_current.renderer()->isImage() || m_allowImagesToBreak)
-        && (!m_current.renderer()->isRubyRun() || downcast<RenderRubyRun>(m_current.renderer())->canBreakBefore(m_renderTextInfo.m_lineBreakIterator))) {
-        commitLineBreakAtCurrentWidth(*m_current.renderer());
-    }
-
-    if (m_ignoringSpaces)
-        m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.renderer(), 0));
-
-    m_lineInfo.setEmpty(false, &m_block, &m_width);
-    m_ignoringSpaces = false;
-    m_currentCharacterIsSpace = false;
-    m_currentCharacterIsWS = false;
-    m_trailingObjects.clear();
-
-    // Optimize for a common case. If we can't find whitespace after the list
-    // item, then this is all moot.
-    LayoutUnit replacedLogicalWidth = m_block.logicalWidthForChild(replacedBox) + m_block.marginStartForChild(replacedBox) + m_block.marginEndForChild(replacedBox) + inlineLogicalWidth(m_current.renderer());
-    if (is<RenderListMarker>(*m_current.renderer())) {
-        if (m_blockStyle.collapseWhiteSpace() && shouldSkipWhitespaceAfterStartObject(m_block, m_current.renderer(), m_lineMidpointState)) {
-            // Like with inline flows, we start ignoring spaces to make sure that any
-            // additional spaces we see will be discarded.
-            m_currentCharacterIsSpace = true;
-            m_currentCharacterIsWS = false;
-            m_ignoringSpaces = true;
-        }
-        if (downcast<RenderListMarker>(*m_current.renderer()).isInside())
-            m_width.addUncommittedWidth(replacedLogicalWidth);
-    } else
-        m_width.addUncommittedWidth(replacedLogicalWidth);
-    if (is<RenderRubyRun>(*m_current.renderer())) {
-        m_width.applyOverhang(downcast<RenderRubyRun>(m_current.renderer()), m_lastObject, m_nextObject);
-        downcast<RenderRubyRun>(m_current.renderer())->updatePriorContextFromCachedBreakIterator(m_renderTextInfo.m_lineBreakIterator);
-    } else {
-        // Update prior line break context characters, using U+FFFD (OBJECT REPLACEMENT CHARACTER) for replaced element.
-        m_renderTextInfo.m_lineBreakIterator.updatePriorContext(replacementCharacter);
-    }
-}
-
-inline float firstPositiveWidth(const WordMeasurements& wordMeasurements)
-{
-    for (size_t i = 0; i < wordMeasurements.size(); ++i) {
-        if (wordMeasurements[i].width > 0)
-            return wordMeasurements[i].width;
-    }
-    return 0;
-}
-
-inline bool iteratorIsBeyondEndOfRenderCombineText(const InlineIterator& iter, RenderCombineText& renderer)
-{
-    return iter.renderer() == &renderer && iter.offset() >= renderer.textLength();
-}
-
-inline void nextCharacter(UChar& currentCharacter, UChar& lastCharacter, UChar& secondToLastCharacter)
-{
-    secondToLastCharacter = lastCharacter;
-    lastCharacter = currentCharacter;
-}
-
-// FIXME: Don't let counters mark themselves as needing pref width recalcs during layout
-// so we don't need this hack.
-inline void updateCounterIfNeeded(RenderText& renderText)
-{
-    if (!renderText.preferredLogicalWidthsDirty() || !is<RenderCounter>(renderText))
-        return;
-    downcast<RenderCounter>(renderText).updateCounter();
-}
-
-inline float measureHyphenWidth(RenderText& renderer, const FontCascade& font, HashSet<const Font*>* fallbackFonts = 0)
-{
-    const RenderStyle& style = renderer.style();
-    return font.width(RenderBlock::constructTextRun(&renderer, font, style.hyphenString().string(), style), fallbackFonts);
-}
-
-ALWAYS_INLINE float textWidth(RenderText& text, unsigned from, unsigned len, const FontCascade& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace, HashSet<const Font*>& fallbackFonts, TextLayout* layout = nullptr)
-{
-    const RenderStyle& style = text.style();
-
-    GlyphOverflow glyphOverflow;
-    if (isFixedPitch || (!from && len == text.textLength()) || style.hasTextCombine())
-        return text.width(from, len, font, xPos, &fallbackFonts, &glyphOverflow);
-
-    if (layout)
-        return FontCascade::width(*layout, from, len, &fallbackFonts);
-
-    TextRun run = RenderBlock::constructTextRun(&text, font, &text, from, len, style);
-    run.setCharactersLength(text.textLength() - from);
-    ASSERT(run.charactersLength() >= run.length());
-
-    run.setCharacterScanForCodePath(!text.canUseSimpleFontCodePath());
-    run.setTabSize(!collapseWhiteSpace, style.tabSize());
-    run.setXPos(xPos);
-    return font.width(run, &fallbackFonts, &glyphOverflow);
-}
-
-// Adding a pair of midpoints before a character will split it out into a new line box.
-inline void ensureCharacterGetsLineBox(LineMidpointState& lineMidpointState, InlineIterator& textParagraphSeparator)
-{
-    InlineIterator midpoint(0, textParagraphSeparator.renderer(), textParagraphSeparator.offset());
-    lineMidpointState.startIgnoringSpaces(InlineIterator(0, textParagraphSeparator.renderer(), textParagraphSeparator.offset() - 1));
-    lineMidpointState.stopIgnoringSpaces(InlineIterator(0, textParagraphSeparator.renderer(), textParagraphSeparator.offset()));
-}
-
-inline void tryHyphenating(RenderText& text, const FontCascade& font, const AtomicString& localeIdentifier, unsigned consecutiveHyphenatedLines, int consecutiveHyphenatedLinesLimit, int minimumPrefixLimit, int minimumSuffixLimit, unsigned lastSpace, unsigned pos, float xPos, int availableWidth, bool isFixedPitch, bool collapseWhiteSpace, int lastSpaceWordSpacing, InlineIterator& lineBreak, int nextBreakable, bool& hyphenated)
-{
-    // Map 'hyphenate-limit-{before,after}: auto;' to 2.
-    unsigned minimumPrefixLength;
-    unsigned minimumSuffixLength;
-
-    if (minimumPrefixLimit < 0)
-        minimumPrefixLength = 2;
-    else
-        minimumPrefixLength = static_cast<unsigned>(minimumPrefixLimit);
-
-    if (minimumSuffixLimit < 0)
-        minimumSuffixLength = 2;
-    else
-        minimumSuffixLength = static_cast<unsigned>(minimumSuffixLimit);
-
-    if (pos - lastSpace <= minimumSuffixLength)
-        return;
-
-    if (consecutiveHyphenatedLinesLimit >= 0 && consecutiveHyphenatedLines >= static_cast<unsigned>(consecutiveHyphenatedLinesLimit))
-        return;
-
-    int hyphenWidth = measureHyphenWidth(text, font);
-
-    float maxPrefixWidth = availableWidth - xPos - hyphenWidth - lastSpaceWordSpacing;
-    // If the maximum width available for the prefix before the hyphen is small, then it is very unlikely
-    // that an hyphenation opportunity exists, so do not bother to look for it.
-    if (maxPrefixWidth <= font.pixelSize() * 5 / 4)
-        return;
-
-    const RenderStyle& style = text.style();
-    TextRun run = RenderBlock::constructTextRun(&text, font, &text, lastSpace, pos - lastSpace, style);
-    run.setCharactersLength(text.textLength() - lastSpace);
-    ASSERT(run.charactersLength() >= run.length());
-
-    run.setTabSize(!collapseWhiteSpace, style.tabSize());
-    run.setXPos(xPos + lastSpaceWordSpacing);
-
-    unsigned prefixLength = font.offsetForPosition(run, maxPrefixWidth, false);
-    if (prefixLength < minimumPrefixLength)
-        return;
-
-    prefixLength = lastHyphenLocation(StringView(text.text()).substring(lastSpace, pos - lastSpace), std::min(prefixLength, pos - lastSpace - minimumSuffixLength) + 1, localeIdentifier);
-    if (!prefixLength || prefixLength < minimumPrefixLength)
-        return;
-
-    // When lastSpace is a space, which it always is except sometimes at the beginning of a line or after collapsed
-    // space, it should not count towards hyphenate-limit-before.
-    if (prefixLength == minimumPrefixLength) {
-        UChar characterAtLastSpace = text.characterAt(lastSpace);
-        if (characterAtLastSpace == ' ' || characterAtLastSpace == '\n' || characterAtLastSpace == '\t' || characterAtLastSpace == noBreakSpace)
-            return;
-    }
-
-    ASSERT(pos - lastSpace - prefixLength >= minimumSuffixLength);
-
-#if !ASSERT_DISABLED
-    HashSet<const Font*> fallbackFonts;
-    float prefixWidth = hyphenWidth + textWidth(text, lastSpace, prefixLength, font, xPos, isFixedPitch, collapseWhiteSpace, fallbackFonts) + lastSpaceWordSpacing;
-    ASSERT(xPos + prefixWidth <= availableWidth);
-#else
-    UNUSED_PARAM(isFixedPitch);
-#endif
-
-    lineBreak.moveTo(&text, lastSpace + prefixLength, nextBreakable);
-    hyphenated = true;
-}
-
-inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool& hyphenated,  unsigned& consecutiveHyphenatedLines)
-{
-    if (!m_current.offset())
-        m_appliedStartWidth = false;
-
-    RenderText& renderText = downcast<RenderText>(*m_current.renderer());
-
-    bool isSVGText = renderText.isSVGInlineText();
-
-    // If we have left a no-wrap inline and entered an autowrap inline while ignoring spaces
-    // then we need to mark the start of the autowrap inline as a potential linebreak now.
-    if (m_autoWrap && !RenderStyle::autoWrap(m_lastWS) && m_ignoringSpaces)
-        commitLineBreakAtCurrentWidth(renderText);
-
-    if (renderText.style().hasTextCombine() && is<RenderCombineText>(*m_current.renderer()) && !downcast<RenderCombineText>(*m_current.renderer()).isCombined()) {
-        auto& combineRenderer = downcast<RenderCombineText>(*m_current.renderer());
-        combineRenderer.combineText();
-        // The length of the renderer's text may have changed. Increment stale iterator positions
-        if (iteratorIsBeyondEndOfRenderCombineText(m_lineBreakHistory.current(), combineRenderer)) {
-            ASSERT(iteratorIsBeyondEndOfRenderCombineText(m_resolver.position(), combineRenderer));
-            m_lineBreakHistory.increment();
-            m_resolver.increment();
-        }
-    }
-
-    const RenderStyle& style = lineStyle(renderText, m_lineInfo);
-    const FontCascade& font = style.fontCascade();
-    bool isFixedPitch = font.isFixedPitch();
-    bool canHyphenate = style.hyphens() == HyphensAuto && WebCore::canHyphenate(style.locale());
-
-    unsigned lastSpace = m_current.offset();
-    float wordSpacing = m_currentStyle->fontCascade().wordSpacing();
-    float lastSpaceWordSpacing = 0;
-    float wordSpacingForWordMeasurement = 0;
-
-    float wrapW = m_width.uncommittedWidth() + inlineLogicalWidth(m_current.renderer(), !m_appliedStartWidth, true);
-    float charWidth = 0;
-    bool breakNBSP = m_autoWrap && m_currentStyle->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.
-    bool breakWords = m_currentStyle->breakWords() && ((m_autoWrap && !m_width.committedWidth()) || m_currWS == PRE);
-    bool midWordBreak = false;
-    bool breakAll = m_currentStyle->wordBreak() == BreakAllWordBreak && m_autoWrap;
-    float hyphenWidth = 0;
-    bool isLooseCJKMode = false;
-
-    if (isSVGText) {
-        breakWords = false;
-        breakAll = false;
-    }
-
-    if (m_renderTextInfo.m_text != &renderText) {
-        updateCounterIfNeeded(renderText);
-        m_renderTextInfo.m_text = &renderText;
-        m_renderTextInfo.m_font = &font;
-        m_renderTextInfo.m_layout = font.createLayout(&renderText, m_width.currentWidth(), m_collapseWhiteSpace);
-        m_renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(renderText.text(), style.locale(), mapLineBreakToIteratorMode(m_blockStyle.lineBreak()));
-        isLooseCJKMode = m_renderTextInfo.m_lineBreakIterator.isLooseCJKMode();
-    } else if (m_renderTextInfo.m_layout && m_renderTextInfo.m_font != &font) {
-        m_renderTextInfo.m_font = &font;
-        m_renderTextInfo.m_layout = font.createLayout(&renderText, m_width.currentWidth(), m_collapseWhiteSpace);
-    }
-
-    TextLayout* textLayout = m_renderTextInfo.m_layout.get();
-
-    // Non-zero only when kerning is enabled and TextLayout isn't used, in which case we measure
-    // words with their trailing space, then subtract its width.
-    HashSet<const Font*> fallbackFonts;
-    float wordTrailingSpaceWidth = (font.typesettingFeatures() & Kerning) && !textLayout ? font.width(RenderBlock::constructTextRun(&renderText, font, &space, 1, style), &fallbackFonts) + wordSpacing : 0;
-
-    UChar lastCharacter = m_renderTextInfo.m_lineBreakIterator.lastCharacter();
-    UChar secondToLastCharacter = m_renderTextInfo.m_lineBreakIterator.secondToLastCharacter();
-    for (; m_current.offset() < renderText.textLength(); m_current.fastIncrementInTextNode()) {
-        bool previousCharacterIsSpace = m_currentCharacterIsSpace;
-        bool previousCharacterIsWS = m_currentCharacterIsWS;
-        UChar c = m_current.current();
-        m_currentCharacterIsSpace = c == ' ' || c == '\t' || (!m_preservesNewline && (c == '\n'));
-
-        if (!m_collapseWhiteSpace || !m_currentCharacterIsSpace)
-            m_lineInfo.setEmpty(false, &m_block, &m_width);
-
-        if (c == softHyphen && m_autoWrap && !hyphenWidth && style.hyphens() != HyphensNone) {
-            hyphenWidth = measureHyphenWidth(renderText, font, &fallbackFonts);
-            m_width.addUncommittedWidth(hyphenWidth);
-        }
-
-        bool applyWordSpacing = false;
-
-        m_currentCharacterIsWS = m_currentCharacterIsSpace || (breakNBSP && c == noBreakSpace);
-
-        if ((breakAll || breakWords) && !midWordBreak && (!m_currentCharacterIsSpace || style.whiteSpace() != PRE_WRAP)) {
-            wrapW += charWidth;
-            bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && m_current.offset() + 1 < renderText.textLength() && U16_IS_TRAIL(renderText[m_current.offset() + 1]);
-            charWidth = textWidth(renderText, m_current.offset(), midWordBreakIsBeforeSurrogatePair ? 2 : 1, font, m_width.committedWidth() + wrapW, isFixedPitch, m_collapseWhiteSpace, fallbackFonts, textLayout);
-            midWordBreak = m_width.committedWidth() + wrapW + charWidth > m_width.availableWidth();
-        }
-
-        int nextBreakablePosition = m_current.nextBreakablePosition();
-        bool betweenWords = c == '\n' || (m_currWS != PRE && !m_atStart && isBreakable(m_renderTextInfo.m_lineBreakIterator, m_current.offset(), nextBreakablePosition, breakNBSP, isLooseCJKMode)
-            && (style.hyphens() != HyphensNone || (m_current.previousInSameNode() != softHyphen)));
-        m_current.setNextBreakablePosition(nextBreakablePosition);
-
-        if (betweenWords || midWordBreak) {
-            bool stoppedIgnoringSpaces = false;
-            if (m_ignoringSpaces) {
-                lastSpaceWordSpacing = 0;
-                if (!m_currentCharacterIsSpace) {
-                    // Stop ignoring spaces and begin at this
-                    // new point.
-                    m_ignoringSpaces = false;
-                    wordSpacingForWordMeasurement = 0;
-                    lastSpace = m_current.offset(); // e.g., "Foo    goo", don't add in any of the ignored spaces.
-                    m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.renderer(), m_current.offset()));
-                    stoppedIgnoringSpaces = true;
-                } else {
-                    // Just keep ignoring these spaces.
-                    nextCharacter(c, lastCharacter, secondToLastCharacter);
-                    continue;
-                }
-            }
-
-            wordMeasurements.grow(wordMeasurements.size() + 1);
-            WordMeasurement& wordMeasurement = wordMeasurements.last();
-
-            wordMeasurement.renderer = &renderText;
-            wordMeasurement.endOffset = m_current.offset();
-            wordMeasurement.startOffset = lastSpace;
-
-            float additionalTempWidth;
-            if (wordTrailingSpaceWidth && c == ' ')
-                additionalTempWidth = textWidth(renderText, lastSpace, m_current.offset() + 1 - lastSpace, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, wordMeasurement.fallbackFonts, textLayout) - wordTrailingSpaceWidth;
-            else
-                additionalTempWidth = textWidth(renderText, lastSpace, m_current.offset() - lastSpace, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, wordMeasurement.fallbackFonts, textLayout);
-
-            if (wordMeasurement.fallbackFonts.isEmpty() && !fallbackFonts.isEmpty())
-                wordMeasurement.fallbackFonts.swap(fallbackFonts);
-            fallbackFonts.clear();
-
-            wordMeasurement.width = additionalTempWidth + wordSpacingForWordMeasurement;
-            additionalTempWidth += lastSpaceWordSpacing;
-            m_width.addUncommittedWidth(additionalTempWidth);
-
-            if (m_collapseWhiteSpace && previousCharacterIsSpace && m_currentCharacterIsSpace && additionalTempWidth)
-                m_width.setTrailingWhitespaceWidth(additionalTempWidth);
-
-            if (!m_appliedStartWidth) {
-                m_width.addUncommittedWidth(inlineLogicalWidth(m_current.renderer(), true, false));
-                m_appliedStartWidth = true;
-            }
-
-            applyWordSpacing = wordSpacing && m_currentCharacterIsSpace;
-
-            if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine())
-                m_width.fitBelowFloats(m_lineInfo.isFirstLine());
-
-            if (m_autoWrap || breakWords) {
-                // If we break only after white-space, consider the current character
-                // as candidate width for this line.
-                bool lineWasTooWide = false;
-                if (m_width.fitsOnLine() && m_currentCharacterIsWS && m_currentStyle->breakOnlyAfterWhiteSpace() && !midWordBreak) {
-                    float charWidth = textWidth(renderText, m_current.offset(), 1, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, wordMeasurement.fallbackFonts, textLayout) + (applyWordSpacing ? wordSpacing : 0);
-                    // Check if line is too big even without the extra space
-                    // at the end of the line. If it is not, do nothing.
-                    // If the line needs the extra whitespace to be too long,
-                    // then move the line break to the space and skip all
-                    // additional whitespace.
-                    if (!m_width.fitsOnLineIncludingExtraWidth(charWidth)) {
-                        lineWasTooWide = true;
-                        m_lineBreakHistory.push([&](InlineIterator& modifyMe) {
-                            modifyMe.moveTo(m_current.renderer(), m_current.offset(), m_current.nextBreakablePosition());
-                            m_lineBreaker.skipTrailingWhitespace(modifyMe, m_lineInfo);
-                        });
-                    }
-                }
-                if (lineWasTooWide || !m_width.fitsOnLine()) {
-                    if (canHyphenate && !m_width.fitsOnLine()) {
-                        m_lineBreakHistory.push([&](InlineIterator& modifyMe) {
-                            tryHyphenating(renderText, font, style.locale(), consecutiveHyphenatedLines, m_blockStyle.hyphenationLimitLines(), style.hyphenationLimitBefore(), style.hyphenationLimitAfter(), lastSpace, m_current.offset(), m_width.currentWidth() - additionalTempWidth, m_width.availableWidth(), isFixedPitch, m_collapseWhiteSpace, lastSpaceWordSpacing, modifyMe, m_current.nextBreakablePosition(), m_lineBreaker.m_hyphenated);
-                        });
-                        if (m_lineBreaker.m_hyphenated) {
-                            m_atEnd = true;
-                            return false;
-                        }
-                    }
-                    if (m_lineBreakHistory.atTextParagraphSeparator()) {
-                        if (!stoppedIgnoringSpaces && m_current.offset() > 0)
-                            ensureCharacterGetsLineBox(m_lineMidpointState, m_current);
-                        m_lineBreakHistory.increment();
-                        m_lineInfo.setPreviousLineBrokeCleanly(true);
-                        wordMeasurement.endOffset = m_lineBreakHistory.offset();
-                    }
-                    if (m_lineBreakHistory.offset() && downcast<RenderText>(m_lineBreakHistory.renderer()) && downcast<RenderText>(*m_lineBreakHistory.renderer()).textLength() && downcast<RenderText>(*m_lineBreakHistory.renderer()).characterAt(m_lineBreakHistory.offset() - 1) == softHyphen && style.hyphens() != HyphensNone)
-                        hyphenated = true;
-                    if (m_lineBreakHistory.offset() && m_lineBreakHistory.offset() != (unsigned)wordMeasurement.endOffset && !wordMeasurement.width) {
-                        if (charWidth) {
-                            wordMeasurement.endOffset = m_lineBreakHistory.offset();
-                            wordMeasurement.width = charWidth;
-                        }
-                    }
-                    // Didn't fit. Jump to the end unless there's still an opportunity to collapse whitespace.
-                    if (m_ignoringSpaces || !m_collapseWhiteSpace || !m_currentCharacterIsSpace || !previousCharacterIsSpace) {
-                        m_atEnd = true;
-                        return false;
-                    }
-                } else {
-                    if (!betweenWords || (midWordBreak && !m_autoWrap))
-                        m_width.addUncommittedWidth(-additionalTempWidth);
-                    if (hyphenWidth) {
-                        // Subtract the width of the soft hyphen out since we fit on a line.
-                        m_width.addUncommittedWidth(-hyphenWidth);
-                        hyphenWidth = 0;
-                    }
-                }
-            }
-
-            if (c == '\n' && m_preservesNewline) {
-                if (!stoppedIgnoringSpaces && m_current.offset())
-                    ensureCharacterGetsLineBox(m_lineMidpointState, m_current);
-                commitLineBreakAtCurrentWidth(*m_current.renderer(), m_current.offset(), m_current.nextBreakablePosition());
-                m_lineBreakHistory.increment();
-                m_lineInfo.setPreviousLineBrokeCleanly(true);
-                return true;
-            }
-
-            if (m_autoWrap && betweenWords) {
-                commitLineBreakAtCurrentWidth(*m_current.renderer(), m_current.offset(), m_current.nextBreakablePosition());
-                wrapW = 0;
-                // 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;
-            }
-
-            if (midWordBreak && !U16_IS_TRAIL(c) && !(U_GET_GC_MASK(c) & U_GC_M_MASK)) {
-                // Remember this as a breakable position in case
-                // adding the end width forces a break.
-                m_lineBreakHistory.moveTo(m_current.renderer(), m_current.offset(), m_current.nextBreakablePosition());
-                midWordBreak &= (breakWords || breakAll);
-            }
-
-            if (betweenWords) {
-                lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
-                wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurement.width) ? wordSpacing : 0;
-                lastSpace = m_current.offset();
-            }
-
-            if (!m_ignoringSpaces && m_currentStyle->collapseWhiteSpace()) {
-                // If we encounter a newline, or if we encounter a
-                // second space, we need to go ahead and break up this
-                // run and enter a mode where we start collapsing spaces.
-                if (m_currentCharacterIsSpace && previousCharacterIsSpace) {
-                    m_ignoringSpaces = true;
-
-                    // We just entered a mode where we are ignoring
-                    // spaces. Create a midpoint to terminate the run
-                    // before the second space.
-                    m_lineMidpointState.startIgnoringSpaces(m_startOfIgnoredSpaces);
-                    m_trailingObjects.updateMidpointsForTrailingBoxes(m_lineMidpointState, InlineIterator(), TrailingObjects::DoNotCollapseFirstSpace);
-                }
-            }
-        } else if (m_ignoringSpaces) {
-            // Stop ignoring spaces and begin at this
-            // new point.
-            m_ignoringSpaces = false;
-            lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
-            wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurements.last().width) ? wordSpacing : 0;
-            lastSpace = m_current.offset(); // e.g., "Foo    goo", don't add in any of the ignored spaces.
-            m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.renderer(), m_current.offset()));
-        }
-
-        if (isSVGText && m_current.offset()) {
-            // Force creation of new InlineBoxes for each absolute positioned character (those that start new text chunks).
-            if (downcast<RenderSVGInlineText>(renderText).characterStartsNewTextChunk(m_current.offset()))
-                ensureCharacterGetsLineBox(m_lineMidpointState, m_current);
-        }
-
-        if (m_currentCharacterIsSpace && !previousCharacterIsSpace) {
-            m_startOfIgnoredSpaces.setRenderer(m_current.renderer());
-            m_startOfIgnoredSpaces.setOffset(m_current.offset());
-            // Spaces after right-aligned text and before a line-break get collapsed away completely so that the trailing
-            // space doesn't seem to push the text out from the right-hand edge.
-            // FIXME: Do this regardless of the container's alignment - will require rebaselining a lot of test results.
-            if (m_nextObject && m_startOfIgnoredSpaces.offset() && m_nextObject->isBR() && (m_blockStyle.textAlign() == RIGHT || m_blockStyle.textAlign() == WEBKIT_RIGHT)) {
-                m_startOfIgnoredSpaces.setOffset(m_startOfIgnoredSpaces.offset() - 1);
-                // If there's just a single trailing space start ignoring it now so it collapses away.
-                if (m_current.offset() == renderText.textLength() - 1)
-                    m_lineMidpointState.startIgnoringSpaces(m_startOfIgnoredSpaces);
-            }
-        }
-
-        if (!m_currentCharacterIsWS && previousCharacterIsWS) {
-            if (m_autoWrap && m_currentStyle->breakOnlyAfterWhiteSpace())
-                m_lineBreakHistory.moveTo(m_current.renderer(), m_current.offset(), m_current.nextBreakablePosition());
-        }
-
-        if (m_collapseWhiteSpace && m_currentCharacterIsSpace && !m_ignoringSpaces)
-            m_trailingObjects.setTrailingWhitespace(downcast<RenderText>(m_current.renderer()));
-        else if (!m_currentStyle->collapseWhiteSpace() || !m_currentCharacterIsSpace)
-            m_trailingObjects.clear();
-
-        m_atStart = false;
-        nextCharacter(c, lastCharacter, secondToLastCharacter);
-    }
-
-    m_renderTextInfo.m_lineBreakIterator.setPriorContext(lastCharacter, secondToLastCharacter);
-
-    wordMeasurements.grow(wordMeasurements.size() + 1);
-    WordMeasurement& wordMeasurement = wordMeasurements.last();
-    wordMeasurement.renderer = &renderText;
-
-    // IMPORTANT: current.m_pos is > length here!
-    float additionalTempWidth = m_ignoringSpaces ? 0 : textWidth(renderText, lastSpace, m_current.offset() - lastSpace, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, wordMeasurement.fallbackFonts, textLayout);
-    wordMeasurement.startOffset = lastSpace;
-    wordMeasurement.endOffset = m_current.offset();
-    wordMeasurement.width = m_ignoringSpaces ? 0 : additionalTempWidth + wordSpacingForWordMeasurement;
-    additionalTempWidth += lastSpaceWordSpacing;
-
-    float inlineLogicalTempWidth = inlineLogicalWidth(m_current.renderer(), !m_appliedStartWidth, m_includeEndWidth);
-    m_width.addUncommittedWidth(additionalTempWidth + inlineLogicalTempWidth);
-
-    if (wordMeasurement.fallbackFonts.isEmpty() && !fallbackFonts.isEmpty())
-        wordMeasurement.fallbackFonts.swap(fallbackFonts);
-    fallbackFonts.clear();
-
-    if (m_collapseWhiteSpace && m_currentCharacterIsSpace && additionalTempWidth)
-        m_width.setTrailingWhitespaceWidth(additionalTempWidth, inlineLogicalTempWidth);
-
-    m_includeEndWidth = false;
-
-    if (!m_width.fitsOnLine()) {
-        if (canHyphenate) {
-            m_lineBreakHistory.push([&](InlineIterator& modifyMe) {
-                tryHyphenating(renderText, font, style.locale(), consecutiveHyphenatedLines, m_blockStyle.hyphenationLimitLines(), style.hyphenationLimitBefore(), style.hyphenationLimitAfter(), lastSpace, m_current.offset(), m_width.currentWidth() - additionalTempWidth, m_width.availableWidth(), isFixedPitch, m_collapseWhiteSpace, lastSpaceWordSpacing, modifyMe, m_current.nextBreakablePosition(), m_lineBreaker.m_hyphenated);
-            });
-        }
-
-        if (!hyphenated && m_lineBreakHistory.previousInSameNode() == softHyphen && style.hyphens() != HyphensNone) {
-            hyphenated = true;
-            m_atEnd = true;
-        }
-    }
-    return false;
-}
-
-inline bool textBeginsWithBreakablePosition(RenderText& nextText)
-{
-    UChar c = nextText.characterAt(0);
-    return c == ' ' || c == '\t' || (c == '\n' && !nextText.preservesNewline());
-}
-
-inline bool BreakingContext::canBreakAtThisPosition()
-{
-    // If we are no-wrap and have found a line-breaking opportunity already then we should take it.
-    if (m_width.committedWidth() && !m_width.fitsOnLine(m_currentCharacterIsSpace) && m_currWS == NOWRAP)
-        return true;
-
-    // Avoid breaking on empty inlines.
-    if (is<RenderInline>(*m_current.renderer()) && isEmptyInline(downcast<RenderInline>(*m_current.renderer())))
-        return false;
-
-    // Avoid breaking before empty inlines (as long as the current object isn't replaced).
-    if (!m_current.renderer()->isReplaced() && is<RenderInline>(m_nextObject) && isEmptyInline(downcast<RenderInline>(*m_nextObject)))
-        return false;
-
-    // Return early if we autowrap and the current character is a space as we will always want to break at such a position.
-    if (m_autoWrap && m_currentCharacterIsSpace)
-        return true;
-
-    if (m_nextObject && m_nextObject->isLineBreakOpportunity())
-        return m_autoWrap;
-
-    bool nextIsAutoWrappingText = is<RenderText>(m_nextObject) && (m_autoWrap || m_nextObject->style().autoWrap());
-    if (!nextIsAutoWrappingText)
-        return m_autoWrap;
-    RenderText& nextRenderText = downcast<RenderText>(*m_nextObject);
-    bool currentIsTextOrEmptyInline = is<RenderText>(*m_current.renderer()) || (is<RenderInline>(*m_current.renderer()) && isEmptyInline(downcast<RenderInline>(*m_current.renderer())));
-    if (!currentIsTextOrEmptyInline)
-        return m_autoWrap && !m_current.renderer()->isRubyRun();
-
-    bool canBreakHere = !m_currentCharacterIsSpace && textBeginsWithBreakablePosition(nextRenderText);
-
-    // See if attempting to fit below floats creates more available width on the line.
-    if (!m_width.fitsOnLine() && !m_width.committedWidth())
-        m_width.fitBelowFloats(m_lineInfo.isFirstLine());
-
-    bool canPlaceOnLine = m_width.fitsOnLine() || !m_autoWrapWasEverTrueOnLine;
-
-    if (canPlaceOnLine && canBreakHere)
-        commitLineBreakAtCurrentWidth(nextRenderText);
-
-    return canBreakHere;
-}
-
-inline void BreakingContext::commitAndUpdateLineBreakIfNeeded()
-{
-    bool checkForBreak = canBreakAtThisPosition();
-
-    if (checkForBreak && !m_width.fitsOnLine(m_ignoringSpaces)) {
-        // if we have floats, try to get below them.
-        if (m_currentCharacterIsSpace && !m_ignoringSpaces && m_currentStyle->collapseWhiteSpace())
-            m_trailingObjects.clear();
-
-        if (m_width.committedWidth()) {
-            m_atEnd = true;
-            return;
-        }
-
-        m_width.fitBelowFloats(m_lineInfo.isFirstLine());
-
-        // |width| may have been adjusted because we got shoved down past a float (thus
-        // giving us more room), so we need to retest, and only jump to
-        // the end label if we still don't fit on the line. -dwh
-        if (!m_width.fitsOnLine(m_ignoringSpaces)) {
-            m_atEnd = true;
-            return;
-        }
-    } else if (m_blockStyle.autoWrap() && !m_width.fitsOnLine() && !m_width.committedWidth()) {
-        // If the container autowraps but the current child does not then we still need to ensure that it
-        // wraps and moves below any floats.
-        m_width.fitBelowFloats(m_lineInfo.isFirstLine());
-    }
-
-    if (!m_current.renderer()->isFloatingOrOutOfFlowPositioned()) {
-        m_lastObject = m_current.renderer();
-        if (m_lastObject->isReplaced() && m_autoWrap && !m_lastObject->isRubyRun() && (!m_lastObject->isImage() || m_allowImagesToBreak) && (!is<RenderListMarker>(*m_lastObject) || downcast<RenderListMarker>(*m_lastObject).isInside()))
-            commitLineBreakAtCurrentWidth(*m_nextObject);
-    }
-}
-
-inline TrailingObjects::CollapseFirstSpaceOrNot checkMidpoints(LineMidpointState& lineMidpointState, const InlineIterator& lBreak)
-{
-    // Check to see if our last midpoint is a start point beyond the line break. If so,
-    // shave it off the list, and shave off a trailing space if the previous end point doesn't
-    // preserve whitespace.
-    if (lBreak.renderer() && lineMidpointState.numMidpoints() && !(lineMidpointState.numMidpoints() % 2)) {
-        InlineIterator* midpoints = lineMidpointState.midpoints().data();
-        InlineIterator& endpoint = midpoints[lineMidpointState.numMidpoints() - 2];
-        const InlineIterator& startpoint = midpoints[lineMidpointState.numMidpoints() - 1];
-        InlineIterator currpoint = endpoint;
-        while (!currpoint.atEnd() && currpoint != startpoint && currpoint != lBreak)
-            currpoint.increment();
-        if (currpoint == lBreak) {
-            // We hit the line break before the start point. Shave off the start point.
-            lineMidpointState.decreaseNumMidpoints();
-            if (endpoint.renderer()->style().collapseWhiteSpace() && endpoint.renderer()->isText()) {
-                endpoint.fastDecrement();
-                return TrailingObjects::DoNotCollapseFirstSpace;
-            }
-        }
-    }
-    return TrailingObjects::CollapseFirstSpace;
-}
-
-inline InlineIterator BreakingContext::handleEndOfLine()
-{
-    if (m_lineBreakHistory.current() == m_resolver.position()) {
-        if (!m_lineBreakHistory.renderer() || !m_lineBreakHistory.renderer()->isBR()) {
-            // we just add as much as possible
-            if (m_blockStyle.whiteSpace() == PRE && !m_current.offset())
-                commitLineBreakAtCurrentWidth(*m_lastObject, m_lastObject->isText() ? m_lastObject->length() : 0);
-            else if (m_lineBreakHistory.renderer()) {
-                // 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.
-                commitLineBreakAtCurrentWidth(*m_current.renderer(), m_current.offset());
-            }
-        }
-        // make sure we consume at least one char/object.
-        if (m_lineBreakHistory.current() == m_resolver.position())
-            m_lineBreakHistory.increment();
-    } else if (!m_current.offset() && !m_width.committedWidth() && m_width.uncommittedWidth() && !m_hadUncommittedWidthBeforeCurrent) {
-        // Do not push the current object to the next line, when this line has some content, but it is still considered empty.
-        // Empty inline elements like <span></span> can produce such lines and now we just ignore these break opportunities
-        // at the start of a line, if no width has been committed yet.
-        // Behave as if it was actually empty and consume at least one object.
-        m_lineBreakHistory.increment();
-    }
-
-    // Sanity check our midpoints.
-    TrailingObjects::CollapseFirstSpaceOrNot collapsed = checkMidpoints(m_lineMidpointState, m_lineBreakHistory.current());
-
-    m_trailingObjects.updateMidpointsForTrailingBoxes(m_lineMidpointState, m_lineBreakHistory.current(), collapsed);
-
-    // We might have made lineBreak an iterator that points past the end
-    // of the object. Do this adjustment to make it point to the start
-    // of the next object instead to avoid confusing the rest of the
-    // code.
-    if (m_lineBreakHistory.offset()) {
-        m_lineBreakHistory.update([](InlineIterator& modifyMe) {
-            modifyMe.setOffset(modifyMe.offset() - 1);
-            modifyMe.increment();
-        });
-    }
-
-#if ENABLE(CSS_TRAILING_WORD)
-    if (m_blockStyle.trailingWord() == TrailingWord::PartiallyBalanced)
-        return optimalLineBreakLocationForTrailingWord();
-#endif
-    return m_lineBreakHistory.current();
-}
-
-#if ENABLE(CSS_TRAILING_WORD)
-inline InlineIterator BreakingContext::optimalLineBreakLocationForTrailingWord()
-{
-    const unsigned longTrailingWordLength = 20;
-    const float optimalTrailingLineRatio = 0.1;
-    InlineIterator lineBreak = m_lineBreakHistory.current();
-    if (!lineBreak.renderer() || !m_lineInfo.isFirstLine() || bidiNextSkippingEmptyInlines(*lineBreak.root(), lineBreak.renderer()) || !is<RenderText>(lineBreak.renderer()))
-        return lineBreak;
-    RenderText& renderText = downcast<RenderText>(*lineBreak.renderer());
-    // Don't even bother measuring if our remaining line has many characters
-    if (renderText.textLength() == lineBreak.offset() || renderText.textLength() - lineBreak.offset() > longTrailingWordLength)
-        return lineBreak;
-    bool isLooseCJKMode = m_renderTextInfo.m_text != &renderText && m_renderTextInfo.m_lineBreakIterator.isLooseCJKMode();
-    bool breakNBSP = m_autoWrap && m_currentStyle->nbspMode() == SPACE;
-    int nextBreakablePosition = lineBreak.nextBreakablePosition();
-    isBreakable(m_renderTextInfo.m_lineBreakIterator, lineBreak.offset() + 1, nextBreakablePosition, breakNBSP, isLooseCJKMode);
-    if (nextBreakablePosition < 0 || static_cast<unsigned>(nextBreakablePosition) != renderText.textLength())
-        return lineBreak;
-    const RenderStyle& style = lineStyle(renderText, m_lineInfo);
-    const FontCascade& font = style.fontCascade();
-    HashSet<const Font*> dummyFonts;
-    InlineIterator best = lineBreak;
-    for (size_t i = 1; i < m_lineBreakHistory.historyLength(); ++i) {
-        const InlineIterator& candidate = m_lineBreakHistory.get(i);
-        if (candidate.renderer() != lineBreak.renderer())
-            return best;
-        float width = textWidth(renderText, candidate.offset(), renderText.textLength() - candidate.offset(), font, 0, font.isFixedPitch(), m_collapseWhiteSpace, dummyFonts);
-        if (width > m_width.availableWidth())
-            return best;
-        if (width / m_width.availableWidth() > optimalTrailingLineRatio) // Subsequent line is long enough
-            return candidate;
-        best = candidate;
-    }
-    return best;
-}
-#endif
-
-}
-
-#endif // BreakingContextInlineHeaders_h

Modified: trunk/Source/WebCore/rendering/line/LineBreaker.cpp (181170 => 181171)


--- trunk/Source/WebCore/rendering/line/LineBreaker.cpp	2015-03-06 18:47:28 UTC (rev 181170)
+++ trunk/Source/WebCore/rendering/line/LineBreaker.cpp	2015-03-06 19:06:30 UTC (rev 181171)
@@ -25,7 +25,7 @@
 #include "config.h"
 #include "LineBreaker.h"
 
-#include "BreakingContextInlineHeaders.h"
+#include "BreakingContext.h"
 #include "RenderCombineText.h"
 
 namespace WebCore {
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to