Skip to content
Permalink
Browse files
Factor selection state computation out of LegacyInlineTextBox
https://bugs.webkit.org/show_bug.cgi?id=226718

Reviewed by Alan Bujtas.

Move the code to SelectionRangeData.

* layout/integration/LayoutIntegrationRunIteratorModernPath.h:
(WebCore::LayoutIntegration::RunIteratorModernPath::selectableRange const):
* rendering/HighlightData.cpp:
(WebCore::HighlightData::highlightStateForRenderer):
(WebCore::HighlightData::highlightStateForTextBox):
(WebCore::HighlightData::rangeForTextBox):
* rendering/HighlightData.h:
(WebCore::HighlightData::HighlightData):
* rendering/LegacyInlineTextBox.cpp:
(WebCore::LegacyInlineTextBox::selectionState):
(WebCore::LegacyInlineTextBox::selectableRange const):
(WebCore::LegacyInlineTextBox::selectionStartEnd const):
(WebCore::LegacyInlineTextBox::highlightStartEnd const):
(WebCore::LegacyInlineTextBox::verifySelectionState const): Deleted.
(WebCore::LegacyInlineTextBox::clampedStartEndForState const): Deleted.
* rendering/LegacyInlineTextBox.h:
* rendering/SelectionRangeData.cpp:
(WebCore::SelectionRangeData::SelectionRangeData):
* rendering/TextBoxSelectableRange.h:


Canonical link: https://commits.webkit.org/238559@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@278561 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
anttijk committed Jun 7, 2021
1 parent e84725b commit 789ae4deb399d0af15194cd5879cca2519705bdf
@@ -1,3 +1,32 @@
2021-06-07 Antti Koivisto <antti@apple.com>

Factor selection state computation out of LegacyInlineTextBox
https://bugs.webkit.org/show_bug.cgi?id=226718

Reviewed by Alan Bujtas.

Move the code to SelectionRangeData.

* layout/integration/LayoutIntegrationRunIteratorModernPath.h:
(WebCore::LayoutIntegration::RunIteratorModernPath::selectableRange const):
* rendering/HighlightData.cpp:
(WebCore::HighlightData::highlightStateForRenderer):
(WebCore::HighlightData::highlightStateForTextBox):
(WebCore::HighlightData::rangeForTextBox):
* rendering/HighlightData.h:
(WebCore::HighlightData::HighlightData):
* rendering/LegacyInlineTextBox.cpp:
(WebCore::LegacyInlineTextBox::selectionState):
(WebCore::LegacyInlineTextBox::selectableRange const):
(WebCore::LegacyInlineTextBox::selectionStartEnd const):
(WebCore::LegacyInlineTextBox::highlightStartEnd const):
(WebCore::LegacyInlineTextBox::verifySelectionState const): Deleted.
(WebCore::LegacyInlineTextBox::clampedStartEndForState const): Deleted.
* rendering/LegacyInlineTextBox.h:
* rendering/SelectionRangeData.cpp:
(WebCore::SelectionRangeData::SelectionRangeData):
* rendering/TextBoxSelectableRange.h:

2021-06-07 Wenson Hsieh <wenson_hsieh@apple.com>

[Cocoa] Find-in-page should match text inside image overlays
@@ -209,7 +209,8 @@ class RunIteratorModernPath {
return {
start(),
length(),
run().style().hyphenString().length()
run().style().hyphenString().length(),
run().isLineBreak()
};
}

@@ -41,6 +41,7 @@
#include "RenderMultiColumnSpannerPlaceholder.h"
#include "RenderObject.h"
#include "RenderView.h"
#include "TextBoxSelectableRange.h"
#include "VisibleSelection.h"
#include <wtf/text/TextStream.h>

@@ -120,6 +121,9 @@ bool HighlightData::setRenderRange(const HighlightRangeData& rangeData)

