Title: [278621] trunk
Revision
278621
Author
[email protected]
Date
2021-06-08 11:02:20 -0700 (Tue, 08 Jun 2021)

Log Message

Factor MarkedText collection out of LegacyInlineTextBox
https://bugs.webkit.org/show_bug.cgi?id=226731

Reviewed by Sam Weinig.

Source/WebCore:

Move more code out from the legacy inline classes.

* rendering/LegacyInlineTextBox.cpp:
(WebCore::LegacyInlineTextBox::paint):
(WebCore::LegacyInlineTextBox::hasMarkers const):
(WebCore::LegacyInlineTextBox::paintPlatformDocumentMarkers):
(WebCore::LegacyInlineTextBox::calculateUnionOfAllDocumentMarkerBounds const):
(WebCore::LegacyInlineTextBox::paintMarkedTexts):
(WebCore::LegacyInlineTextBox::highlightStartEnd const): Deleted.
(WebCore::LegacyInlineTextBox::collectMarkedTextsForDraggedContent): Deleted.
(WebCore::LegacyInlineTextBox::collectMarkedTextsForDocumentMarkers const): Deleted.
(WebCore::LegacyInlineTextBox::collectMarkedTextsForHighlights const): Deleted.
* rendering/LegacyInlineTextBox.h:
(WebCore::LegacyInlineTextBox::paintMarkedTexts):
* rendering/MarkedText.cpp:
(WebCore::MarkedText::subdivide):
(WebCore::MarkedText::collectForHighlights):
(WebCore::MarkedText::collectForDocumentMarkers):
(WebCore::MarkedText::collectForDraggedContent):
(WebCore::subdivide): Deleted.
* rendering/MarkedText.h:
(WebCore::MarkedText::operator== const):
* rendering/MarkedTextStyle.cpp:
(WebCore::subdivideAndResolveStyle):

Tools:

* TestWebKitAPI/Tests/WebCore/MarkedText.cpp:
(TestWebKitAPI::TEST):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (278620 => 278621)


--- trunk/Source/WebCore/ChangeLog	2021-06-08 18:01:31 UTC (rev 278620)
+++ trunk/Source/WebCore/ChangeLog	2021-06-08 18:02:20 UTC (rev 278621)
@@ -1,3 +1,35 @@
+2021-06-08  Antti Koivisto  <[email protected]>
+
+        Factor MarkedText collection out of LegacyInlineTextBox
+        https://bugs.webkit.org/show_bug.cgi?id=226731
+
+        Reviewed by Sam Weinig.
+
+        Move more code out from the legacy inline classes.
+
+        * rendering/LegacyInlineTextBox.cpp:
+        (WebCore::LegacyInlineTextBox::paint):
+        (WebCore::LegacyInlineTextBox::hasMarkers const):
+        (WebCore::LegacyInlineTextBox::paintPlatformDocumentMarkers):
+        (WebCore::LegacyInlineTextBox::calculateUnionOfAllDocumentMarkerBounds const):
+        (WebCore::LegacyInlineTextBox::paintMarkedTexts):
+        (WebCore::LegacyInlineTextBox::highlightStartEnd const): Deleted.
+        (WebCore::LegacyInlineTextBox::collectMarkedTextsForDraggedContent): Deleted.
+        (WebCore::LegacyInlineTextBox::collectMarkedTextsForDocumentMarkers const): Deleted.
+        (WebCore::LegacyInlineTextBox::collectMarkedTextsForHighlights const): Deleted.
+        * rendering/LegacyInlineTextBox.h:
+        (WebCore::LegacyInlineTextBox::paintMarkedTexts):
+        * rendering/MarkedText.cpp:
+        (WebCore::MarkedText::subdivide):
+        (WebCore::MarkedText::collectForHighlights):
+        (WebCore::MarkedText::collectForDocumentMarkers):
+        (WebCore::MarkedText::collectForDraggedContent):
+        (WebCore::subdivide): Deleted.
+        * rendering/MarkedText.h:
+        (WebCore::MarkedText::operator== const):
+        * rendering/MarkedTextStyle.cpp:
+        (WebCore::subdivideAndResolveStyle):
+
 2021-06-08  Truitt Savell  <[email protected]>
 
         Unreviewed, reverting r278609.

Modified: trunk/Source/WebCore/rendering/LegacyInlineTextBox.cpp (278620 => 278621)


--- trunk/Source/WebCore/rendering/LegacyInlineTextBox.cpp	2021-06-08 18:01:31 UTC (rev 278620)
+++ trunk/Source/WebCore/rendering/LegacyInlineTextBox.cpp	2021-06-08 18:02:20 UTC (rev 278621)
@@ -36,7 +36,6 @@
 #include "GraphicsContext.h"
 
 #include "HighlightData.h"
-#include "HighlightRegister.h"
 #include "HitTestResult.h"
 #include "ImageBuffer.h"
 #include "InlineTextBoxStyle.h"
@@ -492,10 +491,12 @@
         if (containsComposition && !useCustomUnderlines)
             paintCompositionBackground(paintInfo, boxOrigin);
 
