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]);