RenderObject::HighlightState HighlightData::highlightStateForRenderer(const RenderObject& renderer)
{
if (m_isSelection)
return renderer.selectionState();

if (&renderer == m_renderRange.start()) {
if (m_renderRange.start() && m_renderRange.end() && m_renderRange.start() == m_renderRange.end())
return RenderObject::HighlightState::Both;
@@ -143,4 +147,50 @@ RenderObject::HighlightState HighlightData::highlightStateForRenderer(const Rend
return RenderObject::HighlightState::None;
}

RenderObject::HighlightState HighlightData::highlightStateForTextBox(const RenderText& renderer, const TextBoxSelectableRange& textBoxRange)
{
auto state = highlightStateForRenderer(renderer);

if (state == RenderObject::HighlightState::None || state == RenderObject::HighlightState::Inside)
return state;

auto startOffset = this->startOffset();
auto endOffset = this->endOffset();

// The position after a hard line break is considered to be past its end.
ASSERT(textBoxRange.start + textBoxRange.length >= (textBoxRange.isLineBreak ? 1 : 0));
unsigned lastSelectable = textBoxRange.start + textBoxRange.length - (textBoxRange.isLineBreak ? 1 : 0);

bool containsStart = state != RenderObject::HighlightState::End && startOffset >= textBoxRange.start && startOffset < textBoxRange.start + textBoxRange.length;
bool containsEnd = state != RenderObject::HighlightState::Start && endOffset > textBoxRange.start && endOffset <= lastSelectable;
if (containsStart && containsEnd)
return RenderObject::HighlightState::Both;
if (containsStart)
return RenderObject::HighlightState::Start;
if (containsEnd)
return RenderObject::HighlightState::End;
if ((state == RenderObject::HighlightState::End || startOffset < textBoxRange.start) && (state == RenderObject::HighlightState::Start || endOffset > lastSelectable))
return RenderObject::HighlightState::Inside;

return RenderObject::HighlightState::None;
}

std::pair<unsigned, unsigned> HighlightData::rangeForTextBox(const RenderText& renderer, const TextBoxSelectableRange& textBoxRange)
{
auto state = highlightStateForTextBox(renderer, textBoxRange);

switch (state) {
case RenderObject::HighlightState::Inside:
return textBoxRange.clamp(0, std::numeric_limits<unsigned>::max());
case RenderObject::HighlightState::Start:
return textBoxRange.clamp(startOffset(), std::numeric_limits<unsigned>::max());
case RenderObject::HighlightState::End:
return textBoxRange.clamp(0, endOffset());
case RenderObject::HighlightState::Both:
return textBoxRange.clamp(startOffset(), endOffset());
case RenderObject::HighlightState::None:
return { 0, 0 };
};
}

} // namespace WebCore
@@ -35,6 +35,7 @@
namespace WebCore {

struct HighlightRangeData;
struct TextBoxSelectableRange;
class RenderMultiColumnSpannerPlaceholder;

class RenderRange {
@@ -80,6 +81,12 @@ class RenderRangeIterator {

class HighlightData {
public:
enum IsSelectionTag { IsSelection };
HighlightData() = default;
HighlightData(IsSelectionTag)
: m_isSelection(true)
{ }

void setRenderRange(const RenderRange&);
bool setRenderRange(const HighlightRangeData&); // Returns true if successful.
const RenderRange& get() const { return m_renderRange; }
@@ -91,9 +98,12 @@ class HighlightData {
unsigned endOffset() const { return m_renderRange.endOffset(); }

RenderObject::HighlightState highlightStateForRenderer(const RenderObject&);
RenderObject::HighlightState highlightStateForTextBox(const RenderText&, const TextBoxSelectableRange&);
std::pair<unsigned, unsigned> rangeForTextBox(const RenderText&, const TextBoxSelectableRange&);

protected:
RenderRange m_renderRange;
const bool m_isSelection { false };
};

} // namespace WebCore
@@ -161,7 +161,7 @@ bool LegacyInlineTextBox::isSelectable(unsigned startPosition, unsigned endPosit

RenderObject::HighlightState LegacyInlineTextBox::selectionState()
{
auto state = verifySelectionState(renderer().selectionState(), renderer().view().selection());
auto state = renderer().view().selection().highlightStateForTextBox(renderer(), selectableRange());

// FIXME: this code mutates selection state, but it's used at a simple getter elsewhere
// in this file. This code should likely live in HighlightData, or somewhere else.
@@ -185,33 +185,6 @@ RenderObject::HighlightState LegacyInlineTextBox::selectionState()
return state;
}

RenderObject::HighlightState LegacyInlineTextBox::verifySelectionState(RenderObject::HighlightState state, HighlightData& selection) const
{
if (state == RenderObject::HighlightState::Start || state == RenderObject::HighlightState::End || state == RenderObject::HighlightState::Both) {
auto startOffset = selection.startOffset();
auto endOffset = selection.endOffset();
// The position after a hard line break is considered to be past its end.
ASSERT(start() + len() >= (isLineBreak() ? 1 : 0));
unsigned lastSelectable = start() + len() - (isLineBreak() ? 1 : 0);

bool start = (state != RenderObject::HighlightState::End && startOffset >= m_start && startOffset < m_start + m_len);
bool end = (state != RenderObject::HighlightState::Start && endOffset > m_start && endOffset <= lastSelectable);
if (start && end)
state = RenderObject::HighlightState::Both;
else if (start)
state = RenderObject::HighlightState::Start;
else if (end)
state = RenderObject::HighlightState::End;
else if ((state == RenderObject::HighlightState::End || startOffset < m_start)
&& (state == RenderObject::HighlightState::Start || endOffset > lastSelectable))
state = RenderObject::HighlightState::Inside;
else if (state == RenderObject::HighlightState::Both)
state = RenderObject::HighlightState::None;
}

return state;
}

inline const FontCascade& LegacyInlineTextBox::lineFont() const
{
return combinedText() ? combinedText()->textCombineFont() : lineStyle().fontCascade();
@@ -666,38 +639,19 @@ TextBoxSelectableRange LegacyInlineTextBox::selectableRange() const
m_start,
m_len,
additionalLengthAtEnd,
isLineBreak(),
truncation
};
}

std::pair<unsigned, unsigned> LegacyInlineTextBox::clampedStartEndForState(unsigned start, unsigned end, RenderObject::HighlightState selectionState) const
{
if (selectionState == RenderObject::HighlightState::Inside)
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 selectableRange().clamp(start, end);
}

std::pair<unsigned, unsigned> LegacyInlineTextBox::selectionStartEnd() const
{
auto selectionState = renderer().selectionState();

return clampedStartEndForState(renderer().view().selection().startOffset(), renderer().view().selection().endOffset(), selectionState);
return renderer().view().selection().rangeForTextBox(renderer(), selectableRange());
}

std::pair<unsigned, unsigned> LegacyInlineTextBox::highlightStartEnd(HighlightData &rangeData) const
std::pair<unsigned, unsigned> LegacyInlineTextBox::highlightStartEnd(HighlightData& rangeData) const
{
auto state = rangeData.highlightStateForRenderer(renderer());
state = verifySelectionState(state, rangeData);

if (state == RenderObject::HighlightState::None)
return {0, 0};

return clampedStartEndForState(rangeData.startOffset(), rangeData.endOffset(), state);
return rangeData.rangeForTextBox(renderer(), selectableRange());
}

bool LegacyInlineTextBox::hasMarkers() const
@@ -134,9 +134,6 @@ class LegacyInlineTextBox : public LegacyInlineBox {
void extractLine() final;
void attachLine() final;

RenderObject::HighlightState verifySelectionState(RenderObject::HighlightState, HighlightData&) const;
std::pair<unsigned, unsigned> clampedStartEndForState(unsigned, unsigned, RenderObject::HighlightState) const;

public:
RenderObject::HighlightState selectionState() final;

@@ -108,7 +108,8 @@ static SelectionContext collectSelectionData(const RenderRange& selection, bool
}

SelectionRangeData::SelectionRangeData(RenderView& view)
: m_renderView(view)
: HighlightData(IsSelection)
, m_renderView(view)
#if ENABLE(SERVICE_CONTROLS)
, m_selectionGeometryGatherer(view)
#endif
@@ -32,6 +32,7 @@ struct TextBoxSelectableRange {
const unsigned start;
const unsigned length;
const unsigned additionalLengthAtEnd { 0 };
const bool isLineBreak { false };
const std::optional<unsigned> truncation { };

unsigned clamp(unsigned offset) const

0 comments on commit 789ae4d

Please sign in to comment.