diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2016-04-11 08:48:27 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2016-04-11 09:12:36 +0200 |
commit | f34e73a16a3d757057e007874cb5008f16e20f02 (patch) | |
tree | bcc228617cf240773fd09daac1a1a2614b552b68 /src/widgets/styles | |
parent | 5380808453728a354ae28aae76e85ac448245cf1 (diff) | |
parent | b9d386f2ccd69c7f6a766a6d90a6024eeb48e90a (diff) |
Merge remote-tracking branch 'origin/5.7' into dev
Conflicts:
src/corelib/kernel/qobject.cpp
src/gui/painting/qpaintengine_raster.cpp
Change-Id: I74e1779832f43d033708dcfd6b666c7b4f0111fb
Diffstat (limited to 'src/widgets/styles')
-rw-r--r-- | src/widgets/styles/qcommonstyle.cpp | 10 | ||||
-rw-r--r-- | src/widgets/styles/qfusionstyle.cpp | 12 | ||||
-rw-r--r-- | src/widgets/styles/qstyleanimation.cpp | 1 | ||||
-rw-r--r-- | src/widgets/styles/qstylesheetstyle.cpp | 6 | ||||
-rw-r--r-- | src/widgets/styles/qwindowsstyle.cpp | 35 | ||||
-rw-r--r-- | src/widgets/styles/qwindowsstyle_p_p.h | 7 | ||||
-rw-r--r-- | src/widgets/styles/qwindowsvistastyle.cpp | 81 | ||||
-rw-r--r-- | src/widgets/styles/qwindowsxpstyle.cpp | 100 | ||||
-rw-r--r-- | src/widgets/styles/qwindowsxpstyle_p_p.h | 42 |
9 files changed, 165 insertions, 129 deletions
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index 63024360ae..437becbf70 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -803,10 +803,8 @@ static void drawArrow(const QStyle *style, const QStyleOptionToolButton *toolbut default: return; } - QStyleOption arrowOpt; + QStyleOption arrowOpt = *toolbutton; arrowOpt.rect = rect; - arrowOpt.palette = toolbutton->palette; - arrowOpt.state = toolbutton->state; style->drawPrimitive(pe, &arrowOpt, painter, widget); } #endif // QT_NO_TOOLBUTTON @@ -3345,8 +3343,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl mflags |= State_Sunken; } - QStyleOption tool(0); - tool.palette = toolbutton->palette; + QStyleOption tool = *toolbutton; if (toolbutton->subControls & SC_ToolButton) { if (bflags & (State_Sunken | State_On | State_Raised)) { tool.rect = button; @@ -3415,8 +3412,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl bool down = false; QPixmap pm; - QStyleOption tool(0); - tool.palette = tb->palette; + QStyleOption tool = *tb; if (tb->subControls & SC_TitleBarCloseButton && tb->titleBarFlags & Qt::WindowSystemMenuHint) { ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarCloseButton, widget); down = tb->activeSubControls & SC_TitleBarCloseButton && (opt->state & State_Sunken); diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index b15b9701d9..5b6e47e2c6 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -1649,7 +1649,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin); QRect vTextRect = visualRect(opt->direction, menuitem->rect, textRect); - QString s = menuitem->text; + QStringRef s(&menuitem->text); if (!s.isEmpty()) { // draw text p->save(); int t = s.indexOf(QLatin1Char('\t')); @@ -1660,12 +1660,13 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio if (t >= 0) { QRect vShortcutRect = visualRect(opt->direction, menuitem->rect, QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom()))); + const QString textToDraw = s.mid(t + 1).toString(); if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) { p->setPen(menuitem->palette.light().color()); - p->drawText(vShortcutRect.adjusted(1, 1, 1, 1), text_flags, s.mid(t + 1)); + p->drawText(vShortcutRect.adjusted(1, 1, 1, 1), text_flags, textToDraw); p->setPen(discol); } - p->drawText(vShortcutRect, text_flags, s.mid(t + 1)); + p->drawText(vShortcutRect, text_flags, textToDraw); s = s.left(t); } QFont font = menuitem->font; @@ -1680,12 +1681,13 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio font.setBold(true); p->setFont(font); + const QString textToDraw = s.left(t).toString(); if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) { p->setPen(menuitem->palette.light().color()); - p->drawText(vTextRect.adjusted(1, 1, 1, 1), text_flags, s.left(t)); + p->drawText(vTextRect.adjusted(1, 1, 1, 1), text_flags, textToDraw); p->setPen(discol); } - p->drawText(vTextRect, text_flags, s.left(t)); + p->drawText(vTextRect, text_flags, textToDraw); p->restore(); } diff --git a/src/widgets/styles/qstyleanimation.cpp b/src/widgets/styles/qstyleanimation.cpp index 67e2ee3225..0b8e32be19 100644 --- a/src/widgets/styles/qstyleanimation.cpp +++ b/src/widgets/styles/qstyleanimation.cpp @@ -273,6 +273,7 @@ static QImage blendedImage(const QImage &start, const QImage &end, float alpha) case 32: { blended = QImage(sw, sh, start.format()); + blended.setDevicePixelRatio(start.devicePixelRatio()); uchar *mixed_data = blended.bits(); const uchar *back_data = start.bits(); const uchar *front_data = end.bits(); diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index 053820e459..44555c3058 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -3679,7 +3679,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q QRect textRect = subRule.contentsRect(opt->rect); textRect.setWidth(textRect.width() - mi.tabWidth); - QString s = mi.text; + QStringRef s(&mi.text); p->setPen(mi.palette.buttonText().color()); if (!s.isEmpty()) { int text_flags = Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; @@ -3689,10 +3689,10 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q if (t >= 0) { QRect vShortcutRect = visualRect(opt->direction, mi.rect, QRect(textRect.topRight(), QPoint(mi.rect.right(), textRect.bottom()))); - p->drawText(vShortcutRect, text_flags, s.mid(t + 1)); + p->drawText(vShortcutRect, text_flags, s.mid(t + 1).toString()); s = s.left(t); } - p->drawText(textRect, text_flags, s.left(t)); + p->drawText(textRect, text_flags, s.left(t).toString()); } if (mi.menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index fa1ba80402..e0e9d0f6f1 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -71,6 +71,8 @@ #include <private/qstylehelper_p.h> #include <private/qstyleanimation_p.h> +#include <algorithm> + QT_BEGIN_NAMESPACE #if defined(Q_OS_WIN) @@ -117,8 +119,6 @@ enum QSliderDirection { SlUp, SlDown, SlLeft, SlRight }; \internal */ -int QWindowsStylePrivate::m_appDevicePixelRatio = 0; - QWindowsStylePrivate::QWindowsStylePrivate() : alt_down(false), menuBarTimer(0) { @@ -131,11 +131,9 @@ QWindowsStylePrivate::QWindowsStylePrivate() #endif } -int QWindowsStylePrivate::appDevicePixelRatio() +qreal QWindowsStylePrivate::appDevicePixelRatio() { - if (!QWindowsStylePrivate::m_appDevicePixelRatio) - QWindowsStylePrivate::m_appDevicePixelRatio = qRound(qApp->devicePixelRatio()); - return QWindowsStylePrivate::m_appDevicePixelRatio; + return qApp->devicePixelRatio(); } // Returns \c true if the toplevel parent of \a widget has seen the Alt-key @@ -163,12 +161,11 @@ bool QWindowsStyle::eventFilter(QObject *o, QEvent *e) // Alt has been pressed - find all widgets that care QList<QWidget *> l = widget->findChildren<QWidget *>(); - for (int pos=0 ; pos < l.size() ; ++pos) { - QWidget *w = l.at(pos); - if (w->isWindow() || !w->isVisible() || - w->style()->styleHint(SH_UnderlineShortcut, 0, w)) - l.removeAt(pos); - } + auto ignorable = [](QWidget *w) { + return w->isWindow() || !w->isVisible() + || w->style()->styleHint(SH_UnderlineShortcut, 0, w); + }; + l.erase(std::remove_if(l.begin(), l.end(), ignorable), l.end()); // Update states before repainting d->seenAlt.append(widget); d->alt_down = true; @@ -397,7 +394,7 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW { int ret = QWindowsStylePrivate::pixelMetricFromSystemDp(pm, opt, widget); if (ret != QWindowsStylePrivate::InvalidMetric) - return ret / QWindowsStylePrivate::devicePixelRatio(widget); + return qRound(qreal(ret) / QWindowsStylePrivate::devicePixelRatio(widget)); ret = QWindowsStylePrivate::fixedPixelMetric(pm); if (ret != QWindowsStylePrivate::InvalidMetric) @@ -1183,7 +1180,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai QRect textRect(xpos, y + QWindowsStylePrivate::windowsItemVMargin, w - xm - QWindowsStylePrivate::windowsRightBorder - tab + 1, h - 2 * QWindowsStylePrivate::windowsItemVMargin); QRect vTextRect = visualRect(opt->direction, menuitem->rect, textRect); - QString s = menuitem->text; + QStringRef s(&menuitem->text); if (!s.isEmpty()) { // draw text p->save(); int t = s.indexOf(QLatin1Char('\t')); @@ -1194,24 +1191,26 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai if (t >= 0) { QRect vShortcutRect = visualRect(opt->direction, menuitem->rect, QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom()))); + const QString textToDraw = s.mid(t + 1).toString(); if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, opt, widget)) { p->setPen(menuitem->palette.light().color()); - p->drawText(vShortcutRect.adjusted(1,1,1,1), text_flags, s.mid(t + 1)); + p->drawText(vShortcutRect.adjusted(1, 1, 1, 1), text_flags, textToDraw); p->setPen(discol); } - p->drawText(vShortcutRect, text_flags, s.mid(t + 1)); + p->drawText(vShortcutRect, text_flags, textToDraw); s = s.left(t); } QFont font = menuitem->font; if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem) font.setBold(true); p->setFont(font); + const QString textToDraw = s.left(t).toString(); if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, opt, widget)) { p->setPen(menuitem->palette.light().color()); - p->drawText(vTextRect.adjusted(1,1,1,1), text_flags, s.left(t)); + p->drawText(vTextRect.adjusted(1, 1, 1, 1), text_flags, textToDraw); p->setPen(discol); } - p->drawText(vTextRect, text_flags, s.left(t)); + p->drawText(vTextRect, text_flags, textToDraw); p->restore(); } if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow diff --git a/src/widgets/styles/qwindowsstyle_p_p.h b/src/widgets/styles/qwindowsstyle_p_p.h index 503cd2ca26..e6c44f401e 100644 --- a/src/widgets/styles/qwindowsstyle_p_p.h +++ b/src/widgets/styles/qwindowsstyle_p_p.h @@ -70,8 +70,8 @@ public: QWindowsStylePrivate(); static int pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0); static int fixedPixelMetric(QStyle::PixelMetric pm); - static int devicePixelRatio(const QWidget *widget = 0) - { return widget ? int(widget->devicePixelRatioF()) : QWindowsStylePrivate::appDevicePixelRatio(); } + static qreal devicePixelRatio(const QWidget *widget = 0) + { return widget ? widget->devicePixelRatioF() : QWindowsStylePrivate::appDevicePixelRatio(); } bool hasSeenAlt(const QWidget *widget) const; bool altDown() const { return alt_down; } @@ -96,8 +96,7 @@ public: }; private: - static int appDevicePixelRatio(); - static int m_appDevicePixelRatio; + static qreal appDevicePixelRatio(); }; QT_END_NAMESPACE diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index a48417677a..2b2b919818 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -108,6 +108,15 @@ bool canAnimate(const QStyleOption *option) { && !option->styleObject->property("_q_no_animation").toBool(); } +static inline QImage createAnimationBuffer(const QStyleOption *option, const QWidget *widget) +{ + const int devicePixelRatio = widget ? widget->devicePixelRatio() : 1; + QImage result(option->rect.size() * devicePixelRatio, QImage::Format_ARGB32_Premultiplied); + result.setDevicePixelRatio(devicePixelRatio); + result.fill(0); + return result; +} + /* \internal Used by animations to clone a styleoption and shift its offset */ @@ -320,12 +329,10 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt // We create separate images for the initial and final transition states and store them in the // Transition object. - QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); - startImage.fill(0); + QImage startImage = createAnimationBuffer(option, widget); QPainter startPainter(&startImage); - QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); - endImage.fill(0); + QImage endImage = createAnimationBuffer(option, widget); QPainter endPainter(&endImage); // If we have a running animation on the widget already, we will use that to paint the initial @@ -425,8 +432,8 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt XPThemeData themeSize = theme; themeSize.partId = TVP_HOTGLYPH; themeSize.stateId = GLPS_OPENED; - const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); - decoration_size = qMax(size.width(), size.height()); + const QSizeF size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + decoration_size = qRound(qMax(size.width(), size.height())); } int mid_h = option->rect.x() + option->rect.width() / 2; int mid_v = option->rect.y() + option->rect.height() / 2; @@ -873,8 +880,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption QStyleOption *styleOption = clonedAnimationStyleOption(option); styleOption->state = (QStyle::State)oldState; - QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); - startImage.fill(0); + QImage startImage = createAnimationBuffer(option, widget); QPainter startPainter(&startImage); // Use current state of existing animation if already one is running @@ -886,8 +892,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption } t->setStartImage(startImage); - QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); - endImage.fill(0); + QImage endImage = createAnimationBuffer(option, widget); QPainter endPainter(&endImage); styleOption->state = option->state; proxy()->drawControl(element, styleOption, &endPainter, widget); @@ -949,10 +954,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject(option))); if (!anim) { - QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); - startImage.fill(0); - QImage alternateImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); - alternateImage.fill(0); + QImage startImage = createAnimationBuffer(option, widget); + QImage alternateImage = createAnimationBuffer(option, widget); QWindowsVistaPulse *pulse = new QWindowsVistaPulse(styleObject(option)); @@ -991,10 +994,10 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ToolBarTheme, TP_DROPDOWNBUTTON); if (theme.isValid()) { - const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QSizeF size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); if (!size.isEmpty()) { - mbiw = size.width(); - mbih = size.height(); + mbiw = qRound(size.width()); + mbih = qRound(size.height()); } } QRect ir = subElementRect(SE_PushButtonContents, option, 0); @@ -1178,17 +1181,18 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption case CE_MenuItem: if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { // windows always has a check column, regardless whether we have an icon or not - int checkcol = 25 / QWindowsXPStylePrivate::devicePixelRatio(widget); - const int gutterWidth = 3 / QWindowsXPStylePrivate::devicePixelRatio(widget); + const qreal devicePixelRatio = QWindowsXPStylePrivate::devicePixelRatio(widget); + int checkcol = qRound(qreal(25) / devicePixelRatio); + const int gutterWidth = qRound(qreal(3) / devicePixelRatio); { XPThemeData theme(widget, 0, QWindowsXPStylePrivate::MenuTheme, MENU_POPUPCHECKBACKGROUND, MBI_HOT); XPThemeData themeSize = theme; themeSize.partId = MENU_POPUPCHECK; themeSize.stateId = 0; - const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); - const QMargins margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); - checkcol = qMax(menuitem->maxIconWidth, gutterWidth + size.width() + margins.left() + margins.right()); + const QSizeF size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMarginsF margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + checkcol = qMax(menuitem->maxIconWidth, qRound(gutterWidth + size.width() + margins.left() + margins.right())); } QRect rect = option->rect; @@ -1245,17 +1249,17 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption XPThemeData themeSize = theme; themeSize.partId = MENU_POPUPCHECK; themeSize.stateId = 0; - const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); - const QMargins margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); - QRect checkRect(0, 0, size.width() + margins.left() + margins.right(), - size.height() + margins.bottom() + margins.top()); + const QSizeF size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMarginsF margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + QRect checkRect(0, 0, qRound(size.width() + margins.left() + margins.right()), + qRound(size.height() + margins.bottom() + margins.top())); checkRect.moveCenter(vCheckRect.center()); theme.rect = checkRect; d->drawBackground(theme); if (menuitem->icon.isNull()) { - checkRect = QRect(QPoint(0, 0), size); + checkRect = QRect(QPoint(0, 0), size.toSize()); checkRect.moveCenter(theme.rect.center()); theme.rect = checkRect; @@ -1549,13 +1553,10 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle } if (doTransition) { - - QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); - startImage.fill(0); + QImage startImage = createAnimationBuffer(option, widget); QPainter startPainter(&startImage); - QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); - endImage.fill(0); + QImage endImage = createAnimationBuffer(option, widget); QPainter endPainter(&endImage); QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject)); @@ -1861,10 +1862,10 @@ QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption XPThemeData themeSize = theme; themeSize.partId = MENU_POPUPCHECK; themeSize.stateId = 0; - const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); - const QMargins margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); - minimumHeight = qMax(size.height() + margins.bottom() + margins.top(), sz.height()); - sz.rwidth() += size.width() + margins.left() + margins.right(); + const QSizeF size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMarginsF margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + minimumHeight = qMax(qRound(size.height() + margins.bottom() + margins.top()), sz.height()); + sz.rwidth() += qRound(size.width() + margins.left() + margins.right()); } if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { @@ -1972,10 +1973,10 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption int arrowWidth = 13; int arrowHeight = 5; if (theme.isValid()) { - const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QSizeF size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); if (!size.isEmpty()) { - arrowWidth = size.width(); - arrowHeight = size.height(); + arrowWidth = qRound(size.width()); + arrowHeight = qRound(size.height()); } } if (option->state & State_Horizontal) { @@ -2516,7 +2517,7 @@ QIcon QWindowsVistaStyle::standardIcon(StandardPixmap standardIcon, QWindowsXPStylePrivate::ButtonTheme, BP_COMMANDLINKGLYPH, CMDLGS_NORMAL); if (theme.isValid()) { - const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QSize size = (theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget)).toSize(); QIcon linkGlyph; QPixmap pm(size); pm.fill(Qt::transparent); diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index c3072303de..1f910d41cb 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 @@ -2007,7 +2045,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) { @@ -2078,7 +2116,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(); } @@ -2541,10 +2579,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(); @@ -3359,7 +3397,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) { @@ -3505,9 +3543,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; @@ -3702,10 +3740,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) @@ -3875,7 +3913,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); } } @@ -3909,7 +3947,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); @@ -3943,7 +3981,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); @@ -3979,7 +4017,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); diff --git a/src/widgets/styles/qwindowsxpstyle_p_p.h b/src/widgets/styles/qwindowsxpstyle_p_p.h index 31977304fe..68aa10e12a 100644 --- a/src/widgets/styles/qwindowsxpstyle_p_p.h +++ b/src/widgets/styles/qwindowsxpstyle_p_p.h @@ -208,15 +208,15 @@ public: static RECT toRECT(const QRect &qr); bool isValid(); - QSize size(); - QMargins margins(const QRect &rect, int propId = TMT_CONTENTMARGINS); - QMargins margins(int propId = TMT_CONTENTMARGINS); + QSizeF size(); + QMarginsF margins(const QRect &rect, int propId = TMT_CONTENTMARGINS); + QMarginsF margins(int propId = TMT_CONTENTMARGINS); - static QSize themeSize(const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, int part = 0, int state = 0); - static QMargins themeMargins(const QRect &rect, const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, - int part = 0, int state = 0, int propId = TMT_CONTENTMARGINS); - static QMargins themeMargins(const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, - int part = 0, int state = 0, int propId = TMT_CONTENTMARGINS); + static QSizeF themeSize(const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, int part = 0, int state = 0); + static QMarginsF themeMargins(const QRect &rect, const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, + int part = 0, int state = 0, int propId = TMT_CONTENTMARGINS); + static QMarginsF themeMargins(const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, + int part = 0, int state = 0, int propId = TMT_CONTENTMARGINS); const QWidget *widget; QPainter *painter; @@ -393,8 +393,8 @@ public: void setTransparency(QWidget *widget, XPThemeData &themeData); bool drawBackground(XPThemeData &themeData); - bool drawBackgroundThruNativeBuffer(XPThemeData &themeData); - bool drawBackgroundDirectly(XPThemeData &themeData); + bool drawBackgroundThruNativeBuffer(XPThemeData &themeData, int aditionalDevicePixelRatio); + bool drawBackgroundDirectly(HDC dc, XPThemeData &themeData, int aditionalDevicePixelRatio); bool hasAlphaChannel(const QRect &rect); bool fixAlphaChannel(const QRect &rect); @@ -433,9 +433,9 @@ private: static HTHEME m_themes[NThemes]; }; -inline QSize XPThemeData::size() +inline QSizeF XPThemeData::size() { - QSize result(0, 0); + QSizeF result(0, 0); if (isValid()) { SIZE size; if (SUCCEEDED(QWindowsXPStylePrivate::pGetThemePartSize(handle(), 0, partId, stateId, 0, TS_TRUE, &size))) @@ -444,9 +444,9 @@ inline QSize XPThemeData::size() return result; } -inline QMargins XPThemeData::margins(const QRect &qRect, int propId) +inline QMarginsF XPThemeData::margins(const QRect &qRect, int propId) { - QMargins result(0, 0, 0 ,0); + QMarginsF result(0, 0, 0 ,0); if (isValid()) { MARGINS margins; RECT rect = XPThemeData::toRECT(qRect); @@ -456,9 +456,9 @@ inline QMargins XPThemeData::margins(const QRect &qRect, int propId) return result; } -inline QMargins XPThemeData::margins(int propId) +inline QMarginsF XPThemeData::margins(int propId) { - QMargins result(0, 0, 0 ,0); + QMarginsF result(0, 0, 0 ,0); if (isValid()) { MARGINS margins; if (SUCCEEDED(QWindowsXPStylePrivate::pGetThemeMargins(handle(), 0, partId, stateId, propId, NULL, &margins))) @@ -467,21 +467,21 @@ inline QMargins XPThemeData::margins(int propId) return result; } -inline QSize XPThemeData::themeSize(const QWidget *w, QPainter *p, int themeIn, int part, int state) +inline QSizeF XPThemeData::themeSize(const QWidget *w, QPainter *p, int themeIn, int part, int state) { XPThemeData theme(w, p, themeIn, part, state); return theme.size(); } -inline QMargins XPThemeData::themeMargins(const QRect &rect, const QWidget *w, QPainter *p, int themeIn, - int part, int state, int propId) +inline QMarginsF XPThemeData::themeMargins(const QRect &rect, const QWidget *w, QPainter *p, int themeIn, + int part, int state, int propId) { XPThemeData theme(w, p, themeIn, part, state); return theme.margins(rect, propId); } -inline QMargins XPThemeData::themeMargins(const QWidget *w, QPainter *p, int themeIn, - int part, int state, int propId) +inline QMarginsF XPThemeData::themeMargins(const QWidget *w, QPainter *p, int themeIn, + int part, int state, int propId) { XPThemeData theme(w, p, themeIn, part, state); return theme.margins(propId); |