Chromium Code Reviews| Index: third_party/WebKit/Source/core/editing/LayoutSelection.cpp |
| diff --git a/third_party/WebKit/Source/core/editing/LayoutSelection.cpp b/third_party/WebKit/Source/core/editing/LayoutSelection.cpp |
| index 7fe3f6b27259f3321a664818cd3c5e9ff835272c..67b22d6e0cdc8b1769dd540c083c52529b45b176 100644 |
| --- a/third_party/WebKit/Source/core/editing/LayoutSelection.cpp |
| +++ b/third_party/WebKit/Source/core/editing/LayoutSelection.cpp |
| @@ -32,13 +32,34 @@ |
| namespace blink { |
| +SelectionPaintRange::SelectionPaintRange(LayoutObject* start_layout_object, |
| + int start_offset, |
| + LayoutObject* end_layout_object, |
| + int end_offset) |
| + : start_layout_object_(start_layout_object), |
| + start_offset_(start_offset), |
| + end_layout_object_(end_layout_object), |
| + end_offset_(end_offset) { |
| + DCHECK(StartLayoutObject()); |
| + DCHECK(EndLayoutObject()); |
| + if (StartLayoutObject() == EndLayoutObject()) |
| + DCHECK_LT(StartOffset(), EndOffset()); |
| +} |
| + |
| +bool SelectionPaintRange::operator==(const SelectionPaintRange& other) const { |
| + return start_layout_object_ == other.start_layout_object_ && |
| + start_offset_ == other.start_offset_ && |
| + end_layout_object_ == other.end_layout_object_ && |
| + end_offset_ == other.end_offset_; |
| +} |
| +bool SelectionPaintRange::operator!=(const SelectionPaintRange& other) const { |
| + return !(*this == other); |
| +} |
| + |
| LayoutSelection::LayoutSelection(FrameSelection& frame_selection) |
| : frame_selection_(&frame_selection), |
| has_pending_selection_(false), |
| - selection_start_(nullptr), |
| - selection_end_(nullptr), |
| - selection_start_pos_(-1), |
| - selection_end_pos_(-1) {} |
| + paint_range_(SelectionPaintRange()) {} |
| SelectionInFlatTree LayoutSelection::CalcVisibleSelection( |
| const VisibleSelectionInFlatTree& original_selection) const { |
| @@ -124,19 +145,17 @@ struct SelectedMap { |
| }; |
| static SelectedMap CollectSelectedMap( |
| - LayoutObject* selection_start, |
| - LayoutObject* selection_end, |
| - int selection_end_pos, |
| + const SelectionPaintRange& range, |
| LayoutSelection::SelectionPaintInvalidationMode |
| block_paint_invalidation_mode) { |
| SelectedMap selected_map; |
| LayoutObject* const stop = |
| - LayoutObjectAfterPosition(selection_end, selection_end_pos); |
| - for (LayoutObject* runner = selection_start; runner && (runner != stop); |
| - runner = runner->NextInPreOrder()) { |
| - if (!runner->CanBeSelectionLeaf() && runner != selection_start && |
| - runner != selection_end) |
| + LayoutObjectAfterPosition(range.EndLayoutObject(), range.EndOffset()); |
| + for (LayoutObject* runner = range.StartLayoutObject(); |
| + runner && (runner != stop); runner = runner->NextInPreOrder()) { |
| + if (!runner->CanBeSelectionLeaf() && runner != range.StartLayoutObject() && |
| + runner != range.EndLayoutObject()) |
| continue; |
| if (runner->GetSelectionState() == SelectionNone) |
| continue; |
| @@ -160,52 +179,45 @@ static SelectedMap CollectSelectedMap( |
| } |
| // Update the selection status of all LayoutObjects between |start| and |end|. |
| -static void SetSelectionState(LayoutObject* start, |
| - LayoutObject* end, |
| - int end_pos) { |
| - if (start && start == end) { |
| - start->SetSelectionStateIfNeeded(SelectionBoth); |
| +static void SetSelectionState(const SelectionPaintRange& range) { |
| + DCHECK(range != SelectionPaintRange()); |
| + if (range.StartLayoutObject() == range.EndLayoutObject()) { |
| + range.StartLayoutObject()->SetSelectionStateIfNeeded(SelectionBoth); |
| } else { |
| - if (start) |
| - start->SetSelectionStateIfNeeded(SelectionStart); |
| - if (end) |
| - end->SetSelectionStateIfNeeded(SelectionEnd); |
| + range.StartLayoutObject()->SetSelectionStateIfNeeded(SelectionStart); |
| + range.EndLayoutObject()->SetSelectionStateIfNeeded(SelectionEnd); |
| } |
| - LayoutObject* const stop = LayoutObjectAfterPosition(end, end_pos); |
| - for (LayoutObject* runner = start; runner && runner != stop; |
| - runner = runner->NextInPreOrder()) { |
| - if (runner != start && runner != end && runner->CanBeSelectionLeaf()) |
| + LayoutObject* const stop = |
| + LayoutObjectAfterPosition(range.EndLayoutObject(), range.EndOffset()); |
| + for (LayoutObject* runner = range.StartLayoutObject(); |
| + runner && runner != stop; runner = runner->NextInPreOrder()) { |
| + if (runner != range.StartLayoutObject() && |
| + runner != range.EndLayoutObject() && runner->CanBeSelectionLeaf()) |
| runner->SetSelectionStateIfNeeded(SelectionInside); |
| } |
| } |
| void LayoutSelection::SetSelection( |
| - LayoutObject* start, |
| - int start_pos, |
| - LayoutObject* end, |
| - int end_pos, |
| + const SelectionPaintRange& new_range, |
| SelectionPaintInvalidationMode block_paint_invalidation_mode) { |
| - DCHECK(start); |
| - DCHECK(end); |
| + DCHECK(new_range != SelectionPaintRange()); |
|
yosin_UTC9
2017/05/24 09:31:18
I prefer to use |IsNull()| as |EpehemralRange|
yoichio
2017/05/25 02:00:35
Done.
|
| // Just return if the selection hasn't changed. |
| - if (selection_start_ == start && selection_start_pos_ == start_pos && |
| - selection_end_ == end && selection_end_pos_ == end_pos) |
| + if (paint_range_ == new_range) |
| return; |
| DCHECK(frame_selection_->GetDocument().GetLayoutView()->GetFrameView()); |
| DCHECK(!frame_selection_->GetDocument().NeedsLayoutTreeUpdate()); |
| SelectedMap old_selected_map = |
| - CollectSelectedMap(selection_start_, selection_end_, selection_end_pos_, |
| - block_paint_invalidation_mode); |
| + CollectSelectedMap(paint_range_, block_paint_invalidation_mode); |
| // Now clear the selection. |
| for (auto layout_object : old_selected_map.object_map.Keys()) |
| layout_object->SetSelectionStateIfNeeded(SelectionNone); |
| - SetSelectionState(start, end, end_pos); |
| + SetSelectionState(new_range); |
| // Now that the selection state has been updated for the new objects, walk |
| // them again and put them in the new objects list. |
| @@ -213,7 +225,7 @@ void LayoutSelection::SetSelection( |
| // SelectionState, it's just more convenient to have it use the same data |
| // structure as |old_selected_map|. |
| SelectedMap new_selected_map = |
| - CollectSelectedMap(start, end, end_pos, kPaintInvalidationNewXOROld); |
| + CollectSelectedMap(new_range, kPaintInvalidationNewXOROld); |
| // Have any of the old selected objects changed compared to the new selection? |
| for (const auto& pair : old_selected_map.object_map) { |
| @@ -221,8 +233,10 @@ void LayoutSelection::SetSelection( |
| SelectionState new_selection_state = obj->GetSelectionState(); |
| SelectionState old_selection_state = pair.value; |
| if (new_selection_state != old_selection_state || |
| - (start == obj && start_pos != selection_start_pos_) || |
| - (end == obj && end_pos != selection_end_pos_)) { |
| + (new_range.StartLayoutObject() == obj && |
| + new_range.StartOffset() != paint_range_.StartOffset()) || |
| + (new_range.EndLayoutObject() == obj && |
| + new_range.EndOffset() != paint_range_.EndOffset())) { |
| obj->SetShouldInvalidateSelection(); |
| new_selected_map.object_map.erase(obj); |
| } |
| @@ -249,16 +263,12 @@ void LayoutSelection::SetSelection( |
| for (auto layout_object : new_selected_map.block_map.Keys()) |
| layout_object->SetShouldInvalidateSelection(); |
| - // set selection start and end |
| - selection_start_ = start; |
| - selection_start_pos_ = start_pos; |
| - selection_end_ = end; |
| - selection_end_pos_ = end_pos; |
| + paint_range_ = new_range; |
| } |
| std::pair<int, int> LayoutSelection::SelectionStartEnd() { |
| Commit(); |
| - return std::make_pair(selection_start_pos_, selection_end_pos_); |
| + return std::make_pair(paint_range_.StartOffset(), paint_range_.EndOffset()); |
| } |
| void LayoutSelection::ClearSelection() { |
| @@ -267,17 +277,12 @@ void LayoutSelection::ClearSelection() { |
| // invalidations. |
| DisableCompositingQueryAsserts disabler; |
| - // Just return if the selection hasn't changed. |
| - if (!selection_start_) { |
| - DCHECK_EQ(selection_end_, nullptr); |
| - DCHECK_EQ(selection_start_pos_, -1); |
| - DCHECK_EQ(selection_end_pos_, -1); |
| + // Just return if the selection is already empty. |
| + if (paint_range_ == SelectionPaintRange()) |
| return; |
| - } |
| const SelectedMap& old_selected_map = |
| - CollectSelectedMap(selection_start_, selection_end_, selection_end_pos_, |
| - kPaintInvalidationNewMinusOld); |
| + CollectSelectedMap(paint_range_, kPaintInvalidationNewMinusOld); |
| // Clear SelectionState and invalidation. |
| for (auto layout_object : old_selected_map.object_map.Keys()) { |
| const SelectionState old_state = layout_object->GetSelectionState(); |
| @@ -288,10 +293,7 @@ void LayoutSelection::ClearSelection() { |
| } |
| // Reset selection start and end. |
| - selection_start_ = nullptr; |
| - selection_start_pos_ = -1; |
| - selection_end_ = nullptr; |
| - selection_end_pos_ = -1; |
| + paint_range_ = SelectionPaintRange(); |
| } |
| void LayoutSelection::Commit() { |
| @@ -342,16 +344,14 @@ void LayoutSelection::Commit() { |
| if (!start_layout_object || !end_layout_object) |
| return; |
| DCHECK(start_layout_object->View() == end_layout_object->View()); |
| - SetSelection(start_layout_object, start_pos.ComputeEditingOffset(), |
| - end_layout_object, end_pos.ComputeEditingOffset()); |
| + SetSelection( |
| + SelectionPaintRange(start_layout_object, start_pos.ComputeEditingOffset(), |
| + end_layout_object, end_pos.ComputeEditingOffset())); |
| } |
| void LayoutSelection::OnDocumentShutdown() { |
| has_pending_selection_ = false; |
| - selection_start_ = nullptr; |
| - selection_end_ = nullptr; |
| - selection_start_pos_ = -1; |
| - selection_end_pos_ = -1; |
| + paint_range_ = SelectionPaintRange(); |
| } |
| static LayoutRect SelectionRectForLayoutObject(const LayoutObject* object) { |
| @@ -372,12 +372,12 @@ IntRect LayoutSelection::SelectionBounds() { |
| VisitedContainingBlockSet visited_containing_blocks; |
| Commit(); |
| - LayoutObject* os = selection_start_; |
| - LayoutObject* stop = |
| - LayoutObjectAfterPosition(selection_end_, selection_end_pos_); |
| + LayoutObject* os = paint_range_.StartLayoutObject(); |
| + LayoutObject* stop = LayoutObjectAfterPosition(paint_range_.EndLayoutObject(), |
| + paint_range_.EndOffset()); |
| while (os && os != stop) { |
| - if ((os->CanBeSelectionLeaf() || os == selection_start_ || |
| - os == selection_end_) && |
| + if ((os->CanBeSelectionLeaf() || os == paint_range_.StartLayoutObject() || |
| + os == paint_range_.EndLayoutObject()) && |
| os->GetSelectionState() != SelectionNone) { |
| // Blocks are responsible for painting line gaps and margin gaps. They |
| // must be examined as well. |
| @@ -400,12 +400,12 @@ IntRect LayoutSelection::SelectionBounds() { |
| } |
| void LayoutSelection::InvalidatePaintForSelection() { |
| - LayoutObject* end = |
| - LayoutObjectAfterPosition(selection_end_, selection_end_pos_); |
| - for (LayoutObject* o = selection_start_; o && o != end; |
| + LayoutObject* end = LayoutObjectAfterPosition(paint_range_.EndLayoutObject(), |
| + paint_range_.EndOffset()); |
| + for (LayoutObject* o = paint_range_.StartLayoutObject(); o && o != end; |
| o = o->NextInPreOrder()) { |
| - if (!o->CanBeSelectionLeaf() && o != selection_start_ && |
| - o != selection_end_) |
| + if (!o->CanBeSelectionLeaf() && o != paint_range_.StartLayoutObject() && |
| + o != paint_range_.EndLayoutObject()) |
| continue; |
| if (o->GetSelectionState() == SelectionNone) |
| continue; |