Title: [278545] trunk/Source/WebCore
Revision
278545
Author
[email protected]
Date
2021-06-06 23:19:03 -0700 (Sun, 06 Jun 2021)

Log Message

Factor selection clamping into a type
https://bugs.webkit.org/show_bug.cgi?id=226697

Reviewed by Sam Weinig.

TextBoxSelectableRange will be helpful for moving selection code out of the legacy inline boxes.
It also allows some code sharing already in this patch.

* Headers.cmake:
* WebCore.xcodeproj/project.pbxproj:
* layout/integration/LayoutIntegrationRunIteratorLegacyPath.h:
(WebCore::LayoutIntegration::RunIteratorLegacyPath::isSelectable const):
* layout/integration/LayoutIntegrationRunIteratorModernPath.h:
(WebCore::LayoutIntegration::RunIteratorModernPath::positionForOffset const):
(WebCore::LayoutIntegration::RunIteratorModernPath::isSelectable const):
(WebCore::LayoutIntegration::RunIteratorModernPath::selectionRect const):
(WebCore::LayoutIntegration::RunIteratorModernPath::selectableRange const):
(WebCore::LayoutIntegration::RunIteratorModernPath::clampedOffset const): Deleted.
* rendering/LegacyInlineTextBox.cpp:
(WebCore::LegacyInlineTextBox::isSelectable const):
(WebCore::LegacyInlineTextBox::localSelectionRect const):
(WebCore::LegacyInlineTextBox::paint):
(WebCore::LegacyInlineTextBox::selectableRange const):
(WebCore::LegacyInlineTextBox::clampedStartEndForState const):
(WebCore::LegacyInlineTextBox::calculateDocumentMarkerBounds const):
(WebCore::LegacyInlineTextBox::collectMarkedTextsForDraggedContent):
(WebCore::LegacyInlineTextBox::collectMarkedTextsForDocumentMarkers const):
(WebCore::LegacyInlineTextBox::paintCompositionBackground):
(WebCore::LegacyInlineTextBox::positionForOffset const):
(WebCore::LegacyInlineTextBox::isSelected const): Deleted.
(WebCore::LegacyInlineTextBox::clampedOffset const): Deleted.
* rendering/LegacyInlineTextBox.h:
* rendering/RenderBlockFlow.cpp:
(WebCore::RenderBlockFlow::inlineSelectionGaps):
* rendering/TextBoxSelectableRange.h: Added.
(WebCore::TextBoxSelectableRange::clamp const):
(WebCore::TextBoxSelectableRange::intersects const):
* rendering/svg/SVGInlineTextBox.cpp:
(WebCore::SVGInlineTextBox::localSelectionRect const):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (278544 => 278545)


