From cea58f4b77e1639e5671cf424544d4948fb8e9ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 24 Jan 2013 09:26:45 +0100 Subject: [PATCH] Add devicePixelRatio metric to QPaintDevice. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously QPainter computed the devicePixelRatio based on the physical and logical dpi, and expected that the ratio between them would be either 1x or 2x. This was problematic for paint devices like printers where the physical dpi can be much higher than the logical dpi, and also for QScreen where the physical dpi would have to be defined as a multiple of the logical dpi. Add QPaintDevice::PdmDevicePixelRatio and QPaintDevice:: devicePixelRatio() getter and implement it for the QPaintDevice subclasses. Use it when calculating the highdpi scale transform in qpainter.cpp and when scaling the clip rect in qwidget.cpp. Remove physical dpi scaling for QImage, QPixmap and QOpenGLPaintDevice, reverting to the old behavior. Change-Id: I6c97510613196d4536ff39d08e9750b8782283d4 Reviewed-by: Samuel Rødal Reviewed-by: Gunnar Sletta --- src/gui/image/qimage.cpp | 9 +++-- src/gui/image/qpicture.cpp | 3 ++ src/gui/image/qpixmap_blitter.cpp | 2 ++ src/gui/image/qpixmap_raster.cpp | 6 ++-- src/gui/opengl/qopenglpaintdevice.cpp | 6 ++-- src/gui/painting/qpaintdevice.cpp | 2 ++ src/gui/painting/qpaintdevice.h | 4 ++- src/gui/painting/qpaintdevice.qdoc | 13 +++++++ src/gui/painting/qpainter.cpp | 34 +++++++++---------- src/gui/painting/qpainter_p.h | 1 + src/gui/painting/qpdf.cpp | 3 ++ src/opengl/qglframebufferobject.cpp | 3 ++ src/opengl/qglpaintdevice.cpp | 2 ++ src/opengl/qglpixelbuffer.cpp | 3 ++ .../platforms/cocoa/qprintengine_mac.mm | 3 ++ src/widgets/kernel/qwidget.cpp | 3 +- src/widgets/kernel/qwidget_qpa.cpp | 2 ++ 17 files changed, 73 insertions(+), 26 deletions(-) diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 7287f54e74..0efb9c2646 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -4994,12 +4994,17 @@ int QImage::metric(PaintDeviceMetric metric) const break; case PdmPhysicalDpiX: - return qRound(d->dpmx * 0.0254 * d->devicePixelRatio); + return qRound(d->dpmx * 0.0254); break; case PdmPhysicalDpiY: - return qRound(d->dpmy * 0.0254 * d->devicePixelRatio); + return qRound(d->dpmy * 0.0254); break; + + case PdmDevicePixelRatio: + return d->devicePixelRatio; + break; + default: qWarning("QImage::metric(): Unhandled metric type %d", metric); break; diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp index f6de22851d..1071ed754b 100644 --- a/src/gui/image/qpicture.cpp +++ b/src/gui/image/qpicture.cpp @@ -956,6 +956,9 @@ int QPicture::metric(PaintDeviceMetric m) const case PdmDepth: val = 24; break; + case PdmDevicePixelRatio: + val = 1; + break; default: val = 0; qWarning("QPicture::metric: Invalid metric command"); diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp index 75b7a4ba06..4c1b30a6d8 100644 --- a/src/gui/image/qpixmap_blitter.cpp +++ b/src/gui/image/qpixmap_blitter.cpp @@ -120,6 +120,8 @@ int QBlittablePlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) con case QPaintDevice::PdmDpiY: // fall-through case QPaintDevice::PdmPhysicalDpiY: return qt_defaultDpiY(); + case QPaintDevice::PdmDevicePixelRatio: + return 1; default: qWarning("QRasterPlatformPixmap::metric(): Unhandled metric type %d", metric); break; diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index 302945dbf8..c80ccd8b1d 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -278,11 +278,13 @@ int QRasterPlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) const case QPaintDevice::PdmDpiX: return qt_defaultDpiX(); case QPaintDevice::PdmPhysicalDpiX: - return qt_defaultDpiX() * image.devicePixelRatio(); + return qt_defaultDpiX(); case QPaintDevice::PdmDpiY: return qt_defaultDpiX(); case QPaintDevice::PdmPhysicalDpiY: - return qt_defaultDpiY() * image.devicePixelRatio(); + return qt_defaultDpiY(); + case QPaintDevice::PdmDevicePixelRatio: + return image.devicePixelRatio(); default: qWarning("QRasterPlatformPixmap::metric(): Unhandled metric type %d", metric); break; diff --git a/src/gui/opengl/qopenglpaintdevice.cpp b/src/gui/opengl/qopenglpaintdevice.cpp index d55d6a91bf..1e427c9dd6 100644 --- a/src/gui/opengl/qopenglpaintdevice.cpp +++ b/src/gui/opengl/qopenglpaintdevice.cpp @@ -282,9 +282,11 @@ int QOpenGLPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const case PdmDpiY: return qRound(d_ptr->dpmy * 0.0254); case PdmPhysicalDpiX: - return qRound(d_ptr->dpmx * 0.0254 * d_ptr->devicePixelRatio); + return qRound(d_ptr->dpmx * 0.0254); case PdmPhysicalDpiY: - return qRound(d_ptr->dpmy * 0.0254 * d_ptr->devicePixelRatio); + return qRound(d_ptr->dpmy * 0.0254); + case PdmDevicePixelRatio: + return 1; default: qWarning("QOpenGLPaintDevice::metric() - metric %d not known", metric); return 0; diff --git a/src/gui/painting/qpaintdevice.cpp b/src/gui/painting/qpaintdevice.cpp index 6ac288607d..81d2063039 100644 --- a/src/gui/painting/qpaintdevice.cpp +++ b/src/gui/painting/qpaintdevice.cpp @@ -95,6 +95,8 @@ int QPaintDevice::metric(PaintDeviceMetric m) const } else if (m == PdmNumColors) { // FIXME: does this need to be a real value? return 256; + } else if (m == PdmDevicePixelRatio) { + return 1; } else { qDebug("Unrecognised metric %d!",m); return 0; diff --git a/src/gui/painting/qpaintdevice.h b/src/gui/painting/qpaintdevice.h index 1529b701cf..bb66f32b7f 100644 --- a/src/gui/painting/qpaintdevice.h +++ b/src/gui/painting/qpaintdevice.h @@ -65,7 +65,8 @@ public: PdmDpiX, PdmDpiY, PdmPhysicalDpiX, - PdmPhysicalDpiY + PdmPhysicalDpiY, + PdmDevicePixelRatio }; virtual ~QPaintDevice(); @@ -82,6 +83,7 @@ public: int logicalDpiY() const { return metric(PdmDpiY); } int physicalDpiX() const { return metric(PdmPhysicalDpiX); } int physicalDpiY() const { return metric(PdmPhysicalDpiY); } + int devicePixelRatio() const { return metric(PdmDevicePixelRatio); } int colorCount() const { return metric(PdmNumColors); } int depth() const { return metric(PdmDepth); } diff --git a/src/gui/painting/qpaintdevice.qdoc b/src/gui/painting/qpaintdevice.qdoc index 7397dc7fc2..993b23850e 100644 --- a/src/gui/painting/qpaintdevice.qdoc +++ b/src/gui/painting/qpaintdevice.qdoc @@ -114,6 +114,10 @@ \value PdmPhysicalDpiY The vertical resolution of the device in dots per inch. See also physicalDpiY(). + \value PdmDevicePixelRatio The device pixel ratio for device. Common + values are 1 for normal-dpi displays and 2 for high-dpi "retina" + displays. + \sa metric() */ @@ -273,3 +277,12 @@ \sa physicalDpiX(), logicalDpiY() */ + +/*! + \fn int QPaintDevice::devicePixelRatio() const + + Returns the device pixel ratio for device. + + Common values are 1 for normal-dpi displays and 2 for high-dpi + "retina" displays. +*/ diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index be77fffc7c..e42b70427c 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -225,17 +225,24 @@ QTransform QPainterPrivate::viewTransform() const return QTransform(); } +int QPainterPrivate::effectiveDevicePixelRatio() const +{ + // Limited feature introduction for Qt 5.0.0, remove ifdef in a later release. +#ifdef Q_OS_MAC + // Special cases for devices that does not support PdmDevicePixelRatio go here: + if (device->devType() == QInternal::Printer) + return 1; + + return qMax(1, device->metric(QPaintDevice::PdmDevicePixelRatio)); +#else + return 1; +#endif +} + QTransform QPainterPrivate::hidpiScaleTransform() const { -#ifdef Q_OS_MAC - // Limited feature introduction for Qt 5.0.0, remove ifdef in a later release. - if (device->devType() == QInternal::Printer || device->physicalDpiX() == 0 || device->logicalDpiX() == 0) - return QTransform(); - const qreal deviceScale = (device->physicalDpiX() / device->logicalDpiX()); - if (deviceScale > 1.0) - return QTransform::fromScale(deviceScale, deviceScale); -#endif - return QTransform(); + int devicePixelRatio = effectiveDevicePixelRatio(); + return QTransform::fromScale(devicePixelRatio, devicePixelRatio); } /* @@ -1837,14 +1844,7 @@ bool QPainter::begin(QPaintDevice *pd) Q_ASSERT(d->engine->isActive()); -#ifdef Q_OS_MAC - // Limited feature introduction for Qt 5.0.0, remove ifdef in a later release. - const bool isHighDpi = (pd->devType() == QInternal::Printer || d->device->physicalDpiX() == 0 || d->device->logicalDpiX() == 0) ? - false : (d->device->physicalDpiX() / d->device->logicalDpiX() > 1); -#else - const bool isHighDpi = false; -#endif - if (!d->state->redirectionMatrix.isIdentity() || isHighDpi) + if (!d->state->redirectionMatrix.isIdentity() || d->effectiveDevicePixelRatio() > 1) d->updateMatrix(); Q_ASSERT(d->engine->isActive()); diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h index 36a73866e7..04772b3ec9 100644 --- a/src/gui/painting/qpainter_p.h +++ b/src/gui/painting/qpainter_p.h @@ -249,6 +249,7 @@ public: } QTransform viewTransform() const; + int effectiveDevicePixelRatio() const; QTransform hidpiScaleTransform() const; static bool attachPainterPrivate(QPainter *q, QPaintDevice *pdev); void detachPainterPrivate(QPainter *q); diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index eed64180e5..5d9a743dac 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -1455,6 +1455,9 @@ int QPdfEngine::metric(QPaintDevice::PaintDeviceMetric metricType) const case QPaintDevice::PdmDepth: val = 32; break; + case QPaintDevice::PdmDevicePixelRatio: + val = 1; + break; default: qWarning("QPdfWriter::metric: Invalid metric command"); return 0; diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index 15880108f3..1c802cabcb 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -1232,6 +1232,9 @@ int QGLFramebufferObject::metric(PaintDeviceMetric metric) const case PdmPhysicalDpiY: return qRound(dpmy * 0.0254); + case QPaintDevice::PdmDevicePixelRatio: + return 1; + default: qWarning("QGLFramebufferObject::metric(), Unhandled metric type: %d.\n", metric); break; diff --git a/src/opengl/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp index a3779218d2..ef9bdba070 100644 --- a/src/opengl/qglpaintdevice.cpp +++ b/src/opengl/qglpaintdevice.cpp @@ -67,6 +67,8 @@ int QGLPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const const QGLFormat f = format(); return f.redBufferSize() + f.greenBufferSize() + f.blueBufferSize() + f.alphaBufferSize(); } + case PdmDevicePixelRatio: + return 1; default: qWarning("QGLPaintDevice::metric() - metric %d not known", metric); return 0; diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index e514e34552..e5e7de0fff 100644 --- a/src/opengl/qglpixelbuffer.cpp +++ b/src/opengl/qglpixelbuffer.cpp @@ -462,6 +462,9 @@ int QGLPixelBuffer::metric(PaintDeviceMetric metric) const case PdmPhysicalDpiY: return qRound(dpmy * 0.0254); + case QPaintDevice::PdmDevicePixelRatio: + return 1; + default: qWarning("QGLPixelBuffer::metric(), Unhandled metric type: %d\n", metric); break; diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index 4748005f1a..2dedf99582 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -364,6 +364,9 @@ int QMacPrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const case QPaintDevice::PdmDepth: val = 24; break; + case QPaintDevice::PdmDevicePixelRatio: + val = 1; + break; default: val = 0; qWarning("QPrinter::metric: Invalid metric command"); diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index edd2329df8..90cfb3446f 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1811,9 +1811,8 @@ void QWidgetPrivate::setSystemClip(QPaintDevice *paintDevice, const QRegion ® // it has been tested. QPaintEngine *paintEngine = paintDevice->paintEngine(); #ifdef Q_OS_MAC - const qreal devicePixelRatio = (paintDevice->physicalDpiX() == 0 || paintDevice->logicalDpiX() == 0) ? - 1.0 : (paintDevice->physicalDpiX() / paintDevice->logicalDpiX()); QTransform scaleTransform; + const qreal devicePixelRatio = paintDevice->devicePixelRatio(); scaleTransform.scale(devicePixelRatio, devicePixelRatio); paintEngine->d_func()->systemClip = scaleTransform.map(region); #else diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp index 1374d25cef..8c31d4ad26 100644 --- a/src/widgets/kernel/qwidget_qpa.cpp +++ b/src/widgets/kernel/qwidget_qpa.cpp @@ -836,6 +836,8 @@ int QWidget::metric(PaintDeviceMetric m) const return qRound(screen->physicalDotsPerInchX()); } else if (m == PdmPhysicalDpiY) { return qRound(screen->physicalDotsPerInchY()); + } else if (m == PdmDevicePixelRatio) { + return screen->devicePixelRatio(); } else { val = QPaintDevice::metric(m);// XXX }