-        Vector<MarkedText> markedTexts = collectMarkedTextsForDocumentMarkers(TextPaintPhase::Background);
-        auto highlightMarkedTexts = collectMarkedTextsForHighlights(TextPaintPhase::Background);
-        if (!highlightMarkedTexts.isEmpty())
-            markedTexts.appendVector(WTFMove(highlightMarkedTexts));
+        auto selectableRange = this->selectableRange();
+
+        Vector<MarkedText> markedTexts;
+        markedTexts.appendVector(MarkedText::collectForDocumentMarkers(renderer(), selectableRange, MarkedText::PaintPhase::Background));
+        markedTexts.appendVector(MarkedText::collectForHighlights(renderer(), parent()->renderer(), selectableRange, MarkedText::PaintPhase::Background));
+
 #if ENABLE(TEXT_SELECTION)
         if (haveSelection && !useCustomUnderlines && !context.paintingDisabled()) {
             auto selectionMarkedText = createMarkedTextFromSelectionInBox(*this);
@@ -508,7 +509,7 @@
         // Coalesce styles of adjacent marked texts to minimize the number of drawing commands.
         auto coalescedStyledMarkedTexts = coalesceAdjacentMarkedTexts(styledMarkedTexts, &MarkedTextStyle::areBackgroundMarkedTextStylesEqual);
 
-        paintMarkedTexts(paintInfo, TextPaintPhase::Background, boxRect, coalescedStyledMarkedTexts);
+        paintMarkedTexts(paintInfo, MarkedText::PaintPhase::Background, boxRect, coalescedStyledMarkedTexts);
     }
 
     // FIXME: Right now, LegacyInlineTextBoxes never call addRelevantUnpaintedObject() even though they might
