src/hbservers/hbthemeserver/hbthemeserverutils.cpp
changeset 34 ed14f46c0e55
parent 5 627c4a0fd0e7
--- a/src/hbservers/hbthemeserver/hbthemeserverutils.cpp	Mon Oct 04 17:49:30 2010 +0300
+++ b/src/hbservers/hbthemeserver/hbthemeserverutils.cpp	Mon Oct 18 18:23:13 2010 +0300
@@ -25,11 +25,14 @@
 
 #include "hbthemeserverutils_p.h"
 
+#include <QBuffer>
+#include <QByteArray>
+#include <QDebug>
+#include <QFile>
 #include <QHash>
 #include <QString>
 #include <QStringList>
-#include <QFile>
-#include <QDebug>
+#include <QSvgRenderer>
 
 #include "hbmemoryutils_p.h"
 #include "hbcssparser_p.h"
@@ -37,7 +40,6 @@
 #include "hbeffectxmlparser_p.h"
 #include "hbdeviceprofiledatabase_p.h"
 #include "hbthemeperf_p.h"
-#include "hbcache_p.h"
 #include "hbiconsource_p.h"
 #include "hbwidgetloader_p.h"
 #include "hbwidgetloaderactions_p.h"
@@ -53,9 +55,18 @@
 typedef QHash<QString, int> ServerHashForLayoutDefs;
 Q_GLOBAL_STATIC(ServerHashForLayoutDefs, layoutDefsCache)
 
+// Offset for the cache of the missed CSS files for classes starting 'hb'
+static int missedHbCssFilesOffset = -1;
+static const QString HB_CLASSNAME_PREFIX("hb");
+
 static const int ICON_SOURCES_MAX_SIZE = 8;
 static QList<HbIconSource *> iconSources; // cache of recently used icon sources
 
