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

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: Rebase & split marker list by marker type. 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
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:
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 doesNotOverlap(const DocumentMarker& lhv, const DocumentMarker& rhv)
159 {
160 return lhv.endOffset() < rhv.startOffset();
161 }
162
136 // Markers are stored in order sorted by their start offset. 163 // Markers are stored in order sorted by their start offset.
137 // Markers of the same type do not overlap each other. 164 // Markers of the same type do not overlap each other.
138 165
139 void DocumentMarkerController::addMarker(Node* node, const DocumentMarker& newMa rker) 166 void DocumentMarkerController::addMarker(Node* node, const DocumentMarker& newMa rker)
140 { 167 {
141 ASSERT(newMarker.endOffset() >= newMarker.startOffset()); 168 ASSERT(newMarker.endOffset() >= newMarker.startOffset());
142 if (newMarker.endOffset() == newMarker.startOffset()) 169 if (newMarker.endOffset() == newMarker.startOffset())
143 return; 170 return;
144 171
145 m_possiblyExistingMarkerTypes.add(newMarker.type()); 172 m_possiblyExistingMarkerTypes.add(newMarker.type());
146 173
147 OwnPtr<MarkerList>& list = m_markers.add(node, nullptr).iterator->value; 174 OwnPtr<MarkerLists>& markers = m_markers.add(node, nullptr).iterator->value;
148 175 if (!markers) {
149 if (!list) { 176 markers = adoptPtr(new MarkerLists);
150 list = adoptPtr(new MarkerList); 177 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::Marke rTypeIndexesCount; ++markerListIndex) {
groby-ooo-7-16 2013/09/19 18:17:09 I'd suggest only adding a MarkerList for the neede
pstanek 2013/09/21 21:09:59 Done.
178 markers->insert(markerListIndex, adoptPtr(new MarkerList));
179 }
180 }
181 OwnPtr<MarkerList>& list = markers->at(MarkerTypeToMarkerIndex(newMarker.typ e()));
182 if (list->isEmpty()) {
151 list->append(RenderedDocumentMarker(newMarker)); 183 list->append(RenderedDocumentMarker(newMarker));
152 } else { 184 } else {
153 RenderedDocumentMarker toInsert(newMarker); 185 RenderedDocumentMarker toInsert(newMarker);
154 size_t numMarkers = list->size(); 186 if (list->last().endOffset() >= newMarker.startOffset()) {
155 size_t i; 187 if (toInsert.type() != DocumentMarker::TextMatch) {
156 // Iterate over all markers whose start offset is less than or equal to the new marker's. 188 mergeOverlapping(list.get(), toInsert);
157 // If one of them is of the same type as the new marker and touches it o r intersects with it 189 } else {
158 // (there is at most one), remove it and adjust the new marker's start o ffset to encompass it. 190 MarkerList::iterator pos = std::lower_bound(list->begin(), list- >end(), toInsert, startsFurther);
159 for (i = 0; i < numMarkers; ++i) { 191 list->insert(pos - list->begin(), RenderedDocumentMarker(toInser t));
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 } 192 }
193 } else {
194 list->append(RenderedDocumentMarker(toInsert));
groby-ooo-7-16 2013/09/19 18:17:09 I'd combine that into the list->empty branch() i.e
pstanek 2013/09/21 21:09:59 Done.
169 } 195 }
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 } 196 }
191 197
groby-ooo-7-16 2013/09/19 18:17:09 Side note: I'm surprised this doesn't set docDirty
192 // repaint the affected node 198 // repaint the affected node
193 if (node->renderer()) 199 if (node->renderer())
194 node->renderer()->repaint(); 200 node->renderer()->repaint();
195 } 201 }
196 202
203 void DocumentMarkerController::mergeOverlapping(MarkerList* list, DocumentMarker & toInsert)
204 {
205 // Iterate over all markers whose start offset is less than or equal to the new marker's.
206 // If one of them is of the same type as the new marker and touches it or in tersects with it
207 // (there is at most one), remove it and adjust the new marker's start offse t to encompass it.
208 MarkerList::iterator firstOverlapping = list->begin();
groby-ooo-7-16 2013/09/19 18:17:09 I think this can now be simplified significantly.
pstanek 2013/09/21 21:09:59 Done.
209 size_t offset = 0;
210 do {
211 firstOverlapping = std::lower_bound(firstOverlapping + offset, list->end (), toInsert, doesNotOverlap);
212 offset = 1;
213 } while (firstOverlapping != list->end() && firstOverlapping->type() != toIn sert.type());
214
215 size_t index = firstOverlapping - list->begin();
216 list->insert(index, RenderedDocumentMarker(toInsert));
217 MarkerList::iterator inserted = firstOverlapping;
218 ++firstOverlapping;
219 if (firstOverlapping != list->end() && !startsFurther(*inserted, *firstOverl apping)) {
220 inserted->setStartOffset(firstOverlapping->startOffset());
221 list->remove(firstOverlapping - list->begin());
222 }
223
224 // Iterate over all markers whose end offset is less than or equal to the ne w marker's.
225 // If one of them is of the same type as the new marker and touches it or in tersects with it
226 // adjust the new marker's end offset to cover it if necessary.
227 for (MarkerList::iterator i = inserted + 1; i != list->end(); ) {
228 if (i->startOffset() > inserted->endOffset())
229 break;
230 list->remove(i - list->begin());
231 if (inserted->endOffset() <= i->endOffset()) {
232 inserted->setEndOffset(i->endOffset());
233 break;
234 }
235 }
236 }
237
197 // copies markers from srcNode to dstNode, applying the specified shift delta to the copies. The shift is 238 // 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. 239 // 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) 240 void DocumentMarkerController::copyMarkers(Node* srcNode, unsigned startOffset, int length, Node* dstNode, int delta)
200 { 241 {
201 if (length <= 0) 242 if (length <= 0)
202 return; 243 return;
203 244
204 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) 245 if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
205 return; 246 return;
206 ASSERT(!m_markers.isEmpty()); 247 ASSERT(!m_markers.isEmpty());
207 248
208 MarkerList* list = m_markers.get(srcNode); 249 MarkerLists* markers = m_markers.get(srcNode);
209 if (!list) 250 if (!markers)
210 return; 251 return;
211 252
212 bool docDirty = false; 253 bool docDirty = false;
213 unsigned endOffset = startOffset + length - 1; 254 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTyp eIndexesCount; ++markerListIndex) {
214 for (size_t i = 0; i != list->size(); ++i) { 255 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
215 DocumentMarker marker = list->at(i);
216 256
217 // stop if we are now past the specified range 257 unsigned endOffset = startOffset + length - 1;
218 if (marker.startOffset() > endOffset) 258 for (size_t i = 0; i != list->size(); ++i) {
219 break; 259 DocumentMarker marker = list->at(i);
220 260
221 // skip marker that is before the specified range or is the wrong type 261 // stop if we are now past the specified range
222 if (marker.endOffset() < startOffset) 262 if (marker.startOffset() > endOffset)
223 continue; 263 break;
224 264
225 // pin the marker to the specified range and apply the shift delta 265 // skip marker that is before the specified range
226 docDirty = true; 266 if (marker.endOffset() < startOffset)
groby-ooo-7-16 2013/09/19 18:17:09 We can lower_bound this.
pstanek 2013/09/21 21:09:59 Done.
227 if (marker.startOffset() < startOffset) 267 continue;
228 marker.setStartOffset(startOffset);
229 if (marker.endOffset() > endOffset)
230 marker.setEndOffset(endOffset);
231 marker.shiftOffsets(delta);
232 268
233 addMarker(dstNode, marker); 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->isEmpty()) {
259 // markers are returned in order, so stop if we are now past the specifi ed range 304 ++emptyListsCount;
260 if (marker.startOffset() >= endOffset)
261 break;
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())) {
groby-ooo-7-16 2013/09/19 18:17:09 Personal nit: No need for curlies on single-line b
pstanek 2013/09/21 21:09:59 Done.
308 continue;
309 }
310 unsigned endOffset = startOffset + length;
311 for (size_t i = 0; i < list->size();) {
312 DocumentMarker marker = list->at(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 // skip marker that is before target
273 list->remove(i); 319 if (marker.endOffset() <= startOffset) {
groby-ooo-7-16 2013/09/19 18:17:09 I suppose we could upper_bound this, saving us ite
pstanek 2013/09/21 21:09:59 Done.
320 i++;
321 continue;
322 }
274 323
275 if (shouldRemovePartiallyOverlappingMarker) 324 // at this point we know that marker and target intersect in some wa y
276 // Stop here. Don't add resulting slices back. 325 docDirty = true;
277 continue;
278 326
279 // add either of the resulting slices that are left after removing targe t 327 // pitch the old marker
280 if (startOffset > marker.startOffset()) { 328 list->remove(i);
281 DocumentMarker newLeft = marker; 329
282 newLeft.setEndOffset(startOffset); 330 if (shouldRemovePartiallyOverlappingMarker) {
283 list->insert(i, RenderedDocumentMarker(newLeft)); 331 // Stop here. Don't add resulting slices back.
284 // i now points to the newly-inserted node, but we want to skip that one 332 continue;
285 i++; 333 }
286 } 334
287 if (marker.endOffset() > endOffset) { 335 // add either of the resulting slices that are left after removing t arget
288 DocumentMarker newRight = marker; 336 if (startOffset > marker.startOffset()) {
289 newRight.setStartOffset(endOffset); 337 DocumentMarker newLeft = marker;
290 list->insert(i, RenderedDocumentMarker(newRight)); 338 newLeft.setEndOffset(startOffset);
291 // i now points to the newly-inserted node, but we want to skip that one 339 list->insert(i, RenderedDocumentMarker(newLeft));
292 i++; 340 // i now points to the newly-inserted node, but we want to skip that one
341 i++;
342 }
343 if (marker.endOffset() > endOffset) {
344 DocumentMarker newRight = marker;
345 newRight.setStartOffset(endOffset);
346 list->insert(i, RenderedDocumentMarker(newRight));
347 // i now points to the newly-inserted node, but we want to skip that one
348 i++;
349 }
293 } 350 }
294 } 351 }
295 352
296 if (list->isEmpty()) { 353 if (emptyListsCount == DocumentMarker::MarkerTypeIndexesCount) {
groby-ooo-7-16 2013/09/19 18:17:09 If we do ad-hoc creation for individual lists, we
pstanek 2013/09/21 21:09:59 Done.
297 m_markers.remove(node); 354 m_markers.remove(node);
298 if (m_markers.isEmpty()) 355 if (m_markers.isEmpty())
299 m_possiblyExistingMarkerTypes = 0; 356 m_possiblyExistingMarkerTypes = 0;
300 } 357 }
301 358
302 // repaint the affected node 359 // repaint the affected node
303 if (docDirty && node->renderer()) 360 if (docDirty && node->renderer())
304 node->renderer()->repaint(); 361 node->renderer()->repaint();
305 } 362 }
306 363
307 DocumentMarker* DocumentMarkerController::markerContainingPoint(const LayoutPoin t& point, DocumentMarker::MarkerType markerType) 364 DocumentMarker* DocumentMarkerController::markerContainingPoint(const LayoutPoin t& point, DocumentMarker::MarkerType markerType)
308 { 365 {
309 if (!possiblyHasMarkers(markerType)) 366 if (!possiblyHasMarkers(markerType))
310 return 0; 367 return 0;
311 ASSERT(!(m_markers.isEmpty())); 368 ASSERT(!(m_markers.isEmpty()));
312 369
313 // outer loop: process each node that contains any markers 370 // outer loop: process each node that contains any markers
314 MarkerMap::iterator end = m_markers.end(); 371 MarkerMap::iterator end = m_markers.end();
315 for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != e nd; ++nodeIterator) { 372 for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != e nd; ++nodeIterator) {
316 // inner loop; process each marker in this node 373 // inner loop; process each marker in this node
317 MarkerList* list = nodeIterator->value.get(); 374 MarkerLists* markers = nodeIterator->value.get();
375 OwnPtr<MarkerList>& list = (*markers)[MarkerTypeToMarkerIndex(markerType )];
318 unsigned markerCount = list->size(); 376 unsigned markerCount = list->size();
319 for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) { 377 for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) {
320 RenderedDocumentMarker& marker = list->at(markerIndex); 378 RenderedDocumentMarker& marker = list->at(markerIndex);
321 379
322 // skip marker that is wrong type
323 if (marker.type() != markerType)
324 continue;
325
326 if (marker.contains(point)) 380 if (marker.contains(point))
327 return &marker; 381 return &marker;
328 } 382 }
329 } 383 }
330 384
331 return 0; 385 return 0;
332 } 386 }
333 387
334 Vector<DocumentMarker*> DocumentMarkerController::markersFor(Node* node, Documen tMarker::MarkerTypes markerTypes) 388 Vector<DocumentMarker*> DocumentMarkerController::markersFor(Node* node, Documen tMarker::MarkerTypes markerTypes)
335 { 389 {
336 Vector<DocumentMarker*> result; 390 Vector<DocumentMarker*> result;
337 MarkerList* list = m_markers.get(node); 391
338 if (!list) 392 MarkerLists* markers = m_markers.get(node);
393 if (!markers)
339 return result; 394 return result;
340 395
341 for (size_t i = 0; i < list->size(); ++i) { 396 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTyp eIndexesCount; ++markerListIndex) {
342 if (markerTypes.contains(list->at(i).type())) 397 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
398 if (list->isEmpty() || !markerTypes.contains(list->begin()->type()))
399 continue;
400
401 for (size_t i = 0; i < list->size(); ++i) {
groby-ooo-7-16 2013/09/19 18:17:09 nit: no curlies on single-line statements.
pstanek 2013/09/21 21:09:59 Done.
343 result.append(&(list->at(i))); 402 result.append(&(list->at(i)));
403 }
344 } 404 }
345 405
346 return result; 406 return result;
347 } 407 }
348 408
349 Vector<DocumentMarker*> DocumentMarkerController::markers() 409 Vector<DocumentMarker*> DocumentMarkerController::markers()
groby-ooo-7-16 2013/09/19 18:17:09 I'm wondering if the callers of this expect the ma
pstanek 2013/09/20 15:07:40 Good point. it seems they has to.
groby-ooo-7-16 2013/09/20 15:35:58 A quick code search actually reveals no callers?
pstanek 2013/09/21 21:09:59 Done.
350 { 410 {
351 Vector<DocumentMarker*> result; 411 Vector<DocumentMarker*> result;
352 for (MarkerMap::iterator i = m_markers.begin(); i != m_markers.end(); ++i) { 412 for (MarkerMap::iterator i = m_markers.begin(); i != m_markers.end(); ++i) {
353 for (size_t j = 0; j < i->value->size(); ++j) 413 MarkerLists* markers = i->value.get();
354 result.append(&(i->value->at(j))); 414 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::Marke rTypeIndexesCount; ++markerListIndex) {
415 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
416 for (size_t j = 0; j < list->size(); ++j)
groby-ooo-7-16 2013/09/19 18:17:09 I believe Vector has appendVector, which does just
pstanek 2013/09/20 15:07:40 Type mismatch. MarkerList is Vector<DocumentMarker
417 result.append(&(list->at(j)));
418 }
355 } 419 }
356 return result; 420 return result;
357 } 421 }
358 422
359 Vector<DocumentMarker*> DocumentMarkerController::markersInRange(Range* range, D ocumentMarker::MarkerTypes markerTypes) 423 Vector<DocumentMarker*> DocumentMarkerController::markersInRange(Range* range, D ocumentMarker::MarkerTypes markerTypes)
groby-ooo-7-16 2013/09/19 18:17:09 Same as above: Do they need to be sorted?
groby-ooo-7-16 2013/09/20 15:35:58 WebFrameImpl::replaceMisspelledRange does - but ma
pstanek 2013/09/21 21:09:59 Done.
360 { 424 {
361 if (!possiblyHasMarkers(markerTypes)) 425 if (!possiblyHasMarkers(markerTypes))
362 return Vector<DocumentMarker*>(); 426 return Vector<DocumentMarker*>();
363 427
364 Vector<DocumentMarker*> foundMarkers; 428 Vector<DocumentMarker*> foundMarkers;
365 429
366 Node* startContainer = range->startContainer(); 430 Node* startContainer = range->startContainer();
367 ASSERT(startContainer); 431 ASSERT(startContainer);
368 Node* endContainer = range->endContainer(); 432 Node* endContainer = range->endContainer();
369 ASSERT(endContainer); 433 ASSERT(endContainer);
370 434
371 Node* pastLastNode = range->pastLastNode(); 435 Node* pastLastNode = range->pastLastNode();
372 for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTrave rsal::next(node)) { 436 for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTrave rsal::next(node)) {
373 Vector<DocumentMarker*> markers = markersFor(node); 437 Vector<DocumentMarker*> markers = markersFor(node);
374 Vector<DocumentMarker*>::const_iterator end = markers.end(); 438 Vector<DocumentMarker*>::const_iterator end = markers.end();
375 for (Vector<DocumentMarker*>::const_iterator it = markers.begin(); it != end; ++it) { 439 for (Vector<DocumentMarker*>::const_iterator it = markers.begin(); it != end; ++it) {
376 DocumentMarker* marker = *it; 440 DocumentMarker* marker = *it;
377 if (!markerTypes.contains(marker->type())) 441 if (!markerTypes.contains(marker->type()))
378 continue; 442 continue;
379 if (node == startContainer && marker->endOffset() <= static_cast<uns igned>(range->startOffset())) 443 if (node == startContainer && marker->endOffset() <= static_cast<uns igned>(range->startOffset()))
groby-ooo-7-16 2013/09/19 18:17:09 I suppose we could do a lower bounds check and jus
pstanek 2013/09/20 15:07:40 This calls makersFor() returning one vector with a
groby-ooo-7-16 2013/09/20 15:35:58 Yes, that's why I suggested filing those as separa
380 continue; 444 continue;
381 if (node == endContainer && marker->startOffset() >= static_cast<uns igned>(range->endOffset())) 445 if (node == endContainer && marker->startOffset() >= static_cast<uns igned>(range->endOffset()))
382 continue; 446 continue;
383 foundMarkers.append(marker); 447 foundMarkers.append(marker);
384 } 448 }
385 } 449 }
386 return foundMarkers; 450 return foundMarkers;
387 } 451 }
388 452
389 Vector<IntRect> DocumentMarkerController::renderedRectsForMarkers(DocumentMarker ::MarkerType markerType) 453 Vector<IntRect> DocumentMarkerController::renderedRectsForMarkers(DocumentMarker ::MarkerType markerType)
390 { 454 {
391 Vector<IntRect> result; 455 Vector<IntRect> result;
392 456
393 if (!possiblyHasMarkers(markerType)) 457 if (!possiblyHasMarkers(markerType))
394 return result; 458 return result;
395 ASSERT(!(m_markers.isEmpty())); 459 ASSERT(!(m_markers.isEmpty()));
396 460
397 // outer loop: process each node 461 // outer loop: process each node
398 MarkerMap::iterator end = m_markers.end(); 462 MarkerMap::iterator end = m_markers.end();
399 for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != e nd; ++nodeIterator) { 463 for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != e nd; ++nodeIterator) {
400 // inner loop; process each marker in this node 464 // inner loop; process each marker in this node
401 MarkerList* list = nodeIterator->value.get(); 465 MarkerLists* markers = nodeIterator->value.get();
402 unsigned markerCount = list->size(); 466 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::Marke rTypeIndexesCount; ++markerListIndex) {
403 for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) { 467 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
404 const RenderedDocumentMarker& marker = list->at(markerIndex); 468 if (list->isEmpty() || list->begin()->type() != markerType)
469 continue;
470 for (unsigned markerIndex = 0; markerIndex < list->size(); ++markerI ndex) {
471 const RenderedDocumentMarker& marker = list->at(markerIndex);
405 472
406 // skip marker that is wrong type 473 if (!marker.isRendered())
407 if (marker.type() != markerType) 474 continue;
408 continue;
409 475
410 if (!marker.isRendered()) 476 result.append(marker.renderedRect());
411 continue; 477 }
412
413 result.append(marker.renderedRect());
414 } 478 }
415 } 479 }
416 480
417 return result; 481 return result;
418 } 482 }
419 483
420 void DocumentMarkerController::removeMarkers(Node* node, DocumentMarker::MarkerT ypes markerTypes) 484 void DocumentMarkerController::removeMarkers(Node* node, DocumentMarker::MarkerT ypes markerTypes)
421 { 485 {
422 if (!possiblyHasMarkers(markerTypes)) 486 if (!possiblyHasMarkers(markerTypes))
423 return; 487 return;
(...skipping 18 matching lines...) Expand all
442 if (iterator != m_markers.end()) 506 if (iterator != m_markers.end())
443 removeMarkersFromList(iterator, markerTypes); 507 removeMarkersFromList(iterator, markerTypes);
444 } 508 }
445 509
446 m_possiblyExistingMarkerTypes.remove(markerTypes); 510 m_possiblyExistingMarkerTypes.remove(markerTypes);
447 } 511 }
448 512
449 void DocumentMarkerController::removeMarkersFromList(MarkerMap::iterator iterato r, DocumentMarker::MarkerTypes markerTypes) 513 void DocumentMarkerController::removeMarkersFromList(MarkerMap::iterator iterato r, DocumentMarker::MarkerTypes markerTypes)
450 { 514 {
451 bool needsRepainting = false; 515 bool needsRepainting = false;
452 bool listCanBeRemoved; 516 bool nodeCanBeRemoved;
453 517
518 size_t emptyListsCount = 0;
454 if (markerTypes == DocumentMarker::AllMarkers()) { 519 if (markerTypes == DocumentMarker::AllMarkers()) {
455 needsRepainting = true; 520 needsRepainting = true;
456 listCanBeRemoved = true; 521 nodeCanBeRemoved = true;
457 } else { 522 } else {
458 MarkerList* list = iterator->value.get(); 523 MarkerLists* markers = iterator->value.get();
459 524
460 for (size_t i = 0; i != list->size(); ) { 525 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::Marke rTypeIndexesCount; ++markerListIndex) {
461 DocumentMarker marker = list->at(i); 526 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
462 527 if (list->isEmpty()) {
463 // skip nodes that are not of the specified type 528 ++emptyListsCount;
464 if (!markerTypes.contains(marker.type())) {
465 ++i;
466 continue; 529 continue;
467 } 530 }
468 531 if (markerTypes.contains(list->begin()->type())) {
469 // pitch the old marker 532 list->clear();
470 list->remove(i); 533 ++emptyListsCount;
471 needsRepainting = true; 534 needsRepainting = true;
472 // i now is the index of the next marker 535 }
473 } 536 }
474 537
475 listCanBeRemoved = list->isEmpty(); 538 nodeCanBeRemoved = emptyListsCount == DocumentMarker::MarkerTypeIndexesC ount;
476 } 539 }
477 540
478 if (needsRepainting) { 541 if (needsRepainting) {
479 if (RenderObject* renderer = iterator->key->renderer()) 542 if (RenderObject* renderer = iterator->key->renderer())
480 renderer->repaint(); 543 renderer->repaint();
481 } 544 }
482 545
483 if (listCanBeRemoved) { 546 if (nodeCanBeRemoved) {
484 m_markers.remove(iterator); 547 m_markers.remove(iterator);
485 if (m_markers.isEmpty()) 548 if (m_markers.isEmpty())
486 m_possiblyExistingMarkerTypes = 0; 549 m_possiblyExistingMarkerTypes = 0;
487 } 550 }
488 } 551 }
489 552
490 void DocumentMarkerController::repaintMarkers(DocumentMarker::MarkerTypes marker Types) 553 void DocumentMarkerController::repaintMarkers(DocumentMarker::MarkerTypes marker Types)
491 { 554 {
492 if (!possiblyHasMarkers(markerTypes)) 555 if (!possiblyHasMarkers(markerTypes))
493 return; 556 return;
494 ASSERT(!m_markers.isEmpty()); 557 ASSERT(!m_markers.isEmpty());
495 558
496 // outer loop: process each markered node in the document 559 // outer loop: process each markered node in the document
497 MarkerMap::iterator end = m_markers.end(); 560 MarkerMap::iterator end = m_markers.end();
498 for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) { 561 for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) {
499 Node* node = i->key.get(); 562 Node* node = i->key.get();
500 563
501 // inner loop: process each marker in the current node 564 // inner loop: process each marker in the current node
502 MarkerList* list = i->value.get(); 565 MarkerLists* markers = i->value.get();
503 bool nodeNeedsRepaint = false; 566 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::Marke rTypeIndexesCount; ++markerListIndex) {
504 for (size_t i = 0; i != list->size(); ++i) { 567 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
505 DocumentMarker marker = list->at(i); 568 if (list->isEmpty() || !markerTypes.contains(list->begin()->type()))
569 continue;
506 570
507 // skip nodes that are not of the specified type 571 // cause the node to be redrawn
508 if (markerTypes.contains(marker.type())) { 572 if (RenderObject* renderer = node->renderer())
509 nodeNeedsRepaint = true; 573 renderer->repaint();
groby-ooo-7-16 2013/09/19 18:17:09 I believe this needs a break - otherwise, this can
pstanek 2013/09/21 21:09:59 Done.
510 break;
511 }
512 } 574 }
513
514 if (!nodeNeedsRepaint)
515 continue;
516
517 // cause the node to be redrawn
518 if (RenderObject* renderer = node->renderer())
519 renderer->repaint();
520 } 575 }
521 } 576 }
522 577
523 void DocumentMarkerController::invalidateRenderedRectsForMarkersInRect(const Lay outRect& r) 578 void DocumentMarkerController::invalidateRenderedRectsForMarkersInRect(const Lay outRect& r)
524 { 579 {
525 // outer loop: process each markered node in the document 580 // outer loop: process each markered node in the document
526 MarkerMap::iterator end = m_markers.end(); 581 MarkerMap::iterator end = m_markers.end();
527 for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) { 582 for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) {
528 583
529 // inner loop: process each rect in the current node 584 // inner loop: process each rect in the current node
530 MarkerList* list = i->value.get(); 585 MarkerLists* markers = i->value.get();
531 for (size_t listIndex = 0; listIndex < list->size(); ++listIndex) 586 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::Marke rTypeIndexesCount; ++markerListIndex) {
532 list->at(listIndex).invalidate(r); 587 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
588 for (size_t markerIndex = 0; markerIndex < list->size(); ++markerInd ex)
589 list->at(markerIndex).invalidate(r);
590 }
533 } 591 }
534 } 592 }
535 593
536 void DocumentMarkerController::shiftMarkers(Node* node, unsigned startOffset, in t delta) 594 void DocumentMarkerController::shiftMarkers(Node* node, unsigned startOffset, in t delta)
537 { 595 {
538 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) 596 if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
539 return; 597 return;
540 ASSERT(!m_markers.isEmpty()); 598 ASSERT(!m_markers.isEmpty());
541 599
542 MarkerList* list = m_markers.get(node); 600 MarkerLists* markers = m_markers.get(node);
543 if (!list) 601 if (!markers)
544 return; 602 return;
545 603
546 bool docDirty = false; 604 bool docDirty = false;
547 for (size_t i = 0; i != list->size(); ++i) { 605 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTyp eIndexesCount; ++markerListIndex) {
548 RenderedDocumentMarker& marker = list->at(i); 606 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
549 if (marker.startOffset() >= startOffset) { 607 for (size_t i = 0; i != list->size(); ++i) {
550 ASSERT((int)marker.startOffset() + delta >= 0); 608 RenderedDocumentMarker& marker = list->at(i);
551 marker.shiftOffsets(delta); 609 if (marker.startOffset() >= startOffset) {
groby-ooo-7-16 2013/09/19 18:17:09 upper_bound
pstanek 2013/09/20 18:56:00 "Unlike lower_bound, the value pointed by the iter
pstanek 2013/09/21 21:09:59 Done.
552 docDirty = true; 610 ASSERT((int)marker.startOffset() + delta >= 0);
611 marker.shiftOffsets(delta);
612 docDirty = true;
553 613
554 // Marker moved, so previously-computed rendered rectangle is now in valid 614 // Marker moved, so previously-computed rendered rectangle is no w invalid
555 marker.invalidate(); 615 marker.invalidate();
616 }
556 } 617 }
557 } 618 }
558 619
559 // repaint the affected node 620 // repaint the affected node
560 if (docDirty && node->renderer()) 621 if (docDirty && node->renderer())
561 node->renderer()->repaint(); 622 node->renderer()->repaint();
562 } 623 }
563 624
564 void DocumentMarkerController::setMarkersActive(Range* range, bool active) 625 void DocumentMarkerController::setMarkersActive(Range* range, bool active)
565 { 626 {
566 if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) 627 if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
567 return; 628 return;
568 ASSERT(!m_markers.isEmpty()); 629 ASSERT(!m_markers.isEmpty());
569 630
570 Node* startContainer = range->startContainer(); 631 Node* startContainer = range->startContainer();
571 Node* endContainer = range->endContainer(); 632 Node* endContainer = range->endContainer();
572 633
573 Node* pastLastNode = range->pastLastNode(); 634 Node* pastLastNode = range->pastLastNode();
574 635
575 for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTrave rsal::next(node)) { 636 for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTrave rsal::next(node)) {
576 int startOffset = node == startContainer ? range->startOffset() : 0; 637 int startOffset = node == startContainer ? range->startOffset() : 0;
577 int endOffset = node == endContainer ? range->endOffset() : INT_MAX; 638 int endOffset = node == endContainer ? range->endOffset() : INT_MAX;
578 setMarkersActive(node, startOffset, endOffset, active); 639 setMarkersActive(node, startOffset, endOffset, active);
579 } 640 }
580 } 641 }
581 642
582 void DocumentMarkerController::setMarkersActive(Node* node, unsigned startOffset , unsigned endOffset, bool active) 643 void DocumentMarkerController::setMarkersActive(Node* node, unsigned startOffset , unsigned endOffset, bool active)
583 { 644 {
584 MarkerList* list = m_markers.get(node); 645 MarkerLists* markers = m_markers.get(node);
585 if (!list) 646 if (!markers)
586 return; 647 return;
587 648
588 bool docDirty = false; 649 bool docDirty = false;
589 for (size_t i = 0; i != list->size(); ++i) { 650 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTyp eIndexesCount; ++markerListIndex) {
590 DocumentMarker& marker = list->at(i); 651 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
652 for (size_t i = 0; i != list->size(); ++i) {
653 DocumentMarker& marker = list->at(i);
591 654
592 // Markers are returned in order, so stop if we are now past the specifi ed range. 655 // Markers are returned in order, so stop if we are now past the spe cified range.
593 if (marker.startOffset() >= endOffset) 656 if (marker.startOffset() >= endOffset)
594 break; 657 break;
595 658
596 // Skip marker that is wrong type or before target. 659 // Skip marker that is before target.
597 if (marker.endOffset() <= startOffset || marker.type() != DocumentMarker ::TextMatch) 660 if (marker.endOffset() <= startOffset || marker.type() != DocumentMa rker::TextMatch)
groby-ooo-7-16 2013/09/19 18:17:09 upper_bound
pstanek 2013/09/20 15:17:33 Oh. this does anything for TextMatch markers only
groby-ooo-7-16 2013/09/20 15:35:58 Well, a tiny bit at least :) On 2013/09/20 15:17:3
pstanek 2013/09/21 21:09:59 Done.
598 continue; 661 continue;
599 662
600 marker.setActiveMatch(active); 663 marker.setActiveMatch(active);
601 docDirty = true; 664 docDirty = true;
665 }
602 } 666 }
603 667
604 // repaint the affected node 668 // repaint the affected node
605 if (docDirty && node->renderer()) 669 if (docDirty && node->renderer())
606 node->renderer()->repaint(); 670 node->renderer()->repaint();
607 } 671 }
608 672
609 bool DocumentMarkerController::hasMarkers(Range* range, DocumentMarker::MarkerTy pes markerTypes) 673 bool DocumentMarkerController::hasMarkers(Range* range, DocumentMarker::MarkerTy pes markerTypes)
610 { 674 {
611 if (!possiblyHasMarkers(markerTypes)) 675 if (!possiblyHasMarkers(markerTypes))
612 return false; 676 return false;
613 ASSERT(!m_markers.isEmpty()); 677 ASSERT(!m_markers.isEmpty());
614 678
615 Node* startContainer = range->startContainer(); 679 Node* startContainer = range->startContainer();
616 ASSERT(startContainer); 680 ASSERT(startContainer);
617 Node* endContainer = range->endContainer(); 681 Node* endContainer = range->endContainer();
618 ASSERT(endContainer); 682 ASSERT(endContainer);
619 683
620 Node* pastLastNode = range->pastLastNode(); 684 Node* pastLastNode = range->pastLastNode();
621 for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTrave rsal::next(node)) { 685 for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTrave rsal::next(node)) {
622 Vector<DocumentMarker*> markers = markersFor(node); 686 Vector<DocumentMarker*> markers = markersFor(node);
623 Vector<DocumentMarker*>::const_iterator end = markers.end(); 687 Vector<DocumentMarker*>::const_iterator end = markers.end();
624 for (Vector<DocumentMarker*>::const_iterator it = markers.begin(); it != end; ++it) { 688 for (Vector<DocumentMarker*>::const_iterator it = markers.begin(); it != end; ++it) {
625 DocumentMarker* marker = *it; 689 DocumentMarker* marker = *it;
626 if (!markerTypes.contains(marker->type())) 690 if (!markerTypes.contains(marker->type()))
627 continue; 691 continue;
628 if (node == startContainer && marker->endOffset() <= static_cast<uns igned>(range->startOffset())) 692 if (node == startContainer && marker->endOffset() <= static_cast<uns igned>(range->startOffset()))
groby-ooo-7-16 2013/09/19 18:17:09 upper/lower_bound
pstanek 2013/09/20 15:07:40 markersFor() again
629 continue; 693 continue;
630 if (node == endContainer && marker->startOffset() >= static_cast<uns igned>(range->endOffset())) 694 if (node == endContainer && marker->startOffset() >= static_cast<uns igned>(range->endOffset()))
631 continue; 695 continue;
632 return true; 696 return true;
633 } 697 }
634 } 698 }
635 return false; 699 return false;
636 } 700 }
637 701
638 #ifndef NDEBUG 702 #ifndef NDEBUG
639 void DocumentMarkerController::showMarkers() const 703 void DocumentMarkerController::showMarkers() const
640 { 704 {
641 fprintf(stderr, "%d nodes have markers:\n", m_markers.size()); 705 fprintf(stderr, "%d nodes have markers:\n", m_markers.size());
642 MarkerMap::const_iterator end = m_markers.end(); 706 MarkerMap::const_iterator end = m_markers.end();
643 for (MarkerMap::const_iterator nodeIterator = m_markers.begin(); nodeIterato r != end; ++nodeIterator) { 707 for (MarkerMap::const_iterator nodeIterator = m_markers.begin(); nodeIterato r != end; ++nodeIterator) {
644 Node* node = nodeIterator->key.get(); 708 Node* node = nodeIterator->key.get();
645 fprintf(stderr, "%p", node); 709 fprintf(stderr, "%p", node);
646 MarkerList* list = nodeIterator->value.get(); 710 MarkerLists* markers = m_markers.get(node);
647 for (unsigned markerIndex = 0; markerIndex < list->size(); ++markerIndex ) { 711 for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::Marke rTypeIndexesCount; ++markerListIndex) {
648 const DocumentMarker& marker = list->at(markerIndex); 712 OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
649 fprintf(stderr, " %d:[%d:%d](%d)", marker.type(), marker.startOffset (), marker.endOffset(), marker.activeMatch()); 713 for (unsigned markerIndex = 0; markerIndex < list->size(); ++markerI ndex) {
714 const DocumentMarker& marker = list->at(markerIndex);
715 fprintf(stderr, " %d:[%d:%d](%d)", marker.type(), marker.startOf fset(), marker.endOffset(), marker.activeMatch());
716 }
650 } 717 }
651 718
652 fprintf(stderr, "\n"); 719 fprintf(stderr, "\n");
653 } 720 }
654 } 721 }
655 #endif 722 #endif
656 723
657 } // namespace WebCore 724 } // namespace WebCore
658 725
659 #ifndef NDEBUG 726 #ifndef NDEBUG
660 void showDocumentMarkers(const WebCore::DocumentMarkerController* controller) 727 void showDocumentMarkers(const WebCore::DocumentMarkerController* controller)
661 { 728 {
662 if (controller) 729 if (controller)
663 controller->showMarkers(); 730 controller->showMarkers();
664 } 731 }
665 #endif 732 #endif
OLDNEW
« Source/core/dom/DocumentMarker.h ('K') | « Source/core/dom/DocumentMarkerController.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698