src/hbcore/image/hbiconloader.cpp
changeset 28 b7da29130b0e
parent 23 e6ad4ef83b23
child 30 80e4d18b72f5
equal deleted inserted replaced
23:e6ad4ef83b23 28:b7da29130b0e
    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);
   229     animationManager(HbIconAnimationManager::global()),
   236     animationManager(HbIconAnimationManager::global()),
   230     animationLoading(false),
   237     animationLoading(false),
   231     lastIconSource(0),
   238     lastIconSource(0),
   232     layoutMirrored(Unknown),
   239     layoutMirrored(Unknown),
   233     mLocalLoadMutex(QMutex::Recursive),
   240     mLocalLoadMutex(QMutex::Recursive),
   234     mIconSourceMutex(QMutex::Recursive)
   241     mIconSourceMutex(QMutex::Recursive),
       
   242     cacheKeeper(this)
   235 {
   243 {
   236     qRegisterMetaType<HbIconImpl *>();
   244     qRegisterMetaType<HbIconImpl *>();
   237     qRegisterMetaType<HbIconLoadingParams>();
   245     qRegisterMetaType<HbIconLoadingParams>();
   238     qRegisterMetaType<void *>();
   246     qRegisterMetaType<void *>();
   239     mLocalLoader = new HbLocalIconLoader;
   247     mLocalLoader = new HbLocalIconLoader;
   247     // there is a chance that start() has not yet executed.
   255     // there is a chance that start() has not yet executed.
   248     QMetaObject::invokeMethod(mLocalLoader, "doQuit", Qt::QueuedConnection);
   256     QMetaObject::invokeMethod(mLocalLoader, "doQuit", Qt::QueuedConnection);
   249     mLocalLoaderThread.wait();
   257     mLocalLoaderThread.wait();
   250     delete lastIconSource;
   258     delete lastIconSource;
   251     qDeleteAll(mActiveAsyncRequests);
   259     qDeleteAll(mActiveAsyncRequests);
       
   260     cacheKeeper.clear();
       
   261     // There may be icons in iconImplCache at this point and they are not
       
   262     // leftovers so they must not be destroyed. In many cases the HbIconLoader
       
   263     // is destroyed before the destructors of icon engines or framedrawers are run
       
   264     // so it must be left up to them to correctly unref all icons.
       
   265     iconImplCache.clear();
   252 }
   266 }
   253 
   267 
   254 HbIconLoaderPrivate *HbIconLoaderPrivate::global()
   268 HbIconLoaderPrivate *HbIconLoaderPrivate::global()
   255 {
   269 {
   256     HbIconLoader *loader = HbIconLoader::global();
   270     HbIconLoader *loader = HbIconLoader::global();
   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) {
   811 }
   851 }
   812 
   852 
   813 void HbIconLoader::handleForegroundLost()
   853 void HbIconLoader::handleForegroundLost()
   814 {
   854 {
   815 #if defined(HB_SGIMAGE_ICON) || defined(HB_NVG_CS_ICON)
   855 #if defined(HB_SGIMAGE_ICON) || defined(HB_NVG_CS_ICON)
   816     // Remove SGImage/NVG type of icons
   856     freeIconData();
   817     freeGpuIconData();
       
   818     // delete the VGImage
   857     // delete the VGImage
   819     HbEglStates *eglStateInstance = HbEglStates::global();
   858     HbEglStates *eglStateInstance = HbEglStates::global();
   820     eglStateInstance->handleForegroundLost();
   859     eglStateInstance->handleForegroundLost();
   821     // notify the server to clear the SGImage and NVG type of icons from the client's session
   860     // notify the server to clear the SGImage and NVG type of icons from the client's session
   822     HbThemeClient::global()->notifyForegroundLostToServer();
   861     HbThemeClient::global()->notifyForegroundLostToServer();
   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
  1198             }
  1263             }
  1199         }
  1264         }
  1200 
  1265 
  1201 #endif // HB_SVG_ANIMATION
  1266 #endif // HB_SVG_ANIMATION
  1202 
  1267 
  1203         params.image = QImage(renderSize.toSize(), QImage::Format_ARGB32); // should be _Premultiplied but that results in incorrect rendering
  1268         params.image = QImage(renderSize.toSize(), QImage::Format_ARGB32_Premultiplied);
  1204         params.image.fill(Qt::transparent);
  1269         params.image.fill(QColor(Qt::transparent).rgba());
  1205         QPainter painter;
  1270         QPainter painter;
  1206         painter.begin(&params.image);
  1271         painter.begin(&params.image);
  1207         svgRenderer->render(&painter, QRectF(QPointF(), renderSize.toSize()));
  1272         svgRenderer->render(&painter, QRectF(QPointF(), renderSize.toSize()));
  1208         painter.end();
  1273         painter.end();
  1209     }
  1274     }
  1239             // Determine scale factor as QPicture doesn't allow for scaling
  1304             // Determine scale factor as QPicture doesn't allow for scaling
  1240             sx = renderSize.width() / picSize.width();
  1305             sx = renderSize.width() / picSize.width();
  1241             sy = renderSize.height() / picSize.height();
  1306             sy = renderSize.height() / picSize.height();
  1242         }
  1307         }
  1243 
  1308 
  1244         params.image = QImage(renderSize.toSize(), QImage::Format_ARGB32);
  1309         params.image = QImage(renderSize.toSize(), QImage::Format_ARGB32_Premultiplied);
  1245         params.image.fill(Qt::transparent);
  1310         params.image.fill(QColor(Qt::transparent).rgba());
  1246         QPainter painter;
  1311         QPainter painter;
  1247         painter.begin(&params.image);
  1312         painter.begin(&params.image);
  1248         if (scale) {
  1313         if (scale) {
  1249             painter.scale(sx, sy);
  1314             painter.scale(sx, sy);
  1250         }
  1315         }
  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 &params )
       
  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
  1373     Q_UNUSED(newRenderMode)
  1479     Q_UNUSED(newRenderMode)
  1374 #endif
  1480 #endif
  1375 
  1481 
  1376 #if defined(HB_SGIMAGE_ICON) || defined(HB_NVG_CS_ICON)
  1482 #if defined(HB_SGIMAGE_ICON) || defined(HB_NVG_CS_ICON)
  1377     if (newRenderMode != renderMode) {
  1483     if (newRenderMode != renderMode) {
  1378         cacheKeeper()->clear(); // unref all unused icons
  1484         d->cacheKeeper.clear(); // unref all unused icons
  1379         if (newRenderMode == ESWRendering) {
  1485         if (newRenderMode == ESWRendering) {
  1380             // switching from HW to SW mode
  1486             // switching from HW to SW mode
  1381             freeGpuIconData();
  1487             freeGpuIconData();
  1382         }
  1488         }
  1383         if (HbThemeClient::global()->switchRenderingMode(newRenderMode)) {
  1489         if (HbThemeClient::global()->switchRenderingMode(newRenderMode)) {
  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 &params, QByteArray *outCacheKey)
  1707 HbIconImpl *HbIconLoader::lookupInCache(const HbIconLoadingParams &params, 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 }
  1626 {
  1738 {
  1627     QMutexLocker loadLocker(&d->mLocalLoadMutex);
  1739     QMutexLocker loadLocker(&d->mLocalLoadMutex);
  1628     QMutexLocker iconSourceLocker(&d->mIconSourceMutex);
  1740     QMutexLocker iconSourceLocker(&d->mIconSourceMutex);
  1629     if (format == "SVG") {
  1741     if (format == "SVG") {
  1630         loadSvgIcon(params);
  1742         loadSvgIcon(params);
       
  1743     } else if(format == "NVG") {
       
  1744         //support for client side rendering of nvg icons
       
  1745         loadNvgIcon(params);
  1631     } else if (format == "PIC") {
  1746     } else if (format == "PIC") {
  1632         loadPictureIcon(params);
  1747         loadPictureIcon(params);
  1633     } else if (format == "MNG" || format == "GIF") {
  1748     } else if (format == "MNG" || format == "GIF") {
  1634         loadAnimatedIcon(params, format);
  1749         loadAnimatedIcon(params, format);
  1635     } else {
  1750     } else {
  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 &params, HbIconImpl *icon, QByteArray *existingCacheKey)
  1804 void HbIconLoader::cacheIcon(const HbIconLoadingParams &params, 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.
  1757         IconLoaderOptions options,
  1873         IconLoaderOptions options,
  1758         QVector<HbIconImpl *> &multiPieceImpls,
  1874         QVector<HbIconImpl *> &multiPieceImpls,
  1759         const QColor &color)
  1875         const QColor &color)
  1760 {
  1876 {
  1761     Q_UNUSED(color);
  1877     Q_UNUSED(color);
       
  1878     Q_UNUSED(multiPieceImpls);
       
  1879 
  1762     HbIconImpl *icon = 0;
  1880     HbIconImpl *icon = 0;
  1763     if (listOfIcons.count() == 0) {
  1881     if (listOfIcons.count() == 0) {
  1764         return icon;
  1882         return icon;
  1765     }
  1883     }
  1766 
  1884 
  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) {
  1917             }
  2068             }
  1918         }
  2069         }
  1919     }
  2070     }
  1920 }
  2071 }
  1921 
  2072 
  1922 void CacheKeeper::unref(HbIconImpl *icon)
  2073 void HbIconLoaderPrivate::CacheKeeper::unref(HbIconImpl *icon)
  1923 {
  2074 {
  1924     if (mIcons.contains(icon)) {
  2075     if (mIcons.contains(icon)) {
       
  2076 #ifdef HB_ICON_CACHE_DEBUG
       
  2077         qDebug() << "CacheKeeper::unref: Releasing" << icon->iconFileName() << icon->keySize();
       
  2078 #endif
  1925         mIcons.removeOne(icon);
  2079         mIcons.removeOne(icon);
  1926         mConsumption -= iconImplConsumption(icon);
  2080         mConsumption -= iconImplConsumption(icon);
  1927         icon->decrementRefCount();
  2081         icon->decrementRefCount();
  1928     }
  2082     }
  1929 }
  2083 }
  1930 
  2084 
  1931 void CacheKeeper::clear()
  2085 void HbIconLoaderPrivate::CacheKeeper::clear()
  1932 {
  2086 {
  1933     // Get rid of all unused icons in the iconimplcache, regardless of
  2087     // Get rid of all unused icons in the iconimplcache, regardless of
  1934     // the icons' rendering mode. Note that the list may contain non-sgimage
  2088     // the icons' rendering mode. Note that the list may contain non-sgimage
  1935     // iconimpls too that are created on the server, and unlike sgimage the
  2089     // iconimpls too that are created on the server, and unlike sgimage the
  1936     // unload request for these can never be skipped.
  2090     // unload request for these can never be skipped.
  1950     if (!unloadList.isEmpty()) {
  2104     if (!unloadList.isEmpty()) {
  1951         HbThemeClient::global()->batchUnloadIcon(unloadList);
  2105         HbThemeClient::global()->batchUnloadIcon(unloadList);
  1952     }
  2106     }
  1953 }
  2107 }
  1954 
  2108 
  1955 void CacheKeeper::del(HbIconImpl *icon, bool sendUnloadReq)
  2109 void HbIconLoaderPrivate::CacheKeeper::del(HbIconImpl *icon, bool sendUnloadReq)
  1956 {
  2110 {
  1957     HbIconLoader::global()->removeItemInCache(icon);
  2111     HbIconLoader::global()->removeItemInCache(icon);
  1958     if (sendUnloadReq && icon->isCreatedOnServer()) {
  2112     if (sendUnloadReq && icon->isCreatedOnServer()) {
  1959         HbThemeClient::global()->unloadIcon(iconImplToReqInfo(icon));
  2113         HbThemeClient::global()->unloadIcon(iconImplToReqInfo(icon));
  1960     }
  2114     }
  1975 
  2129 
  1976     if (icon->refCount() == 0) {
  2130     if (icon->refCount() == 0) {
  1977         if (!unloadedByServer) {
  2131         if (!unloadedByServer) {
  1978             // Offer the icon to the cacheKeeper first.
  2132             // Offer the icon to the cacheKeeper first.
  1979             if (!noKeep) {
  2133             if (!noKeep) {
  1980                 cacheKeeper()->ref(icon);
  2134                 d->cacheKeeper.ref(icon);
  1981             }
  2135             }
  1982             // If it was accepted then the refcount was increased so stop here.
  2136             // If it was accepted then the refcount was increased so stop here.
  1983             if (icon->refCount() > 0) {
  2137             if (icon->refCount() > 0) {
  1984                 return;
  2138                 return;
  1985             }
  2139             }
  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)
  2134     // Decrement the ref count. If its zero, remove it from the client cache (if defined) and
  2177     // Decrement the ref count. If its zero, remove it from the client cache (if defined) and
  2135     // then send to server for unload.
  2178     // then send to server for unload.
  2136     foreach(HbIconImpl * impl, multiPieceImpls) {
  2179     foreach(HbIconImpl * impl, multiPieceImpls) {
  2137         impl->decrementRefCount();
  2180         impl->decrementRefCount();
  2138         if (impl->refCount() == 0) {
  2181         if (impl->refCount() == 0) {
  2139             int rem = iconImplCache.remove(iconImplCache.key(impl));
  2182             if (d->iconImplCache.remove(d->iconImplCache.key(impl)) > 0) {
  2140             if (rem > 0) {
  2183 #ifdef HB_ICON_CACHE_DEBUG
  2141 #ifdef HB_ICON_TRACES
  2184                 qDebug() << "HbIconLoader::unLoadMultiIcon: Removed from cache"
  2142                 qDebug() << "HbIconLoader::unLoadMultiIcon :Removed from HbIconImpl Cache " << rem << impl->iconFileName() << impl->keySize();
  2185                          << impl->iconFileName() << impl->keySize();
  2143 #endif
  2186 #endif
  2144             }
  2187             }
  2145             if (impl->isCreatedOnServer()) {
  2188             if (impl->isCreatedOnServer()) {
  2146                 // List of icons to be unloaded.
  2189                 // List of icons to be unloaded.
  2147                 iconNameList << impl->iconFileName();
  2190                 iconNameList << impl->iconFileName();