diff options
author | Mark Hung <marklh9@gmail.com> | 2018-03-28 07:26:08 +0800 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2018-04-04 09:03:22 +0200 |
commit | 75c166d058717a7edd26273f50a86fe5f2cc7fb0 (patch) | |
tree | be50a490d470c3d5b7296b8af307d6165d96789d /external | |
parent | 791fb3979df47a9fe21a1fbb9debbc955f3e035b (diff) |
tdf#115623: patch libepubgen to support writing-mode.
Backport three patches from libepubgen master branch to support
exporting style:writing-mode as body CSS styles.
1. Support writing-mode for reflowable layout method.
https://sourceforge.net/p/libepubgen/code/ci/9a284081eea4a95235a6d6a6a50cbe3f7ad323ba/
2. Always keep page properties when splitting.
https://sourceforge.net/p/libepubgen/code/ci/0318031b9094b9180d1d391d0ca31a782b016e99/
3. Ensure page properties in the page span work
https://sourceforge.net/p/libepubgen/code/ci/1f602fcaa74fc9dbc6457019d11c602ff4040a4e/
Change-Id: I9033cb1f5fcbfedb423308fb29b9bd4d6d7d7a43
Reviewed-on: https://gerrit.libreoffice.org/52083
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
Diffstat (limited to 'external')
4 files changed, 676 insertions, 0 deletions
diff --git a/external/libepubgen/0001-Support-writing-mode-for-reflowable-layout-method.patch.1 b/external/libepubgen/0001-Support-writing-mode-for-reflowable-layout-method.patch.1 new file mode 100644 index 000000000000..d3799d1d6e8b --- /dev/null +++ b/external/libepubgen/0001-Support-writing-mode-for-reflowable-layout-method.patch.1 @@ -0,0 +1,264 @@ +From 9b1c3fd42fa256b58dfb4dedd070954406c25596 Mon Sep 17 00:00:00 2001 +From: Mark Hung <marklh9@gmail.com> +Date: Mon, 19 Mar 2018 20:36:11 +0800 +Subject: [PATCH 1/3] Support writing-mode for reflowable layout method. + +Convert style:writing-mode in page properties to css style for +HTML body element. The class names of body elements will be like +"body0". +--- + src/lib/EPUBGenerator.cpp | 1 + + src/lib/EPUBHTMLGenerator.cpp | 18 +++++++++++++-- + src/lib/EPUBSpanStyleManager.cpp | 45 ++++++++++++++++++++++++++++++++------ + src/lib/EPUBSpanStyleManager.h | 14 ++++++++---- + src/test/EPUBTextGeneratorTest.cpp | 25 +++++++++++++++++++++ + 5 files changed, 90 insertions(+), 13 deletions(-) + +diff --git a/src/lib/EPUBGenerator.cpp b/src/lib/EPUBGenerator.cpp +index 83f3f40..56db4dc 100644 +--- a/src/lib/EPUBGenerator.cpp ++++ b/src/lib/EPUBGenerator.cpp +@@ -122,6 +122,7 @@ void EPUBGenerator::startNewHtmlFile() + if (m_layoutMethod == EPUB_LAYOUT_METHOD_FIXED && m_currentHtml) + m_currentHtml->getPageProperties(pageProperties); + m_currentHtml = m_htmlManager.create(m_imageManager, m_fontManager, m_listStyleManager, m_paragraphStyleManager, m_spanStyleManager, m_tableStyleManager, m_stylesheetPath, m_stylesMethod, m_layoutMethod, m_version); ++ + if (m_layoutMethod == EPUB_LAYOUT_METHOD_FIXED) + m_currentHtml->setPageProperties(pageProperties); + +diff --git a/src/lib/EPUBHTMLGenerator.cpp b/src/lib/EPUBHTMLGenerator.cpp +index 342213e..d5cc0d2 100644 +--- a/src/lib/EPUBHTMLGenerator.cpp ++++ b/src/lib/EPUBHTMLGenerator.cpp +@@ -600,6 +600,20 @@ void EPUBHTMLGenerator::endDocument() + RVNGPropertyList bodyAttrs; + if (m_impl->m_version >= 30) + bodyAttrs.insert("xmlns:epub", "http://www.idpf.org/2007/ops"); ++ ++ if (m_impl->m_actualPageProperties["style:writing-mode"]) ++ { ++ switch (m_impl->m_stylesMethod) ++ { ++ case EPUB_STYLES_METHOD_CSS: ++ bodyAttrs.insert("class", m_impl->m_spanManager.getClass(m_impl->m_actualPageProperties, true).c_str()); ++ break; ++ case EPUB_STYLES_METHOD_INLINE: ++ bodyAttrs.insert("style", m_impl->m_spanManager.getStyle(m_impl->m_actualPageProperties, true).c_str()); ++ break; ++ } ++ } ++ + m_impl->m_document.openElement("body", bodyAttrs); + m_impl->flushUnsent(m_impl->m_document); + m_impl->m_document.closeElement("body"); +@@ -710,10 +724,10 @@ void EPUBHTMLGenerator::openSpan(const RVNGPropertyList &propList) + switch (m_impl->m_stylesMethod) + { + case EPUB_STYLES_METHOD_CSS: +- attrs.insert("class", m_impl->m_spanManager.getClass(propList).c_str()); ++ attrs.insert("class", m_impl->m_spanManager.getClass(propList, false).c_str()); + break; + case EPUB_STYLES_METHOD_INLINE: +- attrs.insert("style", m_impl->m_spanManager.getStyle(propList).c_str()); ++ attrs.insert("style", m_impl->m_spanManager.getStyle(propList, false).c_str()); + break; + } + m_impl->output(false).openElement("span", attrs); +diff --git a/src/lib/EPUBSpanStyleManager.cpp b/src/lib/EPUBSpanStyleManager.cpp +index e25fa26..ded34ba 100644 +--- a/src/lib/EPUBSpanStyleManager.cpp ++++ b/src/lib/EPUBSpanStyleManager.cpp +@@ -21,7 +21,7 @@ namespace libepubgen + + using librevenge::RVNGPropertyList; + +-std::string EPUBSpanStyleManager::getClass(RVNGPropertyList const &pList) ++std::string EPUBSpanStyleManager::getClass(RVNGPropertyList const &pList, bool bIsBody) + { + if (pList["librevenge:span-id"]) + { +@@ -31,20 +31,31 @@ std::string EPUBSpanStyleManager::getClass(RVNGPropertyList const &pList) + } + + EPUBCSSProperties content; +- extractProperties(pList, content); ++ if (bIsBody) ++ extractBodyProperties(pList, content); ++ else ++ extractSpanProperties(pList, content); ++ + ContentNameMap_t::const_iterator it = m_contentNameMap.find(content); + if (it != m_contentNameMap.end()) + return it->second; + std::stringstream s; +- s << "span" << m_contentNameMap.size(); ++ if (bIsBody) ++ s << "body" << (m_numberBody.next() - 1); ++ else ++ s << "span" << (m_numberSpan.next() - 1); ++ + m_contentNameMap[content]=s.str(); + return s.str(); + } + +-std::string EPUBSpanStyleManager::getStyle(RVNGPropertyList const &pList) ++std::string EPUBSpanStyleManager::getStyle(RVNGPropertyList const &pList, bool bIsBody) + { + EPUBCSSProperties content; +- extractProperties(pList, content); ++ if (bIsBody) ++ extractBodyProperties(pList, content); ++ else ++ extractSpanProperties(pList, content); + + std::stringstream s; + for (const auto &property : content) +@@ -62,7 +73,7 @@ void EPUBSpanStyleManager::defineSpan(RVNGPropertyList const &propList) + int id=propList["librevenge:span-id"]->getInt(); + RVNGPropertyList pList(propList); + pList.remove("librevenge:span-id"); +- m_idNameMap[id]=getClass(pList); ++ m_idNameMap[id]=getClass(pList, false); + } + + void EPUBSpanStyleManager::send(EPUBCSSSink &out) +@@ -75,7 +86,7 @@ void EPUBSpanStyleManager::send(EPUBCSSSink &out) + } + } + +-void EPUBSpanStyleManager::extractProperties(RVNGPropertyList const &pList, EPUBCSSProperties &cssProps) const ++void EPUBSpanStyleManager::extractSpanProperties(RVNGPropertyList const &pList, EPUBCSSProperties &cssProps) const + { + if (pList["fo:background-color"]) + cssProps["background-color"] = pList["fo:background-color"]->getStr().cstr(); +@@ -227,6 +238,26 @@ void EPUBSpanStyleManager::extractTextPosition(char const *value, EPUBCSSPropert + } + } + ++void EPUBSpanStyleManager::extractBodyProperties(RVNGPropertyList const &pList, EPUBCSSProperties &cssProps) const ++{ ++ if (pList["style:writing-mode"]) ++ { ++ std::string mode = pList["style:writing-mode"]->getStr().cstr(); ++ if (mode == "tb-rl" || mode == "tb") ++ mode = "vertical-rl"; ++ else if (mode == "tb-lr") ++ mode = "vertical-lr"; ++ else // For the rest: lr, lr-tb, rl, rl-tb ++ { ++ mode = "horizontal-tb"; ++ cssProps["direction"] = (mode == "rl-tb" || mode == "rl")?"rtl":"ltr"; ++ } ++ ++ cssProps["-epub-writing-mode"] = mode; ++ cssProps["-webkit-writing-mode"] = mode; ++ cssProps["writing-mode"] = mode; ++ } ++} + } + + /* vim:set shiftwidth=2 softtabstop=2 expandtab: */ +diff --git a/src/lib/EPUBSpanStyleManager.h b/src/lib/EPUBSpanStyleManager.h +index ec9d0e5..6c18392 100644 +--- a/src/lib/EPUBSpanStyleManager.h ++++ b/src/lib/EPUBSpanStyleManager.h +@@ -19,6 +19,7 @@ + #include <librevenge/librevenge.h> + + #include "EPUBCSSProperties.h" ++#include "EPUBCounter.h" + + namespace libepubgen + { +@@ -32,7 +33,7 @@ class EPUBSpanStyleManager + + public: + //! constructor +- EPUBSpanStyleManager() : m_contentNameMap(), m_idNameMap() ++ EPUBSpanStyleManager() : m_contentNameMap(), m_idNameMap(), m_numberSpan(), m_numberBody() + { + } + //! destructor +@@ -42,14 +43,16 @@ public: + //! define a span style + void defineSpan(librevenge::RVNGPropertyList const &pList); + //! returns the class name corresponding to a propertylist +- std::string getClass(librevenge::RVNGPropertyList const &pList); ++ std::string getClass(librevenge::RVNGPropertyList const &pList, bool bIsBody); + //! returns the style string corresponding to a propertylist +- std::string getStyle(librevenge::RVNGPropertyList const &pList); ++ std::string getStyle(librevenge::RVNGPropertyList const &pList, bool bIsBody); + //! send the data to the sink + void send(EPUBCSSSink &out); + protected: + //! convert a property list into a CSS property map +- void extractProperties(librevenge::RVNGPropertyList const &pList, EPUBCSSProperties &cssProps) const; ++ void extractSpanProperties(librevenge::RVNGPropertyList const &pList, EPUBCSSProperties &cssProps) const; ++ //! Extract body styles from a property list into a CSS property map ++ void extractBodyProperties(librevenge::RVNGPropertyList const &pList, EPUBCSSProperties &cssProps) const; + //! add data corresponding to a text position into the map + void extractTextPosition(char const *value, EPUBCSSProperties &cssProps) const; + //! add data corresponding to the line decoration into the map +@@ -59,6 +62,9 @@ protected: + //! a map id -> name + std::map<int, std::string> m_idNameMap; + ++ EPUBCounter m_numberSpan; ++ EPUBCounter m_numberBody; ++ + private: + EPUBSpanStyleManager(EPUBSpanStyleManager const &orig); + EPUBSpanStyleManager operator=(EPUBSpanStyleManager const &orig); +diff --git a/src/test/EPUBTextGeneratorTest.cpp b/src/test/EPUBTextGeneratorTest.cpp +index ddf0c90..cf5e35f 100644 +--- a/src/test/EPUBTextGeneratorTest.cpp ++++ b/src/test/EPUBTextGeneratorTest.cpp +@@ -235,6 +235,7 @@ private: + CPPUNIT_TEST(testFixedLayoutSpine); + CPPUNIT_TEST(testPageBreak); + CPPUNIT_TEST(testPageBreakImage); ++ CPPUNIT_TEST(testWritingMode); + CPPUNIT_TEST_SUITE_END(); + + private: +@@ -274,6 +275,7 @@ private: + void testFixedLayoutSpine(); + void testPageBreak(); + void testPageBreakImage(); ++ void testWritingMode(); + + /// Asserts that exactly one xpath exists in buffer, and its content equals content. + void assertXPathContent(xmlBufferPtr buffer, const std::string &xpath, const std::string &content); +@@ -1350,6 +1352,29 @@ void EPUBTextGeneratorTest::testPageBreakImage() + CPPUNIT_ASSERT(package.m_streams.find("OEBPS/sections/section0002.xhtml") != package.m_streams.end()); + } + ++void EPUBTextGeneratorTest::testWritingMode() ++{ ++ StringEPUBPackage package; ++ libepubgen::EPUBTextGenerator generator(&package); ++ generator.setOption(libepubgen::EPUB_GENERATOR_OPTION_SPLIT, libepubgen::EPUB_SPLIT_METHOD_PAGE_BREAK); ++ generator.startDocument(librevenge::RVNGPropertyList()); ++ ++ { ++ librevenge::RVNGPropertyList page; ++ page.insert("style:writing-mode", "tb"); ++ generator.openPageSpan(page); ++ ++ librevenge::RVNGPropertyList para; ++ generator.openParagraph(para); ++ generator.insertText("Para1"); ++ generator.closeParagraph(); ++ generator.closePageSpan(); ++ } ++ generator.endDocument(); ++ assertCss(package.m_cssStreams["OEBPS/styles/stylesheet.css"], ".body0", "writing-mode: vertical-rl", true); ++ assertXPath(package.m_streams["OEBPS/sections/section0001.xhtml"], "//xhtml:body", "class", "body0"); ++} ++ + CPPUNIT_TEST_SUITE_REGISTRATION(EPUBTextGeneratorTest); + + } +-- +2.14.1 + diff --git a/external/libepubgen/0002-Always-keep-page-properties-when-splitting-the-HTML-.patch.1 b/external/libepubgen/0002-Always-keep-page-properties-when-splitting-the-HTML-.patch.1 new file mode 100644 index 000000000000..9b26c279fa5c --- /dev/null +++ b/external/libepubgen/0002-Always-keep-page-properties-when-splitting-the-HTML-.patch.1 @@ -0,0 +1,181 @@ +From c3bd3bee2f6e01f0b5f5a8fb376ce175573a8e96 Mon Sep 17 00:00:00 2001 +From: Mark Hung <marklh9@gmail.com> +Date: Sat, 24 Mar 2018 12:50:12 +0800 +Subject: [PATCH 2/3] Always keep page properties when splitting the HTML file. + +Those page properties shall be changed only via openPageSpan. +It was kept only when the layout out method is EPUB_LAYOUT_METHOD_FIXED +before. +--- + src/lib/EPUBGenerator.cpp | 9 ++-- + src/test/EPUBTextGeneratorTest.cpp | 98 ++++++++++++++++++++++++++++++++++++-- + 2 files changed, 99 insertions(+), 8 deletions(-) + +diff --git a/src/lib/EPUBGenerator.cpp b/src/lib/EPUBGenerator.cpp +index 56db4dc..110667f 100644 +--- a/src/lib/EPUBGenerator.cpp ++++ b/src/lib/EPUBGenerator.cpp +@@ -110,21 +110,20 @@ void EPUBGenerator::setDocumentMetaData(const RVNGPropertyList &props) + void EPUBGenerator::startNewHtmlFile() + { + // close the current HTML file ++ librevenge::RVNGPropertyList pageProperties; + if (bool(m_currentHtml)) + { + endHtmlFile(); + m_currentHtml->endDocument(); ++ m_currentHtml->getPageProperties(pageProperties); + } + + m_splitGuard.onSplit(); + +- librevenge::RVNGPropertyList pageProperties; +- if (m_layoutMethod == EPUB_LAYOUT_METHOD_FIXED && m_currentHtml) +- m_currentHtml->getPageProperties(pageProperties); + m_currentHtml = m_htmlManager.create(m_imageManager, m_fontManager, m_listStyleManager, m_paragraphStyleManager, m_spanStyleManager, m_tableStyleManager, m_stylesheetPath, m_stylesMethod, m_layoutMethod, m_version); + +- if (m_layoutMethod == EPUB_LAYOUT_METHOD_FIXED) +- m_currentHtml->setPageProperties(pageProperties); ++ // Splitted html file should keep the same page property. ++ m_currentHtml->setPageProperties(pageProperties); + + // restore state in the new file + m_currentHtml->startDocument(m_documentProps); +diff --git a/src/test/EPUBTextGeneratorTest.cpp b/src/test/EPUBTextGeneratorTest.cpp +index cf5e35f..0946408 100644 +--- a/src/test/EPUBTextGeneratorTest.cpp ++++ b/src/test/EPUBTextGeneratorTest.cpp +@@ -235,7 +235,10 @@ private: + CPPUNIT_TEST(testFixedLayoutSpine); + CPPUNIT_TEST(testPageBreak); + CPPUNIT_TEST(testPageBreakImage); +- CPPUNIT_TEST(testWritingMode); ++ CPPUNIT_TEST(testPageSpanProperties); ++ CPPUNIT_TEST(testSplitOnPageBreakInPageSpan); ++ CPPUNIT_TEST(testSplitOnHeadingInPageSpan); ++ CPPUNIT_TEST(testSplitOnSizeInPageSpan); + CPPUNIT_TEST_SUITE_END(); + + private: +@@ -275,7 +278,10 @@ private: + void testFixedLayoutSpine(); + void testPageBreak(); + void testPageBreakImage(); +- void testWritingMode(); ++ void testPageSpanProperties(); ++ void testSplitOnPageBreakInPageSpan(); ++ void testSplitOnHeadingInPageSpan(); ++ void testSplitOnSizeInPageSpan(); + + /// Asserts that exactly one xpath exists in buffer, and its content equals content. + void assertXPathContent(xmlBufferPtr buffer, const std::string &xpath, const std::string &content); +@@ -1352,7 +1358,7 @@ void EPUBTextGeneratorTest::testPageBreakImage() + CPPUNIT_ASSERT(package.m_streams.find("OEBPS/sections/section0002.xhtml") != package.m_streams.end()); + } + +-void EPUBTextGeneratorTest::testWritingMode() ++void EPUBTextGeneratorTest::testPageSpanProperties() + { + StringEPUBPackage package; + libepubgen::EPUBTextGenerator generator(&package); +@@ -1368,11 +1374,97 @@ void EPUBTextGeneratorTest::testWritingMode() + generator.openParagraph(para); + generator.insertText("Para1"); + generator.closeParagraph(); ++ } ++ generator.endDocument(); ++ assertCss(package.m_cssStreams["OEBPS/styles/stylesheet.css"], ".body0", "writing-mode: vertical-rl", true); ++ assertXPath(package.m_streams["OEBPS/sections/section0001.xhtml"], "//xhtml:body", "class", "body0"); ++} ++ ++void EPUBTextGeneratorTest::testSplitOnPageBreakInPageSpan() ++{ ++ StringEPUBPackage package; ++ libepubgen::EPUBTextGenerator generator(&package); ++ generator.setOption(libepubgen::EPUB_GENERATOR_OPTION_SPLIT, libepubgen::EPUB_SPLIT_METHOD_PAGE_BREAK); ++ generator.startDocument(librevenge::RVNGPropertyList()); ++ ++ { ++ librevenge::RVNGPropertyList page; ++ page.insert("style:writing-mode", "tb"); ++ generator.openPageSpan(page); ++ ++ librevenge::RVNGPropertyList para; ++ generator.openParagraph(para); ++ generator.insertText("Para1"); ++ generator.closeParagraph(); ++ // Splitting a new html file inside the page span, the writing-mode shall not change. ++ para.insert("fo:break-before", "page"); ++ generator.openParagraph(para); ++ generator.insertText("Para2"); ++ generator.closeParagraph(); ++ generator.closePageSpan(); ++ } ++ generator.endDocument(); ++ assertCss(package.m_cssStreams["OEBPS/styles/stylesheet.css"], ".body0", "writing-mode: vertical-rl", true); ++ assertXPath(package.m_streams["OEBPS/sections/section0001.xhtml"], "//xhtml:body", "class", "body0"); ++ assertXPath(package.m_streams["OEBPS/sections/section0002.xhtml"], "//xhtml:body", "class", "body0"); ++} ++ ++void EPUBTextGeneratorTest::testSplitOnHeadingInPageSpan() ++{ ++ StringEPUBPackage package; ++ libepubgen::EPUBTextGenerator generator(&package); ++ generator.setOption(libepubgen::EPUB_GENERATOR_OPTION_SPLIT, libepubgen::EPUB_SPLIT_METHOD_HEADING); ++ generator.startDocument(librevenge::RVNGPropertyList()); ++ ++ { ++ librevenge::RVNGPropertyList page; ++ page.insert("style:writing-mode", "tb"); ++ generator.openPageSpan(page); ++ ++ librevenge::RVNGPropertyList para; ++ para.insert("text:outline-level", "1"); ++ generator.openParagraph(para); ++ generator.insertText("Chapter1"); ++ generator.closeParagraph(); ++ // Splitting a new html file inside the page span, the writing-mode shall not change. ++ generator.openParagraph(para); ++ generator.insertText("Chapter2"); ++ generator.closeParagraph(); ++ generator.closePageSpan(); ++ } ++ generator.endDocument(); ++ assertCss(package.m_cssStreams["OEBPS/styles/stylesheet.css"], ".body0", "writing-mode: vertical-rl", true); ++ assertXPath(package.m_streams["OEBPS/sections/section0001.xhtml"], "//xhtml:body", "class", "body0"); ++ assertXPath(package.m_streams["OEBPS/sections/section0002.xhtml"], "//xhtml:body", "class", "body0"); ++} ++ ++void EPUBTextGeneratorTest::testSplitOnSizeInPageSpan() ++{ ++ StringEPUBPackage package; ++ libepubgen::EPUBTextGenerator generator(&package); ++ generator.setOption(libepubgen::EPUB_GENERATOR_OPTION_SPLIT, libepubgen::EPUB_SPLIT_METHOD_SIZE); ++ generator.setSplitSize(5); ++ generator.startDocument(librevenge::RVNGPropertyList()); ++ ++ { ++ librevenge::RVNGPropertyList page; ++ page.insert("style:writing-mode", "tb"); ++ generator.openPageSpan(page); ++ ++ librevenge::RVNGPropertyList para; ++ generator.openParagraph(para); ++ generator.insertText("Hello!"); ++ generator.closeParagraph(); ++ // Splitting a new html file inside the page span, the writing-mode shall not change. ++ generator.openParagraph(para); ++ generator.insertText("Hello!"); ++ generator.closeParagraph(); + generator.closePageSpan(); + } + generator.endDocument(); + assertCss(package.m_cssStreams["OEBPS/styles/stylesheet.css"], ".body0", "writing-mode: vertical-rl", true); + assertXPath(package.m_streams["OEBPS/sections/section0001.xhtml"], "//xhtml:body", "class", "body0"); ++ assertXPath(package.m_streams["OEBPS/sections/section0002.xhtml"], "//xhtml:body", "class", "body0"); + } + + CPPUNIT_TEST_SUITE_REGISTRATION(EPUBTextGeneratorTest); +-- +2.14.1 + diff --git a/external/libepubgen/0003-Ensure-page-properties-in-the-page-span-works.patch.1 b/external/libepubgen/0003-Ensure-page-properties-in-the-page-span-works.patch.1 new file mode 100644 index 000000000000..62dd2cbab5dd --- /dev/null +++ b/external/libepubgen/0003-Ensure-page-properties-in-the-page-span-works.patch.1 @@ -0,0 +1,225 @@ +From 715786e10deaa6849a6e46b5a9884edde44e194b Mon Sep 17 00:00:00 2001 +From: Mark Hung <marklh9@gmail.com> +Date: Sun, 25 Mar 2018 10:27:07 +0800 +Subject: [PATCH 3/3] Ensure page properties in the page span works. + +As the page properties are converted to CSS styles of the +body element, this patch force it to start a new HTML file +when openPageSpan is invoked to open the second page span. + +This ensures that page properties in every page span works, +even there are multiple page spans between intentional HTML +page splits such as on size, on headings, or on page breaks. +--- + src/lib/EPUBGenerator.cpp | 4 +++- + src/lib/EPUBSplitGuard.cpp | 19 ++++++++++++++++++- + src/lib/EPUBSplitGuard.h | 7 ++++++- + src/lib/EPUBTextGenerator.cpp | 5 +++++ + src/test/EPUBTextGeneratorTest.cpp | 38 ++++++++++++++++++++++++++++++++++++++ + 5 files changed, 70 insertions(+), 3 deletions(-) + +diff --git a/src/lib/EPUBGenerator.cpp b/src/lib/EPUBGenerator.cpp +index 110667f..9e0c972 100644 +--- a/src/lib/EPUBGenerator.cpp ++++ b/src/lib/EPUBGenerator.cpp +@@ -44,7 +44,7 @@ EPUBGenerator::EPUBGenerator(EPUBPackage *const package, int version) + , m_documentProps() + , m_metadata() + , m_currentHtml() +- , m_splitGuard(EPUB_SPLIT_METHOD_PAGE_BREAK) ++ , m_splitGuard(EPUB_SPLIT_METHOD_PAGE_BREAK,true) + , m_version(version) + , m_stylesMethod(EPUB_STYLES_METHOD_CSS) + , m_layoutMethod(EPUB_LAYOUT_METHOD_REFLOWABLE) +@@ -173,6 +173,8 @@ void EPUBGenerator::setLayoutMethod(EPUBLayoutMethod layout) + if (m_layoutMethod == EPUB_LAYOUT_METHOD_FIXED) + // Fixed layout implies split on page break. + m_splitGuard.setSplitMethod(EPUB_SPLIT_METHOD_PAGE_BREAK); ++ ++ m_splitGuard.setSplitOnSecondPageSpan(m_layoutMethod == EPUB_LAYOUT_METHOD_REFLOWABLE); + } + + void EPUBGenerator::writeContainer() +diff --git a/src/lib/EPUBSplitGuard.cpp b/src/lib/EPUBSplitGuard.cpp +index 4f7531d..5bee515 100644 +--- a/src/lib/EPUBSplitGuard.cpp ++++ b/src/lib/EPUBSplitGuard.cpp +@@ -15,8 +15,10 @@ namespace libepubgen + static const unsigned DEFAULT_SPLIT_HEADING_LEVEL = 1; + static const unsigned DEFAULT_SPLIT_SIZE = 1 << 16; + +-EPUBSplitGuard::EPUBSplitGuard(const EPUBSplitMethod method) ++EPUBSplitGuard::EPUBSplitGuard(const EPUBSplitMethod method,bool splitOnSecondPageSpan) + : m_method(method) ++ , m_splitOnSecondPageSpan(splitOnSecondPageSpan) ++ , m_htmlEverInPageSpan(false) + , m_headingLevel(DEFAULT_SPLIT_HEADING_LEVEL) + , m_currentHeadingLevel(0) + , m_size(DEFAULT_SPLIT_SIZE) +@@ -25,6 +27,11 @@ EPUBSplitGuard::EPUBSplitGuard(const EPUBSplitMethod method) + { + } + ++void EPUBSplitGuard::setHtmlEverInPageSpan(bool value) ++{ ++ m_htmlEverInPageSpan = value; ++} ++ + void EPUBSplitGuard::setSplitHeadingLevel(const unsigned level) + { + m_headingLevel = level; +@@ -45,6 +52,11 @@ void EPUBSplitGuard::setSplitMethod(EPUBSplitMethod method) + m_method = method; + } + ++void EPUBSplitGuard::setSplitOnSecondPageSpan(bool value) ++{ ++ m_splitOnSecondPageSpan = value; ++} ++ + void EPUBSplitGuard::openLevel() + { + ++m_nestingLevel; +@@ -70,6 +82,11 @@ bool EPUBSplitGuard::splitOnHeading(const unsigned level) const + return canSplit(EPUB_SPLIT_METHOD_HEADING) && (m_headingLevel >= level); + } + ++bool EPUBSplitGuard::splitOnSecondPageSpan() const ++{ ++ return m_splitOnSecondPageSpan && m_htmlEverInPageSpan; ++} ++ + bool EPUBSplitGuard::inHeading(bool any) const + { + if (!m_currentHeadingLevel) +diff --git a/src/lib/EPUBSplitGuard.h b/src/lib/EPUBSplitGuard.h +index ff55846..a55bad3 100644 +--- a/src/lib/EPUBSplitGuard.h ++++ b/src/lib/EPUBSplitGuard.h +@@ -18,13 +18,15 @@ namespace libepubgen + class EPUBSplitGuard + { + public: +- explicit EPUBSplitGuard(EPUBSplitMethod method); ++ explicit EPUBSplitGuard(EPUBSplitMethod method,bool splitOnSecondPageSpan); + + void setSplitHeadingLevel(unsigned level); + void setCurrentHeadingLevel(unsigned level); + void setSplitSize(unsigned size); ++ void setHtmlEverInPageSpan(bool value); + /// Allows overwriting the value given in the constructor. + void setSplitMethod(EPUBSplitMethod method); ++ void setSplitOnSecondPageSpan(bool value); + + void openLevel(); + void closeLevel(); +@@ -32,6 +34,7 @@ public: + + bool splitOnPageBreak() const; + bool splitOnHeading(unsigned level) const; ++ bool splitOnSecondPageSpan() const; + bool inHeading(bool any) const; + bool splitOnSize() const; + +@@ -42,6 +45,8 @@ private: + + private: + EPUBSplitMethod m_method; ++ bool m_splitOnSecondPageSpan; ++ bool m_htmlEverInPageSpan; + unsigned m_headingLevel; + unsigned m_currentHeadingLevel; + unsigned m_size; +diff --git a/src/lib/EPUBTextGenerator.cpp b/src/lib/EPUBTextGenerator.cpp +index 8e88adb..db9d360 100644 +--- a/src/lib/EPUBTextGenerator.cpp ++++ b/src/lib/EPUBTextGenerator.cpp +@@ -110,6 +110,7 @@ void EPUBTextGenerator::Impl::startHtmlFile() + + void EPUBTextGenerator::Impl::endHtmlFile() + { ++ getSplitGuard().setHtmlEverInPageSpan(false); + if (m_inPageSpan) + getHtml()->openPageSpan(m_pageSpanProps); + if (bool(m_currentHeader)) +@@ -206,10 +207,14 @@ void EPUBTextGenerator::openPageSpan(const librevenge::RVNGPropertyList &propLis + { + assert(!m_impl->m_inPageSpan); + ++ if (m_impl->getSplitGuard().splitOnSecondPageSpan()) ++ m_impl->startNewHtmlFile(); ++ + m_impl->m_inPageSpan = true; + m_impl->m_pageSpanProps = propList; + + m_impl->getHtml()->openPageSpan(propList); ++ m_impl->getSplitGuard().setHtmlEverInPageSpan(true); + } + + void EPUBTextGenerator::closePageSpan() +diff --git a/src/test/EPUBTextGeneratorTest.cpp b/src/test/EPUBTextGeneratorTest.cpp +index 0946408..b5e43a5 100644 +--- a/src/test/EPUBTextGeneratorTest.cpp ++++ b/src/test/EPUBTextGeneratorTest.cpp +@@ -239,6 +239,7 @@ private: + CPPUNIT_TEST(testSplitOnPageBreakInPageSpan); + CPPUNIT_TEST(testSplitOnHeadingInPageSpan); + CPPUNIT_TEST(testSplitOnSizeInPageSpan); ++ CPPUNIT_TEST(testManyWritingModes); + CPPUNIT_TEST_SUITE_END(); + + private: +@@ -282,6 +283,7 @@ private: + void testSplitOnPageBreakInPageSpan(); + void testSplitOnHeadingInPageSpan(); + void testSplitOnSizeInPageSpan(); ++ void testManyWritingModes(); + + /// Asserts that exactly one xpath exists in buffer, and its content equals content. + void assertXPathContent(xmlBufferPtr buffer, const std::string &xpath, const std::string &content); +@@ -1467,6 +1469,42 @@ void EPUBTextGeneratorTest::testSplitOnSizeInPageSpan() + assertXPath(package.m_streams["OEBPS/sections/section0002.xhtml"], "//xhtml:body", "class", "body0"); + } + ++void EPUBTextGeneratorTest::testManyWritingModes() ++{ ++ StringEPUBPackage package; ++ libepubgen::EPUBTextGenerator generator(&package); ++ generator.setOption(libepubgen::EPUB_GENERATOR_OPTION_SPLIT, libepubgen::EPUB_SPLIT_METHOD_PAGE_BREAK); ++ generator.startDocument(librevenge::RVNGPropertyList()); ++ ++ { ++ librevenge::RVNGPropertyList page; ++ page.insert("style:writing-mode", "tb"); ++ generator.openPageSpan(page); ++ ++ librevenge::RVNGPropertyList para; ++ generator.openParagraph(para); ++ generator.insertText("Para1"); ++ generator.closeParagraph(); ++ generator.closePageSpan(); ++ } ++ { ++ librevenge::RVNGPropertyList page; ++ page.insert("style:writing-mode", "lr"); ++ generator.openPageSpan(page); ++ ++ librevenge::RVNGPropertyList para; ++ generator.openParagraph(para); ++ generator.insertText("Para1"); ++ generator.closeParagraph(); ++ generator.closePageSpan(); ++ } ++ generator.endDocument(); ++ assertCss(package.m_cssStreams["OEBPS/styles/stylesheet.css"], ".body0", "writing-mode: vertical-rl", true); ++ assertCss(package.m_cssStreams["OEBPS/styles/stylesheet.css"], ".body1", "writing-mode: horizontal-tb", true); ++ assertXPath(package.m_streams["OEBPS/sections/section0001.xhtml"], "//xhtml:body", "class", "body0"); ++ assertXPath(package.m_streams["OEBPS/sections/section0002.xhtml"], "//xhtml:body", "class", "body1"); ++} ++ + CPPUNIT_TEST_SUITE_REGISTRATION(EPUBTextGeneratorTest); + + } +-- +2.14.1 + diff --git a/external/libepubgen/UnpackedTarball_libepubgen.mk b/external/libepubgen/UnpackedTarball_libepubgen.mk index 47b21d7ee5d0..a6b2020f5f07 100644 --- a/external/libepubgen/UnpackedTarball_libepubgen.mk +++ b/external/libepubgen/UnpackedTarball_libepubgen.mk @@ -10,6 +10,12 @@ epubgen_patches := # Backport of <https://sourceforge.net/p/libepubgen/code/ci/006848cb62225647c418d5143d4e88a9d73829da/>. epubgen_patches += libepubgen-epub3.patch.1 +# Backport of <https://sourceforge.net/p/libepubgen/code/ci/9a284081eea4a95235a6d6a6a50cbe3f7ad323ba/>. +epubgen_patches += 0001-Support-writing-mode-for-reflowable-layout-method.patch.1 +# Backport of <https://sourceforge.net/p/libepubgen/code/ci/0318031b9094b9180d1d391d0ca31a782b016e99/>. +epubgen_patches += 0002-Always-keep-page-properties-when-splitting-the-HTML-.patch.1 +# Backport of <https://sourceforge.net/p/libepubgen/code/ci/1f602fcaa74fc9dbc6457019d11c602ff4040a4e/>. +epubgen_patches += 0003-Ensure-page-properties-in-the-page-span-works.patch.1 ifeq ($(COM_IS_CLANG),TRUE) ifneq ($(filter -fsanitize=%,$(CC)),) |