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; |
} |
} |