Respect "page-break-before" and "page-break-after" inline styles

This commit is contained in:
Slava Monich 2015-07-03 14:52:42 +03:00
parent fc3171abad
commit 74d70a9d3a
5 changed files with 59 additions and 26 deletions

View file

@ -32,10 +32,17 @@ void StyleSheetTableParser::storeData(const std::string &tagName, const std::str
myTable.addMap(tagName, className, map); myTable.addMap(tagName, className, map);
} }
shared_ptr<ZLTextStyleEntry> StyleSheetSingleStyleParser::parseString(const char *text) { 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(myMap);
bool value;
if (pageBreakBefore && StyleSheetTable::getPageBreakBefore(myMap, value)) {
*pageBreakBefore = value ? B3_TRUE : B3_FALSE;
}
if (pageBreakAfter && StyleSheetTable::getPageBreakAfter(myMap, value)) {
*pageBreakAfter = value ? B3_TRUE : B3_FALSE;
}
reset(); reset();
return control; return control;
} }

View file

@ -21,6 +21,7 @@
#define __STYLESHEETPARSER_H__ #define __STYLESHEETPARSER_H__
#include "StyleSheetTable.h" #include "StyleSheetTable.h"
#include "ZLBoolean3.h"
class ZLInputStream; class ZLInputStream;
@ -76,7 +77,7 @@ private:
class StyleSheetSingleStyleParser : public StyleSheetParser { class StyleSheetSingleStyleParser : public StyleSheetParser {
public: public:
shared_ptr<ZLTextStyleEntry> parseString(const char *text); shared_ptr<ZLTextStyleEntry> parseString(const char *text, ZLBoolean3* pageBreakBefore, ZLBoolean3* pageBreakAfter);
}; };
#endif /* __STYLESHEETPARSER_H__ */ #endif /* __STYLESHEETPARSER_H__ */

View file

@ -31,25 +31,12 @@ void StyleSheetTable::addMap(const std::string &tag, const std::string &aClass,
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); myControlMap[key] = createControl(map);
const std::vector<std::string> &pbb = values(map, "page-break-before"); bool value;
if (!pbb.empty()) { if (getPageBreakBefore(map, value)) {
if ((pbb[0] == "always") || myPageBreakBeforeMap[key] = value;
(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 (getPageBreakAfter(map, value)) {
if (!pba.empty()) { myPageBreakAfterMap[key] = value;
if ((pba[0] == "always") ||
(pba[0] == "left") ||
(pba[0] == "right")) {
myPageBreakAfterMap[key] = true;
} else if (pba[0] == "avoid") {
myPageBreakAfterMap[key] = false;
}
} }
} }
} }
@ -255,3 +242,35 @@ shared_ptr<ZLTextStyleEntry> StyleSheetTable::createControl(const AttributeMap &
return entry; return entry;
} }
bool StyleSheetTable::getPageBreakBefore(const AttributeMap &map, bool &value) {
const std::vector<std::string> &pbb = values(map, "page-break-before");
if (!pbb.empty()) {
if ((pbb[0] == "always") ||
(pbb[0] == "left") ||
(pbb[0] == "right")) {
value = true;
return true;
} else if (pbb[0] == "avoid") {
value = false;
return true;
}
}
return false;
}
bool StyleSheetTable::getPageBreakAfter(const AttributeMap &map, bool &value) {
const std::vector<std::string> &pba = values(map, "page-break-after");
if (!pba.empty()) {
if ((pba[0] == "always") ||
(pba[0] == "left") ||
(pba[0] == "right")) {
value = true;
return true;
} else if (pba[0] == "avoid") {
value = false;
return true;
}
}
return false;
}

View file

@ -33,6 +33,8 @@ 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(const AttributeMap &map);
static bool getPageBreakBefore(const AttributeMap &map, bool &value);
static bool getPageBreakAfter(const AttributeMap &map, bool &value);
private: private:
void addMap(const std::string &tag, const std::string &aClass, const AttributeMap &map); void addMap(const std::string &tag, const std::string &aClass, const AttributeMap &map);

View file

@ -526,10 +526,17 @@ void XHTMLReader::startElementHandler(const char *tag, const char **attributes)
const char *aClass = attributeValue(attributes, "class"); const char *aClass = attributeValue(attributes, "class");
const std::string sClass = (aClass != 0) ? aClass : ""; const std::string sClass = (aClass != 0) ? aClass : "";
if (myStyleSheetTable.doBreakBefore(sTag, sClass)) { shared_ptr<ZLTextStyleEntry> inlineStyle;
const char *style = attributeValue(attributes, "style");
ZLBoolean3 pageBreakBefore(B3_UNDEFINED), pageBreakAfter(B3_UNDEFINED);
if (style != 0) {
inlineStyle = myStyleParser.parseString(style, &pageBreakBefore, &pageBreakAfter);
}
if (pageBreakBefore == B3_TRUE || (pageBreakBefore == B3_UNDEFINED && myStyleSheetTable.doBreakBefore(sTag, sClass))) {
myModelReader.insertEndOfSectionParagraph(); myModelReader.insertEndOfSectionParagraph();
} }
myDoPageBreakAfterStack.push_back(myStyleSheetTable.doBreakAfter(sTag, sClass)); myDoPageBreakAfterStack.push_back(pageBreakAfter == B3_TRUE || (pageBreakAfter == B3_UNDEFINED && myStyleSheetTable.doBreakAfter(sTag, sClass)));
XHTMLTagAction *action = ourTagActions[sTag]; XHTMLTagAction *action = ourTagActions[sTag];
if (action != 0) { if (action != 0) {
@ -540,10 +547,7 @@ void XHTMLReader::startElementHandler(const char *tag, const char **attributes)
entry = addStyleEntry(entry, myStyleSheetTable.control(sTag, "")); entry = addStyleEntry(entry, myStyleSheetTable.control(sTag, ""));
entry = addStyleEntry(entry, myStyleSheetTable.control("", sClass)); entry = addStyleEntry(entry, myStyleSheetTable.control("", sClass));
entry = addStyleEntry(entry, myStyleSheetTable.control(sTag, sClass)); entry = addStyleEntry(entry, myStyleSheetTable.control(sTag, sClass));
const char *style = attributeValue(attributes, "style"); entry = addStyleEntry(entry, inlineStyle);
if (style != 0) {
entry = addStyleEntry(entry, myStyleParser.parseString(style));
}
if (!entry.isNull()) { if (!entry.isNull()) {
myModelReader.addControl(*entry); myModelReader.addControl(*entry);
myStyleEntryStack.push_back(entry); myStyleEntryStack.push_back(entry);