@@ -525,18 +526,18 @@
     bool shouldPaintSelectionForeground = haveSelection && !useCustomUnderlines;
     Vector<MarkedText> markedTexts;
     if (paintInfo.phase != PaintPhase::Selection) {
+        auto selectableRange = this->selectableRange();
+
         // The marked texts for the gaps between document markers and selection are implicitly created by subdividing the entire line.
-        auto selectableRange = this->selectableRange();
         markedTexts.append({ selectableRange.clamp(m_start), selectableRange.clamp(end()), MarkedText::Unmarked });
+        
         if (!isPrinting) {
-            markedTexts.appendVector(collectMarkedTextsForDocumentMarkers(TextPaintPhase::Foreground));
-            auto highlightMarkedTexts = collectMarkedTextsForHighlights(TextPaintPhase::Foreground);
-            if (!highlightMarkedTexts.isEmpty())
-                markedTexts.appendVector(WTFMove(highlightMarkedTexts));
+            markedTexts.appendVector(MarkedText::collectForDocumentMarkers(renderer(), selectableRange, MarkedText::PaintPhase::Foreground));
+            markedTexts.appendVector(MarkedText::collectForHighlights(renderer(), parent()->renderer(), selectableRange, MarkedText::PaintPhase::Foreground));
 
             bool shouldPaintDraggedContent = !(paintInfo.paintBehavior.contains(PaintBehavior::ExcludeSelection));
             if (shouldPaintDraggedContent) {
-                auto markedTextsForDraggedContent = collectMarkedTextsForDraggedContent();
+                auto markedTextsForDraggedContent = MarkedText::collectForDraggedContent(renderer(), selectableRange);
                 if (!markedTextsForDraggedContent.isEmpty()) {
                     shouldPaintSelectionForeground = false;
                     markedTexts.appendVector(markedTextsForDraggedContent);
@@ -564,11 +565,11 @@
     // Coalesce styles of adjacent marked texts to minimize the number of drawing commands.
     auto coalescedStyledMarkedTexts = coalesceAdjacentMarkedTexts(styledMarkedTexts, &MarkedTextStyle::areForegroundMarkedTextStylesEqual);
 
-    paintMarkedTexts(paintInfo, TextPaintPhase::Foreground, boxRect, coalescedStyledMarkedTexts);
+    paintMarkedTexts(paintInfo, MarkedText::PaintPhase::Foreground, boxRect, coalescedStyledMarkedTexts);
 
     // Paint decorations
     auto textDecorations = lineStyle.textDecorationsInEffect();
-    bool highlightDecorations = !collectMarkedTextsForHighlights(TextPaintPhase::Decoration).isEmpty();
+    bool highlightDecorations = !MarkedText::collectForHighlights(renderer(), parent()->renderer(), selectableRange(), MarkedText::PaintPhase::Decoration).isEmpty();
     bool lineDecorations = !textDecorations.isEmpty();
     if ((lineDecorations || highlightDecorations) && paintInfo.phase != PaintPhase::Selection) {
         TextRun textRun = createTextRun();
@@ -603,7 +604,7 @@
         // Coalesce styles of adjacent marked texts to minimize the number of drawing commands.
         auto coalescedStyledMarkedTexts = coalesceAdjacentMarkedTexts(styledMarkedTexts, &MarkedTextStyle::areDecorationMarkedTextStylesEqual);
 
-        paintMarkedTexts(paintInfo, TextPaintPhase::Decoration, boxRect, coalescedStyledMarkedTexts, textDecorationSelectionClipOutRect);
+        paintMarkedTexts(paintInfo, MarkedText::PaintPhase::Decoration, boxRect, coalescedStyledMarkedTexts, textDecorationSelectionClipOutRect);
     }
 
     // 3. Paint fancy decorations, including composition underlines and platform-specific underlines for spelling errors, grammar errors, et cetera.
@@ -649,20 +650,16 @@
     return renderer().view().selection().rangeForTextBox(renderer(), selectableRange());
 }
 
-std::pair<unsigned, unsigned> LegacyInlineTextBox::highlightStartEnd(HighlightData& rangeData) const
-{
-    return rangeData.rangeForTextBox(renderer(), selectableRange());
-}
-
 bool LegacyInlineTextBox::hasMarkers() const
 {
-    return collectMarkedTextsForDocumentMarkers(TextPaintPhase::Decoration).size();
+    return MarkedText::collectForDocumentMarkers(renderer(), selectableRange(), MarkedText::PaintPhase::Decoration).size();
 }
 
 void LegacyInlineTextBox::paintPlatformDocumentMarkers(GraphicsContext& context, const FloatPoint& boxOrigin)
 {
     // This must match calculateUnionOfAllDocumentMarkerBounds().
-    for (auto& markedText : subdivide(collectMarkedTextsForDocumentMarkers(TextPaintPhase::Decoration), OverlapStrategy::Frontmost))
+    auto markedTexts = MarkedText::collectForDocumentMarkers(renderer(), selectableRange(), MarkedText::PaintPhase::Decoration);
+    for (auto& markedText : MarkedText::subdivide(markedTexts, MarkedText::OverlapStrategy::Frontmost))
         paintPlatformDocumentMarker(context, boxOrigin, markedText);
 }
 
@@ -670,7 +667,8 @@
 {
     // This must match paintPlatformDocumentMarkers().
     FloatRect result;
-    for (auto& markedText : subdivide(collectMarkedTextsForDocumentMarkers(TextPaintPhase::Decoration), OverlapStrategy::Frontmost))
+    auto markedTexts = MarkedText::collectForDocumentMarkers(renderer(), selectableRange(), MarkedText::PaintPhase::Decoration);
+    for (auto& markedText : MarkedText::subdivide(markedTexts, MarkedText::OverlapStrategy::Frontmost))
         result = unionRect(result, calculateDocumentMarkerBounds(markedText));
     return result;
 }
@@ -731,174 +729,6 @@
     context.drawDotsForDocumentMarker(bounds, lineStyleForMarkedTextType());
 }
 
-Vector<MarkedText> LegacyInlineTextBox::collectMarkedTextsForDraggedContent()
-{
-    using DraggendContentRange = std::pair<unsigned, unsigned>;
-    auto draggedContentRanges = renderer().draggedContentRangesBetweenOffsets(m_start, m_start + m_len);
-
-    Vector<MarkedText> result = draggedContentRanges.map([this] (const DraggendContentRange& range) -> MarkedText {
-        auto [clampedStart, clampedEnd] = selectableRange().clamp(range.first, range.second);
-        return { clampedStart, clampedEnd, MarkedText::DraggedContent };
-    });
-    return result;
-}
-
-Vector<MarkedText> LegacyInlineTextBox::collectMarkedTextsForDocumentMarkers(TextPaintPhase phase) const
-{
-    ASSERT_ARG(phase, phase == TextPaintPhase::Background || phase == TextPaintPhase::Foreground || phase == TextPaintPhase::Decoration);
-
-    if (!renderer().textNode())
-        return { };
-
-    Vector<RenderedDocumentMarker*> markers = renderer().document().markers().markersFor(*renderer().textNode());
-
-    auto markedTextTypeForMarkerType = [] (DocumentMarker::MarkerType type) {
-        switch (type) {
-        case DocumentMarker::Spelling:
-            return MarkedText::SpellingError;
-        case DocumentMarker::Grammar:
-            return MarkedText::GrammarError;
-        case DocumentMarker::CorrectionIndicator:
-            return MarkedText::Correction;
-        case DocumentMarker::TextMatch:
-            return MarkedText::TextMatch;
-        case DocumentMarker::DictationAlternatives:
-            return MarkedText::DictationAlternatives;
-#if PLATFORM(IOS_FAMILY)
-        case DocumentMarker::DictationPhraseWithAlternatives:
-            return MarkedText::DictationPhraseWithAlternatives;
-#endif
-        default:
-            return MarkedText::Unmarked;
-        }
-    };
-
-    Vector<MarkedText> markedTexts;
-    markedTexts.reserveInitialCapacity(markers.size());
-
-    // Give any document markers that touch this run a chance to draw before the text has been drawn.
-    // Note end() points at the last char, not one past it like endOffset and ranges do.
-    for (auto* marker : markers) {
-        // Collect either the background markers or the foreground markers, but not both
-        switch (marker->type()) {
-        case DocumentMarker::Grammar:
-        case DocumentMarker::Spelling:
-        case DocumentMarker::CorrectionIndicator:
-        case DocumentMarker::Replacement:
-        case DocumentMarker::DictationAlternatives:
-#if PLATFORM(IOS_FAMILY)
-        // FIXME: Remove the PLATFORM(IOS_FAMILY)-guard.
-        case DocumentMarker::DictationPhraseWithAlternatives:
-#endif
-            if (phase != TextPaintPhase::Decoration)
-                continue;
-            break;
-        case DocumentMarker::TextMatch:
-            if (!renderer().frame().editor().markedTextMatchesAreHighlighted())
-                continue;
-            if (phase == TextPaintPhase::Decoration)
-                continue;
-            break;
-#if ENABLE(TELEPHONE_NUMBER_DETECTION)
-        case DocumentMarker::TelephoneNumber:
-            if (!renderer().frame().editor().markedTextMatchesAreHighlighted())
-                continue;
-            if (phase != TextPaintPhase::Background)
-                continue;
-            break;
-#endif
-        default:
-            continue;
-        }
-
-        if (marker->endOffset() <= start()) {
-            // Marker is completely before this run. This might be a marker that sits before the
-            // first run we draw, or markers that were within runs we skipped due to truncation.
-            continue;
-        }
-
-        if (marker->startOffset() >= end()) {
-            // Marker is completely after this run, bail. A later run will paint it.
-            break;
-        }
-
-        // Marker intersects this run. Collect it.
-        switch (marker->type()) {
-        case DocumentMarker::Spelling:
-        case DocumentMarker::CorrectionIndicator:
-        case DocumentMarker::DictationAlternatives:
-        case DocumentMarker::Grammar:
-#if PLATFORM(IOS_FAMILY)
-        // FIXME: See <rdar://problem/8933352>. Also, remove the PLATFORM(IOS_FAMILY)-guard.
-        case DocumentMarker::DictationPhraseWithAlternatives:
-#endif
-        case DocumentMarker::TextMatch: {
-            auto [clampedStart, clampedEnd] = selectableRange().clamp(marker->startOffset(), marker->endOffset());
-            markedTexts.uncheckedAppend({ clampedStart, clampedEnd, markedTextTypeForMarkerType(marker->type()), marker });
-            break;
-        }
-        case DocumentMarker::Replacement:
-            break;
-#if ENABLE(TELEPHONE_NUMBER_DETECTION)
-        case DocumentMarker::TelephoneNumber:
-            break;
-#endif
-        default:
-            ASSERT_NOT_REACHED();
-        }
-    }
-    return markedTexts;
-}
-
-Vector<MarkedText> LegacyInlineTextBox::collectMarkedTextsForHighlights(TextPaintPhase phase) const
-{
-    ASSERT_ARG(phase, phase == TextPaintPhase::Background || phase == TextPaintPhase::Foreground || phase == TextPaintPhase::Decoration);
-    UNUSED_PARAM(phase);
-    if (!renderer().textNode())
-        return { };
-
-    Vector<MarkedText> markedTexts;
-    HighlightData highlightData;
-    if (RuntimeEnabledFeatures::sharedFeatures().highlightAPIEnabled()) {
-        auto& parentRenderer = parent()->renderer();
-        auto& parentStyle = parentRenderer.style();
-        if (auto highlightRegister = renderer().document().highlightRegisterIfExists()) {
-            for (auto& highlight : highlightRegister->map()) {
-                auto renderStyle = parentRenderer.getUncachedPseudoStyle({ PseudoId::Highlight, highlight.key }, &parentStyle);
-                if (!renderStyle)
-                    continue;
-                if (renderStyle->textDecorationsInEffect().isEmpty() && phase == TextPaintPhase::Decoration)
-                    continue;
-                for (auto& rangeData : highlight.value->rangesData()) {
-                    if (!highlightData.setRenderRange(rangeData))
-                        continue;
-
-                    auto [highlightStart, highlightEnd] = highlightStartEnd(highlightData);
-                    if (highlightStart < highlightEnd)
-                        markedTexts.append({ highlightStart, highlightEnd, MarkedText::Highlight, nullptr, highlight.key });
-                }
-            }
-        }
-    }
-#if ENABLE(APP_HIGHLIGHTS)
-    if (auto appHighlightRegister = renderer().document().appHighlightRegisterIfExists()) {
-        if (appHighlightRegister->highlightsVisibility() == HighlightVisibility::Visible) {
-            for (auto& highlight : appHighlightRegister->map()) {
-                for (auto& rangeData : highlight.value->rangesData()) {
-                    if (!highlightData.setRenderRange(rangeData))
-                        continue;
-
-                    auto [highlightStart, highlightEnd] = highlightStartEnd(highlightData);
-                    if (highlightStart < highlightEnd)
-                        markedTexts.append({ highlightStart, highlightEnd, MarkedText::AppHighlight });
-                }
-            }
-        }
-    }
-#endif
-    return markedTexts;
-}
-
 FloatPoint LegacyInlineTextBox::textOriginFromBoxRect(const FloatRect& boxRect) const
 {
     FloatPoint textOrigin { boxRect.x(), boxRect.y() + lineFont().fontMetrics().ascent() };
@@ -913,18 +743,18 @@
     return textOrigin;
 }
 
-void LegacyInlineTextBox::paintMarkedTexts(PaintInfo& paintInfo, TextPaintPhase phase, const FloatRect& boxRect, const Vector<StyledMarkedText>& markedTexts, const FloatRect& decorationClipOutRect)
+void LegacyInlineTextBox::paintMarkedTexts(PaintInfo& paintInfo, MarkedText::PaintPhase phase, const FloatRect& boxRect, const Vector<StyledMarkedText>& markedTexts, const FloatRect& decorationClipOutRect)
 {
     switch (phase) {
-    case TextPaintPhase::Background:
+    case MarkedText::PaintPhase::Background:
         for (auto& markedText : markedTexts)
             paintMarkedTextBackground(paintInfo, boxRect.location(), markedText.style.backgroundColor, markedText.startOffset, markedText.endOffset);
         return;
-    case TextPaintPhase::Foreground:
+    case MarkedText::PaintPhase::Foreground:
         for (auto& markedText : markedTexts)
             paintMarkedTextForeground(paintInfo, boxRect, markedText);
         return;
-    case TextPaintPhase::Decoration:
+    case MarkedText::PaintPhase::Decoration:
         for (auto& markedText : markedTexts)
             paintMarkedTextDecoration(paintInfo, boxRect, decorationClipOutRect, markedText);
         return;

Modified: trunk/Source/WebCore/rendering/LegacyInlineTextBox.h (278620 => 278621)


--- trunk/Source/WebCore/rendering/LegacyInlineTextBox.h	2021-06-08 18:01:31 UTC (rev 278620)
+++ trunk/Source/WebCore/rendering/LegacyInlineTextBox.h	2021-06-08 18:02:20 UTC (rev 278621)
@@ -23,6 +23,7 @@
 #pragma once
 
 #include "LegacyInlineBox.h"
+#include "MarkedText.h"
 #include "RenderText.h"
 #include "TextRun.h"
 
@@ -123,7 +124,6 @@
     virtual LayoutRect localSelectionRect(unsigned startPos, unsigned endPos) const;
     bool isSelectable(unsigned startPosition, unsigned endPosition) const;
     std::pair<unsigned, unsigned> selectionStartEnd() const;
-    std::pair<unsigned, unsigned> highlightStartEnd(HighlightData&) const;
 
 protected:
     void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) override;
@@ -163,15 +163,9 @@
     FloatRect calculateDocumentMarkerBounds(const MarkedText&) const;
 
 private:
-    enum class TextPaintPhase { Background, Foreground, Decoration };
-
-    Vector<MarkedText> collectMarkedTextsForDraggedContent();
-    Vector<MarkedText> collectMarkedTextsForDocumentMarkers(TextPaintPhase) const;
-    Vector<MarkedText> collectMarkedTextsForHighlights(TextPaintPhase) const;
-
     FloatPoint textOriginFromBoxRect(const FloatRect&) const;
 
-    void paintMarkedTexts(PaintInfo&, TextPaintPhase, const FloatRect& boxRect, const Vector<StyledMarkedText>&, const FloatRect& decorationClipOutRect = { });
+    void paintMarkedTexts(PaintInfo&, MarkedText::PaintPhase, const FloatRect& boxRect, const Vector<StyledMarkedText>&, const FloatRect& decorationClipOutRect = { });
 
     void paintPlatformDocumentMarker(GraphicsContext&, const FloatPoint& boxOrigin, const MarkedText&);
     void paintPlatformDocumentMarkers(GraphicsContext&, const FloatPoint& boxOrigin);

Modified: trunk/Source/WebCore/rendering/MarkedText.cpp (278620 => 278621)


--- trunk/Source/WebCore/rendering/MarkedText.cpp	2021-06-08 18:01:31 UTC (rev 278620)
+++ trunk/Source/WebCore/rendering/MarkedText.cpp	2021-06-08 18:02:20 UTC (rev 278621)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2021 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,12 +26,21 @@
 #include "config.h"
 #include "MarkedText.h"
 
+#include "Document.h"
+#include "DocumentMarkerController.h"
+#include "Editor.h"
+#include "ElementRuleCollector.h"
+#include "HighlightRegister.h"
+#include "RenderBoxModelObject.h"
+#include "RenderText.h"
+#include "RenderedDocumentMarker.h"
+#include "RuntimeEnabledFeatures.h"
 #include <algorithm>
 #include <wtf/HashSet.h>
 
 namespace WebCore {
 
-Vector<MarkedText> subdivide(const Vector<MarkedText>& markedTexts, OverlapStrategy overlapStrategy)
+Vector<MarkedText> MarkedText::subdivide(const Vector<MarkedText>& markedTexts, OverlapStrategy overlapStrategy)
 {
     if (markedTexts.isEmpty())
         return { };
@@ -93,6 +102,161 @@
     return result;
 }
 
+Vector<MarkedText> MarkedText::collectForHighlights(RenderText& renderer, RenderBoxModelObject& parentRenderer, const TextBoxSelectableRange& selectableRange, PaintPhase phase)
+{
+    Vector<MarkedText> markedTexts;
+    HighlightData highlightData;
+    if (RuntimeEnabledFeatures::sharedFeatures().highlightAPIEnabled()) {
+        auto& parentStyle = parentRenderer.style();
+        if (auto highlightRegister = renderer.document().highlightRegisterIfExists()) {
+            for (auto& highlight : highlightRegister->map()) {
+                auto renderStyle = parentRenderer.getUncachedPseudoStyle({ PseudoId::Highlight, highlight.key }, &parentStyle);
+                if (!renderStyle)
+                    continue;
+                if (renderStyle->textDecorationsInEffect().isEmpty() && phase == PaintPhase::Decoration)
+                    continue;
+                for (auto& rangeData : highlight.value->rangesData()) {
+                    if (!highlightData.setRenderRange(rangeData))
+                        continue;
+
+                    auto [highlightStart, highlightEnd] = highlightData.rangeForTextBox(renderer, selectableRange);
+                    if (highlightStart < highlightEnd)
+                        markedTexts.append({ highlightStart, highlightEnd, MarkedText::Highlight, nullptr, highlight.key });
+                }
+            }
+        }
+    }
+#if ENABLE(APP_HIGHLIGHTS)
+    if (auto appHighlightRegister = renderer.document().appHighlightRegisterIfExists()) {
+        if (appHighlightRegister->highlightsVisibility() == HighlightVisibility::Visible) {
+            for (auto& highlight : appHighlightRegister->map()) {
+                for (auto& rangeData : highlight.value->rangesData()) {
+                    if (!highlightData.setRenderRange(rangeData))
+                        continue;
+
+                    auto [highlightStart, highlightEnd] = highlightData.rangeForTextBox(renderer, selectableRange);
+                    if (highlightStart < highlightEnd)
+                        markedTexts.append({ highlightStart, highlightEnd, MarkedText::AppHighlight });
+                }
+            }
+        }
+    }
+#endif
+    return markedTexts;
 }
 
+Vector<MarkedText> MarkedText::collectForDocumentMarkers(RenderText& renderer, const TextBoxSelectableRange& selectableRange, PaintPhase phase)
+{
+    if (!renderer.textNode())
+        return { };
 
+    Vector<RenderedDocumentMarker*> markers = renderer.document().markers().markersFor(*renderer.textNode());
+
+    auto markedTextTypeForMarkerType = [] (DocumentMarker::MarkerType type) {
+        switch (type) {
+        case DocumentMarker::Spelling:
+            return MarkedText::SpellingError;
+        case DocumentMarker::Grammar:
+            return MarkedText::GrammarError;
+        case DocumentMarker::CorrectionIndicator:
+            return MarkedText::Correction;
+        case DocumentMarker::TextMatch:
+            return MarkedText::TextMatch;
+        case DocumentMarker::DictationAlternatives:
+            return MarkedText::DictationAlternatives;
+#if PLATFORM(IOS_FAMILY)
+        case DocumentMarker::DictationPhraseWithAlternatives:
+            return MarkedText::DictationPhraseWithAlternatives;
+#endif
+        default:
+            return MarkedText::Unmarked;
+        }
+    };
+
+    Vector<MarkedText> markedTexts;
+    markedTexts.reserveInitialCapacity(markers.size());
+
+    // Give any document markers that touch this run a chance to draw before the text has been drawn.
+    // Note end() points at the last char, not one past it like endOffset and ranges do.
+    for (auto* marker : markers) {
+        // Collect either the background markers or the foreground markers, but not both
+        switch (marker->type()) {
+        case DocumentMarker::Grammar:
+        case DocumentMarker::Spelling:
+        case DocumentMarker::CorrectionIndicator:
+        case DocumentMarker::Replacement:
+        case DocumentMarker::DictationAlternatives:
+#if PLATFORM(IOS_FAMILY)
+        // FIXME: Remove the PLATFORM(IOS_FAMILY)-guard.
+        case DocumentMarker::DictationPhraseWithAlternatives:
+#endif
+            if (phase != MarkedText::PaintPhase::Decoration)
+                continue;
+            break;
+        case DocumentMarker::TextMatch:
+            if (!renderer.frame().editor().markedTextMatchesAreHighlighted())
+                continue;
+            if (phase == MarkedText::PaintPhase::Decoration)
+                continue;
+            break;
+#if ENABLE(TELEPHONE_NUMBER_DETECTION)
+        case DocumentMarker::TelephoneNumber:
+            if (!renderer.frame().editor().markedTextMatchesAreHighlighted())
+                continue;
+            if (phase != MarkedText::PaintPhase::Background)
+                continue;
+            break;
+#endif
+        default:
+            continue;
+        }
+
+        if (marker->endOffset() <= selectableRange.start) {
+            // Marker is completely before this run. This might be a marker that sits before the
+            // first run we draw, or markers that were within runs we skipped due to truncation.
+            continue;
+        }
+
+        if (marker->startOffset() >= selectableRange.start + selectableRange.length) {
+            // Marker is completely after this run, bail. A later run will paint it.
+            break;
+        }
+
+        // Marker intersects this run. Collect it.
+        switch (marker->type()) {
+        case DocumentMarker::Spelling:
+        case DocumentMarker::CorrectionIndicator:
+        case DocumentMarker::DictationAlternatives:
+        case DocumentMarker::Grammar:
+#if PLATFORM(IOS_FAMILY)
+        // FIXME: See <rdar://problem/8933352>. Also, remove the PLATFORM(IOS_FAMILY)-guard.
+        case DocumentMarker::DictationPhraseWithAlternatives:
+#endif
+        case DocumentMarker::TextMatch: {
+            auto [clampedStart, clampedEnd] = selectableRange.clamp(marker->startOffset(), marker->endOffset());
+            markedTexts.uncheckedAppend({ clampedStart, clampedEnd, markedTextTypeForMarkerType(marker->type()), marker });
+            break;
+        }
+        case DocumentMarker::Replacement:
+            break;
+#if ENABLE(TELEPHONE_NUMBER_DETECTION)
+        case DocumentMarker::TelephoneNumber:
+            break;
+#endif
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+    return markedTexts;
+}
+
+Vector<MarkedText> MarkedText::collectForDraggedContent(RenderText& renderer, const TextBoxSelectableRange& selectableRange)
+{
+    auto draggedContentRanges = renderer.draggedContentRangesBetweenOffsets(selectableRange.start, selectableRange.start + selectableRange.length);
+
+    return draggedContentRanges.map([&](const auto& range) -> MarkedText {
+        return { selectableRange.clamp(range.first), selectableRange.clamp(range.second), MarkedText::DraggedContent };
+    });
+}
+
+}

Modified: trunk/Source/WebCore/rendering/MarkedText.h (278620 => 278621)


--- trunk/Source/WebCore/rendering/MarkedText.h	2021-06-08 18:01:31 UTC (rev 278620)
+++ trunk/Source/WebCore/rendering/MarkedText.h	2021-06-08 18:02:20 UTC (rev 278621)
@@ -30,7 +30,10 @@
 
 namespace WebCore {
 
+class RenderBoxModelObject;
+class RenderText;
 class RenderedDocumentMarker;
+struct TextBoxSelectableRange;
 
 struct MarkedText {
     // Sorted by paint order
@@ -52,6 +55,18 @@
         Selection,
         DraggedContent,
     };
+
+    enum class PaintPhase {
+        Background,
+        Foreground,
+        Decoration
+    };
+
+    enum class OverlapStrategy {
+        None,
+        Frontmost
+    };
+
     unsigned startOffset;
     unsigned endOffset;
     Type type;
@@ -64,10 +79,13 @@
     {
         return startOffset == other.startOffset && endOffset == other.endOffset && type == other.type && marker == other.marker && highlightName == other.highlightName;
     }
+
+    WEBCORE_EXPORT static Vector<MarkedText> subdivide(const Vector<MarkedText>&, OverlapStrategy = OverlapStrategy::None);
+
+    static Vector<MarkedText> collectForDocumentMarkers(RenderText&, const TextBoxSelectableRange&, PaintPhase);
+    static Vector<MarkedText> collectForHighlights(RenderText&, RenderBoxModelObject& parentRenderer, const TextBoxSelectableRange&, PaintPhase);
+    static Vector<MarkedText> collectForDraggedContent(RenderText&, const TextBoxSelectableRange&);
 };
 
-enum class OverlapStrategy { None, Frontmost };
-WEBCORE_EXPORT Vector<MarkedText> subdivide(const Vector<MarkedText>&, OverlapStrategy = OverlapStrategy::None);
-
 }
 

Modified: trunk/Source/WebCore/rendering/MarkedTextStyle.cpp (278620 => 278621)


--- trunk/Source/WebCore/rendering/MarkedTextStyle.cpp	2021-06-08 18:01:31 UTC (rev 278620)
+++ trunk/Source/WebCore/rendering/MarkedTextStyle.cpp	2021-06-08 18:02:20 UTC (rev 278621)
@@ -131,7 +131,7 @@
         return { styledMarkedText };
     }
 
-    auto markedTexts = subdivide(textsToSubdivide);
+    auto markedTexts = MarkedText::subdivide(textsToSubdivide);
     ASSERT(!markedTexts.isEmpty());
     if (UNLIKELY(markedTexts.isEmpty()))
         return { };

Modified: trunk/Tools/ChangeLog (278620 => 278621)


--- trunk/Tools/ChangeLog	2021-06-08 18:01:31 UTC (rev 278620)
+++ trunk/Tools/ChangeLog	2021-06-08 18:02:20 UTC (rev 278621)
@@ -1,3 +1,13 @@
+2021-06-08  Antti Koivisto  <[email protected]>
+
+        Factor MarkedText collection out of LegacyInlineTextBox
+        https://bugs.webkit.org/show_bug.cgi?id=226731
+
+        Reviewed by Sam Weinig.
+
+        * TestWebKitAPI/Tests/WebCore/MarkedText.cpp:
+        (TestWebKitAPI::TEST):
+
 2021-06-08  Sam Weinig  <[email protected]>
 
         Add copy of std::span so that we can use it pre-moving to c++20

Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/MarkedText.cpp (278620 => 278621)


--- trunk/Tools/TestWebKitAPI/Tests/WebCore/MarkedText.cpp	2021-06-08 18:01:31 UTC (rev 278620)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/MarkedText.cpp	2021-06-08 18:02:20 UTC (rev 278621)
@@ -80,14 +80,14 @@
 
 TEST(MarkedText, SubdivideEmpty)
 {
-    EXPECT_EQ(0U, subdivide({ }).size());
-    EXPECT_EQ(0U, subdivide({ }, OverlapStrategy::Frontmost).size());
+    EXPECT_EQ(0U, MarkedText::subdivide({ }).size());
+    EXPECT_EQ(0U, MarkedText::subdivide({ }, MarkedText::OverlapStrategy::Frontmost).size());
 }
 
 TEST(MarkedText, SubdivideSimple)
 {
     MarkedText markedText { 0, 9, MarkedText::SpellingError };
-    auto results = subdivide({ markedText });
+    auto results = MarkedText::subdivide({ markedText });
     ASSERT_EQ(1U, results.size());
     EXPECT_EQ(markedText, results[0]);
 }
@@ -99,7 +99,7 @@
         MarkedText { grammarErrorMarker.startOffset(), grammarErrorMarker.endOffset(), MarkedText::GrammarError, &grammarErrorMarker },
         MarkedText { 22, 32, MarkedText::SpellingError },
     };
-    auto results = subdivide(expectedMarkedTexts);
+    auto results = MarkedText::subdivide(expectedMarkedTexts);
     ASSERT_EQ(expectedMarkedTexts.size(), results.size());
     for (size_t i = 0; i < expectedMarkedTexts.size(); ++i)
         EXPECT_EQ(expectedMarkedTexts[i], results[i]);
@@ -122,7 +122,7 @@
         MarkedText { 20, 40, MarkedText::SpellingError },
         MarkedText { 41, 45, MarkedText::SpellingError },
     };
-    auto results = subdivide(markedTexts);
+    auto results = MarkedText::subdivide(markedTexts);
     ASSERT_EQ(expectedMarkedTexts.size(), results.size());
     for (size_t i = 0; i < expectedMarkedTexts.size(); ++i)
         EXPECT_EQ(expectedMarkedTexts[i], results[i]);
@@ -143,7 +143,7 @@
         MarkedText { 20, 40, MarkedText::SpellingError },
         MarkedText { 41, 45, MarkedText::SpellingError },
     };
