Input buttons rendered at the wrong size when pinching-to-zoom
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 Jul 2015 21:39:34 +0000 (21:39 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 Jul 2015 21:39:34 +0000 (21:39 +0000)
https://bugs.webkit.org/show_bug.cgi?id=146916

Patch by Wenson Hsieh <wenson_hsieh@apple.com> on 2015-07-14
Reviewed by Dean Jackson.

Scales buttons and their focus rects up when pinching to zoom by painting to an offscreen ImageBuffer which is
then scaled and painted onto the display.

* platform/Theme.h: Modified signature of Theme::paint.
(WebCore::Theme::paint): Added plumbing necessary to send the device and page scale factors to paintButton.
* platform/mac/ThemeMac.h: Modified signature of paintButton.
* platform/mac/ThemeMac.mm: Added ImageBuffer.h header.
(WebCore::buttonFocusRectOutlineWidth): Represents the width of the focus rect of a button. Used by paintButton
    to determine the size of the ImageBuffer required to draw a focus rect.
(WebCore::paintButton): Changed to paint button cells and the focus rect, if applicable, to a temporary ImageBuffer
    before painting the ImageBuffer onto the view. Refactored to receive a deviceScaleFactor and page scale factor,
    used when painting to the ImageBuffer.
(WebCore::ThemeMac::paint): Added plumbing necessary to send the device and page scale factors to paintButton.
* rendering/RenderTheme.cpp: Modified signature of RenderTheme::paint.
(WebCore::RenderTheme::paint): Added plumbing necessary to send the device and page scale factors to paintButton.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@186817 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/Theme.h
Source/WebCore/platform/mac/ThemeMac.h
Source/WebCore/platform/mac/ThemeMac.mm
Source/WebCore/rendering/RenderTheme.cpp

index 64a22ab..7f5bfe8 100644 (file)
@@ -1,3 +1,26 @@
+2015-07-14  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Input buttons rendered at the wrong size when pinching-to-zoom
+        https://bugs.webkit.org/show_bug.cgi?id=146916
+
+        Reviewed by Dean Jackson.
+
+        Scales buttons and their focus rects up when pinching to zoom by painting to an offscreen ImageBuffer which is
+        then scaled and painted onto the display.
+
+        * platform/Theme.h: Modified signature of Theme::paint.
+        (WebCore::Theme::paint): Added plumbing necessary to send the device and page scale factors to paintButton.
+        * platform/mac/ThemeMac.h: Modified signature of paintButton.
+        * platform/mac/ThemeMac.mm: Added ImageBuffer.h header.
+        (WebCore::buttonFocusRectOutlineWidth): Represents the width of the focus rect of a button. Used by paintButton
+            to determine the size of the ImageBuffer required to draw a focus rect.
+        (WebCore::paintButton): Changed to paint button cells and the focus rect, if applicable, to a temporary ImageBuffer
+            before painting the ImageBuffer onto the view. Refactored to receive a deviceScaleFactor and page scale factor,
+            used when painting to the ImageBuffer.
+        (WebCore::ThemeMac::paint): Added plumbing necessary to send the device and page scale factors to paintButton.
+        * rendering/RenderTheme.cpp: Modified signature of RenderTheme::paint.
+        (WebCore::RenderTheme::paint): Added plumbing necessary to send the device and page scale factors to paintButton.
+
 2015-07-14  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r186809.
index 10e0c77..a136751 100644 (file)
@@ -100,7 +100,7 @@ public:
     virtual bool controlRequiresPreWhiteSpace(ControlPart) const { return false; }
 
     // Method for painting a control. The rect is in zoomed coordinates.
-    virtual void paint(ControlPart, ControlStates*, GraphicsContext*, const FloatRect& /*zoomedRect*/, float /*zoomFactor*/, ScrollView*) { }
+    virtual void paint(ControlPart, ControlStates*, GraphicsContext*, const FloatRect& /*zoomedRect*/, float /*zoomFactor*/, ScrollView*, float /*deviceScaleFactor*/, float /*pageScaleFactor*/) { }
 
     // Some controls may spill out of their containers (e.g., the check on an OS X checkbox).  When these controls repaint,
     // the theme needs to communicate this inflated rect to the engine so that it can invalidate the whole control.
index 4440144..c7dd5d0 100644 (file)
@@ -52,7 +52,7 @@ public:
 
     virtual bool controlRequiresPreWhiteSpace(ControlPart part) const override { return part == PushButtonPart; }
 
-    virtual void paint(ControlPart, ControlStates*, GraphicsContext*, const FloatRect&, float zoomFactor, ScrollView*) override;
+    virtual void paint(ControlPart, ControlStates*, GraphicsContext*, const FloatRect&, float zoomFactor, ScrollView*, float deviceScaleFactor, float pageScaleFactor) override;
     virtual void inflateControlPaintRect(ControlPart, const ControlStates*, FloatRect&, float zoomFactor) const override;
 
     // FIXME: Once RenderThemeMac is converted over to use Theme then this can be internal to ThemeMac.
index cdaedbc..4b2779e 100644 (file)
@@ -29,6 +29,7 @@
 #import "AXObjectCache.h"
 #import "BlockExceptions.h"
 #import "GraphicsContext.h"
+#import "ImageBuffer.h"
 #import "LocalCurrentGraphicsContext.h"
 #import "ScrollView.h"
 #import "WebCoreSystemInterface.h"
@@ -530,7 +531,12 @@ static NSButtonCell *button(ControlPart part, const ControlStates* controlStates
     return cell;
 }
 
-static void paintButton(ControlPart part, ControlStates* controlStates, GraphicsContext* context, const FloatRect& zoomedRect, float zoomFactor, ScrollView* scrollView)
+static float buttonFocusRectOutlineWidth()
+{
+    return 3.0f;
+}
+    
+static void paintButton(ControlPart part, ControlStates* controlStates, GraphicsContext* context, const FloatRect& zoomedRect, float zoomFactor, ScrollView* scrollView, float deviceScaleFactor, float pageScaleFactor)
 {
     BEGIN_BLOCK_OBJC_EXCEPTIONS
     
@@ -561,9 +567,19 @@ static void paintButton(ControlPart part, ControlStates* controlStates, Graphics
             context->scale(FloatSize(zoomFactor, zoomFactor));
             context->translate(-inflatedRect.x(), -inflatedRect.y());
         }
-    } 
-
-    LocalCurrentGraphicsContext localContext(context);
+    }
+    
+    bool shouldUseImageBuffer = pageScaleFactor != 1.0f || zoomFactor != 1.0f;
+    float focusThickness = buttonFocusRectOutlineWidth();
+    
+    std::unique_ptr<ImageBuffer> imageBuffer;
+    GraphicsContext* drawButtonContext = context;
+    if (shouldUseImageBuffer) {
+        imageBuffer = ImageBuffer::createCompatibleBuffer(inflatedRect.size() + 2 * FloatSize(focusThickness, focusThickness), deviceScaleFactor, ColorSpaceDeviceRGB, context, false);
+        drawButtonContext = imageBuffer->context();
+    }
+    LocalCurrentGraphicsContext localContext(drawButtonContext);
+    
     NSView *view = ThemeMac::ensuredView(scrollView, controlStates);
     NSWindow *window = [view window];
     NSButtonCell *previousDefaultButtonCell = [window defaultButtonCell];
