Windows XP style: Allow High DPI scaling to draw directly.
Previously, the style defaulted to drawing via pixmaps when the device transformation of the QPainter was more complex than TxTranslate. Introduce an enumeration describing the transformation to be able to identify the scaling used by High DPI scaling and allow for direct drawing in that case as well. Add scale factors. Create pixmaps with device pixel ration in drawBackgroundThruNativeBuffer() if High DPI scaling is in effect. Issues: Borders may go missing due to the up-scaling/rounding. Code branches for DrawBackgroundEx==0 are not touched since it is assumed these old versions of Windows do not run in High DPI. Task-number: QTBUG-49374 Change-Id: Idfe1887e4fac3be2843438dc76cb4971a198ab2a Reviewed-by: Alessandro Portale <alessandro.portale@theqtcompany.com>bb10
parent
0e088bd22c
commit
670a9c00ef
|
|
@ -704,6 +704,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
|
||||
|
|
@ -727,21 +740,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.
|
||||
|
|
@ -759,17 +773,38 @@ 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(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(XPThemeData &themeData, int additionalDevicePixelRatio)
|
||||
{
|
||||
QPainter *painter = themeData.painter;
|
||||
HDC dc = 0;
|
||||
|
|
@ -778,7 +813,7 @@ bool QWindowsXPStylePrivate::drawBackgroundDirectly(XPThemeData &themeData)
|
|||
|
||||
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())
|
||||
|
|
@ -786,7 +821,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);
|
||||
|
||||
|
|
@ -798,6 +833,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
|
||||
|
|
@ -855,10 +891,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());
|
||||
|
|
@ -890,6 +927,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);
|
||||
|
|
@ -1066,6 +1105,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
|
||||
|
|
|
|||
|
|
@ -387,8 +387,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(XPThemeData &themeData, int aditionalDevicePixelRatio);
|
||||
|
||||
bool hasAlphaChannel(const QRect &rect);
|
||||
bool fixAlphaChannel(const QRect &rect);
|
||||
|
|
|
|||
Loading…
Reference in New Issue