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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
93 | 93 |
94 static LayoutObject* LayoutObjectAfterPosition(LayoutObject* object, | 94 static LayoutObject* LayoutObjectAfterPosition(LayoutObject* object, |
95 unsigned offset) { | 95 unsigned offset) { |
96 if (!object) | 96 if (!object) |
97 return nullptr; | 97 return nullptr; |
98 | 98 |
99 LayoutObject* child = object->ChildAt(offset); | 99 LayoutObject* child = object->ChildAt(offset); |
100 return child ? child : object->NextInPreOrderAfterChildren(); | 100 return child ? child : object->NextInPreOrderAfterChildren(); |
101 } | 101 } |
102 | 102 |
103 // When exploring the LayoutTree looking for the nodes involved in the | |
104 // Selection, sometimes it's required to change the traversing direction because | |
105 // the "start" position is below the "end" one. | |
yosin_UTC9
2017/05/23 09:01:36
It seems patch[1] introduce backward traversal to
| |
106 static inline LayoutObject* GetNextOrPrevLayoutObjectBasedOnDirection( | |
107 const LayoutObject* o, | |
108 const LayoutObject* stop, | |
109 bool& continue_exploring, | |
110 bool& exploring_backwards) { | |
111 LayoutObject* next; | |
112 if (exploring_backwards) { | |
113 next = o->PreviousInPreOrder(); | |
114 continue_exploring = next && !(next)->IsLayoutView(); | |
115 } else { | |
116 next = o->NextInPreOrder(); | |
117 continue_exploring = next && next != stop; | |
118 exploring_backwards = !next && (next != stop); | |
119 if (exploring_backwards) { | |
120 next = stop->PreviousInPreOrder(); | |
121 continue_exploring = next && !next->IsLayoutView(); | |
122 } | |
123 } | |
124 | |
125 return next; | |
126 } | |
127 | |
128 // Objects each have a single selection rect to examine. | 103 // Objects each have a single selection rect to examine. |
129 using SelectedObjectMap = HashMap<LayoutObject*, SelectionState>; | 104 using SelectedObjectMap = HashMap<LayoutObject*, SelectionState>; |
130 // Blocks contain selected objects and fill gaps between them, either on the | 105 // Blocks contain selected objects and fill gaps between them, either on the |
131 // left, right, or in between lines and blocks. | 106 // left, right, or in between lines and blocks. |
132 // In order to get the visual rect right, we have to examine left, middle, and | 107 // In order to get the visual rect right, we have to examine left, middle, and |
133 // right rects individually, since otherwise the union of those rects might | 108 // right rects individually, since otherwise the union of those rects might |
134 // remain the same even when changes have occurred. | 109 // remain the same even when changes have occurred. |
135 using SelectedBlockMap = HashMap<LayoutBlock*, SelectionState>; | 110 using SelectedBlockMap = HashMap<LayoutBlock*, SelectionState>; |
136 struct SelectedMap { | 111 struct SelectedMap { |
137 STACK_ALLOCATED(); | 112 STACK_ALLOCATED(); |
(...skipping 10 matching lines...) Expand all Loading... | |
148 DISALLOW_COPY_AND_ASSIGN(SelectedMap); | 123 DISALLOW_COPY_AND_ASSIGN(SelectedMap); |
149 }; | 124 }; |
150 | 125 |
151 static SelectedMap CollectSelectedMap( | 126 static SelectedMap CollectSelectedMap( |
152 LayoutObject* selection_start, | 127 LayoutObject* selection_start, |
153 LayoutObject* selection_end, | 128 LayoutObject* selection_end, |
154 int selection_end_pos, | 129 int selection_end_pos, |
155 LayoutSelection::SelectionPaintInvalidationMode | 130 LayoutSelection::SelectionPaintInvalidationMode |
156 block_paint_invalidation_mode) { | 131 block_paint_invalidation_mode) { |
157 SelectedMap selected_map; | 132 SelectedMap selected_map; |
158 LayoutObject* runner = selection_start; | 133 |
159 LayoutObject* const stop = | 134 LayoutObject* const stop = |
160 LayoutObjectAfterPosition(selection_end, selection_end_pos); | 135 LayoutObjectAfterPosition(selection_end, selection_end_pos); |
161 bool exploring_backwards = false; | 136 for (LayoutObject* runner = selection_start; runner && (runner != stop); |
162 bool continue_exploring = runner && (runner != stop); | 137 runner = runner->NextInPreOrder()) { |
163 while (continue_exploring) { | 138 if (!runner->CanBeSelectionLeaf() && runner != selection_start && |
164 if ((runner->CanBeSelectionLeaf() || runner == selection_start || | 139 runner != selection_end) |
165 runner == selection_end) && | 140 continue; |
166 runner->GetSelectionState() != SelectionNone) { | 141 if (runner->GetSelectionState() == SelectionNone) |
167 // Blocks are responsible for painting line gaps and margin gaps. They | 142 continue; |
168 // must be examined as well. | 143 |
169 selected_map.object_map.Set(runner, runner->GetSelectionState()); | 144 // Blocks are responsible for painting line gaps and margin gaps. They |
170 if (block_paint_invalidation_mode == | 145 // must be examined as well. |
171 LayoutSelection::kPaintInvalidationNewXOROld) { | 146 selected_map.object_map.Set(runner, runner->GetSelectionState()); |
172 LayoutBlock* containing_block = runner->ContainingBlock(); | 147 if (block_paint_invalidation_mode == |
173 while (containing_block && !containing_block->IsLayoutView()) { | 148 LayoutSelection::kPaintInvalidationNewXOROld) { |
174 SelectedBlockMap::AddResult result = selected_map.block_map.insert( | 149 LayoutBlock* containing_block = runner->ContainingBlock(); |
175 containing_block, containing_block->GetSelectionState()); | 150 while (containing_block && !containing_block->IsLayoutView()) { |
176 if (!result.is_new_entry) | 151 SelectedBlockMap::AddResult result = selected_map.block_map.insert( |
177 break; | 152 containing_block, containing_block->GetSelectionState()); |
178 containing_block = containing_block->ContainingBlock(); | 153 if (!result.is_new_entry) |
179 } | 154 break; |
155 containing_block = containing_block->ContainingBlock(); | |
180 } | 156 } |
181 } | 157 } |
182 | |
183 runner = GetNextOrPrevLayoutObjectBasedOnDirection( | |
184 runner, stop, continue_exploring, exploring_backwards); | |
185 } | 158 } |
186 return selected_map; | 159 return selected_map; |
187 } | 160 } |
188 | 161 |
189 // Update the selection status of all LayoutObjects between |start| and |end|. | 162 // Update the selection status of all LayoutObjects between |start| and |end|. |
190 static void SetSelectionState(LayoutObject* start, | 163 static void SetSelectionState(LayoutObject* start, |
191 LayoutObject* end, | 164 LayoutObject* end, |
192 int end_pos) { | 165 int end_pos) { |
193 if (start && start == end) { | 166 if (start && start == end) { |
194 start->SetSelectionStateIfNeeded(SelectionBoth); | 167 start->SetSelectionStateIfNeeded(SelectionBoth); |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
339 if (IsVisuallyEquivalentCandidate(candidate)) | 312 if (IsVisuallyEquivalentCandidate(candidate)) |
340 end_pos = candidate; | 313 end_pos = candidate; |
341 | 314 |
342 // We can get into a state where the selection endpoints map to the same | 315 // We can get into a state where the selection endpoints map to the same |
343 // |VisiblePosition| when a selection is deleted because we don't yet notify | 316 // |VisiblePosition| when a selection is deleted because we don't yet notify |
344 // the |FrameSelection| of text removal. | 317 // the |FrameSelection| of text removal. |
345 if (start_pos.IsNull() || end_pos.IsNull() || | 318 if (start_pos.IsNull() || end_pos.IsNull() || |
346 selection.VisibleStart().DeepEquivalent() == | 319 selection.VisibleStart().DeepEquivalent() == |
347 selection.VisibleEnd().DeepEquivalent()) | 320 selection.VisibleEnd().DeepEquivalent()) |
348 return; | 321 return; |
322 DCHECK(start_pos <= end_pos); | |
yosin_UTC9
2017/05/23 09:01:36
nit: DCHECK_LE(start_pos, end_pos)
| |
349 LayoutObject* start_layout_object = start_pos.AnchorNode()->GetLayoutObject(); | 323 LayoutObject* start_layout_object = start_pos.AnchorNode()->GetLayoutObject(); |
350 LayoutObject* end_layout_object = end_pos.AnchorNode()->GetLayoutObject(); | 324 LayoutObject* end_layout_object = end_pos.AnchorNode()->GetLayoutObject(); |
351 if (!start_layout_object || !end_layout_object) | 325 if (!start_layout_object || !end_layout_object) |
352 return; | 326 return; |
353 DCHECK(start_layout_object->View() == end_layout_object->View()); | 327 DCHECK(start_layout_object->View() == end_layout_object->View()); |
354 SetSelection(start_layout_object, start_pos.ComputeEditingOffset(), | 328 SetSelection(start_layout_object, start_pos.ComputeEditingOffset(), |
355 end_layout_object, end_pos.ComputeEditingOffset()); | 329 end_layout_object, end_pos.ComputeEditingOffset()); |
356 } | 330 } |
357 | 331 |
358 void LayoutSelection::OnDocumentShutdown() { | 332 void LayoutSelection::OnDocumentShutdown() { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
421 | 395 |
422 o->SetShouldInvalidateSelection(); | 396 o->SetShouldInvalidateSelection(); |
423 } | 397 } |
424 } | 398 } |
425 | 399 |
426 DEFINE_TRACE(LayoutSelection) { | 400 DEFINE_TRACE(LayoutSelection) { |
427 visitor->Trace(frame_selection_); | 401 visitor->Trace(frame_selection_); |
428 } | 402 } |
429 | 403 |
430 } // namespace blink | 404 } // namespace blink |
OLD | NEW |