@@ -576,12 +592,22 @@ static void paintButton(ControlPart part, ControlStates* controlStates, Graphics
     } else if ([previousDefaultButtonCell isEqual:buttonCell])
         [window setDefaultButtonCell:nil];
 
-    [buttonCell drawWithFrame:NSRect(inflatedRect) inView:view];
-    bool needsRepaint = false;
-    if (states & ControlStates::FocusState)
-        needsRepaint = drawCellFocusRing(buttonCell, inflatedRect, view);
-
-    controlStates->setNeedsRepaint(needsRepaint);
+    if (shouldUseImageBuffer) {
+        [buttonCell drawWithFrame:CGRectMake(focusThickness, focusThickness, inflatedRect.width(), inflatedRect.height()) inView:view];
+        if (!(states & ControlStates::FocusState))
+            context->drawImageBuffer(imageBuffer.get(), ColorSpaceDeviceRGB, inflatedRect.location() - FloatSize(focusThickness, focusThickness));
+    } else
+        [buttonCell drawWithFrame:CGRect(inflatedRect) inView:view];
+    
+    if (states & ControlStates::FocusState) {
+        if (shouldUseImageBuffer) {
+            drawCellFocusRing(buttonCell, CGRectMake(focusThickness, focusThickness, inflatedRect.width(), inflatedRect.height()), view);
+            context->drawImageBuffer(imageBuffer.get(), ColorSpaceDeviceRGB, inflatedRect.location() - FloatSize(focusThickness, focusThickness));
+        } else
+            drawCellFocusRing(buttonCell, inflatedRect, view);
+    }
+    
+    controlStates->setNeedsRepaint(false);
 
     [buttonCell setControlView:nil];
 
