summaryrefslogtreecommitdiff
path: root/writerperfect
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2018-01-22 15:18:45 +0100
committerMiklos Vajna <vmiklos@collabora.co.uk>2018-01-23 09:05:02 +0100
commita54787669b9283efdfdd18b0cbafc3184cdde58f (patch)
treec64aac62a0c2d2e7baf1b5eddaba396270ec09d4 /writerperfect
parent75f5d70d5d9f58a76e42d151f187c50bad50378c (diff)
EPUB export, fixed layout: add chapter names to the navigation document
Extend vcl::PDFExtOutDevData so that it's possible to use it outside the PDF export; this way the EPUB export can know which chapters start on which page. This means fixed and reflowable layout has the same table of contents, instead of just Page <N> in the fixed layout case. Change-Id: I935fb23c66ec747431b91e83b0e677d4e5f704b9 Reviewed-on: https://gerrit.libreoffice.org/48332 Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk> Tested-by: Jenkins <ci@libreoffice.org>
Diffstat (limited to 'writerperfect')
-rw-r--r--writerperfect/qa/unit/EPUBExportTest.cxx7
-rw-r--r--writerperfect/qa/unit/data/writer/epubexport/fxl-2page.fodt7
-rw-r--r--writerperfect/source/writer/EPUBExportFilter.cxx12
-rw-r--r--writerperfect/source/writer/EPUBExportFilter.hxx4
-rw-r--r--writerperfect/source/writer/exp/xmlimp.cxx32
-rw-r--r--writerperfect/source/writer/exp/xmlimp.hxx17
6 files changed, 59 insertions, 20 deletions
diff --git a/writerperfect/qa/unit/EPUBExportTest.cxx b/writerperfect/qa/unit/EPUBExportTest.cxx
index 176324b0dff7..47e84ebf1bbc 100644
--- a/writerperfect/qa/unit/EPUBExportTest.cxx
+++ b/writerperfect/qa/unit/EPUBExportTest.cxx
@@ -348,6 +348,13 @@ void EPUBExportTest::testEPUBFixedLayoutImplicitBreak()
// This was missing, implicit page break (as calculated by the layout) was lost on export.
CPPUNIT_ASSERT(mxZipFile->hasByName("OEBPS/sections/section0002.xhtml"));
CPPUNIT_ASSERT(!mxZipFile->hasByName("OEBPS/sections/section0003.xhtml"));
+
+ // Make sure that fixed layout has chapter names in the navigation
+ // document.
+ mpXmlDoc = parseExport("OEBPS/toc.xhtml");
+ // This was 'Page 1' instead.
+ assertXPathContent(mpXmlDoc, "//xhtml:li[1]/xhtml:a", "First chapter");
+ assertXPathContent(mpXmlDoc, "//xhtml:li[2]/xhtml:a", "Second chapter");
}
void EPUBExportTest::testPageBreakSplit()
diff --git a/writerperfect/qa/unit/data/writer/epubexport/fxl-2page.fodt b/writerperfect/qa/unit/data/writer/epubexport/fxl-2page.fodt
index 6a22acd0821f..40f628b5e646 100644
--- a/writerperfect/qa/unit/data/writer/epubexport/fxl-2page.fodt
+++ b/writerperfect/qa/unit/data/writer/epubexport/fxl-2page.fodt
@@ -44,6 +44,10 @@
<style:paragraph-properties text:number-lines="false" text:line-number="0"/>
<style:text-properties style:font-size-asian="12pt" style:font-name-complex="Lucida Sans1" style:font-family-complex="&apos;Lucida Sans&apos;" style:font-family-generic-complex="swiss"/>
</style:style>
+ <style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text">
+ <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false"/>
+ <style:text-properties fo:font-size="130%" fo:font-weight="bold" style:font-size-asian="130%" style:font-weight-asian="bold" style:font-size-complex="130%" style:font-weight-complex="bold"/>
+ </style:style>
</office:styles>
<office:automatic-styles>
<style:style style:name="P1" style:family="paragraph" style:parent-style-name="Standard">
@@ -65,7 +69,10 @@
</office:master-styles>
<office:body>
<office:text text:use-soft-page-breaks="true">
+ <text:h text:style-name="Heading_20_1" text:outline-level="1">First chapter</text:h>
<text:p text:style-name="P1"><text:span text:style-name="T1">He heard quiet steps behind him. That didn&apos;t bode well. Who could be following him this late at night and in this deadbeat part of town? And at this particular moment, just after he pulled off the big time and was making off with the greenbacks. Was there another crook who&apos;d had the same idea, and was now watching him and waiting for a chance to grab the fruit of his labor? Or did the steps behind him mean that one of many law officers in town was on to him and just waiting to pounce and snap those cuffs on his wrists? He nervously looked all around. Suddenly he saw the alley. Like lightning he darted off to the left and disappeared between the two warehouses almost falling over the trash can lying in the middle of the sidewalk. He tried to nervously tap </text:span><text:soft-page-break/><text:span text:style-name="T1">his way along in the inky darkness and suddenly stiffened: it was a dead-end, he would have to go back the way he had come. The steps got louder and louder, he saw the black outline of a figure coming around the corner. Is this the end of the line?</text:span></text:p>
+ <text:h text:style-name="Heading_20_1" text:outline-level="1">Second chapter</text:h>
+ <text:p text:style-name="Standard">This is the end.</text:p>
</office:text>
</office:body>
</office:document>
diff --git a/writerperfect/source/writer/EPUBExportFilter.cxx b/writerperfect/source/writer/EPUBExportFilter.cxx
index b25118350193..2e4286e1f80b 100644
--- a/writerperfect/source/writer/EPUBExportFilter.cxx
+++ b/writerperfect/source/writer/EPUBExportFilter.cxx
@@ -94,7 +94,7 @@ sal_Bool EPUBExportFilter::filter(const uno::Sequence<beans::PropertyValue> &rDe
if (xSourceModel.is())
aSourceURL = xSourceModel->getURL();
- std::vector<std::pair<uno::Sequence<sal_Int8>, Size>> aPageMetafiles;
+ std::vector<exp::FixedLayoutPage> aPageMetafiles;
if (nLayoutMethod == libepubgen::EPUB_LAYOUT_METHOD_FIXED)
CreateMetafiles(aPageMetafiles);
@@ -119,7 +119,7 @@ sal_Bool EPUBExportFilter::filter(const uno::Sequence<beans::PropertyValue> &rDe
return xFilter->filter(rDescriptor);
}
-void EPUBExportFilter::CreateMetafiles(std::vector<std::pair<uno::Sequence<sal_Int8>, Size>> &rPageMetafiles)
+void EPUBExportFilter::CreateMetafiles(std::vector<exp::FixedLayoutPage> &rPageMetafiles)
{
DocumentToGraphicRenderer aRenderer(mxSourceDocument, /*bSelectionOnly=*/false);
uno::Reference<frame::XModel> xModel(mxSourceDocument, uno::UNO_QUERY);
@@ -142,7 +142,7 @@ void EPUBExportFilter::CreateMetafiles(std::vector<std::pair<uno::Sequence<sal_I
Size aLogic = aRenderer.getDocumentSizeIn100mm(nPage);
// Get the CSS pixel size of the page (mm100 -> pixel using 96 DPI, independent from system DPI).
Size aCss(static_cast<double>(aLogic.getWidth()) / 26.4583, static_cast<double>(aLogic.getHeight()) / 26.4583);
- Graphic aGraphic = aRenderer.renderToGraphic(nPage, aDocumentSizePixel, aCss, COL_WHITE);
+ Graphic aGraphic = aRenderer.renderToGraphic(nPage, aDocumentSizePixel, aCss, COL_WHITE, /*bExtOutDevData=*/true);
auto &rGDIMetaFile = const_cast<GDIMetaFile &>(aGraphic.GetGDIMetaFile());
// Set preferred map unit and size on the metafile, so the SVG size
@@ -156,7 +156,11 @@ void EPUBExportFilter::CreateMetafiles(std::vector<std::pair<uno::Sequence<sal_I
rGDIMetaFile.Write(aMemoryStream);
uno::Sequence<sal_Int8> aSequence(static_cast<const sal_Int8 *>(aMemoryStream.GetData()), aMemoryStream.Tell());
- rPageMetafiles.emplace_back(aSequence, aCss);
+ exp::FixedLayoutPage aPage;
+ aPage.aMetafile = aSequence;
+ aPage.aCssPixels = aCss;
+ aPage.aChapterNames = aRenderer.getChapterNames();
+ rPageMetafiles.push_back(aPage);
}
}
diff --git a/writerperfect/source/writer/EPUBExportFilter.hxx b/writerperfect/source/writer/EPUBExportFilter.hxx
index 188139a32843..ee676d3e1701 100644
--- a/writerperfect/source/writer/EPUBExportFilter.hxx
+++ b/writerperfect/source/writer/EPUBExportFilter.hxx
@@ -19,7 +19,7 @@
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
-class Size;
+#include "exp/xmlimp.hxx"
namespace writerperfect
{
@@ -59,7 +59,7 @@ public:
private:
/// Create page metafiles in case of fixed layout.
- void CreateMetafiles(std::vector<std::pair<css::uno::Sequence<sal_Int8>, Size>> &rPageMetafiles);
+ void CreateMetafiles(std::vector<exp::FixedLayoutPage> &rPageMetafiles);
};
} // namespace writerperfect
diff --git a/writerperfect/source/writer/exp/xmlimp.cxx b/writerperfect/source/writer/exp/xmlimp.cxx
index ef681119d4cf..3ef02f69f008 100644
--- a/writerperfect/source/writer/exp/xmlimp.cxx
+++ b/writerperfect/source/writer/exp/xmlimp.cxx
@@ -238,7 +238,7 @@ public:
rtl::Reference<XMLImportContext> CreateChildContext(const OUString &rName, const uno::Reference<xml::sax::XAttributeList> &/*xAttribs*/) override;
// Handles metafile for a single page.
- void HandleFixedLayoutPage(const uno::Sequence<sal_Int8> &rPage, const Size &rSize, bool bFirst);
+ void HandleFixedLayoutPage(const FixedLayoutPage &rPage, bool bFirst);
};
XMLOfficeDocContext::XMLOfficeDocContext(XMLImport &rImport)
@@ -266,7 +266,7 @@ rtl::Reference<XMLImportContext> XMLOfficeDocContext::CreateChildContext(const O
bool bFirst = true;
for (const auto &rPage : mrImport.GetPageMetafiles())
{
- HandleFixedLayoutPage(rPage.first, rPage.second, bFirst);
+ HandleFixedLayoutPage(rPage, bFirst);
if (bFirst)
bFirst = false;
}
@@ -274,7 +274,7 @@ rtl::Reference<XMLImportContext> XMLOfficeDocContext::CreateChildContext(const O
return nullptr;
}
-void XMLOfficeDocContext::HandleFixedLayoutPage(const uno::Sequence<sal_Int8> &rPage, const Size &rSize, bool bFirst)
+void XMLOfficeDocContext::HandleFixedLayoutPage(const FixedLayoutPage &rPage, bool bFirst)
{
uno::Reference<uno::XComponentContext> xCtx = mrImport.GetComponentContext();
uno::Reference<xml::sax::XWriter> xSaxWriter = xml::sax::Writer::create(xCtx);
@@ -292,17 +292,31 @@ void XMLOfficeDocContext::HandleFixedLayoutPage(const uno::Sequence<sal_Int8> &r
SvMemoryStream aMemoryStream;
xSaxWriter->setOutputStream(new utl::OStreamWrapper(aMemoryStream));
- xSVGWriter->write(xSaxWriter, rPage);
+ xSVGWriter->write(xSaxWriter, rPage.aMetafile);
- // Have all the info, invoke libepubgen.
+ // Have all the info, invoke the generator.
librevenge::RVNGPropertyList aPageProperties;
// Pixel -> inch.
- double fWidth = rSize.getWidth();
+ double fWidth = rPage.aCssPixels.getWidth();
fWidth /= 96;
aPageProperties.insert("fo:page-width", fWidth);
- double fHeight = rSize.getHeight();
+ double fHeight = rPage.aCssPixels.getHeight();
fHeight /= 96;
aPageProperties.insert("fo:page-height", fHeight);
+
+ if (!rPage.aChapterNames.empty())
+ {
+ // Name of chapters starting on this page.
+ librevenge::RVNGPropertyListVector aChapterNames;
+ for (const auto &rName : rPage.aChapterNames)
+ {
+ librevenge::RVNGPropertyList aChapter;
+ aChapter.insert("librevenge:name", rName.toUtf8().getStr());
+ aChapterNames.append(aChapter);
+ }
+ aPageProperties.insert("librevenge:chapter-names", aChapterNames);
+ }
+
mrImport.GetGenerator().openPageSpan(aPageProperties);
librevenge::RVNGPropertyList aParagraphProperties;
if (!bFirst)
@@ -320,7 +334,7 @@ void XMLOfficeDocContext::HandleFixedLayoutPage(const uno::Sequence<sal_Int8> &r
mrImport.GetGenerator().closePageSpan();
}
-XMLImport::XMLImport(const uno::Reference<uno::XComponentContext> &xContext, librevenge::RVNGTextInterface &rGenerator, const OUString &rURL, const uno::Sequence<beans::PropertyValue> &rDescriptor, const std::vector<std::pair<uno::Sequence<sal_Int8>, Size>> &rPageMetafiles)
+XMLImport::XMLImport(const uno::Reference<uno::XComponentContext> &xContext, librevenge::RVNGTextInterface &rGenerator, const OUString &rURL, const uno::Sequence<beans::PropertyValue> &rDescriptor, const std::vector<FixedLayoutPage> &rPageMetafiles)
: mrGenerator(rGenerator),
mxContext(xContext),
mrPageMetafiles(rPageMetafiles)
@@ -421,7 +435,7 @@ PopupState XMLImport::FillPopupData(const OUString &rURL, librevenge::RVNGProper
return PopupState::Consumed;
}
-const std::vector<std::pair<uno::Sequence<sal_Int8>, Size>> &XMLImport::GetPageMetafiles() const
+const std::vector<FixedLayoutPage> &XMLImport::GetPageMetafiles() const
{
return mrPageMetafiles;
}
diff --git a/writerperfect/source/writer/exp/xmlimp.hxx b/writerperfect/source/writer/exp/xmlimp.hxx
index 246eb45dbd16..1953c7196772 100644
--- a/writerperfect/source/writer/exp/xmlimp.hxx
+++ b/writerperfect/source/writer/exp/xmlimp.hxx
@@ -23,8 +23,7 @@
#include <cppuhelper/implbase.hxx>
#include <rtl/ref.hxx>
-
-class Size;
+#include <tools/gen.hxx>
namespace writerperfect
{
@@ -33,6 +32,14 @@ namespace exp
class XMLImportContext;
+/// Contains info about a fixed-layout page.
+struct FixedLayoutPage
+{
+ css::uno::Sequence<sal_Int8> aMetafile;
+ Size aCssPixels;
+ std::vector<OUString> aChapterNames;
+};
+
/// States describing the result of a link -> popup conversion.
enum class PopupState
{
@@ -74,10 +81,10 @@ class XMLImport : public cppu::WeakImplHelper
const css::uno::Reference<css::uno::XComponentContext> &mxContext;
css::uno::Reference<css::uri::XUriReferenceFactory> mxUriReferenceFactory;
OUString maMediaDir;
- const std::vector<std::pair<css::uno::Sequence<sal_Int8>, Size>> &mrPageMetafiles;
+ const std::vector<FixedLayoutPage> &mrPageMetafiles;
public:
- XMLImport(const css::uno::Reference<css::uno::XComponentContext> &xContext, librevenge::RVNGTextInterface &rGenerator, const OUString &rURL, const css::uno::Sequence<css::beans::PropertyValue> &rDescriptor, const std::vector<std::pair<css::uno::Sequence<sal_Int8>, Size>> &rPageMetafiles);
+ XMLImport(const css::uno::Reference<css::uno::XComponentContext> &xContext, librevenge::RVNGTextInterface &rGenerator, const OUString &rURL, const css::uno::Sequence<css::beans::PropertyValue> &rDescriptor, const std::vector<FixedLayoutPage> &rPageMetafiles);
rtl::Reference<XMLImportContext> CreateContext(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs);
@@ -99,7 +106,7 @@ public:
const librevenge::RVNGPropertyListVector &GetCoverImages();
const librevenge::RVNGPropertyList &GetMetaData();
PopupState FillPopupData(const OUString &rURL, librevenge::RVNGPropertyList &rPropList);
- const std::vector<std::pair<css::uno::Sequence<sal_Int8>, Size>> &GetPageMetafiles() const;
+ const std::vector<FixedLayoutPage> &GetPageMetafiles() const;
const css::uno::Reference<css::uno::XComponentContext> &GetComponentContext() const;
// XDocumentHandler