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 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed. | 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed. |
| 4 * | 4 * |
| 5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
| 6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
| 7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
| 8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
| 9 * | 9 * |
| 10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 | 23 |
| 24 #include "gen/sky/platform/RuntimeEnabledFeatures.h" | 24 #include "gen/sky/platform/RuntimeEnabledFeatures.h" |
| 25 #include "sky/engine/core/dom/Document.h" | 25 #include "sky/engine/core/dom/Document.h" |
| 26 #include "sky/engine/core/dom/Element.h" | 26 #include "sky/engine/core/dom/Element.h" |
| 27 #include "sky/engine/core/frame/LocalFrame.h" | 27 #include "sky/engine/core/frame/LocalFrame.h" |
| 28 #include "sky/engine/core/page/Page.h" | 28 #include "sky/engine/core/page/Page.h" |
| 29 #include "sky/engine/core/rendering/GraphicsContextAnnotator.h" | 29 #include "sky/engine/core/rendering/GraphicsContextAnnotator.h" |
| 30 #include "sky/engine/core/rendering/HitTestResult.h" | 30 #include "sky/engine/core/rendering/HitTestResult.h" |
| 31 #include "sky/engine/core/rendering/RenderGeometryMap.h" | 31 #include "sky/engine/core/rendering/RenderGeometryMap.h" |
| 32 #include "sky/engine/core/rendering/RenderLayer.h" | 32 #include "sky/engine/core/rendering/RenderLayer.h" |
| 33 #include "sky/engine/core/rendering/RenderSelectionInfo.h" | |
| 34 #include "sky/engine/platform/TraceEvent.h" | 33 #include "sky/engine/platform/TraceEvent.h" |
| 35 #include "sky/engine/platform/geometry/FloatQuad.h" | 34 #include "sky/engine/platform/geometry/FloatQuad.h" |
| 36 #include "sky/engine/platform/geometry/TransformState.h" | 35 #include "sky/engine/platform/geometry/TransformState.h" |
| 37 #include "sky/engine/platform/graphics/GraphicsContext.h" | 36 #include "sky/engine/platform/graphics/GraphicsContext.h" |
| 38 | 37 |
| 39 namespace blink { | 38 namespace blink { |
| 40 | 39 |
| 41 RenderView::RenderView(Document* document) | 40 RenderView::RenderView(Document* document) |
| 42 : RenderBlockFlow(document) | 41 : RenderBlockFlow(document) |
| 43 , m_frameView(document->view()) | 42 , m_frameView(document->view()) |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 296 { | 295 { |
| 297 if (!object) | 296 if (!object) |
| 298 return 0; | 297 return 0; |
| 299 | 298 |
| 300 RenderObject* child = object->childAt(offset); | 299 RenderObject* child = object->childAt(offset); |
| 301 return child ? child : object->nextInPreOrderAfterChildren(); | 300 return child ? child : object->nextInPreOrderAfterChildren(); |
| 302 } | 301 } |
| 303 | 302 |
| 304 IntRect RenderView::selectionBounds() const | 303 IntRect RenderView::selectionBounds() const |
| 305 { | 304 { |
| 306 typedef HashMap<RawPtr<RenderObject>, OwnPtr<RenderSelectionInfo> > Selectio nMap; | 305 HashSet<RenderObject*> selectedObjects; |
| 307 SelectionMap selectedObjects; | |
| 308 | 306 |
| 309 RenderObject* os = m_selectionStart; | 307 RenderObject* os = m_selectionStart; |
| 310 RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos ); | 308 RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos ); |
| 311 while (os && os != stop) { | 309 while (os && os != stop) { |
| 312 if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selec tionEnd) && os->selectionState() != SelectionNone) { | 310 if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selec tionEnd) && os->selectionState() != SelectionNone) { |
| 313 // Blocks are responsible for painting line gaps and margin gaps. Th ey must be examined as well. | 311 // Blocks are responsible for painting line gaps and margin gaps. Th ey must be examined as well. |
| 314 selectedObjects.set(os, adoptPtr(new RenderSelectionInfo(os, false)) ); | 312 selectedObjects.add(os); |
| 315 RenderBlock* cb = os->containingBlock(); | 313 RenderBlock* cb = os->containingBlock(); |
| 316 while (cb && !cb->isRenderView()) { | 314 while (cb && !cb->isRenderView()) { |
| 317 OwnPtr<RenderSelectionInfo>& blockInfo = selectedObjects.add(cb, nullptr).storedValue->value; | 315 if (!selectedObjects.add(cb).isNewEntry) |
| 318 if (blockInfo) | |
| 319 break; | 316 break; |
| 320 blockInfo = adoptPtr(new RenderSelectionInfo(cb, false)); | |
| 321 cb = cb->containingBlock(); | 317 cb = cb->containingBlock(); |
| 322 } | 318 } |
| 323 } | 319 } |
| 324 | 320 |
| 325 os = os->nextInPreOrder(); | 321 os = os->nextInPreOrder(); |
| 326 } | 322 } |
| 327 | 323 |
| 328 // Now create a single bounding box rect that encloses the whole selection. | 324 // Now create a single bounding box rect that encloses the whole selection. |
| 329 LayoutRect selRect; | 325 LayoutRect selRect; |
| 330 SelectionMap::iterator end = selectedObjects.end(); | 326 |
| 331 for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) { | 327 for (auto& renderer : selectedObjects) { |
| 332 RenderSelectionInfo* info = i->value.get(); | 328 const RenderLayerModelObject* paintInvalidationContainer = renderer->con tainerForPaintInvalidation(); |
| 333 // RenderSelectionInfo::rect() is in the coordinates of the paintInvalid ationContainer, so map to page coordinates. | 329 ASSERT(paintInvalidationContainer); |
|
ojan
2015/01/13 00:40:47
paintInvalidationContainer is only null if the ren
esprehn
2015/01/13 00:54:48
Yeah that should never happen.
| |
| 334 LayoutRect currRect = info->rect(); | 330 // selectionRectForPaintInvalidation is in the coordinates of the paintI nvalidationContainer, so map to page coordinates. |
| 335 if (const RenderLayerModelObject* paintInvalidationContainer = info->pai ntInvalidationContainer()) { | 331 bool clipToVisibleContent = false; |
| 336 FloatQuad absQuad = paintInvalidationContainer->localToAbsoluteQuad( FloatRect(currRect)); | 332 LayoutRect rect = renderer->selectionRectForPaintInvalidation(paintInval idationContainer, clipToVisibleContent); |
| 337 currRect = absQuad.enclosingBoundingBox(); | 333 FloatQuad absQuad = paintInvalidationContainer->localToAbsoluteQuad(Floa tRect(rect)); |
| 338 } | 334 selRect.unite(absQuad.enclosingBoundingBox()); |
| 339 selRect.unite(currRect); | |
| 340 } | 335 } |
| 341 return pixelSnappedIntRect(selRect); | 336 return pixelSnappedIntRect(selRect); |
| 342 } | 337 } |
| 343 | 338 |
| 344 // When exploring the RenderTree looking for the nodes involved in the Selection , sometimes it's | 339 // When exploring the RenderTree looking for the nodes involved in the Selection , sometimes it's |
| 345 // required to change the traversing direction because the "start" position is b elow the "end" one. | 340 // required to change the traversing direction because the "start" position is b elow the "end" one. |
| 346 static inline RenderObject* getNextOrPrevRenderObjectBasedOnDirection(const Rend erObject* o, const RenderObject* stop, bool& continueExploring, bool& exploringB ackwards) | 341 static inline RenderObject* getNextOrPrevRenderObjectBasedOnDirection(const Rend erObject* o, const RenderObject* stop, bool& continueExploring, bool& exploringB ackwards) |
| 347 { | 342 { |
| 348 RenderObject* next; | 343 RenderObject* next; |
| 349 if (exploringBackwards) { | 344 if (exploringBackwards) { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 372 // Make sure both our start and end objects are defined. | 367 // Make sure both our start and end objects are defined. |
| 373 // Check www.msnbc.com and try clicking around to find the case where this h appened. | 368 // Check www.msnbc.com and try clicking around to find the case where this h appened. |
| 374 if ((start && !end) || (end && !start)) | 369 if ((start && !end) || (end && !start)) |
| 375 return; | 370 return; |
| 376 | 371 |
| 377 // Just return if the selection hasn't changed. | 372 // Just return if the selection hasn't changed. |
| 378 if (m_selectionStart == start && m_selectionStartPos == startPos && | 373 if (m_selectionStart == start && m_selectionStartPos == startPos && |
| 379 m_selectionEnd == end && m_selectionEndPos == endPos) | 374 m_selectionEnd == end && m_selectionEndPos == endPos) |
| 380 return; | 375 return; |
| 381 | 376 |
| 382 // Record the old selected objects. These will be used later | |
| 383 // when we compare against the new selected objects. | |
| 384 int oldStartPos = m_selectionStartPos; | |
| 385 int oldEndPos = m_selectionEndPos; | |
| 386 | |
| 387 // Objects each have a single selection rect to examine. | |
| 388 typedef HashMap<RawPtr<RenderObject>, OwnPtr<RenderSelectionInfo> > Selected ObjectMap; | |
| 389 SelectedObjectMap oldSelectedObjects; | |
| 390 SelectedObjectMap newSelectedObjects; | |
| 391 | |
| 392 // Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks. | |
| 393 // In order to get the paint invalidation rect right, we have to examine lef t, middle, and right rects individually, since otherwise | |
| 394 // the union of those rects might remain the same even when changes have occ urred. | |
| 395 typedef HashMap<RawPtr<RenderBlock>, OwnPtr<RenderBlockSelectionInfo> > Sele ctedBlockMap; | |
| 396 SelectedBlockMap oldSelectedBlocks; | |
| 397 SelectedBlockMap newSelectedBlocks; | |
| 398 | |
| 399 RenderObject* os = m_selectionStart; | 377 RenderObject* os = m_selectionStart; |
| 400 RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos ); | 378 RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos ); |
| 401 bool exploringBackwards = false; | 379 bool exploringBackwards = false; |
| 402 bool continueExploring = os && (os != stop); | 380 bool continueExploring = os && (os != stop); |
| 403 while (continueExploring) { | 381 while (continueExploring) { |
| 404 if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selec tionEnd) && os->selectionState() != SelectionNone) { | 382 if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selec tionEnd) && os->selectionState() != SelectionNone) { |
| 405 // Blocks are responsible for painting line gaps and margin gaps. T hey must be examined as well. | 383 os->setSelectionStateIfNeeded(SelectionNone); |
|
ojan
2015/01/13 00:40:47
This is from line 425 below. Not sure why the old
| |
| 406 oldSelectedObjects.set(os, adoptPtr(new RenderSelectionInfo(os, true ))); | |
| 407 if (blockPaintInvalidationMode == PaintInvalidationNewXOROld) { | |
| 408 RenderBlock* cb = os->containingBlock(); | |
| 409 while (cb && !cb->isRenderView()) { | |
| 410 OwnPtr<RenderBlockSelectionInfo>& blockInfo = oldSelectedBlo cks.add(cb, nullptr).storedValue->value; | |
| 411 if (blockInfo) | |
| 412 break; | |
| 413 blockInfo = adoptPtr(new RenderBlockSelectionInfo(cb)); | |
| 414 cb = cb->containingBlock(); | |
| 415 } | |
| 416 } | |
| 417 } | 384 } |
| 418 | 385 |
| 419 os = getNextOrPrevRenderObjectBasedOnDirection(os, stop, continueExplori ng, exploringBackwards); | 386 os = getNextOrPrevRenderObjectBasedOnDirection(os, stop, continueExplori ng, exploringBackwards); |
| 420 } | 387 } |
| 421 | 388 |
| 422 // Now clear the selection. | |
| 423 SelectedObjectMap::iterator oldObjectsEnd = oldSelectedObjects.end(); | |
| 424 for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObj ectsEnd; ++i) | |
| 425 i->key->setSelectionStateIfNeeded(SelectionNone); | |
| 426 | |
| 427 // set selection start and end | 389 // set selection start and end |
| 428 m_selectionStart = start; | 390 m_selectionStart = start; |
| 429 m_selectionStartPos = startPos; | 391 m_selectionStartPos = startPos; |
| 430 m_selectionEnd = end; | 392 m_selectionEnd = end; |
| 431 m_selectionEndPos = endPos; | 393 m_selectionEndPos = endPos; |
| 432 | 394 |
| 433 // Update the selection status of all objects between m_selectionStart and m _selectionEnd | 395 // Update the selection status of all objects between m_selectionStart and m _selectionEnd |
| 434 if (start && start == end) | 396 if (start && start == end) { |
| 435 start->setSelectionStateIfNeeded(SelectionBoth); | 397 start->setSelectionStateIfNeeded(SelectionBoth); |
| 436 else { | 398 } else { |
| 437 if (start) | 399 if (start) |
| 438 start->setSelectionStateIfNeeded(SelectionStart); | 400 start->setSelectionStateIfNeeded(SelectionStart); |
| 439 if (end) | 401 if (end) |
| 440 end->setSelectionStateIfNeeded(SelectionEnd); | 402 end->setSelectionStateIfNeeded(SelectionEnd); |
| 441 } | 403 } |
| 442 | 404 |
| 443 RenderObject* o = start; | 405 RenderObject* o = start; |
| 444 stop = rendererAfterPosition(end, endPos); | 406 stop = rendererAfterPosition(end, endPos); |
| 445 | 407 |
| 446 while (o && o != stop) { | 408 while (o && o != stop) { |
| 447 if (o != start && o != end && o->canBeSelectionLeaf()) | 409 if (o != start && o != end && o->canBeSelectionLeaf()) |
| 448 o->setSelectionStateIfNeeded(SelectionInside); | 410 o->setSelectionStateIfNeeded(SelectionInside); |
| 449 o = o->nextInPreOrder(); | 411 o = o->nextInPreOrder(); |
| 450 } | 412 } |
| 451 | |
| 452 if (blockPaintInvalidationMode != PaintInvalidationNothing) | |
| 453 layer()->clearBlockSelectionGapsBounds(); | |
| 454 | |
| 455 // Now that the selection state has been updated for the new objects, walk t hem again and | |
| 456 // put them in the new objects list. | |
| 457 o = start; | |
| 458 exploringBackwards = false; | |
| 459 continueExploring = o && (o != stop); | |
| 460 while (continueExploring) { | |
| 461 if ((o->canBeSelectionLeaf() || o == start || o == end) && o->selectionS tate() != SelectionNone) { | |
| 462 newSelectedObjects.set(o, adoptPtr(new RenderSelectionInfo(o, true)) ); | |
| 463 RenderBlock* cb = o->containingBlock(); | |
| 464 while (cb && !cb->isRenderView()) { | |
| 465 OwnPtr<RenderBlockSelectionInfo>& blockInfo = newSelectedBlocks. add(cb, nullptr).storedValue->value; | |
| 466 if (blockInfo) | |
| 467 break; | |
| 468 blockInfo = adoptPtr(new RenderBlockSelectionInfo(cb)); | |
| 469 cb = cb->containingBlock(); | |
| 470 } | |
| 471 } | |
| 472 | |
| 473 o = getNextOrPrevRenderObjectBasedOnDirection(o, stop, continueExploring , exploringBackwards); | |
| 474 } | |
| 475 | |
| 476 if (!m_frameView || blockPaintInvalidationMode == PaintInvalidationNothing) | |
| 477 return; | |
| 478 | |
| 479 // Have any of the old selected objects changed compared to the new selectio n? | |
| 480 for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObj ectsEnd; ++i) { | |
| 481 RenderObject* obj = i->key; | |
| 482 RenderSelectionInfo* newInfo = newSelectedObjects.get(obj); | |
| 483 RenderSelectionInfo* oldInfo = i->value.get(); | |
| 484 if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() ! = newInfo->state() || | |
| 485 (m_selectionStart == obj && oldStartPos != m_selectionStartPos) || | |
| 486 (m_selectionEnd == obj && oldEndPos != m_selectionEndPos)) { | |
| 487 oldInfo->invalidatePaint(); | |
| 488 if (newInfo) { | |
| 489 newInfo->invalidatePaint(); | |
| 490 newSelectedObjects.remove(obj); | |
| 491 } | |
| 492 } | |
| 493 } | |
| 494 | |
| 495 // Any new objects that remain were not found in the old objects dict, and s o they need to be updated. | |
| 496 SelectedObjectMap::iterator newObjectsEnd = newSelectedObjects.end(); | |
| 497 for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); i != newObj ectsEnd; ++i) | |
| 498 i->value->invalidatePaint(); | |
| 499 | |
| 500 // Have any of the old blocks changed? | |
| 501 SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end(); | |
| 502 for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); i != oldBlock sEnd; ++i) { | |
| 503 RenderBlock* block = i->key; | |
| 504 RenderBlockSelectionInfo* newInfo = newSelectedBlocks.get(block); | |
| 505 RenderBlockSelectionInfo* oldInfo = i->value.get(); | |
| 506 if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) { | |
| 507 oldInfo->invalidatePaint(); | |
| 508 if (newInfo) { | |
| 509 newInfo->invalidatePaint(); | |
| 510 newSelectedBlocks.remove(block); | |
| 511 } | |
| 512 } | |
| 513 } | |
| 514 | |
| 515 // Any new blocks that remain were not found in the old blocks dict, and so they need to be updated. | |
| 516 SelectedBlockMap::iterator newBlocksEnd = newSelectedBlocks.end(); | |
| 517 for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); i != newBlock sEnd; ++i) | |
| 518 i->value->invalidatePaint(); | |
| 519 } | 413 } |
| 520 | 414 |
| 521 void RenderView::getSelection(RenderObject*& startRenderer, int& startOffset, Re nderObject*& endRenderer, int& endOffset) const | 415 void RenderView::getSelection(RenderObject*& startRenderer, int& startOffset, Re nderObject*& endRenderer, int& endOffset) const |
| 522 { | 416 { |
| 523 startRenderer = m_selectionStart; | 417 startRenderer = m_selectionStart; |
| 524 startOffset = m_selectionStartPos; | 418 startOffset = m_selectionStartPos; |
| 525 endRenderer = m_selectionEnd; | 419 endRenderer = m_selectionEnd; |
| 526 endOffset = m_selectionEndPos; | 420 endOffset = m_selectionEndPos; |
| 527 } | 421 } |
| 528 | 422 |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 656 m_iframes.remove(iframe); | 550 m_iframes.remove(iframe); |
| 657 } | 551 } |
| 658 | 552 |
| 659 void RenderView::updateIFramesAfterLayout() | 553 void RenderView::updateIFramesAfterLayout() |
| 660 { | 554 { |
| 661 for (auto& iframe: m_iframes) | 555 for (auto& iframe: m_iframes) |
| 662 iframe->updateWidgetBounds(); | 556 iframe->updateWidgetBounds(); |
| 663 } | 557 } |
| 664 | 558 |
| 665 } // namespace blink | 559 } // namespace blink |
| OLD | NEW |