61 #include <QMutex> |
61 #include <QMutex> |
62 #include <QMutexLocker> |
62 #include <QMutexLocker> |
63 |
63 |
64 #ifdef HB_NVG_CS_ICON |
64 #ifdef HB_NVG_CS_ICON |
65 #include "hbeglstate_p.h" |
65 #include "hbeglstate_p.h" |
|
66 #include "hbnvgrasterizer_p.h" |
66 #endif |
67 #endif |
67 |
68 |
68 // SVG animation is currently disabled because of bugs in QT's svg engine |
69 // SVG animation is currently disabled because of bugs in QT's svg engine |
69 #undef HB_SVG_ANIMATION |
70 #undef HB_SVG_ANIMATION |
70 |
71 |
|
72 //#define HB_ICON_CACHE_DEBUG |
|
73 |
71 // Icon name without extension |
74 // Icon name without extension |
72 static const char *s_unknown = "unknown"; |
75 static const char *s_unknown = "unknown"; |
73 |
76 |
74 /*! |
77 /*! |
75 \class HbIconLoader |
78 \class HbIconLoader |
76 |
79 |
77 \brief HbIconLoader loads icons according to the Freedesktop Icon Theme Specification |
80 \brief HbIconLoader loads and caches vector and raster icons |
|
81 either via the Theme Server or directly from files/resources. |
78 |
82 |
79 \internal |
83 \internal |
80 */ |
84 */ |
81 |
85 |
82 // Allocated dynamically so it can be deleted before the application object is destroyed. |
86 // Allocated dynamically so it can be deleted before the application object is destroyed. |
83 // Deleting it later causes segmentation fault. |
87 // Deleting it later causes segmentation fault. |
84 static HbIconLoader *theLoader = 0; |
88 static HbIconLoader *theLoader = 0; |
85 |
89 static bool loaderDestroyed = false; |
86 /* |
|
87 * Client side caching of sgimage icon required, as sgimage lite cannot be |
|
88 * opened multiple times |
|
89 * |
|
90 * It is also beneficial for performance, because it reduces IPC in certain |
|
91 * cases. |
|
92 * |
|
93 * Note that by default this is not a permanent cache, i.e. when an iconimpl's |
|
94 * refcount reaches zero it is removed from the cache. This means that the |
|
95 * cache is beneficial for having the same icon rendered by two or more HbIcons |
|
96 * at the same time (very typical in some itemview (e.g. list widget) cases), |
|
97 * but it would not benefit a load-unload-load scenario because the icon is |
|
98 * removed from the cache during the unload when there are no references |
|
99 * anymore. |
|
100 * |
|
101 * However the cachekeeper below will change this behavior, preventing refcounts |
|
102 * reaching zero in unLoadIcon(), so this cache may contain also icons that are |
|
103 * not really in use and are only referenced by the cachekeeper. This is |
|
104 * required for further reduction of IPC calls. |
|
105 */ |
|
106 static QHash<QByteArray, HbIconImpl *> iconImplCache; |
|
107 |
|
108 // The global cachekeeper instance will hold references to icons that would |
|
109 // normally be unloaded (i.e. mIcons will contain icons with refcount 1). |
|
110 // |
|
111 // Icons get added from unLoadIcon(), meaning that if the cachekeeper decides to |
|
112 // hold a reference then the icon is not really unloaded (and thus stays in |
|
113 // iconImplCache). |
|
114 // |
|
115 // When the icon gets referenced due to a cache hit, in loadIcon() and other |
|
116 // places, the icon is removed from the cachekeeper. |
|
117 class CacheKeeper { |
|
118 public: |
|
119 CacheKeeper() : mConsumption(0) { } |
|
120 void ref(HbIconImpl *icon); |
|
121 void unref(HbIconImpl *icon); |
|
122 void clear(); |
|
123 private: |
|
124 void del(HbIconImpl *icon, bool sendUnloadReq); |
|
125 QList<HbIconImpl *> mIcons; |
|
126 int mConsumption; |
|
127 }; |
|
128 |
|
129 Q_GLOBAL_STATIC(CacheKeeper, cacheKeeper) |
|
130 |
90 |
131 // The max consumption for the icons held by the cachekeeper, assuming that each |
91 // The max consumption for the icons held by the cachekeeper, assuming that each |
132 // icon is 32bpp. Note that the cachekeeper's content is cleared also when |
92 // icon is 32bpp. Note that the cachekeeper's content is cleared also when |
133 // losing visibility and when switching rendering mode. |
93 // losing visibility and when switching rendering mode. |
134 const int MAX_KEEPALIVE_CACHE_SIZE_BYTES = 1024 * 1024; // 1 MB |
94 const int MAX_KEEPALIVE_CACHE_SIZE_BYTES = 1024 * 1024; // 1 MB |
210 HbLocalLoaderThread mLocalLoaderThread; |
170 HbLocalLoaderThread mLocalLoaderThread; |
211 HbLocalIconLoader *mLocalLoader; |
171 HbLocalIconLoader *mLocalLoader; |
212 QMutex mLocalLoadMutex; |
172 QMutex mLocalLoadMutex; |
213 QMutex mIconSourceMutex; |
173 QMutex mIconSourceMutex; |
214 friend class HbLocalLoaderThread; |
174 friend class HbLocalLoaderThread; |
|
175 |
|
176 /* |
|
177 * Client side caching of sgimage icon required, as sgimage lite cannot be |
|
178 * opened multiple times |
|
179 * |
|
180 * It is also beneficial for performance, because it reduces IPC in certain |
|
181 * cases. |
|
182 * |
|
183 * Note that by default this is not a permanent cache, i.e. when an iconimpl's |
|
184 * refcount reaches zero it is removed from the cache. This means that the |
|
185 * cache is beneficial for having the same icon rendered by two or more HbIcons |
|
186 * at the same time (very typical in some itemview (e.g. list widget) cases), |
|
187 * but it would not benefit a load-unload-load scenario because the icon is |
|
188 * removed from the cache during the unload when there are no references |
|
189 * anymore. |
|
190 * |
|
191 * However the cachekeeper below will change this behavior, preventing refcounts |
|
192 * reaching zero in unLoadIcon(), so this cache may contain also icons that are |
|
193 * not really in use and are only referenced by the cachekeeper. This is |
|
194 * required for further reduction of IPC calls. |
|
195 */ |
|
196 QHash<QByteArray, HbIconImpl *> iconImplCache; |
|
197 |
|
198 // The global cachekeeper instance will hold references to icons that would |
|
199 // normally be unloaded (i.e. mIcons will contain icons with refcount 1). |
|
200 // |
|
201 // Icons get added from unLoadIcon(), meaning that if the cachekeeper decides to |
|
202 // hold a reference then the icon is not really unloaded (and thus stays in |
|
203 // iconImplCache). |
|
204 // |
|
205 // When the icon gets referenced due to a cache hit, in loadIcon() and other |
|
206 // places, the icon is removed from the cachekeeper. |
|
207 class CacheKeeper { |
|
208 public: |
|
209 CacheKeeper(HbIconLoaderPrivate *p) : mConsumption(0), mIconLoaderPrivate(p) { } |
|
210 void ref(HbIconImpl *icon); |
|
211 void unref(HbIconImpl *icon); |
|
212 void clear(); |
|
213 private: |
|
214 void del(HbIconImpl *icon, bool sendUnloadReq); |
|
215 QList<HbIconImpl *> mIcons; |
|
216 int mConsumption; |
|
217 HbIconLoaderPrivate *mIconLoaderPrivate; |
|
218 friend class HbIconLoaderPrivate; |
|
219 }; |
|
220 |
|
221 CacheKeeper cacheKeeper; |
215 }; |
222 }; |
216 |
223 |
217 void HbLocalLoaderThread::run() |
224 void HbLocalLoaderThread::run() |
218 { |
225 { |
219 setPriority(QThread::LowPriority); |
226 setPriority(QThread::LowPriority); |
605 |
619 |
606 // Set default rendering mode to EHWRendering |
620 // Set default rendering mode to EHWRendering |
607 renderMode = EHWRendering; |
621 renderMode = EHWRendering; |
608 |
622 |
609 // Delete the icon loader when the application is destroyed. |
623 // Delete the icon loader when the application is destroyed. |
610 connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(destroy())); |
624 connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), SLOT(destroy())); |
611 |
625 |
612 connect(HbLayoutDirectionNotifier::instance(), SIGNAL(layoutDirectionChangeStarted()), |
626 connect(HbLayoutDirectionNotifier::instance(), SIGNAL(layoutDirectionChangeStarted()), |
613 this, SLOT(updateLayoutDirection())); |
627 this, SLOT(updateLayoutDirection())); |
614 |
628 |
615 #ifdef HB_TOOL_INTERFACE |
629 HbTheme *theme = hbInstance->theme(); |
616 // This enables partial theme updates. |
630 connect(&theme->d_ptr->iconTheme, SIGNAL(iconsUpdated(QStringList)), SLOT(themeChange(QStringList))); |
617 connect(&hbInstance->theme()->d_ptr->iconTheme, SIGNAL(iconsUpdated(QStringList)), this, SLOT(themeChange(QStringList))); |
631 connect(theme, SIGNAL(changeFinished()), SLOT(themeChangeFinished())); |
618 #endif |
|
619 } |
632 } |
620 |
633 |
621 HbIconLoader::~HbIconLoader() |
634 HbIconLoader::~HbIconLoader() |
622 { |
635 { |
623 cacheKeeper()->clear(); |
|
624 delete d; |
636 delete d; |
|
637 loaderDestroyed = true; |
625 } |
638 } |
626 |
639 |
627 HbIconLoader *HbIconLoader::global() |
640 HbIconLoader *HbIconLoader::global() |
628 { |
641 { |
629 // Allocated dynamically so it can be deleted before the application object is destroyed. |
642 // Allocated dynamically so it can be deleted before the application object is destroyed. |
630 // Deleting it later causes segmentation fault. |
643 // Deleting it later causes segmentation fault. |
631 if (!theLoader) { |
644 // Once destroyed, creating the loader again must not be allowed (e.g. because there |
|
645 // may not be a QApplication instance anymore at this stage). It is normal to |
|
646 // return null pointer in this case, it can happen only during app shutdown. If anybody |
|
647 // is using HbIconLoader::global() from destructors, they have to be prepared for the |
|
648 // null ptr result too. |
|
649 if (!theLoader && !loaderDestroyed) { |
632 theLoader = new HbIconLoader; |
650 theLoader = new HbIconLoader; |
633 } |
651 } |
634 |
652 |
635 return theLoader; |
653 return theLoader; |
636 } |
654 } |
782 size = size * (qreal)(d->resolution) / (qreal)(d->sourceResolution) * d->zoom; |
800 size = size * (qreal)(d->resolution) / (qreal)(d->sourceResolution) * d->zoom; |
783 } |
801 } |
784 |
802 |
785 void HbIconLoader::themeChange(const QStringList &updatedFiles) |
803 void HbIconLoader::themeChange(const QStringList &updatedFiles) |
786 { |
804 { |
787 foreach(HbFrameDrawerPrivate * frameDrawer, frameDrawerInstanceList) frameDrawer->themeChange(updatedFiles); |
805 // For icons, the content is dropped in HbIconEngine. |
|
806 // For framedrawers, HbFrameItem notifies the framedrawer when the theme changes. |
|
807 // This below is only needed to support partial theme updates for framedrawers in external tools. |
|
808 // (standalone framedrawers do not update automatically, except in tools) |
|
809 #ifdef HB_TOOL_INTERFACE |
|
810 foreach(HbFrameDrawerPrivate * frameDrawer, frameDrawerInstanceList) { |
|
811 frameDrawer->themeChange(updatedFiles); |
|
812 } |
|
813 #else |
|
814 Q_UNUSED(updatedFiles); |
|
815 #endif |
|
816 } |
|
817 |
|
818 void HbIconLoader::themeChangeFinished() |
|
819 { |
|
820 #ifdef HB_ICON_CACHE_DEBUG |
|
821 qDebug("HbIconLoader::themeChangeFinished: dropping unused icons"); |
|
822 #endif |
|
823 // We need to drop unused icons to prevent reusing them now that the theme is different. |
|
824 // Doing it in themeChange() would not be right, it would be too early, |
|
825 // because unloading would make the dropped icons unused (but referenced) so |
|
826 // we would end up with reusing the old graphics. This here is safe. |
|
827 d->cacheKeeper.clear(); |
788 } |
828 } |
789 |
829 |
790 void HbIconLoader::destroy() |
830 void HbIconLoader::destroy() |
791 { |
831 { |
792 if (theLoader) { |
832 if (theLoader) { |
827 * Removes the IconImpl entry from the client side cache |
866 * Removes the IconImpl entry from the client side cache |
828 */ |
867 */ |
829 void HbIconLoader::removeItemInCache(HbIconImpl *iconImpl) |
868 void HbIconLoader::removeItemInCache(HbIconImpl *iconImpl) |
830 { |
869 { |
831 if (iconImpl) { |
870 if (iconImpl) { |
832 iconImplCache.remove(iconImplCache.key(iconImpl)); |
871 if (d->iconImplCache.remove(d->iconImplCache.key(iconImpl)) > 0) { |
|
872 #ifdef HB_ICON_CACHE_DEBUG |
|
873 qDebug() << "HbIconLoader::removeItemInCache: Removed" |
|
874 << iconImpl->iconFileName() << iconImpl->keySize(); |
|
875 #endif |
|
876 } |
833 } |
877 } |
834 } |
878 } |
835 |
879 |
836 /*! |
880 /*! |
837 * Cleans up (deletes) the HbIconImpl instances at the client side |
881 * Cleans up (deletes) the HbIconImpl instances at the client side |
838 * It also resets the engine's iconImpl and MaskableIcon's iconImpl |
882 * It also resets the engine's iconImpl and MaskableIcon's iconImpl |
839 */ |
883 */ |
840 void HbIconLoader::freeGpuIconData() |
884 void HbIconLoader::freeGpuIconData() |
841 { |
885 { |
842 #if defined(HB_SGIMAGE_ICON) || defined(HB_NVG_CS_ICON) |
886 #if defined(HB_SGIMAGE_ICON) || defined(HB_NVG_CS_ICON) |
843 cacheKeeper()->clear(); // unref all unused icons |
887 d->cacheKeeper.clear(); // unref all unused icons |
|
888 for (int i = 0; i < iconEngineList.count(); i++) { |
|
889 HbIconEngine *engine = iconEngineList.at(i); |
|
890 if (engine->iconFormatType() == SGIMAGE || engine->iconFormatType() == NVG) { |
|
891 engine->resetIconImpl(); |
|
892 } |
|
893 } |
|
894 for (int i = 0; i < frameDrawerInstanceList.count(); i++) { |
|
895 HbFrameDrawerPrivate *fd = frameDrawerInstanceList.at(i); |
|
896 if (fd->iconFormatType() == SGIMAGE || fd->iconFormatType() == NVG) { |
|
897 fd->resetMaskableIcon(); |
|
898 } |
|
899 } |
|
900 #endif |
|
901 } |
|
902 |
|
903 /*! |
|
904 * Cleans up (deletes) the HbIconImpl instances at the client side |
|
905 * It also resets the engine's iconImpl and MaskableIcon's iconImpl |
|
906 */ |
|
907 void HbIconLoader::freeIconData() |
|
908 { |
|
909 d->cacheKeeper.clear(); // unref all unused icons |
844 for (int i = 0; i < iconEngineList.count(); i++) { |
910 for (int i = 0; i < iconEngineList.count(); i++) { |
845 HbIconEngine *engine = iconEngineList.at(i); |
911 HbIconEngine *engine = iconEngineList.at(i); |
846 engine->resetIconImpl(); |
912 engine->resetIconImpl(); |
847 } |
913 } |
848 for (int i = 0; i < frameDrawerInstanceList.count(); i++) { |
914 for (int i = 0; i < frameDrawerInstanceList.count(); i++) { |
849 HbFrameDrawerPrivate *fd = frameDrawerInstanceList.at(i); |
915 HbFrameDrawerPrivate *fd = frameDrawerInstanceList.at(i); |
850 if ((fd->iconFormatType() == SGIMAGE) || (fd->iconFormatType() == NVG)) { |
916 fd->resetMaskableIcon(); |
851 fd->resetMaskableIcon(); |
917 |
852 } |
918 } |
853 } |
919 } |
854 #endif |
920 |
855 } |
|
856 |
921 |
857 /*! |
922 /*! |
858 \internal |
923 \internal |
859 |
924 |
860 This is a wrapper for findSharedResourceHelper(). It is used for getting |
925 This is a wrapper for findSharedResourceHelper(). It is used for getting |
1354 |
1419 |
1355 // Delete original pixmap if its size is large |
1420 // Delete original pixmap if its size is large |
1356 source->deleteImageIfLargerThan(IMAGE_SIZE_LIMIT); |
1421 source->deleteImageIfLargerThan(IMAGE_SIZE_LIMIT); |
1357 } |
1422 } |
1358 |
1423 |
|
1424 void HbIconLoader::loadNvgIcon(HbIconLoadingParams ¶ms ) |
|
1425 { |
|
1426 #ifdef HB_NVG_CS_ICON |
|
1427 HbIconSource *source = getIconSource(params.iconFileName, "NVG"); |
|
1428 if (!source) { |
|
1429 return; |
|
1430 } |
|
1431 |
|
1432 HbNvgRasterizer * nvgRasterizer = HbNvgRasterizer::global(); |
|
1433 QByteArray *sourceByteArray = source->byteArray(); |
|
1434 if( !sourceByteArray ) { |
|
1435 return; |
|
1436 } |
|
1437 |
|
1438 QByteArray nvgArray = *sourceByteArray; |
|
1439 QSizeF renderSize = source->defaultSize(); |
|
1440 if (!params.isDefaultSize) { |
|
1441 renderSize.scale(params.size, params.aspectRatioMode); |
|
1442 } else if (params.options.testFlag(ResolutionCorrected)) { |
|
1443 applyResolutionCorrection(renderSize); |
|
1444 } |
|
1445 |
|
1446 QSize iconSize = renderSize.toSize(); |
|
1447 QImage image(iconSize, QImage::Format_ARGB32_Premultiplied); |
|
1448 QImage::Format imageFormat = image.format(); |
|
1449 int stride = image.bytesPerLine(); |
|
1450 void * rasterizedData = image.bits(); |
|
1451 |
|
1452 bool success = nvgRasterizer->rasterize(nvgArray, iconSize, |
|
1453 params.aspectRatioMode, |
|
1454 rasterizedData, stride,imageFormat); |
|
1455 if (success) { |
|
1456 params.image = image; |
|
1457 } |
|
1458 |
|
1459 #else |
|
1460 Q_UNUSED(params) |
|
1461 #endif |
|
1462 |
|
1463 } |
|
1464 |
1359 /*! |
1465 /*! |
1360 * \fn void HbIconLoader::switchRenderingMode() |
1466 * \fn void HbIconLoader::switchRenderingMode() |
1361 * |
1467 * |
1362 * This function gets notified when the rendering mode of the application changes e.g |
1468 * This function gets notified when the rendering mode of the application changes e.g |
1363 * ( Hardware - Software rendering or vice versa ). If the mode is changed from |
1469 * ( Hardware - Software rendering or vice versa ). If the mode is changed from |
1394 } else { |
1500 } else { |
1395 renderMode = ESWRendering; |
1501 renderMode = ESWRendering; |
1396 } |
1502 } |
1397 } |
1503 } |
1398 |
1504 |
|
1505 // Note that this is not the same as HbThemeUtils::isLogicalName. |
|
1506 // A non-logical name can still indicate content that must go through themeserver. |
1399 inline bool isLocalContent(const QString &iconName) |
1507 inline bool isLocalContent(const QString &iconName) |
1400 { |
1508 { |
1401 // Check if we have a simple file or embedded resource, given with full |
1509 // Check if we have a simple file or embedded resource, given with full |
1402 // or relative path. A filename like "x.png" is also local content |
1510 // or relative path. A filename like "x.png" is also local content |
1403 // because logical icon names must never contain an extension. |
1511 // because logical icon names must never contain an extension. |
1404 bool localContent = iconName.startsWith(':') |
1512 bool localContent = iconName.startsWith(':') |
1405 || iconName.contains('/') || iconName.contains('\\') |
1513 || iconName.contains('/') || iconName.contains('\\') |
1406 || (iconName.length() > 1 && iconName.at(1) == ':') |
1514 || (iconName.length() > 1 && iconName.at(1) == ':') |
1407 || (iconName.contains('.') && !iconName.startsWith("qtg_", Qt::CaseInsensitive)); |
1515 || (iconName.contains('.') && !iconName.startsWith("qtg_", Qt::CaseInsensitive)); |
1408 |
|
1409 // Cannot load NVG locally. Remove this check when local loading for NVG is available. |
|
1410 if (iconName.endsWith(".nvg", Qt::CaseInsensitive)) { |
|
1411 localContent = false; |
|
1412 } |
|
1413 |
1516 |
1414 return localContent; |
1517 return localContent; |
1415 } |
1518 } |
1416 |
1519 |
1417 inline bool serverUseAllowed(const QString &iconName, HbIconLoader::IconLoaderOptions options) |
1520 inline bool serverUseAllowed(const QString &iconName, HbIconLoader::IconLoaderOptions options) |
1550 GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory) |
1653 GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory) |
1551 // Try to take data from server if parameters don't prevent it |
1654 // Try to take data from server if parameters don't prevent it |
1552 if (serverUseAllowed(iconName, options) |
1655 if (serverUseAllowed(iconName, options) |
1553 // Use the server only for theme graphics. |
1656 // Use the server only for theme graphics. |
1554 // For local files, i.e. anything that is not a single logical name, use local loading. |
1657 // For local files, i.e. anything that is not a single logical name, use local loading. |
1555 && !isLocalContent(iconName) |
1658 && !isLocalContent(iconName) |
1556 && format != "MNG" |
1659 && format != "MNG" |
1557 && format != "GIF" |
1660 && format != "GIF" |
1558 && manager) { |
1661 && manager) { |
1559 |
1662 |
1560 //Initiate an IPC to themeserver to get the icon-data from the server. |
1663 // Initiate an IPC to themeserver to get the icon-data from the server. |
1561 |
1664 |
1562 if (callback) { |
1665 if (callback) { |
1563 getIconFromServerAsync(params, callback, callbackParam); |
1666 getIconFromServerAsync(params, callback, callbackParam); |
1564 return 0; |
1667 return 0; |
1565 } |
1668 } |
1566 |
1669 |
1567 icon = getIconFromServer(params); |
1670 icon = getIconFromServer(params); |
1568 |
1671 |
|
1672 // No check for DoNotCache here. If we decided to use the server regardless of |
|
1673 // the flag then there's a chance that we have to cache (in case of SgImage |
|
1674 // for example) for proper operation, no matter what. |
1569 if (icon) { |
1675 if (icon) { |
1570 cacheIcon(params, icon, &cacheKey); |
1676 cacheIcon(params, icon, &cacheKey); |
1571 return icon; |
1677 return icon; |
1572 } |
1678 } |
1573 |
1679 |
1598 return icon; |
1704 return icon; |
1599 } |
1705 } |
1600 |
1706 |
1601 HbIconImpl *HbIconLoader::lookupInCache(const HbIconLoadingParams ¶ms, QByteArray *outCacheKey) |
1707 HbIconImpl *HbIconLoader::lookupInCache(const HbIconLoadingParams ¶ms, QByteArray *outCacheKey) |
1602 { |
1708 { |
|
1709 // Stop right away for resolution corrected icons, these may get false cache |
|
1710 // hits. The use of such icons should be very rare anyway. |
|
1711 if (params.options.testFlag(ResolutionCorrected)) { |
|
1712 return 0; |
|
1713 } |
|
1714 |
1603 QByteArray cacheKey = d->createCacheKeyFrom(params.iconName, |
1715 QByteArray cacheKey = d->createCacheKeyFrom(params.iconName, |
1604 params.size, |
1716 params.size, |
1605 params.aspectRatioMode, |
1717 params.aspectRatioMode, |
1606 params.mode, |
1718 params.mode, |
1607 params.mirrored, |
1719 params.mirrored, |
1608 params.color); |
1720 params.color); |
1609 if (outCacheKey) { |
1721 if (outCacheKey) { |
1610 *outCacheKey = cacheKey; |
1722 *outCacheKey = cacheKey; |
1611 } |
1723 } |
1612 if (iconImplCache.contains(cacheKey)) { |
1724 if (d->iconImplCache.contains(cacheKey)) { |
1613 HbIconImpl *icon = iconImplCache.value(cacheKey); |
1725 HbIconImpl *icon = d->iconImplCache.value(cacheKey); |
1614 icon->incrementRefCount(); |
1726 icon->incrementRefCount(); |
1615 cacheKeeper()->unref(icon); |
1727 d->cacheKeeper.unref(icon); |
1616 #ifdef HB_ICON_CACHE_DEBUG |
1728 #ifdef HB_ICON_CACHE_DEBUG |
1617 qDebug() << "HbIconLoader::loadIcon(): " << "Cache hit in iconImplCache for" << params.iconName << params.size; |
1729 qDebug() << "HbIconLoader::lookupInCache: Cache hit for" << params.iconName << params.size |
1618 qDebug() << "HbIconLoader::loadIcon(): Client RefCount now = " << icon->refCount(); |
1730 << "Client refcount now" << icon->refCount(); |
1619 #endif |
1731 #endif |
1620 return icon; |
1732 return icon; |
1621 } |
1733 } |
1622 return 0; |
1734 return 0; |
1623 } |
1735 } |
1681 opt.palette = QApplication::palette(); |
1796 opt.palette = QApplication::palette(); |
1682 pm = QApplication::style()->generatedIconPixmap(params.mode, pm, &opt); |
1797 pm = QApplication::style()->generatedIconPixmap(params.mode, pm, &opt); |
1683 } |
1798 } |
1684 } |
1799 } |
1685 |
1800 |
1686 return new HbPixmapIconImpl(pm, params.iconFileName); |
1801 return HbIconImplCreator::createIconImpl(pm, params); |
1687 } |
1802 } |
1688 |
1803 |
1689 void HbIconLoader::cacheIcon(const HbIconLoadingParams ¶ms, HbIconImpl *icon, QByteArray *existingCacheKey) |
1804 void HbIconLoader::cacheIcon(const HbIconLoadingParams ¶ms, HbIconImpl *icon, QByteArray *existingCacheKey) |
1690 { |
1805 { |
1691 QByteArray cacheKey; |
1806 QByteArray cacheKey; |
1692 if (existingCacheKey) { |
1807 if (existingCacheKey) { |
1693 cacheKey = *existingCacheKey; |
1808 cacheKey = *existingCacheKey; |
1694 } else { |
1809 } else { |
1695 cacheKey = d->createCacheKeyFrom(params.iconName, |
1810 cacheKey = d->createCacheKeyFrom(params.iconName, |
1696 params.size, |
1811 params.size, |
1697 params.aspectRatioMode, |
1812 params.aspectRatioMode, |
1698 params.mode, |
1813 params.mode, |
1699 params.mirrored, |
1814 params.mirrored, |
1700 params.color); |
1815 params.color); |
1701 } |
1816 } |
1702 iconImplCache.insert(cacheKey, icon); |
1817 d->iconImplCache.insert(cacheKey, icon); |
1703 |
1818 |
1704 #ifdef HB_ICON_CACHE_DEBUG |
1819 #ifdef HB_ICON_CACHE_DEBUG |
1705 qDebug() << "HbIconLoader::loadIcon(): " << params.iconName << " inserted into impl-cache, ref-count now = " << icon->refCount(); |
1820 qDebug() << "HbIconLoader:cacheIcon: " << params.iconName |
|
1821 << "inserted into local cache, client refcount now" << icon->refCount(); |
1706 #endif |
1822 #endif |
1707 } |
1823 } |
1708 |
1824 |
1709 /*! |
1825 /*! |
1710 Cancels an outstanding loadIcon request. |
1826 Cancels an outstanding loadIcon request. |
1769 |
1887 |
1770 // Whether mirrored version of the icon was found in the file system (otherwise it's mirrored by code). |
1888 // Whether mirrored version of the icon was found in the file system (otherwise it's mirrored by code). |
1771 bool mirroredIconFound = false; |
1889 bool mirroredIconFound = false; |
1772 |
1890 |
1773 // We don't want to get the consolidated icon for only NVG build, ie. without SGImage lite support. |
1891 // We don't want to get the consolidated icon for only NVG build, ie. without SGImage lite support. |
1774 // Consolidated icon will be created for NVG with SGImage lite support and when NVG is not available. |
1892 // Consolidated icon will be created for NVG with SGImage lite support. |
|
1893 // and when NVG is not available. |
1775 QByteArray cacheKey = d->createCacheKeyFrom( |
1894 QByteArray cacheKey = d->createCacheKeyFrom( |
1776 multiPartIconData.multiPartIconId, |
1895 multiPartIconData.multiPartIconId, |
1777 size, |
1896 size, |
1778 aspectRatioMode, |
1897 aspectRatioMode, |
1779 mode, |
1898 mode, |
1780 mirrored, |
1899 mirrored, |
1781 color); |
1900 color); |
1782 //If consolidated icon found in the client's cache, increment ref-count and return |
1901 //If consolidated icon found in the client's cache, increment ref-count and return |
1783 if (iconImplCache.contains(cacheKey)) { |
1902 if (d->iconImplCache.contains(cacheKey)) { |
1784 HbIconImpl *ptr = iconImplCache.value(cacheKey); |
1903 HbIconImpl *ptr = d->iconImplCache.value(cacheKey); |
1785 ptr->incrementRefCount(); |
1904 ptr->incrementRefCount(); |
1786 cacheKeeper()->unref(ptr); |
1905 d->cacheKeeper.unref(ptr); |
1787 #ifdef HB_ICON_CACHE_DEBUG |
1906 #ifdef HB_ICON_CACHE_DEBUG |
1788 qDebug() << "HbIconLoader::loadMultiPieceIcon()" << "Cache hit in iconImplCache " << multiPartIconData.multiPartIconId << size; |
1907 qDebug() << "HbIconLoader::loadMultiPieceIcon: Cache hit" << multiPartIconData.multiPartIconId |
1789 qDebug() << "HbIconLoader::loadMultiPieceIcon : Client RefCount now = " << ptr->refCount(); |
1908 << size << "Client refcount now" << ptr->refCount(); |
1790 #endif |
1909 #endif |
1791 return ptr; |
1910 return ptr; |
1792 } |
1911 } |
1793 |
1912 |
1794 QStringList iconPathList; |
1913 QStringList iconPathList; |
1833 params.mirroredIconFound = mirroredIconFound; |
1952 params.mirroredIconFound = mirroredIconFound; |
1834 |
1953 |
1835 // Creating HbIconImpl for the consolidated icon-data returned from themeserver. |
1954 // Creating HbIconImpl for the consolidated icon-data returned from themeserver. |
1836 icon = HbIconImplCreator::createIconImpl(iconInfo, params); |
1955 icon = HbIconImplCreator::createIconImpl(iconInfo, params); |
1837 if (icon) { |
1956 if (icon) { |
1838 // Not yet in local cache (was checked before the server request) so insert. |
|
1839 iconImplCache.insert(cacheKey, icon); |
|
1840 icon->setMultiPieceIcon(); |
1957 icon->setMultiPieceIcon(); |
1841 #ifdef HB_ICON_CACHE_DEBUG |
1958 } |
1842 qDebug() << "HbIconLoader::loadMultiPieceIcon(): " << params.iconName << " inserted into impl-cache, ref-count now = " << icon->refCount(); |
|
1843 #endif |
|
1844 } |
|
1845 return icon; |
|
1846 } else { |
1959 } else { |
1847 //themeserver wasn't successful in stitching of consolidated icon |
1960 //Consolidated (stitched) icon could not be loaded on themeserver side, taking |
1848 multiPieceImpls.clear(); |
1961 //fallback path for creating the consolidated icon on the client side. |
1849 int count = iconPathList.count(); |
1962 icon = createLocalConsolidatedIcon(multiPartIconData, |
1850 QVector<QSizeF> sizeList; |
1963 iconPathList, |
1851 for (int i = 0; i < count; i++) { |
1964 size, |
1852 sizeList << multiPartIconData.pixmapSizes[i]; |
|
1853 } |
|
1854 |
|
1855 #ifdef Q_OS_SYMBIAN |
|
1856 //Since the consolidated icon-creation failed on themeserver, request loading of individual |
|
1857 //frame-items in a single IPC request to themeserver |
|
1858 getMultiIconImplFromServer(iconPathList, sizeList, |
|
1859 aspectRatioMode, |
1965 aspectRatioMode, |
1860 mode, |
1966 mode, |
1861 mirrored, |
|
1862 mirroredIconFound, |
|
1863 options, |
1967 options, |
1864 color, |
1968 color); |
1865 HbIconLoader::AnyType, |
1969 } |
1866 HbIconLoader::AnyPurpose, |
1970 |
1867 multiPieceImpls, |
1971 if (icon) { |
1868 renderMode); |
1972 // Not yet in local cache (was checked before the server request) so insert. |
1869 #else |
1973 d->iconImplCache.insert(cacheKey, icon); |
1870 //For OS other than Symbian, call HbIconLoader::loadIcon to individually load icons |
1974 #ifdef HB_ICON_CACHE_DEBUG |
1871 for (int i = 0; i < count; i++) { |
1975 qDebug() << "HbIconLoader::loadMultiPieceIcon: " << multiPartIconData.multiPartIconId |
1872 HbIconImpl *impl = loadIcon(iconPathList[i], HbIconLoader::AnyType, |
1976 << " inserted into local cache, client refcount now" << icon->refCount(); |
1873 HbIconLoader::AnyPurpose, |
1977 #endif |
1874 sizeList.at(i), |
1978 } |
1875 Qt::IgnoreAspectRatio, |
1979 return icon; |
1876 QIcon::Normal, |
1980 } |
1877 (options | DoNotCache)); |
1981 |
1878 impl->setMultiPieceIcon(); |
1982 HbIconImpl * HbIconLoader::createLocalConsolidatedIcon(const HbMultiPartSizeData &multiPartIconData, |
1879 if (impl) { |
1983 const QStringList & iconPathList, |
1880 multiPieceImpls.append(impl); |
1984 const QSizeF &consolidatedSize, |
1881 } |
1985 Qt::AspectRatioMode aspectRatioMode, |
1882 } |
1986 QIcon::Mode mode, |
1883 |
1987 const IconLoaderOptions & options, |
1884 #endif |
1988 const QColor &color) |
1885 |
1989 { |
1886 return icon; |
1990 // load the icons in to QImage |
1887 } |
1991 HbIconLoadingParams params; |
|
1992 params.purpose = HbIconLoader::AnyPurpose; |
|
1993 params.aspectRatioMode = aspectRatioMode; |
|
1994 params.mode = mode; |
|
1995 params.color = color; |
|
1996 params.animator = 0; |
|
1997 params.mirrored = options.testFlag(HorizontallyMirrored); |
|
1998 params.mirroredIconFound = false; |
|
1999 params.mirroringHandled = false; |
|
2000 params.modeHandled = false; |
|
2001 params.renderMode = renderMode; |
|
2002 params.canCache = false; |
|
2003 params.animationCreated = false; |
|
2004 |
|
2005 QStringList::const_iterator iterFiles = iconPathList.begin(); |
|
2006 QStringList::const_iterator iterFilesEnd = iconPathList.end(); |
|
2007 |
|
2008 QImage finalImage(consolidatedSize.toSize(), QImage::Format_ARGB32_Premultiplied); |
|
2009 finalImage.fill(QColor(Qt::transparent).rgba()); |
|
2010 QPainter painter(&finalImage); |
|
2011 |
|
2012 for (int i=0; iterFiles != iterFilesEnd; ++iterFiles, ++i) { |
|
2013 |
|
2014 // Populate icon loading parameters |
|
2015 params.iconFileName = *iterFiles; |
|
2016 params.size = multiPartIconData.pixmapSizes[i]; |
|
2017 params.options = options; |
|
2018 params.isDefaultSize = params.size.isNull(); |
|
2019 |
|
2020 QString format = formatFromPath(params.iconFileName); |
|
2021 |
|
2022 loadLocal(params, format); |
|
2023 |
|
2024 painter.drawImage(multiPartIconData.targets[i].topLeft(), |
|
2025 params.image); |
|
2026 |
|
2027 params.image = QImage(); |
|
2028 } |
|
2029 painter.end(); |
|
2030 |
|
2031 params.image = finalImage; |
|
2032 |
|
2033 return finishLocal(params); |
1888 } |
2034 } |
1889 |
2035 |
1890 inline int iconImplConsumption(HbIconImpl *icon) |
2036 inline int iconImplConsumption(HbIconImpl *icon) |
1891 { |
2037 { |
1892 QSize sz = icon->keySize().toSize(); |
2038 QSize sz = icon->keySize().toSize(); |
1893 return sz.width() * sz.height() * 4; |
2039 return sz.width() * sz.height() * 4; |
1894 } |
2040 } |
1895 |
2041 |
1896 void CacheKeeper::ref(HbIconImpl *icon) |
2042 void HbIconLoaderPrivate::CacheKeeper::ref(HbIconImpl *icon) |
1897 { |
2043 { |
1898 int consumption = iconImplConsumption(icon); |
2044 int consumption = iconImplConsumption(icon); |
1899 // Never hold something more than once and do not ref anything when icons |
2045 // Never hold something more than once and do not ref anything when icons |
1900 // are unloaded immediately when becoming hidden. Ignore also icons that are |
2046 // are unloaded immediately when becoming hidden. Ignore also icons that are |
1901 // too large and those which had not been inserted into iconImplCache |
2047 // too large and those which had not been inserted into iconImplCache |
1902 // (e.g. icons that were created with the DoNotCache option). |
2048 // (e.g. icons that were created with the DoNotCache option). |
1903 if (!mIcons.contains(icon) |
2049 if (!mIcons.contains(icon) |
1904 && !HbInstancePrivate::d_ptr()->mDropHiddenIconData |
2050 && !HbInstancePrivate::d_ptr()->mDropHiddenIconData |
1905 && consumption < MAX_KEEPALIVE_ITEM_SIZE_BYTES |
2051 && consumption < MAX_KEEPALIVE_ITEM_SIZE_BYTES |
1906 && !iconImplCache.key(icon).isEmpty()) |
2052 && !mIconLoaderPrivate->iconImplCache.key(icon).isEmpty()) |
1907 { |
2053 { |
1908 icon->incrementRefCount(); |
2054 icon->incrementRefCount(); |
1909 mIcons.append(icon); |
2055 mIcons.append(icon); |
1910 mConsumption += consumption; |
2056 mConsumption += consumption; |
|
2057 #ifdef HB_ICON_CACHE_DEBUG |
|
2058 qDebug() << "CacheKeeper::ref: Accepted" << icon->iconFileName() |
|
2059 << icon->keySize() << consumption |
|
2060 << "Total consumption now" << mConsumption; |
|
2061 #endif |
1911 // Now do some housekeeping. |
2062 // Now do some housekeeping. |
1912 while (mConsumption > MAX_KEEPALIVE_CACHE_SIZE_BYTES) { |
2063 while (mConsumption > MAX_KEEPALIVE_CACHE_SIZE_BYTES) { |
1913 HbIconImpl *oldest = mIcons.first(); |
2064 HbIconImpl *oldest = mIcons.first(); |
1914 unref(oldest); |
2065 unref(oldest); |
1915 if (oldest->refCount() == 0 && oldest != icon) { |
2066 if (oldest->refCount() == 0 && oldest != icon) { |
2009 } |
2163 } |
2010 return pixmap; |
2164 return pixmap; |
2011 } |
2165 } |
2012 |
2166 |
2013 /*! |
2167 /*! |
2014 * \fn void HbIconLoader::getMultiIconImplFromServer() |
|
2015 * |
|
2016 * This function is responsible for loading individual pieces of a multi-piece icon. |
|
2017 * This gets called if the consolidated icon-creation process on themeserver has failed. |
|
2018 * This function initiates a single IPC to themeserver in which it sends out icon-parameters |
|
2019 * for each of the frame-items and gets back a list of HbSharedIconInfo corresponding to |
|
2020 * individual pieces. |
|
2021 * |
|
2022 */ |
|
2023 void HbIconLoader::getMultiIconImplFromServer(QStringList &multiPartIconList, |
|
2024 QVector<QSizeF> &sizeList, |
|
2025 Qt::AspectRatioMode aspectRatioMode, |
|
2026 QIcon::Mode mode, |
|
2027 bool mirrored, |
|
2028 bool mirroredIconFound, |
|
2029 HbIconLoader::IconLoaderOptions options, |
|
2030 const QColor &color, |
|
2031 HbIconLoader::IconDataType type, |
|
2032 HbIconLoader::Purpose, |
|
2033 QVector<HbIconImpl *> & iconImplList, |
|
2034 HbRenderingMode currRenderMode) |
|
2035 { |
|
2036 Q_UNUSED(type); |
|
2037 QVector<int> posList; |
|
2038 // Search the client cache first before asking the server. |
|
2039 int count = multiPartIconList.count(); |
|
2040 QVector<QByteArray> cacheKeys; |
|
2041 for (int i = 0; i < count; i++) { |
|
2042 QByteArray cacheKey = d->createCacheKeyFrom(multiPartIconList[i], |
|
2043 sizeList[i], |
|
2044 aspectRatioMode, |
|
2045 mode, |
|
2046 mirrored, |
|
2047 color); |
|
2048 cacheKeys.append(cacheKey); |
|
2049 // Look up in the local iconImplCache. |
|
2050 HbIconImpl *ptr = 0; |
|
2051 if (iconImplCache.contains(cacheKey)) { |
|
2052 ptr = iconImplCache.value(cacheKey); |
|
2053 // If a specific frame-item is found in local impl-cache, |
|
2054 // increment the ref count and remove the entry from the |
|
2055 // list that needs to be sent to server. |
|
2056 ptr->incrementRefCount(); |
|
2057 cacheKeeper()->unref(ptr); |
|
2058 #ifdef HB_ICON_CACHE_DEBUG |
|
2059 qDebug() << "HbIconLoader::getMultiIconImplFromServer()" << "Cache hit in iconImplCache "; |
|
2060 qDebug() << "HbIconLoader::getMultiIconImplFromServer : Client RefCount now = " << ptr->refCount(); |
|
2061 #endif |
|
2062 iconImplList.append(ptr); |
|
2063 multiPartIconList.replace(i, QString()); |
|
2064 } else { |
|
2065 posList << i; |
|
2066 } |
|
2067 } |
|
2068 for (int i = 0; i < count; i++) { |
|
2069 if (multiPartIconList[i].isEmpty()) { |
|
2070 multiPartIconList.removeAt(i); |
|
2071 sizeList.remove(i); |
|
2072 i--; |
|
2073 } |
|
2074 } |
|
2075 |
|
2076 // If no hit in local cache, ask server for all the pieces' information. |
|
2077 if (count > 0) { |
|
2078 HbSharedIconInfoList iconInfoList = HbThemeClient::global()->getMultiIconInfo(multiPartIconList, sizeList, |
|
2079 aspectRatioMode, mode, mirrored, options, color, currRenderMode); |
|
2080 |
|
2081 HbIconImpl *impl = 0; |
|
2082 |
|
2083 HbIconLoadingParams params; |
|
2084 |
|
2085 params.aspectRatioMode = aspectRatioMode; |
|
2086 params.mode = mode; |
|
2087 params.mirrored = mirrored; |
|
2088 params.mirroredIconFound = mirroredIconFound; |
|
2089 |
|
2090 for (int i = 0; i < count; i++) { |
|
2091 params.iconFileName = multiPartIconList[i]; |
|
2092 params.size = sizeList.at(i); |
|
2093 impl = HbIconImplCreator::createIconImpl(iconInfoList.icon[i], params); |
|
2094 if (impl) { |
|
2095 // Not yet in local cache (was checked before the server request) so insert. |
|
2096 iconImplCache.insert(cacheKeys[i], impl); |
|
2097 #ifdef HB_ICON_CACHE_DEBUG |
|
2098 qDebug() << "HbIconLoader::getMultiIconImplFromServer(): " |
|
2099 << params.iconName << " inserted into impl-cache, ref-count now = " << impl->refCount(); |
|
2100 #endif |
|
2101 } else { |
|
2102 //If for some reason individual frame-item's loading in themeserver fails, use HbIconLoader::loadIcon() |
|
2103 // as a fallback option to load it. |
|
2104 impl = loadIcon(multiPartIconList[i], |
|
2105 HbIconLoader::AnyType, |
|
2106 HbIconLoader::AnyPurpose, |
|
2107 sizeList.at(i), |
|
2108 Qt::IgnoreAspectRatio, |
|
2109 QIcon::Normal, |
|
2110 (options | DoNotCache)); |
|
2111 } |
|
2112 |
|
2113 if (impl) { |
|
2114 impl->setMultiPieceIcon(); |
|
2115 if (posList.count() > 0) { |
|
2116 iconImplList.insert(posList.front(), impl); |
|
2117 posList.pop_front(); |
|
2118 } |
|
2119 } |
|
2120 } |
|
2121 } |
|
2122 } |
|
2123 |
|
2124 /*! |
|
2125 * HbIconLoader::unLoadMultiIcon |
2168 * HbIconLoader::unLoadMultiIcon |
2126 * |
2169 * |
2127 * This function initiates a single IPC to unload each of the frame-items in a multi-piece icon. |
2170 * This function initiates a single IPC to unload each of the frame-items in a multi-piece icon. |
2128 */ |
2171 */ |
2129 void HbIconLoader::unLoadMultiIcon(QVector<HbIconImpl *> &multiPieceImpls) |
2172 void HbIconLoader::unLoadMultiIcon(QVector<HbIconImpl *> &multiPieceImpls) |