summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-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
-rw-r--r--src/gui/kernel/qguiapplication.cpp29
-rw-r--r--src/gui/kernel/qguiapplication.h1
-rw-r--r--src/gui/kernel/qplatformscreen.cpp12
-rw-r--r--src/gui/kernel/qplatformscreen.h1
-rw-r--r--src/gui/kernel/qplatformwindow.cpp12
-rw-r--r--src/gui/kernel/qplatformwindow.h2
-rw-r--r--src/gui/kernel/qscreen.cpp14
-rw-r--r--src/gui/kernel/qscreen.h2
-rw-r--r--src/gui/kernel/qwindow.cpp18
-rw-r--r--src/gui/kernel/qwindow.h2
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp29
-rw-r--r--src/gui/painting/qpaintengineex.cpp4
-rw-r--r--src/gui/painting/qpainter.cpp48
-rw-r--r--src/gui/painting/qpainter_p.h1
25 files changed, 313 insertions, 29 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; }
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 80e13227ee..fb14490a24 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -703,7 +703,34 @@ QList<QScreen *> QGuiApplication::screens()
/*!
- Returns the top level window at the given position \a pos, if any.
+ Returns the highest screen device pixel ratio found on
+ the system. This is the ratio between physical pixels and
+ device-independent pixels.
+
+ Use this function only when you don't know which window you are targeting.
+ If you do know the target window use QWindow::devicePixelRatio() instead.
+
+ \sa QWindow::devicePixelRatio();
+ \sa QGuiApplicaiton::devicePixelRatio();
+*/
+qreal QGuiApplication::devicePixelRatio() const
+{
+ // Cache topDevicePixelRatio, iterate through the screen list once only.
+ static qreal topDevicePixelRatio = 0.0;
+ if (!qFuzzyIsNull(topDevicePixelRatio)) {
+ return topDevicePixelRatio;
+ }
+
+ topDevicePixelRatio = 1.0; // make sure we never return 0.
+ foreach (QScreen *screen, QGuiApplicationPrivate::screen_list) {
+ topDevicePixelRatio = qMax(topDevicePixelRatio, screen->devicePixelRatio());
+ }
+
+ return topDevicePixelRatio;
+}
+
+/*!
+ Returns the top level window at the given position, if any.
*/
QWindow *QGuiApplication::topLevelAt(const QPoint &pos)
{
diff --git a/src/gui/kernel/qguiapplication.h b/src/gui/kernel/qguiapplication.h
index 27ea86ec6e..7c0dbbdcde 100644
--- a/src/gui/kernel/qguiapplication.h
+++ b/src/gui/kernel/qguiapplication.h
@@ -104,6 +104,7 @@ public:
static QScreen *primaryScreen();
static QList<QScreen *> screens();
+ qreal devicePixelRatio() const;
#ifndef QT_NO_CURSOR
static QCursor *overrideCursor();
diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp
index 211a9650dc..ab2fdfa409 100644
--- a/src/gui/kernel/qplatformscreen.cpp
+++ b/src/gui/kernel/qplatformscreen.cpp
@@ -161,6 +161,18 @@ QDpi QPlatformScreen::logicalDpi() const
}
/*!
+ Reimplement this function in subclass to return the device pixel
+ ratio for the screen. This is the ratio between physical pixels
+ and device-independent pixels.
+
+ \sa QPlatformWindow::devicePixelRatio();
+*/
+qreal QPlatformScreen::devicePixelRatio() const
+{
+ return 1.0;
+}
+
+/*!
Reimplement this function in subclass to return the vertical refresh rate
of the screen, in Hz.
diff --git a/src/gui/kernel/qplatformscreen.h b/src/gui/kernel/qplatformscreen.h
index 493a1cedd0..91365b1cf0 100644
--- a/src/gui/kernel/qplatformscreen.h
+++ b/src/gui/kernel/qplatformscreen.h
@@ -98,6 +98,7 @@ public:
virtual QSizeF physicalSize() const;
virtual QDpi logicalDpi() const;
+ virtual qreal devicePixelRatio() const;
virtual qreal refreshRate() const;
diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp
index 3bf06c6ab1..25b863c9a3 100644
--- a/src/gui/kernel/qplatformwindow.cpp
+++ b/src/gui/kernel/qplatformwindow.cpp
@@ -355,6 +355,18 @@ Qt::ScreenOrientation QPlatformWindow::requestWindowOrientation(Qt::ScreenOrient
return Qt::PrimaryOrientation;
}
+/*!
+ Reimplement this function in subclass to return the device pixel ratio
+ for the window. This is the ratio between physical pixels
+ and device-independent pixels.
+
+ \sa QPlatformWindow::devicePixelRatio();
+*/
+qreal QPlatformWindow::devicePixelRatio() const
+{
+ return 1.0;
+}
+
bool QPlatformWindow::setKeyboardGrabEnabled(bool grab)
{
Q_UNUSED(grab);
diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h
index 12650d6073..607c8e4035 100644
--- a/src/gui/kernel/qplatformwindow.h
+++ b/src/gui/kernel/qplatformwindow.h
@@ -117,6 +117,8 @@ public:
virtual void handleContentOrientationChange(Qt::ScreenOrientation orientation);
virtual Qt::ScreenOrientation requestWindowOrientation(Qt::ScreenOrientation orientation);
+ virtual qreal devicePixelRatio() const;
+
virtual bool setKeyboardGrabEnabled(bool grab);
virtual bool setMouseGrabEnabled(bool grab);
diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp
index 0c30de498c..f5467ab742 100644
--- a/src/gui/kernel/qscreen.cpp
+++ b/src/gui/kernel/qscreen.cpp
@@ -214,6 +214,20 @@ qreal QScreen::logicalDotsPerInch() const
return (dpi.first + dpi.second) * qreal(0.5);
}
+/*
+ Returns the ratio between physical pixels and device-independent pixels for the screen.
+
+ Common values are 1.0 on normal displays and 2.0 on Apple retina displays.
+
+ \sa QWindow::devicePixelRatio();
+ \sa QGuiApplicaiton::devicePixelRatio();
+*/
+qreal QScreen::devicePixelRatio() const
+{
+ Q_D(const QScreen);
+ return d->platformScreen->devicePixelRatio();
+}
+
/*!
\property QScreen::physicalSize
\brief the screen's physical size (in millimeters)
diff --git a/src/gui/kernel/qscreen.h b/src/gui/kernel/qscreen.h
index 48eaad94f7..fbbd886755 100644
--- a/src/gui/kernel/qscreen.h
+++ b/src/gui/kernel/qscreen.h
@@ -109,6 +109,8 @@ public:
qreal logicalDotsPerInchY() const;
qreal logicalDotsPerInch() const;
+ qreal devicePixelRatio() const;
+
QSize availableSize() const;
QRect availableGeometry() const;
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index c24609e886..aaf2b25ad4 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -806,6 +806,24 @@ Qt::ScreenOrientation QWindow::orientation() const
}
/*!
+ Returns the ratio between physical pixels and device-independent pixels
+ for the window. This value is dependent on the screen the window is on,
+ and may change when the window is moved.
+
+ Common values are 1.0 on normal displays and 2.0 on Apple "retina" displays.
+
+ \sa QWindow::devicePixelRatio();
+ \sa QGuiApplicaiton::devicePixelRatio();
+*/
+qreal QWindow::devicePixelRatio() const
+{
+ Q_D(const QWindow);
+ if (!d->platformWindow)
+ return 1.0;
+ return d->platformWindow->devicePixelRatio();
+}
+
+/*!
\brief set the screen-occupation state of the window
The window \a state represents whether the window appears in the
diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h
index e6c9a3736f..229275d7c7 100644
--- a/src/gui/kernel/qwindow.h
+++ b/src/gui/kernel/qwindow.h
@@ -184,6 +184,8 @@ public:
void reportContentOrientationChange(Qt::ScreenOrientation orientation);
Qt::ScreenOrientation contentOrientation() const;
+ qreal devicePixelRatio() const;
+
bool requestOrientation(Qt::ScreenOrientation orientation);
Qt::ScreenOrientation orientation() const;
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 2841a583d5..46648fe297 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -1072,9 +1072,11 @@ void QRasterPaintEnginePrivate::systemStateChanged()
exDeviceRect = deviceRect;
Q_Q(QRasterPaintEngine);
- q->state()->strokeFlags |= QPaintEngine::DirtyClipRegion;
- q->state()->fillFlags |= QPaintEngine::DirtyClipRegion;
- q->state()->pixmapFlags |= QPaintEngine::DirtyClipRegion;
+ if (q->state()) {
+ q->state()->strokeFlags |= QPaintEngine::DirtyClipRegion;
+ q->state()->fillFlags |= QPaintEngine::DirtyClipRegion;
+ q->state()->pixmapFlags |= QPaintEngine::DirtyClipRegion;
+ }
}
void QRasterPaintEnginePrivate::updateMatrixData(QSpanData *spanData, const QBrush &b, const QTransform &m)
@@ -2143,9 +2145,10 @@ void QRasterPaintEngine::drawImage(const QPointF &p, const QImage &img)
Q_D(QRasterPaintEngine);
QRasterPaintEngineState *s = state();
+ qreal scale = img.devicePixelRatio();
- if (s->matrix.type() > QTransform::TxTranslate) {
- drawImage(QRectF(p.x(), p.y(), img.width(), img.height()),
+ if (scale > 1.0 || s->matrix.type() > QTransform::TxTranslate) {
+ drawImage(QRectF(p.x(), p.y(), img.width() / scale, img.height() / scale),
img,
QRectF(0, 0, img.width(), img.height()));
} else {
@@ -2349,6 +2352,22 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
return;
}
} else {
+ // Test for optimized high-dpi case: 2x source on 2x target. (Could be generalized to nX.)
+ bool sourceRect2x = r.width() * 2 == sr.width() && r.height() * 2 == sr.height();
+ bool scale2x = (s->matrix.m11() == qreal(2)) && (s->matrix.m22() == qreal(2));
+ if (s->matrix.type() == QTransform::TxScale && sourceRect2x && scale2x) {
+ SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()];
+ if (func) {
+ QPointF pt(r.x() * 2 + s->matrix.dx(), r.y() * 2 + s->matrix.dy());
+ if (!clip) {
+ d->drawImage(pt, img, func, d->deviceRect, s->intOpacity, sr.toRect());
+ return;
+ } else if (clip->hasRectClip) {
+ d->drawImage(pt, img, func, clip->clipRect, s->intOpacity, sr.toRect());
+ return;
+ }
+ }
+ }
SrcOverScaleFunc func = qScaleFunctions[d->rasterBuffer->format][img.format()];
if (func && (!clip || clip->hasRectClip)) {
func(d->rasterBuffer->buffer(), d->rasterBuffer->bytesPerLine(),
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index 113cbd8a8e..2c41ab9ff2 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -939,12 +939,12 @@ void QPaintEngineEx::drawPolygon(const QPoint *points, int pointCount, PolygonDr
void QPaintEngineEx::drawPixmap(const QPointF &pos, const QPixmap &pm)
{
- drawPixmap(QRectF(pos, pm.size()), pm, pm.rect());
+ drawPixmap(QRectF(pos, pm.size() / pm.devicePixelRatio()), pm, pm.rect());
}
void QPaintEngineEx::drawImage(const QPointF &pos, const QImage &image)
{
- drawImage(QRectF(pos, image.size()), image, image.rect());
+ drawImage(QRectF(pos, image.size() / image.devicePixelRatio()), image, image.rect());
}
void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s)
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 0cfe953e43..8ec9c1648f 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -225,6 +225,18 @@ QTransform QPainterPrivate::viewTransform() const
return QTransform();
}
+QTransform QPainterPrivate::hidpiScaleTransform() const
+{
+#ifdef Q_OS_MAC
+ // Limited feature introduction for Qt 5.0.0, remove ifdef in a later release.
+ if (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();
+}
/*
\internal
@@ -641,6 +653,8 @@ void QPainterPrivate::updateMatrix()
else
state->dirtyFlags |= QPaintEngine::DirtyTransform;
+ state->matrix *= hidpiScaleTransform();
+
// printf("VxF=%d, WxF=%d\n", state->VxF, state->WxF);
// qDebug() << " --- using matrix" << state->matrix << redirection_offset;
}
@@ -1827,7 +1841,14 @@ bool QPainter::begin(QPaintDevice *pd)
Q_ASSERT(d->engine->isActive());
- if (!d->state->redirectionMatrix.isIdentity())
+#ifdef Q_OS_MAC
+ // Limited feature introduction for Qt 5.0.0, remove ifdef in a later release.
+ const bool isHighDpi = (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)
d->updateMatrix();
Q_ASSERT(d->engine->isActive());
@@ -5092,7 +5113,8 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
x += d->state->matrix.dx();
y += d->state->matrix.dy();
}
- d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(0, 0, w, h));
+ int scale = pm.devicePixelRatio();
+ d->engine->drawPixmap(QRectF(x, y, w / scale, h / scale), pm, QRectF(0, 0, w, h));
}
}
@@ -5122,6 +5144,11 @@ void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
qreal sw = sr.width();
qreal sh = sr.height();
+ // Get pixmap scale. Use it when calculating the target
+ // rect size from pixmap size. For example, a 2X 64x64 pixel
+ // pixmap should result in a 32x32 point target rect.
+ const qreal pmscale = pm.devicePixelRatio();
+
// Sanity-check clipping
if (sw <= 0)
sw = pm.width() - sx;
@@ -5130,9 +5157,9 @@ void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
sh = pm.height() - sy;
if (w < 0)
- w = sw;
+ w = sw / pmscale;
if (h < 0)
- h = sh;
+ h = sh / pmscale;
if (sx < 0) {
qreal w_ratio = sx * w/sw;
@@ -5345,6 +5372,7 @@ void QPainter::drawImage(const QPointF &p, const QImage &image)
int w = image.width();
int h = image.height();
+ qreal scale = image.devicePixelRatio();
d->updateState(d->state);
@@ -5368,8 +5396,7 @@ void QPainter::drawImage(const QPointF &p, const QImage &image)
setBrush(brush);
setPen(Qt::NoPen);
setBrushOrigin(QPointF(0, 0));
-
- drawRect(image.rect());
+ drawRect(QRect(QPoint(0, 0), image.size() / scale));
restore();
return;
}
@@ -5380,7 +5407,7 @@ void QPainter::drawImage(const QPointF &p, const QImage &image)
y += d->state->matrix.dy();
}
- d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(0, 0, w, h), Qt::AutoColor);
+ d->engine->drawImage(QRectF(x, y, w / scale, h / scale), image, QRectF(0, 0, w, h), Qt::AutoColor);
}
void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
@@ -5399,6 +5426,7 @@ void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QR
qreal sy = sourceRect.y();
qreal sw = sourceRect.width();
qreal sh = sourceRect.height();
+ qreal imageScale = image.devicePixelRatio();
// Sanity-check clipping
if (sw <= 0)
@@ -5408,9 +5436,9 @@ void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QR
sh = image.height() - sy;
if (w < 0)
- w = sw;
+ w = sw / imageScale;
if (h < 0)
- h = sh;
+ h = sh / imageScale;
if (sx < 0) {
qreal w_ratio = sx * w/sw;
@@ -8235,7 +8263,7 @@ QTransform QPainter::combinedTransform() const
qWarning("QPainter::combinedTransform: Painter not active");
return QTransform();
}
- return d->state->worldMatrix * d->viewTransform();
+ return d->state->worldMatrix * d->viewTransform() * d->hidpiScaleTransform();
}
/*!
diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h
index 0e46cee4b5..fd5d560141 100644
--- a/src/gui/painting/qpainter_p.h
+++ b/src/gui/painting/qpainter_p.h
@@ -249,6 +249,7 @@ public:
}
QTransform viewTransform() const;
+ QTransform hidpiScaleTransform() const;
static bool attachPainterPrivate(QPainter *q, QPaintDevice *pdev);
void detachPainterPrivate(QPainter *q);