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 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
202 if (!exception_state.HadException()) { | 202 if (!exception_state.HadException()) { |
203 // TODO(yosin): Once we have a |EphemeralRange| version of |boundingBox()|, | 203 // TODO(yosin): Once we have a |EphemeralRange| version of |boundingBox()|, |
204 // we should use it instead of |Range| version. | 204 // we should use it instead of |Range| version. |
205 marker.SetRenderedRect(LayoutRect(range->BoundingBox())); | 205 marker.SetRenderedRect(LayoutRect(range->BoundingBox())); |
206 } else { | 206 } else { |
207 marker.NullifyRenderedRect(); | 207 marker.NullifyRenderedRect(); |
208 } | 208 } |
209 range->Dispose(); | 209 range->Dispose(); |
210 } | 210 } |
211 | 211 |
212 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
213 void DocumentMarkerListEditor::AddMarker(MarkerList* list, | |
214 const DocumentMarker* marker) { | |
215 RenderedDocumentMarker* rendered_marker = | |
216 RenderedDocumentMarker::Create(*marker); | |
217 if (list->IsEmpty() || list->back()->EndOffset() < marker->StartOffset()) { | |
218 list->push_back(rendered_marker); | |
219 } else { | |
220 if (marker->GetType() != DocumentMarker::kTextMatch && | |
221 marker->GetType() != DocumentMarker::kComposition) { | |
222 MergeOverlapping(list, rendered_marker); | |
223 } else { | |
224 MarkerList::iterator pos = | |
225 std::lower_bound(list->begin(), list->end(), marker, StartsFurther); | |
226 list->insert(pos - list->begin(), rendered_marker); | |
227 } | |
228 } | |
229 } | |
230 | |
212 // Markers are stored in order sorted by their start offset. | 231 // Markers are stored in order sorted by their start offset. |
213 // Markers of the same type do not overlap each other. | 232 // Markers of the same type do not overlap each other. |
214 | 233 |
215 void DocumentMarkerController::AddMarker(Node* node, | 234 void DocumentMarkerController::AddMarker(Node* node, |
216 const DocumentMarker& new_marker) { | 235 const DocumentMarker& new_marker) { |
217 DCHECK_GE(new_marker.EndOffset(), new_marker.StartOffset()); | 236 DCHECK_GE(new_marker.EndOffset(), new_marker.StartOffset()); |
218 if (new_marker.EndOffset() == new_marker.StartOffset()) | 237 if (new_marker.EndOffset() == new_marker.StartOffset()) |
219 return; | 238 return; |
220 | 239 |
221 possibly_existing_marker_types_.Add(new_marker.GetType()); | 240 possibly_existing_marker_types_.Add(new_marker.GetType()); |
222 | 241 |
223 Member<MarkerLists>& markers = | 242 Member<MarkerLists>& markers = |
224 markers_.insert(node, nullptr).stored_value->value; | 243 markers_.insert(node, nullptr).stored_value->value; |
225 if (!markers) { | 244 if (!markers) { |
226 markers = new MarkerLists; | 245 markers = new MarkerLists; |
227 markers->Grow(DocumentMarker::kMarkerTypeIndexesCount); | 246 markers->Grow(DocumentMarker::kMarkerTypeIndexesCount); |
228 } | 247 } |
229 | 248 |
230 DocumentMarker::MarkerTypeIndex marker_list_index = | 249 DocumentMarker::MarkerTypeIndex marker_list_index = |
231 MarkerTypeToMarkerIndex(new_marker.GetType()); | 250 MarkerTypeToMarkerIndex(new_marker.GetType()); |
232 if (!markers->at(marker_list_index)) { | 251 if (!markers->at(marker_list_index)) { |
233 markers->at(marker_list_index) = new MarkerList; | 252 markers->at(marker_list_index) = new MarkerList; |
234 } | 253 } |
235 | 254 |
236 Member<MarkerList>& list = markers->at(marker_list_index); | 255 Member<MarkerList>& list = markers->at(marker_list_index); |
237 RenderedDocumentMarker* new_rendered_marker = | 256 DocumentMarkerListEditor::AddMarker(list, &new_marker); |
238 RenderedDocumentMarker::Create(new_marker); | |
239 if (list->IsEmpty() || list->back()->EndOffset() < new_marker.StartOffset()) { | |
240 list->push_back(new_rendered_marker); | |
241 } else { | |
242 if (new_marker.GetType() != DocumentMarker::kTextMatch && | |
243 new_marker.GetType() != DocumentMarker::kComposition) { | |
244 MergeOverlapping(list.Get(), new_rendered_marker); | |
245 } else { | |
246 MarkerList::iterator pos = std::lower_bound(list->begin(), list->end(), | |
247 &new_marker, StartsFurther); | |
248 list->insert(pos - list->begin(), new_rendered_marker); | |
249 } | |
250 } | |
251 | 257 |
252 // repaint the affected node | 258 // repaint the affected node |
253 if (node->GetLayoutObject()) { | 259 if (node->GetLayoutObject()) { |
254 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( | 260 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( |
255 kPaintInvalidationDocumentMarkerChange); | 261 kPaintInvalidationDocumentMarkerChange); |
256 } | 262 } |
257 } | 263 } |
258 | 264 |
259 void DocumentMarkerController::MergeOverlapping( | 265 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files |
266 void DocumentMarkerListEditor::MergeOverlapping( | |
260 MarkerList* list, | 267 MarkerList* list, |
261 RenderedDocumentMarker* to_insert) { | 268 RenderedDocumentMarker* to_insert) { |
262 MarkerList::iterator first_overlapping = | 269 MarkerList::iterator first_overlapping = |
263 std::lower_bound(list->begin(), list->end(), to_insert, DoesNotOverlap); | 270 std::lower_bound(list->begin(), list->end(), to_insert, DoesNotOverlap); |
264 size_t index = first_overlapping - list->begin(); | 271 size_t index = first_overlapping - list->begin(); |
265 list->insert(index, to_insert); | 272 list->insert(index, to_insert); |
266 MarkerList::iterator inserted = list->begin() + index; | 273 MarkerList::iterator inserted = list->begin() + index; |
267 first_overlapping = inserted + 1; | 274 first_overlapping = inserted + 1; |
268 for (MarkerList::iterator i = first_overlapping; | 275 for (MarkerList::iterator i = first_overlapping; |
269 i != list->end() && (*i)->StartOffset() <= (*inserted)->EndOffset();) { | 276 i != list->end() && (*i)->StartOffset() <= (*inserted)->EndOffset();) { |
270 (*inserted)->SetStartOffset( | 277 (*inserted)->SetStartOffset( |
271 std::min((*inserted)->StartOffset(), (*i)->StartOffset())); | 278 std::min((*inserted)->StartOffset(), (*i)->StartOffset())); |
272 (*inserted)->SetEndOffset( | 279 (*inserted)->SetEndOffset( |
273 std::max((*inserted)->EndOffset(), (*i)->EndOffset())); | 280 std::max((*inserted)->EndOffset(), (*i)->EndOffset())); |
274 list->erase(i - list->begin()); | 281 list->erase(i - list->begin()); |
275 } | 282 } |
276 } | 283 } |
277 | 284 |
285 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
286 bool DocumentMarkerListEditor::MoveMarkers(MarkerList* src_list, | |
287 int length, | |
288 MarkerList* dst_list) { | |
289 DCHECK_GT(length, 0); | |
290 bool didMoveMarker = false; | |
291 unsigned end_offset = length - 1; | |
292 | |
293 MarkerList::iterator it; | |
294 for (it = src_list->begin(); it != src_list->end(); ++it) { | |
295 DocumentMarker& marker = **it; | |
296 if (marker.StartOffset() > end_offset) | |
297 break; | |
298 | |
299 // pin the marker to the specified range and apply the shift delta | |
300 if (marker.EndOffset() > end_offset) | |
301 marker.SetEndOffset(end_offset); | |
302 | |
303 DocumentMarkerListEditor::AddMarker(dst_list, &marker); | |
304 didMoveMarker = true; | |
305 } | |
306 | |
307 // Remove the range of markers that were moved to dstNode | |
308 src_list->erase(0, it - src_list->begin()); | |
309 | |
310 return didMoveMarker; | |
311 } | |
312 | |
278 // Moves markers from src_node to dst_node. Markers are moved if their start | 313 // Moves markers from src_node to dst_node. Markers are moved if their start |
279 // offset is less than length. Markers that run past that point are truncated. | 314 // offset is less than length. Markers that run past that point are truncated. |
280 void DocumentMarkerController::MoveMarkers(Node* src_node, | 315 void DocumentMarkerController::MoveMarkers(Node* src_node, |
281 int length, | 316 int length, |
282 Node* dst_node) { | 317 Node* dst_node) { |
283 if (length <= 0) | 318 if (length <= 0) |
284 return; | 319 return; |
285 | 320 |
286 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers())) | 321 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers())) |
287 return; | 322 return; |
288 DCHECK(!markers_.IsEmpty()); | 323 DCHECK(!markers_.IsEmpty()); |
289 | 324 |
290 MarkerLists* markers = markers_.at(src_node); | 325 MarkerLists* src_markers = markers_.at(src_node); |
291 if (!markers) | 326 if (!src_markers) |
292 return; | 327 return; |
293 | 328 |
329 if (!markers_.Contains(dst_node)) { | |
330 markers_.insert(dst_node, | |
331 new MarkerLists(DocumentMarker::kMarkerTypeIndexesCount)); | |
332 } | |
333 | |
334 MarkerLists* dst_markers = markers_.at(dst_node); | |
335 | |
294 bool doc_dirty = false; | 336 bool doc_dirty = false; |
295 for (Member<MarkerList> list : *markers) { | 337 for (size_t marker_list_index = 0; marker_list_index < src_markers->size(); |
296 if (!list) | 338 marker_list_index++) { |
339 MarkerList* src_list = src_markers->at(marker_list_index); | |
340 if (!src_list) | |
297 continue; | 341 continue; |
298 | 342 |
299 unsigned end_offset = length - 1; | 343 if (!dst_markers->at(marker_list_index)) { |
300 MarkerList::iterator it; | 344 dst_markers->at(marker_list_index) = new MarkerList; |
301 for (it = list->begin(); it != list->end(); ++it) { | |
302 DocumentMarker* marker = it->Get(); | |
303 | |
304 // stop if we are now past the specified range | |
305 if (marker->StartOffset() > end_offset) | |
306 break; | |
307 | |
308 // pin the marker to the specified range | |
309 doc_dirty = true; | |
310 if (marker->EndOffset() > end_offset) | |
311 marker->SetEndOffset(end_offset); | |
312 | |
313 AddMarker(dst_node, *marker); | |
314 } | 345 } |
315 | 346 |
316 // Remove the range of markers that were moved to dstNode | 347 DocumentMarkerListEditor::MoveMarkers(src_list, length, |
Xiaocheng
2017/04/14 01:37:01
The return value is still unused...
| |
317 list->erase(0, it - list->begin()); | 348 dst_markers->at(marker_list_index)); |
318 } | 349 } |
319 | 350 |
320 // repaint the affected node | 351 // repaint the affected node |
321 if (doc_dirty && dst_node->GetLayoutObject()) { | 352 if (doc_dirty && dst_node->GetLayoutObject()) { |
322 dst_node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( | 353 dst_node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( |
323 kPaintInvalidationDocumentMarkerChange); | 354 kPaintInvalidationDocumentMarkerChange); |
324 } | 355 } |
325 } | 356 } |
326 | 357 |
358 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
359 bool DocumentMarkerListEditor::RemoveMarkers(MarkerList* list, | |
360 unsigned start_offset, | |
361 int length) { | |
362 bool doc_dirty = false; | |
363 unsigned end_offset = start_offset + length; | |
364 MarkerList::iterator start_pos = | |
365 std::upper_bound(list->begin(), list->end(), start_offset, EndsBefore); | |
366 for (MarkerList::iterator i = start_pos; i != list->end();) { | |
367 DocumentMarker marker(*i->Get()); | |
368 | |
369 // markers are returned in order, so stop if we are now past the specified | |
370 // range | |
371 if (marker.StartOffset() >= end_offset) | |
372 break; | |
373 | |
374 list->erase(i - list->begin()); | |
375 doc_dirty = true; | |
376 } | |
377 | |
378 return doc_dirty; | |
379 } | |
380 | |
327 void DocumentMarkerController::RemoveMarkers( | 381 void DocumentMarkerController::RemoveMarkers( |
328 Node* node, | 382 Node* node, |
329 unsigned start_offset, | 383 unsigned start_offset, |
330 int length, | 384 int length, |
331 DocumentMarker::MarkerTypes marker_types) { | 385 DocumentMarker::MarkerTypes marker_types) { |
332 if (length <= 0) | 386 if (length <= 0) |
333 return; | 387 return; |
334 | 388 |
335 if (!PossiblyHasMarkers(marker_types)) | 389 if (!PossiblyHasMarkers(marker_types)) |
336 return; | 390 return; |
(...skipping 10 matching lines...) Expand all Loading... | |
347 ++marker_list_index) { | 401 ++marker_list_index) { |
348 Member<MarkerList>& list = (*markers)[marker_list_index]; | 402 Member<MarkerList>& list = (*markers)[marker_list_index]; |
349 if (!list || list->IsEmpty()) { | 403 if (!list || list->IsEmpty()) { |
350 if (list.Get() && list->IsEmpty()) | 404 if (list.Get() && list->IsEmpty()) |
351 list.Clear(); | 405 list.Clear(); |
352 ++empty_lists_count; | 406 ++empty_lists_count; |
353 continue; | 407 continue; |
354 } | 408 } |
355 if (!marker_types.Contains((*list->begin())->GetType())) | 409 if (!marker_types.Contains((*list->begin())->GetType())) |
356 continue; | 410 continue; |
357 unsigned end_offset = start_offset + length; | |
358 MarkerList::iterator start_pos = | |
359 std::upper_bound(list->begin(), list->end(), start_offset, EndsBefore); | |
360 for (MarkerList::iterator i = start_pos; i != list->end();) { | |
361 DocumentMarker marker(*i->Get()); | |
362 | 411 |
363 // markers are returned in order, so stop if we are now past the specified | 412 doc_dirty |= |
364 // range | 413 DocumentMarkerListEditor::RemoveMarkers(list, start_offset, length); |
365 if (marker.StartOffset() >= end_offset) | |
366 break; | |
367 | |
368 list->erase(i - list->begin()); | |
369 doc_dirty = true; | |
370 } | |
371 | 414 |
372 if (list->IsEmpty()) { | 415 if (list->IsEmpty()) { |
373 list.Clear(); | 416 list.Clear(); |
374 ++empty_lists_count; | 417 ++empty_lists_count; |
375 } | 418 } |
376 } | 419 } |
377 | 420 |
378 if (empty_lists_count == DocumentMarker::kMarkerTypeIndexesCount) { | 421 if (empty_lists_count == DocumentMarker::kMarkerTypeIndexesCount) { |
379 markers_.erase(node); | 422 markers_.erase(node); |
380 if (markers_.IsEmpty()) | 423 if (markers_.IsEmpty()) |
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
777 builder.Append(")"); | 820 builder.Append(")"); |
778 } | 821 } |
779 } | 822 } |
780 builder.Append("\n"); | 823 builder.Append("\n"); |
781 } | 824 } |
782 LOG(INFO) << markers_.size() << " nodes have markers:\n" | 825 LOG(INFO) << markers_.size() << " nodes have markers:\n" |
783 << builder.ToString().Utf8().Data(); | 826 << builder.ToString().Utf8().Data(); |
784 } | 827 } |
785 #endif | 828 #endif |
786 | 829 |
830 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
831 bool DocumentMarkerListEditor::ShiftMarkers(MarkerList* list, | |
832 unsigned offset, | |
833 unsigned old_length, | |
834 unsigned new_length) { | |
835 bool did_shift_marker = false; | |
836 for (MarkerList::iterator it = list->begin(); it != list->end(); ++it) { | |
837 RenderedDocumentMarker& marker = **it; | |
838 Optional<DocumentMarker::MarkerOffsets> result = | |
839 marker.ComputeOffsetsAfterShift(offset, old_length, new_length); | |
840 if (result == WTF::kNullopt) { | |
841 list->erase(it - list->begin()); | |
842 --it; | |
843 did_shift_marker = true; | |
844 continue; | |
845 } | |
846 | |
847 if (marker.StartOffset() != result.value().start_offset || | |
848 marker.EndOffset() != result.value().end_offset) { | |
849 did_shift_marker = true; | |
850 marker.SetStartOffset(result.value().start_offset); | |
851 marker.SetEndOffset(result.value().end_offset); | |
852 } | |
853 } | |
854 | |
855 return did_shift_marker; | |
856 } | |
857 | |
787 // SynchronousMutationObserver | 858 // SynchronousMutationObserver |
788 void DocumentMarkerController::DidUpdateCharacterData(CharacterData* node, | 859 void DocumentMarkerController::DidUpdateCharacterData(CharacterData* node, |
789 unsigned offset, | 860 unsigned offset, |
790 unsigned old_length, | 861 unsigned old_length, |
791 unsigned new_length) { | 862 unsigned new_length) { |
792 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers())) | 863 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers())) |
793 return; | 864 return; |
794 DCHECK(!markers_.IsEmpty()); | 865 DCHECK(!markers_.IsEmpty()); |
795 | 866 |
796 MarkerLists* markers = markers_.at(node); | 867 MarkerLists* markers = markers_.at(node); |
797 if (!markers) | 868 if (!markers) |
798 return; | 869 return; |
799 | 870 |
800 bool did_shift_marker = false; | 871 bool did_shift_marker = false; |
801 for (MarkerList* list : *markers) { | 872 for (MarkerList* list : *markers) { |
802 if (!list) | 873 if (!list) |
803 continue; | 874 continue; |
804 | 875 |
805 for (MarkerList::iterator it = list->begin(); it != list->end(); ++it) { | 876 did_shift_marker |= DocumentMarkerListEditor::ShiftMarkers( |
806 RenderedDocumentMarker& marker = **it; | 877 list, offset, old_length, new_length); |
807 Optional<DocumentMarker::MarkerOffsets> result = | |
808 marker.ComputeOffsetsAfterShift(offset, old_length, new_length); | |
809 if (result == WTF::kNullopt) { | |
810 list->erase(it - list->begin()); | |
811 --it; | |
812 did_shift_marker = true; | |
813 continue; | |
814 } | |
815 | |
816 if (marker.StartOffset() != result.value().start_offset || | |
817 marker.EndOffset() != result.value().end_offset) { | |
818 did_shift_marker = true; | |
819 marker.SetStartOffset(result.value().start_offset); | |
820 marker.SetEndOffset(result.value().end_offset); | |
821 } | |
822 } | |
823 } | 878 } |
824 | 879 |
825 if (!did_shift_marker) | 880 if (!did_shift_marker) |
826 return; | 881 return; |
827 if (!node->GetLayoutObject()) | 882 if (!node->GetLayoutObject()) |
828 return; | 883 return; |
829 InvalidateRectsForMarkersInNode(*node); | 884 InvalidateRectsForMarkersInNode(*node); |
830 // repaint the affected node | 885 // repaint the affected node |
831 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation(); | 886 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation(); |
832 } | 887 } |
833 | 888 |
834 } // namespace blink | 889 } // namespace blink |
835 | 890 |
836 #ifndef NDEBUG | 891 #ifndef NDEBUG |
837 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { | 892 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { |
838 if (controller) | 893 if (controller) |
839 controller->ShowMarkers(); | 894 controller->ShowMarkers(); |
840 } | 895 } |
841 #endif | 896 #endif |
OLD | NEW |