--- trunk/Source/WebCore/ChangeLog	2021-06-07 06:16:22 UTC (rev 278544)
+++ trunk/Source/WebCore/ChangeLog	2021-06-07 06:19:03 UTC (rev 278545)
@@ -1,3 +1,45 @@
+2021-06-06  Antti Koivisto  <[email protected]>
+
+        Factor selection clamping into a type
+        https://bugs.webkit.org/show_bug.cgi?id=226697
+
+        Reviewed by Sam Weinig.
+
+        TextBoxSelectableRange will be helpful for moving selection code out of the legacy inline boxes.
+        It also allows some code sharing already in this patch.
+
+        * Headers.cmake:
+        * WebCore.xcodeproj/project.pbxproj:
+        * layout/integration/LayoutIntegrationRunIteratorLegacyPath.h:
+        (WebCore::LayoutIntegration::RunIteratorLegacyPath::isSelectable const):
+        * layout/integration/LayoutIntegrationRunIteratorModernPath.h:
+        (WebCore::LayoutIntegration::RunIteratorModernPath::positionForOffset const):
+        (WebCore::LayoutIntegration::RunIteratorModernPath::isSelectable const):
+        (WebCore::LayoutIntegration::RunIteratorModernPath::selectionRect const):
+        (WebCore::LayoutIntegration::RunIteratorModernPath::selectableRange const):
+        (WebCore::LayoutIntegration::RunIteratorModernPath::clampedOffset const): Deleted.
+        * rendering/LegacyInlineTextBox.cpp:
+        (WebCore::LegacyInlineTextBox::isSelectable const):
+        (WebCore::LegacyInlineTextBox::localSelectionRect const):
+        (WebCore::LegacyInlineTextBox::paint):
+        (WebCore::LegacyInlineTextBox::selectableRange const):
+        (WebCore::LegacyInlineTextBox::clampedStartEndForState const):
+        (WebCore::LegacyInlineTextBox::calculateDocumentMarkerBounds const):
+        (WebCore::LegacyInlineTextBox::collectMarkedTextsForDraggedContent):
+        (WebCore::LegacyInlineTextBox::collectMarkedTextsForDocumentMarkers const):
+        (WebCore::LegacyInlineTextBox::paintCompositionBackground):
+        (WebCore::LegacyInlineTextBox::positionForOffset const):
+        (WebCore::LegacyInlineTextBox::isSelected const): Deleted.
+        (WebCore::LegacyInlineTextBox::clampedOffset const): Deleted.
+        * rendering/LegacyInlineTextBox.h:
+        * rendering/RenderBlockFlow.cpp:
+        (WebCore::RenderBlockFlow::inlineSelectionGaps):
+        * rendering/TextBoxSelectableRange.h: Added.
+        (WebCore::TextBoxSelectableRange::clamp const):
+        (WebCore::TextBoxSelectableRange::intersects const):
+        * rendering/svg/SVGInlineTextBox.cpp:
+        (WebCore::SVGInlineTextBox::localSelectionRect const):
+
 2021-06-06  Chris Dumez  <[email protected]>
 
         Drop MainThreadTaskDispatcher and use callOnMainThread() instead

Modified: trunk/Source/WebCore/Headers.cmake (278544 => 278545)


--- trunk/Source/WebCore/Headers.cmake	2021-06-07 06:16:22 UTC (rev 278544)
+++ trunk/Source/WebCore/Headers.cmake	2021-06-07 06:19:03 UTC (rev 278545)
@@ -1580,6 +1580,7 @@
     rendering/RenderWidget.h
     rendering/ScrollAlignment.h
     rendering/SelectionRangeData.h
+    rendering/TextBoxSelectableRange.h
 
     rendering/line/LineWidth.h
     rendering/line/TrailingObjects.h

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (278544 => 278545)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-06-07 06:16:22 UTC (rev 278544)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-06-07 06:19:03 UTC (rev 278545)
@@ -5212,6 +5212,7 @@
 		E446143A0CD689C800FADA75 /* JSHTMLMediaElement.h in Headers */ = {isa = PBXBuildFile; fileRef = E4B423800CBFB73C00AF2ECE /* JSHTMLMediaElement.h */; };
 		E446143C0CD689CC00FADA75 /* JSHTMLSourceElement.h in Headers */ = {isa = PBXBuildFile; fileRef = E4B423720CBFB6E000AF2ECE /* JSHTMLSourceElement.h */; };
 		E44614520CD68A3500FADA75 /* RenderVideo.h in Headers */ = {isa = PBXBuildFile; fileRef = E4B41E340CBFB60900AF2ECE /* RenderVideo.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		E447F5B3266CF63D00133F00 /* TextBoxSelectableRange.h in Headers */ = {isa = PBXBuildFile; fileRef = E447F5B1266CF63D00133F00 /* TextBoxSelectableRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E44B4BB4141650D7002B1D8B /* SelectorChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = E44B4BB2141650D7002B1D8B /* SelectorChecker.h */; };
 		E44FA1851BCA6B5A0091B6EF /* ComposedTreeIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E44FA1841BCA6B5A0091B6EF /* ComposedTreeIterator.h */; };
 		E451C6312394027900993190 /* LayoutUnits.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F73918C2106CEDD006AF262 /* LayoutUnits.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -16564,6 +16565,7 @@
 		E44614110CD6826900FADA75 /* JSMediaError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMediaError.h; sourceTree = "<group>"; };
 		E44614120CD6826900FADA75 /* JSTimeRanges.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTimeRanges.cpp; sourceTree = "<group>"; };
 		E44614130CD6826900FADA75 /* JSTimeRanges.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTimeRanges.h; sourceTree = "<group>"; };
+		E447F5B1266CF63D00133F00 /* TextBoxSelectableRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextBoxSelectableRange.h; sourceTree = "<group>"; };
 		E44B4BB1141650D7002B1D8B /* SelectorChecker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectorChecker.cpp; sourceTree = "<group>"; };
 		E44B4BB2141650D7002B1D8B /* SelectorChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectorChecker.h; sourceTree = "<group>"; };
 		E44EE3A617576E5500EEE8CF /* FontGenericFamilies.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FontGenericFamilies.cpp; sourceTree = "<group>"; };
@@ -30409,6 +30411,7 @@
 				A8CFF04C0A154F09000A4234 /* TableLayout.h */,
 				0F54DCE31881051D003EEDBB /* TextAutoSizing.cpp */,
 				0F54DCE41881051D003EEDBB /* TextAutoSizing.h */,
