diff options
| author | Michele Calgaro <michele.calgaro@yahoo.it> | 2024-06-07 23:30:05 +0900 |
|---|---|---|
| committer | Michele Calgaro <michele.calgaro@yahoo.it> | 2024-06-07 23:30:05 +0900 |
| commit | 17b259df9cb6b28779d4881b2b6c805ee2e48eea (patch) | |
| tree | 5ed61937459cb7081089111b0242c01ec178f1f3 /reader/src/formats/css/StyleSheetParser.cpp | |
| parent | 1cba8bce178eb2d6719c6f7f21e2c9352c5513a6 (diff) | |
| download | tde-ebook-reader-17b259df9cb6b28779d4881b2b6c805ee2e48eea.tar.gz tde-ebook-reader-17b259df9cb6b28779d4881b2b6c805ee2e48eea.zip | |
Rename to tde-ebook-reader
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
Diffstat (limited to 'reader/src/formats/css/StyleSheetParser.cpp')
| -rw-r--r-- | reader/src/formats/css/StyleSheetParser.cpp | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/reader/src/formats/css/StyleSheetParser.cpp b/reader/src/formats/css/StyleSheetParser.cpp new file mode 100644 index 0000000..33dc900 --- /dev/null +++ b/reader/src/formats/css/StyleSheetParser.cpp @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <cctype> +#include <cstring> + +#include <ZLStringUtil.h> +#include <ZLInputStream.h> +#include <ZLLogger.h> + +#include "StyleSheetParser.h" + +StyleSheetTableParser::StyleSheetTableParser(StyleSheetTable &table) : myTable(table) { + //ZLLogger::Instance().registerClass("CSS"); +} + +void StyleSheetTableParser::storeData(const std::string &selector, const StyleSheetTable::AttributeMap &map) { + std::string s = selector; + ZLStringUtil::stripWhiteSpaces(s); + + if (s.empty()) { + return; + } + + if (s[0] == '@') { + processAtRule(s, map); + return; + } + + const std::vector<std::string> ids = ZLStringUtil::split(s, ","); + for (std::vector<std::string>::const_iterator it = ids.begin(); it != ids.end(); ++it) { + std::string id = *it; + ZLStringUtil::stripWhiteSpaces(id); + if (!id.empty()) { + const std::size_t index = id.find('.'); + if (index == std::string::npos) { + myTable.addMap(id, std::string(), map); + } else { + myTable.addMap(id.substr(0, index), id.substr(index + 1), map); + } + } + } +} + +void StyleSheetTableParser::processAtRule(const std::string &name, const StyleSheetTable::AttributeMap &map) { + (void)map; + if (name == "@font-face") { + } +} + +shared_ptr<ZLTextStyleEntry> StyleSheetSingleStyleParser::parseString(const char *text) { + myReadState = WAITING_FOR_ATTRIBUTE; + parse(text, std::strlen(text), true); + shared_ptr<ZLTextStyleEntry> control = StyleSheetTable::createControl(myMap); + reset(); + return control; +} + +StyleSheetParser::StyleSheetParser() { + reset(); +} + +StyleSheetParser::~StyleSheetParser() { +} + +void StyleSheetParser::reset() { + myWord.erase(); + myAttributeName.erase(); + myReadState = WAITING_FOR_SELECTOR; + myInsideComment = false; + mySelectorString.erase(); + myMap.clear(); +} + +void StyleSheetParser::parse(ZLInputStream &stream) { + if (stream.open()) { + char *buffer = new char[1024]; + while (true) { + int len = stream.read(buffer, 1024); + if (len == 0) { + break; + } + parse(buffer, len); + } + delete[] buffer; + stream.close(); + } +} + +void StyleSheetParser::parse(const char *text, int len, bool final) { + const char *start = text; + const char *end = text + len; + for (const char *ptr = start; ptr != end; ++ptr) { + if (std::isspace(*ptr)) { + if (start != ptr) { + myWord.append(start, ptr - start); + } + processWord(myWord); + myWord.erase(); + start = ptr + 1; + } else if (isControlSymbol(*ptr)) { + if (start != ptr) { + myWord.append(start, ptr - start); + } + processWord(myWord); + myWord.erase(); + processControl(*ptr); + start = ptr + 1; + } + } + if (start < end) { + myWord.append(start, end - start); + if (final) { + processWord(myWord); + myWord.erase(); + } + } +} + +bool StyleSheetParser::isControlSymbol(const char symbol) { + switch (myReadState) { + default: + case WAITING_FOR_SELECTOR: + return false; + case SELECTOR: + return symbol == '{' || symbol == ';'; + case WAITING_FOR_ATTRIBUTE: + return symbol == '}' || symbol == ':'; + case ATTRIBUTE_NAME: + return symbol == ':'; + case ATTRIBUTE_VALUE: + return symbol == '}' || symbol == ';'; + } +} + +void StyleSheetParser::storeData(const std::string&, const StyleSheetTable::AttributeMap&) { +} + +void StyleSheetParser::processAtRule(const std::string&, const StyleSheetTable::AttributeMap&) { +} + +void StyleSheetParser::processControl(const char control) { + switch (myReadState) { + case WAITING_FOR_SELECTOR: + break; + case SELECTOR: + switch (control) { + case '{': + myReadState = WAITING_FOR_ATTRIBUTE; + break; + case ';': + myReadState = WAITING_FOR_SELECTOR; + mySelectorString.erase(); + break; + } + break; + case WAITING_FOR_ATTRIBUTE: + if (control == '}') { + myReadState = WAITING_FOR_SELECTOR; + storeData(mySelectorString, myMap); + mySelectorString.erase(); + myMap.clear(); + } + break; + case ATTRIBUTE_NAME: + if (control == ':') { + myReadState = ATTRIBUTE_VALUE; + } + break; + case ATTRIBUTE_VALUE: + if (control == ';') { + myReadState = WAITING_FOR_ATTRIBUTE; + } else if (control == '}') { + myReadState = WAITING_FOR_SELECTOR; + storeData(mySelectorString, myMap); + mySelectorString.erase(); + myMap.clear(); + } + break; + } +} + +void StyleSheetParser::processWord(std::string &word) { + while (!word.empty()) { + int index = word.find(myInsideComment ? "*/" : "/*"); + if (!myInsideComment) { + if (index == -1) { + processWordWithoutComments(word); + } else if (index > 0) { + processWordWithoutComments(word.substr(0, index)); + } + } + if (index == -1) { + break; + } + myInsideComment = !myInsideComment; + word.erase(0, index + 2); + } +} + +void StyleSheetParser::processWordWithoutComments(const std::string &word) { + switch (myReadState) { + case WAITING_FOR_SELECTOR: + myReadState = SELECTOR; + mySelectorString = word; + break; + case SELECTOR: + mySelectorString += ' ' + word; + break; + case WAITING_FOR_ATTRIBUTE: + myReadState = ATTRIBUTE_NAME; + // go through + case ATTRIBUTE_NAME: + myAttributeName = word; + myMap[myAttributeName].clear(); + break; + case ATTRIBUTE_VALUE: + { + const std::size_t l = word.length(); + if (l >= 2 && (word[0] == '"' || word[0] == '\'') && word[0] == word[l - 1]) { + myMap[myAttributeName].push_back(word.substr(1, l - 2)); + } else { + myMap[myAttributeName].push_back(word); + } + break; + } + } +} |
