StyleSheetStyle: Load @Nx images
Perform a @Nx image file lookup when loading pixmaps. Make drawBackgroundImage() handle high-dpi pixmaps, here the layout calculations needs to be in device- independent pixels Fixes: QTBUG-36825 Change-Id: I61e6f53c59f61f3bd88c34a036349e51e8c8ad92 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
This commit is contained in:
parent
0cae5a4c4b
commit
d7e274a446
@ -115,6 +115,8 @@
|
|||||||
#include <QtWidgets/qtoolbar.h>
|
#include <QtWidgets/qtoolbar.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <QtGui/qscreen.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace QCss;
|
using namespace QCss;
|
||||||
@ -952,8 +954,10 @@ QRenderRule::QRenderRule(const QVector<Declaration> &declarations, const QObject
|
|||||||
Attachment attachment = Attachment_Scroll;
|
Attachment attachment = Attachment_Scroll;
|
||||||
origin = Origin_Padding;
|
origin = Origin_Padding;
|
||||||
Origin clip = Origin_Border;
|
Origin clip = Origin_Border;
|
||||||
if (v.extractBackground(&brush, &uri, &repeat, &alignment, &origin, &attachment, &clip))
|
if (v.extractBackground(&brush, &uri, &repeat, &alignment, &origin, &attachment, &clip)) {
|
||||||
bg = new QStyleSheetBackgroundData(brush, QPixmap(uri), repeat, alignment, origin, attachment, clip);
|
bg = new QStyleSheetBackgroundData(brush, QStyleSheetStyle::loadPixmap(uri, object),
|
||||||
|
repeat, alignment, origin, attachment, clip);
|
||||||
|
}
|
||||||
|
|
||||||
QBrush sfg, fg;
|
QBrush sfg, fg;
|
||||||
QBrush sbg, abg;
|
QBrush sbg, abg;
|
||||||
@ -992,7 +996,7 @@ QRenderRule::QRenderRule(const QVector<Declaration> &declarations, const QObject
|
|||||||
bd->bi = new QStyleSheetBorderImageData;
|
bd->bi = new QStyleSheetBorderImageData;
|
||||||
|
|
||||||
QStyleSheetBorderImageData *bi = bd->bi;
|
QStyleSheetBorderImageData *bi = bd->bi;
|
||||||
bi->pixmap = QPixmap(uri);
|
bi->pixmap = QStyleSheetStyle::loadPixmap(uri, object);
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
bi->cuts[i] = cuts[i];
|
bi->cuts[i] = cuts[i];
|
||||||
bi->horizStretch = horizStretch;
|
bi->horizStretch = horizStretch;
|
||||||
@ -1215,30 +1219,33 @@ void QRenderRule::drawBackgroundImage(QPainter *p, const QRect &rect, QPoint off
|
|||||||
if (background()->attachment == Attachment_Fixed)
|
if (background()->attachment == Attachment_Fixed)
|
||||||
off = QPoint(0, 0);
|
off = QPoint(0, 0);
|
||||||
|
|
||||||
|
QSize bgpSize = bgp.size() / bgp.devicePixelRatio();
|
||||||
|
int bgpHeight = bgpSize.height();
|
||||||
|
int bgpWidth = bgpSize.width();
|
||||||
QRect r = originRect(rect, background()->origin);
|
QRect r = originRect(rect, background()->origin);
|
||||||
QRect aligned = QStyle::alignedRect(Qt::LeftToRight, background()->position, bgp.size(), r);
|
QRect aligned = QStyle::alignedRect(Qt::LeftToRight, background()->position, bgpSize, r);
|
||||||
QRect inter = aligned.translated(-off).intersected(r);
|
QRect inter = aligned.translated(-off).intersected(r);
|
||||||
|
|
||||||
switch (background()->repeat) {
|
switch (background()->repeat) {
|
||||||
case Repeat_Y:
|
case Repeat_Y:
|
||||||
p->drawTiledPixmap(inter.x(), r.y(), inter.width(), r.height(), bgp,
|
p->drawTiledPixmap(inter.x(), r.y(), inter.width(), r.height(), bgp,
|
||||||
inter.x() - aligned.x() + off.x(),
|
inter.x() - aligned.x() + off.x(),
|
||||||
bgp.height() - int(aligned.y() - r.y()) % bgp.height() + off.y());
|
bgpHeight - int(aligned.y() - r.y()) % bgpHeight + off.y());
|
||||||
break;
|
break;
|
||||||
case Repeat_X:
|
case Repeat_X:
|
||||||
p->drawTiledPixmap(r.x(), inter.y(), r.width(), inter.height(), bgp,
|
p->drawTiledPixmap(r.x(), inter.y(), r.width(), inter.height(), bgp,
|
||||||
bgp.width() - int(aligned.x() - r.x())%bgp.width() + off.x(),
|
bgpWidth - int(aligned.x() - r.x())%bgpWidth + off.x(),
|
||||||
inter.y() - aligned.y() + off.y());
|
inter.y() - aligned.y() + off.y());
|
||||||
break;
|
break;
|
||||||
case Repeat_XY:
|
case Repeat_XY:
|
||||||
p->drawTiledPixmap(r, bgp,
|
p->drawTiledPixmap(r, bgp,
|
||||||
QPoint(bgp.width() - int(aligned.x() - r.x())% bgp.width() + off.x(),
|
QPoint(bgpWidth - int(aligned.x() - r.x())% bgpWidth + off.x(),
|
||||||
bgp.height() - int(aligned.y() - r.y())%bgp.height() + off.y()));
|
bgpHeight - int(aligned.y() - r.y())%bgpHeight + off.y()));
|
||||||
break;
|
break;
|
||||||
case Repeat_None:
|
case Repeat_None:
|
||||||
default:
|
default:
|
||||||
p->drawPixmap(inter.x(), inter.y(), bgp, inter.x() - aligned.x() + off.x(),
|
p->drawPixmap(inter.x(), inter.y(), bgp, inter.x() - aligned.x() + off.x(),
|
||||||
inter.y() - aligned.y() + off.y(), inter.width(), inter.height());
|
inter.y() - aligned.y() + off.y(), bgp.width() , bgp.height());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6107,6 +6114,28 @@ bool QStyleSheetStyle::isNaturalChild(const QObject *obj)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPixmap QStyleSheetStyle::loadPixmap(const QString &fileName, const QObject *context)
|
||||||
|
{
|
||||||
|
qreal ratio = -1.0;
|
||||||
|
if (const QWidget *widget = qobject_cast<const QWidget *>(context)) {
|
||||||
|
if (QScreen *screen = QApplication::screenAt(widget->mapToGlobal(QPoint(0, 0))))
|
||||||
|
ratio = screen->devicePixelRatio();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ratio < 0) {
|
||||||
|
if (const QApplication *app = qApp)
|
||||||
|
ratio = app->devicePixelRatio();
|
||||||
|
else
|
||||||
|
ratio = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal sourceDevicePixelRatio = 1.0;
|
||||||
|
QString resolvedFileName = qt_findAtNxFile(fileName, ratio, &sourceDevicePixelRatio);
|
||||||
|
QPixmap pixmap(resolvedFileName);
|
||||||
|
pixmap.setDevicePixelRatio(sourceDevicePixelRatio);
|
||||||
|
return pixmap;
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#include "moc_qstylesheetstyle_p.cpp"
|
#include "moc_qstylesheetstyle_p.cpp"
|
||||||
|
@ -167,6 +167,7 @@ private:
|
|||||||
|
|
||||||
static Qt::Alignment resolveAlignment(Qt::LayoutDirection, Qt::Alignment);
|
static Qt::Alignment resolveAlignment(Qt::LayoutDirection, Qt::Alignment);
|
||||||
static bool isNaturalChild(const QObject *obj);
|
static bool isNaturalChild(const QObject *obj);
|
||||||
|
static QPixmap loadPixmap(const QString &fileName, const QObject *context);
|
||||||
bool initObject(const QObject *obj) const;
|
bool initObject(const QObject *obj) const;
|
||||||
public:
|
public:
|
||||||
static int numinstances;
|
static int numinstances;
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 299 B After Width: | Height: | Size: 300 B |
Binary file not shown.
After Width: | Height: | Size: 318 B |
@ -2,5 +2,6 @@
|
|||||||
<RCC version="1.0">
|
<RCC version="1.0">
|
||||||
<qresource>
|
<qresource>
|
||||||
<file>images/testimage.png</file>
|
<file>images/testimage.png</file>
|
||||||
|
<file>images/testimage@2x.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
@ -33,6 +33,7 @@
|
|||||||
#include <QMetaObject>
|
#include <QMetaObject>
|
||||||
|
|
||||||
#include <private/qstylesheetstyle_p.h>
|
#include <private/qstylesheetstyle_p.h>
|
||||||
|
#include <private/qhighdpiscaling_p.h>
|
||||||
#include <QtTest/private/qtesthelpers_p.h>
|
#include <QtTest/private/qtesthelpers_p.h>
|
||||||
|
|
||||||
using namespace QTestPrivate;
|
using namespace QTestPrivate;
|
||||||
@ -101,6 +102,9 @@ private slots:
|
|||||||
void styleSheetTargetAttribute();
|
void styleSheetTargetAttribute();
|
||||||
void unpolish();
|
void unpolish();
|
||||||
|
|
||||||
|
void highdpiImages_data();
|
||||||
|
void highdpiImages();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QColor COLOR(const QWidget& w) {
|
QColor COLOR(const QWidget& w) {
|
||||||
w.ensurePolished();
|
w.ensurePolished();
|
||||||
@ -2066,6 +2070,35 @@ void tst_QStyleSheetStyle::unpolish()
|
|||||||
QCOMPARE(w.minimumWidth(), 0);
|
QCOMPARE(w.minimumWidth(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QStyleSheetStyle::highdpiImages_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<qreal>("screenFactor");
|
||||||
|
QTest::addColumn<QColor>("color");
|
||||||
|
|
||||||
|
QTest::newRow("highdpi") << 2.0 << QColor(0x00, 0xFF, 0x00);
|
||||||
|
QTest::newRow("lowdpi") << 1.0 << QColor(0xFF, 0x00, 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QStyleSheetStyle::highdpiImages()
|
||||||
|
{
|
||||||
|
QFETCH(qreal, screenFactor);
|
||||||
|
QFETCH(QColor, color);
|
||||||
|
|
||||||
|
QWidget w;
|
||||||
|
QScreen *screen = QGuiApplication::screenAt(w.pos());
|
||||||
|
QHighDpiScaling::setScreenFactor(screen, screenFactor);
|
||||||
|
w.setStyleSheet("QWidget { background-image: url(\":/images/testimage.png\"); }");
|
||||||
|
w.show();
|
||||||
|
|
||||||
|
QVERIFY(QTest::qWaitForWindowExposed(&w));
|
||||||
|
QImage image(w.size(), QImage::Format_ARGB32);
|
||||||
|
w.render(&image);
|
||||||
|
QVERIFY(testForColors(image, color));
|
||||||
|
|
||||||
|
QHighDpiScaling::setScreenFactor(screen, 1.0);
|
||||||
|
QHighDpiScaling::updateHighDpiScaling(); // reset to normal
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QStyleSheetStyle)
|
QTEST_MAIN(tst_QStyleSheetStyle)
|
||||||
#include "tst_qstylesheetstyle.moc"
|
#include "tst_qstylesheetstyle.moc"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user