Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(198)

Side by Side Diff: third_party/WebKit/Source/core/editing/CaretDisplayItemClient.cpp

Issue 2665823002: Invalidate caret during paint invalidation (Closed)
Patch Set: - Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved. 2 * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 16 matching lines...) Expand all
27 27
28 #include "core/editing/EditingUtilities.h" 28 #include "core/editing/EditingUtilities.h"
29 #include "core/editing/VisibleUnits.h" 29 #include "core/editing/VisibleUnits.h"
30 #include "core/frame/FrameView.h" 30 #include "core/frame/FrameView.h"
31 #include "core/frame/Settings.h" 31 #include "core/frame/Settings.h"
32 #include "core/layout/LayoutBlock.h" 32 #include "core/layout/LayoutBlock.h"
33 #include "core/layout/LayoutView.h" 33 #include "core/layout/LayoutView.h"
34 #include "core/layout/api/LayoutBlockItem.h" 34 #include "core/layout/api/LayoutBlockItem.h"
35 #include "core/layout/api/LayoutItem.h" 35 #include "core/layout/api/LayoutItem.h"
36 #include "core/layout/api/LayoutViewItem.h" 36 #include "core/layout/api/LayoutViewItem.h"
37 #include "core/paint/ObjectPaintInvalidator.h"
37 #include "core/paint/PaintInfo.h" 38 #include "core/paint/PaintInfo.h"
39 #include "core/paint/PaintInvalidator.h"
38 #include "core/paint/PaintLayer.h" 40 #include "core/paint/PaintLayer.h"
39 #include "platform/graphics/GraphicsContext.h" 41 #include "platform/graphics/GraphicsContext.h"
40 #include "platform/graphics/GraphicsLayer.h"
41 #include "platform/graphics/paint/DrawingRecorder.h" 42 #include "platform/graphics/paint/DrawingRecorder.h"
42 43
43 namespace blink { 44 namespace blink {
44 45
45 CaretDisplayItemClient::CaretDisplayItemClient() = default; 46 CaretDisplayItemClient::CaretDisplayItemClient() = default;
46 CaretDisplayItemClient::~CaretDisplayItemClient() = default; 47 CaretDisplayItemClient::~CaretDisplayItemClient() = default;
47 48
48 static inline bool caretRendersInsideNode(Node* node) { 49 static inline bool caretRendersInsideNode(const Node* node) {
49 return node && !isDisplayInsideTable(node) && !editingIgnoresContent(*node); 50 return node && !isDisplayInsideTable(node) && !editingIgnoresContent(*node);
50 } 51 }
51 52
52 LayoutBlock* CaretDisplayItemClient::caretLayoutObject(Node* node) { 53 LayoutBlock* CaretDisplayItemClient::caretLayoutBlock(const Node* node) {
53 if (!node) 54 if (!node)
54 return nullptr; 55 return nullptr;
55 56
56 LayoutObject* layoutObject = node->layoutObject(); 57 LayoutObject* layoutObject = node->layoutObject();
57 if (!layoutObject) 58 if (!layoutObject)
58 return nullptr; 59 return nullptr;
59 60
60 // if caretNode is a block and caret is inside it then caret should be painted 61 // if caretNode is a block and caret is inside it then caret should be painted
61 // by that block 62 // by that block
62 bool paintedByBlock = 63 bool paintedByBlock =
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 DCHECK(caretPosition.anchorNode()->layoutObject()); 101 DCHECK(caretPosition.anchorNode()->layoutObject());
101 102
102 // First compute a rect local to the layoutObject at the selection start. 103 // First compute a rect local to the layoutObject at the selection start.
103 LayoutObject* layoutObject; 104 LayoutObject* layoutObject;
104 const LayoutRect& caretLocalRect = 105 const LayoutRect& caretLocalRect =
105 localCaretRectOfPosition(caretPosition, layoutObject); 106 localCaretRectOfPosition(caretPosition, layoutObject);
106 107
107 // Get the layoutObject that will be responsible for painting the caret 108 // Get the layoutObject that will be responsible for painting the caret
108 // (which is either the layoutObject we just found, or one of its containers). 109 // (which is either the layoutObject we just found, or one of its containers).
109 LayoutBlockItem caretPainterItem = 110 LayoutBlockItem caretPainterItem =
110 LayoutBlockItem(caretLayoutObject(caretPosition.anchorNode())); 111 LayoutBlockItem(caretLayoutBlock(caretPosition.anchorNode()));
111 112
112 return mapCaretRectToCaretPainter(LayoutItem(layoutObject), caretPainterItem, 113 return mapCaretRectToCaretPainter(LayoutItem(layoutObject), caretPainterItem,
113 caretLocalRect); 114 caretLocalRect);
114 } 115 }
115 116
116 // TODO(yoichio): |node| is FrameSelection::m_previousCaretNode and this is bad 117 void CaretDisplayItemClient::updateForPaintInvalidation(
117 // design. We should use only previous layoutObject or Rectangle to invalidate 118 const PositionWithAffinity& caretPosition) {
118 // old caret. 119 LayoutBlock* newLayoutBlock = caretLayoutBlock(caretPosition.anchorNode());
119 void CaretDisplayItemClient::invalidateLocalCaretRect(Node* node, 120 if (newLayoutBlock != m_layoutBlock) {
120 const LayoutRect& rect) { 121 if (m_layoutBlock)
121 LayoutBlock* caretLayoutBlock = caretLayoutObject(node); 122 m_layoutBlock->setMayNeedPaintInvalidation();
122 if (!caretLayoutBlock) 123 m_previousLayoutBlock = m_layoutBlock;
124 m_layoutBlock = newLayoutBlock;
125 setNeedsPaintInvalidation();
126 } else {
127 m_previousLayoutBlock = nullptr;
128 }
129
130 Color newColor;
131 if (caretPosition.anchorNode()) {
132 newColor = caretPosition.anchorNode()->layoutObject()->resolveColor(
133 CSSPropertyCaretColor);
134 }
135 if (newColor != m_color) {
136 setNeedsPaintInvalidation();
137 m_color = newColor;
138 }
139
140 if (m_needsPaintInvalidation && m_layoutBlock)
141 m_layoutBlock->setMayNeedPaintInvalidation();
142 m_localRect = computeCaretRect(caretPosition);
143 }
144
145 void CaretDisplayItemClient::invalidatePaintIfNeeded(
146 const LayoutBlock& block,
147 const PaintInvalidatorContext& context,
148 PaintInvalidationReason layoutBlockPaintInvalidationReason) {
149 if (block == m_previousLayoutBlock) {
150 // Invalidate the previous caret if it was in a different block.
151 // m_previousLayoutBlock is set only when it's different from m_layoutBlock.
152 DCHECK(block != m_layoutBlock);
153
154 ObjectPaintInvalidatorWithContext objectInvalidator(*m_previousLayoutBlock,
155 context);
156 if (!isImmediateFullPaintInvalidationReason(
157 layoutBlockPaintInvalidationReason)) {
158 objectInvalidator.fullyInvalidatePaint(PaintInvalidationCaret,
159 m_visualRect, LayoutRect());
160 }
161
162 // If m_layoutBlock is not null, the following will be done when
163 // the new caret is invalidated in m_layoutBlock.
164 if (!m_layoutBlock) {
165 context.paintingLayer->setNeedsRepaint();
166 objectInvalidator.invalidateDisplayItemClient(*this,
167 PaintInvalidationCaret);
168 m_visualRect = LayoutRect();
169 m_needsPaintInvalidation = false;
170 }
171
172 m_previousLayoutBlock = nullptr;
173 return;
174 }
175
176 if (block != m_layoutBlock)
123 return; 177 return;
124 178
125 // FIXME: Need to over-paint 1 pixel to workaround some rounding problems. 179 // Invalidate the new caret, and the old caret if it was in the same block.
126 // https://bugs.webkit.org/show_bug.cgi?id=108283 180 LayoutRect newVisualRect;
127 LayoutRect inflatedRect = rect; 181 if (m_layoutBlock && !m_localRect.isEmpty()) {
128 inflatedRect.inflate(LayoutUnit(1)); 182 newVisualRect = m_localRect;
183 context.mapLocalRectToPaintInvalidationBacking(*m_layoutBlock,
184 newVisualRect);
185 newVisualRect.move(m_layoutBlock->scrollAdjustmentForPaintInvalidation(
186 *context.paintInvalidationContainer));
129 187
130 // FIXME: We should not allow paint invalidation out of paint invalidation 188 if (m_layoutBlock->usesCompositedScrolling()) {
131 // state. crbug.com/457415 189 // The caret should use scrolling coordinate space.
132 DisablePaintInvalidationStateAsserts disabler; 190 DCHECK(m_layoutBlock == context.paintInvalidationContainer);
191 newVisualRect.move(LayoutSize(m_layoutBlock->scrolledContentOffset()));
192 }
193 }
133 194
134 m_visualRect = 195 if (m_needsPaintInvalidation || newVisualRect != m_visualRect) {
135 node->layoutObject()->invalidatePaintRectangle(inflatedRect, this); 196 m_needsPaintInvalidation = false;
197
198 ObjectPaintInvalidatorWithContext objectInvalidator(*m_layoutBlock,
199 context);
200 if (!isImmediateFullPaintInvalidationReason(
201 layoutBlockPaintInvalidationReason)) {
202 objectInvalidator.fullyInvalidatePaint(PaintInvalidationCaret,
203 m_visualRect, newVisualRect);
204 }
205
206 context.paintingLayer->setNeedsRepaint();
207 objectInvalidator.invalidateDisplayItemClient(*this,
208 PaintInvalidationCaret);
209 }
210
211 m_visualRect = newVisualRect;
136 } 212 }
137 213
138 void CaretDisplayItemClient::paintCaret(Node* node, 214 void CaretDisplayItemClient::paintCaret(
139 GraphicsContext& context, 215 GraphicsContext& context,
140 const LayoutRect& caretLocalRect, 216 const LayoutPoint& paintOffset,
141 const LayoutPoint& paintOffset, 217 DisplayItem::Type displayItemType) const {
142 DisplayItem::Type displayItemType) {
143 if (DrawingRecorder::useCachedDrawingIfPossible(context, *this, 218 if (DrawingRecorder::useCachedDrawingIfPossible(context, *this,
144 displayItemType)) 219 displayItemType))
145 return; 220 return;
146 221
147 LayoutRect drawingRect = caretLocalRect; 222 LayoutRect drawingRect = m_localRect;
148 if (LayoutBlock* layoutObject = caretLayoutObject(node)) 223 m_layoutBlock->flipForWritingMode(drawingRect);
149 layoutObject->flipForWritingMode(drawingRect);
150 drawingRect.moveBy(paintOffset); 224 drawingRect.moveBy(paintOffset);
151 225
152 const Color caretColor =
153 node->layoutObject()->resolveColor(CSSPropertyCaretColor);
154 IntRect paintRect = pixelSnappedIntRect(drawingRect); 226 IntRect paintRect = pixelSnappedIntRect(drawingRect);
155 DrawingRecorder drawingRecorder(context, *this, DisplayItem::kCaret, 227 DrawingRecorder drawingRecorder(context, *this, DisplayItem::kCaret,
156 paintRect); 228 paintRect);
157 context.fillRect(paintRect, caretColor); 229 context.fillRect(paintRect, m_color);
158 } 230 }
159 231
160 String CaretDisplayItemClient::debugName() const { 232 String CaretDisplayItemClient::debugName() const {
161 return "Caret"; 233 return "Caret";
162 } 234 }
163 235
164 LayoutRect CaretDisplayItemClient::visualRect() const { 236 LayoutRect CaretDisplayItemClient::visualRect() const {
165 return m_visualRect; 237 return m_visualRect;
166 } 238 }
167 239
168 } // namespace blink 240 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698