Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: Source/core/dom/DocumentMarkerController.cpp

Issue 23728006: addMarker() optimizations. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Compilation fix Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/core/dom/DocumentMarkerController.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 reserved. 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
7 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/) 7 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/)
8 * Copyright (C) Research In Motion Limited 2010. All rights reserved. 8 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
9 * 9 *
10 * This library is free software; you can redistribute it and/or 10 * This library is free software; you can redistribute it and/or
(...skipping 22 matching lines...) Expand all
33 #include "core/dom/RenderedDocumentMarker.h" 33 #include "core/dom/RenderedDocumentMarker.h"
34 #include "core/editing/TextIterator.h" 34 #include "core/editing/TextIterator.h"
35 #include "core/rendering/RenderObject.h" 35 #include "core/rendering/RenderObject.h"
36 36
37 #ifndef NDEBUG 37 #ifndef NDEBUG
38 #include <stdio.h> 38 #include <stdio.h>
39 #endif 39 #endif
40 40
41 namespace WebCore { 41 namespace WebCore {
42 42
43 namespace {
44
45 DocumentMarker::MarkerTypeIndex MarkerTypeToMarkerIndex(DocumentMarker::MarkerTy pe type)
46 {
47 switch (type) {
48 case DocumentMarker::Spelling:
49 return DocumentMarker::SpellingMarkerIndex;
50 case DocumentMarker::Grammar:
51 return DocumentMarker::GramarMarkerIndex;
52 case DocumentMarker::TextMatch:
53 return DocumentMarker::TextMatchMarkerIndex;
54 }
55
56 ASSERT_NOT_REACHED();
57 return DocumentMarker::SpellingMarkerIndex;
58 }
59
60 } // namespace
61
43 inline bool DocumentMarkerController::possiblyHasMarkers(DocumentMarker::MarkerT ypes types) 62 inline bool DocumentMarkerController::possiblyHasMarkers(DocumentMarker::MarkerT ypes types)
44 { 63 {
45 return m_possiblyExistingMarkerTypes.intersects(types); 64 return m_possiblyExistingMarkerTypes.intersects(types);
46 } 65 }
47 66
48 DocumentMarkerController::DocumentMarkerController() 67 DocumentMarkerController::DocumentMarkerController()
49 : m_possiblyExistingMarkerTypes(0) 68 : m_possiblyExistingMarkerTypes(0)
50 { 69 {
51 } 70 }
52 71
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 return; 145 return;
127 ASSERT(!m_markers.isEmpty()); 146 ASSERT(!m_markers.isEmpty());
128 147
129 RefPtr<Range> textPiece = markedText.range(); 148 RefPtr<Range> textPiece = markedText.range();
130 int startOffset = textPiece->startOffset(); 149 int startOffset = textPiece->startOffset();
131 int endOffset = textPiece->endOffset(); 150 int endOffset = textPiece->endOffset();
132 removeMarkers(textPiece->startContainer(), startOffset, endOffset - star tOffset, markerTypes, shouldRemovePartiallyOverlappingMarker); 151 removeMarkers(textPiece->startContainer(), startOffset, endOffset - star tOffset, markerTypes, shouldRemovePartiallyOverlappingMarker);
133 } 152 }
134 } 153 }
135 154
155 static bool startsFurther(const DocumentMarker& lhv, const DocumentMarker& rhv)
156 {
157 return lhv.startOffset() < rhv.startOffset();
158 }
159
160 static bool startsAfter(const DocumentMarker& marker, size_t startOffset)
161 {
162 return marker.startOffset() < startOffset;
163 }
164
165 static bool endsBefore(size_t startOffset, const DocumentMarker& rhv)
166 {
167 return startOffset < rhv.endOffset();
168 }
169
170 static bool compareByStart(const DocumentMarker* lhv, const DocumentMarker* rhv)
171 {
172 return startsFurther(*lhv, *rhv);
173 }
174
175 static bool doesNotOverlap(const DocumentMarker& lhv, const DocumentMarker& rhv)
176 {
177 return lhv.endOffset() < rhv.startOffset();
178 }
179
180 static bool doesNotInclude(const DocumentMarker& marker, size_t startOffset)
181 {
182 return marker.endOffset() < startOffset;
183 }
184
136 // Markers are stored in order sorted by their start offset. 185 // Markers are stored in order sorted by their start offset.
137 // Markers of the same type do not overlap each other. 186 // Markers of the same type do not overlap each other.
138 187
139 void DocumentMarkerController::addMarker(Node* node, const DocumentMarker& newMa rker) 188 void DocumentMarkerController::addMarker(Node* node, const DocumentMarker& newMa rker)
140 { 189 {
141 ASSERT(newMarker.endOffset() >= newMarker.startOffset()); 190 ASSERT(newMarker.endOffset() >= newMarker.startOffset());
142 if (newMarker.endOffset() == newMarker.startOffset()) 191 if (newMarker.endOffset() == newMarker.startOffset())
143 return; 192 return;
144 193
145 m_possiblyExistingMarkerTypes.add(newMarker.type()); 194 m_possiblyExistingMarkerTypes.add(newMarker.type());
146 195
147 OwnPtr<MarkerList>& list = m_markers.add(node, nullptr).iterator->value; 196 OwnPtr<MarkerLists>& markers = m_markers.add(node, nullptr).iterator->value;
197 if (!markers) {
198 markers = adoptPtr(new MarkerLists);
199 markers->grow(DocumentMarker::MarkerTypeIndexesCount);
200 }
148 201
149 if (!list) { 202 DocumentMarker::MarkerTypeIndex markerListIndex = MarkerTypeToMarkerIndex(ne wMarker.type());
150 list = adoptPtr(new MarkerList); 203 if (!markers->at(markerListIndex)) {
204 markers->insert(markerListIndex, adoptPtr(new MarkerList));
205 }
206
207 OwnPtr<MarkerList>& list = markers->at(markerListIndex);
208 if (list->isEmpty() || list->last().endOffset() < newMarker.startOffset()) {
151 list->append(RenderedDocumentMarker(newMarker)); 209 list->append(RenderedDocumentMarker(newMarker));
152 } else { 210 } else {
153 RenderedDocumentMarker toInsert(newMarker); 211 RenderedDocumentMarker toInsert(newMarker);
154 size_t numMarkers = list->size(); 212 if (toInsert.type() != DocumentMarker::TextMatch) {
155 size_t i; 213 mergeOverlapping(list.get(), toInsert);
156 // Iterate over all markers whose start offset is less than or equal to the new marker's. 214 } else {
157 // If one of them is of the same type as the new marker and touches it o r intersects with it 215 MarkerList::iterator pos = std::lower_bound(list->begin(), list->end (), toInsert, startsFurther);
158 // (there is at most one), remove it and adjust the new marker's start o ffset to encompass it. 216 list->insert(pos - list->begin(), RenderedDocumentMarker(toInsert));
159 for (i = 0; i < numMarkers; ++i) {
160 DocumentMarker marker = list->at(i);
161 if (marker.startOffset() > toInsert.startOffset())
162 break;
163 if (marker.type() == toInsert.type() && marker.type() != DocumentMar ker::TextMatch && marker.endOffset() >= toInsert.startOffset()) {
164 toInsert.setStartOffset(marker.startOffset());
165 list->remove(i);
166 numMarkers--;
167 break;
168 }
169 } 217 }
170 size_t j = i;
171 // Iterate over all markers whose end offset is less than or equal to th e new marker's,
172 // removing markers of the same type as the new marker which touch it or intersect with it,
173 // adjusting the new marker's end offset to cover them if necessary.
174 while (j < numMarkers) {
175 DocumentMarker marker = list->at(j);
176 if (marker.startOffset() > toInsert.endOffset())
177 break;
178 if (marker.type() == toInsert.type() && marker.type() != DocumentMar ker::TextMatch) {
179 list->remove(j);
180 if (toInsert.endOffset() <= marker.endOffset()) {
181 toInsert.setEndOffset(marker.endOffset());
182 break;
183 }
184 numMarkers--;
185 } else
186 j++;
187 }
188 // At this point i points to the node before which we want to insert.
189 list->insert(i, RenderedDocumentMarker(toInsert));
190 } 218 }
191 219
192 // repaint the affected node 220 // repaint the affected node
193 if (node->renderer()) 221 if (node->renderer())
194 node->renderer()->repaint(); 222 node->renderer()->repaint();
195 } 223 }
196 224
225 void DocumentMarkerController::mergeOverlapping(MarkerList* list, DocumentMarker & toInsert)
226 {
227 MarkerList::iterator firstOverlapping = std::lower_bound(list->begin(), list ->end(), toInsert, doesNotOverlap);
228 size_t index = firstOverlapping - list->begin();
229 list->insert(index, RenderedDocumentMarker(toInsert));
230 MarkerList::iterator inserted = list->begin() + index;
231 firstOverlapping = inserted + 1;
232 for (MarkerList::iterator i = firstOverlapping; i != list->end() && i->start Offset() <= inserted->endOffset(); ) {
233 inserted->setStartOffset(std::min(inserted->startOffset(), i->startOffse t()));
234 inserted->setEndOffset(std::max(inserted->endOffset(), i->endOffset()));
235 list->remove(i - list->begin());
236 }
237 }
238
197 // copies markers from srcNode to dstNode, applying the specified shift delta to the copies. The shift is 239 // copies markers from srcNode to dstNode, applying the specified shift delta to the copies. The shift is
198 // useful if, e.g., the caller has created the dstNode from a non-prefix substri ng of the srcNode. 240 // useful if, e.g., the caller has created the dstNode from a non-prefix substri ng of the srcNode.
199 void DocumentMarkerController::copyMarkers(Node* srcNode, unsigned startOffset, int length, Node* dstNode, int delta) 241 void DocumentMarkerController::copyMarkers(Node* srcNode, unsigned startOffset, int length, Node* dstNode, int delta)
200 { 242 {
201 if (length <= 0) 243 if (length <= 0)
202 return; 244 return;
203 245
204 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) 246 if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
205 return; 247 return;
206 ASSERT(!m_markers.isEmpty()); 248 ASSERT(!m_markers.isEmpty());
207 249
208 MarkerList* list = m_markers.get(srcNode); 250 MarkerLists* markers = m_markers.get(srcNode);
209 if (!list) 251 if (!markers)
210 return; 252 return;
211 253
212 bool docDirty = false; 254 bool docDirty = false;
213 unsigned endOffset = startOffset + length - 1; 255 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTyp eIndexesCount; ++markerListIndex) {
214 for (size_t i = 0; i != list->size(); ++i) { 256 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
215 DocumentMarker marker = list->at(i); 257 if (!list)
216
217 // stop if we are now past the specified range
218 if (marker.startOffset() > endOffset)
219 break;
220
221 // skip marker that is before the specified range or is the wrong type
222 if (marker.endOffset() < startOffset)
223 continue; 258 continue;
224 259
225 // pin the marker to the specified range and apply the shift delta 260 unsigned endOffset = startOffset + length - 1;
226 docDirty = true; 261 MarkerList::iterator startPos = std::lower_bound(list->begin(), list->en d(), startOffset, doesNotInclude);
227 if (marker.startOffset() < startOffset) 262 for (MarkerList::iterator i = startPos; i != list->end(); ++i) {
228 marker.setStartOffset(startOffset); 263 DocumentMarker marker = *i;
229 if (marker.endOffset() > endOffset)
230 marker.setEndOffset(endOffset);
231 marker.shiftOffsets(delta);
232 264
233 addMarker(dstNode, marker); 265 // stop if we are now past the specified range
266 if (marker.startOffset() > endOffset)
267 break;
268
269 // pin the marker to the specified range and apply the shift delta
270 docDirty = true;
271 if (marker.startOffset() < startOffset)
272 marker.setStartOffset(startOffset);
273 if (marker.endOffset() > endOffset)
274 marker.setEndOffset(endOffset);
275 marker.shiftOffsets(delta);
276
277 addMarker(dstNode, marker);
278 }
234 } 279 }
235 280
236 // repaint the affected node 281 // repaint the affected node
237 if (docDirty && dstNode->renderer()) 282 if (docDirty && dstNode->renderer())
238 dstNode->renderer()->repaint(); 283 dstNode->renderer()->repaint();
239 } 284 }
240 285
241 void DocumentMarkerController::removeMarkers(Node* node, unsigned startOffset, i nt length, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMa rkerOrNot shouldRemovePartiallyOverlappingMarker) 286 void DocumentMarkerController::removeMarkers(Node* node, unsigned startOffset, i nt length, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMa rkerOrNot shouldRemovePartiallyOverlappingMarker)
242 { 287 {
243 if (length <= 0) 288 if (length <= 0)
244 return; 289 return;
245 290
246 if (!possiblyHasMarkers(markerTypes)) 291 if (!possiblyHasMarkers(markerTypes))
247 return; 292 return;
248 ASSERT(!(m_markers.isEmpty())); 293 ASSERT(!(m_markers.isEmpty()));
249 294
250 MarkerList* list = m_markers.get(node); 295 MarkerLists* markers = m_markers.get(node);
251 if (!list) 296 if (!markers)
252 return; 297 return;
253 298
254 bool docDirty = false; 299 bool docDirty = false;
255 unsigned endOffset = startOffset + length; 300 size_t emptyListsCount = 0;
256 for (size_t i = 0; i < list->size();) { 301 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTyp eIndexesCount; ++markerListIndex) {
257 DocumentMarker marker = list->at(i); 302 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
258 303 if (!list || list->isEmpty()) {
259 // markers are returned in order, so stop if we are now past the specifi ed range 304 if (list.get() && list->isEmpty())
260 if (marker.startOffset() >= endOffset) 305 list.clear();
261 break; 306 ++emptyListsCount;
262
263 // skip marker that is wrong type or before target
264 if (marker.endOffset() <= startOffset || !markerTypes.contains(marker.ty pe())) {
265 i++;
266 continue; 307 continue;
267 } 308 }
309 if (!markerTypes.contains(list->begin()->type()))
310 continue;
311 unsigned endOffset = startOffset + length;
312 MarkerList::iterator startPos = std::upper_bound(list->begin(), list->en d(), startOffset, endsBefore);
313 for (MarkerList::iterator i = startPos; i != list->end(); ) {
314 DocumentMarker marker = *i;
268 315
269 // at this point we know that marker and target intersect in some way 316 // markers are returned in order, so stop if we are now past the spe cified range
270 docDirty = true; 317 if (marker.startOffset() >= endOffset)
318 break;
271 319
272 // pitch the old marker 320 // at this point we know that marker and target intersect in some wa y
273 list->remove(i); 321 docDirty = true;
274 322
275 if (shouldRemovePartiallyOverlappingMarker) 323 // pitch the old marker
276 // Stop here. Don't add resulting slices back. 324 list->remove(i - list->begin());
277 continue;
278 325
279 // add either of the resulting slices that are left after removing targe t 326 if (shouldRemovePartiallyOverlappingMarker) {
280 if (startOffset > marker.startOffset()) { 327 // Stop here. Don't add resulting slices back.
281 DocumentMarker newLeft = marker; 328 continue;
282 newLeft.setEndOffset(startOffset); 329 }
283 list->insert(i, RenderedDocumentMarker(newLeft)); 330
284 // i now points to the newly-inserted node, but we want to skip that one 331 // add either of the resulting slices that are left after removing t arget
285 i++; 332 if (startOffset > marker.startOffset()) {
333 DocumentMarker newLeft = marker;
334 newLeft.setEndOffset(startOffset);
335 size_t insertIndex = i - list->begin();
336 list->insert(insertIndex , RenderedDocumentMarker(newLeft));
337 // Move to the marker after the inserted one.
338 i = list->begin() + insertIndex + 1;
339 }
340 if (marker.endOffset() > endOffset) {
341 DocumentMarker newRight = marker;
342 newRight.setStartOffset(endOffset);
343 size_t insertIndex = i - list->begin();
344 list->insert(insertIndex, RenderedDocumentMarker(newRight));
345 // Move to the marker after the inserted one.
346 i = list->begin() + insertIndex + 1;
347 }
286 } 348 }
287 if (marker.endOffset() > endOffset) { 349
288 DocumentMarker newRight = marker; 350 if (list->isEmpty()) {
289 newRight.setStartOffset(endOffset); 351 list.clear();
290 list->insert(i, RenderedDocumentMarker(newRight)); 352 ++emptyListsCount;
291 // i now points to the newly-inserted node, but we want to skip that one
292 i++;
293 } 353 }
294 } 354 }
295 355
296 if (list->isEmpty()) { 356 if (emptyListsCount == DocumentMarker::MarkerTypeIndexesCount) {
297 m_markers.remove(node); 357 m_markers.remove(node);
298 if (m_markers.isEmpty()) 358 if (m_markers.isEmpty())
299 m_possiblyExistingMarkerTypes = 0; 359 m_possiblyExistingMarkerTypes = 0;
300 } 360 }
301 361
302 // repaint the affected node 362 // repaint the affected node
303 if (docDirty && node->renderer()) 363 if (docDirty && node->renderer())
304 node->renderer()->repaint(); 364 node->renderer()->repaint();
305 } 365 }
306 366
307 DocumentMarker* DocumentMarkerController::markerContainingPoint(const LayoutPoin t& point, DocumentMarker::MarkerType markerType) 367 DocumentMarker* DocumentMarkerController::markerContainingPoint(const LayoutPoin t& point, DocumentMarker::MarkerType markerType)
308 { 368 {
309 if (!possiblyHasMarkers(markerType)) 369 if (!possiblyHasMarkers(markerType))
310 return 0; 370 return 0;
311 ASSERT(!(m_markers.isEmpty())); 371 ASSERT(!(m_markers.isEmpty()));
312 372
313 // outer loop: process each node that contains any markers 373 // outer loop: process each node that contains any markers
314 MarkerMap::iterator end = m_markers.end(); 374 MarkerMap::iterator end = m_markers.end();
315 for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != e nd; ++nodeIterator) { 375 for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != e nd; ++nodeIterator) {
316 // inner loop; process each marker in this node 376 // inner loop; process each marker in this node
317 MarkerList* list = nodeIterator->value.get(); 377 MarkerLists* markers = nodeIterator->value.get();
318 unsigned markerCount = list->size(); 378 OwnPtr<MarkerList>& list = (*markers)[MarkerTypeToMarkerIndex(markerType )];
379 unsigned markerCount = list.get() ? list->size() : 0;
319 for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) { 380 for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) {
320 RenderedDocumentMarker& marker = list->at(markerIndex); 381 RenderedDocumentMarker& marker = list->at(markerIndex);
321 382
322 // skip marker that is wrong type
323 if (marker.type() != markerType)
324 continue;
325
326 if (marker.contains(point)) 383 if (marker.contains(point))
327 return &marker; 384 return &marker;
328 } 385 }
329 } 386 }
330 387
331 return 0; 388 return 0;
332 } 389 }
333 390
334 Vector<DocumentMarker*> DocumentMarkerController::markersFor(Node* node, Documen tMarker::MarkerTypes markerTypes) 391 Vector<DocumentMarker*> DocumentMarkerController::markersFor(Node* node, Documen tMarker::MarkerTypes markerTypes)
335 { 392 {
336 Vector<DocumentMarker*> result; 393 Vector<DocumentMarker*> result;
337 MarkerList* list = m_markers.get(node); 394
338 if (!list) 395 MarkerLists* markers = m_markers.get(node);
396 if (!markers)
339 return result; 397 return result;
340 398
341 for (size_t i = 0; i < list->size(); ++i) { 399 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTyp eIndexesCount; ++markerListIndex) {
342 if (markerTypes.contains(list->at(i).type())) 400 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
401 if (!list || list->isEmpty() || !markerTypes.contains(list->begin()->typ e()))
402 continue;
403
404 for (size_t i = 0; i < list->size(); ++i)
343 result.append(&(list->at(i))); 405 result.append(&(list->at(i)));
344 } 406 }
345 407
408 std::sort(result.begin(), result.end(), compareByStart);
346 return result; 409 return result;
347 } 410 }
348 411
349 Vector<DocumentMarker*> DocumentMarkerController::markers() 412 Vector<DocumentMarker*> DocumentMarkerController::markers()
350 { 413 {
351 Vector<DocumentMarker*> result; 414 Vector<DocumentMarker*> result;
352 for (MarkerMap::iterator i = m_markers.begin(); i != m_markers.end(); ++i) { 415 for (MarkerMap::iterator i = m_markers.begin(); i != m_markers.end(); ++i) {
353 for (size_t j = 0; j < i->value->size(); ++j) 416 MarkerLists* markers = i->value.get();
354 result.append(&(i->value->at(j))); 417 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::Marke rTypeIndexesCount; ++markerListIndex) {
418 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
419 for (size_t j = 0; list.get() && j < list->size(); ++j)
420 result.append(&(list->at(j)));
421 }
355 } 422 }
423 std::sort(result.begin(), result.end(), compareByStart);
356 return result; 424 return result;
357 } 425 }
358 426
359 Vector<DocumentMarker*> DocumentMarkerController::markersInRange(Range* range, D ocumentMarker::MarkerTypes markerTypes) 427 Vector<DocumentMarker*> DocumentMarkerController::markersInRange(Range* range, D ocumentMarker::MarkerTypes markerTypes)
360 { 428 {
361 if (!possiblyHasMarkers(markerTypes)) 429 if (!possiblyHasMarkers(markerTypes))
362 return Vector<DocumentMarker*>(); 430 return Vector<DocumentMarker*>();
363 431
364 Vector<DocumentMarker*> foundMarkers; 432 Vector<DocumentMarker*> foundMarkers;
365 433
(...skipping 25 matching lines...) Expand all
391 Vector<IntRect> result; 459 Vector<IntRect> result;
392 460
393 if (!possiblyHasMarkers(markerType)) 461 if (!possiblyHasMarkers(markerType))
394 return result; 462 return result;
395 ASSERT(!(m_markers.isEmpty())); 463 ASSERT(!(m_markers.isEmpty()));
396 464
397 // outer loop: process each node 465 // outer loop: process each node
398 MarkerMap::iterator end = m_markers.end(); 466 MarkerMap::iterator end = m_markers.end();
399 for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != e nd; ++nodeIterator) { 467 for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != e nd; ++nodeIterator) {
400 // inner loop; process each marker in this node 468 // inner loop; process each marker in this node
401 MarkerList* list = nodeIterator->value.get(); 469 MarkerLists* markers = nodeIterator->value.get();
402 unsigned markerCount = list->size(); 470 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::Marke rTypeIndexesCount; ++markerListIndex) {
403 for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) { 471 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
404 const RenderedDocumentMarker& marker = list->at(markerIndex); 472 if (!list || list->isEmpty() || list->begin()->type() != markerType)
473 continue;
474 for (unsigned markerIndex = 0; markerIndex < list->size(); ++markerI ndex) {
475 const RenderedDocumentMarker& marker = list->at(markerIndex);
405 476
406 // skip marker that is wrong type 477 if (!marker.isRendered())
407 if (marker.type() != markerType) 478 continue;
408 continue;
409 479
410 if (!marker.isRendered()) 480 result.append(marker.renderedRect());
411 continue; 481 }
412
413 result.append(marker.renderedRect());
414 } 482 }
415 } 483 }
416 484
417 return result; 485 return result;
418 } 486 }
419 487
420 void DocumentMarkerController::removeMarkers(Node* node, DocumentMarker::MarkerT ypes markerTypes) 488 void DocumentMarkerController::removeMarkers(Node* node, DocumentMarker::MarkerT ypes markerTypes)
421 { 489 {
422 if (!possiblyHasMarkers(markerTypes)) 490 if (!possiblyHasMarkers(markerTypes))
423 return; 491 return;
(...skipping 18 matching lines...) Expand all
442 if (iterator != m_markers.end()) 510 if (iterator != m_markers.end())
443 removeMarkersFromList(iterator, markerTypes); 511 removeMarkersFromList(iterator, markerTypes);
444 } 512 }
445 513
446 m_possiblyExistingMarkerTypes.remove(markerTypes); 514 m_possiblyExistingMarkerTypes.remove(markerTypes);
447 } 515 }
448 516
449 void DocumentMarkerController::removeMarkersFromList(MarkerMap::iterator iterato r, DocumentMarker::MarkerTypes markerTypes) 517 void DocumentMarkerController::removeMarkersFromList(MarkerMap::iterator iterato r, DocumentMarker::MarkerTypes markerTypes)
450 { 518 {
451 bool needsRepainting = false; 519 bool needsRepainting = false;
452 bool listCanBeRemoved; 520 bool nodeCanBeRemoved;
453 521
522 size_t emptyListsCount = 0;
454 if (markerTypes == DocumentMarker::AllMarkers()) { 523 if (markerTypes == DocumentMarker::AllMarkers()) {
455 needsRepainting = true; 524 needsRepainting = true;
456 listCanBeRemoved = true; 525 nodeCanBeRemoved = true;
457 } else { 526 } else {
458 MarkerList* list = iterator->value.get(); 527 MarkerLists* markers = iterator->value.get();
459 528
460 for (size_t i = 0; i != list->size(); ) { 529 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::Marke rTypeIndexesCount; ++markerListIndex) {
461 DocumentMarker marker = list->at(i); 530 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
462 531 if (!list || list->isEmpty()) {
463 // skip nodes that are not of the specified type 532 if (list.get() && list->isEmpty())
464 if (!markerTypes.contains(marker.type())) { 533 list.clear();
465 ++i; 534 ++emptyListsCount;
466 continue; 535 continue;
467 } 536 }
468 537 if (markerTypes.contains(list->begin()->type())) {
469 // pitch the old marker 538 list->clear();
470 list->remove(i); 539 list.clear();
471 needsRepainting = true; 540 ++emptyListsCount;
472 // i now is the index of the next marker 541 needsRepainting = true;
542 }
473 } 543 }
474 544
475 listCanBeRemoved = list->isEmpty(); 545 nodeCanBeRemoved = emptyListsCount == DocumentMarker::MarkerTypeIndexesC ount;
476 } 546 }
477 547
478 if (needsRepainting) { 548 if (needsRepainting) {
479 if (RenderObject* renderer = iterator->key->renderer()) 549 if (RenderObject* renderer = iterator->key->renderer())
480 renderer->repaint(); 550 renderer->repaint();
481 } 551 }
482 552
483 if (listCanBeRemoved) { 553 if (nodeCanBeRemoved) {
484 m_markers.remove(iterator); 554 m_markers.remove(iterator);
485 if (m_markers.isEmpty()) 555 if (m_markers.isEmpty())
486 m_possiblyExistingMarkerTypes = 0; 556 m_possiblyExistingMarkerTypes = 0;
487 } 557 }
488 } 558 }
489 559
490 void DocumentMarkerController::repaintMarkers(DocumentMarker::MarkerTypes marker Types) 560 void DocumentMarkerController::repaintMarkers(DocumentMarker::MarkerTypes marker Types)
491 { 561 {
492 if (!possiblyHasMarkers(markerTypes)) 562 if (!possiblyHasMarkers(markerTypes))
493 return; 563 return;
494 ASSERT(!m_markers.isEmpty()); 564 ASSERT(!m_markers.isEmpty());
495 565
496 // outer loop: process each markered node in the document 566 // outer loop: process each markered node in the document
497 MarkerMap::iterator end = m_markers.end(); 567 MarkerMap::iterator end = m_markers.end();
498 for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) { 568 for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) {
499 Node* node = i->key.get(); 569 Node* node = i->key.get();
500 570
501 // inner loop: process each marker in the current node 571 // inner loop: process each marker in the current node
502 MarkerList* list = i->value.get(); 572 MarkerLists* markers = i->value.get();
503 bool nodeNeedsRepaint = false; 573 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::Marke rTypeIndexesCount; ++markerListIndex) {
504 for (size_t i = 0; i != list->size(); ++i) { 574 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
505 DocumentMarker marker = list->at(i); 575 if (!list || list->isEmpty() || !markerTypes.contains(list->begin()- >type()))
576 continue;
506 577
507 // skip nodes that are not of the specified type 578 // cause the node to be redrawn
508 if (markerTypes.contains(marker.type())) { 579 if (RenderObject* renderer = node->renderer()) {
509 nodeNeedsRepaint = true; 580 renderer->repaint();
510 break; 581 break;
511 } 582 }
512 } 583 }
513
514 if (!nodeNeedsRepaint)
515 continue;
516
517 // cause the node to be redrawn
518 if (RenderObject* renderer = node->renderer())
519 renderer->repaint();
520 } 584 }
521 } 585 }
522 586
523 void DocumentMarkerController::invalidateRenderedRectsForMarkersInRect(const Lay outRect& r) 587 void DocumentMarkerController::invalidateRenderedRectsForMarkersInRect(const Lay outRect& r)
524 { 588 {
525 // outer loop: process each markered node in the document 589 // outer loop: process each markered node in the document
526 MarkerMap::iterator end = m_markers.end(); 590 MarkerMap::iterator end = m_markers.end();
527 for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) { 591 for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) {
528 592
529 // inner loop: process each rect in the current node 593 // inner loop: process each rect in the current node
530 MarkerList* list = i->value.get(); 594 MarkerLists* markers = i->value.get();
531 for (size_t listIndex = 0; listIndex < list->size(); ++listIndex) 595 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::Marke rTypeIndexesCount; ++markerListIndex) {
532 list->at(listIndex).invalidate(r); 596 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
597 for (size_t markerIndex = 0; list.get() && markerIndex < list->size( ); ++markerIndex)
598 list->at(markerIndex).invalidate(r);
599 }
533 } 600 }
534 } 601 }
535 602
536 void DocumentMarkerController::shiftMarkers(Node* node, unsigned startOffset, in t delta) 603 void DocumentMarkerController::shiftMarkers(Node* node, unsigned startOffset, in t delta)
537 { 604 {
538 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) 605 if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
539 return; 606 return;
540 ASSERT(!m_markers.isEmpty()); 607 ASSERT(!m_markers.isEmpty());
541 608
542 MarkerList* list = m_markers.get(node); 609 MarkerLists* markers = m_markers.get(node);
543 if (!list) 610 if (!markers)
544 return; 611 return;
545 612
546 bool docDirty = false; 613 bool docDirty = false;
547 for (size_t i = 0; i != list->size(); ++i) { 614 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTyp eIndexesCount; ++markerListIndex) {
548 RenderedDocumentMarker& marker = list->at(i); 615 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
549 if (marker.startOffset() >= startOffset) { 616 if (!list)
550 ASSERT((int)marker.startOffset() + delta >= 0); 617 continue;
551 marker.shiftOffsets(delta); 618 MarkerList::iterator startPos = std::lower_bound(list->begin(), list->en d(), startOffset, startsAfter);
619 for (MarkerList::iterator marker = startPos; marker != list->end(); ++ma rker) {
620 ASSERT((int)marker->startOffset() + delta >= 0);
621 marker->shiftOffsets(delta);
552 docDirty = true; 622 docDirty = true;
553 623
554 // Marker moved, so previously-computed rendered rectangle is now in valid 624 // Marker moved, so previously-computed rendered rectangle is now in valid
555 marker.invalidate(); 625 marker->invalidate();
556 } 626 }
557 } 627 }
558 628
559 // repaint the affected node 629 // repaint the affected node
560 if (docDirty && node->renderer()) 630 if (docDirty && node->renderer())
561 node->renderer()->repaint(); 631 node->renderer()->repaint();
562 } 632 }
563 633
564 void DocumentMarkerController::setMarkersActive(Range* range, bool active) 634 void DocumentMarkerController::setMarkersActive(Range* range, bool active)
565 { 635 {
566 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) 636 if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
567 return; 637 return;
568 ASSERT(!m_markers.isEmpty()); 638 ASSERT(!m_markers.isEmpty());
569 639
570 Node* startContainer = range->startContainer(); 640 Node* startContainer = range->startContainer();
571 Node* endContainer = range->endContainer(); 641 Node* endContainer = range->endContainer();
572 642
573 Node* pastLastNode = range->pastLastNode(); 643 Node* pastLastNode = range->pastLastNode();
574 644
575 for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTrave rsal::next(node)) { 645 for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTrave rsal::next(node)) {
576 int startOffset = node == startContainer ? range->startOffset() : 0; 646 int startOffset = node == startContainer ? range->startOffset() : 0;
577 int endOffset = node == endContainer ? range->endOffset() : INT_MAX; 647 int endOffset = node == endContainer ? range->endOffset() : INT_MAX;
578 setMarkersActive(node, startOffset, endOffset, active); 648 setMarkersActive(node, startOffset, endOffset, active);
579 } 649 }
580 } 650 }
581 651
582 void DocumentMarkerController::setMarkersActive(Node* node, unsigned startOffset , unsigned endOffset, bool active) 652 void DocumentMarkerController::setMarkersActive(Node* node, unsigned startOffset , unsigned endOffset, bool active)
583 { 653 {
584 MarkerList* list = m_markers.get(node); 654 MarkerLists* markers = m_markers.get(node);
585 if (!list) 655 if (!markers)
586 return; 656 return;
587 657
588 bool docDirty = false; 658 bool docDirty = false;
589 for (size_t i = 0; i != list->size(); ++i) { 659 OwnPtr<MarkerList>& list = (*markers)[MarkerTypeToMarkerIndex(DocumentMarker ::TextMatch)];
590 DocumentMarker& marker = list->at(i); 660 if (!list)
661 return;
662 MarkerList::iterator startPos = std::upper_bound(list->begin(), list->end(), startOffset, endsBefore);
663 for (MarkerList::iterator marker = startPos; marker != list->end(); ++marker ) {
591 664
592 // Markers are returned in order, so stop if we are now past the specifi ed range. 665 // Markers are returned in order, so stop if we are now past the specifi ed range.
593 if (marker.startOffset() >= endOffset) 666 if (marker->startOffset() >= endOffset)
594 break; 667 break;
595 668
596 // Skip marker that is wrong type or before target. 669 marker->setActiveMatch(active);
597 if (marker.endOffset() <= startOffset || marker.type() != DocumentMarker ::TextMatch)
598 continue;
599
600 marker.setActiveMatch(active);
601 docDirty = true; 670 docDirty = true;
602 } 671 }
603 672
604 // repaint the affected node 673 // repaint the affected node
605 if (docDirty && node->renderer()) 674 if (docDirty && node->renderer())
606 node->renderer()->repaint(); 675 node->renderer()->repaint();
607 } 676 }
608 677
609 bool DocumentMarkerController::hasMarkers(Range* range, DocumentMarker::MarkerTy pes markerTypes) 678 bool DocumentMarkerController::hasMarkers(Range* range, DocumentMarker::MarkerTy pes markerTypes)
610 { 679 {
(...skipping 25 matching lines...) Expand all
636 } 705 }
637 706
638 #ifndef NDEBUG 707 #ifndef NDEBUG
639 void DocumentMarkerController::showMarkers() const 708 void DocumentMarkerController::showMarkers() const
640 { 709 {
641 fprintf(stderr, "%d nodes have markers:\n", m_markers.size()); 710 fprintf(stderr, "%d nodes have markers:\n", m_markers.size());
642 MarkerMap::const_iterator end = m_markers.end(); 711 MarkerMap::const_iterator end = m_markers.end();
643 for (MarkerMap::const_iterator nodeIterator = m_markers.begin(); nodeIterato r != end; ++nodeIterator) { 712 for (MarkerMap::const_iterator nodeIterator = m_markers.begin(); nodeIterato r != end; ++nodeIterator) {
644 Node* node = nodeIterator->key.get(); 713 Node* node = nodeIterator->key.get();
645 fprintf(stderr, "%p", node); 714 fprintf(stderr, "%p", node);
646 MarkerList* list = nodeIterator->value.get(); 715 MarkerLists* markers = m_markers.get(node);
647 for (unsigned markerIndex = 0; markerIndex < list->size(); ++markerIndex ) { 716 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::Marke rTypeIndexesCount; ++markerListIndex) {
648 const DocumentMarker& marker = list->at(markerIndex); 717 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
649 fprintf(stderr, " %d:[%d:%d](%d)", marker.type(), marker.startOffset (), marker.endOffset(), marker.activeMatch()); 718 for (unsigned markerIndex = 0; list.get() && markerIndex < list->siz e(); ++markerIndex) {
719 const DocumentMarker& marker = list->at(markerIndex);
720 fprintf(stderr, " %d:[%d:%d](%d)", marker.type(), marker.startOf fset(), marker.endOffset(), marker.activeMatch());
721 }
650 } 722 }
651 723
652 fprintf(stderr, "\n"); 724 fprintf(stderr, "\n");
653 } 725 }
654 } 726 }
655 #endif 727 #endif
656 728
657 } // namespace WebCore 729 } // namespace WebCore
658 730
659 #ifndef NDEBUG 731 #ifndef NDEBUG
660 void showDocumentMarkers(const WebCore::DocumentMarkerController* controller) 732 void showDocumentMarkers(const WebCore::DocumentMarkerController* controller)
661 { 733 {
662 if (controller) 734 if (controller)
663 controller->showMarkers(); 735 controller->showMarkers();
664 } 736 }
665 #endif 737 #endif
OLDNEW
« no previous file with comments | « Source/core/dom/DocumentMarkerController.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698