Merge lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/trunk-fix-icon-svg-image-loading into lp:ubuntu-ui-toolkit/staging

Proposed by Michał Sawicz
Status: Rejected
Rejected by: Michał Sawicz
Proposed branch: lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/trunk-fix-icon-svg-image-loading
Merge into: lp:ubuntu-ui-toolkit/staging
Diff against target: 280 lines (+77/-66)
3 files modified
src/Ubuntu/Components/plugin/unitythemeiconprovider.cpp (+61/-51)
src/Ubuntu/Components/plugin/unitythemeiconprovider.h (+1/-1)
tests/unit_x11/tst_iconprovider/tst_iconprovider.cpp (+15/-14)
To merge this branch: bzr merge lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/trunk-fix-icon-svg-image-loading
Reviewer Review Type Date Requested Status
Michał Sawicz Disapprove
ubuntu-sdk-build-bot continuous-integration Approve
Review via email: mp+292509@code.launchpad.net

Commit message

Adjust the UnityThemeIconProvider to duplicate Qt's own image loading behaviour, fixes some image scaling issues

Description of the change

The Pixmap->Image thing might be unnecessary, but
1) I wanted to duplicate exactly Qt's behaviour and
2) Qt converts the QPixmap to a QImage internally before uploading to texture

To post a comment you must log in.
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
1283. By Michał Sawicz

Make tst_IconProvider talk in QImage

Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
1284. By Lukáš Tinkl

fix loading & scaling SVGs

Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
1285. By Lukáš Tinkl

add a test with wrong aspect ratio that returns a correct one

1286. By Lukáš Tinkl