@@ -823,7 +849,7 @@ void ThemeMac::inflateControlPaintRect(ControlPart part, const ControlStates* st
     END_BLOCK_OBJC_EXCEPTIONS
 }
 
-void ThemeMac::paint(ControlPart part, ControlStates* states, GraphicsContext* context, const FloatRect& zoomedRect, float zoomFactor, ScrollView* scrollView)
+void ThemeMac::paint(ControlPart part, ControlStates* states, GraphicsContext* context, const FloatRect& zoomedRect, float zoomFactor, ScrollView* scrollView, float deviceScaleFactor, float pageScaleFactor)
 {
     switch (part) {
         case CheckboxPart:
@@ -836,7 +862,7 @@ void ThemeMac::paint(ControlPart part, ControlStates* states, GraphicsContext* c
         case DefaultButtonPart:
         case ButtonPart:
         case SquareButtonPart:
-            paintButton(part, states, context, zoomedRect, zoomFactor, scrollView);
+            paintButton(part, states, context, zoomedRect, zoomFactor, scrollView, deviceScaleFactor, pageScaleFactor);
             break;
         case InnerSpinButtonPart:
             paintStepper(states, context, zoomedRect, zoomFactor, scrollView);
index 8014082..72c3442 100644 (file)
@@ -277,9 +277,12 @@ bool RenderTheme::paint(const RenderObject& o, ControlStates* controlStates, con
 
     ControlPart part = o.style().appearance();
     IntRect integralSnappedRect = snappedIntRect(r);
-    FloatRect devicePixelSnappedRect = snapRectToDevicePixels(r, o.document().deviceScaleFactor());
+    float deviceScaleFactor = o.document().deviceScaleFactor();
+    FloatRect devicePixelSnappedRect = snapRectToDevicePixels(r, deviceScaleFactor);
 
 #if USE(NEW_THEME)
+    float pageScaleFactor = o.document().page() ? o.document().page()->pageScaleFactor() : 1.0f;
+    
     switch (part) {
     case CheckboxPart:
     case RadioPart:
@@ -289,7 +292,7 @@ bool RenderTheme::paint(const RenderObject& o, ControlStates* controlStates, con
     case ButtonPart:
     case InnerSpinButtonPart:
         updateControlStatesForRenderer(o, controlStates);
-        m_theme->paint(part, controlStates, const_cast<GraphicsContext*>(paintInfo.context), devicePixelSnappedRect, o.style().effectiveZoom(), &o.view().frameView());
+        m_theme->paint(part, controlStates, const_cast<GraphicsContext*>(paintInfo.context), devicePixelSnappedRect, o.style().effectiveZoom(), &o.view().frameView(), deviceScaleFactor, pageScaleFactor);
         return false;
     default:
         break;