diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2016-04-07 10:47:20 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2016-04-07 10:47:20 +0200 |
commit | ee0951d69b38f766e67262487be95b88501aa4a5 (patch) | |
tree | 116c334060500be340d4d61c99026316b0df3ce9 /src/widgets/styles/qwindowsxpstyle.cpp | |
parent | 0bb645b1ccc5a9d57b21cf0b2c4306b8e48c611c (diff) | |
parent | d37239aa419ee4adff4b0a8d5c1403cadff72319 (diff) |
Merge remote-tracking branch 'origin/5.6' into 5.7
Conflicts:
src/network/access/qftp.cpp
src/widgets/itemviews/qheaderview.cpp
src/widgets/itemviews/qlistview.cpp
tests/auto/network/access/qftp/tst_qftp.cpp
Change-Id: I9f928f25d45d8944dd60bb583f649fc1615bc5d9
Diffstat (limited to 'src/widgets/styles/qwindowsxpstyle.cpp')
-rw-r--r-- | src/widgets/styles/qwindowsxpstyle.cpp | 100 |
1 files changed, 69 insertions, 31 deletions
diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index c33e4167c1..661c1f7a88 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -431,7 +431,7 @@ const QPixmap *QWindowsXPStylePrivate::tabBody(QWidget *widget) { if (!tabbody) { XPThemeData theme(0, 0, QWindowsXPStylePrivate::TabTheme, TABP_BODY); - const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QSize size = (theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget)).toSize(); tabbody = new QPixmap(size.width(), QApplication::desktop()->screenGeometry().height()); QPainter painter(tabbody); @@ -712,6 +712,19 @@ bool QWindowsXPStylePrivate::swapAlphaChannel(const QRect &rect, bool allPixels) return valueChange; } +enum TransformType { SimpleTransform, HighDpiScalingTransform, ComplexTransform }; + +static inline TransformType transformType(const QTransform &transform, qreal devicePixelRatio) +{ + if (transform.type() <= QTransform::TxTranslate) + return SimpleTransform; + if (transform.type() > QTransform::TxScale) + return ComplexTransform; + return qFuzzyCompare(transform.m11(), devicePixelRatio) + && qFuzzyCompare(transform.m22(), devicePixelRatio) + ? HighDpiScalingTransform : ComplexTransform; +} + /*! \internal Main theme drawing function. Determines the correct lowlevel drawing method depending on several @@ -735,21 +748,22 @@ bool QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData) painter->save(); - bool complexXForm = painter->deviceTransform().type() > QTransform::TxTranslate; - // Access paintDevice via engine since the painter may // return the clip device which can still be a widget device in case of grabWidget(). bool translucentToplevel = false; const QPaintDevice *paintDevice = painter->device(); + const qreal aditionalDevicePixelRatio = themeData.widget ? themeData.widget->devicePixelRatio() : 1; if (paintDevice->devType() == QInternal::Widget) { const QWidget *window = static_cast<const QWidget *>(paintDevice)->window(); translucentToplevel = window->testAttribute(Qt::WA_TranslucentBackground); } + const TransformType tt = transformType(painter->deviceTransform(), aditionalDevicePixelRatio); + bool canDrawDirectly = false; if (themeData.widget && painter->opacity() == 1.0 && !themeData.rotate - && !complexXForm && !themeData.mirrorVertically + && tt != ComplexTransform && !themeData.mirrorVertically && (!themeData.mirrorHorizontally || pDrawThemeBackgroundEx) && !translucentToplevel) { // Draw on backing store DC only for real widgets or backing store images. @@ -767,26 +781,44 @@ bool QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData) } const HDC dc = canDrawDirectly ? hdcForWidgetBackingStore(themeData.widget) : HDC(0); - const bool result = dc ? drawBackgroundDirectly(themeData) : drawBackgroundThruNativeBuffer(themeData); + const bool result = dc + ? drawBackgroundDirectly(dc, themeData, qRound(aditionalDevicePixelRatio)) + : drawBackgroundThruNativeBuffer(themeData, qRound(aditionalDevicePixelRatio)); painter->restore(); return result; } +static inline QRect scaleRect(const QRect &r, int factor) +{ + return r.isValid() && factor > 1 + ? QRect(r.topLeft() * factor, r.size() * factor) + : r; +} + +static QRegion scaleRegion(const QRegion ®ion, int factor) +{ + if (region.isEmpty() || factor == 1) + return region; + if (region.rectCount() == 1) + return QRegion(scaleRect(region.boundingRect(), factor)); + QRegion result; + foreach (const QRect &rect, region.rects()) + result += QRect(rect.topLeft() * factor, rect.size() * factor); + return result; +} + /*! \internal This function draws the theme parts directly to the paintengines HDC. Do not use this if you need to perform other transformations on the resulting data. */ -bool QWindowsXPStylePrivate::drawBackgroundDirectly(XPThemeData &themeData) +bool QWindowsXPStylePrivate::drawBackgroundDirectly(HDC dc, XPThemeData &themeData, int additionalDevicePixelRatio) { QPainter *painter = themeData.painter; - HDC dc = 0; - if (themeData.widget) - dc = hdcForWidgetBackingStore(themeData.widget); QPoint redirectionDelta(int(painter->deviceMatrix().dx()), int(painter->deviceMatrix().dy())); - QRect area = themeData.rect.translated(redirectionDelta); + QRect area = scaleRect(themeData.rect, additionalDevicePixelRatio).translated(redirectionDelta); QRegion sysRgn = painter->paintEngine()->systemClip(); if (sysRgn.isEmpty()) @@ -794,7 +826,7 @@ bool QWindowsXPStylePrivate::drawBackgroundDirectly(XPThemeData &themeData) else sysRgn &= area; if (painter->hasClipping()) - sysRgn &= painter->clipRegion().translated(redirectionDelta); + sysRgn &= scaleRegion(painter->clipRegion(), additionalDevicePixelRatio).translated(redirectionDelta); HRGN hrgn = qt_hrgn_from_qregion(sysRgn); SelectClipRgn(dc, hrgn); @@ -806,6 +838,7 @@ bool QWindowsXPStylePrivate::drawBackgroundDirectly(XPThemeData &themeData) RECT drawRECT = themeData.toRECT(area); DTBGOPTS drawOptions; + memset(&drawOptions, 0, sizeof(drawOptions)); drawOptions.dwSize = sizeof(drawOptions); drawOptions.rcClip = themeData.toRECT(sysRgn.boundingRect()); drawOptions.dwFlags = DTBG_CLIPRECT @@ -813,8 +846,9 @@ bool QWindowsXPStylePrivate::drawBackgroundDirectly(XPThemeData &themeData) | (themeData.noContent ? DTBG_OMITCONTENT : 0) | (themeData.mirrorHorizontally ? DTBG_MIRRORDC : 0); + HRESULT result = S_FALSE; if (pDrawThemeBackgroundEx != 0) { - pDrawThemeBackgroundEx(themeData.handle(), dc, themeData.partId, themeData.stateId, &(drawRECT), &drawOptions); + result = pDrawThemeBackgroundEx(themeData.handle(), dc, themeData.partId, themeData.stateId, &(drawRECT), &drawOptions); } else { // We are running on a system where the uxtheme.dll does not have // the DrawThemeBackgroundEx function, so we need to clip away @@ -848,11 +882,11 @@ bool QWindowsXPStylePrivate::drawBackgroundDirectly(XPThemeData &themeData) } } - pDrawThemeBackground(themeData.handle(), dc, themeData.partId, themeData.stateId, &(drawRECT), &(drawOptions.rcClip)); + result = pDrawThemeBackground(themeData.handle(), dc, themeData.partId, themeData.stateId, &(drawRECT), &(drawOptions.rcClip)); } SelectClipRgn(dc, 0); DeleteObject(hrgn); - return true; + return SUCCEEDED(result); } /*! \internal @@ -863,10 +897,11 @@ bool QWindowsXPStylePrivate::drawBackgroundDirectly(XPThemeData &themeData) flips (horizonal mirroring only, vertical are handled by the theme engine). */ -bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeData) +bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeData, + int additionalDevicePixelRatio) { QPainter *painter = themeData.painter; - QRect rect = themeData.rect; + QRect rect = scaleRect(themeData.rect, additionalDevicePixelRatio); if ((themeData.rotate + 90) % 180 == 0) { // Catch 90,270,etc.. degree flips. rect = QRect(0, 0, rect.height(), rect.width()); @@ -898,6 +933,8 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa pixmapCacheKey.append(QLatin1Char('w')); pixmapCacheKey.append(QString::number(h)); pixmapCacheKey.append(QLatin1Char('h')); + pixmapCacheKey.append(QString::number(additionalDevicePixelRatio)); + pixmapCacheKey.append(QLatin1Char('d')); QPixmap cachedPixmap; ThemeMapKey key(themeData); @@ -1074,6 +1111,7 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa printf("Image format is: %s\n", alphaType == RealAlpha ? "Real Alpha" : alphaType == MaskAlpha ? "Masked Alpha" : "No Alpha"); #endif img = QImage(bufferPixels, bufferW, bufferH, format); + img.setDevicePixelRatio(additionalDevicePixelRatio); } // Blitting backing store @@ -2010,7 +2048,7 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op themeNumber = QWindowsXPStylePrivate::StatusTheme; partId = SP_GRIPPER; XPThemeData theme(0, p, themeNumber, partId, 0); - QSize size = theme.size() / QWindowsStylePrivate::devicePixelRatio(widget); + QSize size = (theme.size() / QWindowsStylePrivate::devicePixelRatio(widget)).toSize(); size.rheight()--; if (const QStyleOptionSizeGrip *sg = qstyleoption_cast<const QStyleOptionSizeGrip *>(option)) { switch (sg->corner) { @@ -2081,7 +2119,7 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op QWindowsXPStylePrivate::ToolBarTheme, TP_SPLITBUTTONDROPDOWN); if (theme.isValid()) { - const QSize size = theme.size() / QWindowsStylePrivate::devicePixelRatio(widget); + const QSize size = (theme.size() / QWindowsStylePrivate::devicePixelRatio(widget)).toSize(); mbiw = size.width(); mbih = size.height(); } @@ -2544,10 +2582,10 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op QRect QWindowsXPStylePrivate::scrollBarGripperBounds(QStyle::State flags, const QWidget *widget, XPThemeData *theme) { const bool horizontal = flags & QStyle::State_Horizontal; - const QMargins contentsMargin = theme->margins(theme->rect, TMT_SIZINGMARGINS) - / QWindowsStylePrivate::devicePixelRatio(widget); + const QMargins contentsMargin = (theme->margins(theme->rect, TMT_SIZINGMARGINS) + / QWindowsStylePrivate::devicePixelRatio(widget)).toMargins(); theme->partId = horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT; - const QSize size = theme->size() / QWindowsStylePrivate::devicePixelRatio(widget); + const QSize size = (theme->size() / QWindowsStylePrivate::devicePixelRatio(widget)).toSize(); const int hSpace = theme->rect.width() - size.width(); const int vSpace = theme->rect.height() - size.height(); @@ -3362,7 +3400,7 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con int res = QWindowsXPStylePrivate::pixelMetricFromSystemDp(pm, option, widget); if (res != QWindowsStylePrivate::InvalidMetric) - return res / QWindowsStylePrivate::devicePixelRatio(widget); + return qRound(qreal(res) / QWindowsStylePrivate::devicePixelRatio(widget)); res = 0; switch (pm) { @@ -3508,9 +3546,9 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl const int height = tb->rect.height(); const int width = tb->rect.width(); const int buttonMargin = int(QStyleHelper::dpiScaled(4)); - int buttonHeight = GetSystemMetrics(SM_CYSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) + int buttonHeight = qRound(qreal(GetSystemMetrics(SM_CYSIZE)) / QWindowsStylePrivate::devicePixelRatio(widget)) - buttonMargin; - int buttonWidth = GetSystemMetrics(SM_CXSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) + int buttonWidth = qRound(qreal(GetSystemMetrics(SM_CXSIZE)) / QWindowsStylePrivate::devicePixelRatio(widget)) - buttonMargin; const int delta = buttonWidth + 2; int controlTop = option->rect.bottom() - buttonHeight - 2; @@ -3705,10 +3743,10 @@ QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt { XPThemeData buttontheme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_PUSHBUTTON, PBS_NORMAL); if (buttontheme.isValid()) { - const QMargins borderSize = buttontheme.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMarginsF borderSize = buttontheme.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); if (!borderSize.isNull()) { - sz.rwidth() += borderSize.left() + borderSize.right() - 2; - sz.rheight() += borderSize.bottom() + borderSize.top() - 2; + sz.rwidth() += qRound(borderSize.left() + borderSize.right() - 2); + sz.rheight() += qRound(borderSize.bottom() + borderSize.top() - 2); } const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin) + 1); sz += QSize(qMax(pixelMetric(QStyle::PM_ScrollBarExtent, option, widget) @@ -3878,7 +3916,7 @@ QPixmap QWindowsXPStyle::standardPixmap(StandardPixmap standardPixmap, const QSt if (widget && widget->isWindow()) { XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL); if (theme.isValid()) { - const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QSize size = (theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget)).toSize(); return QIcon(QWindowsStyle::standardPixmap(standardPixmap, option, widget)).pixmap(size); } } @@ -3912,7 +3950,7 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, WP_MAXBUTTON, MAXBS_NORMAL); if (theme.isValid()) { - const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QSize size = (themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget)).toSize(); QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); @@ -3946,7 +3984,7 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL); if (theme.isValid()) { - const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QSize size = (theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget)).toSize(); QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); @@ -3982,7 +4020,7 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, WP_RESTOREBUTTON, RBS_NORMAL); if (theme.isValid()) { - const QSize size = themeSize.size() / QWindowsStylePrivate::devicePixelRatio(widget); + const QSize size = (themeSize.size() / QWindowsStylePrivate::devicePixelRatio(widget)).toSize(); QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); |