Diff
Modified: trunk/Source/WebCore/ChangeLog (284111 => 284112)
--- trunk/Source/WebCore/ChangeLog 2021-10-13 18:02:14 UTC (rev 284111)
+++ trunk/Source/WebCore/ChangeLog 2021-10-13 18:02:22 UTC (rev 284112)
@@ -1,5 +1,49 @@
2021-10-13 Antti Koivisto <[email protected]>
+ [LFC][Integration] Move text box logical order cache to the caller
+ https://bugs.webkit.org/show_bug.cgi?id=231669
+
+ Reviewed by Alan Bujtas.
+
+ Don't maintain this rarely used cache internally in the iterator. Instead move it to the caller.
+
+ Also make the code non-legacy specific so it will work with future IFC BiDi.
+
+ * dom/Position.cpp:
+ (WebCore::Position::upstream const):
+ (WebCore::Position::downstream const):
+ (WebCore::searchAheadForBetterMatch):
+ * editing/CompositeEditCommand.cpp:
+ (WebCore::CompositeEditCommand::deleteInsignificantText):
+ * editing/TextIterator.cpp:
+ (WebCore::TextIterator::advance):
+ (WebCore::TextIterator::handleTextNode):
+ (WebCore::TextIterator::handleTextRun):
+ (WebCore::TextIterator::revertToRemainingTextRun):
+ (WebCore::TextIterator::handleTextNodeFirstLetter):
+ * editing/TextIterator.h:
+ * layout/integration/InlineIteratorBoxLegacyPath.h:
+ (WebCore::InlineIterator::BoxLegacyPath::traverseNextTextBox):
+ (WebCore::InlineIterator::BoxLegacyPath::traverseNextTextBoxInTextOrder): Deleted.
+ * layout/integration/InlineIteratorBoxModernPath.h:
+ (WebCore::InlineIterator::BoxModernPath::traverseNextTextBoxInTextOrder): Deleted.
+ * layout/integration/InlineIteratorTextBox.cpp:
+ (WebCore::InlineIterator::firstTextBoxInLogicalOrderFor):
+ (WebCore::InlineIterator::nextTextBoxInLogicalOrder):
+
+ Traverse using free functions instead of members.
+
+ (WebCore::InlineIterator::TextBox::nextTextBoxInTextOrder const): Deleted.
+ (WebCore::InlineIterator::TextBoxIterator::traverseNextTextBoxInTextOrder): Deleted.
+ (WebCore::InlineIterator::firstTextBoxInTextOrderFor): Deleted.
+ * layout/integration/InlineIteratorTextBox.h:
+ * rendering/LegacyInlineTextBox.h:
+ (WebCore::LegacyInlineTextBox::compareByStart): Deleted.
+ * rendering/RenderText.cpp:
+ (WebCore::containsOffset):
+
+2021-10-13 Antti Koivisto <[email protected]>
+
[LFC][Integration] Add concept of integration root and stop using InitialContainingBlock
https://bugs.webkit.org/show_bug.cgi?id=231662
Modified: trunk/Source/WebCore/dom/Position.cpp (284111 => 284112)
--- trunk/Source/WebCore/dom/Position.cpp 2021-10-13 18:02:14 UTC (rev 284111)
+++ trunk/Source/WebCore/dom/Position.cpp 2021-10-13 18:02:22 UTC (rev 284112)
@@ -740,7 +740,7 @@
if (is<RenderText>(*renderer)) {
auto& textRenderer = downcast<RenderText>(*renderer);
- auto firstTextRun = InlineIterator::firstTextBoxInTextOrderFor(textRenderer);
+ auto [firstTextRun, orderCache] = InlineIterator::firstTextBoxInLogicalOrderFor(textRenderer);
if (!firstTextRun)
continue;
@@ -758,7 +758,7 @@
if (textOffset > run->start() && textOffset <= run->end())
return currentPosition;
- auto nextRun = run->nextTextBoxInTextOrder();
+ auto nextRun = InlineIterator::nextTextBoxInLogicalOrder(run, orderCache);
if (textOffset == run->end() + 1 && nextRun && run->line() != nextRun->line())
return currentPosition;
@@ -847,7 +847,7 @@
if (is<RenderText>(*renderer)) {
auto& textRenderer = downcast<RenderText>(*renderer);
- auto firstTextRun = InlineIterator::firstTextBoxInTextOrderFor(textRenderer);
+ auto [firstTextRun, orderCache] = InlineIterator::firstTextBoxInLogicalOrderFor(textRenderer);
if (!firstTextRun)
continue;
@@ -864,7 +864,7 @@
if (textOffset >= run->start() && textOffset < run->end())
return currentPosition;
- auto nextRun = run->nextTextBoxInTextOrder();
+ auto nextRun = InlineIterator::nextTextBoxInLogicalOrder(run, orderCache);
if (textOffset == run->end() && nextRun && run->line() != nextRun->line())
return currentPosition;
@@ -1173,7 +1173,7 @@
if (isNonTextLeafChild(*next))
return { };
if (is<RenderText>(*next)) {
- if (auto run = InlineIterator::firstTextBoxInTextOrderFor(downcast<RenderText>(*next)))
+ if (auto [run, orderCache] = InlineIterator::firstTextBoxInLogicalOrderFor(downcast<RenderText>(*next)); run)
return run;
}
}
Modified: trunk/Source/WebCore/editing/CompositeEditCommand.cpp (284111 => 284112)
--- trunk/Source/WebCore/editing/CompositeEditCommand.cpp 2021-10-13 18:02:14 UTC (rev 284111)
+++ trunk/Source/WebCore/editing/CompositeEditCommand.cpp 2021-10-13 18:02:22 UTC (rev 284112)
@@ -1016,7 +1016,7 @@
if (!textRenderer)
return;
- auto run = InlineIterator::firstTextBoxInTextOrderFor(*textRenderer);
+ auto [run, orderCache] = InlineIterator::firstTextBoxInLogicalOrderFor(*textRenderer);
if (!run) {
wholeTextNodeIsEmpty = true;
return;
@@ -1051,7 +1051,7 @@
previousRun = run;
if (run)
- run.traverseNextTextBoxInTextOrder();
+ run = InlineIterator::nextTextBoxInLogicalOrder(run, orderCache);
}
};
determineRemovalMode();
Modified: trunk/Source/WebCore/editing/TextIterator.cpp (284111 => 284112)
--- trunk/Source/WebCore/editing/TextIterator.cpp 2021-10-13 18:02:14 UTC (rev 284111)
+++ trunk/Source/WebCore/editing/TextIterator.cpp 2021-10-13 18:02:22 UTC (rev 284112)
@@ -438,12 +438,9 @@
return;
}
- if (!m_textRun && m_remainingTextRun) {
- m_textRun = m_remainingTextRun;
- m_remainingTextRun = { };
- m_firstLetterText = { };
- m_offset = 0;
- }
+ if (!m_textRun && m_remainingTextRun)
+ revertToRemainingTextRun();
+
// handle remembered text box
if (m_textRun) {
handleTextRun();
@@ -581,7 +578,7 @@
return true;
}
- m_textRun = InlineIterator::firstTextBoxInTextOrderFor(renderer);
+ std::tie(m_textRun, m_textRunLogicalOrderCache) = InlineIterator::firstTextBoxInLogicalOrderFor(renderer);
bool shouldHandleFirstLetter = !m_handledFirstLetter && is<RenderTextFragment>(renderer) && !m_offset;
if (shouldHandleFirstLetter)
@@ -608,7 +605,7 @@
return;
}
- auto firstTextRun = InlineIterator::firstTextBoxInTextOrderFor(renderer);
+ auto [firstTextRun, orderCache] = InlineIterator::firstTextBoxInLogicalOrderFor(renderer);
String rendererText = renderer.text();
unsigned start = m_offset;
@@ -633,8 +630,7 @@
unsigned runEnd = std::min(textRunEnd, end);
// Determine what the next text run will be, but don't advance yet
- auto nextTextRun = m_textRun;
- nextTextRun.traverseNextTextBoxInTextOrder();
+ auto nextTextRun = InlineIterator::nextTextBoxInLogicalOrder(m_textRun, m_textRunLogicalOrderCache);
if (runStart < runEnd) {
auto isNewlineOrTab = [&](UChar character) {
@@ -677,14 +673,22 @@
m_textRun = nextTextRun;
}
if (!m_textRun && m_remainingTextRun) {
- m_textRun = m_remainingTextRun;
- m_remainingTextRun = { };
- m_firstLetterText = { };
- m_offset = 0;
+ revertToRemainingTextRun();
handleTextRun();
}
}
+void TextIterator::revertToRemainingTextRun()
+{
+ ASSERT(!m_textRun && m_remainingTextRun);
+
+ m_textRun = m_remainingTextRun;
+ m_textRunLogicalOrderCache = std::exchange(m_remainingTextRunLogicalOrderCache, { });
+ m_remainingTextRun = { };
+ m_firstLetterText = { };
+ m_offset = 0;
+}
+
static inline RenderText* firstRenderTextInFirstLetter(RenderBoxModelObject* firstLetter)
{
if (!firstLetter)
@@ -702,7 +706,8 @@
if (auto* firstLetterText = firstRenderTextInFirstLetter(firstLetter)) {
m_handledFirstLetter = true;
m_remainingTextRun = m_textRun;
- m_textRun = InlineIterator::firstTextBoxInTextOrderFor(*firstLetterText);
+ m_remainingTextRunLogicalOrderCache = std::exchange(m_textRunLogicalOrderCache, { });
+ std::tie(m_textRun, m_textRunLogicalOrderCache) = InlineIterator::firstTextBoxInLogicalOrderFor(*firstLetterText);
m_firstLetterText = firstLetterText;
}
}
Modified: trunk/Source/WebCore/editing/TextIterator.h (284111 => 284112)
--- trunk/Source/WebCore/editing/TextIterator.h 2021-10-13 18:02:14 UTC (rev 284111)
+++ trunk/Source/WebCore/editing/TextIterator.h 2021-10-13 18:02:22 UTC (rev 284112)
@@ -120,6 +120,7 @@
void handleTextNodeFirstLetter(RenderTextFragment&);
void emitCharacter(UChar, Node& characterNode, Node* offsetBaseNode, int textStartOffset, int textEndOffset);
void emitText(Text& textNode, RenderText&, int textStartOffset, int textEndOffset);
+ void revertToRemainingTextRun();
Node* baseNodeForEmittingNewLine() const;
@@ -150,9 +151,11 @@
// Used when there is still some pending text from the current node; when these are false and null, we go back to normal iterating.
Node* m_nodeForAdditionalNewline { nullptr };
InlineIterator::TextBoxIterator m_textRun;
+ InlineIterator::LogicalOrderCache m_textRunLogicalOrderCache;
// Used when iterating over :first-letter text to save pointer to remaining text box.
InlineIterator::TextBoxIterator m_remainingTextRun;
+ InlineIterator::LogicalOrderCache m_remainingTextRunLogicalOrderCache;
// Used to point to RenderText object for :first-letter.
RenderText* m_firstLetterText { nullptr };
Modified: trunk/Source/WebCore/layout/integration/InlineIteratorBoxLegacyPath.h (284111 => 284112)
--- trunk/Source/WebCore/layout/integration/InlineIteratorBoxLegacyPath.h 2021-10-13 18:02:14 UTC (rev 284111)
+++ trunk/Source/WebCore/layout/integration/InlineIteratorBoxLegacyPath.h 2021-10-13 18:02:22 UTC (rev 284112)
@@ -87,15 +87,6 @@
}
void traverseNextTextBox() { m_inlineBox = inlineTextBox()->nextTextBox(); }
- void traverseNextTextBoxInTextOrder()
- {
- if (!m_logicalOrderCache.isEmpty()) {
- traverseNextInlineBoxInCacheOrder();
- ASSERT(!m_inlineBox || is<LegacyInlineTextBox>(m_inlineBox));
- return;
- }
- traverseNextTextBox();
- }
void traverseNextOnLine()
{
Modified: trunk/Source/WebCore/layout/integration/InlineIteratorBoxModernPath.h (284111 => 284112)
--- trunk/Source/WebCore/layout/integration/InlineIteratorBoxModernPath.h 2021-10-13 18:02:14 UTC (rev 284111)
+++ trunk/Source/WebCore/layout/integration/InlineIteratorBoxModernPath.h 2021-10-13 18:02:22 UTC (rev 284112)
@@ -136,12 +136,6 @@
ASSERT(atEnd() || box().text());
}
- void traverseNextTextBoxInTextOrder()
- {
- // FIXME: No RTL in LFC.
- traverseNextTextBox();
- }
-
void traverseNextOnLine()
{
ASSERT(!atEnd());
Modified: trunk/Source/WebCore/layout/integration/InlineIteratorTextBox.cpp (284111 => 284112)
--- trunk/Source/WebCore/layout/integration/InlineIteratorTextBox.cpp 2021-10-13 18:02:14 UTC (rev 284111)
+++ trunk/Source/WebCore/layout/integration/InlineIteratorTextBox.cpp 2021-10-13 18:02:22 UTC (rev 284112)
@@ -38,11 +38,6 @@
return TextBoxIterator(*this).traverseNextTextBox();
}
-TextBoxIterator TextBox::nextTextBoxInTextOrder() const
-{
- return TextBoxIterator(*this).traverseNextTextBoxInTextOrder();
-}
-
LayoutRect TextBox::selectionRect(unsigned rangeStart, unsigned rangeEnd) const
{
auto [clampedStart, clampedEnd] = selectableRange().clamp(rangeStart, rangeEnd);
@@ -94,14 +89,6 @@
return *this;
}
-TextBoxIterator& TextBoxIterator::traverseNextTextBoxInTextOrder()
-{
- WTF::switchOn(m_box.m_pathVariant, [](auto& path) {
- path.traverseNextTextBoxInTextOrder();
- });
- return *this;
-}
-
TextBoxIterator firstTextBoxFor(const RenderText& text)
{
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
@@ -112,20 +99,41 @@
return { BoxLegacyPath { text.firstTextBox() } };
}
-TextBoxIterator firstTextBoxInTextOrderFor(const RenderText& text)
+std::pair<TextBoxIterator, LogicalOrderCache> firstTextBoxInLogicalOrderFor(const RenderText& text)
{
- if (text.firstTextBox() && text.containsReversedText()) {
- Vector<const LegacyInlineBox*> sortedTextBoxes;
- for (auto* textBox = text.firstTextBox(); textBox; textBox = textBox->nextTextBox())
- sortedTextBoxes.append(textBox);
- std::sort(sortedTextBoxes.begin(), sortedTextBoxes.end(), [](auto* a, auto* b) {
- return LegacyInlineTextBox::compareByStart(downcast<LegacyInlineTextBox>(a), downcast<LegacyInlineTextBox>(b));
- });
- auto* first = sortedTextBoxes[0];
- return { BoxLegacyPath { first, WTFMove(sortedTextBoxes), 0 } };
+ if (!text.containsReversedText())
+ return { firstTextBoxFor(text), nullptr };
+
+ auto cache = WTF::makeUnique<LogicalOrderCacheData>();
+ for (auto textBox : textBoxesFor(text))
+ cache->boxes.append(textBox);
+
+ if (cache->boxes.isEmpty())
+ return { TextBoxIterator { }, nullptr };
+
+ std::sort(cache->boxes.begin(), cache->boxes.end(), [&](auto& a, auto& b) {
+ return a->start() < b->start();
+ });
+
+ return { cache->boxes[0], WTFMove(cache) };
+}
+
+TextBoxIterator nextTextBoxInLogicalOrder(const TextBoxIterator& textBox, LogicalOrderCache& cache)
+{
+ if (!cache)
+ return textBox->nextTextBox();
+
+ if (cache->index == cache->boxes.size() || cache->boxes[cache->index] != textBox) {
+ cache->index = cache->boxes.find(textBox);
+ ASSERT(cache->index != notFound);
}
- return firstTextBoxFor(text);
+ cache->index++;
+
+ if (cache->index < cache->boxes.size())
+ return cache->boxes[cache->index];
+
+ return { };
}
TextBoxIterator textBoxFor(const LegacyInlineTextBox* legacyInlineTextBox)
Modified: trunk/Source/WebCore/layout/integration/InlineIteratorTextBox.h (284111 => 284112)
--- trunk/Source/WebCore/layout/integration/InlineIteratorTextBox.h 2021-10-13 18:02:14 UTC (rev 284111)
+++ trunk/Source/WebCore/layout/integration/InlineIteratorTextBox.h 2021-10-13 18:02:22 UTC (rev 284112)
@@ -32,6 +32,9 @@
namespace InlineIterator {
+struct LogicalOrderCacheData;
+using LogicalOrderCache = std::unique_ptr<LogicalOrderCacheData>;
+
class TextBox : public Box {
public:
TextBox(PathVariant&&);
@@ -60,7 +63,6 @@
const LegacyInlineTextBox* legacyInlineBox() const { return downcast<LegacyInlineTextBox>(Box::legacyInlineBox()); }
TextBoxIterator nextTextBox() const;
- TextBoxIterator nextTextBoxInTextOrder() const;
};
class TextBoxIterator : public LeafBoxIterator {
@@ -75,7 +77,6 @@
const TextBox* operator->() const { return &get(); }
TextBoxIterator& traverseNextTextBox();
- TextBoxIterator& traverseNextTextBoxInTextOrder();
private:
BoxIterator& traverseNextOnLine() = delete;
@@ -103,7 +104,6 @@
};
TextBoxIterator firstTextBoxFor(const RenderText&);
-TextBoxIterator firstTextBoxInTextOrderFor(const RenderText&);
TextBoxIterator textBoxFor(const LegacyInlineTextBox*);
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
TextBoxIterator textBoxFor(const LayoutIntegration::InlineContent&, const InlineDisplay::Box&);
@@ -111,6 +111,15 @@
#endif
TextBoxRange textBoxesFor(const RenderText&);
+struct LogicalOrderCacheData {
+ WTF_MAKE_STRUCT_FAST_ALLOCATED;
+
+ Vector<TextBoxIterator> boxes;
+ size_t index { 0 };
+};
+std::pair<TextBoxIterator, LogicalOrderCache> firstTextBoxInLogicalOrderFor(const RenderText&);
+TextBoxIterator nextTextBoxInLogicalOrder(const TextBoxIterator&, LogicalOrderCache&);
+
inline bool TextBox::hasHyphen() const
{
return WTF::switchOn(m_pathVariant, [](auto& path) {
Modified: trunk/Source/WebCore/rendering/LegacyInlineTextBox.h (284111 => 284112)
--- trunk/Source/WebCore/rendering/LegacyInlineTextBox.h 2021-10-13 18:02:14 UTC (rev 284111)
+++ trunk/Source/WebCore/rendering/LegacyInlineTextBox.h 2021-10-13 18:02:22 UTC (rev 284112)
@@ -88,8 +88,6 @@
using LegacyInlineBox::forceLeftExpansion;
using LegacyInlineBox::setForceLeftExpansion;
- static inline bool compareByStart(const LegacyInlineTextBox* first, const LegacyInlineTextBox* second) { return first->start() < second->start(); }
-
LayoutUnit baselinePosition(FontBaseline) const final;
LayoutUnit lineHeight() const final;
Modified: trunk/Source/WebCore/rendering/RenderText.cpp (284111 => 284112)
--- trunk/Source/WebCore/rendering/RenderText.cpp 2021-10-13 18:02:14 UTC (rev 284111)
+++ trunk/Source/WebCore/rendering/RenderText.cpp 2021-10-13 18:02:22 UTC (rev 284112)
@@ -1712,7 +1712,7 @@
enum class OffsetType { Character, Caret };
static bool containsOffset(const RenderText& text, unsigned offset, OffsetType type)
{
- for (auto box = InlineIterator::firstTextBoxInTextOrderFor(text); box; box.traverseNextTextBoxInTextOrder()) {
+ for (auto [box, orderCache] = InlineIterator::firstTextBoxInLogicalOrderFor(text); box; box = InlineIterator::nextTextBoxInLogicalOrder(box, orderCache)) {
auto start = box->start();
if (offset < start)
return false;