diff options
author | Morten Johan Sørvig <morten.sorvig@digia.com> | 2012-11-20 11:34:52 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2012-12-01 08:33:20 +0100 |
commit | 5e61bbe586519c3d9bc636153d32e810da4e59a3 (patch) | |
tree | 67d67ef644be72ee5b3d685c9a22538d7ec1e01d /src/gui/image | |
parent | c8dc41bacdc30026cb79d0d6c72255312084bfe3 (diff) |
Basic high-dpi "retina" support for Qt 5.
Bring Qt 5 on par with Qt 4, prepare for more comprehensive
support later on.
Introduce device independent pixels (dips), device pixels,
and devicePixelRatio. Add high-dpi support to QPainter,
QGLWidget, the cocoa platform plugin, mac and fusion styles.
Dips are similar to CSS pixels, Apple points and
Android density-independent pixels. Device pixels
are pixels in the backing store/physical pixels on screen.
devicePixelRatio is the ratio between them, which is
1.0 on standard displays and 2.0 on "retina" displays.
New API:
QImage::devicePixelRatio() and setDevicePixelRatio()
QPixmap::devicePixelRatio() and setDevicePixelRatio()
QWindow::devicePixelRatio()
QScreen::devicePixelRatio()
QGuiApplicaiton::devicePixelRatio()
Change-Id: If98c3ca9bfdf0e1bdbcf7574cd5b912c9ff63856
Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>
Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
Diffstat (limited to 'src/gui/image')
-rw-r--r-- | src/gui/image/qimage.cpp | 67 | ||||
-rw-r--r-- | src/gui/image/qimage.h | 3 | ||||
-rw-r--r-- | src/gui/image/qimage_p.h | 7 | ||||
-rw-r--r-- | src/gui/image/qimagereader.cpp | 5 | ||||
-rw-r--r-- | src/gui/image/qpixmap.cpp | 44 | ||||
-rw-r--r-- | src/gui/image/qpixmap.h | 3 | ||||
-rw-r--r-- | src/gui/image/qpixmap_blitter.cpp | 10 | ||||
-rw-r--r-- | src/gui/image/qpixmap_blitter_p.h | 3 | ||||
-rw-r--r-- | src/gui/image/qpixmap_raster.cpp | 19 | ||||
-rw-r--r-- | src/gui/image/qpixmap_raster_p.h | 3 | ||||
-rw-r--r-- | src/gui/image/qplatformpixmap.h | 3 |
11 files changed, 156 insertions, 11 deletions
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 9da360bc26..c40ca1545a 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -95,10 +95,12 @@ static QImage rotated270(const QImage &src); QBasicAtomicInt qimage_serial_number = Q_BASIC_ATOMIC_INITIALIZER(1); QImageData::QImageData() - : ref(0), width(0), height(0), depth(0), nbytes(0), data(0), + : ref(0), width(0), height(0), depth(0), nbytes(0), devicePixelRatio(1.0), data(0), format(QImage::Format_ARGB32), bytes_per_line(0), ser_no(qimage_serial_number.fetchAndAddRelaxed(1)), detach_no(0), + ldpmx(qt_defaultDpiX() * 100 / qreal(2.54)), + ldpmy(qt_defaultDpiY() * 100 / qreal(2.54)), dpmx(qt_defaultDpiX() * 100 / qreal(2.54)), dpmy(qt_defaultDpiY() * 100 / qreal(2.54)), offset(0, 0), own_data(true), ro_data(false), has_alpha_clut(false), @@ -1216,6 +1218,7 @@ QImage QImage::copy(const QRect& r) const image.d->dpmx = dotsPerMeterX(); image.d->dpmy = dotsPerMeterY(); + image.d->devicePixelRatio = devicePixelRatio(); image.d->offset = offset(); image.d->has_alpha_clut = d->has_alpha_clut; image.d->text = d->text; @@ -1370,6 +1373,52 @@ QVector<QRgb> QImage::colorTable() const } /*! + Returns the device pixel ratio for the image. This is the + ratio between image pixels and device-independent pixels. + + Use this function when calculating layout geometry based on + the image size: QSize layoutSize = image.size() / image.devicePixelRatio() + + The default value is 1.0. + + \sa setDevicePixelRatio() +*/ +qreal QImage::devicePixelRatio() const +{ + if (!d) + return 1.0; + return d->devicePixelRatio; +} + +/*! + Sets the the device pixel ratio for the image. This is the + ratio between image pixels and device-independent pixels. + + The default value is 1.0. Setting it to something else has + two effects: + + QPainters that are opened on the image will be scaled. For + example, painting on a 200x200 image if with a ratio of 2.0 + will result in effective (device-independent) painting bounds + of 100x100. + + Code paths in Qt that calculate layout geometry based on the + image size will take the ratio into account: + QSize layoutSize = image.size() / image.devicePixelRatio() + The net effect of this is that the image is displayed as + high-dpi image rather than a large image. + + \sa devicePixelRatio() +*/ +void QImage::setDevicePixelRatio(qreal scaleFactor) +{ + if (!d) + return; + detach(); + d->devicePixelRatio = scaleFactor; +} + +/*! \since 4.6 Returns the number of bytes occupied by the image data. @@ -3359,6 +3408,7 @@ QImage QImage::convertToFormat(Format format, Qt::ImageConversionFlags flags) co image.setDotsPerMeterY(dotsPerMeterY()); image.setDotsPerMeterX(dotsPerMeterX()); + image.setDevicePixelRatio(devicePixelRatio()); image.d->text = d->text; @@ -3479,6 +3529,7 @@ QImage QImage::convertToFormat(Format format, const QVector<QRgb> &colorTable, Q QImage image(d->width, d->height, format); QIMAGE_SANITYCHECK_MEMORY(image); + image.setDevicePixelRatio(devicePixelRatio()); image.d->text = d->text; @@ -4932,17 +4983,20 @@ int QImage::metric(PaintDeviceMetric metric) const return d->depth; case PdmDpiX: - return qRound(d->dpmx * 0.0254); + return qRound(d->ldpmx * 0.0254); + break; case PdmDpiY: - return qRound(d->dpmy * 0.0254); + return qRound(d->ldpmy * 0.0254); + break; case PdmPhysicalDpiX: - return qRound(d->dpmx * 0.0254); + return qRound(d->dpmx * 0.0254 * d->devicePixelRatio); + break; case PdmPhysicalDpiY: - return qRound(d->dpmy * 0.0254); - + return qRound(d->dpmy * 0.0254 * d->devicePixelRatio); + break; default: qWarning("QImage::metric(): Unhandled metric type %d", metric); break; @@ -5641,6 +5695,7 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode dImage.d->dpmx = dotsPerMeterX(); dImage.d->dpmy = dotsPerMeterY(); + dImage.d->devicePixelRatio = devicePixelRatio(); switch (bpp) { // initizialize the data diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 0356c1cab1..304d54a378 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -211,6 +211,9 @@ public: QVector<QRgb> colorTable() const; void setColorTable(const QVector<QRgb> colors); + qreal devicePixelRatio() const; + void setDevicePixelRatio(qreal scaleFactor); + void fill(uint pixel); void fill(const QColor &color); void fill(Qt::GlobalColor color); diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h index 74a79a8425..2bb989c03b 100644 --- a/src/gui/image/qimage_p.h +++ b/src/gui/image/qimage_p.h @@ -74,6 +74,7 @@ struct Q_GUI_EXPORT QImageData { // internal image data int height; int depth; int nbytes; // number of bytes data + qreal devicePixelRatio; QVector<QRgb> colortable; uchar *data; QImage::Format format; @@ -81,8 +82,10 @@ struct Q_GUI_EXPORT QImageData { // internal image data int ser_no; // serial number int detach_no; - qreal dpmx; // dots per meter X (or 0) - qreal dpmy; // dots per meter Y (or 0) + qreal ldpmx; // logical dots per meter X (or 0) + qreal ldpmy; // logical dots per meter Y (or 0) + qreal dpmx; // device dots per meter X (or 0) + qreal dpmy; // device dots per meter Y (or 0) QPoint offset; // offset in pixels uint own_data : 1; diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index 3b0fe33d21..a27a7710f6 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -1234,6 +1234,11 @@ bool QImageReader::read(QImage *image) } } + // successful read; check for "@2x" file name suffix and set device pixel ratio. + if (QFileInfo(fileName()).baseName().endsWith("@2x")) { + image->setDevicePixelRatio(2.0); + } + return true; } diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 113369fd75..8782119b7a 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -638,6 +638,50 @@ void QPixmap::setMask(const QBitmap &mask) data->fromImage(image, Qt::AutoColor); } +/*! + Returns the device pixel ratio for the pixmap. This is the + ratio between pixmap pixels and device-independent pixels. + + Use this function when calculating layout geometry based on + the pixmap size: QSize layoutSize = image.size() / image.devicePixelRatio() + + The default value is 1.0. + + \sa setDevicePixelRatio() +*/ +qreal QPixmap::devicePixelRatio() const +{ + if (!data) + return qreal(1.0); + return data->devicePixelRatio(); +} + +/*! + Sets the the device pixel ratio for the pixmap. This is the + ratio between image pixels and device-independent pixels. + + The default value is 1.0. Setting it to something else has + two effects: + + QPainters that are opened on the pixmap will be scaled. For + example, painting on a 200x200 image if with a ratio of 2.0 + will result in effective (device-independent) painting bounds + of 100x100. + + Code paths in Qt that calculate layout geometry based on the + pixmap size will take the ratio into account: + QSize layoutSize = pixmap.size() / pixmap.devicePixelRatio() + The net effect of this is that the pixmap is displayed as + high-dpi pixmap rather than a large pixmap. + + \sa devicePixelRatio() +*/ +void QPixmap::setDevicePixelRatio(qreal scaleFactor) +{ + detach(); + data->setDevicePixelRatio(scaleFactor); +} + #ifndef QT_NO_IMAGE_HEURISTIC_MASK /*! Creates and returns a heuristic mask for this pixmap. diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h index 5f5c28def2..af141cd325 100644 --- a/src/gui/image/qpixmap.h +++ b/src/gui/image/qpixmap.h @@ -102,6 +102,9 @@ public: QBitmap mask() const; void setMask(const QBitmap &); + qreal devicePixelRatio() const; + void setDevicePixelRatio(qreal scaleFactor); + bool hasAlpha() const; bool hasAlphaChannel() const; diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp index 2bc3a67509..2a4576e8a8 100644 --- a/src/gui/image/qpixmap_blitter.cpp +++ b/src/gui/image/qpixmap_blitter.cpp @@ -195,6 +195,16 @@ void QBlittablePlatformPixmap::fromImage(const QImage &image, } } +qreal QBlittablePlatformPixmap::devicePixelRatio() const +{ + return m_devicePixelRatio; +} + +void QBlittablePlatformPixmap::setDevicePixelRatio(qreal scaleFactor) +{ + m_devicePixelRatio = scaleFactor; +} + QPaintEngine *QBlittablePlatformPixmap::paintEngine() const { if (!m_engine) { diff --git a/src/gui/image/qpixmap_blitter_p.h b/src/gui/image/qpixmap_blitter_p.h index c4e0e0a4cc..a0e5f55f69 100644 --- a/src/gui/image/qpixmap_blitter_p.h +++ b/src/gui/image/qpixmap_blitter_p.h @@ -66,6 +66,8 @@ public: QImage toImage() const; bool hasAlphaChannel() const; void fromImage(const QImage &image, Qt::ImageConversionFlags flags); + qreal devicePixelRatio() const; + void setDevicePixelRatio(qreal scaleFactor); QPaintEngine *paintEngine() const; @@ -89,6 +91,7 @@ protected: QScopedPointer<QBlitterPaintEngine> m_engine; QScopedPointer<QBlittable> m_blittable; bool m_alpha; + qreal m_devicePixelRatio; #ifdef QT_BLITTER_RASTEROVERLAY QImage *m_rasterOverlay; diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index d30c6eaae7..5c188f0362 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -272,12 +272,14 @@ int QRasterPlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) const return d->colortable.size(); case QPaintDevice::PdmDepth: return this->d; - case QPaintDevice::PdmDpiX: // fall-through + case QPaintDevice::PdmDpiX: + return qt_defaultDpiX(); case QPaintDevice::PdmPhysicalDpiX: + return qt_defaultDpiX() * image.devicePixelRatio(); + case QPaintDevice::PdmDpiY: return qt_defaultDpiX(); - case QPaintDevice::PdmDpiY: // fall-through case QPaintDevice::PdmPhysicalDpiY: - return qt_defaultDpiY(); + return qt_defaultDpiY() * image.devicePixelRatio(); default: qWarning("QRasterPlatformPixmap::metric(): Unhandled metric type %d", metric); break; @@ -350,6 +352,7 @@ void QRasterPlatformPixmap::createPixmapForImage(QImage &sourceImage, Qt::ImageC } is_null = (w <= 0 || h <= 0); + image.d->devicePixelRatio = sourceImage.devicePixelRatio(); setSerialNumber(image.cacheKey() >> 32); } @@ -358,4 +361,14 @@ QImage* QRasterPlatformPixmap::buffer() return ℑ } +qreal QRasterPlatformPixmap::devicePixelRatio() const +{ + return image.devicePixelRatio(); +} + +void QRasterPlatformPixmap::setDevicePixelRatio(qreal scaleFactor) +{ + image.setDevicePixelRatio(scaleFactor); +} + QT_END_NAMESPACE diff --git a/src/gui/image/qpixmap_raster_p.h b/src/gui/image/qpixmap_raster_p.h index 7bc007f67f..e560577e17 100644 --- a/src/gui/image/qpixmap_raster_p.h +++ b/src/gui/image/qpixmap_raster_p.h @@ -79,6 +79,9 @@ public: QImage toImage(const QRect &rect) const; QPaintEngine* paintEngine() const; QImage* buffer(); + qreal devicePixelRatio() const; + void setDevicePixelRatio(qreal scaleFactor); + protected: int metric(QPaintDevice::PaintDeviceMetric metric) const; diff --git a/src/gui/image/qplatformpixmap.h b/src/gui/image/qplatformpixmap.h index 9d28721f99..af3abecaf8 100644 --- a/src/gui/image/qplatformpixmap.h +++ b/src/gui/image/qplatformpixmap.h @@ -108,6 +108,9 @@ public: inline PixelType pixelType() const { return type; } inline ClassId classId() const { return static_cast<ClassId>(id); } + virtual qreal devicePixelRatio() const = 0; + virtual void setDevicePixelRatio(qreal scaleFactor) = 0; + virtual QImage* buffer(); inline int width() const { return w; } |