| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |