Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
| 5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) | 5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
| 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights 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 Loading... | |
| 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 Loading... | |
| 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 ▮ | 382 return ▮ |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |