From dcd2debe625841ee8cba6d13a56cde7613c40358 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?=
 <morten.sorvig@theqtcompany.com>
Date: Fri, 19 Jun 2015 16:40:39 +0200
Subject: [PATCH] Enable non-integer device pixel ratio

Work around QPaintDevice::metric's int return type
by adding a new metric that returns a scaled devicePixelRatio.
Choose a scale factor that gives us more than enough
range.

The QPaintDevice::devicePixelRatio() convenience accessor
is public API and can unfortunately not be changed
to return a qreal. Add devicePixelRatioF() which
returns the (unscaled) devicePixelRatio.

Change all call sites of QPaintDevice::devicePixelRatio()
to use QPainDevice::devicePixelRatioF().

Task-number: QTBUG-46615
Change-Id: I97ec4000fe379b7ff5e1624a871ae2512790aad9
Reviewed-by: Paul Olav Tvete <paul.tvete@theqtcompany.com>
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
---
 src/gui/image/qimage.cpp                           |  4 ++++
 src/gui/image/qpicture.cpp                         |  3 +++
 src/gui/image/qpixmap_blitter.cpp                  |  2 ++
 src/gui/image/qpixmap_raster.cpp                   |  3 +++
 src/gui/kernel/qopenglwindow.cpp                   |  5 ----
 src/gui/kernel/qpaintdevicewindow.cpp              |  6 +++--
 src/gui/kernel/qrasterwindow.cpp                   |  2 --
 src/gui/opengl/qopenglpaintdevice.cpp              |  3 +++
 src/gui/painting/qpaintdevice.cpp                  |  6 +++++
 src/gui/painting/qpaintdevice.h                    |  6 +++--
 src/gui/painting/qpaintdevice.qdoc                 | 21 ++++++++++++++++
 src/gui/painting/qpainter.cpp                      | 10 ++++----
 src/gui/painting/qpainter_p.h                      |  2 +-
 src/gui/painting/qpdf.cpp                          |  3 +++
 src/gui/text/qstatictext.cpp                       |  3 +++
 src/gui/text/qtextimagehandler.cpp                 |  4 ++--
 src/opengl/qgl.cpp                                 |  4 ++--
 src/opengl/qglframebufferobject.cpp                |  3 +++
 src/opengl/qglpaintdevice.cpp                      |  2 ++
 src/opengl/qglpixelbuffer.cpp                      |  3 +++
 src/plugins/platforms/cocoa/qprintengine_mac.mm    |  3 +++
 .../direct2d/qwindowsdirect2dpaintdevice.cpp       |  3 +++
 src/widgets/kernel/qopenglwidget.cpp               | 28 +++++++++++++---------
 src/widgets/kernel/qwidget.cpp                     | 21 ++++++++--------
 src/widgets/styles/qmacstyle_mac.mm                |  4 ++--
 src/widgets/styles/qwindowsstyle_p_p.h             |  2 +-
 src/widgets/widgets/qlabel.cpp                     |  2 +-
 27 files changed, 112 insertions(+), 46 deletions(-)

