summaryrefslogtreecommitdiffstats
path: root/reader/src/formats/css
diff options
context:
space:
mode:
Diffstat (limited to 'reader/src/formats/css')
-rw-r--r--reader/src/formats/css/StyleSheetParser.cpp244
-rw-r--r--reader/src/formats/css/StyleSheetParser.h84
-rw-r--r--reader/src/formats/css/StyleSheetTable.cpp267
-rw-r--r--reader/src/formats/css/StyleSheetTable.h76
4 files changed, 671 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;
+ }
+ }
+}
diff --git a/reader/src/formats/css/StyleSheetParser.h b/reader/src/formats/css/StyleSheetParser.h
new file mode 100644
index 0000000..8949823
--- /dev/null
+++ b/reader/src/formats/css/StyleSheetParser.h
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#ifndef __STYLESHEETPARSER_H__
+#define __STYLESHEETPARSER_H__
+
+#include "StyleSheetTable.h"
+
+class ZLInputStream;
+
+class StyleSheetParser {
+
+protected:
+ StyleSheetParser();
+
+public:
+ virtual ~StyleSheetParser();
+ void reset();
+ void parse(ZLInputStream &stream);
+ void parse(const char *text, int len, bool final = false);
+
+protected:
+ virtual void storeData(const std::string &selector, const StyleSheetTable::AttributeMap &map);
+ virtual void processAtRule(const std::string &name, const StyleSheetTable::AttributeMap &map);
+
+private:
+ bool isControlSymbol(const char symbol);
+ void processWord(std::string &word);
+ void processWordWithoutComments(const std::string &word);
+ void processControl(const char control);
+
+private:
+ std::string myWord;
+ std::string myAttributeName;
+ enum {
+ WAITING_FOR_SELECTOR,
+ SELECTOR,
+ WAITING_FOR_ATTRIBUTE,
+ ATTRIBUTE_NAME,
+ ATTRIBUTE_VALUE,
+ } myReadState;
+ bool myInsideComment;
+ std::string mySelectorString;
+ StyleSheetTable::AttributeMap myMap;
+
+friend class StyleSheetSingleStyleParser;
+};
+
+class StyleSheetTableParser : public StyleSheetParser {
+
+public:
+ StyleSheetTableParser(StyleSheetTable &table);
+
+private:
+ void storeData(const std::string &selector, const StyleSheetTable::AttributeMap &map);
+ void processAtRule(const std::string &name, const StyleSheetTable::AttributeMap &map);
+
+private:
+ StyleSheetTable &myTable;
+};
+
+class StyleSheetSingleStyleParser : public StyleSheetParser {
+
+public:
+ shared_ptr<ZLTextStyleEntry> parseString(const char *text);
+};
+
+#endif /* __STYLESHEETPARSER_H__ */
diff --git a/reader/src/formats/css/StyleSheetTable.cpp b/reader/src/formats/css/StyleSheetTable.cpp
new file mode 100644
index 0000000..fe45a85
--- /dev/null
+++ b/reader/src/formats/css/StyleSheetTable.cpp
@@ -0,0 +1,267 @@
+/*
+ * 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 <cstdlib>
+
+#include <ZLStringUtil.h>
+#include <ZLLogger.h>
+
+#include "StyleSheetTable.h"
+
+bool StyleSheetTable::isEmpty() const {
+ return myControlMap.empty() && myPageBreakBeforeMap.empty() && myPageBreakAfterMap.empty();
+}
+
+void StyleSheetTable::addMap(const std::string &tag, const std::string &aClass, const AttributeMap &map) {
+ if ((!tag.empty() || !aClass.empty()) && !map.empty()) {
+ Key key(tag, aClass);
+ myControlMap[key] = createControl(map);
+ const std::vector<std::string> &pbb = values(map, "page-break-before");
+ if (!pbb.empty()) {
+ if ((pbb[0] == "always") ||
+ (pbb[0] == "left") ||
+ (pbb[0] == "right")) {
+ myPageBreakBeforeMap[key] = true;
+ } else if (pbb[0] == "avoid") {
+ myPageBreakBeforeMap[key] = false;
+ }
+ }
+ const std::vector<std::string> &pba = values(map, "page-break-after");
+ if (!pba.empty()) {
+ if ((pba[0] == "always") ||
+ (pba[0] == "left") ||
+ (pba[0] == "right")) {
+ myPageBreakAfterMap[key] = true;
+ } else if (pba[0] == "avoid") {
+ myPageBreakAfterMap[key] = false;
+ }
+ }
+ }
+}
+
+static bool parseLength(const std::string &toParse, short &size, ZLTextStyleEntry::SizeUnit &unit) {
+ if (ZLStringUtil::stringEndsWith(toParse, "%")) {
+ unit = ZLTextStyleEntry::SIZE_UNIT_PERCENT;
+ size = std::atoi(toParse.c_str());
+ return true;
+ } else if (ZLStringUtil::stringEndsWith(toParse, "em")) {
+ unit = ZLTextStyleEntry::SIZE_UNIT_EM_100;
+ size = (short)(100 * ZLStringUtil::stringToDouble(toParse, 0));
+ return true;
+ } else if (ZLStringUtil::stringEndsWith(toParse, "ex")) {
+ unit = ZLTextStyleEntry::SIZE_UNIT_EX_100;
+ size = (short)(100 * ZLStringUtil::stringToDouble(toParse, 0));
+ return true;
+ } else if (ZLStringUtil::stringEndsWith(toParse, "px")) {
+ unit = ZLTextStyleEntry::SIZE_UNIT_PIXEL;
+ size = std::atoi(toParse.c_str());
+ return true;
+ } else if (ZLStringUtil::stringEndsWith(toParse, "pt")) {
+ unit = ZLTextStyleEntry::SIZE_UNIT_POINT;
+ size = std::atoi(toParse.c_str());
+ return true;
+ }
+ return false;
+}
+
+void StyleSheetTable::setLength(ZLTextStyleEntry &entry, ZLTextStyleEntry::Feature featureId, const AttributeMap &map, const std::string &attributeName) {
+ StyleSheetTable::AttributeMap::const_iterator it = map.find(attributeName);
+ if (it == map.end()) {
+ return;
+ }
+ const std::vector<std::string> &values = it->second;
+ if (!values.empty() && !values[0].empty()) {
+ short size;
+ ZLTextStyleEntry::SizeUnit unit;
+ if (parseLength(values[0], size, unit)) {
+ entry.setLength(featureId, size, unit);
+ }
+ }
+}
+
+bool StyleSheetTable::doBreakBefore(const std::string &tag, const std::string &aClass) const {
+ std::map<Key,bool>::const_iterator it = myPageBreakBeforeMap.find(Key(tag, aClass));
+ if (it != myPageBreakBeforeMap.end()) {
+ return it->second;
+ }
+
+ it = myPageBreakBeforeMap.find(Key("", aClass));
+ if (it != myPageBreakBeforeMap.end()) {
+ return it->second;
+ }
+
+ it = myPageBreakBeforeMap.find(Key(tag, ""));
+ if (it != myPageBreakBeforeMap.end()) {
+ return it->second;
+ }
+
+ return false;
+}
+
+bool StyleSheetTable::doBreakAfter(const std::string &tag, const std::string &aClass) const {
+ std::map<Key,bool>::const_iterator it = myPageBreakAfterMap.find(Key(tag, aClass));
+ if (it != myPageBreakAfterMap.end()) {
+ return it->second;
+ }
+
+ it = myPageBreakAfterMap.find(Key("", aClass));
+ if (it != myPageBreakAfterMap.end()) {
+ return it->second;
+ }
+
+ it = myPageBreakAfterMap.find(Key(tag, ""));
+ if (it != myPageBreakAfterMap.end()) {
+ return it->second;
+ }
+
+ return false;
+}
+
+shared_ptr<ZLTextStyleEntry> StyleSheetTable::control(const std::string &tag, const std::string &aClass) const {
+ std::map<Key,shared_ptr<ZLTextStyleEntry> >::const_iterator it =
+ myControlMap.find(Key(tag, aClass));
+ return (it != myControlMap.end()) ? it->second : 0;
+}
+
+const std::vector<std::string> &StyleSheetTable::values(const AttributeMap &map, const std::string &name) {
+ const AttributeMap::const_iterator it = map.find(name);
+ if (it != map.end()) {
+ return it->second;
+ }
+ static const std::vector<std::string> emptyVector;
+ return emptyVector;
+}
+
+shared_ptr<ZLTextStyleEntry> StyleSheetTable::createControl(const AttributeMap &styles) {
+ shared_ptr<ZLTextStyleEntry> entry = new ZLTextStyleEntry(ZLTextStyleEntry::STYLE_CSS_ENTRY);
+
+ const std::vector<std::string> &alignment = values(styles, "text-align");
+ if (!alignment.empty()) {
+ if (alignment[0] == "justify") {
+ entry->setAlignmentType(ALIGN_JUSTIFY);
+ } else if (alignment[0] == "left") {
+ entry->setAlignmentType(ALIGN_LEFT);
+ } else if (alignment[0] == "right") {
+ entry->setAlignmentType(ALIGN_RIGHT);
+ } else if (alignment[0] == "center") {
+ entry->setAlignmentType(ALIGN_CENTER);
+ }
+ }
+
+ const std::vector<std::string> &deco = values(styles, "text-decoration");
+ for (std::vector<std::string>::const_iterator it = deco.begin(); it != deco.end(); ++it) {
+ if (*it == "underline") {
+ entry->setFontModifier(ZLTextStyleEntry::FONT_MODIFIER_UNDERLINED, true);
+ } else if (*it == "line-through") {
+ entry->setFontModifier(ZLTextStyleEntry::FONT_MODIFIER_STRIKEDTHROUGH, true);
+ } else if (*it == "none") {
+ entry->setFontModifier(ZLTextStyleEntry::FONT_MODIFIER_UNDERLINED, false);
+ entry->setFontModifier(ZLTextStyleEntry::FONT_MODIFIER_STRIKEDTHROUGH, false);
+ }
+ }
+
+ const std::vector<std::string> &bold = values(styles, "font-weight");
+ if (!bold.empty()) {
+ //ZLLogger::Instance().println(ZLLogger::DEFAULT_CLASS, "bold: " + bold[0]);
+ int num = -1;
+ if (bold[0] == "bold") {
+ num = 700;
+ } else if (bold[0] == "normal") {
+ num = 400;
+ } else if (bold[0] == "bolder") {
+ // TODO: implement
+ } else if (bold[0] == "lighter") {
+ // TODO: implement
+ } else {
+ num = ZLStringUtil::stringToInteger(bold[0], -1);
+ }
+ if (num != -1) {
+ entry->setFontModifier(ZLTextStyleEntry::FONT_MODIFIER_BOLD, num >= 600);
+ }
+ }
+
+ const std::vector<std::string> &italic = values(styles, "font-style");
+ if (!italic.empty()) {
+ entry->setFontModifier(ZLTextStyleEntry::FONT_MODIFIER_ITALIC, italic[0] == "italic");
+ }
+
+ const std::vector<std::string> &variant = values(styles, "font-variant");
+ if (!variant.empty()) {
+ entry->setFontModifier(ZLTextStyleEntry::FONT_MODIFIER_SMALLCAPS, variant[0] == "small-caps");
+ }
+
+ const std::vector<std::string> &fontFamily = values(styles, "font-family");
+ if (!fontFamily.empty() && !fontFamily[0].empty()) {
+ entry->setFontFamily(fontFamily[0]);
+ //ZLLogger::Instance().println(ZLLogger::DEFAULT_CLASS, "font family: " + fontFamily[0]);
+ }
+
+ const std::vector<std::string> &fontSize = values(styles, "font-size");
+ if (!fontSize.empty()) {
+ //TODO implement FONT_MODIFIER_INHERIT, SMALLER and LARGER support
+ bool doSetFontSize = true;
+ short size = 100;
+ ZLTextStyleEntry::SizeUnit unit = ZLTextStyleEntry::SIZE_UNIT_PERCENT;
+ if (fontSize[0] == "xx-small") {
+ size = 58;
+ } else if (fontSize[0] == "x-small") {
+ size = 69;
+ } else if (fontSize[0] == "small") {
+ size = 83;
+ } else if (fontSize[0] == "medium") {
+ size = 100;
+ } else if (fontSize[0] == "large") {
+ size = 120;
+ } else if (fontSize[0] == "x-large") {
+ size = 144;
+ } else if (fontSize[0] == "xx-large") {
+ size = 173;
+ } else if (fontSize[0] == "inherit") {
+ entry->setFontModifier(ZLTextStyleEntry::FONT_MODIFIER_INHERIT, true);
+ doSetFontSize = false;
+ } else if (fontSize[0] == "smaller") {
+ entry->setFontModifier(ZLTextStyleEntry::FONT_MODIFIER_SMALLER, true);
+ doSetFontSize = false;
+ } else if (fontSize[0] == "larger") {
+ entry->setFontModifier(ZLTextStyleEntry::FONT_MODIFIER_LARGER, true);
+ doSetFontSize = false;
+ } else if (!parseLength(fontSize[0], size, unit)) {
+ doSetFontSize = false;
+ }
+ if (doSetFontSize) {
+ entry->setLength(ZLTextStyleEntry::LENGTH_FONT_SIZE, size, unit);
+ }
+ }
+
+ setLength(*entry, ZLTextStyleEntry::LENGTH_LEFT_INDENT, styles, "margin-left");
+ setLength(*entry, ZLTextStyleEntry::LENGTH_RIGHT_INDENT, styles, "margin-right");
+ setLength(*entry, ZLTextStyleEntry::LENGTH_FIRST_LINE_INDENT_DELTA, styles, "text-indent");
+ setLength(*entry, ZLTextStyleEntry::LENGTH_SPACE_BEFORE, styles, "margin-top");
+ setLength(*entry, ZLTextStyleEntry::LENGTH_SPACE_BEFORE, styles, "padding-top");
+ setLength(*entry, ZLTextStyleEntry::LENGTH_SPACE_AFTER, styles, "margin-bottom");
+ setLength(*entry, ZLTextStyleEntry::LENGTH_SPACE_AFTER, styles, "padding-bottom");
+
+ return entry;
+}
+
+void StyleSheetTable::clear() {
+ myControlMap.clear();
+ myPageBreakBeforeMap.clear();
+ myPageBreakAfterMap.clear();
+}
diff --git a/reader/src/formats/css/StyleSheetTable.h b/reader/src/formats/css/StyleSheetTable.h
new file mode 100644
index 0000000..54236fb
--- /dev/null
+++ b/reader/src/formats/css/StyleSheetTable.h
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+#ifndef __STYLESHEETTABLE_H__
+#define __STYLESHEETTABLE_H__
+
+#include <string>
+#include <map>
+#include <vector>
+
+#include <shared_ptr.h>
+
+#include <ZLTextParagraph.h>
+#include <ZLTextStyleEntry.h>
+
+class StyleSheetTable {
+
+public:
+ typedef std::map<std::string,std::vector<std::string> > AttributeMap;
+ static shared_ptr<ZLTextStyleEntry> createControl(const AttributeMap &map);
+
+private:
+ void addMap(const std::string &tag, const std::string &aClass, const AttributeMap &map);
+
+ static void setLength(ZLTextStyleEntry &entry, ZLTextStyleEntry::Feature featureId, const AttributeMap &map, const std::string &attributeName);
+ static const std::vector<std::string> &values(const AttributeMap &map, const std::string &name);
+
+public:
+ bool isEmpty() const;
+ bool doBreakBefore(const std::string &tag, const std::string &aClass) const;
+ bool doBreakAfter(const std::string &tag, const std::string &aClass) const;
+ shared_ptr<ZLTextStyleEntry> control(const std::string &tag, const std::string &aClass) const;
+
+ void clear();
+
+private:
+ struct Key {
+ Key(const std::string &tag, const std::string &aClass);
+
+ const std::string TagName;
+ const std::string ClassName;
+
+ bool operator < (const Key &key) const;
+ };
+
+ std::map<Key,shared_ptr<ZLTextStyleEntry> > myControlMap;
+ std::map<Key,bool> myPageBreakBeforeMap;
+ std::map<Key,bool> myPageBreakAfterMap;
+
+friend class StyleSheetTableParser;
+};
+
+inline StyleSheetTable::Key::Key(const std::string &tag, const std::string &aClass) : TagName(tag), ClassName(aClass) {
+}
+
+inline bool StyleSheetTable::Key::operator < (const StyleSheetTable::Key &key) const {
+ return (TagName < key.TagName) || ((TagName == key.TagName) && (ClassName < key.ClassName));
+}
+
+#endif /* __STYLESHEETTABLE_H__ */