summaryrefslogtreecommitdiffstats
path: root/src
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
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')
-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
-rw-r--r--src/opengl/qgl.cpp4
-rw-r--r--src/opengl/qgl_qpa.cpp5
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm26
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm12
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm12
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm15
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm31
-rw-r--r--src/widgets/itemviews/qitemdelegate.cpp10
-rw-r--r--src/widgets/kernel/qwidget.cpp29
-rw-r--r--src/widgets/kernel/qwidget_p.h1
-rw-r--r--src/widgets/styles/qfusionstyle.cpp100
-rw-r--r--src/widgets/styles/qmacstyle_mac.mm32
-rw-r--r--src/widgets/styles/qstyle.cpp5
-rw-r--r--src/widgets/styles/qstyle_p.h11
-rw-r--r--src/widgets/widgets/qlabel.cpp9
43 files changed, 533 insertions, 115 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);
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 8c98a0ea3a..69f4871c6b 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -4100,7 +4100,9 @@ void QGLWidget::glDraw()
#endif
if (!d->glcx->initialized()) {
glInit();
- resizeGL(d->glcx->device()->width(), d->glcx->device()->height()); // New context needs this "resize"
+ const qreal scaleFactor = (window() && window()->windowHandle()) ?
+ window()->windowHandle()->devicePixelRatio() : 1.0;
+ resizeGL(d->glcx->device()->width() * scaleFactor, d->glcx->device()->height() * scaleFactor); // New context needs this "resize"
}
paintGL();
if (doubleBuffer()) {
diff --git a/src/opengl/qgl_qpa.cpp b/src/opengl/qgl_qpa.cpp
index ba07f6121c..0e8b8abb4f 100644
--- a/src/opengl/qgl_qpa.cpp
+++ b/src/opengl/qgl_qpa.cpp
@@ -370,7 +370,10 @@ void QGLWidget::resizeEvent(QResizeEvent *e)
makeCurrent();
if (!d->glcx->initialized())
glInit();
- resizeGL(width(), height());
+ const qreal scaleFactor = (window() && window()->windowHandle()) ?
+ window()->windowHandle()->devicePixelRatio() : 1.0;
+
+ resizeGL(width() * scaleFactor, height() * scaleFactor);
}
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
index 0e1998170a..192ef00649 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.h
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h
@@ -62,6 +62,7 @@ public:
void resize (const QSize &size, const QRegion &);
bool scroll(const QRegion &area, int dx, int dy);
CGImageRef getBackingStoreCGImage();
+ qreal getBackingStoreDevicePixelRatio();
private:
QImage m_qImage;
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index 7bd7e4ce38..ec3168ce99 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -59,10 +59,22 @@ QCocoaBackingStore::~QCocoaBackingStore()
QPaintDevice *QCocoaBackingStore::paintDevice()
{
- if (m_qImage.size() != m_requestedSize) {
+ if (m_qImage.size() / m_qImage.devicePixelRatio() != m_requestedSize) {
CGImageRelease(m_cgImage);
m_cgImage = 0;
- m_qImage = QImage(m_requestedSize, QImage::Format_ARGB32_Premultiplied);
+
+ int scaleFactor = 1;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
+ QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window()->handle());
+ if (cocoaWindow && cocoaWindow->m_contentView) {
+ scaleFactor = int([[cocoaWindow->m_contentView window] backingScaleFactor]);
+ }
+ }
+#endif
+
+ m_qImage = QImage(m_requestedSize * scaleFactor, QImage::Format_ARGB32_Premultiplied);
+ m_qImage.setDevicePixelRatio(scaleFactor);
}
return &m_qImage;
}
@@ -90,10 +102,11 @@ void QCocoaBackingStore::resize(const QSize &size, const QRegion &)
bool QCocoaBackingStore::scroll(const QRegion &area, int dx, int dy)
{
extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
- QPoint qpoint(dx, dy);
+ const qreal devicePixelRatio = m_qImage.devicePixelRatio();
+ QPoint qpoint(dx * devicePixelRatio, dy * devicePixelRatio);
const QVector<QRect> qrects = area.rects();
for (int i = 0; i < qrects.count(); ++i) {
- const QRect &qrect = qrects.at(i);
+ const QRect &qrect = QRect(qrects.at(i).topLeft() * devicePixelRatio, qrects.at(i).size() * devicePixelRatio);
qt_scrollRectInImage(m_qImage, qrect, qpoint);
}
return true;
@@ -110,4 +123,9 @@ CGImageRef QCocoaBackingStore::getBackingStoreCGImage()
return m_cgImage;
}
+qreal QCocoaBackingStore::getBackingStoreDevicePixelRatio()
+{
+ return m_qImage.devicePixelRatio();
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index d9bb9c60a9..99956a0b60 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -114,6 +114,18 @@ void QCocoaGLContext::setActiveWindow(QWindow *window)
cocoaWindow->setCurrentContext(this);
[(QNSView *) cocoaWindow->contentView() setQCocoaGLContext:this];
+
+ // Enable high-dpi OpenGL for retina displays. Enabling has the side
+ // effect that Cooca will start calling glViewport(0, 0, width, height),
+ // overriding any glViewport calls in application code. This is usually not a
+ // problem, except if the applcation wants to have a "custom" viewport.
+ // (like the hellogl example)
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
+ if (cocoaWindow->devicePixelRatio() > 1)
+ [cocoaWindow->contentView() setWantsBestResolutionOpenGLSurface:YES];
+ }
+#endif
}
void QCocoaGLContext::doneCurrent()
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index dae9872566..1bb46ea3ea 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -68,6 +68,7 @@ public:
QRect availableGeometry() const { return m_availableGeometry; }
int depth() const { return m_depth; }
QImage::Format format() const { return m_format; }
+ qreal devicePixelRatio() const;
QSizeF physicalSize() const { return m_physicalSize; }
QDpi logicalDpi() const { return m_logicalDpi; }
qreal refreshRate() const { return m_refreshRate; }
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 3767fa014d..393c471c25 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -115,6 +115,18 @@ void QCocoaScreen::updateGeometry()
QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), availableGeometry());
}
+qreal QCocoaScreen::devicePixelRatio() const
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
+ return qreal([m_screen backingScaleFactor]);
+ } else
+#endif
+ {
+ return 1.0;
+ }
+}
+
extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev);
QPixmap QCocoaScreen::grabWindow(WId window, int x, int y, int width, int height) const
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index a9ea135b3e..228644c351 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -140,6 +140,8 @@ public:
void setMenubar(QCocoaMenuBar *mb);
QCocoaMenuBar *menubar() const;
+
+ qreal devicePixelRatio() const;
protected:
// NSWindow handling. The QCocoaWindow/QNSView can either be displayed
// in an existing NSWindow or in one created by Qt.
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 77073d9bc6..c3b2139998 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -39,6 +39,7 @@
**
****************************************************************************/
#include "qcocoawindow.h"
+#include "qcocoaintegration.h"
#include "qnswindowdelegate.h"
#include "qcocoaautoreleasepool.h"
#include "qcocoaeventdispatcher.h"
@@ -820,6 +821,20 @@ QCocoaMenuBar *QCocoaWindow::menubar() const
return m_menubar;
}
+qreal QCocoaWindow::devicePixelRatio() const
+{
+ if (!m_nsWindow)
+ return 1.0;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
+ return qreal([m_nsWindow backingScaleFactor]);
+ } else
+#endif
+ {
+ return 1.0;
+ }
+}
+
QMargins QCocoaWindow::frameMargins() const
{
NSRect frameW = [m_nsWindow frame];
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index d2a4685872..b608989e43 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -244,7 +244,7 @@ static QTouchDevice *touchDevice = 0;
- (void) flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset
{
m_backingStore = backingStore;
- m_backingStoreOffset = offset;
+ m_backingStoreOffset = offset * m_backingStore->getBackingStoreDevicePixelRatio();
QRect br = region.boundingRect();
[self setNeedsDisplayInRect:NSMakeRect(br.x(), br.y(), br.width(), br.height())];
}
@@ -275,33 +275,44 @@ static QTouchDevice *touchDevice = 0;
if (!m_backingStore)
return;
- CGRect dirtyCGRect = NSRectToCGRect(dirtyRect);
+ // Calculate source and target rects. The target rect is the dirtyRect:
+ CGRect dirtyWindowRect = NSRectToCGRect(dirtyRect);
+
+ // The backing store source rect will be larger on retina displays.
+ // Scale dirtyRect by the device pixel ratio:
+ const qreal devicePixelRatio = m_backingStore->getBackingStoreDevicePixelRatio();
+ CGRect dirtyBackingRect = CGRectMake(dirtyRect.origin.x * devicePixelRatio,
+ dirtyRect.origin.y * devicePixelRatio,
+ dirtyRect.size.width * devicePixelRatio,
+ dirtyRect.size.height * devicePixelRatio);
+
NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext];
CGContextRef cgContext = (CGContextRef) [nsGraphicsContext graphicsPort];
// Translate coordiate system from CoreGraphics (bottom-left) to NSView (top-left):
CGContextSaveGState(cgContext);
- int dy = dirtyCGRect.origin.y + CGRectGetMaxY(dirtyCGRect);
+ int dy = dirtyWindowRect.origin.y + CGRectGetMaxY(dirtyWindowRect);
+
CGContextTranslateCTM(cgContext, 0, dy);
CGContextScaleCTM(cgContext, 1, -1);
// If a mask is set, modify the sub image accordingly:
CGImageRef subMask = 0;
if (m_maskImage) {
- subMask = CGImageCreateWithImageInRect(m_maskImage, dirtyCGRect);
- CGContextClipToMask(cgContext, dirtyCGRect, subMask);
+ subMask = CGImageCreateWithImageInRect(m_maskImage, dirtyWindowRect);
+ CGContextClipToMask(cgContext, dirtyWindowRect, subMask);
}
// Clip out and draw the correct sub image from the (shared) backingstore:
CGRect backingStoreRect = CGRectMake(
- dirtyRect.origin.x + m_backingStoreOffset.x(),
- dirtyRect.origin.y + m_backingStoreOffset.y(),
- dirtyRect.size.width,
- dirtyRect.size.height
+ dirtyBackingRect.origin.x + m_backingStoreOffset.x(),
+ dirtyBackingRect.origin.y + m_backingStoreOffset.y(),
+ dirtyBackingRect.size.width,
+ dirtyBackingRect.size.height
);
CGImageRef bsCGImage = m_backingStore->getBackingStoreCGImage();
CGImageRef cleanImg = CGImageCreateWithImageInRect(bsCGImage, backingStoreRect);
- CGContextDrawImage(cgContext, dirtyCGRect, cleanImg);
+ CGContextDrawImage(cgContext, dirtyWindowRect, cleanImg);
// Clean-up:
CGContextRestoreGState(cgContext);
diff --git a/src/widgets/itemviews/qitemdelegate.cpp b/src/widgets/itemviews/qitemdelegate.cpp
index e7ca2d0c6c..7631403933 100644
--- a/src/widgets/itemviews/qitemdelegate.cpp
+++ b/src/widgets/itemviews/qitemdelegate.cpp
@@ -1060,10 +1060,12 @@ QRect QItemDelegate::rect(const QStyleOptionViewItem &option,
switch (value.type()) {
case QVariant::Invalid:
break;
- case QVariant::Pixmap:
- return QRect(QPoint(0, 0), qvariant_cast<QPixmap>(value).size());
- case QVariant::Image:
- return QRect(QPoint(0, 0), qvariant_cast<QImage>(value).size());
+ case QVariant::Pixmap: {
+ const QPixmap &pixmap = qvariant_cast<QPixmap>(value);
+ return QRect(QPoint(0, 0), pixmap.size() / pixmap.devicePixelRatio() ); }
+ case QVariant::Image: {
+ const QImage &image = qvariant_cast<QImage>(value);
+ return QRect(QPoint(0, 0), image.size() / image.devicePixelRatio() ); }
case QVariant::Icon: {
QIcon::Mode mode = d->iconMode(option.state);
QIcon::State state = d->iconState(option.state);
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index e167e646c0..ace25fa78b 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -1794,6 +1794,23 @@ QRegion QWidgetPrivate::clipRegion() const
return r;
}
+void QWidgetPrivate::setSystemClip(QPaintDevice *paintDevice, const QRegion &region)
+{
+// Transform the system clip region from device-independent pixels to device pixels
+// Qt 5.0.0: This is a Mac-only code path for now, can be made cross-platform once
+// 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;
+ scaleTransform.scale(devicePixelRatio, devicePixelRatio);
+ paintEngine->d_func()->systemClip = scaleTransform.map(region);
+#else
+ paintEngine->d_func()->systemClip = region;
+#endif
+}
+
#ifndef QT_NO_GRAPHICSEFFECT
void QWidgetPrivate::invalidateGraphicsEffectsRecursively()
{
@@ -4998,13 +5015,12 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, backingStore);
sourced->context = &context;
if (!sharedPainter) {
- QPaintEngine *paintEngine = pdev->paintEngine();
- paintEngine->d_func()->systemClip = rgn.translated(offset);
+ setSystemClip(pdev, rgn.translated(offset));
QPainter p(pdev);
p.translate(offset);
context.painter = &p;
graphicsEffect->draw(&p);
- paintEngine->d_func()->systemClip = QRegion();
+ setSystemClip(pdev, QRegion());
} else {
context.painter = sharedPainter;
if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
@@ -5061,7 +5077,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
#endif
if (sharedPainter)
- paintEngine->d_func()->systemClip = toBePainted;
+ setSystemClip(pdev, toBePainted);
else
paintEngine->d_func()->systemRect = q->data->crect;
@@ -5073,7 +5089,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
}
if (!sharedPainter)
- paintEngine->d_func()->systemClip = toBePainted.translated(offset);
+ setSystemClip(pdev, toBePainted.translated(offset));
if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) {
QPainter p(q);
@@ -5108,7 +5124,8 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
paintEngine->d_func()->systemRect = QRect();
else
paintEngine->d_func()->currentClipDevice = 0;
- paintEngine->d_func()->systemClip = QRegion();
+
+ setSystemClip(pdev, QRegion());
}
q->setAttribute(Qt::WA_WState_InPaintEvent, false);
if (q->paintingActive())
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index 8aba276966..1d183e41f1 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -402,6 +402,7 @@ public:
QRect clipRect() const;
QRegion clipRegion() const;
+ void setSystemClip(QPaintDevice *paintDevice, const QRegion &region);
void subtractOpaqueChildren(QRegion &rgn, const QRect &clipRect) const;
void subtractOpaqueSiblings(QRegion &source, bool *hasDirtySiblingsAbove = 0,
bool alsoNonOpaque = false) const;
diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp
index ebcdc10d59..623cdb55b9 100644
--- a/src/widgets/styles/qfusionstyle.cpp
+++ b/src/widgets/styles/qfusionstyle.cpp
@@ -303,7 +303,7 @@ static void qt_fusion_draw_mdibutton(QPainter *painter, const QStyleOptionTitleB
gradient.setColorAt(1, mdiButtonGradientStopColor);
QColor mdiButtonBorderColor(active ? option->palette.highlight().color().darker(180): dark.darker(110));
- painter->setPen(QPen(mdiButtonBorderColor, 1));
+ painter->setPen(QPen(mdiButtonBorderColor));
const QLine lines[4] = {
QLine(tmp.left() + 2, tmp.top(), tmp.right() - 2, tmp.top()),
QLine(tmp.left() + 2, tmp.bottom(), tmp.right() - 2, tmp.bottom()),
@@ -457,7 +457,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
if (const QStyleOptionTabBarBase *tbb
= qstyleoption_cast<const QStyleOptionTabBarBase *>(option)) {
painter->save();
- painter->setPen(QPen(outline.lighter(110), 0));
+ painter->setPen(QPen(outline.lighter(110)));
switch (tbb->shape) {
case QTabBar::RoundedNorth: {
QRegion region(tbb->rect);
@@ -603,7 +603,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
}
}
break;
- case PE_Frame:
+ case PE_Frame: {
if (widget && widget->inherits("QComboBoxPrivateContainer")){
QStyleOption copy = *option;
copy.state |= State_Raised;
@@ -611,14 +611,16 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
break;
}
painter->save();
- painter->setPen(outline.lighter(108));
+ QPen thePen(outline.lighter(108));
+ thePen.setCosmetic(false);
+ painter->setPen(thePen);
painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
- painter->restore();
+ painter->restore(); }
break;
case PE_FrameMenu:
painter->save();
{
- painter->setPen(QPen(outline, 1));
+ painter->setPen(QPen(outline));
painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
QColor frameLight = option->palette.background().color().lighter(160);
QColor frameShadow = option->palette.background().color().darker(110);
@@ -644,9 +646,9 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
QRect rect= option->rect;
painter->setPen(softshadow);
painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
- painter->setPen(QPen(option->palette.light(), 0));
+ painter->setPen(QPen(option->palette.light(), 1));
painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1), QPoint(rect.left() + 1, rect.bottom() - 1));
- painter->setPen(QPen(option->palette.background().color().darker(120), 0));
+ painter->setPen(QPen(option->palette.background().color().darker(120)));
painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1), QPoint(rect.right() - 2, rect.bottom() - 1));
painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1), QPoint(rect.right() - 1, rect.bottom() - 1));
@@ -680,12 +682,12 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
painter->save();
{
QRect rect= option->rect;
- painter->setPen(QPen(outline.darker(150), 0));
+ painter->setPen(QPen(outline.darker(150)));
painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
- painter->setPen(QPen(option->palette.light(), 0));
+ painter->setPen(QPen(option->palette.light(), 1));
painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1),
QPoint(rect.left() + 1, rect.bottom() - 1));
- painter->setPen(QPen(option->palette.background().color().darker(120), 0));
+ painter->setPen(QPen(option->palette.background().color().darker(120)));
painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1),
QPoint(rect.right() - 2, rect.bottom() - 1));
painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1),
@@ -705,7 +707,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
painter->translate(0.5, 0.5);
// Draw Outline
- painter->setPen( QPen(hasFocus ? highlightedOutline : outline, 0));
+ painter->setPen( QPen(hasFocus ? highlightedOutline : outline));
painter->setBrush(option->palette.base());
painter->drawRoundedRect(r.adjusted(0, 0, -1, -1), 2, 2);
@@ -740,10 +742,10 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
gradient.setColorAt(1, (state & State_Sunken) ? pressedColor : option->palette.base().color());
painter->setBrush((state & State_Sunken) ? QBrush(pressedColor) : gradient);
- painter->setPen(QPen(outline.lighter(110), 1));
+ painter->setPen(QPen(outline.lighter(110)));
if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
- painter->setPen(QPen(highlightedOutline, 1));
+ painter->setPen(QPen(highlightedOutline));
painter->drawRect(rect);
QColor checkMarkColor = option->palette.text().color().darker(120);
@@ -785,9 +787,9 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
painter->setRenderHint(QPainter::Antialiasing, true);
QPainterPath circle;
circle.addEllipse(rect.center() + QPoint(1.0, 1.0), 6.5, 6.5);
- painter->setPen(QPen(option->palette.background().color().darker(150), 1));
+ painter->setPen(QPen(option->palette.background().color().darker(150)));
if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
- painter->setPen(QPen(highlightedOutline, 1));
+ painter->setPen(QPen(highlightedOutline));
painter->drawPath(circle);
if (state & (State_On )) {
@@ -862,7 +864,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
if (isFlat && !isDown) {
if (isDefault) {
r = option->rect.adjusted(0, 1, 0, -1);
- painter->setPen(QPen(Qt::black, 0));
+ painter->setPen(QPen(Qt::black));
const QLine lines[4] = {
QLine(QPoint(r.left() + 2, r.top()),
QPoint(r.right() - 2, r.top())),
@@ -910,7 +912,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
p->setBrush(Qt::NoBrush);
// Outline
- p->setPen(!isEnabled ? QPen(darkOutline.lighter(115)) : QPen(darkOutline, 1));
+ p->setPen(!isEnabled ? QPen(darkOutline.lighter(115)) : QPen(darkOutline));
p->drawRoundedRect(r, 2.0, 2.0);
p->setPen(d->innerContrastLine());
@@ -1300,7 +1302,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
painter->drawLine(rect.topLeft() - QPoint(0, 1), rect.topRight() - QPoint(0, 1));
painter->setBrush(option->palette.base());
- painter->setPen(QPen(outline, 0));
+ painter->setPen(QPen(outline));
painter->drawRoundedRect(rect.adjusted(0, 0, -1, -1), 2, 2);
// Inner shadow
@@ -1359,14 +1361,14 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
progressBar.setRect(rect.left(), rect.top(), width - 1, rect.height() - 1);
if (!complete) {
painter->drawLine(progressBar.topRight() + QPoint(2, 1), progressBar.bottomRight() + QPoint(2, 0));
- painter->setPen(QPen(highlight.darker(140), 0));
+ painter->setPen(QPen(highlight.darker(140)));
painter->drawLine(progressBar.topRight() + QPoint(1, 1), progressBar.bottomRight() + QPoint(1, 0));
}
} else {
progressBar.setRect(rect.right() - width - 1, rect.top(), width + 2, rect.height() - 1);
if (!complete) {
painter->drawLine(progressBar.topLeft() + QPoint(-2, 1), progressBar.bottomLeft() + QPoint(-2, 0));
- painter->setPen(QPen(highlight.darker(140), 0));
+ painter->setPen(QPen(highlight.darker(140)));
painter->drawLine(progressBar.topLeft() + QPoint(-1, 1), progressBar.bottomLeft() + QPoint(-1, 0));
}
}
@@ -1376,7 +1378,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
if (indeterminate || bar->progress > bar->minimum) {
- painter->setPen(QPen(outline, 0));
+ painter->setPen(QPen(outline));
QColor highlightedGradientStartColor = highlight.lighter(120);
QColor highlightedGradientStopColor = highlight;
@@ -1471,7 +1473,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
QRect r = option->rect;
if (act) {
painter->setBrush(option->palette.highlight().color());
- painter->setPen(QPen(highlightOutline, 0));
+ painter->setPen(QPen(highlightOutline));
painter->drawRect(r.adjusted(0, 0, -1, -1));
// painter->drawRoundedRect(r.adjusted(1, 1, -1, -1), 2, 2);
@@ -1518,7 +1520,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
if (selected) {
QRect r = option->rect;
painter->fillRect(r, highlight);
- painter->setPen(QPen(highlightOutline, 0));
+ painter->setPen(QPen(highlightOutline));
const QLine lines[4] = {
QLine(QPoint(r.left() + 1, r.bottom()), QPoint(r.right() - 1, r.bottom())),
QLine(QPoint(r.left() + 1, r.top()), QPoint(r.right() - 1, r.top())),
@@ -2141,15 +2143,18 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
QPixmap upArrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"),
(spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled) ? arrowColor : disabledColor);
- cachePainter.drawPixmap(QRect(upRect.center().x() - upArrow.width() / 4 + 1,
- upRect.center().y() - upArrow.height() / 4 + 1,
- upArrow.width()/2, upArrow.height()/2), upArrow);
+ QRectF upArrowRect = QRectF(upRect.center().x() - upArrow.width() / 4.0 + 1.0,
+ upRect.center().y() - upArrow.height() / 4.0 + 1.0,
+ upArrow.width() / 2.0, upArrow.height() / 2.0);
+
+ cachePainter.drawPixmap(upArrowRect, upArrow, QRectF(QPointF(0.0, 0.0), upArrow.size()));
QPixmap downArrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"),
(spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled) ? arrowColor : disabledColor, 180);
- cachePainter.drawPixmap(QRect(downRect.center().x() - downArrow.width() / 4 + 1,
- downRect.center().y() - downArrow.height() / 4 + 1,
- downArrow.width()/2, downArrow.height()/2), downArrow);
+ QRectF downArrowRect = QRectF(downRect.center().x() - downArrow.width() / 4.0 + 1.0,
+ downRect.center().y() - downArrow.height() / 4.0 + 1.0,
+ downArrow.width() / 2.0, downArrow.height() / 2.0);
+ cachePainter.drawPixmap(downArrowRect, downArrow, QRectF(QPointF(0.0, 0.0), downArrow.size()));
}
cachePainter.end();
@@ -2486,7 +2491,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
// Paint slider
if (scrollBar->subControls & SC_ScrollBarSlider) {
QRect pixmapRect = scrollBarSlider;
- painter->setPen(QPen(alphaOutline, 0));
+ painter->setPen(QPen(alphaOutline));
if (option->state & State_Sunken && scrollBar->activeSubControls & SC_ScrollBarSlider)
painter->setBrush(midColor2);
else if (option->state & State_MouseOver && scrollBar->activeSubControls & SC_ScrollBarSlider)
@@ -2521,7 +2526,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
painter->setPen(Qt::NoPen);
painter->drawRect(scrollBarSubLine.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, 0, 0));
- painter->setPen(QPen(alphaOutline, 1));
+ painter->setPen(QPen(alphaOutline));
if (option->state & State_Horizontal) {
if (option->direction == Qt::RightToLeft) {
pixmapRect.setLeft(scrollBarSubLine.left());
@@ -2545,9 +2550,10 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
rotation = option->direction == Qt::LeftToRight ? -90 : 90;
QRect upRect = scrollBarSubLine.translated(horizontal ? -2 : -1, 0);
QPixmap arrowPixmap = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, rotation);
- painter->drawPixmap(QRect(upRect.center().x() - arrowPixmap.width() / 4 + 2,
- upRect.center().y() - arrowPixmap.height() / 4 + 1,
- arrowPixmap.width()/2, arrowPixmap.height()/2), arrowPixmap);
+ painter->drawPixmap(QRectF(upRect.center().x() - arrowPixmap.width() / 4.0 + 2.0,
+ upRect.center().y() - arrowPixmap.height() / 4.0 + 1.0,
+ arrowPixmap.width() / 2.0, arrowPixmap.height() / 2.0),
+ arrowPixmap, QRectF(QPoint(0.0, 0.0), arrowPixmap.size()));
}
// The AddLine (down/right) button
@@ -2584,9 +2590,10 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
rotation = option->direction == Qt::LeftToRight ? 90 : -90;
QRect downRect = scrollBarAddLine.translated(-1, 1);
QPixmap arrowPixmap = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, rotation);
- painter->drawPixmap(QRect(downRect.center().x() - arrowPixmap.width() / 4 + 2,
- downRect.center().y() - arrowPixmap.height() / 4,
- arrowPixmap.width()/2, arrowPixmap.height()/2), arrowPixmap);
+ painter->drawPixmap(QRectF(downRect.center().x() - arrowPixmap.width() / 4.0 + 2.0,
+ downRect.center().y() - arrowPixmap.height() / 4.0,
+ arrowPixmap.width() / 2.0, arrowPixmap.height() / 2.0),
+ arrowPixmap, QRectF(QPoint(0.0, 0.0), arrowPixmap.size()));
}
}
@@ -2640,7 +2647,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
downArrowRect.left() - 6: downArrowRect.right() + 6);
proxy()->drawPrimitive(PE_PanelButtonCommand, &buttonOption, &cachePainter, widget);
cachePainter.restore();
- cachePainter.setPen( QPen(hasFocus ? option->palette.highlight() : outline.lighter(110), 0));
+ cachePainter.setPen( QPen(hasFocus ? option->palette.highlight() : outline.lighter(110), 1));
if (!sunken) {
int borderSize = 1;
@@ -2677,9 +2684,10 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
QColor arrowColor = option->palette.buttonText().color();
arrowColor.setAlpha(220);
QPixmap downArrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, 180);
- cachePainter.drawPixmap(QRect(downArrowRect.center().x() - downArrow.width() / 4 + 1,
- downArrowRect.center().y() - downArrow.height() / 4 + 1,
- downArrow.width()/2, downArrow.height()/2), downArrow);
+ cachePainter.drawPixmap(QRectF(downArrowRect.center().x() - downArrow.width() / 4.0 + 1.0,
+ downArrowRect.center().y() - downArrow.height() / 4.0 + 1.0,
+ downArrow.width() / 2.0, downArrow.height() / 2.0),
+ downArrow, QRectF(QPointF(0.0, 0.0), downArrow.size()));
}
cachePainter.end();
QPixmapCache::insert(pixmapName, cache);
@@ -2730,7 +2738,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
gradient.setStart(pixmapRect.left(), pixmapRect.center().y());
gradient.setFinalStop(pixmapRect.right(), pixmapRect.center().y());
}
- groovePainter.setPen(QPen(outline, 0));
+ groovePainter.setPen(QPen(outline));
gradient.setColorAt(0, grooveColor.darker(110));
gradient.setColorAt(1, grooveColor.lighter(110));//palette.button().color().darker(115));
groovePainter.setBrush(gradient);
@@ -2764,7 +2772,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
groovePainter.setRenderHint(QPainter::Antialiasing, true);
groovePainter.translate(0.5, 0.5);
- groovePainter.setPen(QPen(outline, 0));
+ groovePainter.setPen(QPen(outline));
gradient.setColorAt(0, activeHighlight);
gradient.setColorAt(1, activeHighlight.lighter(130));
groovePainter.setBrush(gradient);
@@ -2813,9 +2821,9 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
handlePainter.setBrush(QColor(0, 0, 0, 40));
handlePainter.drawRect(r.adjusted(-1, 2, 1, -2));
- handlePainter.setPen(QPen(d->outline(option->palette), 1));
+ handlePainter.setPen(QPen(d->outline(option->palette)));
if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
- handlePainter.setPen(QPen(d->highlightedOutline(option->palette), 1));
+ handlePainter.setPen(QPen(d->highlightedOutline(option->palette)));
handlePainter.setBrush(gradient);
handlePainter.drawRoundedRect(r, 2, 2);
diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm
index 759b3678d7..89ea4d553a 100644
--- a/src/widgets/styles/qmacstyle_mac.mm
+++ b/src/widgets/styles/qmacstyle_mac.mm
@@ -462,7 +462,7 @@ class QMacCGContext
{
CGContextRef context;
public:
- QMacCGContext(QPainter *p); //qpaintengine_mac.cpp
+ QMacCGContext(QPainter *p);
inline QMacCGContext() { context = 0; }
inline QMacCGContext(const QPaintDevice *pdev) {
extern CGContextRef qt_mac_cg_context(const QPaintDevice *);
@@ -6476,6 +6476,18 @@ void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig
}
}
+// move to QRegion?
+void qt_mac_scale_region(QRegion *region, qreal scaleFactor)
+{
+ QVector<QRect> scaledRects;
+ scaledRects.reserve(region->rects().count());
+
+ foreach (const QRect &rect, region->rects()) {
+ scaledRects.append(QRect(rect.topLeft(), rect.size() * scaleFactor));
+ }
+ region->setRects(&scaledRects[0], scaledRects.count());
+}
+
QMacCGContext::QMacCGContext(QPainter *p)
{
QPaintEngine *pe = p->paintEngine();
@@ -6502,20 +6514,28 @@ QMacCGContext::QMacCGContext(QPainter *p)
CGContextScaleCTM(context, 1, -1);
if (devType == QInternal::Widget) {
- QRegion clip = p->paintEngine()->systemClip();
- QTransform native = p->deviceTransform();
+ // Set the clip rect which is an intersection of the system clip
+ // and the painter clip. To make matters more interesting these
+ // are in device pixels and device-independent pixels, respectively.
+ const qreal devicePixelRatio = image->devicePixelRatio();
+
+ QRegion clip = p->paintEngine()->systemClip(); // get system clip in device pixels
+ QTransform native = p->deviceTransform(); // get device transform. dx/dy is in device pixels
if (p->hasClipping()) {
- QRegion r = p->clipRegion();
+ QRegion r = p->clipRegion(); // get painter clip, which is in device-independent pixels
+ qt_mac_scale_region(&r, devicePixelRatio); // scale painter clip to device pixels
r.translate(native.dx(), native.dy());
if (clip.isEmpty())
clip = r;
else
clip &= r;
}
- qt_mac_clip_cg(context, clip, 0);
+ qt_mac_clip_cg(context, clip, 0); // clip in device pixels
- CGContextTranslateCTM(context, native.dx(), native.dy());
+ // Scale the context so that painting happens in device-independet pixels.
+ CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio);
+ CGContextTranslateCTM(context, native.dx() / devicePixelRatio, native.dy() / devicePixelRatio);
}
} else {
qDebug() << "QMacCGContext:: Unsupported painter devtype type" << devType;
diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp
index 76d6efadee..ab66cdae9f 100644
--- a/src/widgets/styles/qstyle.cpp
+++ b/src/widgets/styles/qstyle.cpp
@@ -618,10 +618,11 @@ void QStyle::drawItemText(QPainter *painter, const QRect &rect, int alignment, c
void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
const QPixmap &pixmap) const
{
- QRect aligned = alignedRect(QApplication::layoutDirection(), QFlag(alignment), pixmap.size(), rect);
+ int scale = pixmap.devicePixelRatio();
+ QRect aligned = alignedRect(QApplication::layoutDirection(), QFlag(alignment), pixmap.size() / scale, rect);
QRect inter = aligned.intersected(rect);
- painter->drawPixmap(inter.x(), inter.y(), pixmap, inter.x() - aligned.x(), inter.y() - aligned.y(), inter.width(), inter.height());
+ painter->drawPixmap(inter.x(), inter.y(), pixmap, inter.x() - aligned.x(), inter.y() - aligned.y(), inter.width() * scale, inter.height() *scale);
}
/*!
diff --git a/src/widgets/styles/qstyle_p.h b/src/widgets/styles/qstyle_p.h
index 85e8e54b16..78dfc6fed9 100644
--- a/src/widgets/styles/qstyle_p.h
+++ b/src/widgets/styles/qstyle_p.h
@@ -43,6 +43,7 @@
#define QSTYLE_P_H
#include "private/qobject_p.h"
+#include <QtGui/qguiapplication.h>
#include <QtWidgets/qstyle.h>
QT_BEGIN_NAMESPACE
@@ -74,12 +75,18 @@ public:
inline QImage styleCacheImage(const QSize &size)
{
- return QImage(size, QImage::Format_ARGB32_Premultiplied);
+ const qreal pixelRatio = qApp->devicePixelRatio();
+ QImage cacheImage = QImage(size * pixelRatio, QImage::Format_ARGB32_Premultiplied);
+ cacheImage.setDevicePixelRatio(pixelRatio);
+ return cacheImage;
}
inline QPixmap styleCachePixmap(const QSize &size)
{
- return QPixmap(size);
+ const qreal pixelRatio = qApp->devicePixelRatio();
+ QPixmap cachePixmap = QPixmap(size * pixelRatio);
+ cachePixmap.setDevicePixelRatio(pixelRatio);
+ return cachePixmap;
}
#define BEGIN_STYLE_PIXMAPCACHE(a) \
diff --git a/src/widgets/widgets/qlabel.cpp b/src/widgets/widgets/qlabel.cpp
index a133b9c310..3b3d15f6d0 100644
--- a/src/widgets/widgets/qlabel.cpp
+++ b/src/widgets/widgets/qlabel.cpp
@@ -562,17 +562,18 @@ QSize QLabelPrivate::sizeForWidth(int w) const
int vextra = hextra;
QFontMetrics fm = q->fontMetrics();
- if (pixmap && !pixmap->isNull())
+ if (pixmap && !pixmap->isNull()) {
br = pixmap->rect();
+ br.setSize(br.size() / pixmap->devicePixelRatio());
#ifndef QT_NO_PICTURE
- else if (picture && !picture->isNull())
+ } else if (picture && !picture->isNull()) {
br = picture->boundingRect();
#endif
#ifndef QT_NO_MOVIE
- else if (movie && !movie->currentPixmap().isNull())
+ } else if (movie && !movie->currentPixmap().isNull()) {
br = movie->currentPixmap().rect();
#endif
- else if (isTextLabel) {
+ } else if (isTextLabel) {
int align = QStyle::visualAlignment(textDirection(), QFlag(this->align));
// Add indentation
int m = indent;