Index: b/src/gui/image/qimage.cpp
===================================================================
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -3793,6 +3793,10 @@ int QImage::metric(PaintDeviceMetric met
         return d->devicePixelRatio;
         break;
 
+    case PdmDevicePixelRatioScaled:
+        return d->devicePixelRatio * QPaintDevice::devicePixelRatioFScale();
+        break;
+
     default:
         qWarning("QImage::metric(): Unhandled metric type %d", metric);
         break;
Index: b/src/gui/image/qpicture.cpp
===================================================================
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -961,6 +961,9 @@ int QPicture::metric(PaintDeviceMetric m
         case PdmDevicePixelRatio:
             val = 1;
             break;
+        case PdmDevicePixelRatioScaled:
+            val = 1 * QPaintDevice::devicePixelRatioFScale();
+            break;
         default:
             val = 0;
             qWarning("QPicture::metric: Invalid metric command");
Index: b/src/gui/image/qpixmap_blitter.cpp
===================================================================
--- a/src/gui/image/qpixmap_blitter.cpp
+++ b/src/gui/image/qpixmap_blitter.cpp
@@ -115,6 +115,8 @@ int QBlittablePlatformPixmap::metric(QPa
         return qt_defaultDpiY();
     case QPaintDevice::PdmDevicePixelRatio:
         return devicePixelRatio();
+    case QPaintDevice::PdmDevicePixelRatioScaled:
+        return devicePixelRatio() * QPaintDevice::devicePixelRatioFScale();
     default:
         qWarning("QRasterPlatformPixmap::metric(): Unhandled metric type %d", metric);
         break;
Index: b/src/gui/image/qpixmap_raster.cpp
===================================================================
--- a/src/gui/image/qpixmap_raster.cpp
+++ b/src/gui/image/qpixmap_raster.cpp
@@ -288,6 +288,9 @@ int QRasterPlatformPixmap::metric(QPaint
         return qt_defaultDpiY();
     case QPaintDevice::PdmDevicePixelRatio:
         return image.devicePixelRatio();
+    case QPaintDevice::PdmDevicePixelRatioScaled:
+        return image.devicePixelRatio() * QPaintDevice::devicePixelRatioFScale();
+
     default:
         qWarning("QRasterPlatformPixmap::metric(): Unhandled metric type %d", metric);
         break;
Index: b/src/gui/kernel/qopenglwindow.cpp
===================================================================
--- a/src/gui/kernel/qopenglwindow.cpp
+++ b/src/gui/kernel/qopenglwindow.cpp
@@ -664,15 +664,10 @@ int QOpenGLWindow::metric(PaintDeviceMet
             if (d->paintDevice)
                 return d->paintDevice->depth();
             break;
-        case PdmDevicePixelRatio:
-            if (d->paintDevice)
-                return devicePixelRatio();
-            break;
         default:
             break;
     }
     return QPaintDeviceWindow::metric(metric);
-
 }
 
 /*!
Index: b/src/gui/kernel/qpaintdevicewindow.cpp
===================================================================
--- a/src/gui/kernel/qpaintdevicewindow.cpp
+++ b/src/gui/kernel/qpaintdevicewindow.cpp
@@ -155,8 +155,10 @@ int QPaintDeviceWindow::metric(PaintDevi
             return qRound(screen->physicalDotsPerInchY());
         break;
     case PdmDevicePixelRatio:
-        if (screen)
-            return screen->devicePixelRatio();
+        return int(QWindow::devicePixelRatio());
+        break;
+    case PdmDevicePixelRatioScaled:
+        return int(QWindow::devicePixelRatio() * devicePixelRatioFScale());
         break;
     default:
         break;
Index: b/src/gui/kernel/qrasterwindow.cpp
===================================================================
--- a/src/gui/kernel/qrasterwindow.cpp
+++ b/src/gui/kernel/qrasterwindow.cpp
@@ -108,8 +108,6 @@ int QRasterWindow::metric(PaintDeviceMet
     switch (metric) {
     case PdmDepth:
         return d->backingstore->paintDevice()->depth();
-    case PdmDevicePixelRatio:
-        return d->backingstore->paintDevice()->devicePixelRatio();
     default:
         break;
     }
Index: b/src/gui/opengl/qopenglpaintdevice.cpp
===================================================================
--- a/src/gui/opengl/qopenglpaintdevice.cpp
+++ b/src/gui/opengl/qopenglpaintdevice.cpp
@@ -271,6 +271,9 @@ int QOpenGLPaintDevice::metric(QPaintDev
         return qRound(d_ptr->dpmy * 0.0254);
     case PdmDevicePixelRatio:
         return d_ptr->devicePixelRatio;
+    case PdmDevicePixelRatioScaled:
+        return d_ptr->devicePixelRatio * QPaintDevice::devicePixelRatioFScale();
+
     default:
         qWarning("QOpenGLPaintDevice::metric() - metric %d not known", metric);
         return 0;
Index: b/src/gui/painting/qpaintdevice.cpp
===================================================================
--- a/src/gui/painting/qpaintdevice.cpp
+++ b/src/gui/painting/qpaintdevice.cpp
@@ -79,7 +79,13 @@ Q_GUI_EXPORT int qt_paint_device_metric(
 
 int QPaintDevice::metric(PaintDeviceMetric m) const
 {
+    // Fallback: A subclass has not implemented PdmDevicePixelRatioScaled but might
+    // have implemented PdmDevicePixelRatio.
+    if (m == PdmDevicePixelRatioScaled)
+        return this->metric(PdmDevicePixelRatio) * devicePixelRatioFScale();
+
     qWarning("QPaintDevice::metrics: Device has no metric information");
+
     if (m == PdmDpiX) {
         return 72;
     } else if (m == PdmDpiY) {
Index: b/src/gui/painting/qpaintdevice.h
===================================================================
--- a/src/gui/painting/qpaintdevice.h
+++ b/src/gui/painting/qpaintdevice.h
@@ -58,7 +58,8 @@ public:
         PdmDpiY,
         PdmPhysicalDpiX,
         PdmPhysicalDpiY,
-        PdmDevicePixelRatio
+        PdmDevicePixelRatio,
+        PdmDevicePixelRatioScaled
     };
 
     virtual ~QPaintDevice();
@@ -76,9 +77,11 @@ public:
     int physicalDpiX() const { return metric(PdmPhysicalDpiX); }
     int physicalDpiY() const { return metric(PdmPhysicalDpiY); }
     int devicePixelRatio() const { return metric(PdmDevicePixelRatio); }
+    qreal devicePixelRatioF()  const { return metric(PdmDevicePixelRatioScaled) / devicePixelRatioFScale(); }
     int colorCount() const { return metric(PdmNumColors); }
     int depth() const { return metric(PdmDepth); }
 
+    static inline qreal devicePixelRatioFScale() {return 10000000.0; }
 protected:
     QPaintDevice() Q_DECL_NOEXCEPT;
     virtual int metric(PaintDeviceMetric metric) const;
@@ -87,7 +90,6 @@ protected:
     virtual QPainter *sharedPainter() const;
 
     ushort        painters;                        // refcount
-
 private:
     Q_DISABLE_COPY(QPaintDevice)
 
Index: b/src/gui/painting/qpaintdevice.qdoc
===================================================================
--- a/src/gui/painting/qpaintdevice.qdoc
+++ b/src/gui/painting/qpaintdevice.qdoc
@@ -286,3 +286,24 @@
     Common values are 1 for normal-dpi displays and 2 for high-dpi
     "retina" displays.
 */
+
+/*!
+    \fn qreal QPaintDevice::devicePixelRatioF() const
+
+    Returns the device pixel ratio for the device as a floating point number.
+
+    \since 5.6
+*/
+
+/*!
+    \fn qreal QPaintDevice::devicePixelRatioFScale()
+
+    \internal
+
+    Returns the scaling factor used for \c PdmDevicePixelRatioScaled. Classes
+    that are not QPaintDevice subclasses are implementing metric(), and need to
+    access this constant. Since it's a qreal, it cannot be an enum, and an inline
+    function is more efficient than a static member variable.
+
+    \since 5.6
+*/
Index: b/src/gui/painting/qpainter.cpp
===================================================================
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -219,18 +219,18 @@ QTransform QPainterPrivate::viewTransfor
     return QTransform();
 }
 
-int QPainterPrivate::effectiveDevicePixelRatio() const
+qreal QPainterPrivate::effectiveDevicePixelRatio() const
 {
     // Special cases for devices that does not support PdmDevicePixelRatio go here:
     if (device->devType() == QInternal::Printer)
-        return 1;
+        return qreal(1);
 
-    return qMax(1, device->metric(QPaintDevice::PdmDevicePixelRatio));
+    return qMax(qreal(1), device->devicePixelRatioF());
 }
 
 QTransform QPainterPrivate::hidpiScaleTransform() const
 {
-    int devicePixelRatio = effectiveDevicePixelRatio();
+    const qreal devicePixelRatio = effectiveDevicePixelRatio();
     return QTransform::fromScale(devicePixelRatio, devicePixelRatio);
 }
 
@@ -5110,7 +5110,7 @@ void QPainter::drawPixmap(const QPointF
             x += d->state->matrix.dx();
             y += d->state->matrix.dy();
         }
-        int scale = pm.devicePixelRatio();
+        qreal scale = pm.devicePixelRatio();
         d->engine->drawPixmap(QRectF(x, y, w / scale, h / scale), pm, QRectF(0, 0, w, h));
     }
 }
