Changeset View
Changeset View
Standalone View
Standalone View
src/kiconloader.cpp
Show First 20 Lines • Show All 91 Lines • ▼ Show 20 Line(s) | |||||
314 | void normalizeIconMetadata(KIconLoader::Group &group, int &size, int &state) const; | 314 | void normalizeIconMetadata(KIconLoader::Group &group, int &size, int &state) const; | ||
315 | 315 | | |||
316 | /** | 316 | /** | ||
317 | * @internal | 317 | * @internal | ||
318 | * Used with KIconLoader::loadIcon to get a base key name from the given | 318 | * Used with KIconLoader::loadIcon to get a base key name from the given | ||
319 | * icon metadata. Ensure the metadata is normalized first. | 319 | * icon metadata. Ensure the metadata is normalized first. | ||
320 | */ | 320 | */ | ||
321 | QString makeCacheKey(const QString &name, KIconLoader::Group group, const QStringList &overlays, | 321 | QString makeCacheKey(const QString &name, KIconLoader::Group group, const QStringList &overlays, | ||
322 | int size, int state) const; | 322 | int size, qreal scale, int state) const; | ||
323 | 323 | | |||
324 | /** | 324 | /** | ||
325 | * @internal | 325 | * @internal | ||
326 | * If the icon is an SVG file, process it generating a stylesheet | 326 | * If the icon is an SVG file, process it generating a stylesheet | ||
327 | * following the current color scheme. in this case the icon can use named colors | 327 | * following the current color scheme. in this case the icon can use named colors | ||
328 | * as text color, background color, highlight color, positive/neutral/negative color | 328 | * as text color, background color, highlight color, positive/neutral/negative color | ||
329 | * @see KColorScheme | 329 | * @see KColorScheme | ||
330 | */ | 330 | */ | ||
331 | QByteArray processSvg(const QString &path, KIconLoader::States state) const; | 331 | QByteArray processSvg(const QString &path, KIconLoader::States state) const; | ||
332 | 332 | | |||
333 | /** | 333 | /** | ||
334 | * @internal | 334 | * @internal | ||
335 | * Creates the QImage for @p path, using SVG rendering as appropriate. | 335 | * Creates the QImage for @p path, using SVG rendering as appropriate. | ||
336 | * @p size is only used for scalable images, but if non-zero non-scalable | 336 | * @p size is only used for scalable images, but if non-zero non-scalable | ||
337 | * images will be resized anyways. | 337 | * images will be resized anyways. | ||
338 | */ | 338 | */ | ||
339 | QImage createIconImage(const QString &path, int size = 0, KIconLoader::States state = KIconLoader::DefaultState); | 339 | QImage createIconImage(const QString &path, int size = 0, qreal scale = 1.0, KIconLoader::States state = KIconLoader::DefaultState); | ||
340 | 340 | | |||
341 | /** | 341 | /** | ||
342 | * @internal | 342 | * @internal | ||
343 | * Adds an QPixmap with its associated path to the shared icon cache. | 343 | * Adds an QPixmap with its associated path to the shared icon cache. | ||
344 | */ | 344 | */ | ||
345 | void insertCachedPixmapWithPath(const QString &key, const QPixmap &data, const QString &path); | 345 | void insertCachedPixmapWithPath(const QString &key, const QPixmap &data, const QString &path); | ||
346 | 346 | | |||
347 | /** | 347 | /** | ||
▲ Show 20 Lines • Show All 182 Lines • ▼ Show 20 Line(s) | 842 | if (group < 0) { | |||
843 | qWarning() << "Neither size nor group specified!"; | 843 | qWarning() << "Neither size nor group specified!"; | ||
844 | group = KIconLoader::Desktop; | 844 | group = KIconLoader::Desktop; | ||
845 | } | 845 | } | ||
846 | size = mpGroups[group].size; | 846 | size = mpGroups[group].size; | ||
847 | } | 847 | } | ||
848 | } | 848 | } | ||
849 | 849 | | |||
850 | QString KIconLoaderPrivate::makeCacheKey(const QString &name, KIconLoader::Group group, | 850 | QString KIconLoaderPrivate::makeCacheKey(const QString &name, KIconLoader::Group group, | ||
851 | const QStringList &overlays, int size, int state) const | 851 | const QStringList &overlays, int size, qreal scale, int state) const | ||
852 | { | 852 | { | ||
853 | // The KSharedDataCache is shared so add some namespacing. The following code | 853 | // The KSharedDataCache is shared so add some namespacing. The following code | ||
854 | // uses QStringBuilder (new in Qt 4.6) | 854 | // uses QStringBuilder (new in Qt 4.6) | ||
855 | 855 | | |||
856 | return (group == KIconLoader::User | 856 | return (group == KIconLoader::User | ||
857 | ? QLatin1Literal("$kicou_") | 857 | ? QLatin1Literal("$kicou_") | ||
858 | : QLatin1Literal("$kico_")) | 858 | : QLatin1Literal("$kico_")) | ||
859 | % name | 859 | % name | ||
860 | % QLatin1Char('_') | 860 | % QLatin1Char('_') | ||
861 | % QString::number(size) | 861 | % QString::number(size) | ||
862 | % QLatin1Char('@') | ||||
863 | % QString::number(scale) | ||||
cfeck: Please use some rounding here. Scaling factors such as 1.4 cannot be represented exactly. | |||||
Just checked that the default precision is 6 digits, so maybe not that important. cfeck: Just checked that the default precision is 6 digits, so maybe not that important. | |||||
862 | % QLatin1Char('_') | 864 | % QLatin1Char('_') | ||
863 | % overlays.join(QStringLiteral("_")) | 865 | % overlays.join(QStringLiteral("_")) | ||
864 | % (group >= 0 ? mpEffect.fingerprint(group, state) | 866 | % (group >= 0 ? mpEffect.fingerprint(group, state) | ||
865 | : NULL_EFFECT_FINGERPRINT()) | 867 | : NULL_EFFECT_FINGERPRINT()) | ||
866 | % QLatin1Char('_') | 868 | % QLatin1Char('_') | ||
867 | % paletteId(qApp->palette()) | 869 | % paletteId(qApp->palette()) | ||
868 | % (q->theme() && q->theme()->followsColorScheme() && state == KIconLoader::SelectedState ? QStringLiteral("_selected") : QString()); | 870 | % (q->theme() && q->theme()->followsColorScheme() && state == KIconLoader::SelectedState ? QStringLiteral("_selected") : QString()); | ||
869 | } | 871 | } | ||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Line(s) | 914 | } else if (reader.tokenType() != QXmlStreamReader::Invalid) { | |||
913 | writer.writeCurrentToken(reader); | 915 | writer.writeCurrentToken(reader); | ||
914 | } | 916 | } | ||
915 | } | 917 | } | ||
916 | buffer.close(); | 918 | buffer.close(); | ||
917 | 919 | | |||
918 | return processedContents; | 920 | return processedContents; | ||
919 | } | 921 | } | ||
920 | 922 | | |||
921 | QImage KIconLoaderPrivate::createIconImage(const QString &path, int size, KIconLoader::States state) | 923 | QImage KIconLoaderPrivate::createIconImage(const QString &path, int size, qreal scale, KIconLoader::States state) | ||
922 | { | 924 | { | ||
923 | //TODO: metadata in the theme to make it do this only if explicitly supported? | 925 | //TODO: metadata in the theme to make it do this only if explicitly supported? | ||
924 | QScopedPointer<QImageReader> reader; | 926 | QScopedPointer<QImageReader> reader; | ||
925 | QBuffer buffer; | 927 | QBuffer buffer; | ||
926 | 928 | | |||
927 | if (q->theme()->followsColorScheme() && (path.endsWith(QLatin1String("svg")) || path.endsWith(QLatin1String("svgz")))) { | 929 | if (q->theme()->followsColorScheme() && (path.endsWith(QLatin1String("svg")) || path.endsWith(QLatin1String("svgz")))) { | ||
928 | buffer.setData(processSvg(path, state)); | 930 | buffer.setData(processSvg(path, state)); | ||
929 | reader.reset(new QImageReader(&buffer)); | 931 | reader.reset(new QImageReader(&buffer)); | ||
930 | } else { | 932 | } else { | ||
931 | reader.reset(new QImageReader(path)); | 933 | reader.reset(new QImageReader(path)); | ||
932 | } | 934 | } | ||
933 | 935 | | |||
934 | if (!reader->canRead()) { | 936 | if (!reader->canRead()) { | ||
935 | return QImage(); | 937 | return QImage(); | ||
936 | } | 938 | } | ||
937 | 939 | | |||
938 | if (size != 0) { | 940 | if (size != 0) { | ||
939 | reader->setScaledSize(QSize(size, size)); | 941 | reader->setScaledSize(QSize(size * scale, size * scale)); | ||
940 | } | 942 | } | ||
941 | 943 | | |||
942 | return reader->read(); | 944 | return reader->read(); | ||
943 | } | 945 | } | ||
944 | 946 | | |||
945 | void KIconLoaderPrivate::insertCachedPixmapWithPath( | 947 | void KIconLoaderPrivate::insertCachedPixmapWithPath( | ||
946 | const QString &key, | 948 | const QString &key, | ||
947 | const QPixmap &data, | 949 | const QPixmap &data, | ||
▲ Show 20 Lines • Show All 182 Lines • ▼ Show 20 Line(s) | 1221 | { | |||
1237 | } | 1239 | } | ||
1238 | return pixmap; | 1240 | return pixmap; | ||
1239 | } | 1241 | } | ||
1240 | 1242 | | |||
1241 | QPixmap KIconLoader::loadIcon(const QString &_name, KIconLoader::Group group, int size, | 1243 | QPixmap KIconLoader::loadIcon(const QString &_name, KIconLoader::Group group, int size, | ||
1242 | int state, const QStringList &overlays, | 1244 | int state, const QStringList &overlays, | ||
1243 | QString *path_store, bool canReturnNull) const | 1245 | QString *path_store, bool canReturnNull) const | ||
1244 | { | 1246 | { | ||
1247 | return loadIcon(_name, group, 1.0 /*scale*/, size, state, overlays, path_store, canReturnNull); | ||||
1248 | } | ||||
1249 | | ||||
1250 | QPixmap KIconLoader::loadIcon(const QString &_name, KIconLoader::Group group, qreal scale, int size, | ||||
1251 | int state, const QStringList &overlays, | ||||
1252 | QString *path_store, bool canReturnNull) const | ||||
1253 | { | ||||
1245 | QString name = _name; | 1254 | QString name = _name; | ||
1246 | bool favIconOverlay = false; | 1255 | bool favIconOverlay = false; | ||
1247 | 1256 | | |||
1248 | if (size < 0 || _name.isEmpty()) { | 1257 | if (size < 0 || _name.isEmpty()) { | ||
1249 | return QPixmap(); | 1258 | return QPixmap(); | ||
1250 | } | 1259 | } | ||
1251 | 1260 | | |||
1252 | /* | 1261 | /* | ||
1253 | * This method works in a kind of pipeline, with the following steps: | 1262 | * This method works in a kind of pipeline, with the following steps: | ||
1254 | * 1. Sanity checks. | 1263 | * 1. Sanity checks. | ||
1255 | * 2. Convert _name, group, size, etc. to a key name. | 1264 | * 2. Convert _name, group, size, etc. to a key name. | ||
cfeck: indent | |||||
1256 | * 3. Check if the key is already cached. | 1265 | * 3. Check if the key is already cached. | ||
1257 | * 4. If not, initialize the theme and find/load the icon. | 1266 | * 4. If not, initialize the theme and find/load the icon. | ||
1258 | * 4a Apply overlays | 1267 | * 4a Apply overlays | ||
1259 | * 4b Re-add to cache. | 1268 | * 4b Re-add to cache. | ||
1260 | */ | 1269 | */ | ||
1261 | 1270 | | |||
1262 | // Special case for absolute path icons. | 1271 | // Special case for absolute path icons. | ||
1263 | if (name.startsWith(QLatin1String("favicons/"))) { | 1272 | if (name.startsWith(QLatin1String("favicons/"))) { | ||
Show All 11 Lines | 1283 | if (name.isEmpty()) { | |||
1275 | return QPixmap(); | 1284 | return QPixmap(); | ||
1276 | } | 1285 | } | ||
1277 | 1286 | | |||
1278 | // May modify group, size, or state. This function puts them into sane | 1287 | // May modify group, size, or state. This function puts them into sane | ||
1279 | // states. | 1288 | // states. | ||
1280 | d->normalizeIconMetadata(group, size, state); | 1289 | d->normalizeIconMetadata(group, size, state); | ||
1281 | 1290 | | |||
1282 | // See if the image is already cached. | 1291 | // See if the image is already cached. | ||
1283 | QString key = d->makeCacheKey(name, group, overlays, size, state); | 1292 | QString key = d->makeCacheKey(name, group, overlays, size, scale, state); | ||
1284 | QPixmap pix; | 1293 | QPixmap pix; | ||
1294 | pix.setDevicePixelRatio(scale); | ||||
davidedmundson: I don't think you need this? | |||||
1295 | | ||||
1285 | bool iconWasUnknown = false; | 1296 | bool iconWasUnknown = false; | ||
1286 | QString path; | 1297 | QString path; | ||
1287 | 1298 | | |||
1288 | if (d->findCachedPixmapWithPath(key, pix, path)) { | 1299 | if (d->findCachedPixmapWithPath(key, pix, path)) {// skip cache | ||
cfeck: Is this a left-over change from disabling this check? | |||||
1289 | if (path_store) { | 1300 | if (path_store) { | ||
1290 | *path_store = path; | 1301 | *path_store = path; | ||
1291 | } | 1302 | } | ||
1292 | 1303 | | |||
1293 | if (!path.isEmpty()) { | 1304 | if (!path.isEmpty()) { | ||
1294 | return pix; | 1305 | return pix; | ||
1295 | } else { | 1306 | } else { | ||
1296 | // path is empty for "unknown" icons, which should be searched for | 1307 | // path is empty for "unknown" icons, which should be searched for | ||
Show All 31 Lines | |||||
1328 | // We keep going in the function so we can ensure this result gets cached. | 1339 | // We keep going in the function so we can ensure this result gets cached. | ||
1329 | if (path.isEmpty() && !canReturnNull) { | 1340 | if (path.isEmpty() && !canReturnNull) { | ||
1330 | path = d->unknownIconPath(size); | 1341 | path = d->unknownIconPath(size); | ||
1331 | iconWasUnknown = true; | 1342 | iconWasUnknown = true; | ||
1332 | } | 1343 | } | ||
1333 | 1344 | | |||
1334 | QImage img; | 1345 | QImage img; | ||
1335 | if (!path.isEmpty()) { | 1346 | if (!path.isEmpty()) { | ||
1336 | img = d->createIconImage(path, size, (KIconLoader::States)state); | 1347 | img = d->createIconImage(path, size, scale, (KIconLoader::States)state); | ||
1337 | } | 1348 | } | ||
1338 | 1349 | | |||
1339 | if (group >= 0) { | 1350 | if (group >= 0) { | ||
1340 | img = d->mpEffect.apply(img, group, state); | 1351 | img = d->mpEffect.apply(img, group, state); | ||
1341 | } | 1352 | } | ||
1342 | 1353 | | |||
1343 | if (favIconOverlay) { | 1354 | if (favIconOverlay) { | ||
1344 | QImage favIcon(name, "PNG"); | 1355 | QImage favIcon(name, "PNG"); | ||
1345 | if (!favIcon.isNull()) { // if favIcon not there yet, don't try to blend it | 1356 | if (!favIcon.isNull()) { // if favIcon not there yet, don't try to blend it | ||
1346 | QPainter p(&img); | 1357 | QPainter p(&img); | ||
1347 | 1358 | | |||
1348 | // Align the favicon overlay | 1359 | // Align the favicon overlay | ||
1349 | QRect r(favIcon.rect()); | 1360 | QRect r(favIcon.rect()); | ||
1350 | r.moveBottomRight(img.rect().bottomRight()); | 1361 | r.moveBottomRight(img.rect().bottomRight()); | ||
1351 | r.adjust(-1, -1, -1, -1); // Move off edge | 1362 | r.adjust(-1, -1, -1, -1); // Move off edge | ||
1352 | 1363 | | |||
1353 | // Blend favIcon over img. | 1364 | // Blend favIcon over img. | ||
1354 | p.drawImage(r, favIcon); | 1365 | p.drawImage(r, favIcon); | ||
1355 | } | 1366 | } | ||
1356 | } | 1367 | } | ||
1357 | 1368 | | |||
Why this line reverts D12002? volkov: Why this line reverts D12002? | |||||
broulik: Dunno, probably oversight or forgotten to rebase.. | |||||
Looks like a rebase: https://phabricator.kde.org/D6313?vs=31197&id=34779&whitespace=ignore-most#toc volkov: Looks like a rebase: https://phabricator.kde.org/D6313?vs=31197&id=34779&whitespace=ignore… | |||||
broulik: Feel free to submit a patch to restore this | |||||
1358 | pix = QPixmap::fromImage(img); | 1369 | pix = QPixmap::fromImage(img); | ||
1359 | 1370 | | |||
1360 | // TODO: If we make a loadIcon that returns the image we can convert | 1371 | // TODO: If we make a loadIcon that returns the image we can convert | ||
1361 | // drawOverlays to use the image instead of pixmaps as well so we don't | 1372 | // drawOverlays to use the image instead of pixmaps as well so we don't | ||
1362 | // have to transfer so much to the graphics card. | 1373 | // have to transfer so much to the graphics card. | ||
1363 | d->drawOverlays(this, group, state, pix, overlays); | 1374 | d->drawOverlays(this, group, state, pix, overlays); | ||
1364 | 1375 | | |||
1365 | // Don't add the path to our unknown icon to the cache, only cache the | 1376 | // Don't add the path to our unknown icon to the cache, only cache the | ||
▲ Show 20 Lines • Show All 70 Lines • Show Last 20 Lines |
Please use some rounding here. Scaling factors such as 1.4 cannot be represented exactly.
Either add some formatting specifiers, e.g. for three decimal places, or use qRound(scale * 1000).