Chromium Code Reviews| Index: third_party/WebKit/Source/core/paint/BlockPaintInvalidator.cpp | 
| diff --git a/third_party/WebKit/Source/core/paint/BlockPaintInvalidator.cpp b/third_party/WebKit/Source/core/paint/BlockPaintInvalidator.cpp | 
| index b64c32efdcfffe4881adadce03d35816fc869609..1bc884200182714b91a2b864127a07e141b638a4 100644 | 
| --- a/third_party/WebKit/Source/core/paint/BlockPaintInvalidator.cpp | 
| +++ b/third_party/WebKit/Source/core/paint/BlockPaintInvalidator.cpp | 
| @@ -4,23 +4,146 @@ | 
| #include "core/paint/BlockPaintInvalidator.h" | 
| +#include "core/editing/DragCaret.h" | 
| #include "core/editing/FrameSelection.h" | 
| #include "core/frame/LocalFrame.h" | 
| #include "core/layout/LayoutBlock.h" | 
| +#include "core/page/Page.h" | 
| #include "core/paint/BoxPaintInvalidator.h" | 
| +#include "core/paint/ObjectPaintInvalidator.h" | 
| #include "core/paint/PaintInvalidator.h" | 
| +#include "core/paint/PaintLayer.h" | 
| namespace blink { | 
| +struct CaretVisualRects { | 
| + bool hasCursorCaret = false; | 
| 
 
yosin_UTC9
2017/01/31 20:12:58
It is better to move |bool| member to end of membe
 
 | 
| + LayoutRect cursorCaretRect; | 
| + bool hasDragCaret = false; | 
| + LayoutRect dragCaretRect; | 
| +}; | 
| + | 
| +typedef HashMap<const LayoutBlock*, CaretVisualRects> CaretVisualRectsMap; | 
| 
 
yosin_UTC9
2017/01/31 20:12:58
nit: Let's use using to C++-ish.
using  CaretVisu
 
 | 
| +static CaretVisualRectsMap& caretVisualRectsMap() { | 
| + DEFINE_STATIC_LOCAL(CaretVisualRectsMap, map, ()); | 
| 
 
chrishtr
2017/01/31 22:51:04
Why can't you store these on the block instead of
 
 | 
| + return map; | 
| +} | 
| + | 
| +static void setPreviousCaretVisualRects(const LayoutBlock& block, | 
| + const CaretVisualRects& rects) { | 
| + DCHECK(block.hasPreviousCaretVisualRects() == | 
| 
 
yosin_UTC9
2017/01/31 20:12:58
nit: DCHECK_EQ
 
 | 
| + caretVisualRectsMap().contains(&block)); | 
| + if (rects.cursorCaretRect.isEmpty() && rects.dragCaretRect.isEmpty()) { | 
| + BlockPaintInvalidator::clearPreviousCaretVisualRects(block); | 
| 
 
yosin_UTC9
2017/01/31 20:12:58
nit: early return style to decrease indentation of
 
 | 
| + } else { | 
| + caretVisualRectsMap().set(&block, rects); | 
| + block.getMutableForPainting().setHasPreviousCaretVisualRects(true); | 
| + } | 
| +} | 
| + | 
| +void BlockPaintInvalidator::blockWillBeDestroyed(const LayoutBlock& block) { | 
| + DCHECK(block.hasPreviousCaretVisualRects() == | 
| 
 
yosin_UTC9
2017/01/31 20:12:58
nit: DCHECK_EQ
 
 | 
| + caretVisualRectsMap().contains(&block)); | 
| + if (block.hasPreviousCaretVisualRects()) | 
| + caretVisualRectsMap().remove(&block); | 
| +} | 
| + | 
| +void BlockPaintInvalidator::setMayNeedPaintInvalidationForCaretsIfNeeded( | 
| + const LocalFrame& localFrameRoot) { | 
| + DCHECK(&localFrameRoot == localFrameRoot.localFrameRoot()); | 
| 
 
yosin_UTC9
2017/01/31 20:12:58
nit: DCHECK_EQ
 
 | 
| + for (auto& item : caretVisualRectsMap()) { | 
| 
 
yosin_UTC9
2017/01/31 20:12:58
nit: s/auto&/const auto&/
We don't never change en
 
 | 
| + const LayoutBlock* block = item.key; | 
| + const CaretVisualRects& rects = item.value; | 
| + DCHECK(block->hasPreviousCaretVisualRects()); | 
| + if (block->frame()->localFrameRoot() != &localFrameRoot) | 
| + continue; | 
| + if (rects.hasCursorCaret != block->hasCursorCaret() || | 
| + rects.hasDragCaret != block->hasDragCaret()) | 
| + block->getMutableForPainting().setMayNeedPaintInvalidation(); | 
| + } | 
| +} | 
| + | 
| +void BlockPaintInvalidator::clearPreviousCaretVisualRects( | 
| + const LayoutBlock& block) { | 
| + if (block.hasPreviousCaretVisualRects()) { | 
| 
 
yosin_UTC9
2017/01/31 20:12:58
nit: early-return style to decrease indentation.
 
 | 
| + caretVisualRectsMap().remove(&block); | 
| + block.getMutableForPainting().setHasPreviousCaretVisualRects(false); | 
| + } | 
| +} | 
| + | 
| +LayoutRect BlockPaintInvalidator::invalidateCaretIfNeeded( | 
| + PaintInvalidationReason reason, | 
| + const LayoutRect& oldVisualRect, | 
| + const LayoutRect& newLocalRect, | 
| + const DisplayItemClient& displayItemClient) { | 
| + LayoutRect newVisualRect = newLocalRect; | 
| + if (!newVisualRect.isEmpty()) { | 
| + // Over-paint 1 pixel to workaround wkbug.com/108283. | 
| + // TODO(wangxianzhu): This might be unnecessary now. | 
| + newVisualRect.inflate(1); | 
| 
 
yosin_UTC9
2017/01/31 20:12:58
Agree. Let's getting rid of this patch to see whic
 
 | 
| + | 
| + m_context.mapLocalRectToPaintInvalidationBacking(m_block, newVisualRect); | 
| + newVisualRect.move(m_block.scrollAdjustmentForPaintInvalidation( | 
| + *m_context.paintInvalidationContainer)); | 
| + } | 
| + | 
| + if (m_block.caretsNeedPaintInvalidation() || newVisualRect != oldVisualRect) { | 
| + ObjectPaintInvalidatorWithContext objectInvalidator(m_block, m_context); | 
| + if (!isImmediateFullPaintInvalidationReason(reason)) { | 
| + objectInvalidator.fullyInvalidatePaint(PaintInvalidationCaret, | 
| + oldVisualRect, newVisualRect); | 
| + } | 
| + | 
| + m_context.paintingLayer->setNeedsRepaint(); | 
| + objectInvalidator.invalidateDisplayItemClient(displayItemClient, | 
| + PaintInvalidationCaret); | 
| + } | 
| + | 
| + return newVisualRect; | 
| +} | 
| + | 
| +void BlockPaintInvalidator::invalidateCaretsIfNeeded( | 
| + PaintInvalidationReason reason) { | 
| + bool hadCarets = m_block.hasPreviousCaretVisualRects(); | 
| + DCHECK(hadCarets == caretVisualRectsMap().contains(&m_block)); | 
| 
 
yosin_UTC9
2017/01/31 20:12:58
nit: DCHECK_EQ
 
 | 
| + | 
| + bool hasCursorCaret = m_block.hasCursorCaret(); | 
| 
 
yosin_UTC9
2017/01/31 20:12:58
nit: s/bool/const bool/
 
 | 
| + bool hasDragCaret = m_block.hasDragCaret(); | 
| 
 
yosin_UTC9
2017/01/31 20:12:58
nit: s/bool/const bool/
 
 | 
| + if (!hadCarets && !hasCursorCaret && !hasDragCaret) | 
| + return; | 
| + | 
| + CaretVisualRects oldCaretVisualRects; | 
| + CaretVisualRects newCaretVisualRects; | 
| + if (hadCarets) | 
| + oldCaretVisualRects = caretVisualRectsMap().get(&m_block); | 
| + | 
| + FrameSelection& selection = m_block.frame()->selection(); | 
| + newCaretVisualRects.hasCursorCaret = hasCursorCaret; | 
| + newCaretVisualRects.cursorCaretRect = invalidateCaretIfNeeded( | 
| + reason, oldCaretVisualRects.cursorCaretRect, | 
| + hasCursorCaret ? selection.caretLocalRect() : LayoutRect(), | 
| + selection.getCaretDisplayItemClient()); | 
| + if (hasCursorCaret) | 
| + selection.setCaretVisualRect(newCaretVisualRects.cursorCaretRect); | 
| + | 
| + DragCaret& dragCaret = m_block.frame()->page()->dragCaret(); | 
| + newCaretVisualRects.hasDragCaret = hasDragCaret; | 
| + newCaretVisualRects.dragCaretRect = invalidateCaretIfNeeded( | 
| + reason, oldCaretVisualRects.dragCaretRect, | 
| + hasDragCaret ? dragCaret.caretLocalRect() : LayoutRect(), | 
| + dragCaret.getDisplayItemClient()); | 
| + if (hasDragCaret) | 
| + dragCaret.setVisualRect(newCaretVisualRects.dragCaretRect); | 
| + | 
| + setPreviousCaretVisualRects(m_block, newCaretVisualRects); | 
| +} | 
| + | 
| PaintInvalidationReason BlockPaintInvalidator::invalidatePaintIfNeeded() { | 
| PaintInvalidationReason reason = | 
| BoxPaintInvalidator(m_block, m_context).invalidatePaintIfNeeded(); | 
| - if (reason != PaintInvalidationNone && m_block.hasCaret()) { | 
| - FrameSelection& selection = m_block.frame()->selection(); | 
| - selection.setCaretRectNeedsUpdate(); | 
| - selection.invalidateCaretRect(true); | 
| - } | 
| + invalidateCaretsIfNeeded(reason); | 
| + | 
| return reason; | 
| } | 
| } |