Index: b/src/gui/painting/qpainter_p.h
===================================================================
--- a/src/gui/painting/qpainter_p.h
+++ b/src/gui/painting/qpainter_p.h
@@ -241,7 +241,7 @@ public:
     }
 
     QTransform viewTransform() const;
-    int effectiveDevicePixelRatio() const;
+    qreal effectiveDevicePixelRatio() const;
     QTransform hidpiScaleTransform() const;
     static bool attachPainterPrivate(QPainter *q, QPaintDevice *pdev);
     void detachPainterPrivate(QPainter *q);
Index: b/src/gui/painting/qpdf.cpp
===================================================================
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -1318,6 +1318,9 @@ int QPdfEngine::metric(QPaintDevice::Pai
     case QPaintDevice::PdmDevicePixelRatio:
         val = 1;
         break;
+    case QPaintDevice::PdmDevicePixelRatioScaled:
+        val = 1 * QPaintDevice::devicePixelRatioFScale();
+        break;
     default:
         qWarning("QPdfWriter::metric: Invalid metric command");
         return 0;
Index: b/src/gui/text/qstatictext.cpp
===================================================================
--- a/src/gui/text/qstatictext.cpp
+++ b/src/gui/text/qstatictext.cpp
@@ -555,6 +555,9 @@ namespace {
             case PdmDevicePixelRatio:
                 val = 1;
                 break;
+            case PdmDevicePixelRatioScaled:
+                val = devicePixelRatioFScale();
+                break;
             default:
                 val = 0;
                 qWarning("DrawTextItemDevice::metric: Invalid metric command");
Index: b/src/gui/text/qtextimagehandler.cpp
===================================================================
--- a/src/gui/text/qtextimagehandler.cpp
+++ b/src/gui/text/qtextimagehandler.cpp
@@ -256,10 +256,10 @@ void QTextImageHandler::drawObject(QPain
         const QTextImageFormat imageFormat = format.toImageFormat();
 
     if (QCoreApplication::instance()->thread() != QThread::currentThread()) {
-        const QImage image = getImage(doc, imageFormat, p->device()->devicePixelRatio());
+        const QImage image = getImage(doc, imageFormat, p->device()->devicePixelRatioF());
         p->drawImage(rect, image, image.rect());
     } else {
-        const QPixmap pixmap = getPixmap(doc, imageFormat, p->device()->devicePixelRatio());
+        const QPixmap pixmap = getPixmap(doc, imageFormat, p->device()->devicePixelRatioF());
         p->drawPixmap(rect, pixmap, pixmap.rect());
     }
 }
Index: b/src/opengl/qgl.cpp
===================================================================
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -4500,7 +4500,7 @@ QImage QGLWidget::grabFrameBuffer(bool w
 {
     makeCurrent();
     QImage res;
-    qreal pixelRatio = devicePixelRatio();
+    qreal pixelRatio = devicePixelRatioF();
     int w = pixelRatio * width();
     int h = pixelRatio * height();
     if (format().rgba())
@@ -4913,7 +4913,7 @@ void QGLWidget::renderText(double x, dou
         GLdouble win_x = 0, win_y = 0, win_z = 0;
         qgluProject(x, y, z, &model[0], &proj[0], &view[0],
                     &win_x, &win_y, &win_z);
-        const int dpr = d->glcx->device()->devicePixelRatio();
+        const int dpr = d->glcx->device()->devicePixelRatioF();
         win_x /= dpr;
         win_y /= dpr;
         win_y = height - win_y; // y is inverted
Index: b/src/opengl/qglframebufferobject.cpp
===================================================================
--- a/src/opengl/qglframebufferobject.cpp
+++ b/src/opengl/qglframebufferobject.cpp
@@ -1285,6 +1285,9 @@ int QGLFramebufferObject::metric(PaintDe
     case QPaintDevice::PdmDevicePixelRatio:
         return 1;
 
+    case QPaintDevice::PdmDevicePixelRatioScaled:
+        return 1 * QPaintDevice::devicePixelRatioFScale();
+
     default:
         qWarning("QGLFramebufferObject::metric(), Unhandled metric type: %d.\n", metric);
         break;
Index: b/src/opengl/qglpaintdevice.cpp
===================================================================
--- a/src/opengl/qglpaintdevice.cpp
+++ b/src/opengl/qglpaintdevice.cpp
@@ -62,6 +62,8 @@ int QGLPaintDevice::metric(QPaintDevice:
     }
     case PdmDevicePixelRatio:
         return 1;
+    case PdmDevicePixelRatioScaled:
+        return 1 * QPaintDevice::devicePixelRatioFScale();
     default:
         qWarning("QGLPaintDevice::metric() - metric %d not known", metric);
         return 0;
Index: b/src/opengl/qglpixelbuffer.cpp
===================================================================
--- a/src/opengl/qglpixelbuffer.cpp
+++ b/src/opengl/qglpixelbuffer.cpp
@@ -458,6 +458,9 @@ int QGLPixelBuffer::metric(PaintDeviceMe
     case QPaintDevice::PdmDevicePixelRatio:
         return 1;
 
+    case QPaintDevice::PdmDevicePixelRatioScaled:
+        return QPaintDevice::devicePixelRatioFScale();
+
     default:
         qWarning("QGLPixelBuffer::metric(), Unhandled metric type: %d\n", metric);
         break;
Index: b/src/plugins/platforms/cocoa/qprintengine_mac.mm
===================================================================
--- a/src/plugins/platforms/cocoa/qprintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm
@@ -212,6 +212,9 @@ int QMacPrintEngine::metric(QPaintDevice
     case QPaintDevice::PdmDevicePixelRatio:
         val = 1;
         break;
+    case QPaintDevice::PdmDevicePixelRatioScaled:
+        val = 1 * QPaintDevice::devicePixelRatioFScale();
+        break;
     default:
         val = 0;
         qWarning("QPrinter::metric: Invalid metric command");
Index: b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp
===================================================================
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp
@@ -113,6 +113,9 @@ int QWindowsDirect2DPaintDevice::metric(
     case QPaintDevice::PdmDevicePixelRatio:
         return 1;
         break;
+    case QPaintDevice::PdmDevicePixelRatioScaled:
+        return 1 * devicePixelRatioFScale();
+        break;
     case QPaintDevice::PdmWidthMM:
     case QPaintDevice::PdmHeightMM:
         return -1;
Index: b/src/widgets/kernel/qopenglwidget.cpp
===================================================================
--- a/src/widgets/kernel/qopenglwidget.cpp
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -695,7 +695,7 @@ void QOpenGLWidgetPrivate::recreateFbo()
     format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
     format.setSamples(samples);
 
-    const QSize deviceSize = q->size() * q->devicePixelRatio();
+    const QSize deviceSize = q->size() * q->devicePixelRatioF();
     fbo = new QOpenGLFramebufferObject(deviceSize, format);
     if (samples > 0)
         resolvedFbo = new QOpenGLFramebufferObject(deviceSize);
@@ -704,7 +704,7 @@ void QOpenGLWidgetPrivate::recreateFbo()
     context->functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
     paintDevice->setSize(deviceSize);
-    paintDevice->setDevicePixelRatio(q->devicePixelRatio());
+    paintDevice->setDevicePixelRatio(q->devicePixelRatioF());
 
     emit q->resized();
 }
@@ -778,8 +778,8 @@ void QOpenGLWidgetPrivate::initialize()
     }
 
     paintDevice = new QOpenGLWidgetPaintDevice(q);
-    paintDevice->setSize(q->size() * q->devicePixelRatio());
-    paintDevice->setDevicePixelRatio(q->devicePixelRatio());
+    paintDevice->setSize(q->size() * q->devicePixelRatioF());
+    paintDevice->setDevicePixelRatio(q->devicePixelRatioF());
 
     context = ctx.take();
     initialized = true;
@@ -808,7 +808,7 @@ void QOpenGLWidgetPrivate::invokeUserPai
     QOpenGLFunctions *f = ctx->functions();
     QOpenGLContextPrivate::get(ctx)->defaultFboRedirect = fbo->handle();
 
-    f->glViewport(0, 0, q->width() * q->devicePixelRatio(), q->height() * q->devicePixelRatio());
+    f->glViewport(0, 0, q->width() * q->devicePixelRatioF(), q->height() * q->devicePixelRatioF());
     q->paintGL();
     flushPending = true;
 
@@ -859,8 +859,8 @@ QImage QOpenGLWidgetPrivate::grabFramebu
     render();
     resolveSamples();
     q->makeCurrent();
-    QImage res = qt_gl_read_framebuffer(q->size() * q->devicePixelRatio(), false, false);
-    res.setDevicePixelRatio(q->devicePixelRatio());
+    QImage res = qt_gl_read_framebuffer(q->size() * q->devicePixelRatioF(), false, false);
+    res.setDevicePixelRatio(q->devicePixelRatioF());
 
     return res;
 }
@@ -879,7 +879,7 @@ void QOpenGLWidgetPrivate::resizeViewpor
     if (!initialized)
         return;
 
-    if (!fbo || q->size() * q->devicePixelRatio() != fbo->size())
+    if (!fbo || q->size() * q->devicePixelRatioF() != fbo->size())
         recreateFbo();
 }
 
@@ -1196,6 +1196,7 @@ int QOpenGLWidget::metric(QPaintDevice::
         return QWidget::metric(metric);
 
     QWidget *tlw = window();
+    QWindow *window = tlw ? tlw->windowHandle() : 0;
     QScreen *screen = tlw && tlw->windowHandle() ? tlw->windowHandle()->screen() : 0;
     if (!screen && QGuiApplication::primaryScreen())
         screen = QGuiApplication::primaryScreen();
@@ -1243,8 +1244,13 @@ int QOpenGLWidget::metric(QPaintDevice::
         else
             return qRound(dpmy * 0.0254);
     case PdmDevicePixelRatio:
-        if (screen)
-            return screen->devicePixelRatio();
+        if (window)
+            return int(window->devicePixelRatio());
+        else
+            return 1.0;
+    case PdmDevicePixelRatioScaled:
+        if (window)
+            return int(window->devicePixelRatio() * devicePixelRatioFScale());
         else
             return 1.0;
     default:
@@ -1304,7 +1310,7 @@ bool QOpenGLWidget::event(QEvent *e)
         }
         break;
     case QEvent::ScreenChangeInternal:
-        if (d->initialized && d->paintDevice->devicePixelRatio() != devicePixelRatio())
+        if (d->initialized && d->paintDevice->devicePixelRatioF() != devicePixelRatioF())
             d->recreateFbo();
         break;
     default:
Index: b/src/widgets/kernel/qwidget.cpp
===================================================================
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -2043,7 +2043,7 @@ void QWidgetPrivate::setSystemClip(QPain
 // Transform the system clip region from device-independent pixels to device pixels
     QPaintEngine *paintEngine = paintDevice->paintEngine();
     QTransform scaleTransform;
-    const qreal devicePixelRatio = paintDevice->devicePixelRatio();
+    const qreal devicePixelRatio = paintDevice->devicePixelRatioF();
     scaleTransform.scale(devicePixelRatio, devicePixelRatio);
     paintEngine->d_func()->systemClip = scaleTransform.map(region);
 }
@@ -5369,7 +5369,7 @@ void QWidgetPrivate::render_helper(QPain
         if (size.isNull())
             return;
 
-        const qreal pixmapDevicePixelRatio = qreal(painter->device()->devicePixelRatio());
+        const qreal pixmapDevicePixelRatio = painter->device()->devicePixelRatioF();
         QPixmap pixmap(size * pixmapDevicePixelRatio);
         pixmap.setDevicePixelRatio(pixmapDevicePixelRatio);
 
@@ -11818,13 +11818,11 @@ void QWidgetPrivate::updateFrameStrut()
     Q_Q(QWidget);
     if (q->data->fstrut_dirty) {
         if (QTLWExtra *te = maybeTopData()) {
-            if (te->window) {
-                if (const QPlatformWindow *pw = te->window->handle()) {
-                    const QMargins margins = pw->frameMargins();
-                    if (!margins.isNull()) {
-                        te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
-                        q->data->fstrut_dirty = false;
-                    }
+            if (te->window && te->window->handle()) {
+                const QMargins margins = te->window->frameMargins();
+                if (!margins.isNull()) {
+                    te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
+                    q->data->fstrut_dirty = false;
                 }
             }
         }
@@ -12643,6 +12641,9 @@ int QWidget::metric(PaintDeviceMetric m)
         return qRound(screen->physicalDotsPerInchY());
     } else if (m == PdmDevicePixelRatio) {
         return topLevelWindow ? topLevelWindow->devicePixelRatio() : qApp->devicePixelRatio();
+    } else if (m == PdmDevicePixelRatioScaled) {
+        return (QPaintDevice::devicePixelRatioFScale() *
+                (topLevelWindow ? topLevelWindow->devicePixelRatio() : qApp->devicePixelRatio()));
     } else {
         val = QPaintDevice::metric(m);// XXX
     }
Index: b/src/widgets/styles/qmacstyle_mac.mm
===================================================================
--- a/src/widgets/styles/qmacstyle_mac.mm
+++ b/src/widgets/styles/qmacstyle_mac.mm
@@ -1989,7 +1989,7 @@ void QMacStylePrivate::drawColorlessButt
         }
     }
 
-    int devicePixelRatio = p->device()->devicePixelRatio();
+    int devicePixelRatio = p->device()->devicePixelRatioF();
     int width = devicePixelRatio * (int(macRect.size.width) + extraWidth);
     int height = devicePixelRatio * (int(macRect.size.height) + extraHeight);
 
@@ -7217,7 +7217,7 @@ CGContextRef qt_mac_cg_context(const QPa
         }
 
         CGContextTranslateCTM(ret, 0, pm->height());
-        int devicePixelRatio = pdev->devicePixelRatio();
+        qreal devicePixelRatio = pdev->devicePixelRatioF();
         CGContextScaleCTM(ret, devicePixelRatio, devicePixelRatio);
         CGContextScaleCTM(ret, 1, -1);
         return ret;
Index: b/src/widgets/styles/qwindowsstyle_p_p.h
===================================================================
--- a/src/widgets/styles/qwindowsstyle_p_p.h
+++ b/src/widgets/styles/qwindowsstyle_p_p.h
@@ -66,7 +66,7 @@ public:
     static int pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0);
     static int fixedPixelMetric(QStyle::PixelMetric pm);
     static int devicePixelRatio(const QWidget *widget = 0)
-        { return widget ? widget->devicePixelRatio() : QWindowsStylePrivate::appDevicePixelRatio(); }
+        { return widget ? int(widget->devicePixelRatioF()) : QWindowsStylePrivate::appDevicePixelRatio(); }
 
     bool hasSeenAlt(const QWidget *widget) const;
     bool altDown() const { return alt_down; }
Index: b/src/widgets/widgets/qlabel.cpp
===================================================================
--- a/src/widgets/widgets/qlabel.cpp
+++ b/src/widgets/widgets/qlabel.cpp
@@ -1081,7 +1081,7 @@ void QLabel::paintEvent(QPaintEvent *)
                     d->cachedimage = new QImage(d->pixmap->toImage());
                 delete d->scaledpixmap;
                 QImage scaledImage =
-                    d->cachedimage->scaled(cr.size() * devicePixelRatio(),
+                    d->cachedimage->scaled(cr.size() * devicePixelRatioF(),
                                            Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
                 d->scaledpixmap = new QPixmap(QPixmap::fromImage(scaledImage));
             }
