Move path implementation functions in LineLayoutTraversal to *Path classes
https://bugs.webkit.org/show_bug.cgi?id=204714

Reviewed by Sam Weinig.

Simplify LineLayoutTraversal and make it easier to extend.

- Turn SimplePath and ComplexPath structs into classes
- Move them to separate files
- Make path implementation functions class members, called via generic lambdas
- Instead of inheriting Box/TextBox to iterators, make it a member variable.
- Move the path variant to Box, avoiding use of templates.

* WebCore.xcodeproj/project.pbxproj:
* rendering/RenderTreeAsText.cpp:
(WebCore::writeTextBox):
* rendering/line/LineLayoutTraversal.cpp:
(WebCore::LineLayoutTraversal::TextBoxIterator::TextBoxIterator):
(WebCore::LineLayoutTraversal::TextBoxIterator::traverseNextInVisualOrder):
(WebCore::LineLayoutTraversal::TextBoxIterator::traverseNextInTextOrder):
(WebCore::LineLayoutTraversal::TextBoxIterator::operator== const):
(WebCore::LineLayoutTraversal::TextBoxIterator::atEnd const):
(WebCore::LineLayoutTraversal::ElementBoxIterator::ElementBoxIterator):
(WebCore::LineLayoutTraversal::ElementBoxIterator::atEnd const):
(WebCore::LineLayoutTraversal::TextBoxIterator::ComplexPath::nextInlineTextBoxInTextOrder const): Deleted.
* rendering/line/LineLayoutTraversal.h:
(WebCore::LineLayoutTraversal::TextBoxIterator::TextBoxIterator):
(WebCore::LineLayoutTraversal::TextBoxIterator::operator* const):
(WebCore::LineLayoutTraversal::TextBoxIterator::operator-> const):
(WebCore::LineLayoutTraversal::ElementBoxIterator::ElementBoxIterator):
(WebCore::LineLayoutTraversal::ElementBoxIterator::operator* const):
(WebCore::LineLayoutTraversal::ElementBoxIterator::operator-> const):
(WebCore::LineLayoutTraversal::Box::Box):
(WebCore::LineLayoutTraversal::Box::rect const):
(WebCore::LineLayoutTraversal::Box::logicalRect const):
(WebCore::LineLayoutTraversal::Box::isLeftToRightDirection const):
(WebCore::LineLayoutTraversal::Box::dirOverride const):
(WebCore::LineLayoutTraversal::Box::isLineBreak const):
(WebCore::LineLayoutTraversal::TextBox::hasHyphen const):
(WebCore::LineLayoutTraversal::TextBox::TextBox):
(WebCore::LineLayoutTraversal::TextBox::text const):
(WebCore::LineLayoutTraversal::TextBox::localStartOffset const):
(WebCore::LineLayoutTraversal::TextBox::localEndOffset const):
(WebCore::LineLayoutTraversal::TextBox::length const):
(WebCore::LineLayoutTraversal::TextBox::isLastOnLine const):
(WebCore::LineLayoutTraversal::TextBox::isLast const):
(): Deleted.
(WebCore::LineLayoutTraversal::Box<Iterator>::rect const): Deleted.
(WebCore::LineLayoutTraversal::Box<Iterator>::logicalRect const): Deleted.
(WebCore::LineLayoutTraversal::Box<Iterator>::isLeftToRightDirection const): Deleted.
(WebCore::LineLayoutTraversal::Box<Iterator>::dirOverride const): Deleted.
(WebCore::LineLayoutTraversal::Box<Iterator>::isLineBreak const): Deleted.
(WebCore::LineLayoutTraversal::Box<Iterator>::iterator const): Deleted.
(WebCore::LineLayoutTraversal::TextBox<Iterator>::hasHyphen const): Deleted.
(WebCore::LineLayoutTraversal::TextBox<Iterator>::text const): Deleted.
(WebCore::LineLayoutTraversal::TextBox<Iterator>::localStartOffset const): Deleted.
(WebCore::LineLayoutTraversal::TextBox<Iterator>::localEndOffset const): Deleted.
(WebCore::LineLayoutTraversal::TextBox<Iterator>::length const): Deleted.
(WebCore::LineLayoutTraversal::TextBox<Iterator>::isLastOnLine const): Deleted.
(WebCore::LineLayoutTraversal::TextBox<Iterator>::isLast const): Deleted.
* rendering/line/LineLayoutTraversalComplexPath.h: Added.
(WebCore::LineLayoutTraversal::ComplexPath::ComplexPath):
(WebCore::LineLayoutTraversal::ComplexPath::rect const):
(WebCore::LineLayoutTraversal::ComplexPath::logicalRect const):
(WebCore::LineLayoutTraversal::ComplexPath::isLeftToRightDirection const):
(WebCore::LineLayoutTraversal::ComplexPath::dirOverride const):
(WebCore::LineLayoutTraversal::ComplexPath::isLineBreak const):
(WebCore::LineLayoutTraversal::ComplexPath::hasHyphen const):
(WebCore::LineLayoutTraversal::ComplexPath::text const):
(WebCore::LineLayoutTraversal::ComplexPath::localStartOffset const):
(WebCore::LineLayoutTraversal::ComplexPath::localEndOffset const):
(WebCore::LineLayoutTraversal::ComplexPath::length const):
(WebCore::LineLayoutTraversal::ComplexPath::isLastOnLine const):
(WebCore::LineLayoutTraversal::ComplexPath::isLast const):
(WebCore::LineLayoutTraversal::ComplexPath::traverseNextTextBoxInVisualOrder):
(WebCore::LineLayoutTraversal::ComplexPath::traverseNextTextBoxInTextOrder):
(WebCore::LineLayoutTraversal::ComplexPath::operator== const):
(WebCore::LineLayoutTraversal::ComplexPath::atEnd const):
(WebCore::LineLayoutTraversal::ComplexPath::inlineTextBox const):
(WebCore::LineLayoutTraversal::ComplexPath::nextInlineTextBoxInTextOrder const):
* rendering/line/LineLayoutTraversalSimplePath.h: Added.
(WebCore::LineLayoutTraversal::SimplePath::SimplePath):
(WebCore::LineLayoutTraversal::SimplePath::rect const):
(WebCore::LineLayoutTraversal::SimplePath::logicalRect const):
(WebCore::LineLayoutTraversal::SimplePath::isLeftToRightDirection const):
(WebCore::LineLayoutTraversal::SimplePath::dirOverride const):
(WebCore::LineLayoutTraversal::SimplePath::isLineBreak const):
(WebCore::LineLayoutTraversal::SimplePath::hasHyphen const):
(WebCore::LineLayoutTraversal::SimplePath::text const):
(WebCore::LineLayoutTraversal::SimplePath::localStartOffset const):
(WebCore::LineLayoutTraversal::SimplePath::localEndOffset const):
(WebCore::LineLayoutTraversal::SimplePath::length const):
(WebCore::LineLayoutTraversal::SimplePath::isLastOnLine const):
(WebCore::LineLayoutTraversal::SimplePath::isLast const):
(WebCore::LineLayoutTraversal::SimplePath::traverseNextTextBoxInVisualOrder):
(WebCore::LineLayoutTraversal::SimplePath::traverseNextTextBoxInTextOrder):
(WebCore::LineLayoutTraversal::SimplePath::operator== const):
(WebCore::LineLayoutTraversal::SimplePath::atEnd const):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@252959 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 3156ac2..407960d 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,104 @@
+2019-11-30  Antti Koivisto  <antti@apple.com>
+
+        Move path implementation functions in LineLayoutTraversal to *Path classes
+        https://bugs.webkit.org/show_bug.cgi?id=204714
+
+        Reviewed by Sam Weinig.
+
+        Simplify LineLayoutTraversal and make it easier to extend.
+
+        - Turn SimplePath and ComplexPath structs into classes
+        - Move them to separate files
+        - Make path implementation functions class members, called via generic lambdas
+        - Instead of inheriting Box/TextBox to iterators, make it a member variable.
+        - Move the path variant to Box, avoiding use of templates.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * rendering/RenderTreeAsText.cpp:
+        (WebCore::writeTextBox):
+        * rendering/line/LineLayoutTraversal.cpp:
+        (WebCore::LineLayoutTraversal::TextBoxIterator::TextBoxIterator):
+        (WebCore::LineLayoutTraversal::TextBoxIterator::traverseNextInVisualOrder):
+        (WebCore::LineLayoutTraversal::TextBoxIterator::traverseNextInTextOrder):
+        (WebCore::LineLayoutTraversal::TextBoxIterator::operator== const):
+        (WebCore::LineLayoutTraversal::TextBoxIterator::atEnd const):
+        (WebCore::LineLayoutTraversal::ElementBoxIterator::ElementBoxIterator):
+        (WebCore::LineLayoutTraversal::ElementBoxIterator::atEnd const):
+        (WebCore::LineLayoutTraversal::TextBoxIterator::ComplexPath::nextInlineTextBoxInTextOrder const): Deleted.
+        * rendering/line/LineLayoutTraversal.h:
+        (WebCore::LineLayoutTraversal::TextBoxIterator::TextBoxIterator):
+        (WebCore::LineLayoutTraversal::TextBoxIterator::operator* const):
+        (WebCore::LineLayoutTraversal::TextBoxIterator::operator-> const):
+        (WebCore::LineLayoutTraversal::ElementBoxIterator::ElementBoxIterator):
+        (WebCore::LineLayoutTraversal::ElementBoxIterator::operator* const):
+        (WebCore::LineLayoutTraversal::ElementBoxIterator::operator-> const):
+        (WebCore::LineLayoutTraversal::Box::Box):
+        (WebCore::LineLayoutTraversal::Box::rect const):
+        (WebCore::LineLayoutTraversal::Box::logicalRect const):
+        (WebCore::LineLayoutTraversal::Box::isLeftToRightDirection const):
+        (WebCore::LineLayoutTraversal::Box::dirOverride const):
+        (WebCore::LineLayoutTraversal::Box::isLineBreak const):
+        (WebCore::LineLayoutTraversal::TextBox::hasHyphen const):
+        (WebCore::LineLayoutTraversal::TextBox::TextBox):
+        (WebCore::LineLayoutTraversal::TextBox::text const):
+        (WebCore::LineLayoutTraversal::TextBox::localStartOffset const):
+        (WebCore::LineLayoutTraversal::TextBox::localEndOffset const):
+        (WebCore::LineLayoutTraversal::TextBox::length const):
+        (WebCore::LineLayoutTraversal::TextBox::isLastOnLine const):
+        (WebCore::LineLayoutTraversal::TextBox::isLast const):
+        (): Deleted.
+        (WebCore::LineLayoutTraversal::Box<Iterator>::rect const): Deleted.
+        (WebCore::LineLayoutTraversal::Box<Iterator>::logicalRect const): Deleted.
+        (WebCore::LineLayoutTraversal::Box<Iterator>::isLeftToRightDirection const): Deleted.
+        (WebCore::LineLayoutTraversal::Box<Iterator>::dirOverride const): Deleted.
+        (WebCore::LineLayoutTraversal::Box<Iterator>::isLineBreak const): Deleted.
+        (WebCore::LineLayoutTraversal::Box<Iterator>::iterator const): Deleted.
+        (WebCore::LineLayoutTraversal::TextBox<Iterator>::hasHyphen const): Deleted.
+        (WebCore::LineLayoutTraversal::TextBox<Iterator>::text const): Deleted.
+        (WebCore::LineLayoutTraversal::TextBox<Iterator>::localStartOffset const): Deleted.
+        (WebCore::LineLayoutTraversal::TextBox<Iterator>::localEndOffset const): Deleted.
+        (WebCore::LineLayoutTraversal::TextBox<Iterator>::length const): Deleted.
+        (WebCore::LineLayoutTraversal::TextBox<Iterator>::isLastOnLine const): Deleted.
+        (WebCore::LineLayoutTraversal::TextBox<Iterator>::isLast const): Deleted.
+        * rendering/line/LineLayoutTraversalComplexPath.h: Added.
+        (WebCore::LineLayoutTraversal::ComplexPath::ComplexPath):
+        (WebCore::LineLayoutTraversal::ComplexPath::rect const):
+        (WebCore::LineLayoutTraversal::ComplexPath::logicalRect const):
+        (WebCore::LineLayoutTraversal::ComplexPath::isLeftToRightDirection const):
+        (WebCore::LineLayoutTraversal::ComplexPath::dirOverride const):
+        (WebCore::LineLayoutTraversal::ComplexPath::isLineBreak const):
+        (WebCore::LineLayoutTraversal::ComplexPath::hasHyphen const):
+        (WebCore::LineLayoutTraversal::ComplexPath::text const):
+        (WebCore::LineLayoutTraversal::ComplexPath::localStartOffset const):
+        (WebCore::LineLayoutTraversal::ComplexPath::localEndOffset const):
+        (WebCore::LineLayoutTraversal::ComplexPath::length const):
+        (WebCore::LineLayoutTraversal::ComplexPath::isLastOnLine const):
+        (WebCore::LineLayoutTraversal::ComplexPath::isLast const):
+        (WebCore::LineLayoutTraversal::ComplexPath::traverseNextTextBoxInVisualOrder):
+        (WebCore::LineLayoutTraversal::ComplexPath::traverseNextTextBoxInTextOrder):
+        (WebCore::LineLayoutTraversal::ComplexPath::operator== const):
+        (WebCore::LineLayoutTraversal::ComplexPath::atEnd const):
+        (WebCore::LineLayoutTraversal::ComplexPath::inlineTextBox const):
+        (WebCore::LineLayoutTraversal::ComplexPath::nextInlineTextBoxInTextOrder const):
+        * rendering/line/LineLayoutTraversalSimplePath.h: Added.
+        (WebCore::LineLayoutTraversal::SimplePath::SimplePath):
+        (WebCore::LineLayoutTraversal::SimplePath::rect const):
+        (WebCore::LineLayoutTraversal::SimplePath::logicalRect const):
+        (WebCore::LineLayoutTraversal::SimplePath::isLeftToRightDirection const):
+        (WebCore::LineLayoutTraversal::SimplePath::dirOverride const):
+        (WebCore::LineLayoutTraversal::SimplePath::isLineBreak const):
+        (WebCore::LineLayoutTraversal::SimplePath::hasHyphen const):
+        (WebCore::LineLayoutTraversal::SimplePath::text const):
+        (WebCore::LineLayoutTraversal::SimplePath::localStartOffset const):
+        (WebCore::LineLayoutTraversal::SimplePath::localEndOffset const):
+        (WebCore::LineLayoutTraversal::SimplePath::length const):
+        (WebCore::LineLayoutTraversal::SimplePath::isLastOnLine const):
+        (WebCore::LineLayoutTraversal::SimplePath::isLast const):
+        (WebCore::LineLayoutTraversal::SimplePath::traverseNextTextBoxInVisualOrder):
+        (WebCore::LineLayoutTraversal::SimplePath::traverseNextTextBoxInTextOrder):
+        (WebCore::LineLayoutTraversal::SimplePath::operator== const):
+        (WebCore::LineLayoutTraversal::SimplePath::atEnd const):
+
 2019-11-30  Zalan Bujtas  <zalan@apple.com>
 
         [LFC][IFC] Add support for hyphenate-limit-lines
