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

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