+				E447F5B1266CF63D00133F00 /* TextBoxSelectableRange.h */,
 				582DE3221C30C85400BE02A8 /* TextDecorationPainter.cpp */,
 				582DE3231C30C85400BE02A8 /* TextDecorationPainter.h */,
 				1C18DA56181AF6A500C4EF22 /* TextPainter.cpp */,
@@ -32468,6 +32471,7 @@
 				41FABD2D1F4DFE4A006A6C97 /* DOMCacheEngine.h in Headers */,
 				41380C291F3436AC00155FDA /* DOMCacheStorage.h in Headers */,
 				4BDA3FFE2151B6F500FD6604 /* DOMCSSCustomPropertyDescriptor.h in Headers */,
+				E447F5B3266CF63D00133F00 /* TextBoxSelectableRange.h in Headers */,
 				FC9A0F75164094CF003D6B8D /* DOMCSSNamespace.h in Headers */,
 				4B6B5CBD21640EFF00603817 /* DOMCSSPaintWorklet.h in Headers */,
 				4BDA3FFF2151B6F500FD6604 /* DOMCSSRegisterCustomProperty.h in Headers */,

Modified: trunk/Source/WebCore/layout/integration/LayoutIntegrationRunIteratorLegacyPath.h (278544 => 278545)


--- trunk/Source/WebCore/layout/integration/LayoutIntegrationRunIteratorLegacyPath.h	2021-06-07 06:16:22 UTC (rev 278544)
+++ trunk/Source/WebCore/layout/integration/LayoutIntegrationRunIteratorLegacyPath.h	2021-06-07 06:19:03 UTC (rev 278545)
@@ -74,7 +74,7 @@
     unsigned offsetForPosition(float x) const { return inlineTextBox()->offsetForPosition(x); }
     float positionForOffset(unsigned offset) const { return inlineTextBox()->positionForOffset(offset); }
 
-    bool isSelectable(unsigned start, unsigned end) const { return inlineTextBox()->isSelected(start, end); }
+    bool isSelectable(unsigned start, unsigned end) const { return inlineTextBox()->isSelectable(start, end); }
     LayoutRect selectionRect(unsigned start, unsigned end) const { return inlineTextBox()->localSelectionRect(start, end); }
 
     const RenderObject& renderer() const

Modified: trunk/Source/WebCore/layout/integration/LayoutIntegrationRunIteratorModernPath.h (278544 => 278545)


--- trunk/Source/WebCore/layout/integration/LayoutIntegrationRunIteratorModernPath.h	2021-06-07 06:16:22 UTC (rev 278544)
+++ trunk/Source/WebCore/layout/integration/LayoutIntegrationRunIteratorModernPath.h	2021-06-07 06:19:03 UTC (rev 278545)
@@ -29,6 +29,7 @@
 
 #include "FontCascade.h"
 #include "LayoutIntegrationInlineContent.h"
