diff -r 11d3954df52a -r 627c4a0fd0e7 src/hbtools/hbbincssmaker/main.cpp --- a/src/hbtools/hbbincssmaker/main.cpp Thu May 27 13:10:59 2010 +0300 +++ b/src/hbtools/hbbincssmaker/main.cpp Fri Jun 11 13:58:22 2010 +0300 @@ -32,10 +32,17 @@ #include #include #include +#include +#include // Global variables -QString AppName("hbbincssmaker"); +static const QString CSSFileExtension = ".css"; +static const QString WMLFileExtension = ".widgetml"; +static const QString ColorCSSEnding = "_color.css"; + +static const QString AppName = "hbbincssmaker"; static bool verboseOn = false; + QTextStream out(stdout); QTextStream verboseOut(stderr); QTextStream err(stderr); @@ -44,6 +51,17 @@ #define VERBOSEIF(test, statement) if(verboseOn && test) { verboseOut << statement; } #define VERBOSELN(statement) if(verboseOn) { verboseOut << statement << endl; } +struct WidgetMLParseInput +{ + QString filename; + QList layouts; + + void clear() + { + layouts.clear(); + filename.clear(); + } +}; void testDeclarations(const HbVector &decls) { @@ -115,72 +133,114 @@ } } -class CssMap +void testLayoutDef(const HbWidgetLoader::LayoutDefinition *layoutDef) +{ + VERBOSELN("mesh items count: " << layoutDef->meshItems.count()); + for (int i = 0; i < layoutDef->meshItems.count(); ++i) { + const HbWidgetLoader::MeshItem &meshItem = layoutDef->meshItems.at(i); + VERBOSELN("src: " << meshItem.src); + VERBOSELN("dst: " << meshItem.dst); + VERBOSELN("spacing text: " << meshItem.spacingText); + VERBOSELN("spacer: " << meshItem.spacer); + } +} + +bool testCss() { -public: - CssMap() {} - void add(const QString &cssName, unsigned int offset) - { - HbOffsetItem mapItem = _mapItems.value(cssName, HbOffsetItem()); - if (mapItem.nameOffset < 0) { - mapItem.nameOffset = _cssNameBuffer.size(); - mapItem.offset = offset; - _cssNameBuffer.append(cssName.toLatin1()).append('\0'); - _mapItems.insert(cssName, mapItem); - } else { - err << "warning: duplicate cache key for " << cssName << endl; - } - } + GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory); + HbSharedMemoryManager *shared = static_cast(manager); + HbSharedCache *cache = shared->cache(); - void registerOffsetHolders() { - foreach(const HbOffsetItem &mapItem, _mapItems) { - HbCssConverterUtils::registerOffsetHolder(const_cast(&mapItem.offset)); + for (int k = 0; k < cache->mOffsetItemCount; ++k) { + if (cache->mOffsetItems[k].offsetCSS >= 0) { + HbCss::StyleSheet *sheet = HbMemoryUtils::getAddress( + HbMemoryManager::SharedMemory, cache->mOffsetItems[k].offsetCSS); + VERBOSELN("Cssmap item " << k + << "- hash value: \"" << cache->mOffsetItems[k].offsetCSS << "\""); + // Tests the stylesheet offsets and prints info to verbose out + testStyleSheet(sheet); + + //test layout definition. + int tableSize = 0; + const HbLayoutIndexItem *ptr = cache->layoutIndexItemBegin( + cache->mOffsetItems[k].offsetLayoutIndexTable, &tableSize); + for (; tableSize > 0; --tableSize, ++ptr) { + HbWidgetLoader::LayoutDefinition *layoutDef = + HbMemoryUtils::getAddress( + HbMemoryManager::SharedMemory, ptr->offset); + testLayoutDef(layoutDef); + } } } + return true; +} - QByteArray data() const { - QByteArray dataArray; - int count = _mapItems.size(); - int adjustment = count * sizeof(HbOffsetItem); - foreach(const HbOffsetItem &mapItem, _mapItems) { - HbOffsetItem tmp(mapItem); - // Fix offsets in the items to be based on the beginning of the css map instead of - // the beginning of the css name buffer. - tmp.nameOffset += adjustment; - dataArray.append(reinterpret_cast(&tmp), sizeof(HbOffsetItem)); - } - dataArray.append(_cssNameBuffer); - return dataArray; - } - int size() const { return _mapItems.count(); } +/*! + Collects and return layout names from \a styleRules. + \a layoutSet - map of already found layoutnames and sections to prevent duplicate layouts + to be added. -private: - QMap _mapItems; - QByteArray _cssNameBuffer; -}; +*/ +QList collectLayoutNames( + QSet > &layoutSet, + const HbVector &styleRules) +{ + QList layouts; + layouts.append(CSSLayoutInfo()); -struct InputFile -{ - InputFile(const QString &cacheName, const QFileInfo &file) : cacheName(cacheName), file(file) - { + foreach(const HbCss::StyleRule &rule, styleRules) { + foreach(const HbCss::Declaration &decl, rule.declarations) { + if (decl.propertyId == HbCss::Property_Layout) { + if (decl.values.count() == 1) { + layouts.last().layoutname = decl.values.at(0).variant.toString(); + } + } else if (decl.propertyId == HbCss::Property_Section) { + if (decl.values.count() == 1) { + layouts.last().section = decl.values.at(0).variant.toString(); + } + } + } + const CSSLayoutInfo &infoRef = layouts.last(); + if (!infoRef.layoutname.isEmpty()) { + QPair layout = qMakePair(infoRef.layoutname, + infoRef.section); + //only add layout, if not already collected before. + if (!layoutSet.contains(layout)) { + layoutSet.insert(layout); + layouts.append(CSSLayoutInfo()); + } + } } - - QString cacheName; - QFileInfo file; -}; -typedef QList InputFileList; + layouts.removeLast(); + return layouts; +} -struct InputFileInfo +/*! + Collects all the layouts defined in \a stylesheet and add the result to \a input. + returns true, if at least one layout is found. +*/ +bool collectLayouts(const QString &cssFilePath, + HbCss::StyleSheet *styleSheet, + WidgetMLParseInput &input) { - QString base; - QString path; - QString prefix; -}; -typedef QList InputFileInfoList; - -bool operator < (const InputFile & if1, const InputFile & if2) -{ - return if1.file.size() > if2.file.size(); + input.clear(); + QSet > layoutSet; //for removing duplicate layout names. + foreach(const HbCss::WidgetStyleRules &rule, styleSheet->widgetRules) { + layoutSet.clear(); + input.layouts += collectLayoutNames(layoutSet, rule.styleRules); + input.layouts += collectLayoutNames(layoutSet, rule.portraitRules); + input.layouts += collectLayoutNames(layoutSet, rule.landscapeRules); + } + bool hasLayoutDef = false; + if (!input.layouts.isEmpty()) { + //if css contains at least 1 layout declaration, it might have .widgetml file. + QString filePath(cssFilePath); + filePath.replace(filePath.size() - CSSFileExtension.size(), + CSSFileExtension.size(), WMLFileExtension); + input.filename = filePath; + hasLayoutDef = true; + } + return hasLayoutDef; } void printHelp() @@ -206,103 +266,203 @@ return collected; } -InputFileList collectCssFiles(const QStringList &inputFilePaths) +QMap collectCssFiles(const QStringList &inputFilePaths) { QStringList filters; filters << "*.css"; - InputFileList inputFiles; + QMap cssFileMap; QFileInfoList inputPath; inputPath.append(QFileInfo()); Q_FOREACH(const QString &path, inputFilePaths) { inputPath[0].setFile(path); QFileInfoList allFiles = collectFiles(inputPath, filters); Q_FOREACH(const QFileInfo &info, allFiles) { - inputFiles.append(InputFile(info.fileName(), info)); + QMap::const_iterator i = cssFileMap.find(info.fileName()); + if (i == cssFileMap.end()) { + cssFileMap.insert(info.fileName(), info); + } else { + err << "duplicate css filenames found: " << i.value().absoluteFilePath() << + " & " << info.absoluteFilePath(); + } } } - return inputFiles; + return cssFileMap; } -bool writeCssBinary(const QStringList &inputFiles, const QString &targetFile) +/*! + Collects the css files from \a inputFiles, parses them to shared memory, stores + offsets to \a offsetMap. + returns true on success. +*/ +bool parseCss(const QStringList &inputFiles, HbOffsetMapBuilder &offsetMap) { if (inputFiles.isEmpty()) return false; - InputFileList cssFiles = collectCssFiles(inputFiles); - if (cssFiles.isEmpty()) return false; - qSort(cssFiles); + QMap cssFiles = collectCssFiles(inputFiles); HbCss::Parser parser; HbCss::StyleSheet *styleSheet = 0; bool success = false; - CssMap cssMap; + GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory); - Q_FOREACH(const InputFile &inputFile, cssFiles) { - const QFileInfo &file = inputFile.file; - VERBOSE("processing " << file.absoluteFilePath() << "..."); - success = false; - int offset = manager->alloc(sizeof(HbCss::StyleSheet)); - if (offset >= 0) { - styleSheet = new (static_cast(manager->base()) + offset) - HbCss::StyleSheet(HbMemoryManager::SharedMemory); - parser.init(file.absoluteFilePath(), true); - success = parser.parse(styleSheet); - cssMap.add(inputFile.cacheName, offset); - VERBOSE("cache key = " << inputFile.cacheName << "..."); + while (!cssFiles.isEmpty()) { + QMap::iterator first = cssFiles.begin(); + QMap::iterator CSSFiles[CSSFileTypeEnd]; + + QString widgetName(first.key()); + if (widgetName.endsWith(ColorCSSEnding)) { + //color css file, find the layout css pair. + CSSFiles[ColorCSSFile] = first; + widgetName.remove(widgetName.size() - ColorCSSEnding.size(), + ColorCSSEnding.size()); + CSSFiles[CSSFile] = cssFiles.find(widgetName + CSSFileExtension); + } else { + //layout css file, find the color css pair. + CSSFiles[CSSFile] = first; + widgetName.remove(widgetName.size() - CSSFileExtension.size(), + CSSFileExtension.size()); + CSSFiles[ColorCSSFile] = cssFiles.find(widgetName + ColorCSSEnding); + } + int offsets[] = {-1, -1}; + + for (int i = 0; i < CSSFileTypeEnd; ++i) { + if (CSSFiles[i] != cssFiles.end()) { + const QFileInfo &file = CSSFiles[i].value(); + VERBOSE("processing " << file.absoluteFilePath() << "..."); + offsets[i] = manager->alloc(sizeof(HbCss::StyleSheet)); + if (offsets[i] >= 0) { + styleSheet = new (static_cast(manager->base()) + offsets[i]) + HbCss::StyleSheet(HbMemoryManager::SharedMemory); + parser.init(file.absoluteFilePath(), true); + success = parser.parse(styleSheet); + VERBOSE("cache key = " << CSSFiles[i].key() << "..."); + } + if (success) { + VERBOSELN("ok"); + } else { + VERBOSELN("failed"); + err << "Failed to parse: " << file.absoluteFilePath() << endl; + break; + } + } } + + const QFileInfo *info = 0; + QString tmp; + if (CSSFiles[CSSFile] != cssFiles.end()) { + tmp = CSSFiles[CSSFile].key(); + info = &CSSFiles[CSSFile].value(); + } + if (!offsetMap.addWidgetOffsets(widgetName, info, offsets)) { + return false; + } + + //remove processed files from the map. + cssFiles.erase(CSSFiles[ColorCSSFile]); + if (!tmp.isEmpty()) { + cssFiles.remove(tmp); + } + } + return success; +} + +/*! + Parses widgetml file and all the layouts using the info from \a parseInput for a widget, + which hash is \a widgetHash, add offsets to \a offsetMap. +*/ +bool parseWidgetML(HbOffsetMapBuilder &offsetMap, + quint32 widgetHash, + const WidgetMLParseInput &parseInput) +{ + HbWidgetLoader loader; + + VERBOSELN("processing: " << parseInput.filename); + QFile file(parseInput.filename); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + VERBOSELN("unable to open file: " << parseInput.filename); + return false; + } + HbWidgetLoader::LayoutDefinition *layoutDef = 0; + int layoutDefOffset = -1; + bool success = true; + + GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory); + QList layoutInfoList; + Q_FOREACH(const CSSLayoutInfo &info, parseInput.layouts) { + VERBOSE("layout: " << info.layoutname << ", " << "section: " << info.section << "..."); + + layoutDefOffset = manager->alloc(sizeof(HbWidgetLoader::LayoutDefinition)); + layoutDef = new(static_cast(manager->base()) + layoutDefOffset) + HbWidgetLoader::LayoutDefinition(HbMemoryManager::SharedMemory); + success = loader.loadLayoutDefinition(layoutDef, &file, info.layoutname, info.section); + if (success) { + layoutInfoList.append(LayoutItem(&info)); + layoutInfoList.last().offset = layoutDefOffset; VERBOSELN("ok"); } else { VERBOSELN("failed"); - err << "Failed to parse: " << file.absoluteFilePath() << endl; break; } + file.seek(0); + } + success = offsetMap.addWidgetMLOffsets(parseInput.filename, widgetHash, layoutInfoList); + return success; +} + +/*! + Parse all the widgetmls to shared memory for widget's found in \a offsetMap, + store the offsets to \a offsetMap. +*/ +bool parseWidgetML(HbOffsetMapBuilder &offsetMap) +{ + QList itemList = offsetMap.items(); + Q_FOREACH(const HbBinMakerOffsetItem &item, itemList) { + if (item.offsetCSS >= 0) { + HbCss::StyleSheet *sheet = HbMemoryUtils::getAddress( + HbMemoryManager::SharedMemory, item.offsetCSS); + WidgetMLParseInput file; + if (collectLayouts(item.name, sheet, file)) { + parseWidgetML(offsetMap, item.widgetHash, file); + } + } } - if (success) { - HbSharedMemoryManager *shared = static_cast(manager); - - // Create shared cache to shared memory. - QByteArray data(cssMap.data()); - - if (shared->createSharedCache(data.data(), data.size(), cssMap.size())) { + return true; +} - // Defragment the chunk contents before dumping it in a file - int endOffset = HbCssConverterUtils::defragmentChunk(); - - if (verboseOn) { - HbSharedCache *cache = shared->cache(); - - for (int k=0; kmOffsetItemCount; ++k) { - HbCss::StyleSheet *sheet = HbMemoryUtils::getAddress( - HbMemoryManager::SharedMemory, cache->mOffsetItems[k].offset); - - QString name(QLatin1String( ((char*)(cache->mOffsetItems)) + cache->mOffsetItems[k].nameOffset)); +bool writeCssBinary(const QStringList &inputFiles, const QString &targetFile) +{ + HbOffsetMapBuilder offsetMap; + if (!(parseCss(inputFiles, offsetMap) + && parseWidgetML(offsetMap))) { + return false; + } + GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory); + HbSharedMemoryManager *shared = static_cast(manager); - VERBOSE("Cssmap item "); - VERBOSE(k); - VERBOSE("- name: \""); - VERBOSE(name); - VERBOSELN("\""); + // Create shared cache to shared memory. + QByteArray data(offsetMap.result()); + bool success = false; + if (shared->createSharedCache(data.data(), data.size(), offsetMap.size())) { + // Defragment the chunk contents before dumping it in a file + int endOffset = HbCssConverterUtils::defragmentChunk(); + if (verboseOn) testCss(); - // Tests the stylesheet offsets and prints info to verbose out - testStyleSheet(sheet); - } - } - - VERBOSELN("writing the binary file"); - QFile binFile(targetFile); - if (!binFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - err << "failed to open target binary file: " << binFile.fileName() << endl; - return false; - } - //int size = shared->size(); - if (binFile.write(static_cast(manager->base()), endOffset) >= 0) { + VERBOSELN("writing the binary file"); + QFile binFile(targetFile); + success = binFile.open(QIODevice::WriteOnly | QIODevice::Truncate); + if (success) { + success = (binFile.write(static_cast(manager->base()), endOffset) >= 0); + if (success) { VERBOSELN("Wrote target binary file: " << binFile.fileName()); } else { err << "failed to write to target binary file: " << binFile.fileName() << endl; } } else { - err << "failed to create shared cache." << endl; + err << "failed to open target binary file: " << binFile.fileName() << endl; } + } else { + err << "failed to create shared cache." << endl; } return success; } @@ -310,6 +470,7 @@ int main(int argc, char **argv) { QCoreApplication app(argc, argv); + int returnValue = 0; if(argc < 3) { printHelp(); @@ -335,15 +496,18 @@ if (targetFile.isEmpty()) { err << "target filename needed" << endl << endl; printHelp(); + returnValue = 1; } else { QString parentDir(QFileInfo(targetFile).absolutePath()); if (QDir::current().mkpath(parentDir)) { - writeCssBinary(inputFiles, targetFile); + if (!writeCssBinary(inputFiles, targetFile)) { + returnValue = 3; + } } else { err << "failed to create path: " << parentDir << endl; + returnValue = 2; } } } - return 0; + return returnValue; } -