diff options
author | Morten Johan Sørvig <morten.sorvig@digia.com> | 2012-11-20 11:34:52 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2012-12-01 08:33:20 +0100 |
commit | 5e61bbe586519c3d9bc636153d32e810da4e59a3 (patch) | |
tree | 67d67ef644be72ee5b3d685c9a22538d7ec1e01d /src | |
parent | c8dc41bacdc30026cb79d0d6c72255312084bfe3 (diff) |
Basic high-dpi "retina" support for Qt 5.
Bring Qt 5 on par with Qt 4, prepare for more comprehensive
support later on.
Introduce device independent pixels (dips), device pixels,
and devicePixelRatio. Add high-dpi support to QPainter,
QGLWidget, the cocoa platform plugin, mac and fusion styles.
Dips are similar to CSS pixels, Apple points and
Android density-independent pixels. Device pixels
are pixels in the backing store/physical pixels on screen.
devicePixelRatio is the ratio between them, which is
1.0 on standard displays and 2.0 on "retina" displays.
New API:
QImage::devicePixelRatio() and setDevicePixelRatio()
QPixmap::devicePixelRatio() and setDevicePixelRatio()
QWindow::devicePixelRatio()
QScreen::devicePixelRatio()
QGuiApplicaiton::devicePixelRatio()
Change-Id: If98c3ca9bfdf0e1bdbcf7574cd5b912c9ff63856
Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>
Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
Diffstat (limited to 'src')
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 ℑ } +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 ®ion) +{ +// 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 ®ion); 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; |