Diff
Modified: trunk/Source/WebCore/ChangeLog (249083 => 249084)
--- trunk/Source/WebCore/ChangeLog 2019-08-24 13:24:29 UTC (rev 249083)
+++ trunk/Source/WebCore/ChangeLog 2019-08-24 13:31:50 UTC (rev 249084)
@@ -1,3 +1,44 @@
+2019-08-24 Antti Koivisto <[email protected]>
+
+ Implement layout system independent text box iterator
+ https://bugs.webkit.org/show_bug.cgi?id=201076
+
+ Reviewed by Zalan Bujtas.
+
+ Add a generic way to traverse line layout without caring about the details of the underlying layout system.
+
+ This patch adds basic support for traversing text boxes and uses it to remove layout path specific branches in RenderTreeAsText.
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * rendering/RenderTreeAsText.cpp:
+ (WebCore::RenderTreeAsText::writeRenderObject):
+ (WebCore::writeTextBox):
+ (WebCore::write):
+ (WebCore::writeTextRun): Deleted.
+ (WebCore::writeSimpleLine): Deleted.
+ * rendering/line/LineLayoutInterfaceTextBoxes.cpp: Added.
+ (WebCore::LineLayoutInterface::TextBox::rect const):
+ (WebCore::LineLayoutInterface::TextBox::logicalRect const):
+ (WebCore::LineLayoutInterface::TextBox::hasHyphen const):
+ (WebCore::LineLayoutInterface::TextBox::isLeftToRightDirection const):
+ (WebCore::LineLayoutInterface::TextBox::dirOverride const):
+ (WebCore::LineLayoutInterface::TextBox::text const):
+ (WebCore::LineLayoutInterface::TextBoxIterator::TextBoxIterator):
+ (WebCore::LineLayoutInterface::TextBoxIterator::traverseNext):
+ (WebCore::LineLayoutInterface::TextBoxIterator::operator== const):
+ (WebCore::LineLayoutInterface::simpleLineRunResolverForText):
+ (WebCore::LineLayoutInterface::rangeForText):
+ (WebCore::LineLayoutInterface::TextBoxRange::TextBoxRange):
+ (WebCore::LineLayoutInterface::textBoxes):
+ * rendering/line/LineLayoutInterfaceTextBoxes.h: Added.
+ (WebCore::LineLayoutInterface::TextBox::TextBox):
+ (WebCore::LineLayoutInterface::TextBoxIterator::operator++):
+ (WebCore::LineLayoutInterface::TextBoxIterator::operator!= const):
+ (WebCore::LineLayoutInterface::TextBoxIterator::operator* const):
+ (WebCore::LineLayoutInterface::TextBoxRange::begin const):
+ (WebCore::LineLayoutInterface::TextBoxRange::end const):
+
2019-08-24 Zalan Bujtas <[email protected]>
[LFC][BFC] Non-inline formatting context(table, grid etc) root container should not collapse through.
Modified: trunk/Source/WebCore/Sources.txt (249083 => 249084)
--- trunk/Source/WebCore/Sources.txt 2019-08-24 13:24:29 UTC (rev 249083)
+++ trunk/Source/WebCore/Sources.txt 2019-08-24 13:31:50 UTC (rev 249084)
@@ -2152,6 +2152,7 @@
rendering/line/LineBreaker.cpp
rendering/line/LineInfo.cpp
+rendering/line/LineLayoutInterfaceTextBoxes.cpp
rendering/line/LineWidth.cpp
rendering/line/TrailingObjects.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (249083 => 249084)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2019-08-24 13:24:29 UTC (rev 249083)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2019-08-24 13:31:50 UTC (rev 249084)
@@ -4789,6 +4789,7 @@
E47C39331FE6E10800BBBC6B /* RenderTreeBuilderMultiColumn.h in Headers */ = {isa = PBXBuildFile; fileRef = E47C39271FE6E0DC00BBBC6B /* RenderTreeBuilderMultiColumn.h */; };
E47E276516036ED200EE2AFB /* ExtensionStyleSheets.h in Headers */ = {isa = PBXBuildFile; fileRef = E47E276416036ED200EE2AFB /* ExtensionStyleSheets.h */; settings = {ATTRIBUTES = (Private, ); }; };
E48137B91DB3B526005C59BF /* StyleValidity.h in Headers */ = {isa = PBXBuildFile; fileRef = E48137B81DB3B526005C59BF /* StyleValidity.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ E484A33E23055325009ADE6A /* LineLayoutInterfaceTextBoxes.h in Headers */ = {isa = PBXBuildFile; fileRef = E484A33B23055303009ADE6A /* LineLayoutInterfaceTextBoxes.h */; };
E48944A3180B57D800F165D8 /* SimpleLineLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = E48944A1180B57D800F165D8 /* SimpleLineLayout.h */; settings = {ATTRIBUTES = (Private, ); }; };
E4916FF7195DF6A0005AB349 /* LayerFlushThrottleState.h in Headers */ = {isa = PBXBuildFile; fileRef = E4916FF6195DF6A0005AB349 /* LayerFlushThrottleState.h */; settings = {ATTRIBUTES = (Private, ); }; };
E4946EAF156E64DD00D3297F /* StyleRuleImport.h in Headers */ = {isa = PBXBuildFile; fileRef = E4946EAD156E64DD00D3297F /* StyleRuleImport.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -14951,6 +14952,8 @@
E47E276416036ED200EE2AFB /* ExtensionStyleSheets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExtensionStyleSheets.h; sourceTree = "<group>"; };
E47E276716036EDC00EE2AFB /* ExtensionStyleSheets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExtensionStyleSheets.cpp; sourceTree = "<group>"; };
E48137B81DB3B526005C59BF /* StyleValidity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleValidity.h; sourceTree = "<group>"; };
+ E484A33B23055303009ADE6A /* LineLayoutInterfaceTextBoxes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LineLayoutInterfaceTextBoxes.h; sourceTree = "<group>"; };
+ E484A33D23055303009ADE6A /* LineLayoutInterfaceTextBoxes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LineLayoutInterfaceTextBoxes.cpp; sourceTree = "<group>"; };
E48944A0180B57D800F165D8 /* SimpleLineLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SimpleLineLayout.cpp; sourceTree = "<group>"; };
E48944A1180B57D800F165D8 /* SimpleLineLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleLineLayout.h; sourceTree = "<group>"; };
E4916FF6195DF6A0005AB349 /* LayerFlushThrottleState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LayerFlushThrottleState.h; sourceTree = "<group>"; };
@@ -28172,6 +28175,8 @@
FFB698CD1833F17600158A31 /* LineInfo.cpp */,
FFB698CE1833F17600158A31 /* LineInfo.h */,
FFEFAB2D183BCB6F00514534 /* LineInlineHeaders.h */,
+ E484A33D23055303009ADE6A /* LineLayoutInterfaceTextBoxes.cpp */,
+ E484A33B23055303009ADE6A /* LineLayoutInterfaceTextBoxes.h */,
FFEFAB2918380DA000514534 /* LineLayoutState.h */,
FFDBC046183D27B700407109 /* LineWidth.cpp */,
FFDBC045183D27B700407109 /* LineWidth.h */,
@@ -31917,6 +31922,7 @@
B2C3DA3E0D006C1D00EF6F26 /* TextCodecLatin1.h in Headers */,
57EF5E601D20C83900171E60 /* TextCodecReplacement.h in Headers */,
B2C3DA400D006C1D00EF6F26 /* TextCodecUserDefined.h in Headers */,
+ E484A33E23055325009ADE6A /* LineLayoutInterfaceTextBoxes.h in Headers */,
B2C3DA420D006C1D00EF6F26 /* TextCodecUTF16.h in Headers */,
9343CB8212F25E510033C5EE /* TextCodecUTF8.h in Headers */,
142B97CA13138943008BEF4B /* TextControlInnerElements.h in Headers */,
Modified: trunk/Source/WebCore/rendering/RenderTreeAsText.cpp (249083 => 249084)
--- trunk/Source/WebCore/rendering/RenderTreeAsText.cpp 2019-08-24 13:24:29 UTC (rev 249083)
+++ trunk/Source/WebCore/rendering/RenderTreeAsText.cpp 2019-08-24 13:31:50 UTC (rev 249084)
@@ -35,6 +35,7 @@
#include "HTMLNames.h"
#include "HTMLSpanElement.h"
#include "InlineTextBox.h"
+#include "LineLayoutInterfaceTextBoxes.h"
#include "Logging.h"
#include "PrintContext.h"
#include "PseudoElement.h"
@@ -63,7 +64,6 @@
#include "RenderWidget.h"
#include "SVGRenderTreeAsText.h"
#include "ShadowRoot.h"
-#include "SimpleLineLayoutResolver.h"
#include "StyleProperties.h"
#include <wtf/HexNumber.h>
#include <wtf/Vector.h>
@@ -202,7 +202,8 @@
// many test results.
const RenderText& text = downcast<RenderText>(o);
r = IntRect(text.firstRunLocation(), text.linesBoundingBox().size());
- if (!text.firstTextBox() && !text.simpleLineLayout())
+ auto textBoxes = LineLayoutInterface::textBoxes(text);
+ if (textBoxes.begin() == textBoxes.end())
adjustForTableCells = false;
} else if (o.isBR()) {
const RenderLineBreak& br = downcast<RenderLineBreak>(o);
@@ -477,48 +478,34 @@
}
}
-static void writeTextRun(TextStream& ts, const RenderText& o, const InlineTextBox& run)
+static void writeTextBox(TextStream& ts, const RenderText& o, const LineLayoutInterface::TextBox& textBox)
{
- // FIXME: For now use an "enclosingIntRect" model for x, y and logicalWidth, although this makes it harder
- // to detect any changes caused by the conversion to floating point. :(
- int x = run.x();
- int y = run.y();
- int logicalWidth = ceilf(run.left() + run.logicalWidth()) - x;
+ auto rect = textBox.rect();
+ auto logicalRect = textBox.logicalRect();
+ int x = rect.x();
+ int y = rect.y();
+
+ // FIXME: Mixing logical and physical here doesn't make sense.
+ int logicalWidth = ceilf(rect.x() + logicalRect.width()) - x;
+
// FIXME: Table cell adjustment is temporary until results can be updated.
if (is<RenderTableCell>(*o.containingBlock()))
y -= floorToInt(downcast<RenderTableCell>(*o.containingBlock()).intrinsicPaddingBefore());
ts << "text run at (" << x << "," << y << ") width " << logicalWidth;
- if (!run.isLeftToRightDirection() || run.dirOverride()) {
- ts << (!run.isLeftToRightDirection() ? " RTL" : " LTR");
- if (run.dirOverride())
+ if (!textBox.isLeftToRightDirection() || textBox.dirOverride()) {
+ ts << (!textBox.isLeftToRightDirection() ? " RTL" : " LTR");
+ if (textBox.dirOverride())
ts << " override";
}
ts << ": "
- << quoteAndEscapeNonPrintables(String(o.text()).substring(run.start(), run.len()));
- if (run.hasHyphen())
+ << quoteAndEscapeNonPrintables(textBox.text());
+ if (textBox.hasHyphen())
ts << " + hyphen string " << quoteAndEscapeNonPrintables(o.style().hyphenString().string());
ts << "\n";
}
-static void writeSimpleLine(TextStream& ts, const RenderText& renderText, const SimpleLineLayout::RunResolver::Run& run)
-{
- auto rect = run.rect();
- int x = rect.x();
- int y = rect.y();
- int logicalWidth = ceilf(rect.x() + rect.width()) - x;
-
- if (is<RenderTableCell>(*renderText.containingBlock()))
- y -= floorToInt(downcast<RenderTableCell>(*renderText.containingBlock()).intrinsicPaddingBefore());
-
- ts << "text run at (" << x << "," << y << ") width " << logicalWidth;
- ts << ": " << quoteAndEscapeNonPrintables(run.text());
- if (run.hasHyphen())
- ts << " + hyphen string " << quoteAndEscapeNonPrintables(renderText.style().hyphenString().string());
- ts << "\n";
-}
-
void write(TextStream& ts, const RenderObject& o, OptionSet<RenderAsTextFlag> behavior)
{
if (is<RenderSVGShape>(o)) {
@@ -563,20 +550,10 @@
if (is<RenderText>(o)) {
auto& text = downcast<RenderText>(o);
- if (auto layout = text.simpleLineLayout()) {
- ASSERT(!text.firstTextBox());
- auto resolver = runResolver(downcast<RenderBlockFlow>(*text.parent()), *layout);
- for (auto run : resolver.rangeForRenderer(text)) {
- ts << indent;
- writeSimpleLine(ts, text, run);
- }
- } else {
- for (auto* box = text.firstTextBox(); box; box = box->nextTextBox()) {
- ts << indent;
- writeTextRun(ts, text, *box);
- }
+ for (auto textBox : LineLayoutInterface::textBoxes(text)) {
+ ts << indent;
+ writeTextBox(ts, text, textBox);
}
-
} else {
for (auto& child : childrenOfType<RenderObject>(downcast<RenderElement>(o))) {
if (child.hasLayer())
Added: trunk/Source/WebCore/rendering/line/LineLayoutInterfaceTextBoxes.cpp (0 => 249084)
--- trunk/Source/WebCore/rendering/line/LineLayoutInterfaceTextBoxes.cpp (rev 0)
+++ trunk/Source/WebCore/rendering/line/LineLayoutInterfaceTextBoxes.cpp 2019-08-24 13:31:50 UTC (rev 249084)
@@ -0,0 +1,183 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "LineLayoutInterfaceTextBoxes.h"
+
+#include "InlineTextBox.h"
+#include "RenderText.h"
+#include "SimpleLineLayoutResolver.h"
+
+namespace WebCore {
+namespace LineLayoutInterface {
+
+FloatRect TextBox::rect() const
+{
+ auto simple = [](const SimpleLineLayout::RunResolver::Iterator simpleLineIterator) {
+ return (*simpleLineIterator).rect();
+ };
+
+ auto complex = [](const InlineTextBox* inlineTextBox) {
+ return inlineTextBox->frameRect();
+ };
+
+ return WTF::switchOn(m_iterator.m_pathVariant, simple, complex);
+}
+
+FloatRect TextBox::logicalRect() const
+{
+ auto simple = [](const SimpleLineLayout::RunResolver::Iterator simpleLineIterator) {
+ return (*simpleLineIterator).rect();
+ };
+
+ auto complex = [](const InlineTextBox* inlineTextBox) {
+ return inlineTextBox->logicalFrameRect();
+ };
+
+ return WTF::switchOn(m_iterator.m_pathVariant, simple, complex);
+}
+
+bool TextBox::hasHyphen() const
+{
+ auto simple = [](const SimpleLineLayout::RunResolver::Iterator simpleLineIterator) {
+ return (*simpleLineIterator).hasHyphen();
+ };
+
+ auto complex = [](const InlineTextBox* inlineTextBox) {
+ return inlineTextBox->hasHyphen();
+ };
+
+ return WTF::switchOn(m_iterator.m_pathVariant, simple, complex);
+}
+
+bool TextBox::isLeftToRightDirection() const
+{
+ auto simple = [](const SimpleLineLayout::RunResolver::Iterator) {
+ return true;
+ };
+
+ auto complex = [](const InlineTextBox* inlineTextBox) {
+ return inlineTextBox->isLeftToRightDirection();
+ };
+
+ return WTF::switchOn(m_iterator.m_pathVariant, simple, complex);
+}
+
+bool TextBox::dirOverride() const
+{
+ auto simple = [](const SimpleLineLayout::RunResolver::Iterator) {
+ return false;
+ };
+
+ auto complex = [](const InlineTextBox* inlineTextBox) {
+ return inlineTextBox->dirOverride();
+ };
+
+ return WTF::switchOn(m_iterator.m_pathVariant, simple, complex);
+}
+
+StringView TextBox::text() const
+{
+ auto simple = [](const SimpleLineLayout::RunResolver::Iterator simpleLineIterator) {
+ return (*simpleLineIterator).text();
+ };
+
+ auto complex = [](const InlineTextBox* inlineTextBox) {
+ return StringView(inlineTextBox->renderer().text()).substring(inlineTextBox->start(), inlineTextBox->len());
+ };
+
+ return WTF::switchOn(m_iterator.m_pathVariant, simple, complex);
+}
+
+TextBoxIterator::TextBoxIterator(const InlineTextBox* inlineTextBox)
+ : m_pathVariant(inlineTextBox)
+{
+}
+
+TextBoxIterator::TextBoxIterator(SimpleLineLayout::RunResolver::Iterator simpleLineIterator)
+ : m_pathVariant(simpleLineIterator)
+{
+}
+
+TextBoxIterator& TextBoxIterator::traverseNext()
+{
+ auto simple = [](SimpleLineLayout::RunResolver::Iterator& simpleLineIterator) {
+ ++simpleLineIterator;
+ };
+
+ auto complex = [](const InlineTextBox*& inlineTextBox) {
+ inlineTextBox = inlineTextBox->nextTextBox();
+ };
+
+ WTF::switchOn(m_pathVariant, simple, complex);
+
+ return *this;
+}
+
+bool TextBoxIterator::operator==(const TextBoxIterator& other) const
+{
+ if (m_pathVariant.index() != other.m_pathVariant.index())
+ return false;
+
+ auto simple = [&](const SimpleLineLayout::RunResolver::Iterator simpleLineIterator) {
+ return simpleLineIterator == WTF::get<SimpleLineLayout::RunResolver::Iterator>(other.m_pathVariant);
+ };
+
+ auto complex = [&](const InlineTextBox* inlineTextBox) {
+ return inlineTextBox == WTF::get<const InlineTextBox*>(other.m_pathVariant);
+ };
+
+ return WTF::switchOn(m_pathVariant, simple, complex);
+}
+
+static Optional<SimpleLineLayout::RunResolver> simpleLineRunResolverForText(const RenderText& text)
+{
+ if (!text.simpleLineLayout())
+ return WTF::nullopt;
+ return SimpleLineLayout::runResolver(downcast<const RenderBlockFlow>(*text.parent()), *text.simpleLineLayout());
+}
+
+static auto rangeForText(const RenderText& text, Optional<SimpleLineLayout::RunResolver>& simpleLineRunResolver)
+{
+ if (simpleLineRunResolver) {
+ auto range = simpleLineRunResolver->rangeForRenderer(text);
+ return WTF::makeIteratorRange(TextBoxIterator(range.begin()), TextBoxIterator(range.end()));
+ }
+ return WTF::makeIteratorRange(TextBoxIterator(text.firstTextBox()), TextBoxIterator(nullptr));
+}
+
+TextBoxRange::TextBoxRange(const RenderText& text)
+ : m_simpleLineRunResolver(simpleLineRunResolverForText(text))
+ , m_range(rangeForText(text, m_simpleLineRunResolver))
+{
+}
+
+TextBoxRange textBoxes(const RenderText& text)
+{
+ return { text };
+}
+
+}
+}
Added: trunk/Source/WebCore/rendering/line/LineLayoutInterfaceTextBoxes.h (0 => 249084)
--- trunk/Source/WebCore/rendering/line/LineLayoutInterfaceTextBoxes.h (rev 0)
+++ trunk/Source/WebCore/rendering/line/LineLayoutInterfaceTextBoxes.h 2019-08-24 13:31:50 UTC (rev 249084)
@@ -0,0 +1,100 @@
+/*
+ * 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 "FloatRect.h"
+#include "SimpleLineLayoutResolver.h"
+#include <wtf/IteratorRange.h>
+#include <wtf/Variant.h>
+#include <wtf/text/StringView.h>
+
+namespace WebCore {
+
+class InlineTextBox;
+class RenderText;
+
+namespace LineLayoutInterface {
+
+class TextBoxContext;
+class TextBoxIterator;
+
+class TextBox {
+public:
+ TextBox(const TextBoxIterator& iterator)
+ : m_iterator(iterator)
+ { }
+
+ FloatRect rect() const;
+ FloatRect logicalRect() const;
+
+ bool hasHyphen() const;
+ bool isLeftToRightDirection() const;
+ bool dirOverride() const;
+
+ StringView text() const;
+
+private:
+ const TextBoxIterator& m_iterator;
+};
+
+class TextBoxIterator {
+public:
+ TextBoxIterator(const InlineTextBox*);
+ TextBoxIterator(SimpleLineLayout::RunResolver::Iterator);
+
+ TextBoxIterator& operator++() { return traverseNext(); }
+
+ bool operator==(const TextBoxIterator&) const;
+ bool operator!=(const TextBoxIterator& other) const { return !(*this == other); }
+
+ TextBox operator*() const { return { *this }; }
+
+private:
+ friend class TextBox;
+
+ TextBoxIterator& traverseNext();
+
+ Variant<SimpleLineLayout::RunResolver::Iterator, const InlineTextBox*> m_pathVariant;
+};
+
+class TextBoxRange {
+public:
+ TextBoxRange(const RenderText&);
+
+ TextBoxIterator begin() const { return m_range.begin(); }
+ TextBoxIterator end() const { return m_range.end(); }
+
+private:
+ friend class TextBoxIterator;
+
+ Optional<SimpleLineLayout::RunResolver> m_simpleLineRunResolver;
+ WTF::IteratorRange<TextBoxIterator> m_range;
+};
+
+TextBoxRange textBoxes(const RenderText&);
+
+}
+}