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);
}
shared_ptr<ZLTextStyleEntry> StyleSheetSingleStyleParser::parseString(const char *text) {
shared_ptr<ZLTextStyleEntry> StyleSheetSingleStyleParser::parseString(const char *text, ZLBoolean3 *pageBreakBefore, ZLBoolean3 *pageBreakAfter) {
myReadState = ATTRIBUTE_NAME;
parse(text, strlen(text), true);
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();
return control;
}

View file

@ -21,6 +21,7 @@
#define __STYLESHEETPARSER_H__
#include "StyleSheetTable.h"
#include "ZLBoolean3.h"
class ZLInputStream;
@ -76,7 +77,7 @@ private:
class StyleSheetSingleStyleParser : public StyleSheetParser {
public:
shared_ptr<ZLTextStyleEntry> parseString(const char *text);
shared_ptr<ZLTextStyleEntry> parseString(const char *text, ZLBoolean3* pageBreakBefore, ZLBoolean3* pageBreakAfter);
};
#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()) {
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;
}
bool value;
if (getPageBreakBefore(map, value)) {
myPageBreakBeforeMap[key] = 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")) {
myPageBreakAfterMap[key] = true;
} else if (pba[0] == "avoid") {
myPageBreakAfterMap[key] = false;
}
if (getPageBreakAfter(map, value)) {
myPageBreakAfterMap[key] = value;
}
}
}
@ -255,3 +242,35 @@ shared_ptr<ZLTextStyleEntry> StyleSheetTable::createControl(const AttributeMap &
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:
typedef std::map<std::string,std::vector<std::string> > AttributeMap;
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:
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 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();
}
myDoPageBreakAfterStack.push_back(myStyleSheetTable.doBreakAfter(sTag, sClass));
myDoPageBreakAfterStack.push_back(pageBreakAfter == B3_TRUE || (pageBreakAfter == B3_UNDEFINED && myStyleSheetTable.doBreakAfter(sTag, sClass)));
XHTMLTagAction *action = ourTagActions[sTag];
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("", sClass));
entry = addStyleEntry(entry, myStyleSheetTable.control(sTag, sClass));
const char *style = attributeValue(attributes, "style");
if (style != 0) {
entry = addStyleEntry(entry, myStyleParser.parseString(style));
}
entry = addStyleEntry(entry, inlineStyle);
if (!entry.isNull()) {
myModelReader.addControl(*entry);
myStyleEntryStack.push_back(entry);