-    auto results = subdivide(markedTexts, OverlapStrategy::Frontmost);
+    auto results = MarkedText::subdivide(markedTexts, MarkedText::OverlapStrategy::Frontmost);
     ASSERT_EQ(expectedMarkedTexts.size(), results.size());
     for (size_t i = 0; i < expectedMarkedTexts.size(); ++i)
         EXPECT_EQ(expectedMarkedTexts[i], results[i]);
@@ -174,7 +174,7 @@
         MarkedText { 51, 58, MarkedText::SpellingError },
         MarkedText { 59, 63, MarkedText::GrammarError },
     };
-    auto results = subdivide(markedTexts, OverlapStrategy::Frontmost);
+    auto results = MarkedText::subdivide(markedTexts, MarkedText::OverlapStrategy::Frontmost);
     ASSERT_EQ(expectedMarkedTexts.size(), results.size());
     for (size_t i = 0; i < expectedMarkedTexts.size(); ++i)
         EXPECT_EQ(expectedMarkedTexts[i], results[i]);
@@ -195,7 +195,7 @@
         MarkedText { 50, 60, MarkedText::GrammarError },
         MarkedText { 50, 60, MarkedText::Selection },
     };
-    auto results = subdivide(markedTexts);
+    auto results = MarkedText::subdivide(markedTexts);
     ASSERT_EQ(expectedMarkedTexts.size(), results.size());
     for (size_t i = 0; i < expectedMarkedTexts.size(); ++i)
         EXPECT_EQ(expectedMarkedTexts[i], results[i]);
@@ -214,7 +214,7 @@
         MarkedText { 40, 50, MarkedText::Selection },
         MarkedText { 50, 60, MarkedText::Selection },
     };
-    auto results = subdivide(markedTexts, OverlapStrategy::Frontmost);
+    auto results = MarkedText::subdivide(markedTexts, MarkedText::OverlapStrategy::Frontmost);
     ASSERT_EQ(expectedMarkedTexts.size(), results.size());
     for (size_t i = 0; i < expectedMarkedTexts.size(); ++i)
         EXPECT_EQ(expectedMarkedTexts[i], results[i]);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to