Support multiple selectors per CSS rule
Also, added more length units for margins
This commit is contained in:
parent
eb5928a5ba
commit
c787512e99
4 changed files with 93 additions and 59 deletions
|
@ -35,7 +35,7 @@ void StyleSheetTableParser::storeData(const std::string &tagName, const std::str
|
||||||
shared_ptr<ZLTextStyleEntry> StyleSheetSingleStyleParser::parseString(const char *text, ZLBoolean3 *pageBreakBefore, ZLBoolean3 *pageBreakAfter) {
|
shared_ptr<ZLTextStyleEntry> StyleSheetSingleStyleParser::parseString(const char *text, ZLBoolean3 *pageBreakBefore, ZLBoolean3 *pageBreakAfter) {
|
||||||
myReadState = ATTRIBUTE_NAME;
|
myReadState = ATTRIBUTE_NAME;
|
||||||
parse(text, strlen(text), true);
|
parse(text, strlen(text), true);
|
||||||
shared_ptr<ZLTextStyleEntry> control = StyleSheetTable::createControl(myMap);
|
shared_ptr<ZLTextStyleEntry> control = StyleSheetTable::createControl(NULL, myMap);
|
||||||
bool value;
|
bool value;
|
||||||
if (pageBreakBefore && StyleSheetTable::getPageBreakBefore(myMap, value)) {
|
if (pageBreakBefore && StyleSheetTable::getPageBreakBefore(myMap, value)) {
|
||||||
*pageBreakBefore = value ? B3_TRUE : B3_FALSE;
|
*pageBreakBefore = value ? B3_TRUE : B3_FALSE;
|
||||||
|
@ -58,8 +58,7 @@ void StyleSheetParser::reset() {
|
||||||
myAttributeName.erase();
|
myAttributeName.erase();
|
||||||
myReadState = TAG_NAME;
|
myReadState = TAG_NAME;
|
||||||
myInsideComment = false;
|
myInsideComment = false;
|
||||||
myTagName.erase();
|
mySelectors.clear();
|
||||||
myClassName.erase();
|
|
||||||
myMap.clear();
|
myMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,11 +131,21 @@ void StyleSheetParser::processControl(const char control) {
|
||||||
break;
|
break;
|
||||||
case '}':
|
case '}':
|
||||||
if (myReadState != BROKEN) {
|
if (myReadState != BROKEN) {
|
||||||
storeData(myTagName, myClassName, myMap);
|
for (unsigned int i=0; i<mySelectors.size(); i++) {
|
||||||
|
std::string selector(mySelectors[i]);
|
||||||
|
std::string tag, klass;
|
||||||
|
const int index = selector.find('.');
|
||||||
|
if (index == -1) {
|
||||||
|
tag = selector;
|
||||||
|
} else {
|
||||||
|
tag = selector.substr(0, index);
|
||||||
|
klass = selector.substr(index + 1);
|
||||||
|
}
|
||||||
|
storeData(tag, klass, myMap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
myReadState = TAG_NAME;
|
myReadState = TAG_NAME;
|
||||||
myTagName.erase();
|
mySelectors.clear();
|
||||||
myClassName.erase();
|
|
||||||
myMap.clear();
|
myMap.clear();
|
||||||
break;
|
break;
|
||||||
case ';':
|
case ';':
|
||||||
|
@ -171,26 +180,16 @@ void StyleSheetParser::processWord(std::string &word) {
|
||||||
void StyleSheetParser::processWordWithoutComments(const std::string &word) {
|
void StyleSheetParser::processWordWithoutComments(const std::string &word) {
|
||||||
switch (myReadState) {
|
switch (myReadState) {
|
||||||
case TAG_NAME:
|
case TAG_NAME:
|
||||||
{
|
if (!word.empty()) {
|
||||||
int index = word.find('.');
|
const unsigned int len = word.length();
|
||||||
if (index == -1) {
|
if (word.at(len-1) == ',') {
|
||||||
if (myTagName.empty()) {
|
mySelectors.push_back(word.substr(0, len-1));
|
||||||
myTagName = word;
|
|
||||||
} else {
|
} else {
|
||||||
myTagName += ' ' + word;
|
mySelectors.push_back(word);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (myTagName.empty()) {
|
|
||||||
myTagName = word.substr(0, index);
|
|
||||||
myClassName = word.substr(index + 1);
|
|
||||||
} else {
|
|
||||||
myTagName += ' ' + word.substr(0, index);
|
|
||||||
myClassName += ' ' + word.substr(index + 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
myMap.clear();
|
myMap.clear();
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case ATTRIBUTE_NAME:
|
case ATTRIBUTE_NAME:
|
||||||
myAttributeName = word;
|
myAttributeName = word;
|
||||||
myMap[myAttributeName].clear();
|
myMap[myAttributeName].clear();
|
||||||
|
|
|
@ -55,8 +55,7 @@ private:
|
||||||
BROKEN,
|
BROKEN,
|
||||||
} myReadState;
|
} myReadState;
|
||||||
bool myInsideComment;
|
bool myInsideComment;
|
||||||
std::string myTagName;
|
std::vector<std::string> mySelectors;
|
||||||
std::string myClassName;
|
|
||||||
StyleSheetTable::AttributeMap myMap;
|
StyleSheetTable::AttributeMap myMap;
|
||||||
|
|
||||||
friend class StyleSheetSingleStyleParser;
|
friend class StyleSheetSingleStyleParser;
|
||||||
|
|
|
@ -30,7 +30,9 @@ bool StyleSheetTable::isEmpty() const {
|
||||||
void StyleSheetTable::addMap(const std::string &tag, const std::string &aClass, const AttributeMap &map) {
|
void StyleSheetTable::addMap(const std::string &tag, const std::string &aClass, const AttributeMap &map) {
|
||||||
if ((!tag.empty() || !aClass.empty()) && !map.empty()) {
|
if ((!tag.empty() || !aClass.empty()) && !map.empty()) {
|
||||||
Key key(tag, aClass);
|
Key key(tag, aClass);
|
||||||
myControlMap[key] = createControl(map);
|
// This will update the existing element if it already exists
|
||||||
|
// or create a new one if it wasn't there yet
|
||||||
|
myControlMap[key] = createControl(myControlMap[key], map);
|
||||||
bool value;
|
bool value;
|
||||||
if (getPageBreakBefore(map, value)) {
|
if (getPageBreakBefore(map, value)) {
|
||||||
myPageBreakBeforeMap[key] = value;
|
myPageBreakBeforeMap[key] = value;
|
||||||
|
@ -41,21 +43,34 @@ void StyleSheetTable::addMap(const std::string &tag, const std::string &aClass,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parseLength(const std::string &toParse, short &size, ZLTextStyleEntry::SizeUnit &unit) {
|
static bool parseLength(const std::string &toParse, short &size, ZLTextStyleEntry::SizeUnit &unit) {
|
||||||
|
if (!toParse.empty()) {
|
||||||
if (ZLStringUtil::stringEndsWith(toParse, "%")) {
|
if (ZLStringUtil::stringEndsWith(toParse, "%")) {
|
||||||
unit = ZLTextStyleEntry::SIZE_UNIT_PERCENT;
|
unit = ZLTextStyleEntry::SIZE_UNIT_PERCENT;
|
||||||
size = atoi(toParse.c_str());
|
size = atoi(toParse.c_str());
|
||||||
|
return true;
|
||||||
} else if (ZLStringUtil::stringEndsWith(toParse, "em")) {
|
} else if (ZLStringUtil::stringEndsWith(toParse, "em")) {
|
||||||
unit = ZLTextStyleEntry::SIZE_UNIT_EM_100;
|
unit = ZLTextStyleEntry::SIZE_UNIT_EM_100;
|
||||||
size = (short)(100 * ZLStringUtil::stringToDouble(toParse, 0));
|
size = (short)(100 * ZLStringUtil::stringToDouble(toParse, 0));
|
||||||
|
return true;
|
||||||
} else if (ZLStringUtil::stringEndsWith(toParse, "ex")) {
|
} else if (ZLStringUtil::stringEndsWith(toParse, "ex")) {
|
||||||
unit = ZLTextStyleEntry::SIZE_UNIT_EX_100;
|
unit = ZLTextStyleEntry::SIZE_UNIT_EX_100;
|
||||||
size = (short)(100 * ZLStringUtil::stringToDouble(toParse, 0));
|
size = (short)(100 * ZLStringUtil::stringToDouble(toParse, 0));
|
||||||
} else {
|
return true;
|
||||||
|
} else if (ZLStringUtil::stringEndsWith(toParse, "px") ||
|
||||||
|
ZLStringUtil::stringEndsWith(toParse, "pt") ||
|
||||||
|
ZLStringUtil::stringEndsWith(toParse, "pc")) {
|
||||||
unit = ZLTextStyleEntry::SIZE_UNIT_PIXEL;
|
unit = ZLTextStyleEntry::SIZE_UNIT_PIXEL;
|
||||||
size = atoi(toParse.c_str());
|
size = atoi(toParse.c_str());
|
||||||
|
return true;
|
||||||
|
} else if (toParse == "0") {
|
||||||
|
unit = ZLTextStyleEntry::SIZE_UNIT_PIXEL;
|
||||||
|
size = 0;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void StyleSheetTable::setLength(ZLTextStyleEntry &entry, ZLTextStyleEntry::Length name, const AttributeMap &map, const std::string &attributeName) {
|
void StyleSheetTable::setLength(ZLTextStyleEntry &entry, ZLTextStyleEntry::Length name, const AttributeMap &map, const std::string &attributeName) {
|
||||||
StyleSheetTable::AttributeMap::const_iterator it = map.find(attributeName);
|
StyleSheetTable::AttributeMap::const_iterator it = map.find(attributeName);
|
||||||
|
@ -68,10 +83,9 @@ void StyleSheetTable::setLength(ZLTextStyleEntry &entry, ZLTextStyleEntry::Lengt
|
||||||
}
|
}
|
||||||
|
|
||||||
void StyleSheetTable::setLength(ZLTextStyleEntry &entry, ZLTextStyleEntry::Length name, const std::string &value) {
|
void StyleSheetTable::setLength(ZLTextStyleEntry &entry, ZLTextStyleEntry::Length name, const std::string &value) {
|
||||||
if (!value.empty()) {
|
|
||||||
short size;
|
short size;
|
||||||
ZLTextStyleEntry::SizeUnit unit;
|
ZLTextStyleEntry::SizeUnit unit;
|
||||||
parseLength(value, size, unit);
|
if (parseLength(value, size, unit)) {
|
||||||
entry.setLength(name, size, unit);
|
entry.setLength(name, size, unit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,8 +143,10 @@ const std::vector<std::string> &StyleSheetTable::values(const AttributeMap &map,
|
||||||
return emptyVector;
|
return emptyVector;
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<ZLTextStyleEntry> StyleSheetTable::createControl(const AttributeMap &styles) {
|
shared_ptr<ZLTextStyleEntry> StyleSheetTable::createControl(shared_ptr<ZLTextStyleEntry> entry, const AttributeMap &styles) {
|
||||||
shared_ptr<ZLTextStyleEntry> entry = new ZLTextStyleEntry();
|
if (entry.isNull()) {
|
||||||
|
entry = new ZLTextStyleEntry();
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<std::string> &alignment = values(styles, "text-align");
|
const std::vector<std::string> &alignment = values(styles, "text-align");
|
||||||
if (!alignment.empty()) {
|
if (!alignment.empty()) {
|
||||||
|
@ -181,6 +197,8 @@ shared_ptr<ZLTextStyleEntry> StyleSheetTable::createControl(const AttributeMap &
|
||||||
entry->setFontFamily(fontFamily[0]);
|
entry->setFontFamily(fontFamily[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
short size;
|
||||||
|
ZLTextStyleEntry::SizeUnit unit;
|
||||||
const std::vector<std::string> &fontSize = values(styles, "font-size");
|
const std::vector<std::string> &fontSize = values(styles, "font-size");
|
||||||
if (!fontSize.empty()) {
|
if (!fontSize.empty()) {
|
||||||
std::string value = fontSize[0];
|
std::string value = fontSize[0];
|
||||||
|
@ -198,11 +216,21 @@ shared_ptr<ZLTextStyleEntry> StyleSheetTable::createControl(const AttributeMap &
|
||||||
entry->setFontSizeMag(2);
|
entry->setFontSizeMag(2);
|
||||||
} else if (value == "xx-large") {
|
} else if (value == "xx-large") {
|
||||||
entry->setFontSizeMag(3);
|
entry->setFontSizeMag(3);
|
||||||
} else if (value.size() > 1 && value[value.size()-1] == '%') {
|
} else {
|
||||||
value.erase(value.size()-1, 1);
|
if (parseLength(value, size, unit)) {
|
||||||
int percent = atoi(value.c_str());
|
switch (unit) {
|
||||||
if (percent > 0) {
|
case ZLTextStyleEntry::SIZE_UNIT_PIXEL:
|
||||||
entry->setFontSizeMag((percent - 100)/20);
|
// What to do with pixels?
|
||||||
|
break;
|
||||||
|
case ZLTextStyleEntry::SIZE_UNIT_EM_100:
|
||||||
|
case ZLTextStyleEntry::SIZE_UNIT_EX_100:
|
||||||
|
case ZLTextStyleEntry::SIZE_UNIT_PERCENT:
|
||||||
|
entry->setFontSizeMag(
|
||||||
|
(size < 100 && size > 80) ? -1 :
|
||||||
|
(size > 100 && size < 120) ? 1 :
|
||||||
|
(size - 100)/20);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -214,21 +242,29 @@ shared_ptr<ZLTextStyleEntry> StyleSheetTable::createControl(const AttributeMap &
|
||||||
}
|
}
|
||||||
switch (margins.size()) {
|
switch (margins.size()) {
|
||||||
case 1:
|
case 1:
|
||||||
setLength(*entry, ZLTextStyleEntry::LENGTH_SPACE_BEFORE, margins[0]);
|
if (parseLength(margins[0], size, unit)) {
|
||||||
setLength(*entry, ZLTextStyleEntry::LENGTH_RIGHT_INDENT, margins[0]);
|
entry->setLength(ZLTextStyleEntry::LENGTH_SPACE_BEFORE, size, unit);
|
||||||
setLength(*entry, ZLTextStyleEntry::LENGTH_SPACE_AFTER, margins[0]);
|
entry->setLength(ZLTextStyleEntry::LENGTH_RIGHT_INDENT, size, unit);
|
||||||
setLength(*entry, ZLTextStyleEntry::LENGTH_LEFT_INDENT, margins[0]);
|
entry->setLength(ZLTextStyleEntry::LENGTH_SPACE_AFTER, size, unit);
|
||||||
|
entry->setLength(ZLTextStyleEntry::LENGTH_LEFT_INDENT, size, unit);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
setLength(*entry, ZLTextStyleEntry::LENGTH_SPACE_BEFORE, margins[0]);
|
if (parseLength(margins[0], size, unit)) {
|
||||||
setLength(*entry, ZLTextStyleEntry::LENGTH_SPACE_AFTER, margins[0]);
|
entry->setLength(ZLTextStyleEntry::LENGTH_SPACE_BEFORE, size, unit);
|
||||||
setLength(*entry, ZLTextStyleEntry::LENGTH_RIGHT_INDENT, margins[1]);
|
entry->setLength(ZLTextStyleEntry::LENGTH_SPACE_AFTER, size, unit);
|
||||||
setLength(*entry, ZLTextStyleEntry::LENGTH_LEFT_INDENT, margins[1]);
|
}
|
||||||
|
if (parseLength(margins[1], size, unit)) {
|
||||||
|
entry->setLength(ZLTextStyleEntry::LENGTH_RIGHT_INDENT, size, unit);
|
||||||
|
entry->setLength(ZLTextStyleEntry::LENGTH_LEFT_INDENT, size, unit);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
setLength(*entry, ZLTextStyleEntry::LENGTH_SPACE_BEFORE, margins[0]);
|
setLength(*entry, ZLTextStyleEntry::LENGTH_SPACE_BEFORE, margins[0]);
|
||||||
setLength(*entry, ZLTextStyleEntry::LENGTH_RIGHT_INDENT, margins[1]);
|
if (parseLength(margins[1], size, unit)) {
|
||||||
setLength(*entry, ZLTextStyleEntry::LENGTH_LEFT_INDENT, margins[1]);
|
entry->setLength(ZLTextStyleEntry::LENGTH_RIGHT_INDENT, size, unit);
|
||||||
|
entry->setLength(ZLTextStyleEntry::LENGTH_LEFT_INDENT, size, unit);
|
||||||
|
}
|
||||||
setLength(*entry, ZLTextStyleEntry::LENGTH_SPACE_AFTER, margins[2]);
|
setLength(*entry, ZLTextStyleEntry::LENGTH_SPACE_AFTER, margins[2]);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
|
|
|
@ -32,7 +32,7 @@ class StyleSheetTable {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::map<std::string,std::vector<std::string> > AttributeMap;
|
typedef std::map<std::string,std::vector<std::string> > AttributeMap;
|
||||||
static shared_ptr<ZLTextStyleEntry> createControl(const AttributeMap &map);
|
static shared_ptr<ZLTextStyleEntry> createControl(shared_ptr<ZLTextStyleEntry> entry, const AttributeMap &map);
|
||||||
static bool getPageBreakBefore(const AttributeMap &map, bool &value);
|
static bool getPageBreakBefore(const AttributeMap &map, bool &value);
|
||||||
static bool getPageBreakAfter(const AttributeMap &map, bool &value);
|
static bool getPageBreakAfter(const AttributeMap &map, bool &value);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue