--- 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 §ion)
+ const QString §ion, 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;
+
+}
+
+