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