1
0
Fork 0
mirror of https://github.com/geometer/FBReaderJ.git synced 2025-10-05 19:42:17 +02:00

CSS @import support

This commit is contained in:
Nikolay Pultsin 2014-03-26 11:54:05 +02:00
parent 8824ec019e
commit f22f0a041f
3 changed files with 58 additions and 10 deletions

View file

@ -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)

View file

@ -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<std::string>::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<ZLInputStream> 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<shared_ptr<Entry> >::const_iterator it = myEntries.begin(); it != myEntries.end(); ++it) {
const Entry &entry = **it;

View file

@ -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<std::string> 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<shared_ptr<Entry> > myEntries;