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

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

Issue 2665823002: Invalidate caret during paint invalidation (Closed)
Patch Set: NeedsRebaseline 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::updateStyleAndLayoutIfNeeded(
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 m_needsPaintInvalidation = true;
126 } else {
127 m_previousLayoutBlock = nullptr;
128 }
129
130 if (!newLayoutBlock) {
131 m_color = Color();
132 m_localRect = LayoutRect();
133 return;
134 }
135
136 Color newColor;
137 if (caretPosition.anchorNode()) {
138 newColor = caretPosition.anchorNode()->layoutObject()->resolveColor(
139 CSSPropertyCaretColor);
140 }
141 if (newColor != m_color) {
142 m_needsPaintInvalidation = true;
143 m_color = newColor;
144 }
145
146 LayoutRect newLocalRect = computeCaretRect(caretPosition);
147 if (newLocalRect != m_localRect) {
148 m_needsPaintInvalidation = true;
149 m_localRect = newLocalRect;
150 }
151
152 if (m_needsPaintInvalidation)
153 newLayoutBlock->setMayNeedPaintInvalidation();
154 }
155
156 void CaretDisplayItemClient::invalidatePaintIfNeeded(
157 const LayoutBlock& block,
158 const PaintInvalidatorContext& context,
159 PaintInvalidationReason layoutBlockPaintInvalidationReason) {
160 if (block == m_previousLayoutBlock) {
161 // Invalidate the previous caret if it was in a different block.
162 // m_previousLayoutBlock is set only when it's different from m_layoutBlock.
163 DCHECK(block != m_layoutBlock);
164
165 ObjectPaintInvalidatorWithContext objectInvalidator(*m_previousLayoutBlock,
166 context);
167 if (!isImmediateFullPaintInvalidationReason(
168 layoutBlockPaintInvalidationReason)) {
169 objectInvalidator.fullyInvalidatePaint(PaintInvalidationCaret,
170 m_visualRect, LayoutRect());
171 }
172
173 // If m_layoutBlock is not null, the following will be done when
174 // the new caret is invalidated in m_layoutBlock.
175 if (!m_layoutBlock) {
176 context.paintingLayer->setNeedsRepaint();
177 objectInvalidator.invalidateDisplayItemClient(*this,
178 PaintInvalidationCaret);
179 m_visualRect = LayoutRect();
180 m_needsPaintInvalidation = false;
181 }
182
183 m_previousLayoutBlock = nullptr;
184 return;
185 }
186
187 if (block != m_layoutBlock)
123 return; 188 return;
124 189
125 // FIXME: Need to over-paint 1 pixel to workaround some rounding problems. 190 // 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 191 LayoutRect newVisualRect;
127 LayoutRect inflatedRect = rect; 192 if (m_layoutBlock && !m_localRect.isEmpty()) {
128 inflatedRect.inflate(LayoutUnit(1)); 193 newVisualRect = m_localRect;
194 context.mapLocalRectToPaintInvalidationBacking(*m_layoutBlock,
195 newVisualRect);
196 newVisualRect.move(m_layoutBlock->scrollAdjustmentForPaintInvalidation(
197 *context.paintInvalidationContainer));
129 198
130 // FIXME: We should not allow paint invalidation out of paint invalidation 199 if (m_layoutBlock->usesCompositedScrolling()) {
131 // state. crbug.com/457415 200 // The caret should use scrolling coordinate space.
132 DisablePaintInvalidationStateAsserts disabler; 201 DCHECK(m_layoutBlock == context.paintInvalidationContainer);
202 newVisualRect.move(LayoutSize(m_layoutBlock->scrolledContentOffset()));
203 }
204 }
133 205
134 m_visualRect = 206 if (m_needsPaintInvalidation || newVisualRect != m_visualRect) {
135 node->layoutObject()->invalidatePaintRectangle(inflatedRect, this); 207 m_needsPaintInvalidation = false;
208
209 ObjectPaintInvalidatorWithContext objectInvalidator(*m_layoutBlock,
210 context);
211 if (!isImmediateFullPaintInvalidationReason(
212 layoutBlockPaintInvalidationReason)) {
213 objectInvalidator.fullyInvalidatePaint(PaintInvalidationCaret,
214 m_visualRect, newVisualRect);
215 }
216
217 context.paintingLayer->setNeedsRepaint();
218 objectInvalidator.invalidateDisplayItemClient(*this,
219 PaintInvalidationCaret);
220 }
221
222 m_visualRect = newVisualRect;
136 } 223 }
137 224
138 void CaretDisplayItemClient::paintCaret(Node* node, 225 void CaretDisplayItemClient::paintCaret(
139 GraphicsContext& context, 226 GraphicsContext& context,
140 const LayoutRect& caretLocalRect, 227 const LayoutPoint& paintOffset,
141 const LayoutPoint& paintOffset, 228 DisplayItem::Type displayItemType) const {
142 DisplayItem::Type displayItemType) {
143 if (DrawingRecorder::useCachedDrawingIfPossible(context, *this, 229 if (DrawingRecorder::useCachedDrawingIfPossible(context, *this,
144 displayItemType)) 230 displayItemType))
145 return; 231 return;
146 232
147 LayoutRect drawingRect = caretLocalRect; 233 LayoutRect drawingRect = m_localRect;
148 if (LayoutBlock* layoutObject = caretLayoutObject(node)) 234 m_layoutBlock->flipForWritingMode(drawingRect);
149 layoutObject->flipForWritingMode(drawingRect);
150 drawingRect.moveBy(paintOffset); 235 drawingRect.moveBy(paintOffset);
151 236
152 const Color caretColor =
153 node->layoutObject()->resolveColor(CSSPropertyCaretColor);
154 IntRect paintRect = pixelSnappedIntRect(drawingRect); 237 IntRect paintRect = pixelSnappedIntRect(drawingRect);
155 DrawingRecorder drawingRecorder(context, *this, DisplayItem::kCaret, 238 DrawingRecorder drawingRecorder(context, *this, DisplayItem::kCaret,
156 paintRect); 239 paintRect);
157 context.fillRect(paintRect, caretColor); 240 context.fillRect(paintRect, m_color);
158 } 241 }
159 242
160 String CaretDisplayItemClient::debugName() const { 243 String CaretDisplayItemClient::debugName() const {
161 return "Caret"; 244 return "Caret";
162 } 245 }
163 246
164 LayoutRect CaretDisplayItemClient::visualRect() const { 247 LayoutRect CaretDisplayItemClient::visualRect() const {
165 return m_visualRect; 248 return m_visualRect;
166 } 249 }
167 250
168 } // namespace blink 251 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/editing/CaretDisplayItemClient.h ('k') | third_party/WebKit/Source/core/editing/DragCaret.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698