diff --git a/ChangeLog b/ChangeLog index b446cc49a..8b470aec5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,7 @@ * Experimental video support * CSS parsing optimization for ePubs (do not parse css files multiple times) * CSS support improvement: added support for space-separated classes list +* Added CSS @import support ===== 1.9.6.1 (Feb 24, 2014) ===== * Fixed some config vaues reading (e.g. background) diff --git a/jni/NativeFormats/fbreader/src/formats/css/StyleSheetParser.cpp b/jni/NativeFormats/fbreader/src/formats/css/StyleSheetParser.cpp index c83c3f519..db3eff874 100644 --- a/jni/NativeFormats/fbreader/src/formats/css/StyleSheetParser.cpp +++ b/jni/NativeFormats/fbreader/src/formats/css/StyleSheetParser.cpp @@ -42,6 +42,8 @@ void StyleSheetParser::reset() { myInsideComment = false; mySelectorString.erase(); myMap.clear(); + myImportVector.clear(); + myFirstRuleProcessed = false; } void StyleSheetParser::parse(const char *text, int len, bool final) { @@ -81,6 +83,8 @@ bool StyleSheetParser::isControlSymbol(const char symbol) { return false; case SELECTOR: return symbol == '{' || symbol == ';'; + case IMPORT: + return symbol == ';'; case WAITING_FOR_ATTRIBUTE: return symbol == '}' || symbol == ':'; case ATTRIBUTE_NAME: @@ -93,6 +97,23 @@ bool StyleSheetParser::isControlSymbol(const char symbol) { void StyleSheetParser::storeData(const std::string&, const StyleSheetTable::AttributeMap&) { } +std::string StyleSheetParser::url2FullPath(const std::string &url) const { + std::string path = url; + if (ZLStringUtil::stringStartsWith(path, "url(") && + ZLStringUtil::stringEndsWith(path, ")")) { + path = path.substr(4, path.size() - 5); + } + if (path.size() > 2 && path[0] == path[path.size() - 1]) { + if (path[0] == '\'' || path[0] == '"') { + path = path.substr(1, path.size() - 2); + } + } + return myPathPrefix + MiscUtil::decodeHtmlURL(path); +} + +void StyleSheetParser::importCSS(const std::string &path) { +} + void StyleSheetParser::processControl(const char control) { switch (myReadState) { case WAITING_FOR_SELECTOR: @@ -108,6 +129,15 @@ void StyleSheetParser::processControl(const char control) { break; } break; + case IMPORT: + if (control == ';') { + if (!myImportVector.empty()) { + importCSS(url2FullPath(myImportVector[0])); + myImportVector.clear(); + } + myReadState = WAITING_FOR_SELECTOR; + } + break; case WAITING_FOR_ATTRIBUTE: if (control == '}') { myReadState = WAITING_FOR_SELECTOR; @@ -155,12 +185,19 @@ void StyleSheetParser::processWord(std::string &word) { void StyleSheetParser::processWordWithoutComments(const std::string &word) { switch (myReadState) { case WAITING_FOR_SELECTOR: - myReadState = SELECTOR; mySelectorString = word; + if (word == "@import") { + myReadState = IMPORT; + } else { + myReadState = SELECTOR; + } break; case SELECTOR: mySelectorString += ' ' + word; break; + case IMPORT: + myImportVector.push_back(word); + break; case WAITING_FOR_ATTRIBUTE: myReadState = ATTRIBUTE_NAME; // go through @@ -240,26 +277,21 @@ void StyleSheetMultiStyleParser::processAtRule(const std::string &name, const St return; } const StyleSheetTable::AttributeMap::const_iterator it = attributes.find("src"); - std::string url; + std::string path; if (it != attributes.end()) { for (std::vector::const_iterator jt = it->second.begin(); jt != it->second.end(); ++jt) { if (ZLStringUtil::stringStartsWith(*jt, "url(") && ZLStringUtil::stringEndsWith(*jt, ")")) { - url = jt->substr(4, jt->size() - 5); - if (url.size() > 2 && url[0] == url[url.size() - 1]) { - if (url[0] == '\'' || url[0] == '"') { - url = url.substr(1, url.size() - 2); - } - } + path = url2FullPath(*jt); break; } } } - if (url.empty()) { + if (path.empty()) { ZLLogger::Instance().println("FONT", "Source not specified for " + family); return; } - const ZLFile fontFile(myPathPrefix + MiscUtil::decodeHtmlURL(url)); + const ZLFile fontFile(path); const bool bold = firstValue(attributes, "font-weight") == "bold"; const bool italic = firstValue(attributes, "font-style") == "italic"; ZLLogger::Instance().println("FONT", family + " => " + fontFile.path()); @@ -295,6 +327,15 @@ void StyleSheetParserWithCache::store(const std::string &tag, const std::string myEntries.push_back(new Entry(tag, aClass, map)); } +void StyleSheetParserWithCache::importCSS(const std::string &path) { + shared_ptr stream = ZLFile(path).inputStream(); + if (!stream.isNull()) { + StyleSheetParserWithCache importParser(myPathPrefix); + importParser.parseStream(*stream); + myEntries.(myEntries.end(), importParser.myEntries.begin(), importParser.myEntries.end()); + } +} + void StyleSheetParserWithCache::applyToTable(StyleSheetTable &table) const { for (std::list >::const_iterator it = myEntries.begin(); it != myEntries.end(); ++it) { const Entry &entry = **it; diff --git a/jni/NativeFormats/fbreader/src/formats/css/StyleSheetParser.h b/jni/NativeFormats/fbreader/src/formats/css/StyleSheetParser.h index ab7fbd7ce..004b8afbb 100644 --- a/jni/NativeFormats/fbreader/src/formats/css/StyleSheetParser.h +++ b/jni/NativeFormats/fbreader/src/formats/css/StyleSheetParser.h @@ -38,6 +38,8 @@ public: protected: virtual void storeData(const std::string &selector, const StyleSheetTable::AttributeMap &map); + std::string url2FullPath(const std::string &url) const; + virtual void importCSS(const std::string &path); private: bool isControlSymbol(const char symbol); @@ -54,6 +56,7 @@ private: enum { WAITING_FOR_SELECTOR, SELECTOR, + IMPORT, WAITING_FOR_ATTRIBUTE, ATTRIBUTE_NAME, ATTRIBUTE_VALUE, @@ -61,6 +64,8 @@ private: bool myInsideComment; std::string mySelectorString; StyleSheetTable::AttributeMap myMap; + std::vector myImportVector; + bool myFirstRuleProcessed; friend class StyleSheetSingleStyleParser; }; @@ -117,6 +122,7 @@ public: private: void store(const std::string &tag, const std::string &aClass, const StyleSheetTable::AttributeMap &map); + void importCSS(const std::string &path); private: std::list > myEntries;