Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights | 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights |
| 4 * reserved. | 4 * reserved. |
| 5 * | 5 * |
| 6 * This library is free software; you can redistribute it and/or | 6 * This library is free software; you can redistribute it and/or |
| 7 * modify it under the terms of the GNU Library General Public | 7 * modify it under the terms of the GNU Library General Public |
| 8 * License as published by the Free Software Foundation; either | 8 * License as published by the Free Software Foundation; either |
| 9 * version 2 of the License, or (at your option) any later version. | 9 * version 2 of the License, or (at your option) any later version. |
| 10 * | 10 * |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 67 LayoutObject* SelectionPaintRange::EndLayoutObject() const { | 67 LayoutObject* SelectionPaintRange::EndLayoutObject() const { |
| 68 DCHECK(!IsNull()); | 68 DCHECK(!IsNull()); |
| 69 return end_layout_object_; | 69 return end_layout_object_; |
| 70 } | 70 } |
| 71 | 71 |
| 72 int SelectionPaintRange::EndOffset() const { | 72 int SelectionPaintRange::EndOffset() const { |
| 73 DCHECK(!IsNull()); | 73 DCHECK(!IsNull()); |
| 74 return end_offset_; | 74 return end_offset_; |
| 75 } | 75 } |
| 76 | 76 |
| 77 SelectionPaintRange::Iterator::Iterator(const SelectionPaintRange* range) { | |
| 78 if (!range) { | |
| 79 current_ = nullptr; | |
| 80 return; | |
| 81 } | |
| 82 current_ = range->StartLayoutObject(); | |
| 83 included_end_ = range->EndLayoutObject(); | |
| 84 stop_ = range->EndLayoutObject()->ChildAt(range->EndOffset()); | |
| 85 if (stop_) | |
| 86 return; | |
| 87 stop_ = range->EndLayoutObject()->NextInPreOrderAfterChildren(); | |
| 88 } | |
| 89 | |
| 90 LayoutObject* SelectionPaintRange::Iterator::operator*() const { | |
| 91 DCHECK(current_); | |
| 92 return current_; | |
| 93 } | |
| 94 | |
| 95 SelectionPaintRange::Iterator& SelectionPaintRange::Iterator::operator++() { | |
| 96 DCHECK(current_); | |
| 97 for (current_ = current_->NextInPreOrder(); current_ && current_ != stop_; | |
| 98 current_ = current_->NextInPreOrder()) { | |
| 99 if (current_ == included_end_ || current_->CanBeSelectionLeaf()) | |
| 100 return *this; | |
| 101 } | |
| 102 | |
| 103 current_ = nullptr; | |
| 104 return *this; | |
| 105 } | |
| 106 | |
| 77 LayoutSelection::LayoutSelection(FrameSelection& frame_selection) | 107 LayoutSelection::LayoutSelection(FrameSelection& frame_selection) |
| 78 : frame_selection_(&frame_selection), | 108 : frame_selection_(&frame_selection), |
| 79 has_pending_selection_(false), | 109 has_pending_selection_(false), |
| 80 paint_range_(SelectionPaintRange()) {} | 110 paint_range_(SelectionPaintRange()) {} |
| 81 | 111 |
| 82 static SelectionInFlatTree CalcSelection( | 112 static SelectionInFlatTree CalcSelection( |
| 83 const VisibleSelectionInFlatTree& original_selection, | 113 const VisibleSelectionInFlatTree& original_selection, |
| 84 bool should_show_blok_cursor) { | 114 bool should_show_blok_cursor) { |
| 85 const PositionInFlatTree& start = original_selection.Start(); | 115 const PositionInFlatTree& start = original_selection.Start(); |
| 86 const PositionInFlatTree& end = original_selection.End(); | 116 const PositionInFlatTree& end = original_selection.End(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 124 ? TextAffinity::kUpstream | 154 ? TextAffinity::kUpstream |
| 125 : affinity); | 155 : affinity); |
| 126 if (visible_end.IsNull()) | 156 if (visible_end.IsNull()) |
| 127 return SelectionInFlatTree(); | 157 return SelectionInFlatTree(); |
| 128 SelectionInFlatTree::Builder builder; | 158 SelectionInFlatTree::Builder builder; |
| 129 builder.Collapse(visible_start.ToPositionWithAffinity()); | 159 builder.Collapse(visible_start.ToPositionWithAffinity()); |
| 130 builder.Extend(visible_end.DeepEquivalent()); | 160 builder.Extend(visible_end.DeepEquivalent()); |
| 131 return builder.Build(); | 161 return builder.Build(); |
| 132 } | 162 } |
| 133 | 163 |
| 134 static LayoutObject* LayoutObjectAfterPosition(LayoutObject* object, | |
| 135 unsigned offset) { | |
| 136 if (!object) | |
| 137 return nullptr; | |
| 138 | 164 |
| 139 LayoutObject* child = object->ChildAt(offset); | |
| 140 return child ? child : object->NextInPreOrderAfterChildren(); | |
| 141 } | |
| 142 | 165 |
| 143 // Objects each have a single selection rect to examine. | 166 // Objects each have a single selection rect to examine. |
| 144 using SelectedObjectMap = HashMap<LayoutObject*, SelectionState>; | 167 using SelectedObjectMap = HashMap<LayoutObject*, SelectionState>; |
| 145 // Blocks contain selected objects and fill gaps between them, either on the | 168 // Blocks contain selected objects and fill gaps between them, either on the |
| 146 // left, right, or in between lines and blocks. | 169 // left, right, or in between lines and blocks. |
| 147 // In order to get the visual rect right, we have to examine left, middle, and | 170 // In order to get the visual rect right, we have to examine left, middle, and |
| 148 // right rects individually, since otherwise the union of those rects might | 171 // right rects individually, since otherwise the union of those rects might |
| 149 // remain the same even when changes have occurred. | 172 // remain the same even when changes have occurred. |
| 150 using SelectedBlockMap = HashMap<LayoutBlock*, SelectionState>; | 173 using SelectedBlockMap = HashMap<LayoutBlock*, SelectionState>; |
| 151 struct SelectedMap { | 174 struct SelectedMap { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 168 kNotCollectBlock, | 191 kNotCollectBlock, |
| 169 }; | 192 }; |
| 170 | 193 |
| 171 static SelectedMap CollectSelectedMap(const SelectionPaintRange& range, | 194 static SelectedMap CollectSelectedMap(const SelectionPaintRange& range, |
| 172 CollectSelectedMapOption option) { | 195 CollectSelectedMapOption option) { |
| 173 if (range.IsNull()) | 196 if (range.IsNull()) |
| 174 return SelectedMap(); | 197 return SelectedMap(); |
| 175 | 198 |
| 176 SelectedMap selected_map; | 199 SelectedMap selected_map; |
| 177 | 200 |
| 178 LayoutObject* const stop = | 201 for (LayoutObject* runner : range) { |
| 179 LayoutObjectAfterPosition(range.EndLayoutObject(), range.EndOffset()); | |
| 180 for (LayoutObject* runner = range.StartLayoutObject(); | |
| 181 runner && (runner != stop); runner = runner->NextInPreOrder()) { | |
| 182 if (!runner->CanBeSelectionLeaf() && runner != range.StartLayoutObject() && | |
| 183 runner != range.EndLayoutObject()) | |
| 184 continue; | |
| 185 if (runner->GetSelectionState() == SelectionState::kNone) | 202 if (runner->GetSelectionState() == SelectionState::kNone) |
| 186 continue; | 203 continue; |
| 187 | 204 |
| 188 // Blocks are responsible for painting line gaps and margin gaps. They | 205 // Blocks are responsible for painting line gaps and margin gaps. They |
| 189 // must be examined as well. | 206 // must be examined as well. |
| 190 selected_map.object_map.Set(runner, runner->GetSelectionState()); | 207 selected_map.object_map.Set(runner, runner->GetSelectionState()); |
| 191 if (option == CollectSelectedMapOption::kCollectBlock) { | 208 if (option == CollectSelectedMapOption::kCollectBlock) { |
| 192 LayoutBlock* containing_block = runner->ContainingBlock(); | 209 LayoutBlock* containing_block = runner->ContainingBlock(); |
| 193 while (containing_block && !containing_block->IsLayoutView()) { | 210 while (containing_block && !containing_block->IsLayoutView()) { |
| 194 SelectedBlockMap::AddResult result = selected_map.block_map.insert( | 211 SelectedBlockMap::AddResult result = selected_map.block_map.insert( |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 209 | 226 |
| 210 if (range.StartLayoutObject() == range.EndLayoutObject()) { | 227 if (range.StartLayoutObject() == range.EndLayoutObject()) { |
| 211 range.StartLayoutObject()->SetSelectionStateIfNeeded( | 228 range.StartLayoutObject()->SetSelectionStateIfNeeded( |
| 212 SelectionState::kStartAndEnd); | 229 SelectionState::kStartAndEnd); |
| 213 } else { | 230 } else { |
| 214 range.StartLayoutObject()->SetSelectionStateIfNeeded( | 231 range.StartLayoutObject()->SetSelectionStateIfNeeded( |
| 215 SelectionState::kStart); | 232 SelectionState::kStart); |
| 216 range.EndLayoutObject()->SetSelectionStateIfNeeded(SelectionState::kEnd); | 233 range.EndLayoutObject()->SetSelectionStateIfNeeded(SelectionState::kEnd); |
| 217 } | 234 } |
| 218 | 235 |
| 219 LayoutObject* const stop = | 236 for (LayoutObject* runner : range) { |
| 220 LayoutObjectAfterPosition(range.EndLayoutObject(), range.EndOffset()); | |
| 221 for (LayoutObject* runner = range.StartLayoutObject(); | |
| 222 runner && runner != stop; runner = runner->NextInPreOrder()) { | |
| 223 if (runner != range.StartLayoutObject() && | 237 if (runner != range.StartLayoutObject() && |
| 224 runner != range.EndLayoutObject() && runner->CanBeSelectionLeaf()) | 238 runner != range.EndLayoutObject() && runner->CanBeSelectionLeaf()) |
| 225 runner->SetSelectionStateIfNeeded(SelectionState::kInside); | 239 runner->SetSelectionStateIfNeeded(SelectionState::kInside); |
| 226 } | 240 } |
| 227 } | 241 } |
| 228 | 242 |
| 229 // Set SetSelectionState and ShouldInvalidateSelection flag of LayoutObjects | 243 // Set SetSelectionState and ShouldInvalidateSelection flag of LayoutObjects |
| 230 // comparing them in |new_range| and |old_range|. | 244 // comparing them in |new_range| and |old_range|. |
| 231 static void UpdateLayoutObjectState(const SelectionPaintRange& new_range, | 245 static void UpdateLayoutObjectState(const SelectionPaintRange& new_range, |
| 232 const SelectionPaintRange& old_range) { | 246 const SelectionPaintRange& old_range) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 297 // invalidations. | 311 // invalidations. |
| 298 DisableCompositingQueryAsserts disabler; | 312 DisableCompositingQueryAsserts disabler; |
| 299 | 313 |
| 300 // Just return if the selection is already empty. | 314 // Just return if the selection is already empty. |
| 301 if (paint_range_.IsNull()) | 315 if (paint_range_.IsNull()) |
| 302 return; | 316 return; |
| 303 | 317 |
| 304 const SelectedMap& old_selected_map = CollectSelectedMap( | 318 const SelectedMap& old_selected_map = CollectSelectedMap( |
| 305 paint_range_, CollectSelectedMapOption::kNotCollectBlock); | 319 paint_range_, CollectSelectedMapOption::kNotCollectBlock); |
| 306 // Clear SelectionState and invalidation. | 320 // Clear SelectionState and invalidation. |
| 321 // TODO(yoichio): Iterate with *this directrly. | |
| 307 for (auto layout_object : old_selected_map.object_map.Keys()) { | 322 for (auto layout_object : old_selected_map.object_map.Keys()) { |
| 308 const SelectionState old_state = layout_object->GetSelectionState(); | 323 const SelectionState old_state = layout_object->GetSelectionState(); |
| 309 layout_object->SetSelectionStateIfNeeded(SelectionState::kNone); | 324 layout_object->SetSelectionStateIfNeeded(SelectionState::kNone); |
| 310 if (layout_object->GetSelectionState() == old_state) | 325 if (layout_object->GetSelectionState() == old_state) |
| 311 continue; | 326 continue; |
| 312 layout_object->SetShouldInvalidateSelection(); | 327 layout_object->SetShouldInvalidateSelection(); |
| 313 } | 328 } |
| 314 | 329 |
| 315 // Reset selection. | 330 // Reset selection. |
| 316 paint_range_ = SelectionPaintRange(); | 331 paint_range_ = SelectionPaintRange(); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 403 // Now create a single bounding box rect that encloses the whole selection. | 418 // Now create a single bounding box rect that encloses the whole selection. |
| 404 LayoutRect sel_rect; | 419 LayoutRect sel_rect; |
| 405 | 420 |
| 406 typedef HashSet<const LayoutBlock*> VisitedContainingBlockSet; | 421 typedef HashSet<const LayoutBlock*> VisitedContainingBlockSet; |
| 407 VisitedContainingBlockSet visited_containing_blocks; | 422 VisitedContainingBlockSet visited_containing_blocks; |
| 408 | 423 |
| 409 Commit(); | 424 Commit(); |
| 410 if (paint_range_.IsNull()) | 425 if (paint_range_.IsNull()) |
| 411 return IntRect(); | 426 return IntRect(); |
| 412 | 427 |
| 413 LayoutObject* os = paint_range_.StartLayoutObject(); | 428 // TODO(yoichio): Use CollectSelectedMap. |
| 414 LayoutObject* stop = LayoutObjectAfterPosition(paint_range_.EndLayoutObject(), | 429 for (LayoutObject* runner : paint_range_) { |
| 415 paint_range_.EndOffset()); | 430 if (runner->GetSelectionState() == SelectionState::kNone) |
| 416 while (os && os != stop) { | 431 continue; |
| 417 if ((os->CanBeSelectionLeaf() || os == paint_range_.StartLayoutObject() || | 432 |
| 418 os == paint_range_.EndLayoutObject()) && | 433 // Blocks are responsible for painting line gaps and margin gaps. They |
| 419 os->GetSelectionState() != SelectionState::kNone) { | 434 // must be examined as well. |
| 420 // Blocks are responsible for painting line gaps and margin gaps. They | 435 sel_rect.Unite(SelectionRectForLayoutObject(runner)); |
| 421 // must be examined as well. | 436 const LayoutBlock* cb = runner->ContainingBlock(); |
| 422 sel_rect.Unite(SelectionRectForLayoutObject(os)); | 437 while (cb && !cb->IsLayoutView()) { |
|
yosin_UTC9
2017/06/12 06:37:36
Let's use for-statement.
s/cb/block/ or s/cb/block
yoichio
2017/06/12 06:45:44
I will use CollectSelectedMap and remove these lin
| |
| 423 const LayoutBlock* cb = os->ContainingBlock(); | 438 sel_rect.Unite(SelectionRectForLayoutObject(cb)); |
| 424 while (cb && !cb->IsLayoutView()) { | 439 VisitedContainingBlockSet::AddResult add_result = |
| 425 sel_rect.Unite(SelectionRectForLayoutObject(cb)); | 440 visited_containing_blocks.insert(cb); |
| 426 VisitedContainingBlockSet::AddResult add_result = | 441 if (!add_result.is_new_entry) |
| 427 visited_containing_blocks.insert(cb); | 442 break; |
| 428 if (!add_result.is_new_entry) | 443 cb = cb->ContainingBlock(); |
| 429 break; | |
| 430 cb = cb->ContainingBlock(); | |
| 431 } | |
| 432 } | 444 } |
| 433 | |
| 434 os = os->NextInPreOrder(); | |
| 435 } | 445 } |
| 436 | 446 |
| 437 return PixelSnappedIntRect(sel_rect); | 447 return PixelSnappedIntRect(sel_rect); |
| 438 } | 448 } |
| 439 | 449 |
| 440 void LayoutSelection::InvalidatePaintForSelection() { | 450 void LayoutSelection::InvalidatePaintForSelection() { |
| 441 if (paint_range_.IsNull()) | 451 if (paint_range_.IsNull()) |
| 442 return; | 452 return; |
| 443 | 453 |
| 444 LayoutObject* end = LayoutObjectAfterPosition(paint_range_.EndLayoutObject(), | 454 for (LayoutObject* runner : paint_range_) { |
| 445 paint_range_.EndOffset()); | 455 if (runner->GetSelectionState() == SelectionState::kNone) |
| 446 for (LayoutObject* o = paint_range_.StartLayoutObject(); o && o != end; | |
| 447 o = o->NextInPreOrder()) { | |
| 448 if (!o->CanBeSelectionLeaf() && o != paint_range_.StartLayoutObject() && | |
| 449 o != paint_range_.EndLayoutObject()) | |
| 450 continue; | |
| 451 if (o->GetSelectionState() == SelectionState::kNone) | |
| 452 continue; | 456 continue; |
| 453 | 457 |
| 454 o->SetShouldInvalidateSelection(); | 458 runner->SetShouldInvalidateSelection(); |
| 455 } | 459 } |
| 456 } | 460 } |
| 457 | 461 |
| 458 DEFINE_TRACE(LayoutSelection) { | 462 DEFINE_TRACE(LayoutSelection) { |
| 459 visitor->Trace(frame_selection_); | 463 visitor->Trace(frame_selection_); |
| 460 } | 464 } |
| 461 | 465 |
| 462 } // namespace blink | 466 } // namespace blink |
| OLD | NEW |