diff --git a/Source/WebCore/Headers.cmake b/Source/WebCore/Headers.cmake
index efc275f..6744c8e 100644
--- a/Source/WebCore/Headers.cmake
+++ b/Source/WebCore/Headers.cmake
@@ -1320,6 +1320,8 @@
     rendering/SimpleLineLayoutResolver.h
 
     rendering/line/LineLayoutTraversal.h
+    rendering/line/LineLayoutTraversalComplexPath.h
+    rendering/line/LineLayoutTraversalSimplePath.h
     rendering/line/LineWidth.h
     rendering/line/TrailingObjects.h
 
diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
index 1a6f188..982432a 100644
--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -4794,6 +4794,8 @@
 		E4295FA412B0614E00D1ACE0 /* ResourceLoadPriority.h in Headers */ = {isa = PBXBuildFile; fileRef = E4295FA312B0614E00D1ACE0 /* ResourceLoadPriority.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E42E76DC1C7AF77600E3614D /* StyleUpdate.h in Headers */ = {isa = PBXBuildFile; fileRef = E42E76DB1C7AF77600E3614D /* StyleUpdate.h */; };
 		E43105BB16750F1600DB2FB8 /* NodeTraversal.h in Headers */ = {isa = PBXBuildFile; fileRef = E43105BA16750F1600DB2FB8 /* NodeTraversal.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		E4343D232392778400EBBB66 /* LineLayoutTraversalSimplePath.h in Headers */ = {isa = PBXBuildFile; fileRef = E4343D212392778300EBBB66 /* LineLayoutTraversalSimplePath.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		E4343D252392779000EBBB66 /* LineLayoutTraversalComplexPath.h in Headers */ = {isa = PBXBuildFile; fileRef = E4343D242392778F00EBBB66 /* LineLayoutTraversalComplexPath.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E43A023B17EB370A004CDD25 /* RenderElement.h in Headers */ = {isa = PBXBuildFile; fileRef = E43A023A17EB370A004CDD25 /* RenderElement.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E43AF8E71AC5B7EC00CA717E /* CacheValidation.h in Headers */ = {isa = PBXBuildFile; fileRef = E43AF8E51AC5B7DD00CA717E /* CacheValidation.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E440AA961C68420800A265CC /* ElementAndTextDescendantIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E440AA951C68420800A265CC /* ElementAndTextDescendantIterator.h */; };
@@ -15107,6 +15109,8 @@
 		E42E76DB1C7AF77600E3614D /* StyleUpdate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleUpdate.h; sourceTree = "<group>"; };
 		E43105B716750F0C00DB2FB8 /* NodeTraversal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NodeTraversal.cpp; sourceTree = "<group>"; };
 		E43105BA16750F1600DB2FB8 /* NodeTraversal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeTraversal.h; sourceTree = "<group>"; };
+		E4343D212392778300EBBB66 /* LineLayoutTraversalSimplePath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LineLayoutTraversalSimplePath.h; sourceTree = "<group>"; };
+		E4343D242392778F00EBBB66 /* LineLayoutTraversalComplexPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LineLayoutTraversalComplexPath.h; sourceTree = "<group>"; };
 		E43A023A17EB370A004CDD25 /* RenderElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderElement.h; sourceTree = "<group>"; };
 		E43A023C17EB3713004CDD25 /* RenderElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderElement.cpp; sourceTree = "<group>"; };
 		E43AF8E41AC5B7DD00CA717E /* CacheValidation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CacheValidation.cpp; sourceTree = "<group>"; };
@@ -28725,6 +28729,8 @@
 				FFEFAB2918380DA000514534 /* LineLayoutState.h */,
 				E484A33D23055303009ADE6A /* LineLayoutTraversal.cpp */,
 				E484A33B23055303009ADE6A /* LineLayoutTraversal.h */,
+				E4343D212392778300EBBB66 /* LineLayoutTraversalSimplePath.h */,
+				E4343D242392778F00EBBB66 /* LineLayoutTraversalComplexPath.h */,
 				FFDBC046183D27B700407109 /* LineWidth.cpp */,
 				FFDBC045183D27B700407109 /* LineWidth.h */,
 				FFAC30FD184FB145008C4F1E /* TrailingObjects.cpp */,
@@ -30535,6 +30541,7 @@
 				837056901F50915C00D93425 /* JSFileSystemEntryCallback.h in Headers */,
 				833B9E361F508D8500E0E428 /* JSFileSystemFileEntry.h in Headers */,
 				712BE4881FE8686A002031CC /* JSFillMode.h in Headers */,
+				E4343D252392779000EBBB66 /* LineLayoutTraversalComplexPath.h in Headers */,
 				B6D9D27B14EAC0860090D75E /* JSFocusEvent.h in Headers */,
 				C280833F1C6DC26F001451B6 /* JSFontFace.h in Headers */,
 				1C24EEA91C72A7B40080F8FC /* JSFontFaceSet.h in Headers */,
@@ -31682,6 +31689,7 @@
 				57DCED74214305F00016B847 /* PublicKeyCredentialData.h in Headers */,
 				57303BEF200980C600355965 /* PublicKeyCredentialDescriptor.h in Headers */,
 				57303C0A20099BAD00355965 /* PublicKeyCredentialRequestOptions.h in Headers */,
+				E4343D232392778400EBBB66 /* LineLayoutTraversalSimplePath.h in Headers */,
 				57303BEB20097F4000355965 /* PublicKeyCredentialType.h in Headers */,
 				0081FF0016B0A2D3008AAA7A /* PublicSuffix.h in Headers */,
 				10FB084B14E15C7E00A3DB98 /* PublicURLManager.h in Headers */,
diff --git a/Source/WebCore/rendering/RenderTreeAsText.cpp b/Source/WebCore/rendering/RenderTreeAsText.cpp
index 2135a52..313e3e5 100644
--- a/Source/WebCore/rendering/RenderTreeAsText.cpp
+++ b/Source/WebCore/rendering/RenderTreeAsText.cpp
@@ -477,7 +477,7 @@
     }
 }
 
-static void writeTextBox(TextStream& ts, const RenderText& o, const LineLayoutTraversal::TextBoxIterator::BoxType& textBox)
+static void writeTextBox(TextStream& ts, const RenderText& o, const LineLayoutTraversal::TextBox& textBox)
 {
     auto rect = textBox.rect();
     auto logicalRect = textBox.logicalRect();
diff --git a/Source/WebCore/rendering/line/LineLayoutTraversal.cpp b/Source/WebCore/rendering/line/LineLayoutTraversal.cpp
index 90e9e04..765b978 100644
--- a/Source/WebCore/rendering/line/LineLayoutTraversal.cpp
+++ b/Source/WebCore/rendering/line/LineLayoutTraversal.cpp
@@ -32,88 +32,50 @@
 namespace LineLayoutTraversal {
 
 TextBoxIterator::TextBoxIterator(const InlineTextBox* inlineTextBox)
-    : m_pathVariant(ComplexPath { inlineTextBox, { } })
+    : m_textBox(ComplexPath { inlineTextBox, { } })
 {
 }
 TextBoxIterator::TextBoxIterator(Vector<const InlineTextBox*>&& sorted, size_t index)
-    : m_pathVariant(ComplexPath { index < sorted.size() ? sorted[index] : nullptr, WTFMove(sorted), index })
+    : m_textBox(ComplexPath { index < sorted.size() ? sorted[index] : nullptr, WTFMove(sorted), index })
 {
 }
 
 TextBoxIterator::TextBoxIterator(SimpleLineLayout::RunResolver::Iterator iterator, SimpleLineLayout::RunResolver::Iterator end)
-    : m_pathVariant(SimplePath { iterator, end })
+    : m_textBox(SimplePath { iterator, end })
 {
 }
 
 TextBoxIterator& TextBoxIterator::traverseNextInVisualOrder()
 {
-    auto simple = [](SimplePath& path) {
-        ++path.iterator;
-    };
-
-    auto complex = [](ComplexPath& path) {
-        path.inlineBox = path.inlineBox->nextTextBox();
-    };
-
-    WTF::switchOn(m_pathVariant, simple, complex);
-
+    WTF::switchOn(m_textBox.m_pathVariant, [](auto& path) {
+        path.traverseNextTextBoxInVisualOrder();
+    });
     return *this;
 }
 
-const InlineTextBox* TextBoxIterator::ComplexPath::nextInlineTextBoxInTextOrder() const
-{
-    if (!sortedInlineTextBoxes.isEmpty()) {
-        if (sortedInlineTextBoxIndex + 1 < sortedInlineTextBoxes.size())
-            return sortedInlineTextBoxes[sortedInlineTextBoxIndex + 1];
-        return nullptr;
-    }
-    return inlineBox->nextTextBox();
-}
-
 TextBoxIterator& TextBoxIterator::traverseNextInTextOrder()
 {
-    auto simple = [](SimplePath& path) {
-        ++path.iterator;
-    };
-
-    auto complex = [](ComplexPath& path) {
-        path.inlineBox = path.nextInlineTextBoxInTextOrder();
-        if (!path.sortedInlineTextBoxes.isEmpty())
-            ++path.sortedInlineTextBoxIndex;
-    };
-
-    WTF::switchOn(m_pathVariant, simple, complex);
-
+    WTF::switchOn(m_textBox.m_pathVariant, [](auto& path) {
+        path.traverseNextTextBoxInTextOrder();
+    });
     return *this;
 }
 
 bool TextBoxIterator::operator==(const TextBoxIterator& other) const
 {
-    if (m_pathVariant.index() != other.m_pathVariant.index())
+    if (m_textBox.m_pathVariant.index() != other.m_textBox.m_pathVariant.index())
         return false;
 
-    auto simple = [&](const SimplePath& path) {
-        return path.iterator == WTF::get<SimplePath>(other.m_pathVariant).iterator;
-    };
-
-    auto complex = [&](const ComplexPath& path) {
-        return path.inlineBox == WTF::get<ComplexPath>(other.m_pathVariant).inlineBox;
-    };
-
-    return WTF::switchOn(m_pathVariant, simple, complex);
+    return WTF::switchOn(m_textBox.m_pathVariant, [&](const auto& path) {
+        return path == WTF::get<std::decay_t<decltype(path)>>(other.m_textBox.m_pathVariant);
+    });
 }
 
 bool TextBoxIterator::atEnd() const
 {
-    auto simple = [&](const SimplePath& path) {
-        return path.iterator == path.end;
-    };
-
-    auto complex = [&](const ComplexPath& path) {
-        return !path.inlineBox;
-    };
-
-    return WTF::switchOn(m_pathVariant, simple, complex);
+    return WTF::switchOn(m_textBox.m_pathVariant, [](auto& path) {
+        return path.atEnd();
+    });
 }
 
 TextBoxIterator firstTextBoxFor(const RenderText& text)
@@ -145,25 +107,19 @@
 }
 
 ElementBoxIterator::ElementBoxIterator(const InlineElementBox* inlineElementBox)
-    : m_pathVariant(ComplexPath { inlineElementBox })
+    : m_box(ComplexPath { inlineElementBox, { } })
 {
 }
 ElementBoxIterator::ElementBoxIterator(SimpleLineLayout::RunResolver::Iterator iterator, SimpleLineLayout::RunResolver::Iterator end)
-    : m_pathVariant(SimplePath { iterator, end })
+    : m_box(SimplePath { iterator, end })
 {
 }
 
 bool ElementBoxIterator::atEnd() const
 {
-    auto simple = [&](const SimplePath& path) {
-        return path.iterator == path.end;
-    };
-
-    auto complex = [&](const ComplexPath& path) {
-        return !path.inlineBox;
-    };
-
-    return WTF::switchOn(m_pathVariant, simple, complex);
+    return WTF::switchOn(m_box.m_pathVariant, [](auto& path) {
+        return path.atEnd();
+    });
 }
 
 ElementBoxIterator elementBoxFor(const RenderLineBreak& renderElement)
diff --git a/Source/WebCore/rendering/line/LineLayoutTraversal.h b/Source/WebCore/rendering/line/LineLayoutTraversal.h
index f401e831..134f420 100644
--- a/Source/WebCore/rendering/line/LineLayoutTraversal.h
+++ b/Source/WebCore/rendering/line/LineLayoutTraversal.h
@@ -25,11 +25,10 @@
 
 #pragma once
 
-#include "FloatRect.h"
 #include "InlineElementBox.h"
-#include "InlineTextBox.h"
+#include "LineLayoutTraversalComplexPath.h"
+#include "LineLayoutTraversalSimplePath.h"
 #include "RenderText.h"
-#include "SimpleLineLayoutResolver.h"
 #include <wtf/HashMap.h>
 #include <wtf/IteratorRange.h>
 #include <wtf/Variant.h>
@@ -38,18 +37,20 @@
 namespace WebCore {
 
 class RenderLineBreak;
-class RenderText;
 
 namespace LineLayoutTraversal {
 
-class TextBoxContext;
+class ElementBoxIterator;
 class TextBoxIterator;
 
 struct EndIterator { };
 
-template<class Iterator>
 class Box {
 public:
+    using PathVariant = Variant<SimplePath, ComplexPath>;
+
+    Box(PathVariant&&);
+
     FloatRect rect() const;
     FloatRect logicalRect() const;
 
@@ -58,19 +59,16 @@
     bool isLineBreak() const;
 
 protected:
-    Box() = default;
-    Box(const Box&) = default;
-    Box(Box&&) = default;
-    ~Box() = default;
-    Box& operator=(const Box&) = default;
-    Box& operator=(Box&&) = default;
+    friend class ElementBoxIterator;
+    friend class TextBoxIterator;
 
-    const Iterator& iterator() const;
+    PathVariant m_pathVariant;
 };
 
-template<class Iterator>
-class TextBox : public Box<Iterator> {
+class TextBox : public Box {
 public:
+    TextBox(PathVariant&&);
+
     bool hasHyphen() const;
     StringView text() const;
 
@@ -81,21 +79,11 @@
 
     bool isLastOnLine() const;
     bool isLast() const;
-
-protected:
-    TextBox() = default;
-    TextBox(const TextBox&) = default;
-    TextBox(TextBox&&) = default;
-    ~TextBox() = default;
-    TextBox& operator=(const TextBox&) = default;
-    TextBox& operator=(TextBox&&) = default;
-
-    using Box<Iterator>::iterator;
 };
 
-class TextBoxIterator : private TextBox<TextBoxIterator> {
+class TextBoxIterator {
 public:
-    TextBoxIterator() : m_pathVariant(ComplexPath { nullptr, { } }) { };
+    TextBoxIterator() : m_textBox(ComplexPath { nullptr, { } }) { };
 
     explicit TextBoxIterator(const InlineTextBox*);
     TextBoxIterator(Vector<const InlineTextBox*>&& sorted, size_t index);
@@ -113,58 +101,31 @@
     bool operator==(EndIterator) const { return atEnd(); }
     bool operator!=(EndIterator) const { return !atEnd(); }
 
-    const TextBox& operator*() const { return *this; }
-    const TextBox* operator->() const { return this; }
+    const TextBox& operator*() const { return m_textBox; }
+    const TextBox* operator->() const { return &m_textBox; }
 
     bool atEnd() const;
 
-    using BoxType = TextBox<TextBoxIterator>;
-
 private:
-    friend class Box<TextBoxIterator>;
-    friend class TextBox<TextBoxIterator>;
-
-    struct SimplePath {
-        SimpleLineLayout::RunResolver::Iterator iterator;
-        SimpleLineLayout::RunResolver::Iterator end;
-    };
-    struct ComplexPath {
-        const InlineTextBox* inlineBox;
-        Vector<const InlineTextBox*> sortedInlineTextBoxes;
-        size_t sortedInlineTextBoxIndex { 0 };
-
-        const InlineTextBox* nextInlineTextBoxInTextOrder() const;
-    };
-    Variant<SimplePath, ComplexPath> m_pathVariant;
+    TextBox m_textBox;
 };
 
-class ElementBoxIterator : private Box<ElementBoxIterator> {
+class ElementBoxIterator {
 public:
-    ElementBoxIterator() : m_pathVariant(ComplexPath { nullptr }) { };
+    ElementBoxIterator() : m_box(ComplexPath { nullptr, { } }) { };
 
     explicit ElementBoxIterator(const InlineElementBox*);
     ElementBoxIterator(SimpleLineLayout::RunResolver::Iterator, SimpleLineLayout::RunResolver::Iterator end);
 
     explicit operator bool() const { return !atEnd(); }
 
-    const Box& operator*() const { return *this; }
-    const Box* operator->() const { return this; }
+    const Box& operator*() const { return m_box; }
+    const Box* operator->() const { return &m_box; }
 
     bool atEnd() const;
 
-    using BoxType = Box<ElementBoxIterator>;
-
 private:
-    friend class Box<ElementBoxIterator>;
-
-    struct SimplePath {
-        SimpleLineLayout::RunResolver::Iterator iterator;
-        SimpleLineLayout::RunResolver::Iterator end;
-    };
-    struct ComplexPath {
-        const InlineElementBox* inlineBox;
-    };
-    Variant<SimplePath, ComplexPath> m_pathVariant;
+    Box m_box;
 };
 
 class TextBoxRange {
@@ -188,170 +149,98 @@
 
 // -----------------------------------------------
 
-template<class Iterator> inline FloatRect Box<Iterator>::rect() const
+inline Box::Box(PathVariant&& path)
+    : m_pathVariant(WTFMove(path))
 {
-    auto simple = [](const typename Iterator::SimplePath& path) {
-        return (*path.iterator).rect();
-    };
-
-    auto complex = [](const typename Iterator::ComplexPath& path) {
-        return path.inlineBox->frameRect();
-    };
-
-    return WTF::switchOn(iterator().m_pathVariant, simple, complex);
 }
 
-template<class Iterator> inline FloatRect Box<Iterator>::logicalRect() const
+inline FloatRect Box::rect() const
 {
-    auto simple = [](const typename Iterator::SimplePath& path) {
-        return (*path.iterator).rect();
-    };
-
-    auto complex = [](const typename Iterator::ComplexPath& path) {
-        return path.inlineBox->logicalFrameRect();
-    };
-
-    return WTF::switchOn(iterator().m_pathVariant, simple, complex);
+    return WTF::switchOn(m_pathVariant, [](auto& path) {
+        return path.rect();
+    });
 }
 
-template<class Iterator> inline bool Box<Iterator>::isLeftToRightDirection() const
+inline FloatRect Box::logicalRect() const
 {
-    auto simple = [](const typename Iterator::SimplePath&) {
-        return true;
-    };
-
-    auto complex = [](const typename Iterator::ComplexPath& path) {
-        return path.inlineBox->isLeftToRightDirection();
-    };
-
-    return WTF::switchOn(iterator().m_pathVariant, simple, complex);
+    return WTF::switchOn(m_pathVariant, [](auto& path) {
+        return path.logicalRect();
+    });
 }
 
-template<class Iterator> inline bool Box<Iterator>::dirOverride() const
+inline bool Box::isLeftToRightDirection() const
 {
-    auto simple = [](const typename Iterator::SimplePath&) {
-        return false;
-    };
-
-    auto complex = [](const typename Iterator::ComplexPath& path) {
-        return path.inlineBox->dirOverride();
-    };
-
-    return WTF::switchOn(iterator().m_pathVariant, simple, complex);
+    return WTF::switchOn(m_pathVariant, [](auto& path) {
+        return path.isLeftToRightDirection();
+    });
 }
 
-template<class Iterator> inline bool Box<Iterator>::isLineBreak() const
+inline bool Box::dirOverride() const
 {
-    auto simple = [](const typename Iterator::SimplePath& path) {
-        return (*path.iterator).isLineBreak();
-    };
-
-    auto complex = [](const typename Iterator::ComplexPath& path) {
-        return path.inlineBox->isLineBreak();
-    };
-
-    return WTF::switchOn(iterator().m_pathVariant, simple, complex);
+    return WTF::switchOn(m_pathVariant, [](auto& path) {
+        return path.dirOverride();
+    });
 }
 
-template<class Iterator> inline const Iterator& Box<Iterator>::iterator() const
+inline bool Box::isLineBreak() const
 {
-    return static_cast<const Iterator&>(*this);
+    return WTF::switchOn(m_pathVariant, [](auto& path) {
+        return path.isLineBreak();
+    });
 }
 
-template<class Iterator> inline bool TextBox<Iterator>::hasHyphen() const
+inline bool TextBox::hasHyphen() const
 {
-    auto simple = [](const typename Iterator::SimplePath& path) {
-        return (*path.iterator).hasHyphen();
-    };
-
-    auto complex = [](const typename Iterator::ComplexPath& path) {
-        return path.inlineBox->hasHyphen();
-    };
-
-    return WTF::switchOn(iterator().m_pathVariant, simple, complex);
+    return WTF::switchOn(m_pathVariant, [](auto& path) {
+        return path.hasHyphen();
+    });
 }
 
-template<class Iterator> inline StringView TextBox<Iterator>::text() const
+inline TextBox::TextBox(PathVariant&& path)
+    : Box(WTFMove(path))
 {
-    auto simple = [](const typename Iterator::SimplePath& path) {
-        return (*path.iterator).text();
-    };
-
-    auto complex = [](const typename Iterator::ComplexPath& path) {
-        return StringView(path.inlineBox->renderer().text()).substring(path.inlineBox->start(), path.inlineBox->len());
-    };
-
-    return WTF::switchOn(iterator().m_pathVariant, simple, complex);
 }
 
-template<class Iterator> inline unsigned TextBox<Iterator>::localStartOffset() const
+inline StringView TextBox::text() const
 {
-    auto simple = [](const typename Iterator::SimplePath& path) {
-        return (*path.iterator).localStart();
-    };
-
-    auto complex = [](const typename Iterator::ComplexPath& path) {
-        return path.inlineBox->start();
-    };
-
-    return WTF::switchOn(iterator().m_pathVariant, simple, complex);
+    return WTF::switchOn(m_pathVariant, [](auto& path) {
+        return path.text();
+    });
 }
 
-template<class Iterator> inline unsigned TextBox<Iterator>::localEndOffset() const
+inline unsigned TextBox::localStartOffset() const
 {
-    auto simple = [](const typename Iterator::SimplePath& path) {
-        return (*path.iterator).localEnd();
-    };
-
-    auto complex = [](const typename Iterator::ComplexPath& path) {
-        return path.inlineBox->end();
-    };
-
-    return WTF::switchOn(iterator().m_pathVariant, simple, complex);
+    return WTF::switchOn(m_pathVariant, [](auto& path) {
+        return path.localStartOffset();
+    });
 }
 
-template<class Iterator> inline unsigned TextBox<Iterator>::length() const
+inline unsigned TextBox::localEndOffset() const
 {
-    auto simple = [](const typename Iterator::SimplePath& path) {
-        return (*path.iterator).end() - (*path.iterator).start();
-    };
-
-    auto complex = [](const typename Iterator::ComplexPath& path) {
-        return path.inlineBox->len();
-    };
-
-    return WTF::switchOn(iterator().m_pathVariant, simple, complex);
+    return WTF::switchOn(m_pathVariant, [](auto& path) {
+        return path.localEndOffset();
+    });
 }
 
-template<class Iterator> inline bool TextBox<Iterator>::isLastOnLine() const
+inline unsigned TextBox::length() const
 {
-    auto simple = [](const typename Iterator::SimplePath& path) {
-        auto next = path.iterator;
-        ++next;
-        return next == path.end || (*path.iterator).lineIndex() != (*next).lineIndex();
-    };
-
-    auto complex = [](const typename Iterator::ComplexPath& path) {
-        auto* next = path.nextInlineTextBoxInTextOrder();
-        return !next || &path.inlineBox->root() != &next->root();
-    };
-
-    return WTF::switchOn(iterator().m_pathVariant, simple, complex);
+    return WTF::switchOn(m_pathVariant, [](auto& path) {
+        return path.length();
+    });
 }
 
-template<class Iterator> inline bool TextBox<Iterator>::isLast() const
+inline bool TextBox::isLastOnLine() const
 {
-    auto simple = [](const typename Iterator::SimplePath& path) {
-        auto next = path.iterator;
-        ++next;
-        return next == path.end;
-    };
+    return WTF::switchOn(m_pathVariant, [](auto& path) {
+        return path.isLastOnLine();
+    });
+}
 
-    auto complex = [](const typename Iterator::ComplexPath& path) {
-        return !path.nextInlineTextBoxInTextOrder();
-    };
-
-    return WTF::switchOn(iterator().m_pathVariant, simple, complex);
+inline bool TextBox::isLast() const
+{
+    return WTF::switchOn(m_pathVariant, [](auto& path) {
+        return path.isLast();
+    });
 }
 
 }
diff --git a/Source/WebCore/rendering/line/LineLayoutTraversalComplexPath.h b/Source/WebCore/rendering/line/LineLayoutTraversalComplexPath.h
new file mode 100644
index 0000000..3643288
--- /dev/null
+++ b/Source/WebCore/rendering/line/LineLayoutTraversalComplexPath.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "InlineTextBox.h"
+#include "RenderText.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+namespace LineLayoutTraversal {
+
+class ComplexPath {
+public:
+    ComplexPath(const InlineBox* inlineBox, Vector<const InlineTextBox*>&& sortedInlineTextBoxes = { }, size_t sortedInlineTextBoxIndex = 0)
+        : m_inlineBox(inlineBox)
+        , m_sortedInlineTextBoxes(WTFMove(sortedInlineTextBoxes))
+        , m_sortedInlineTextBoxIndex(sortedInlineTextBoxIndex)
+    { }
+
+    FloatRect rect() const { return m_inlineBox->frameRect(); }
+    FloatRect logicalRect() const { return m_inlineBox->logicalFrameRect(); }
+
+    bool isLeftToRightDirection() const { return m_inlineBox->isLeftToRightDirection(); }
+    bool dirOverride() const { return m_inlineBox->dirOverride(); }
+    bool isLineBreak() const { return m_inlineBox->isLineBreak(); }
+
+    bool hasHyphen() const { return inlineTextBox()->hasHyphen(); }
+    StringView text() const { return StringView(inlineTextBox()->renderer().text()).substring(inlineTextBox()->start(), inlineTextBox()->len()); }
+    unsigned localStartOffset() const { return inlineTextBox()->start(); }
+    unsigned localEndOffset() const { return inlineTextBox()->end(); }
+    unsigned length() const { return inlineTextBox()->len(); }
+
+    inline bool isLastOnLine() const
+    {
+        auto* next = nextInlineTextBoxInTextOrder();
+        return !next || &inlineTextBox()->root() != &next->root();
+    }
+    inline bool isLast() const { return !nextInlineTextBoxInTextOrder(); };
+
+    void traverseNextTextBoxInVisualOrder() { m_inlineBox = inlineTextBox()->nextTextBox(); }
+    void traverseNextTextBoxInTextOrder()
+    {
+        m_inlineBox = nextInlineTextBoxInTextOrder();
+        if (!m_sortedInlineTextBoxes.isEmpty())
+            ++m_sortedInlineTextBoxIndex;
+    }
+
+    bool operator==(const ComplexPath& other) const { return m_inlineBox == other.m_inlineBox; }
+    bool atEnd() const { return !m_inlineBox; }
+
+private:
+    const InlineTextBox* inlineTextBox() const { return downcast<InlineTextBox>(m_inlineBox); }
+    const InlineTextBox* nextInlineTextBoxInTextOrder() const;
+
+    const InlineBox* m_inlineBox;
+    Vector<const InlineTextBox*> m_sortedInlineTextBoxes;
+    size_t m_sortedInlineTextBoxIndex { 0 };
+};
+
+inline const InlineTextBox* ComplexPath::nextInlineTextBoxInTextOrder() const
+{
+    if (!m_sortedInlineTextBoxes.isEmpty()) {
+        if (m_sortedInlineTextBoxIndex + 1 < m_sortedInlineTextBoxes.size())
+            return m_sortedInlineTextBoxes[m_sortedInlineTextBoxIndex + 1];
+        return nullptr;
+    }
+    return inlineTextBox()->nextTextBox();
+}
+
+}
+}
diff --git a/Source/WebCore/rendering/line/LineLayoutTraversalSimplePath.h b/Source/WebCore/rendering/line/LineLayoutTraversalSimplePath.h
new file mode 100644
index 0000000..f16d721
--- /dev/null
+++ b/Source/WebCore/rendering/line/LineLayoutTraversalSimplePath.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "LineLayoutTraversal.h"
+#include "SimpleLineLayoutResolver.h"
+
+namespace WebCore {
+namespace LineLayoutTraversal {
+
+class SimplePath {
+public:
+    SimplePath(SimpleLineLayout::RunResolver::Iterator iterator, SimpleLineLayout::RunResolver::Iterator end)
+        : m_iterator(iterator)
+        , m_end(end)
+    { }
+
+    FloatRect rect() const { return (*m_iterator).rect(); }
+    FloatRect logicalRect() const { return rect(); }
+
+    bool isLeftToRightDirection() const { return true; }
+    bool dirOverride() const { return false; }
+    bool isLineBreak() const { return (*m_iterator).isLineBreak(); }
+
+    bool hasHyphen() const { return (*m_iterator).hasHyphen(); }
+    StringView text() const { return (*m_iterator).text(); }
+    unsigned localStartOffset() const { return (*m_iterator).localStart(); }
+    unsigned localEndOffset() const { return (*m_iterator).localEnd(); }
+    unsigned length() const { return (*m_iterator).end() - (*m_iterator).start(); }
+
+    bool isLastOnLine() const
+    {
+        auto next = m_iterator;
+        ++next;
+        return next == m_end || (*m_iterator).lineIndex() != (*next).lineIndex();
+    }
+    bool isLast() const
+    {
+        auto next = m_iterator;
+        ++next;
+        return next == m_end;
+    };
+
+    void traverseNextTextBoxInVisualOrder()
+    {
+        // This function is currently only used for consecutive text runs.
+        ++m_iterator;
+    }
+    void traverseNextTextBoxInTextOrder() {  traverseNextTextBoxInVisualOrder(); }
+
+    bool operator==(const SimplePath& other) const { return m_iterator == other.m_iterator; }
+    bool atEnd() const { return m_iterator == m_end; }
+
+private:
+    SimpleLineLayout::RunResolver::Iterator m_iterator;
+    SimpleLineLayout::RunResolver::Iterator m_end;
+};
+
+}
+}