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 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
| 5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) | 5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
| 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights |
| 7 * reserved. | 7 * reserved. |
| 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. | 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. |
| 9 * (http://www.torchmobile.com/) | 9 * (http://www.torchmobile.com/) |
| 10 * Copyright (C) Research In Motion Limited 2010. All rights reserved. | 10 * Copyright (C) Research In Motion Limited 2010. All rights reserved. |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 * | 21 * |
| 22 * You should have received a copy of the GNU Library General Public License | 22 * You should have received a copy of the GNU Library General Public License |
| 23 * along with this library; see the file COPYING.LIB. If not, write to | 23 * along with this library; see the file COPYING.LIB. If not, write to |
| 24 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 24 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 25 * Boston, MA 02110-1301, USA. | 25 * Boston, MA 02110-1301, USA. |
| 26 * | 26 * |
| 27 */ | 27 */ |
| 28 | 28 |
| 29 #include "core/editing/markers/DocumentMarkerController.h" | 29 #include "core/editing/markers/DocumentMarkerController.h" |
| 30 | 30 |
| 31 #include <algorithm> | |
| 31 #include "core/dom/Node.h" | 32 #include "core/dom/Node.h" |
| 32 #include "core/dom/NodeTraversal.h" | 33 #include "core/dom/NodeTraversal.h" |
| 33 #include "core/dom/Range.h" | 34 #include "core/dom/Range.h" |
| 34 #include "core/dom/Text.h" | 35 #include "core/dom/Text.h" |
| 35 #include "core/editing/iterators/TextIterator.h" | 36 #include "core/editing/iterators/TextIterator.h" |
| 37 #include "core/editing/markers/DocumentMarkerListEditor.h" | |
| 36 #include "core/editing/markers/RenderedDocumentMarker.h" | 38 #include "core/editing/markers/RenderedDocumentMarker.h" |
| 37 #include "core/frame/FrameView.h" | 39 #include "core/frame/FrameView.h" |
| 38 #include "core/layout/LayoutObject.h" | 40 #include "core/layout/LayoutObject.h" |
| 39 #include <algorithm> | |
| 40 | 41 |
| 41 #ifndef NDEBUG | 42 #ifndef NDEBUG |
| 42 #include <stdio.h> | 43 #include <stdio.h> |
| 43 #endif | 44 #endif |
| 44 | 45 |
| 45 namespace blink { | 46 namespace blink { |
| 46 | 47 |
| 47 MarkerRemoverPredicate::MarkerRemoverPredicate(const Vector<String>& words) | 48 MarkerRemoverPredicate::MarkerRemoverPredicate(const Vector<String>& words) |
| 48 : words_(words) {} | 49 : words_(words) {} |
| 49 | 50 |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 168 | 169 |
| 169 void DocumentMarkerController::RemoveMarkers( | 170 void DocumentMarkerController::RemoveMarkers( |
| 170 const EphemeralRange& range, | 171 const EphemeralRange& range, |
| 171 DocumentMarker::MarkerTypes marker_types) { | 172 DocumentMarker::MarkerTypes marker_types) { |
| 172 DCHECK(!document_->NeedsLayoutTreeUpdate()); | 173 DCHECK(!document_->NeedsLayoutTreeUpdate()); |
| 173 | 174 |
| 174 TextIterator marked_text(range.StartPosition(), range.EndPosition()); | 175 TextIterator marked_text(range.StartPosition(), range.EndPosition()); |
| 175 DocumentMarkerController::RemoveMarkers(marked_text, marker_types); | 176 DocumentMarkerController::RemoveMarkers(marked_text, marker_types); |
| 176 } | 177 } |
| 177 | 178 |
| 178 static bool StartsFurther(const Member<RenderedDocumentMarker>& lhv, | |
| 179 const DocumentMarker* rhv) { | |
| 180 return lhv->StartOffset() < rhv->StartOffset(); | |
| 181 } | |
| 182 | |
| 183 static bool EndsBefore(size_t start_offset, | |
| 184 const Member<RenderedDocumentMarker>& rhv) { | |
| 185 return start_offset < rhv->EndOffset(); | |
| 186 } | |
| 187 | |
| 188 static bool CompareByStart(const Member<DocumentMarker>& lhv, | 179 static bool CompareByStart(const Member<DocumentMarker>& lhv, |
| 189 const Member<DocumentMarker>& rhv) { | 180 const Member<DocumentMarker>& rhv) { |
| 190 return lhv->StartOffset() < rhv->StartOffset(); | 181 return lhv->StartOffset() < rhv->StartOffset(); |
| 191 } | 182 } |
| 192 | 183 |
| 193 static bool DoesNotOverlap(const Member<RenderedDocumentMarker>& lhv, | |
| 194 const DocumentMarker* rhv) { | |
| 195 return lhv->EndOffset() < rhv->StartOffset(); | |
| 196 } | |
| 197 | |
| 198 static void UpdateMarkerRenderedRect(const Node& node, | 184 static void UpdateMarkerRenderedRect(const Node& node, |
| 199 RenderedDocumentMarker& marker) { | 185 RenderedDocumentMarker& marker) { |
| 200 Range* range = Range::Create(node.GetDocument()); | 186 Range* range = Range::Create(node.GetDocument()); |
| 201 // The offsets of the marker may be out-dated, so check for exceptions. | 187 // The offsets of the marker may be out-dated, so check for exceptions. |
| 202 DummyExceptionStateForTesting exception_state; | 188 DummyExceptionStateForTesting exception_state; |
| 203 range->setStart(&const_cast<Node&>(node), marker.StartOffset(), | 189 range->setStart(&const_cast<Node&>(node), marker.StartOffset(), |
| 204 exception_state); | 190 exception_state); |
| 205 if (!exception_state.HadException()) { | 191 if (!exception_state.HadException()) { |
| 206 range->setEnd(&const_cast<Node&>(node), marker.EndOffset(), | 192 range->setEnd(&const_cast<Node&>(node), marker.EndOffset(), |
| 207 IGNORE_EXCEPTION_FOR_TESTING); | 193 IGNORE_EXCEPTION_FOR_TESTING); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 241 Member<MarkerList>& list = ListForType(markers, new_marker_type); | 227 Member<MarkerList>& list = ListForType(markers, new_marker_type); |
| 242 DocumentMarkerListEditor::AddMarker(list, &new_marker); | 228 DocumentMarkerListEditor::AddMarker(list, &new_marker); |
| 243 | 229 |
| 244 // repaint the affected node | 230 // repaint the affected node |
| 245 if (node->GetLayoutObject()) { | 231 if (node->GetLayoutObject()) { |
| 246 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( | 232 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( |
| 247 kPaintInvalidationDocumentMarkerChange); | 233 kPaintInvalidationDocumentMarkerChange); |
| 248 } | 234 } |
| 249 } | 235 } |
| 250 | 236 |
| 251 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
| 252 // TODO(rlanday): this method was created by cutting and pasting code from | |
| 253 // DocumentMarkerController::AddMarker(), it should be refactored in a future CL | |
| 254 void DocumentMarkerListEditor::AddMarker(MarkerList* list, | |
| 255 const DocumentMarker* marker) { | |
| 256 RenderedDocumentMarker* rendered_marker = | |
| 257 RenderedDocumentMarker::Create(*marker); | |
| 258 if (list->IsEmpty() || list->back()->EndOffset() < marker->StartOffset()) { | |
| 259 list->push_back(rendered_marker); | |
| 260 } else { | |
| 261 if (marker->GetType() != DocumentMarker::kTextMatch && | |
| 262 marker->GetType() != DocumentMarker::kComposition) { | |
| 263 MergeOverlapping(list, rendered_marker); | |
| 264 } else { | |
| 265 MarkerList::iterator pos = | |
| 266 std::lower_bound(list->begin(), list->end(), marker, StartsFurther); | |
| 267 list->insert(pos - list->begin(), rendered_marker); | |
| 268 } | |
| 269 } | |
| 270 } | |
| 271 | |
| 272 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
| 273 void DocumentMarkerListEditor::MergeOverlapping( | |
| 274 MarkerList* list, | |
| 275 RenderedDocumentMarker* to_insert) { | |
| 276 MarkerList::iterator first_overlapping = | |
| 277 std::lower_bound(list->begin(), list->end(), to_insert, DoesNotOverlap); | |
| 278 size_t index = first_overlapping - list->begin(); | |
| 279 list->insert(index, to_insert); | |
| 280 MarkerList::iterator inserted = list->begin() + index; | |
| 281 first_overlapping = inserted + 1; | |
| 282 for (MarkerList::iterator i = first_overlapping; | |
| 283 i != list->end() && (*i)->StartOffset() <= (*inserted)->EndOffset();) { | |
| 284 (*inserted)->SetStartOffset( | |
| 285 std::min((*inserted)->StartOffset(), (*i)->StartOffset())); | |
| 286 (*inserted)->SetEndOffset( | |
| 287 std::max((*inserted)->EndOffset(), (*i)->EndOffset())); | |
| 288 list->erase(i - list->begin()); | |
| 289 } | |
| 290 } | |
| 291 | |
| 292 // Moves markers from src_node to dst_node. Markers are moved if their start | 237 // Moves markers from src_node to dst_node. Markers are moved if their start |
| 293 // offset is less than length. Markers that run past that point are truncated. | 238 // offset is less than length. Markers that run past that point are truncated. |
| 294 void DocumentMarkerController::MoveMarkers(Node* src_node, | 239 void DocumentMarkerController::MoveMarkers(Node* src_node, |
| 295 int length, | 240 int length, |
| 296 Node* dst_node) { | 241 Node* dst_node) { |
| 297 if (length <= 0) | 242 if (length <= 0) |
| 298 return; | 243 return; |
| 299 | 244 |
| 300 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers())) | 245 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers())) |
| 301 return; | 246 return; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 326 doc_dirty = true; | 271 doc_dirty = true; |
| 327 } | 272 } |
| 328 | 273 |
| 329 // repaint the affected node | 274 // repaint the affected node |
| 330 if (doc_dirty && dst_node->GetLayoutObject()) { | 275 if (doc_dirty && dst_node->GetLayoutObject()) { |
| 331 dst_node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( | 276 dst_node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( |
| 332 kPaintInvalidationDocumentMarkerChange); | 277 kPaintInvalidationDocumentMarkerChange); |
| 333 } | 278 } |
| 334 } | 279 } |
| 335 | 280 |
| 336 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
| 337 bool DocumentMarkerListEditor::MoveMarkers(MarkerList* src_list, | |
| 338 int length, | |
| 339 MarkerList* dst_list) { | |
| 340 DCHECK_GT(length, 0); | |
| 341 bool doc_dirty = false; | |
| 342 const unsigned end_offset = length - 1; | |
| 343 MarkerList::iterator it; | |
| 344 for (it = src_list->begin(); it != src_list->end(); ++it) { | |
| 345 DocumentMarker* marker = it->Get(); | |
| 346 | |
| 347 // stop if we are now past the specified range | |
| 348 if (marker->StartOffset() > end_offset) | |
| 349 break; | |
| 350 | |
| 351 // pin the marker to the specified range | |
| 352 doc_dirty = true; | |
| 353 if (marker->EndOffset() > end_offset) | |
| 354 marker->SetEndOffset(end_offset); | |
| 355 | |
| 356 DocumentMarkerListEditor::AddMarker(dst_list, marker); | |
| 357 } | |
| 358 | |
| 359 // Remove the range of markers that were moved to dst_node | |
| 360 src_list->erase(0, it - src_list->begin()); | |
| 361 | |
| 362 return doc_dirty; | |
| 363 } | |
| 364 | |
| 365 void DocumentMarkerController::RemoveMarkers( | 281 void DocumentMarkerController::RemoveMarkers( |
| 366 Node* node, | 282 Node* node, |
| 367 unsigned start_offset, | 283 unsigned start_offset, |
| 368 int length, | 284 int length, |
| 369 DocumentMarker::MarkerTypes marker_types) { | 285 DocumentMarker::MarkerTypes marker_types) { |
| 370 if (length <= 0) | 286 if (length <= 0) |
| 371 return; | 287 return; |
| 372 | 288 |
| 373 if (!PossiblyHasMarkers(marker_types)) | 289 if (!PossiblyHasMarkers(marker_types)) |
| 374 return; | 290 return; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 408 possibly_existing_marker_types_ = 0; | 324 possibly_existing_marker_types_ = 0; |
| 409 } | 325 } |
| 410 | 326 |
| 411 // repaint the affected node | 327 // repaint the affected node |
| 412 if (doc_dirty && node->GetLayoutObject()) { | 328 if (doc_dirty && node->GetLayoutObject()) { |
| 413 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( | 329 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( |
| 414 kPaintInvalidationDocumentMarkerChange); | 330 kPaintInvalidationDocumentMarkerChange); |
| 415 } | 331 } |
| 416 } | 332 } |
| 417 | 333 |
| 418 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
| 419 // TODO(rlanday): this method was created by cutting and pasting code from | |
| 420 // DocumentMarkerController::RemoveMarkers(), it should be refactored in a | |
| 421 // future CL | |
| 422 bool DocumentMarkerListEditor::RemoveMarkers(MarkerList* list, | |
| 423 unsigned start_offset, | |
| 424 int length) { | |
| 425 bool doc_dirty = false; | |
| 426 unsigned end_offset = start_offset + length; | |
| 427 MarkerList::iterator start_pos = | |
| 428 std::upper_bound(list->begin(), list->end(), start_offset, EndsBefore); | |
| 429 for (MarkerList::iterator i = start_pos; i != list->end();) { | |
| 430 DocumentMarker marker(*i->Get()); | |
| 431 | |
| 432 // markers are returned in order, so stop if we are now past the specified | |
| 433 // range | |
| 434 if (marker.StartOffset() >= end_offset) | |
| 435 break; | |
| 436 | |
| 437 list->erase(i - list->begin()); | |
| 438 doc_dirty = true; | |
| 439 } | |
| 440 | |
| 441 return doc_dirty; | |
| 442 } | |
| 443 | |
| 444 DocumentMarkerVector DocumentMarkerController::MarkersFor( | 334 DocumentMarkerVector DocumentMarkerController::MarkersFor( |
| 445 Node* node, | 335 Node* node, |
| 446 DocumentMarker::MarkerTypes marker_types) { | 336 DocumentMarker::MarkerTypes marker_types) { |
| 447 DocumentMarkerVector result; | 337 DocumentMarkerVector result; |
| 448 | 338 |
| 449 MarkerLists* markers = markers_.at(node); | 339 MarkerLists* markers = markers_.at(node); |
| 450 if (!markers) | 340 if (!markers) |
| 451 return result; | 341 return result; |
| 452 | 342 |
| 453 for (size_t marker_list_index = 0; | 343 for (size_t marker_list_index = 0; |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 762 | 652 |
| 763 bool marker_found = false; | 653 bool marker_found = false; |
| 764 for (Node& node : range.Nodes()) { | 654 for (Node& node : range.Nodes()) { |
| 765 int start_offset = node == start_container ? container_start_offset : 0; | 655 int start_offset = node == start_container ? container_start_offset : 0; |
| 766 int end_offset = node == end_container ? container_end_offset : INT_MAX; | 656 int end_offset = node == end_container ? container_end_offset : INT_MAX; |
| 767 marker_found |= SetMarkersActive(&node, start_offset, end_offset, active); | 657 marker_found |= SetMarkersActive(&node, start_offset, end_offset, active); |
| 768 } | 658 } |
| 769 return marker_found; | 659 return marker_found; |
| 770 } | 660 } |
| 771 | 661 |
| 662 static bool EndsBefore(size_t start_offset, | |
|
Xiaocheng
2017/04/20 03:09:15
Moving this function in the same file is an unnece
rlanday
2017/04/20 03:36:16
Fixed
| |
| 663 const Member<RenderedDocumentMarker>& marker) { | |
| 664 return start_offset < marker->EndOffset(); | |
| 665 } | |
| 666 | |
| 772 bool DocumentMarkerController::SetMarkersActive(Node* node, | 667 bool DocumentMarkerController::SetMarkersActive(Node* node, |
| 773 unsigned start_offset, | 668 unsigned start_offset, |
| 774 unsigned end_offset, | 669 unsigned end_offset, |
| 775 bool active) { | 670 bool active) { |
| 776 MarkerLists* markers = markers_.at(node); | 671 MarkerLists* markers = markers_.at(node); |
| 777 if (!markers) | 672 if (!markers) |
| 778 return false; | 673 return false; |
| 779 | 674 |
| 780 bool doc_dirty = false; | 675 bool doc_dirty = false; |
| 781 Member<MarkerList>& list = ListForType(markers, DocumentMarker::kTextMatch); | 676 Member<MarkerList>& list = ListForType(markers, DocumentMarker::kTextMatch); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 861 | 756 |
| 862 if (!did_shift_marker) | 757 if (!did_shift_marker) |
| 863 return; | 758 return; |
| 864 if (!node->GetLayoutObject()) | 759 if (!node->GetLayoutObject()) |
| 865 return; | 760 return; |
| 866 InvalidateRectsForMarkersInNode(*node); | 761 InvalidateRectsForMarkersInNode(*node); |
| 867 // repaint the affected node | 762 // repaint the affected node |
| 868 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation(); | 763 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation(); |
| 869 } | 764 } |
| 870 | 765 |
| 871 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
| 872 bool DocumentMarkerListEditor::ShiftMarkers(MarkerList* list, | |
| 873 unsigned offset, | |
| 874 unsigned old_length, | |
| 875 unsigned new_length) { | |
| 876 bool did_shift_marker = false; | |
| 877 for (MarkerList::iterator it = list->begin(); it != list->end(); ++it) { | |
| 878 RenderedDocumentMarker& marker = **it; | |
| 879 Optional<DocumentMarker::MarkerOffsets> result = | |
| 880 marker.ComputeOffsetsAfterShift(offset, old_length, new_length); | |
| 881 if (result == WTF::kNullopt) { | |
| 882 list->erase(it - list->begin()); | |
| 883 --it; | |
| 884 did_shift_marker = true; | |
| 885 continue; | |
| 886 } | |
| 887 | |
| 888 if (marker.StartOffset() != result.value().start_offset || | |
| 889 marker.EndOffset() != result.value().end_offset) { | |
| 890 did_shift_marker = true; | |
| 891 marker.SetStartOffset(result.value().start_offset); | |
| 892 marker.SetEndOffset(result.value().end_offset); | |
| 893 } | |
| 894 } | |
| 895 | |
| 896 return did_shift_marker; | |
| 897 } | |
| 898 | |
| 899 } // namespace blink | 766 } // namespace blink |
| 900 | 767 |
| 901 #ifndef NDEBUG | 768 #ifndef NDEBUG |
| 902 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { | 769 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { |
| 903 if (controller) | 770 if (controller) |
| 904 controller->ShowMarkers(); | 771 controller->ShowMarkers(); |
| 905 } | 772 } |
| 906 #endif | 773 #endif |
| OLD | NEW |