add a test that passes here and fails with trunk

Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :
review: Disapprove

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/Ubuntu/Components/plugin/unitythemeiconprovider.cpp'
2--- src/Ubuntu/Components/plugin/unitythemeiconprovider.cpp 2016-03-16 14:24:15 +0000
3+++ src/Ubuntu/Components/plugin/unitythemeiconprovider.cpp 2016-04-27 16:15:41 +0000
4@@ -21,8 +21,7 @@
5 #include <QDir>
6 #include <QFileInfo>
7 #include <QSettings>
8-#include <QSvgRenderer>
9-#include <QPainter>
10+#include <QImageReader>
11 #include <QStandardPaths>
12 #include <QtDebug>
13
14@@ -48,27 +47,27 @@
15 // Does a breadth-first search for an icon with any name in @names. Parent
16 // themes are only looked at if the current theme doesn't contain any icon
17 // in @names.
18- QPixmap findBestIcon(const QStringList &names, const QSize &size, QSet<QString> *alreadySearchedThemes)
19+ QImage findBestIcon(const QStringList &names, QSize *impsize, const QSize &size, QSet<QString> *alreadySearchedThemes)
20 {
21 if (alreadySearchedThemes) {
22 if (alreadySearchedThemes->contains(name))
23- return QPixmap();
24+ return QImage();
25 alreadySearchedThemes->insert(name);
26 }
27
28 Q_FOREACH(const QString &name, names) {
29- QPixmap pixmap = lookupIcon(name, size);
30- if (!pixmap.isNull())
31- return pixmap;
32+ QImage image = lookupIcon(name, impsize, size);
33+ if (!image.isNull())
34+ return image;
35 }
36
37 Q_FOREACH(IconThemePointer theme, parents) {
38- QPixmap pixmap = theme->findBestIcon(names, size, alreadySearchedThemes);
39- if (!pixmap.isNull())
40- return pixmap;
41+ QImage image = theme->findBestIcon(names, impsize, size, alreadySearchedThemes);
42+ if (!image.isNull())
43+ return image;
44 }
45
46- return QPixmap();
47+ return QImage();
48 }
49
50 private:
51@@ -82,7 +81,7 @@
52
53 IconTheme(const QString &name): name(name)
54 {
55- QStringList paths = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
56+ const QStringList paths = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
57
58 Q_FOREACH(const QString &path, paths) {
59 QDir dir(path + "/icons/" + name);
60@@ -130,30 +129,42 @@
61 return Fixed;
62 }
63
64- static QPixmap loadIcon(const QString &filename, const QSize &size)
65+ static QImage loadIcon(const QString &filename, QSize *impsize, const QSize &requestSize)
66 {
67- QPixmap pixmap;
68-
69- const bool anyZero = size.width() <= 0 || size.height() <= 0;
70- const Qt::AspectRatioMode scaleMode = anyZero ? Qt::KeepAspectRatioByExpanding : Qt::KeepAspectRatio;
71-
72- if (filename.endsWith(QLatin1String(".png"))) {
73- pixmap = QPixmap(filename);
74- if (!pixmap.isNull() && !size.isNull() && (pixmap.width() != size.width() || pixmap.height() != size.height())) {
75- const QSize newSize = pixmap.size().scaled(size.width(), size.height(), scaleMode);
76- pixmap = pixmap.scaled(newSize);
77- }
78- }
79- else if (filename.endsWith(QLatin1String(".svg"))) {
80- QSvgRenderer renderer(filename);
81- pixmap = QPixmap(renderer.defaultSize().scaled(size.width(), size.height(), scaleMode));
82- pixmap.fill(Qt::transparent);
83- QPainter painter(&pixmap);
84- renderer.render(&painter);
85- painter.end();
86- }
87-
88- return pixmap;
89+ QImage image;
90+ QImageReader imgio(filename);
91+
92+ const bool force_scale = imgio.format() == QStringLiteral("svg")
93+ || imgio.format() == QStringLiteral("svgz");
94+
95+ if (requestSize.width() > 0 || requestSize.height() > 0) {
96+ QSize s = imgio.size();
97+ qreal ratio = 0.0;
98+ if (requestSize.width() > 0 && (force_scale || requestSize.width() < s.width())) {
99+ ratio = qreal(requestSize.width())/s.width();
100+ }
101+ if (requestSize.height() > 0 && (force_scale || requestSize.height() < s.height())) {
102+ qreal hr = qreal(requestSize.height())/s.height();
103+ if (ratio == 0.0 || hr < ratio)
104+ ratio = hr;
105+ }
106+ if (ratio > 0.0) {
107+ s.setHeight(qRound(s.height() * ratio));
108+ s.setWidth(qRound(s.width() * ratio));
109+ imgio.setScaledSize(s);
110+ }
111+ }
112+
113+ if (impsize)
114+ *impsize = imgio.scaledSize();
115+
116+ if (imgio.read(&image)) {
117+ if (impsize)
118+ *impsize = image.size();
119+ return image;
120+ } else {
121+ return QImage();
122+ }
123 }
124
125 QString lookupIconFile(const QString &dir, const QString &name)
126@@ -174,16 +185,16 @@
127 return QString();
128 }
129
130- QPixmap lookupIcon(const QString &iconName, const QSize &size)
131+ QImage lookupIcon(const QString &iconName, QSize *impsize, const QSize &size)
132 {
133 const int iconSize = qMax(size.width(), size.height());
134 if (iconSize > 0)
135- return lookupBestMatchingIcon(iconName, size);
136+ return lookupBestMatchingIcon(iconName, impsize, size);
137 else
138- return lookupLargestIcon(iconName);
139+ return lookupLargestIcon(iconName, impsize);
140 }
141
142- QPixmap lookupBestMatchingIcon(const QString &iconName, const QSize &size)
143+ QImage lookupBestMatchingIcon(const QString &iconName, QSize *impsize, const QSize &size)
144 {
145 int minDistance = 10000;
146 QString bestFilename;
147@@ -205,12 +216,12 @@
148 }
149
150 if (!bestFilename.isNull())
151- return loadIcon(bestFilename, size);
152+ return loadIcon(bestFilename, impsize, size);
153
154- return QPixmap();
155+ return QImage();
156 }
157
158- QPixmap lookupLargestIcon(const QString &iconName)
159+ QImage lookupLargestIcon(const QString &iconName, QSize *impsize)
160 {
161 int maxSize = 0;
162 QString bestFilename;
163@@ -228,9 +239,9 @@
164 }
165
166 if (!bestFilename.isNull())
167- return loadIcon(bestFilename, QSize(maxSize, maxSize));
168+ return loadIcon(bestFilename, impsize, QSize(maxSize, maxSize));
169
170- return QPixmap();
171+ return QImage();
172 }
173
174 int directorySizeDistance(const Directory &dir, const QSize &iconSize)
175@@ -258,24 +269,23 @@
176 };
177
178 UnityThemeIconProvider::UnityThemeIconProvider(const QString &themeName):
179- QQuickImageProvider(QQuickImageProvider::Pixmap)
180+ QQuickImageProvider(QQuickImageProvider::Image)
181 {
182 theme = IconTheme::get(themeName);
183 }
184
185-QPixmap UnityThemeIconProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
186+QImage UnityThemeIconProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
187 {
188 // The hicolor theme will be searched last as per
189 // https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html
190 QSet<QString> alreadySearchedThemes;
191 const QStringList names = id.split(QLatin1Char(','), QString::SkipEmptyParts);
192- QPixmap pixmap = theme->findBestIcon(names, requestedSize, &alreadySearchedThemes);
193+ QImage image = theme->findBestIcon(names, size, requestedSize, &alreadySearchedThemes);
194
195- if (pixmap.isNull()) {
196+ if (image.isNull()) {
197 IconTheme::IconThemePointer theme = IconTheme::get(QStringLiteral("hicolor"));
198- return theme->findBestIcon(names, requestedSize, nullptr);
199+ return theme->findBestIcon(names, size, requestedSize, nullptr);
200 }
201
202- *size = pixmap.size();
203- return pixmap;
204+ return image;
205 }
206
207=== modified file 'src/Ubuntu/Components/plugin/unitythemeiconprovider.h'
208--- src/Ubuntu/Components/plugin/unitythemeiconprovider.h 2016-03-16 14:24:15 +0000
209+++ src/Ubuntu/Components/plugin/unitythemeiconprovider.h 2016-04-27 16:15:41 +0000
210@@ -25,7 +25,7 @@
211 {
212 public:
213 UnityThemeIconProvider(const QString &themeName = QStringLiteral("suru"));
214- QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize);
215+ QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
216
217 private:
218 QSharedPointer<class IconTheme> theme;
219
220=== modified file 'tests/unit_x11/tst_iconprovider/tst_iconprovider.cpp'
221--- tests/unit_x11/tst_iconprovider/tst_iconprovider.cpp 2016-03-16 15:02:35 +0000
222+++ tests/unit_x11/tst_iconprovider/tst_iconprovider.cpp 2016-04-27 16:15:41 +0000
223@@ -39,14 +39,15 @@
224 QTest::addColumn<QSize>("requestSize");
225 QTest::addColumn<QSize>("resultSize");
226
227- QTest::newRow("battery0") << "battery-100-charging" << QSize(-1, -1) << QSize(256, 165);
228- QTest::newRow("battery1") << "battery-100-charging" << QSize(-1, 16) << QSize(24, 16);
229+ QTest::newRow("battery0") << "battery-100-charging" << QSize(-1, -1) << QSize(256, 166);
230+ QTest::newRow("battery1") << "battery-100-charging" << QSize(-1, 16) << QSize(25, 16);
231 QTest::newRow("battery2") << "battery-100-charging" << QSize(16, -1) << QSize(16, 10);
232- QTest::newRow("battery3") << "battery-100-charging" << QSize(0, 16) << QSize(24, 16);
233+ QTest::newRow("battery3") << "battery-100-charging" << QSize(0, 16) << QSize(25, 16);
234 QTest::newRow("battery4") << "battery-100-charging" << QSize(16, 0) << QSize(16, 10);
235 QTest::newRow("battery5") << "battery-100-charging" << QSize(24, 16) << QSize(24, 16);
236- QTest::newRow("battery6") << "battery-100-charging" << QSize(24, 24) << QSize(24, 15);
237+ QTest::newRow("battery6") << "battery-100-charging" << QSize(24, 24) << QSize(24, 16);
238 QTest::newRow("battery7") << "battery-100-charging" << QSize(37, 24) << QSize(37, 24);
239+ QTest::newRow("battery8") << "battery-100-charging" << QSize(15, 512) << QSize(15, 10);
240
241 QTest::newRow("gallery0") << "gallery-app" << QSize(-1, -1) << QSize(512, 512);
242 QTest::newRow("gallery1") << "gallery-app" << QSize(-1, 16) << QSize(16, 16);
243@@ -65,13 +66,13 @@
244
245 UnityThemeIconProvider provider("mockTheme");
246 QSize returnedSize;
247- QPixmap p = provider.requestPixmap(icon, &returnedSize, requestSize);
248- QCOMPARE(p.size(), resultSize);
249+ QImage i = provider.requestImage(icon, &returnedSize, requestSize);
250+ QCOMPARE(i.size(), resultSize);
251 QCOMPARE(returnedSize, resultSize);
252
253 // Search again to make sure subsequent searches still work
254- p = provider.requestPixmap(icon, &returnedSize, requestSize);
255- QCOMPARE(p.size(), resultSize);
256+ i = provider.requestImage(icon, &returnedSize, requestSize);
257+ QCOMPARE(i.size(), resultSize);
258 QCOMPARE(returnedSize, resultSize);
259 }
260
261@@ -82,14 +83,14 @@
262
263 // myapp is in MockTheme3 (white) and hicolor (black)
264 // MockTheme3 one is returned since hicolor is last per spec
265- QPixmap p = provider.requestPixmap("myapp", &returnedSize, QSize(-1, -1));
266- QVERIFY(!p.isNull());
267- QCOMPARE(QColor(p.toImage().pixel(0,0)), QColor(Qt::white));
268+ QImage i = provider.requestImage("myapp", &returnedSize, QSize(-1, -1));
269+ QVERIFY(!i.isNull());
270+ QCOMPARE(QColor(i.pixel(0,0)), QColor(Qt::white));
271
272 // myapp2 is only in hicolor (black) so that's the one returned
273- p = provider.requestPixmap("myapp2", &returnedSize, QSize(-1, -1));
274- QVERIFY(!p.isNull());
275- QCOMPARE(QColor(p.toImage().pixel(0,0)), QColor(Qt::black));
276+ i = provider.requestImage("myapp2", &returnedSize, QSize(-1, -1));
277+ QVERIFY(!i.isNull());
278+ QCOMPARE(QColor(i.pixel(0,0)), QColor(Qt::black));
279 }
280 };
281

Subscribers

People subscribed via source and target branches