- Revision
- 264386
- Author
- [email protected]
- Date
- 2020-07-14 19:46:31 -0700 (Tue, 14 Jul 2020)
Log Message
Caret leaves trails behind when the editable content is subpixel positioned
https://bugs.webkit.org/show_bug.cgi?id=214333
<rdar://problem/61914738>
Reviewed by Simon Fraser.
Replace integral rounding with pixelsnapping when painting the caret.
The paint invalidation uses device pixel snapping and the actual painting needs to match it
in order to not paint outside of the invalidated region.
* editing/Editing.cpp:
(WebCore::caretRendersInsideNode):
(WebCore::rendererForCaretPainting):
* editing/Editing.h:
* editing/FrameSelection.cpp:
(WebCore::FrameSelection::paintCaret):
(WebCore::CaretBase::computeCaretColor):
(WebCore::CaretBase::paintCaret const):
(WebCore::DragCaretController::paintDragCaret const):
* editing/FrameSelection.h:
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (264385 => 264386)
--- trunk/Source/WebCore/ChangeLog 2020-07-15 01:41:06 UTC (rev 264385)
+++ trunk/Source/WebCore/ChangeLog 2020-07-15 02:46:31 UTC (rev 264386)
@@ -1,3 +1,27 @@
+2020-07-14 Zalan Bujtas <[email protected]>
+
+ Caret leaves trails behind when the editable content is subpixel positioned
+ https://bugs.webkit.org/show_bug.cgi?id=214333
+ <rdar://problem/61914738>
+
+ Reviewed by Simon Fraser.
+
+ Replace integral rounding with pixelsnapping when painting the caret.
+
+ The paint invalidation uses device pixel snapping and the actual painting needs to match it
+ in order to not paint outside of the invalidated region.
+
+ * editing/Editing.cpp:
+ (WebCore::caretRendersInsideNode):
+ (WebCore::rendererForCaretPainting):
+ * editing/Editing.h:
+ * editing/FrameSelection.cpp:
+ (WebCore::FrameSelection::paintCaret):
+ (WebCore::CaretBase::computeCaretColor):
+ (WebCore::CaretBase::paintCaret const):
+ (WebCore::DragCaretController::paintDragCaret const):
+ * editing/FrameSelection.h:
+
2020-07-14 James Darpinian <[email protected]>
[WebGL2] vertexAttribI* and getFragDataLocation
Modified: trunk/Source/WebCore/editing/Editing.cpp (264385 => 264386)
--- trunk/Source/WebCore/editing/Editing.cpp 2020-07-15 01:41:06 UTC (rev 264385)
+++ trunk/Source/WebCore/editing/Editing.cpp 2020-07-15 02:46:31 UTC (rev 264386)
@@ -1272,12 +1272,12 @@
return nullptr;
}
-static inline bool caretRendersInsideNode(Node& node)
+static inline bool caretRendersInsideNode(const Node& node)
{
return !isRenderedTable(&node) && !editingIgnoresContent(node);
}
-RenderBlock* rendererForCaretPainting(Node* node)
+RenderBlock* rendererForCaretPainting(const Node* node)
{
if (!node)
return nullptr;
Modified: trunk/Source/WebCore/editing/Editing.h (264385 => 264386)
--- trunk/Source/WebCore/editing/Editing.h 2020-07-15 01:41:06 UTC (rev 264385)
+++ trunk/Source/WebCore/editing/Editing.h 2020-07-15 02:46:31 UTC (rev 264386)
@@ -205,7 +205,7 @@
// Miscellaneous functions for caret rendering.
-RenderBlock* rendererForCaretPainting(Node*);
+RenderBlock* rendererForCaretPainting(const Node*);
LayoutRect localCaretRectInRendererForCaretPainting(const VisiblePosition&, RenderBlock*&);
LayoutRect localCaretRectInRendererForRect(LayoutRect&, Node*, RenderObject*, RenderBlock*&);
IntRect absoluteBoundsForLocalCaretRect(RenderBlock* rendererForCaretPainting, const LayoutRect&, bool* insideFixed = nullptr);
Modified: trunk/Source/WebCore/editing/FrameSelection.cpp (264385 => 264386)
--- trunk/Source/WebCore/editing/FrameSelection.cpp 2020-07-15 01:41:06 UTC (rev 264385)
+++ trunk/Source/WebCore/editing/FrameSelection.cpp 2020-07-15 02:46:31 UTC (rev 264386)
@@ -1784,11 +1784,11 @@
void FrameSelection::paintCaret(GraphicsContext& context, const LayoutPoint& paintOffset, const LayoutRect& clipRect)
{
- if (m_selection.isCaret() && m_caretPaint)
- CaretBase::paintCaret(m_selection.start().deprecatedNode(), context, paintOffset, clipRect);
+ if (m_selection.isCaret() && m_caretPaint && m_selection.start().deprecatedNode())
+ CaretBase::paintCaret(*m_selection.start().deprecatedNode(), context, paintOffset, clipRect);
}
-Color CaretBase::computeCaretColor(const RenderStyle& elementStyle, Node* node)
+Color CaretBase::computeCaretColor(const RenderStyle& elementStyle, const Node* node)
{
// On iOS, we want to fall back to the tintColor, and only override if CSS has explicitly specified a custom color.
#if PLATFORM(IOS_FAMILY) && !PLATFORM(MACCATALYST)
@@ -1809,26 +1809,27 @@
#endif
}
-void CaretBase::paintCaret(Node* node, GraphicsContext& context, const LayoutPoint& paintOffset, const LayoutRect& clipRect) const
+void CaretBase::paintCaret(const Node& node, GraphicsContext& context, const LayoutPoint& paintOffset, const LayoutRect& clipRect) const
{
#if ENABLE(TEXT_CARET)
if (m_caretVisibility == Hidden)
return;
- LayoutRect drawingRect = localCaretRectWithoutUpdate();
- if (auto* renderer = rendererForCaretPainting(node))
+ auto drawingRect = localCaretRectWithoutUpdate();
+ if (auto* renderer = rendererForCaretPainting(&node))
renderer->flipForWritingMode(drawingRect);
- drawingRect.moveBy(roundedIntPoint(paintOffset));
- LayoutRect caret = intersection(drawingRect, clipRect);
+ drawingRect.moveBy(paintOffset);
+ auto caret = intersection(drawingRect, clipRect);
if (caret.isEmpty())
return;
Color caretColor = Color::black;
- Element* element = is<Element>(*node) ? downcast<Element>(node) : node->parentElement();
+ auto* element = is<Element>(node) ? downcast<Element>(&node) : node.parentElement();
if (element && element->renderer())
- caretColor = CaretBase::computeCaretColor(element->renderer()->style(), node);
+ caretColor = CaretBase::computeCaretColor(element->renderer()->style(), &node);
- context.fillRect(caret, caretColor);
+ auto pixelSnappedCaretRect = snapRectToDevicePixels(caret, node.document().deviceScaleFactor());
+ context.fillRect(pixelSnappedCaretRect, caretColor);
#else
UNUSED_PARAM(node);
UNUSED_PARAM(context);
@@ -2287,8 +2288,8 @@
void DragCaretController::paintDragCaret(Frame* frame, GraphicsContext& p, const LayoutPoint& paintOffset, const LayoutRect& clipRect) const
{
#if ENABLE(TEXT_CARET)
- if (m_position.deepEquivalent().deprecatedNode()->document().frame() == frame)
- paintCaret(m_position.deepEquivalent().deprecatedNode(), p, paintOffset, clipRect);
+ if (m_position.deepEquivalent().deprecatedNode() && m_position.deepEquivalent().deprecatedNode()->document().frame() == frame)
+ paintCaret(*m_position.deepEquivalent().deprecatedNode(), p, paintOffset, clipRect);
#else
UNUSED_PARAM(frame);
UNUSED_PARAM(p);
Modified: trunk/Source/WebCore/editing/FrameSelection.h (264385 => 264386)
--- trunk/Source/WebCore/editing/FrameSelection.h 2020-07-15 01:41:06 UTC (rev 264385)
+++ trunk/Source/WebCore/editing/FrameSelection.h 2020-07-15 02:46:31 UTC (rev 264386)
@@ -63,7 +63,7 @@
WTF_MAKE_NONCOPYABLE(CaretBase);
WTF_MAKE_FAST_ALLOCATED;
public:
- WEBCORE_EXPORT static Color computeCaretColor(const RenderStyle& elementStyle, Node*);
+ WEBCORE_EXPORT static Color computeCaretColor(const RenderStyle& elementStyle, const Node*);
protected:
enum CaretVisibility { Visible, Hidden };
explicit CaretBase(CaretVisibility = Hidden);
@@ -72,7 +72,7 @@
void clearCaretRect();
bool updateCaretRect(Document*, const VisiblePosition& caretPosition);
bool shouldRepaintCaret(const RenderView*, bool isContentEditable) const;
- void paintCaret(Node*, GraphicsContext&, const LayoutPoint&, const LayoutRect& clipRect) const;
+ void paintCaret(const Node&, GraphicsContext&, const LayoutPoint&, const LayoutRect& clipRect) const;
const LayoutRect& localCaretRectWithoutUpdate() const { return m_caretLocalRect; }