+#include "TextBoxSelectableRange.h"
 
 namespace WebCore {
 
@@ -91,7 +92,7 @@
         if (isLineBreak())
             return rect().x();
 
-        auto endOffset = clampedOffset(offset);
+        auto endOffset = selectableRange().clamp(offset);
 
         LayoutRect selectionRect = LayoutRect(rect().x(), 0, 0, 0);
         TextRun textRun = createTextRun(HyphenMode::Ignore);
@@ -101,13 +102,12 @@
 
     bool isSelectable(unsigned start, unsigned end) const
     {
-        return clampedOffset(start) < clampedOffset(end);
+        return selectableRange().intersects(start, end);
     }
 
     LayoutRect selectionRect(unsigned rangeStart, unsigned rangeEnd) const
     {
-        unsigned clampedStart = clampedOffset(rangeStart);
-        unsigned clampedEnd = clampedOffset(rangeEnd);
+        auto [clampedStart, clampedEnd] = selectableRange().clamp(rangeStart, rangeEnd);
 
         if (clampedStart >= clampedEnd && !(rangeStart == rangeEnd && rangeStart >= start() && rangeStart <= end()))
             return { };
@@ -204,14 +204,13 @@
 private:
     friend class RunIterator;
 
-    unsigned clampedOffset(unsigned offset) const
+    TextBoxSelectableRange selectableRange() const
     {
-        auto clampedOffset = std::max(start(), std::min(offset, end())) - start();
-        // We treat the last codepoint in this run and the hyphen as a single unit.
-        if (hasHyphen() && clampedOffset == length())
-            clampedOffset += run().style().hyphenString().length();
-
-        return clampedOffset;
+        return {
+            start(),
+            length(),
+            run().style().hyphenString().length()
+        };
     }
 
     enum class HyphenMode { Include, Ignore };

Modified: trunk/Source/WebCore/rendering/LegacyInlineTextBox.cpp (278544 => 278545)


--- trunk/Source/WebCore/rendering/LegacyInlineTextBox.cpp	2021-06-07 06:16:22 UTC (rev 278544)
+++ trunk/Source/WebCore/rendering/LegacyInlineTextBox.cpp	2021-06-07 06:19:03 UTC (rev 278545)
@@ -55,6 +55,7 @@
 #include "RuntimeEnabledFeatures.h"
 #include "Settings.h"
 #include "Text.h"
+#include "TextBoxSelectableRange.h"
 #include "TextDecorationPainter.h"
 #include "TextPaintStyle.h"
 #include "TextPainter.h"
@@ -153,9 +154,9 @@
     return root().selectionHeight();
 }
 
-bool LegacyInlineTextBox::isSelected(unsigned startPosition, unsigned endPosition) const
+bool LegacyInlineTextBox::isSelectable(unsigned startPosition, unsigned endPosition) const
 {
-    return clampedOffset(startPosition) < clampedOffset(endPosition);
+    return selectableRange().intersects(startPosition, endPosition);
 }
 
 RenderObject::HighlightState LegacyInlineTextBox::selectionState()
@@ -243,10 +244,9 @@
 // FIXME: Share more code with paintMarkedTextBackground().
 LayoutRect LegacyInlineTextBox::localSelectionRect(unsigned startPos, unsigned endPos) const
 {
-    unsigned sPos = clampedOffset(startPos);
-    unsigned ePos = clampedOffset(endPos);
+    auto [clampedStart, clampedEnd] = selectableRange().clamp(startPos, endPos);
 
-    if (sPos >= ePos && !(startPos == endPos && startPos >= start() && startPos <= (start() + len())))
+    if (clampedStart >= clampedEnd && !(startPos == endPos && startPos >= start() && startPos <= (start() + len())))
         return { };
 
     LayoutUnit selectionTop = this->selectionTop();
@@ -256,8 +256,8 @@
 
     LayoutRect selectionRect { LayoutUnit(logicalLeft()), selectionTop, LayoutUnit(logicalWidth()), selectionHeight };
     // Avoid measuring the text when the entire line box is selected as an optimization.
-    if (sPos || ePos != textRun.length())
-        lineFont().adjustSelectionRectForText(textRun, selectionRect, sPos, ePos);
+    if (clampedStart || clampedEnd != textRun.length())
+        lineFont().adjustSelectionRectForText(textRun, selectionRect, clampedStart, clampedEnd);
     // FIXME: The computation of the snapped selection rect differs from the computation of this rect
     // in paintMarkedTextBackground(). See <https://bugs.webkit.org/show_bug.cgi?id=138913>.
     return snappedSelectionRect(selectionRect, logicalRight(), selectionTop, selectionHeight, isHorizontal());
@@ -553,7 +553,8 @@
     Vector<MarkedText> markedTexts;
     if (paintInfo.phase != PaintPhase::Selection) {
         // The marked texts for the gaps between document markers and selection are implicitly created by subdividing the entire line.
-        markedTexts.append({ clampedOffset(m_start), clampedOffset(end()), MarkedText::Unmarked });
+        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);
@@ -640,35 +641,45 @@
         context.concatCTM(rotation(boxRect, Counterclockwise));
 }
 
-unsigned LegacyInlineTextBox::clampedOffset(unsigned x) const
+TextBoxSelectableRange LegacyInlineTextBox::selectableRange() const
 {
-    unsigned offset = std::max(std::min(x, m_start + m_len), m_start) - m_start;
-    if (m_truncation == cFullTruncation)
-        return offset;
-    if (m_truncation != cNoTruncation)
-        offset = std::min<unsigned>(offset, m_truncation);
-    else if (offset == m_len) {
-        // Fix up the offset if we are combined text or have a hyphen because we manage these embellishments.
-        // That is, they are not reflected in renderer().text(). We treat combined text as a single unit.
-        // We also treat the last codepoint in this box and the hyphen as a single unit.
+    // Fix up the offset if we are combined text or have a hyphen because we manage these embellishments.
+    // That is, they are not reflected in renderer().text(). We treat combined text as a single unit.
+    // We also treat the last codepoint in this box and the hyphen as a single unit.
+    auto additionalLengthAtEnd = [&] {
         if (auto* combinedText = this->combinedText())
-            offset = combinedText->combinedStringForRendering().length();
-        else if (hasHyphen())
-            offset += lineStyle().hyphenString().length();
-    }
-    return offset;
+            return combinedText->combinedStringForRendering().length() - m_len;
+        if (hasHyphen())
+            return lineStyle().hyphenString().length();
+        return 0u;
+    }();
+
+    auto truncation = [&]() -> std::optional<unsigned> {
+        if (m_truncation == cNoTruncation)
+            return { };
+        if (m_truncation == cFullTruncation)
+            return std::numeric_limits<unsigned>::max();
+        return m_truncation;
+    }();
+
+    return {
+        m_start,
+        m_len,
+        additionalLengthAtEnd,
+        truncation
+    };
 }
 
 std::pair<unsigned, unsigned> LegacyInlineTextBox::clampedStartEndForState(unsigned start, unsigned end, RenderObject::HighlightState selectionState) const
 {
     if (selectionState == RenderObject::HighlightState::Inside)
-        return { 0, clampedOffset(m_start + m_len) };
+        return { 0, selectableRange().clamp(m_start + m_len) };
     
     if (selectionState == RenderObject::HighlightState::Start)
         end = renderer().text().length();
     else if (selectionState == RenderObject::HighlightState::End)
         start = 0;
-    return { clampedOffset(start), clampedOffset(end) };
+    return selectableRange().clamp(start, end);
 }
 
 std::pair<unsigned, unsigned> LegacyInlineTextBox::selectionStartEnd() const
@@ -719,7 +730,7 @@
     auto height = 0.13247 * fontSize;
 
     // Avoid measuring the text when the entire line box is selected as an optimization.
-    if (markedText.startOffset || markedText.endOffset != clampedOffset(end())) {
+    if (markedText.startOffset || markedText.endOffset != selectableRange().clamp(end())) {
         TextRun run = createTextRun();
         LayoutRect selectionRect = LayoutRect(0, y, 0, height);
         lineFont().adjustSelectionRectForText(run, selectionRect, markedText.startOffset, markedText.endOffset);
@@ -770,8 +781,10 @@
 {
     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 {
-        return { clampedOffset(range.first), clampedOffset(range.second), MarkedText::DraggedContent };
+        auto [clampedStart, clampedEnd] = selectableRange().clamp(range.first, range.second);
+        return { clampedStart, clampedEnd, MarkedText::DraggedContent };
     });
     return result;
 }
@@ -865,9 +878,11 @@
         // FIXME: See <rdar://problem/8933352>. Also, remove the PLATFORM(IOS_FAMILY)-guard.
         case DocumentMarker::DictationPhraseWithAlternatives:
 #endif
-        case DocumentMarker::TextMatch:
-            markedTexts.uncheckedAppend({ clampedOffset(marker->startOffset()), clampedOffset(marker->endOffset()), markedTextTypeForMarkerType(marker->type()), marker });
+        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)
@@ -1101,8 +1116,10 @@
 
 void LegacyInlineTextBox::paintCompositionBackground(PaintInfo& paintInfo, const FloatPoint& boxOrigin)
 {
+    auto selectableRange = this->selectableRange();
+
     if (!renderer().frame().editor().compositionUsesCustomHighlights()) {
-        paintMarkedTextBackground(paintInfo, boxOrigin, CompositionHighlight::defaultCompositionFillColor, clampedOffset(renderer().frame().editor().compositionStart()), clampedOffset(renderer().frame().editor().compositionEnd()));
+        paintMarkedTextBackground(paintInfo, boxOrigin, CompositionHighlight::defaultCompositionFillColor, selectableRange.clamp(renderer().frame().editor().compositionStart()), selectableRange.clamp(renderer().frame().editor().compositionEnd()));
         return;
     }
 
@@ -1113,7 +1130,8 @@
         if (highlight.startOffset >= end())
             break;
 
-        paintMarkedTextBackground(paintInfo, boxOrigin, highlight.color, clampedOffset(highlight.startOffset), clampedOffset(highlight.endOffset), MarkedTextBackgroundStyle::Rounded);
+        auto [clampedStart, clampedEnd] = selectableRange.clamp(highlight.startOffset, highlight.endOffset);
+        paintMarkedTextBackground(paintInfo, boxOrigin, highlight.color, clampedStart, clampedEnd, MarkedTextBackgroundStyle::Rounded);
 
         if (highlight.endOffset > end())
             break;
@@ -1243,9 +1261,9 @@
     unsigned endOffset;
     if (isLeftToRightDirection()) {
         startOffset = 0;
-        endOffset = clampedOffset(offset);
+        endOffset = selectableRange().clamp(offset);
     } else {
-        startOffset = clampedOffset(offset);
+        startOffset = selectableRange().clamp(offset);
         endOffset = m_len;
     }
 

Modified: trunk/Source/WebCore/rendering/LegacyInlineTextBox.h (278544 => 278545)


--- trunk/Source/WebCore/rendering/LegacyInlineTextBox.h	2021-06-07 06:16:22 UTC (rev 278544)
+++ trunk/Source/WebCore/rendering/LegacyInlineTextBox.h	2021-06-07 06:19:03 UTC (rev 278545)
@@ -34,6 +34,7 @@
 struct CompositionUnderline;
 struct MarkedText;
 struct StyledMarkedText;
+struct TextBoxSelectableRange;
 struct TextPaintStyle;
 
 const unsigned short cNoTruncation = USHRT_MAX;
@@ -77,6 +78,8 @@
 
     unsigned short truncation() const { return m_truncation; }
 
+    TextBoxSelectableRange selectableRange() const;
+
     void markDirty(bool dirty = true) final;
 
     using LegacyInlineBox::hasHyphen;
@@ -118,7 +121,7 @@
 
 public:
     virtual LayoutRect localSelectionRect(unsigned startPos, unsigned endPos) const;
-    bool isSelected(unsigned startPosition, unsigned endPosition) const;
+    bool isSelectable(unsigned startPosition, unsigned endPosition) const;
     std::pair<unsigned, unsigned> selectionStartEnd() const;
     std::pair<unsigned, unsigned> highlightStartEnd(HighlightData&) const;
 
@@ -126,8 +129,6 @@
     void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) override;
     bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom, HitTestAction) override;
 
