summaryrefslogtreecommitdiffstats
path: root/src/gui/image
diff options
context:
space:
mode:
authorMorten Johan Sørvig <morten.sorvig@digia.com>2012-11-20 11:34:52 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-12-01 08:33:20 +0100
commit5e61bbe586519c3d9bc636153d32e810da4e59a3 (patch)
tree67d67ef644be72ee5b3d685c9a22538d7ec1e01d /src/gui/image
parentc8dc41bacdc30026cb79d0d6c72255312084bfe3 (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.cpp67
-rw-r--r--src/gui/image/qimage.h3
-rw-r--r--src/gui/image/qimage_p.h7
-rw-r--r--src/gui/image/qimagereader.cpp5
-rw-r--r--src/gui/image/qpixmap.cpp44
-rw-r--r--src/gui/image/qpixmap.h3
-rw-r--r--src/gui/image/qpixmap_blitter.cpp10
-rw-r--r--src/gui/image/qpixmap_blitter_p.h3
-rw-r--r--src/gui/image/qpixmap_raster.cpp19
-rw-r--r--src/gui/image/qpixmap_raster_p.h3
-rw-r--r--src/gui/image/qplatformpixmap.h3
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 &image;
}
+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; }