+
+const int PIXEL_DEPTH = 4;
+const int TILE_SIZE_IN_PIXELS = 32 * 32;
+const int SGIMAGE_PIXEL_OVERHEAD = 200;
+
 HbIconSource *HbThemeServerUtils::getIconSource(const QString &filename)
 {
     foreach(HbIconSource *source, iconSources) {
@@ -107,9 +118,10 @@
  */
 int HbThemeServerUtils::getSharedStylesheet(const QString &fileName,
                                             HbLayeredStyleLoader::LayerPriority priority,
+                                            bool &fileExists,
                                             bool *inSharedCache)
 {
-    int cssOffset = -1;
+    qptrdiff cssOffset = -1;
     HbSharedCache *sharedCache = 0;
     if (priority == HbLayeredStyleLoader::Priority_Core) {
         sharedCache = HbSharedCache::instance();
@@ -121,16 +133,12 @@
         *inSharedCache = false;
     }
 
-#ifdef THEME_SERVER_TRACES
-    qDebug() << "In " << Q_FUNC_INFO;
-#endif // THEME_SERVER_TRACES
     if (cssOffset < 0) {
-        if (QFile::exists(fileName)) {
-            HbCss::Parser parser;
-            if (!parseCssFile(parser, fileName, cssOffset)) {
-                if (parser.errorCode == HbCss::Parser::OutOfMemoryError) {
-                    return OUT_OF_MEMORY_ERROR;
-                }
+        THEME_GENERIC_DEBUG() << Q_FUNC_INFO << "Stylesheet: " << fileName << " not found in shared cache.";
+        HbCss::Parser parser;
+        if (!parseCssFile(parser, fileName, cssOffset, fileExists)) {
+            if (parser.errorCode == HbCss::Parser::OutOfMemoryError) {
+                return OUT_OF_MEMORY_ERROR;
             }
         }
         if (sharedCache) { //sharedCache valid only when priority is Priority_Core
@@ -140,13 +148,41 @@
     return cssOffset;
 }
 
+/*
+ * Returns the offset of the missed CSS files for widgets starting with 'hb'
+ */
+int HbThemeServerUtils::getMissedHbCssFilesOffset()
+{
+    if (missedHbCssFilesOffset < 0) {
+        initMissedHbCssFilesList();
+    }
+    return missedHbCssFilesOffset;
+}
+
+void HbThemeServerUtils::initMissedHbCssFilesList()
+{
+    GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory);
+    int offset = -1;
+    try {
+        offset = manager->alloc(sizeof(HbVector<uint>));
+        HbVector<uint> *list = new((char*)manager->base() + offset)
+                HbVector<uint>(HbMemoryManager::SharedMemory);
+    } catch (std::bad_alloc &) {
+        if (offset >= 0) {
+            manager->free(offset);
+            offset = -1;
+        }
+    }
+    missedHbCssFilesOffset = offset;
+}
+
 /**
  * HbThemeServerUtils::parseCssFile()
  *
  * Returns false in case Css file has some error or there is not enough memory
  */
 bool HbThemeServerUtils::parseCssFile(HbCss::Parser &parser, const QString &fileName,
-                                      int &cssOffset)
+                                      qptrdiff &cssOffset, bool &fileExists)
 {
     bool retVal = false;
     // 1. Create a styleSheet in shared memory
@@ -168,7 +204,21 @@
         return retVal;
     }
     // 2. Parse the required file into styleSheet.
-    parser.init(fileName, true);
+    fileExists = parser.init(fileName, true);
+    if (!fileExists) {
+        if (QFileInfo(fileName).fileName().startsWith(HB_CLASSNAME_PREFIX)) {
+            HbVector<uint> *list = HbMemoryUtils::getAddress<HbVector<uint> >(
+                HbMemoryManager::SharedMemory, getMissedHbCssFilesOffset());
+            if (list) {
+                list->append(qHash(fileName));
+            }
+        }
+        if (cssOffset != -1) {
+            manager->free(cssOffset);
+            cssOffset = -1;
+        }
+        return retVal;
+    }
     
     retVal = parser.parse(styleSheet);
     if (!retVal) {
@@ -189,9 +239,9 @@
  */
 
 int HbThemeServerUtils::getSharedLayoutDefinition(const QString &fileName, const QString &layout,
-                                                  const QString &section)
+                                                  const QString &section, bool &fileExists)
 {
-    int layoutDefOffset = -1;
+    qptrdiff layoutDefOffset = -1;
     QStringRef nameKey(&fileName);
     if (nameKey.at(0) == ':') {
         //use only filename as a key.
@@ -218,13 +268,12 @@
     HbWidgetLoader loader;
 
     QFile file(fileName);
-    if (!file.open(QFile::ReadOnly | QFile::Text)) {
-        qWarning("Unable to open file");
+    fileExists = file.open(QFile::ReadOnly | QFile::Text);
+    if (!fileExists) {
+        THEME_GENERIC_DEBUG() << Q_FUNC_INFO << "Unable to open the file: " << fileName;
         return -1;
     }
-#ifdef THEME_SERVER_TRACES
-    qDebug() << "Trying to load: " << fileName << "::" << layout << "::" << section;
-#endif // THEME_SERVER_TRACES
+    THEME_GENERIC_DEBUG() << Q_FUNC_INFO << "Trying to load: " << fileName << "::" << layout << "::" << section;
 
     HbWidgetLoader::LayoutDefinition *layoutDef(0);
     GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory);
@@ -307,24 +356,15 @@
  */
 int HbThemeServerUtils::getSharedEffect(const QString &fileName)
 {
-#ifdef THEME_SERVER_TRACES
-    qDebug() << "In " << Q_FUNC_INFO << fileName;
-#endif // THEME_SERVER_TRACES
+    THEME_GENERIC_DEBUG() << Q_FUNC_INFO << "called with fileName: " << fileName;
 
-    int effOffset = -1;
+    qptrdiff effOffset = -1;
     if (effCache()->contains(fileName)) {
         effOffset = effCache()->value(fileName);
-
-#ifdef THEME_SERVER_TRACES
-        qDebug() << "Got effect in cache: " << fileName << "offset=" << effOffset;
-#endif //THEME_SERVER_TRACES
-
+        THEME_GENERIC_DEBUG() << "in cache: " << fileName << "offset=" << effOffset;
     } else {
-
-#ifdef THEME_SERVER_TRACES
-        qDebug() << "Not in cache, parsing: " << fileName;
-#endif //THEME_SERVER_TRACES
-
+        THEME_GENERIC_DEBUG() << "Not in cache, parsing: " << fileName;
+        
         // 1. Create an effect in shared memory
         GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory);
         HbEffectFxmlData *data = 0;
@@ -339,85 +379,69 @@
                 manager->free(effOffset);
                 effOffset = -1;
             }
+            THEME_GENERIC_DEBUG() << "Exception when allocating shared memory.";
             return effOffset;
         }
         // 2. Parse the file.
         HbEffectXmlParser parser;
 
+        QBuffer fxmlBuffer;
         QFile f(fileName);
         bool fail = false;
-        if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
+
+        if (f.open(QIODevice::ReadOnly)) {
             try {
-                parser.read(&f, data);
-                f.close();
+                QByteArray arr(f.readAll());
+                fxmlBuffer.setBuffer(&arr);
+                if (fxmlBuffer.open(QIODevice::ReadOnly | QIODevice::Text)) {
+                    parser.read(&fxmlBuffer, data);
+                } else {
+                    THEME_GENERIC_DEBUG() << "Cannot open fxmlBuffer from file:" << fileName;
+                    fail = true;
+                }
 
                 // 3. Mark an entry for this styleSheet into the table
-                effCache()->insert(fileName, effOffset);
+                if (!fail) {
+                    effCache()->insert(fileName, effOffset);
+                }
             } catch (std::exception &) {
-                f.close();
                 fail = true;
             }
         } else {
-#ifdef THEME_SERVER_TRACES
-            qWarning() << "Cannot open" << fileName;
-#endif // THEME_SERVER_TRACES
+            THEME_GENERIC_DEBUG() << "Cannot open:" << fileName;
             fail = true;
         }
         if (fail) {
             data->~HbEffectFxmlData();
             manager->free(effOffset);
+            THEME_GENERIC_DEBUG() << "Failed to parse effect.";
             return -1;
         }
 
+        // These will be open, if we got here
+        f.close();
+        fxmlBuffer.close();
+
         // add the filename and css offset to the secondary cache.
         // no need to check if this item is already present in the
         // cache as the parsing of the file happens only once
         // in the server side.
         HbSharedCache::instance()->add(HbSharedCache::Effect, fileName, effOffset);
     }
-
-#ifdef THEME_SERVER_TRACES
-    qDebug() << "returning offset: " << effOffset;
-#endif // THEME_SERVER_TRACES
-
+    
+    THEME_GENERIC_DEBUG() << "returning offset: " << effOffset;
     return effOffset;
 }
 
-/**
- * cleanupUnusedCss  function removes css-resources (stylesheets), whose reference count
- * is zero, it also releases the shared memory occupied by those resources.
- * \param cache server css-cache
- *
- */
-void HbThemeServerUtils::cleanupUnusedCss(HbCache *cache)
-{
-    QList<HbCacheItem*> list = cache->lruList();
-    while (!list.isEmpty()) {
-        HbCacheItem* itemToRemove = list.takeFirst();
-        if (itemToRemove->offset != -1) {
-            HbCss::StyleSheet *styleSheet =
-                HbMemoryUtils::getAddress<HbCss::StyleSheet>(HbMemoryManager::SharedMemory,
-                        itemToRemove->offset);
-            HbMemoryUtils::release<HbCss::StyleSheet>(styleSheet);
-            itemToRemove->offset = -1;
-        }
-        //Since we are cleaning up css-resources whose ref-count is zero, these entries will be
-        // removed from actual cache.
-        delete cache->cacheHandle().take(itemToRemove->fileName);
-    }
-}
-
 void HbThemeServerUtils::createThemeIndex(const QString &themePath, const HbThemeType &themetype)
 {
-    #ifdef THEME_INDEX_TRACES
-    qDebug() <<  "ThemeIndex: createThemeIndex" << themePath.toUtf8();
-    #endif
+    THEME_INDEX_DEBUG() <<  "ThemeIndex: createThemeIndex" << themePath.toUtf8();
     QDir themeBasePath(themePath);
     // Path is like "C:/resource/hb/themes/icons/sfwhitetheme"
     QString themeName = themeBasePath.dirName();
     
     QString filename(themeBasePath.absolutePath());
-    int cutindex = filename.lastIndexOf("/",filename.lastIndexOf("/")-1)+1;
+    int cutindex = filename.lastIndexOf('/',filename.lastIndexOf('/')-1)+1;
     filename = filename.left(cutindex);
     themeBasePath.setPath(filename);
     filename.append(themeName);
@@ -434,55 +458,35 @@
     bool indexOK = false;
 
     if (indexFile.open(QIODevice::ReadOnly)) {
-
         indexOK = true;
-
         GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory);
 
-        HbSharedChunkHeader *chunkHeader = (HbSharedChunkHeader*) manager->base();
-        
+        HbSharedChunkHeader *chunkHeader = (HbSharedChunkHeader*) manager->base();        
         qint64 byteSize = indexFile.size();
-
-        #ifdef THEME_INDEX_TRACES
-        qDebug() <<  "ThemeIndex: " << themeName.toUtf8() << " index file size:" << byteSize;
-        #endif
+        THEME_INDEX_DEBUG() <<  "ThemeIndex: " << themeName.toUtf8() << " index file size:" << byteSize;
 
         int offset = manager->alloc(byteSize);
         if (offset >= 0) {
-            #ifdef THEME_INDEX_TRACES
-            qDebug() <<  "ThemeIndex: memory allocated for theme: " << themeName.toUtf8();
-            #endif
+            THEME_INDEX_DEBUG() <<  "ThemeIndex: memory allocated for theme: " << themeName.toUtf8();
 
             // Read the theme index in the shared chunk
             char *address = HbMemoryUtils::getAddress<char>(HbMemoryManager::SharedMemory, offset);
 
             indexFile.read(address, byteSize);
             indexFile.close();
-
-            #ifdef THEME_INDEX_TRACES
-            qDebug() <<  "ThemeIndex: Reading themeindex for theme" << themeName.toUtf8() << "... Done!";
-            #endif
+            THEME_INDEX_DEBUG() <<  "ThemeIndex: Reading themeindex for theme" << themeName.toUtf8() << "... Done!";
 
             // Verify theme index contents if it is not located in ROM,
             // so that it does not have over-indexing offsets which might
             // crash all the clients trying to read from it.
 
-#ifdef Q_OS_SYMBIAN // ROM check only for Symbian - verify always in other platforms.
             if (themePath[0] != 'z' && themePath[0] != 'Z') {
-#endif
-                #ifdef THEME_INDEX_TRACES
-                qDebug() <<  "ThemeIndex: Validating themeindex for theme" << themeName.toUtf8();
-                #endif
-
+                THEME_INDEX_DEBUG() <<  "ThemeIndex: Validating themeindex for theme" << themeName.toUtf8();
                 HbThemeIndex index(address);
                 indexOK = index.validateItems(byteSize);
+                THEME_INDEX_DEBUG() <<  "ThemeIndex: Validating themeindex for theme" << themeName.toUtf8() << " done! Result: " << indexOK;
+            }
 
-                #ifdef THEME_INDEX_TRACES
-                qDebug() <<  "ThemeIndex: Validating themeindex for theme" << themeName.toUtf8() << " done! Result: " << indexOK;
-                #endif
-#ifdef Q_OS_SYMBIAN
-            }
-#endif
             if (indexOK) {
                 // Allocate theme path string from shared memory
                 QByteArray themePathArray = themeBasePath.absolutePath().toLatin1();
@@ -555,4 +559,131 @@
     }
 }
 
+int HbThemeServerUtils::computeCpuCost(const HbIconKey & key, HbIconFormatType iconType,
+                                        bool isConsolidatedIcon)
+{
+    int cpuItemCost = 0;
+    if (isConsolidatedIcon) {
+        QSize size = key.size.toSize();
+        cpuItemCost = size.width() * size.height() * PIXEL_DEPTH;
+        return cpuItemCost;
+    }
+    HbIconSource *source = HbThemeServerUtils::getIconSource(key.filename);
+    if (source) {
+        if (iconType == BLOB) {
+            QByteArray *sourceByteArray = source->byteArray();
+            if (sourceByteArray) {
+                cpuItemCost = sourceByteArray->length();
+            }
+        } else if (iconType == NVG) {
+            QByteArray *sourceByteArray = source->byteArray();
+            if (sourceByteArray) {
+                QSizeF renderSize = source->defaultSize();
+                if (!key.size.isNull()) {
+                    renderSize.scale(key.size,key.aspectRatioMode);
+                }
+                QSize size = renderSize.toSize();
+                cpuItemCost = size.width() * size.height() * PIXEL_DEPTH;
+            }    
+        } else if (iconType == SVG) {
+            QSvgRenderer *svgRenderer = source->svgRenderer();
+            if (svgRenderer && svgRenderer->isValid()) {
+                QSizeF renderSize = QSizeF(svgRenderer->defaultSize());
+                if (!key.size.isNull()) {
+                    renderSize.scale(key.size, key.aspectRatioMode);
+                }
+                QSize size = renderSize.toSize();
+                cpuItemCost = size.width() * size.height() * PIXEL_DEPTH;
+                source->releaseSvgRenderer();
+                
+            }    
+        } else {
+            QPixmap pm = QPixmap::fromImage(*source->image());
+            QSizeF renderSize = pm.size();
+            if (!key.size.isNull() ) {
+                renderSize.scale(key.size, key.aspectRatioMode);
+            }
+            QSize size = renderSize.toSize();
+            cpuItemCost = size.width() * size.height() * PIXEL_DEPTH;
+            
+        }
+            
+    }
+    return cpuItemCost;
+}
 
+
+int HbThemeServerUtils::computeGpuCost(const HbIconKey & key, HbIconFormatType iconType,
+                                        bool isConsolidatedIcon)
+{
+    int gpuItemCost = 0;
+    if (isConsolidatedIcon) {
+        QSize size = key.size.toSize();
+        int xTiles = ceil(size.width() / 32.0);
+        int yTiles = ceil(size.height() / 32.0);
+        int sizeInPixels =  xTiles * yTiles * TILE_SIZE_IN_PIXELS;
+        int sizeInBytes = sizeInPixels * PIXEL_DEPTH;
+        gpuItemCost = sizeInBytes + SGIMAGE_PIXEL_OVERHEAD ;
+        return gpuItemCost;
+    }
+    HbIconSource *source = HbThemeServerUtils::getIconSource(key.filename);
+    if (source) {
+        if (iconType == NVG) {
+            QByteArray *sourceByteArray = source->byteArray();
+            if (sourceByteArray) {
+                QSizeF renderSize = source->defaultSize();
+                if (!key.size.isNull()) {
+                    renderSize.scale(key.size,key.aspectRatioMode);
+                }
+                QSize size = renderSize.toSize();
+                int xTiles = ceil(size.width() / 32.0);
+                int yTiles = ceil(size.height() / 32.0);
+                int sizeInPixels =  xTiles * yTiles * TILE_SIZE_IN_PIXELS;
+                int sizeInBytes = sizeInPixels * PIXEL_DEPTH;
+                gpuItemCost = sizeInBytes + SGIMAGE_PIXEL_OVERHEAD ;
+            }
+        }
+    }
+    return gpuItemCost;
+
+}
+
+int HbThemeServerUtils::computeFrameItemCpuCost(const HbIconKey & key, HbIconFormatType iconType, 
+                                                HbRenderingMode rm)
+{
+    int cpuItemCost = 0;
+    HbIconSource *source = HbThemeServerUtils::getIconSource(key.filename);
+    if (source) {
+        if (iconType == SVG) {
+            QSvgRenderer *svgRenderer = source->svgRenderer();
+            if (svgRenderer && svgRenderer->isValid()) {
+                QSizeF renderSize = QSizeF(svgRenderer->defaultSize());
+                if (!key.size.isNull()) {
+                    renderSize.scale(key.size, key.aspectRatioMode);
+                }
+                QSize size = renderSize.toSize();
+                cpuItemCost = size.width() * size.height() * PIXEL_DEPTH;
+                source->releaseSvgRenderer();
+                    
+            }
+        } else if (iconType == NVG) {
+            QByteArray *sourceByteArray = source->byteArray();
+            if (sourceByteArray) {    
+                if (rm == EHWRendering ) {
+                    cpuItemCost = sourceByteArray->length();
+                } else {
+                    QSizeF renderSize = source->defaultSize();
+                    if (!key.size.isNull()) {
+                        renderSize.scale(key.size,key.aspectRatioMode);
+                    }
+                    QSize size = renderSize.toSize();
+                    cpuItemCost = size.width() * size.height() * PIXEL_DEPTH;
+               }
+            }
+        }
+    }    
+    return cpuItemCost;
+    
+}
+   
+