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