-    unsigned clampedOffset(unsigned) const;
-
 private:
     void deleteLine() final;
     void extractLine() final;

Modified: trunk/Source/WebCore/rendering/RenderBlockFlow.cpp (278544 => 278545)


--- trunk/Source/WebCore/rendering/RenderBlockFlow.cpp	2021-06-07 06:16:22 UTC (rev 278544)
+++ trunk/Source/WebCore/rendering/RenderBlockFlow.cpp	2021-06-07 06:19:03 UTC (rev 278545)
@@ -3259,7 +3259,7 @@
             case RenderObject::HighlightState::Both:
                 break;
             }
-            if (textBox.isSelected(start, end))
+            if (textBox.isSelectable(start, end))
                 return true;
         }
         return false;

Added: trunk/Source/WebCore/rendering/TextBoxSelectableRange.h (0 => 278545)


--- trunk/Source/WebCore/rendering/TextBoxSelectableRange.h	                        (rev 0)
+++ trunk/Source/WebCore/rendering/TextBoxSelectableRange.h	2021-06-07 06:19:03 UTC (rev 278545)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 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
+ * 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 <optional>
+
+namespace WebCore {
+
+struct TextBoxSelectableRange {
+    const unsigned start;
+    const unsigned length;
+    const unsigned additionalLengthAtEnd { 0 };
+    const std::optional<unsigned> truncation { };
+
+    unsigned clamp(unsigned offset) const
+    {
+        auto clampedOffset = std::clamp(offset, start, start + length) - start;
+
+        if (truncation)
+            return std::min<unsigned>(clampedOffset, *truncation);
+
+        if (clampedOffset == length)
+            clampedOffset += additionalLengthAtEnd;
+
+        return clampedOffset;
+    }
+
+    std::pair<unsigned, unsigned> clamp(unsigned startOffset, unsigned endOffset) const
+    {
+        return { clamp(startOffset), clamp(endOffset) };
+    }
+
+    bool intersects(unsigned startOffset, unsigned endOffset) const
+    {
+        return clamp(startOffset) < clamp(endOffset);
+    }
+};
+
+}

