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 14 matching lines...) Expand all Loading... | |
| 25 #include "core/editing/EditingUtilities.h" | 25 #include "core/editing/EditingUtilities.h" |
| 26 #include "core/editing/FrameSelection.h" | 26 #include "core/editing/FrameSelection.h" |
| 27 #include "core/editing/VisiblePosition.h" | 27 #include "core/editing/VisiblePosition.h" |
| 28 #include "core/editing/VisibleUnits.h" | 28 #include "core/editing/VisibleUnits.h" |
| 29 #include "core/html/TextControlElement.h" | 29 #include "core/html/TextControlElement.h" |
| 30 #include "core/layout/LayoutView.h" | 30 #include "core/layout/LayoutView.h" |
| 31 #include "core/paint/PaintLayer.h" | 31 #include "core/paint/PaintLayer.h" |
| 32 | 32 |
| 33 namespace blink { | 33 namespace blink { |
| 34 | 34 |
| 35 SelectionPaintRange::SelectionPaintRange(LayoutObject* start_layout_object, | |
| 36 int start_offset, | |
| 37 LayoutObject* end_layout_object, | |
| 38 int end_offset) | |
| 39 : start_layout_object_(start_layout_object), | |
| 40 start_offset_(start_offset), | |
| 41 end_layout_object_(end_layout_object), | |
| 42 end_offset_(end_offset) { | |
| 43 DCHECK(start_layout_object_); | |
| 44 DCHECK(end_layout_object_); | |
| 45 if (start_layout_object_ == end_layout_object_) | |
|
yosin_UTC9
2017/05/25 04:29:15
nit: early-return style is better.
yoichio
2017/05/25 08:29:03
Done.
| |
| 46 DCHECK_LT(start_offset_, end_offset_); | |
| 47 } | |
| 48 | |
| 49 bool SelectionPaintRange::operator==(const SelectionPaintRange& other) const { | |
| 50 return start_layout_object_ == other.start_layout_object_ && | |
| 51 start_offset_ == other.start_offset_ && | |
| 52 end_layout_object_ == other.end_layout_object_ && | |
| 53 end_offset_ == other.end_offset_; | |
| 54 } | |
| 55 | |
| 56 LayoutObject* SelectionPaintRange::StartLayoutObject() const { | |
| 57 DCHECK(!IsNull()); | |
| 58 return start_layout_object_; | |
| 59 } | |
| 60 | |
| 61 int SelectionPaintRange::StartOffset() const { | |
| 62 DCHECK(!IsNull()); | |
| 63 return start_offset_; | |
| 64 } | |
| 65 | |
| 66 LayoutObject* SelectionPaintRange::EndLayoutObject() const { | |
| 67 DCHECK(!IsNull()); | |
| 68 return end_layout_object_; | |
| 69 } | |
| 70 | |
| 71 int SelectionPaintRange::EndOffset() const { | |
| 72 DCHECK(!IsNull()); | |
| 73 return end_offset_; | |
| 74 } | |
| 75 | |
| 35 LayoutSelection::LayoutSelection(FrameSelection& frame_selection) | 76 LayoutSelection::LayoutSelection(FrameSelection& frame_selection) |
| 36 : frame_selection_(&frame_selection), | 77 : frame_selection_(&frame_selection), |
| 37 has_pending_selection_(false), | 78 has_pending_selection_(false), |
| 38 selection_start_(nullptr), | 79 paint_range_(SelectionPaintRange()) {} |
| 39 selection_end_(nullptr), | |
| 40 selection_start_pos_(-1), | |
| 41 selection_end_pos_(-1) {} | |
| 42 | 80 |
| 43 SelectionInFlatTree LayoutSelection::CalcVisibleSelection( | 81 SelectionInFlatTree LayoutSelection::CalcVisibleSelection( |
| 44 const VisibleSelectionInFlatTree& original_selection) const { | 82 const VisibleSelectionInFlatTree& original_selection) const { |
| 45 const PositionInFlatTree& start = original_selection.Start(); | 83 const PositionInFlatTree& start = original_selection.Start(); |
| 46 const PositionInFlatTree& end = original_selection.end(); | 84 const PositionInFlatTree& end = original_selection.end(); |
| 47 SelectionType selection_type = original_selection.GetSelectionType(); | 85 SelectionType selection_type = original_selection.GetSelectionType(); |
| 48 const TextAffinity affinity = original_selection.Affinity(); | 86 const TextAffinity affinity = original_selection.Affinity(); |
| 49 | 87 |
| 50 bool paint_block_cursor = | 88 bool paint_block_cursor = |
| 51 frame_selection_->ShouldShowBlockCursor() && | 89 frame_selection_->ShouldShowBlockCursor() && |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 117 SelectedMap(SelectedMap&& other) { | 155 SelectedMap(SelectedMap&& other) { |
| 118 object_map = std::move(other.object_map); | 156 object_map = std::move(other.object_map); |
| 119 block_map = std::move(other.block_map); | 157 block_map = std::move(other.block_map); |
| 120 } | 158 } |
| 121 | 159 |
| 122 private: | 160 private: |
| 123 DISALLOW_COPY_AND_ASSIGN(SelectedMap); | 161 DISALLOW_COPY_AND_ASSIGN(SelectedMap); |
| 124 }; | 162 }; |
| 125 | 163 |
| 126 static SelectedMap CollectSelectedMap( | 164 static SelectedMap CollectSelectedMap( |
| 127 LayoutObject* selection_start, | 165 const SelectionPaintRange& range, |
| 128 LayoutObject* selection_end, | |
| 129 int selection_end_pos, | |
| 130 LayoutSelection::SelectionPaintInvalidationMode | 166 LayoutSelection::SelectionPaintInvalidationMode |
| 131 block_paint_invalidation_mode) { | 167 block_paint_invalidation_mode) { |
| 168 DCHECK(!range.IsNull()); | |
| 132 SelectedMap selected_map; | 169 SelectedMap selected_map; |
| 133 | 170 |
| 134 LayoutObject* const stop = | 171 LayoutObject* const stop = |
| 135 LayoutObjectAfterPosition(selection_end, selection_end_pos); | 172 LayoutObjectAfterPosition(range.EndLayoutObject(), range.EndOffset()); |
| 136 for (LayoutObject* runner = selection_start; runner && (runner != stop); | 173 for (LayoutObject* runner = range.StartLayoutObject(); |
| 137 runner = runner->NextInPreOrder()) { | 174 runner && (runner != stop); runner = runner->NextInPreOrder()) { |
| 138 if (!runner->CanBeSelectionLeaf() && runner != selection_start && | 175 if (!runner->CanBeSelectionLeaf() && runner != range.StartLayoutObject() && |
| 139 runner != selection_end) | 176 runner != range.EndLayoutObject()) |
| 140 continue; | 177 continue; |
| 141 if (runner->GetSelectionState() == SelectionNone) | 178 if (runner->GetSelectionState() == SelectionNone) |
| 142 continue; | 179 continue; |
| 143 | 180 |
| 144 // Blocks are responsible for painting line gaps and margin gaps. They | 181 // Blocks are responsible for painting line gaps and margin gaps. They |
| 145 // must be examined as well. | 182 // must be examined as well. |
| 146 selected_map.object_map.Set(runner, runner->GetSelectionState()); | 183 selected_map.object_map.Set(runner, runner->GetSelectionState()); |
| 147 if (block_paint_invalidation_mode == | 184 if (block_paint_invalidation_mode == |
| 148 LayoutSelection::kPaintInvalidationNewXOROld) { | 185 LayoutSelection::kPaintInvalidationNewXOROld) { |
| 149 LayoutBlock* containing_block = runner->ContainingBlock(); | 186 LayoutBlock* containing_block = runner->ContainingBlock(); |
| 150 while (containing_block && !containing_block->IsLayoutView()) { | 187 while (containing_block && !containing_block->IsLayoutView()) { |
| 151 SelectedBlockMap::AddResult result = selected_map.block_map.insert( | 188 SelectedBlockMap::AddResult result = selected_map.block_map.insert( |
| 152 containing_block, containing_block->GetSelectionState()); | 189 containing_block, containing_block->GetSelectionState()); |
| 153 if (!result.is_new_entry) | 190 if (!result.is_new_entry) |
| 154 break; | 191 break; |
| 155 containing_block = containing_block->ContainingBlock(); | 192 containing_block = containing_block->ContainingBlock(); |
| 156 } | 193 } |
| 157 } | 194 } |
| 158 } | 195 } |
| 159 return selected_map; | 196 return selected_map; |
| 160 } | 197 } |
| 161 | 198 |
| 162 // Update the selection status of all LayoutObjects between |start| and |end|. | 199 // Update the selection status of all LayoutObjects between |start| and |end|. |
| 163 static void SetSelectionState(LayoutObject* start, | 200 static void SetSelectionState(const SelectionPaintRange& range) { |
| 164 LayoutObject* end, | 201 DCHECK(!range.IsNull()); |
| 165 int end_pos) { | 202 if (range.StartLayoutObject() == range.EndLayoutObject()) { |
| 166 if (start && start == end) { | 203 range.StartLayoutObject()->SetSelectionStateIfNeeded(SelectionBoth); |
| 167 start->SetSelectionStateIfNeeded(SelectionBoth); | |
| 168 } else { | 204 } else { |
| 169 if (start) | 205 range.StartLayoutObject()->SetSelectionStateIfNeeded(SelectionStart); |
| 170 start->SetSelectionStateIfNeeded(SelectionStart); | 206 range.EndLayoutObject()->SetSelectionStateIfNeeded(SelectionEnd); |
| 171 if (end) | |
| 172 end->SetSelectionStateIfNeeded(SelectionEnd); | |
| 173 } | 207 } |
| 174 | 208 |
| 175 LayoutObject* const stop = LayoutObjectAfterPosition(end, end_pos); | 209 LayoutObject* const stop = |
| 176 for (LayoutObject* runner = start; runner && runner != stop; | 210 LayoutObjectAfterPosition(range.EndLayoutObject(), range.EndOffset()); |
| 177 runner = runner->NextInPreOrder()) { | 211 for (LayoutObject* runner = range.StartLayoutObject(); |
| 178 if (runner != start && runner != end && runner->CanBeSelectionLeaf()) | 212 runner && runner != stop; runner = runner->NextInPreOrder()) { |
| 213 if (runner != range.StartLayoutObject() && | |
|
yosin_UTC9
2017/05/25 04:29:16
We have a pattern her:
L213
runner != range.start
yoichio
2017/05/25 08:29:03
Acknowledged.
yosin_UTC9
2017/05/25 09:40:31
What do you mean "Acknowledged"? I would like to i
| |
| 214 runner != range.EndLayoutObject() && runner->CanBeSelectionLeaf()) | |
| 179 runner->SetSelectionStateIfNeeded(SelectionInside); | 215 runner->SetSelectionStateIfNeeded(SelectionInside); |
| 180 } | 216 } |
| 181 } | 217 } |
| 182 | 218 |
| 183 void LayoutSelection::SetSelection( | 219 void LayoutSelection::SetSelection( |
| 184 LayoutObject* start, | 220 const SelectionPaintRange& new_range, |
| 185 int start_pos, | |
| 186 LayoutObject* end, | |
| 187 int end_pos, | |
| 188 SelectionPaintInvalidationMode block_paint_invalidation_mode) { | 221 SelectionPaintInvalidationMode block_paint_invalidation_mode) { |
| 189 DCHECK(start); | 222 DCHECK(!new_range.IsNull()); |
| 190 DCHECK(end); | |
| 191 | 223 |
| 192 // Just return if the selection hasn't changed. | 224 // Just return if the selection hasn't changed. |
| 193 if (selection_start_ == start && selection_start_pos_ == start_pos && | 225 if (paint_range_ == new_range) |
| 194 selection_end_ == end && selection_end_pos_ == end_pos) | |
| 195 return; | 226 return; |
| 196 | 227 |
| 197 DCHECK(frame_selection_->GetDocument().GetLayoutView()->GetFrameView()); | 228 DCHECK(frame_selection_->GetDocument().GetLayoutView()->GetFrameView()); |
| 198 DCHECK(!frame_selection_->GetDocument().NeedsLayoutTreeUpdate()); | 229 DCHECK(!frame_selection_->GetDocument().NeedsLayoutTreeUpdate()); |
| 199 | 230 |
| 200 SelectedMap old_selected_map = | 231 SelectedMap old_selected_map = |
| 201 CollectSelectedMap(selection_start_, selection_end_, selection_end_pos_, | 232 CollectSelectedMap(paint_range_, block_paint_invalidation_mode); |
| 202 block_paint_invalidation_mode); | |
| 203 | 233 |
| 204 // Now clear the selection. | 234 // Now clear the selection. |
| 205 for (auto layout_object : old_selected_map.object_map.Keys()) | 235 for (auto layout_object : old_selected_map.object_map.Keys()) |
| 206 layout_object->SetSelectionStateIfNeeded(SelectionNone); | 236 layout_object->SetSelectionStateIfNeeded(SelectionNone); |
| 207 | 237 |
| 208 SetSelectionState(start, end, end_pos); | 238 SetSelectionState(new_range); |
| 209 | 239 |
| 210 // Now that the selection state has been updated for the new objects, walk | 240 // Now that the selection state has been updated for the new objects, walk |
| 211 // them again and put them in the new objects list. | 241 // them again and put them in the new objects list. |
| 212 // TODO(editing-dev): |new_selected_map| doesn't really need to store the | 242 // TODO(editing-dev): |new_selected_map| doesn't really need to store the |
| 213 // SelectionState, it's just more convenient to have it use the same data | 243 // SelectionState, it's just more convenient to have it use the same data |
| 214 // structure as |old_selected_map|. | 244 // structure as |old_selected_map|. |
| 215 SelectedMap new_selected_map = | 245 SelectedMap new_selected_map = |
| 216 CollectSelectedMap(start, end, end_pos, kPaintInvalidationNewXOROld); | 246 CollectSelectedMap(new_range, kPaintInvalidationNewXOROld); |
| 217 | 247 |
| 218 // Have any of the old selected objects changed compared to the new selection? | 248 // Have any of the old selected objects changed compared to the new selection? |
| 219 for (const auto& pair : old_selected_map.object_map) { | 249 for (const auto& pair : old_selected_map.object_map) { |
| 220 LayoutObject* obj = pair.key; | 250 LayoutObject* obj = pair.key; |
| 221 SelectionState new_selection_state = obj->GetSelectionState(); | 251 SelectionState new_selection_state = obj->GetSelectionState(); |
| 222 SelectionState old_selection_state = pair.value; | 252 SelectionState old_selection_state = pair.value; |
| 223 if (new_selection_state != old_selection_state || | 253 if (new_selection_state != old_selection_state || |
| 224 (start == obj && start_pos != selection_start_pos_) || | 254 (new_range.StartLayoutObject() == obj && |
| 225 (end == obj && end_pos != selection_end_pos_)) { | 255 new_range.StartOffset() != paint_range_.StartOffset()) || |
| 256 (new_range.EndLayoutObject() == obj && | |
| 257 new_range.EndOffset() != paint_range_.EndOffset())) { | |
| 226 obj->SetShouldInvalidateSelection(); | 258 obj->SetShouldInvalidateSelection(); |
| 227 new_selected_map.object_map.erase(obj); | 259 new_selected_map.object_map.erase(obj); |
| 228 } | 260 } |
| 229 } | 261 } |
| 230 | 262 |
| 231 // Any new objects that remain were not found in the old objects dict, and so | 263 // Any new objects that remain were not found in the old objects dict, and so |
| 232 // they need to be updated. | 264 // they need to be updated. |
| 233 for (auto layout_object : new_selected_map.object_map.Keys()) | 265 for (auto layout_object : new_selected_map.object_map.Keys()) |
| 234 layout_object->SetShouldInvalidateSelection(); | 266 layout_object->SetShouldInvalidateSelection(); |
| 235 | 267 |
| 236 // Have any of the old blocks changed? | 268 // Have any of the old blocks changed? |
| 237 for (const auto& pair : old_selected_map.block_map) { | 269 for (const auto& pair : old_selected_map.block_map) { |
| 238 LayoutBlock* block = pair.key; | 270 LayoutBlock* block = pair.key; |
| 239 SelectionState new_selection_state = block->GetSelectionState(); | 271 SelectionState new_selection_state = block->GetSelectionState(); |
| 240 SelectionState old_selection_state = pair.value; | 272 SelectionState old_selection_state = pair.value; |
| 241 if (new_selection_state != old_selection_state) { | 273 if (new_selection_state != old_selection_state) { |
| 242 block->SetShouldInvalidateSelection(); | 274 block->SetShouldInvalidateSelection(); |
| 243 new_selected_map.block_map.erase(block); | 275 new_selected_map.block_map.erase(block); |
| 244 } | 276 } |
| 245 } | 277 } |
| 246 | 278 |
| 247 // Any new blocks that remain were not found in the old blocks dict, and so | 279 // Any new blocks that remain were not found in the old blocks dict, and so |
| 248 // they need to be updated. | 280 // they need to be updated. |
| 249 for (auto layout_object : new_selected_map.block_map.Keys()) | 281 for (auto layout_object : new_selected_map.block_map.Keys()) |
| 250 layout_object->SetShouldInvalidateSelection(); | 282 layout_object->SetShouldInvalidateSelection(); |
| 251 | 283 |
| 252 // set selection start and end | 284 paint_range_ = new_range; |
| 253 selection_start_ = start; | |
| 254 selection_start_pos_ = start_pos; | |
| 255 selection_end_ = end; | |
| 256 selection_end_pos_ = end_pos; | |
| 257 } | 285 } |
| 258 | 286 |
| 259 std::pair<int, int> LayoutSelection::SelectionStartEnd() { | 287 std::pair<int, int> LayoutSelection::SelectionStartEnd() { |
| 260 Commit(); | 288 Commit(); |
| 261 return std::make_pair(selection_start_pos_, selection_end_pos_); | 289 return std::make_pair(paint_range_.StartOffset(), paint_range_.EndOffset()); |
| 262 } | 290 } |
| 263 | 291 |
| 264 void LayoutSelection::ClearSelection() { | 292 void LayoutSelection::ClearSelection() { |
| 265 // For querying Layer::compositingState() | 293 // For querying Layer::compositingState() |
| 266 // This is correct, since destroying layout objects needs to cause eager paint | 294 // This is correct, since destroying layout objects needs to cause eager paint |
| 267 // invalidations. | 295 // invalidations. |
| 268 DisableCompositingQueryAsserts disabler; | 296 DisableCompositingQueryAsserts disabler; |
| 269 | 297 |
| 270 // Just return if the selection hasn't changed. | 298 // Just return if the selection is already empty. |
| 271 if (!selection_start_) { | 299 if (paint_range_.IsNull()) |
| 272 DCHECK_EQ(selection_end_, nullptr); | |
| 273 DCHECK_EQ(selection_start_pos_, -1); | |
| 274 DCHECK_EQ(selection_end_pos_, -1); | |
| 275 return; | 300 return; |
| 276 } | |
| 277 | 301 |
| 278 const SelectedMap& old_selected_map = | 302 const SelectedMap& old_selected_map = |
| 279 CollectSelectedMap(selection_start_, selection_end_, selection_end_pos_, | 303 CollectSelectedMap(paint_range_, kPaintInvalidationNewMinusOld); |
| 280 kPaintInvalidationNewMinusOld); | |
| 281 // Clear SelectionState and invalidation. | 304 // Clear SelectionState and invalidation. |
| 282 for (auto layout_object : old_selected_map.object_map.Keys()) { | 305 for (auto layout_object : old_selected_map.object_map.Keys()) { |
| 283 const SelectionState old_state = layout_object->GetSelectionState(); | 306 const SelectionState old_state = layout_object->GetSelectionState(); |
| 284 layout_object->SetSelectionStateIfNeeded(SelectionNone); | 307 layout_object->SetSelectionStateIfNeeded(SelectionNone); |
| 285 if (layout_object->GetSelectionState() == old_state) | 308 if (layout_object->GetSelectionState() == old_state) |
| 286 continue; | 309 continue; |
| 287 layout_object->SetShouldInvalidateSelection(); | 310 layout_object->SetShouldInvalidateSelection(); |
| 288 } | 311 } |
| 289 | 312 |
| 290 // Reset selection start and end. | 313 // Reset selection. |
| 291 selection_start_ = nullptr; | 314 paint_range_ = SelectionPaintRange(); |
| 292 selection_start_pos_ = -1; | |
| 293 selection_end_ = nullptr; | |
| 294 selection_end_pos_ = -1; | |
| 295 } | 315 } |
| 296 | 316 |
| 297 void LayoutSelection::Commit() { | 317 void LayoutSelection::Commit() { |
| 298 if (!HasPendingSelection()) | 318 if (!HasPendingSelection()) |
| 299 return; | 319 return; |
| 300 has_pending_selection_ = false; | 320 has_pending_selection_ = false; |
| 301 | 321 |
| 302 const VisibleSelectionInFlatTree& original_selection = | 322 const VisibleSelectionInFlatTree& original_selection = |
| 303 frame_selection_->ComputeVisibleSelectionInFlatTree(); | 323 frame_selection_->ComputeVisibleSelectionInFlatTree(); |
| 304 | 324 |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 335 if (start_pos.IsNull() || end_pos.IsNull() || | 355 if (start_pos.IsNull() || end_pos.IsNull() || |
| 336 selection.VisibleStart().DeepEquivalent() == | 356 selection.VisibleStart().DeepEquivalent() == |
| 337 selection.VisibleEnd().DeepEquivalent()) | 357 selection.VisibleEnd().DeepEquivalent()) |
| 338 return; | 358 return; |
| 339 DCHECK_LE(start_pos, end_pos); | 359 DCHECK_LE(start_pos, end_pos); |
| 340 LayoutObject* start_layout_object = start_pos.AnchorNode()->GetLayoutObject(); | 360 LayoutObject* start_layout_object = start_pos.AnchorNode()->GetLayoutObject(); |
| 341 LayoutObject* end_layout_object = end_pos.AnchorNode()->GetLayoutObject(); | 361 LayoutObject* end_layout_object = end_pos.AnchorNode()->GetLayoutObject(); |
| 342 if (!start_layout_object || !end_layout_object) | 362 if (!start_layout_object || !end_layout_object) |
| 343 return; | 363 return; |
| 344 DCHECK(start_layout_object->View() == end_layout_object->View()); | 364 DCHECK(start_layout_object->View() == end_layout_object->View()); |
| 345 SetSelection(start_layout_object, start_pos.ComputeEditingOffset(), | 365 SetSelection( |
| 346 end_layout_object, end_pos.ComputeEditingOffset()); | 366 SelectionPaintRange(start_layout_object, start_pos.ComputeEditingOffset(), |
| 367 end_layout_object, end_pos.ComputeEditingOffset())); | |
| 347 } | 368 } |
| 348 | 369 |
| 349 void LayoutSelection::OnDocumentShutdown() { | 370 void LayoutSelection::OnDocumentShutdown() { |
| 350 has_pending_selection_ = false; | 371 has_pending_selection_ = false; |
| 351 selection_start_ = nullptr; | 372 paint_range_ = SelectionPaintRange(); |
| 352 selection_end_ = nullptr; | |
| 353 selection_start_pos_ = -1; | |
| 354 selection_end_pos_ = -1; | |
| 355 } | 373 } |
| 356 | 374 |
| 357 static LayoutRect SelectionRectForLayoutObject(const LayoutObject* object) { | 375 static LayoutRect SelectionRectForLayoutObject(const LayoutObject* object) { |
| 358 if (!object->IsRooted()) | 376 if (!object->IsRooted()) |
| 359 return LayoutRect(); | 377 return LayoutRect(); |
| 360 | 378 |
| 361 if (!object->CanUpdateSelectionOnRootLineBoxes()) | 379 if (!object->CanUpdateSelectionOnRootLineBoxes()) |
| 362 return LayoutRect(); | 380 return LayoutRect(); |
| 363 | 381 |
| 364 return object->SelectionRectInViewCoordinates(); | 382 return object->SelectionRectInViewCoordinates(); |
| 365 } | 383 } |
| 366 | 384 |
| 367 IntRect LayoutSelection::SelectionBounds() { | 385 IntRect LayoutSelection::SelectionBounds() { |
| 368 // Now create a single bounding box rect that encloses the whole selection. | 386 // Now create a single bounding box rect that encloses the whole selection. |
| 369 LayoutRect sel_rect; | 387 LayoutRect sel_rect; |
| 370 | 388 |
| 371 typedef HashSet<const LayoutBlock*> VisitedContainingBlockSet; | 389 typedef HashSet<const LayoutBlock*> VisitedContainingBlockSet; |
| 372 VisitedContainingBlockSet visited_containing_blocks; | 390 VisitedContainingBlockSet visited_containing_blocks; |
| 373 | 391 |
| 374 Commit(); | 392 Commit(); |
| 375 LayoutObject* os = selection_start_; | 393 LayoutObject* os = paint_range_.StartLayoutObject(); |
| 376 LayoutObject* stop = | 394 LayoutObject* stop = LayoutObjectAfterPosition(paint_range_.EndLayoutObject(), |
| 377 LayoutObjectAfterPosition(selection_end_, selection_end_pos_); | 395 paint_range_.EndOffset()); |
| 378 while (os && os != stop) { | 396 while (os && os != stop) { |
|
yosin_UTC9
2017/05/25 04:29:16
Note: We can rewrite this while-statement to for-s
yoichio
2017/05/25 08:29:03
Acknowledged.
yosin_UTC9
2017/05/25 09:40:31
Since introducing iterator is big. We should do in
| |
| 379 if ((os->CanBeSelectionLeaf() || os == selection_start_ || | 397 if ((os->CanBeSelectionLeaf() || os == paint_range_.StartLayoutObject() || |
| 380 os == selection_end_) && | 398 os == paint_range_.EndLayoutObject()) && |
| 381 os->GetSelectionState() != SelectionNone) { | 399 os->GetSelectionState() != SelectionNone) { |
| 382 // Blocks are responsible for painting line gaps and margin gaps. They | 400 // Blocks are responsible for painting line gaps and margin gaps. They |
| 383 // must be examined as well. | 401 // must be examined as well. |
| 384 sel_rect.Unite(SelectionRectForLayoutObject(os)); | 402 sel_rect.Unite(SelectionRectForLayoutObject(os)); |
| 385 const LayoutBlock* cb = os->ContainingBlock(); | 403 const LayoutBlock* cb = os->ContainingBlock(); |
| 386 while (cb && !cb->IsLayoutView()) { | 404 while (cb && !cb->IsLayoutView()) { |
| 387 sel_rect.Unite(SelectionRectForLayoutObject(cb)); | 405 sel_rect.Unite(SelectionRectForLayoutObject(cb)); |
| 388 VisitedContainingBlockSet::AddResult add_result = | 406 VisitedContainingBlockSet::AddResult add_result = |
| 389 visited_containing_blocks.insert(cb); | 407 visited_containing_blocks.insert(cb); |
| 390 if (!add_result.is_new_entry) | 408 if (!add_result.is_new_entry) |
| 391 break; | 409 break; |
| 392 cb = cb->ContainingBlock(); | 410 cb = cb->ContainingBlock(); |
| 393 } | 411 } |
| 394 } | 412 } |
| 395 | 413 |
| 396 os = os->NextInPreOrder(); | 414 os = os->NextInPreOrder(); |
| 397 } | 415 } |
| 398 | 416 |
| 399 return PixelSnappedIntRect(sel_rect); | 417 return PixelSnappedIntRect(sel_rect); |
| 400 } | 418 } |
| 401 | 419 |
| 402 void LayoutSelection::InvalidatePaintForSelection() { | 420 void LayoutSelection::InvalidatePaintForSelection() { |
| 403 LayoutObject* end = | 421 LayoutObject* end = LayoutObjectAfterPosition(paint_range_.EndLayoutObject(), |
| 404 LayoutObjectAfterPosition(selection_end_, selection_end_pos_); | 422 paint_range_.EndOffset()); |
| 405 for (LayoutObject* o = selection_start_; o && o != end; | 423 for (LayoutObject* o = paint_range_.StartLayoutObject(); o && o != end; |
| 406 o = o->NextInPreOrder()) { | 424 o = o->NextInPreOrder()) { |
| 407 if (!o->CanBeSelectionLeaf() && o != selection_start_ && | 425 if (!o->CanBeSelectionLeaf() && o != paint_range_.StartLayoutObject() && |
| 408 o != selection_end_) | 426 o != paint_range_.EndLayoutObject()) |
| 409 continue; | 427 continue; |
| 410 if (o->GetSelectionState() == SelectionNone) | 428 if (o->GetSelectionState() == SelectionNone) |
| 411 continue; | 429 continue; |
| 412 | 430 |
| 413 o->SetShouldInvalidateSelection(); | 431 o->SetShouldInvalidateSelection(); |
| 414 } | 432 } |
| 415 } | 433 } |
| 416 | 434 |
| 417 DEFINE_TRACE(LayoutSelection) { | 435 DEFINE_TRACE(LayoutSelection) { |
| 418 visitor->Trace(frame_selection_); | 436 visitor->Trace(frame_selection_); |
| 419 } | 437 } |
| 420 | 438 |
| 421 } // namespace blink | 439 } // namespace blink |
| OLD | NEW |