diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 8998db301d2..5a2af0dbb01 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -4323,6 +4323,12 @@ int QImage::metric(PaintDeviceMetric metric) const return d->devicePixelRatio * QPaintDevice::devicePixelRatioFScale(); break; + case PdmDevicePixelRatioF_EncodedA: + Q_FALLTHROUGH(); + case PdmDevicePixelRatioF_EncodedB: + return QPaintDevice::encodeMetricF(metric, d->devicePixelRatio); + break; + default: qWarning("QImage::metric(): Unhandled metric type %d", metric); break; diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp index 41563bf3802..925ac37be45 100644 --- a/src/gui/image/qpixmap_blitter.cpp +++ b/src/gui/image/qpixmap_blitter.cpp @@ -88,6 +88,10 @@ int QBlittablePlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) con return devicePixelRatio(); case QPaintDevice::PdmDevicePixelRatioScaled: return devicePixelRatio() * QPaintDevice::devicePixelRatioFScale(); + case QPaintDevice::PdmDevicePixelRatioF_EncodedA: + Q_FALLTHROUGH(); + case QPaintDevice::PdmDevicePixelRatioF_EncodedB: + return QPaintDevice::encodeMetricF(metric, devicePixelRatio()); 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 6e10bdd562f..a261bb7b5c7 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -253,6 +253,10 @@ int QRasterPlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) const return image.devicePixelRatio(); case QPaintDevice::PdmDevicePixelRatioScaled: return image.devicePixelRatio() * QPaintDevice::devicePixelRatioFScale(); + case QPaintDevice::PdmDevicePixelRatioF_EncodedA: + Q_FALLTHROUGH(); + case QPaintDevice::PdmDevicePixelRatioF_EncodedB: + return QPaintDevice::encodeMetricF(metric, image.devicePixelRatio()); default: qWarning("QRasterPlatformPixmap::metric(): Unhandled metric type %d", metric); diff --git a/src/gui/kernel/qpaintdevicewindow.cpp b/src/gui/kernel/qpaintdevicewindow.cpp index 9e8c6ae5a85..8531aeed51d 100644 --- a/src/gui/kernel/qpaintdevicewindow.cpp +++ b/src/gui/kernel/qpaintdevicewindow.cpp @@ -136,6 +136,11 @@ int QPaintDeviceWindow::metric(PaintDeviceMetric metric) const case PdmDevicePixelRatioScaled: return int(QWindow::devicePixelRatio() * devicePixelRatioFScale()); break; + case PdmDevicePixelRatioF_EncodedA: + Q_FALLTHROUGH(); + case PdmDevicePixelRatioF_EncodedB: + return QPaintDevice::encodeMetricF(metric, QWindow::devicePixelRatio()); + break; default: break; } diff --git a/src/gui/painting/qpaintdevice.cpp b/src/gui/painting/qpaintdevice.cpp index 14e2d7cd8ea..de21901e239 100644 --- a/src/gui/painting/qpaintdevice.cpp +++ b/src/gui/painting/qpaintdevice.cpp @@ -17,6 +17,39 @@ QPaintDevice::~QPaintDevice() "painted"); } +/*! + \internal +*/ +// ### Qt 7: Replace this workaround mechanism: virtual devicePixelRatio() and virtual metricF() +inline double QPaintDevice::getDecodedMetricF(PaintDeviceMetric metricA, PaintDeviceMetric metricB) const +{ + qint32 buf[2]; + // The Encoded metric enum values come in pairs of one odd and one even value. + // We map those to the 0 and 1 indexes of buf by taking just the least significant bit. + // Same mapping here as in the encodeMetricF() function, to ensure correct order. + buf[metricA & 1] = metric(metricA); + buf[metricB & 1] = metric(metricB); + double res; + memcpy(&res, buf, sizeof(res)); + return res; +} + +qreal QPaintDevice::devicePixelRatio() const +{ + Q_STATIC_ASSERT((PdmDevicePixelRatioF_EncodedA & 1) != (PdmDevicePixelRatioF_EncodedB & 1)); + double res; + int scaledDpr = metric(PdmDevicePixelRatioScaled); + if (scaledDpr == int(devicePixelRatioFScale())) { + res = 1; // Shortcut for common case + } else if (scaledDpr == 2 * int(devicePixelRatioFScale())) { + res = 2; // Shortcut for common case + } else { + res = getDecodedMetricF(PdmDevicePixelRatioF_EncodedA, PdmDevicePixelRatioF_EncodedB); + if (res <= 0) // These metrics not implemented, fall back to PdmDevicePixelRatioScaled + res = scaledDpr / devicePixelRatioFScale(); + } + return res; +} /*! \internal @@ -64,6 +97,8 @@ int QPaintDevice::metric(PaintDeviceMetric m) const return 256; } else if (m == PdmDevicePixelRatio) { return 1; + } else if (m == PdmDevicePixelRatioF_EncodedA || m == PdmDevicePixelRatioF_EncodedB) { + return 0; } else { qDebug("Unrecognised metric %d!",m); return 0; diff --git a/src/gui/painting/qpaintdevice.h b/src/gui/painting/qpaintdevice.h index ceccac5e7ef..c39d8a059db 100644 --- a/src/gui/painting/qpaintdevice.h +++ b/src/gui/painting/qpaintdevice.h @@ -29,7 +29,9 @@ public: PdmPhysicalDpiX, PdmPhysicalDpiY, PdmDevicePixelRatio, - PdmDevicePixelRatioScaled + PdmDevicePixelRatioScaled, + PdmDevicePixelRatioF_EncodedA, + PdmDevicePixelRatioF_EncodedB }; virtual ~QPaintDevice(); @@ -46,18 +48,20 @@ public: int logicalDpiY() const { return metric(PdmDpiY); } int physicalDpiX() const { return metric(PdmPhysicalDpiX); } int physicalDpiY() const { return metric(PdmPhysicalDpiY); } - qreal devicePixelRatio() const { return metric(PdmDevicePixelRatioScaled) / devicePixelRatioFScale(); } + qreal devicePixelRatio() const; qreal devicePixelRatioF() const { return devicePixelRatio(); } int colorCount() const { return metric(PdmNumColors); } int depth() const { return metric(PdmDepth); } static inline qreal devicePixelRatioFScale() { return 0x10000; } + static inline int encodeMetricF(PaintDeviceMetric metric, double value); protected: QPaintDevice() noexcept; virtual int metric(PaintDeviceMetric metric) const; virtual void initPainter(QPainter *painter) const; virtual QPaintDevice *redirected(QPoint *offset) const; virtual QPainter *sharedPainter() const; + double getDecodedMetricF(PaintDeviceMetric metricA, PaintDeviceMetric metricB) const; ushort painters; // refcount private: @@ -80,6 +84,14 @@ inline int QPaintDevice::devType() const inline bool QPaintDevice::paintingActive() const { return painters != 0; } +inline int QPaintDevice::encodeMetricF(PaintDeviceMetric metric, double value) +{ + qint32 buf[2]; + Q_STATIC_ASSERT(sizeof(buf) == sizeof(double)); + memcpy(buf, &value, sizeof(buf)); + return buf[metric & 1]; +} + QT_END_NAMESPACE #endif // QPAINTDEVICE_H diff --git a/src/gui/painting/qpaintdevice.qdoc b/src/gui/painting/qpaintdevice.qdoc index d63fdcb92ba..9b9a6facb80 100644 --- a/src/gui/painting/qpaintdevice.qdoc +++ b/src/gui/painting/qpaintdevice.qdoc @@ -99,6 +99,14 @@ The constant scaling factor used is devicePixelRatioFScale(). This enum value has been introduced in Qt 5.6. + \value [since 6.8] PdmDevicePixelRatioF_EncodedA This enum item, together with the + corresponding \c B item, are used together for the device pixel ratio of the device, as an + encoded \c double floating point value. A QPaintDevice subclass that supports \e fractional DPR + values should implement support for these two enum items in its override of the metric() + function. The return value is expected to be the result of the encodeMetricF() function. + + \value [since 6.8] PdmDevicePixelRatioF_EncodedB See PdmDevicePixelRatioF_EncodedA. + \sa metric(), devicePixelRatio() */ @@ -288,3 +296,15 @@ \since 5.6 */ + +/*! + \fn int QPaintDevice::encodeMetricF(PaintDeviceMetric metric, double value) + + \internal + + Returns \a value encoded for the metric \a metric. Subclasses implementing metric() should use + this function to encode \value as an integer return value when the query metric specifies an + encoded floating-point value. + + \since 6.8 +*/ diff --git a/src/opengl/qopenglpaintdevice.cpp b/src/opengl/qopenglpaintdevice.cpp index fbc54c46fb9..aaee7f18fe0 100644 --- a/src/opengl/qopenglpaintdevice.cpp +++ b/src/opengl/qopenglpaintdevice.cpp @@ -247,6 +247,10 @@ int QOpenGLPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const return d_ptr->devicePixelRatio; case PdmDevicePixelRatioScaled: return d_ptr->devicePixelRatio * QPaintDevice::devicePixelRatioFScale(); + case PdmDevicePixelRatioF_EncodedA: + Q_FALLTHROUGH(); + case PdmDevicePixelRatioF_EncodedB: + return QPaintDevice::encodeMetricF(metric, d_ptr->devicePixelRatio); default: qWarning("QOpenGLPaintDevice::metric() - metric %d not known", metric); diff --git a/src/openglwidgets/qopenglwidget.cpp b/src/openglwidgets/qopenglwidget.cpp index 4a0bf7f492e..cf70e169903 100644 --- a/src/openglwidgets/qopenglwidget.cpp +++ b/src/openglwidgets/qopenglwidget.cpp @@ -1640,6 +1640,10 @@ int QOpenGLWidget::metric(QPaintDevice::PaintDeviceMetric metric) const return QWidget::metric(metric); case PdmDevicePixelRatioScaled: return QWidget::metric(metric); + case PdmDevicePixelRatioF_EncodedA: + Q_FALLTHROUGH(); + case PdmDevicePixelRatioF_EncodedB: + return QWidget::metric(metric); default: qWarning("QOpenGLWidget::metric(): unknown metric %d", metric); return 0; diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp index 2866c68de26..71a59cb08f5 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp @@ -84,10 +84,12 @@ QT_WARNING_POP case QPaintDevice::PdmDevicePixelRatio: return 1; case QPaintDevice::PdmDevicePixelRatioScaled: - return qRound(devicePixelRatioFScale()); + return int(devicePixelRatioFScale()); case QPaintDevice::PdmWidthMM: case QPaintDevice::PdmHeightMM: break; + default: + break; } return -1; diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index dfc69c7d93b..365323933b5 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -12956,6 +12956,10 @@ int QWidget::metric(PaintDeviceMetric m) const return resolveDevicePixelRatio(); case PdmDevicePixelRatioScaled: return QPaintDevice::devicePixelRatioFScale() * resolveDevicePixelRatio(); + case PdmDevicePixelRatioF_EncodedA: + Q_FALLTHROUGH(); + case PdmDevicePixelRatioF_EncodedB: + return QPaintDevice::encodeMetricF(m, resolveDevicePixelRatio()); default: break; }