Modified: trunk/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp (278544 => 278545)


--- trunk/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp	2021-06-07 06:16:22 UTC (rev 278544)
+++ trunk/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp	2021-06-07 06:19:03 UTC (rev 278545)
@@ -35,6 +35,7 @@
 #include "SVGRenderingContext.h"
 #include "SVGResourcesCache.h"
 #include "SVGRootInlineBox.h"
+#include "TextBoxSelectableRange.h"
 #include "TextPainter.h"
 #include <wtf/IsoMallocInlines.h>
 
@@ -134,11 +135,11 @@
     return snappedSelectionRect;
 }
 
-LayoutRect SVGInlineTextBox::localSelectionRect(unsigned startPosition, unsigned endPosition) const
+LayoutRect SVGInlineTextBox::localSelectionRect(unsigned start, unsigned end) const
 {
-    startPosition = clampedOffset(startPosition);
-    endPosition = clampedOffset(endPosition);
-    if (startPosition >= endPosition)
+    auto [clampedStart, clampedEnd] = selectableRange().clamp(start, end);
+
+    if (clampedStart >= clampedEnd)
         return LayoutRect();
 
     auto& style = renderer().style();
@@ -152,8 +153,8 @@
     for (unsigned i = 0; i < textFragmentsSize; ++i) {
         const SVGTextFragment& fragment = m_textFragments.at(i);
 
-        fragmentStartPosition = startPosition;
-        fragmentEndPosition = endPosition;
+        fragmentStartPosition = clampedStart;
+        fragmentEndPosition = clampedEnd;
         if (!mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition))
             continue;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to