Title: [264386] trunk/Source/WebCore
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; }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to