external/libepubgen/libepubgen-epub3.patch.1                |   25 ++
 writerperfect/Library_wpftwriter.mk                         |    1 
 writerperfect/qa/unit/EPUBExportTest.cxx                    |   17 +
 writerperfect/qa/unit/data/writer/epubexport/fxl-2page.fodt |   71 ++++++++
 writerperfect/source/writer/EPUBExportFilter.cxx            |   49 +++++
 writerperfect/source/writer/EPUBExportFilter.hxx            |    7 
 writerperfect/source/writer/exp/xmlimp.cxx                  |  106 ++++++++++--
 writerperfect/source/writer/exp/xmlimp.hxx                  |    7 
 8 files changed, 264 insertions(+), 19 deletions(-)

New commits:
commit 3ed8466b55ace15a28761e06b6bb76ebd8758106
Author: Miklos Vajna <[email protected]>
Date:   Fri Dec 1 10:58:05 2017 +0100

    EPUB export, fixed layout: switch to a metafile-based approach
    
    Trying to guess layout from flat ODF output is an approach that doesn't
    scale, think of complex documents with split tables, etc.
    
    Do it similar to the PDF export instead: take a metafile of each page
    and use the existing SVG writer to embed it into XHTML.
    
    Change-Id: I6e860834beb8025519d3e367f858077ae9e9c006
    Reviewed-on: https://gerrit.libreoffice.org/45647
    Tested-by: Jenkins <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>

diff --git a/external/libepubgen/libepubgen-epub3.patch.1 
b/external/libepubgen/libepubgen-epub3.patch.1
index c234ab10ec13..af6c9366fbc1 100644
--- a/external/libepubgen/libepubgen-epub3.patch.1
+++ b/external/libepubgen/libepubgen-epub3.patch.1
@@ -5831,3 +5831,28 @@ index c3bc963..02c299a 100644
 -- 
 2.13.6
 
+From 88b9d9a1efb9b064ea99c57ec273f76712d361ff Mon Sep 17 00:00:00 2001
+From: Miklos Vajna <[email protected]>
+Date: Thu, 30 Nov 2017 11:32:41 +0100
+Subject: [PATCH] EPUBTextGenerator: allow a single image on a page
+
+---
+ src/lib/EPUBTextGenerator.cpp      |  1 +
+ src/test/EPUBTextGeneratorTest.cpp | 24 ++++++++++++++++++++++++
+ 2 files changed, 25 insertions(+)
+
+diff --git a/src/lib/EPUBTextGenerator.cpp b/src/lib/EPUBTextGenerator.cpp
+index 02c299a..38573ec 100644
+--- a/src/lib/EPUBTextGenerator.cpp
++++ b/src/lib/EPUBTextGenerator.cpp
+@@ -684,6 +684,7 @@ void EPUBTextGenerator::insertBinaryObject(const 
librevenge::RVNGPropertyList &p
+   if (m_impl->m_inHeader || m_impl->m_inFooter)
+     m_impl->m_currentHeaderOrFooter->addInsertBinaryObject(newPropList);
+ 
++  m_impl->getSplitGuard().incrementSize(1);
+   m_impl->getHtml()->insertBinaryObject(newPropList);
+ }
+ 
+-- 
+2.13.6
+
diff --git a/writerperfect/Library_wpftwriter.mk 
b/writerperfect/Library_wpftwriter.mk
index 5e356304544d..3f0609fc0d9c 100644
--- a/writerperfect/Library_wpftwriter.mk
+++ b/writerperfect/Library_wpftwriter.mk
@@ -36,6 +36,7 @@ $(eval $(call gb_Library_use_libraries,wpftwriter,\
        sal \
        sfx \
        sot \
+       svt \
        svx \
        tl \
        ucbhelper \
diff --git a/writerperfect/qa/unit/EPUBExportTest.cxx 
b/writerperfect/qa/unit/EPUBExportTest.cxx
index ac6e25efc2ae..bd42356e60ce 100644
--- a/writerperfect/qa/unit/EPUBExportTest.cxx
+++ b/writerperfect/qa/unit/EPUBExportTest.cxx
@@ -60,6 +60,7 @@ public:
     void testEPUB2();
     void testEPUBFixedLayout();
     void testEPUBFixedLayoutOption();
+    void testEPUBFixedLayoutImplicitBreak();
     void testPageBreakSplit();
     void testSpanAutostyle();
     void testParaAutostyleCharProps();
@@ -102,6 +103,7 @@ public:
     CPPUNIT_TEST(testEPUB2);
     CPPUNIT_TEST(testEPUBFixedLayout);
     CPPUNIT_TEST(testEPUBFixedLayoutOption);
+    CPPUNIT_TEST(testEPUBFixedLayoutImplicitBreak);
     CPPUNIT_TEST(testPageBreakSplit);
     CPPUNIT_TEST(testSpanAutostyle);
     CPPUNIT_TEST(testParaAutostyleCharProps);
@@ -327,6 +329,21 @@ void EPUBExportTest::testEPUBFixedLayoutOption()
     assertXPathContent(mpXmlDoc, 
"/opf:package/opf:metadata/opf:meta[@property='rendition:layout']", 
"pre-paginated");
 }
 
+void EPUBExportTest::testEPUBFixedLayoutImplicitBreak()
+{
+    uno::Sequence<beans::PropertyValue> 
aFilterData(comphelper::InitPropertySequence(
+    {
+        // Explicitly request fixed layout.
+        {"EPUBLayoutMethod", 
uno::makeAny(static_cast<sal_Int32>(libepubgen::EPUB_LAYOUT_METHOD_FIXED))}
+    }));
+    createDoc("fxl-2page.fodt", aFilterData);
+
+    CPPUNIT_ASSERT(mxZipFile->hasByName("OEBPS/sections/section0001.xhtml"));
+    // 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"));
+}
+
 void EPUBExportTest::testPageBreakSplit()
 {
     uno::Sequence<beans::PropertyValue> 
aFilterData(comphelper::InitPropertySequence(
diff --git a/writerperfect/qa/unit/data/writer/epubexport/fxl-2page.fodt 
b/writerperfect/qa/unit/data/writer/epubexport/fxl-2page.fodt
new file mode 100644
index 000000000000..6a22acd0821f
--- /dev/null
+++ b/writerperfect/qa/unit/data/writer/epubexport/fxl-2page.fodt
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:xlink="http://www.w3.org/1999/xlink"; 
xmlns:dc="http://purl.org/dc/elements/1.1/"; 
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" 
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" 
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" 
xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" 
xmlns:math="http://www.w3.org/1998/Math/MathML"; 
xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" 
xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" 
xmlns:config="urn:oas
 is:names:tc:opendocument:xmlns:config:1.0" 
xmlns:ooo="http://openoffice.org/2004/office"; 
xmlns:ooow="http://openoffice.org/2004/writer"; 
xmlns:oooc="http://openoffice.org/2004/calc"; 
xmlns:dom="http://www.w3.org/2001/xml-events"; 
xmlns:xforms="http://www.w3.org/2002/xforms"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns:rpt="http://openoffice.org/2005/report"; 
xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" 
xmlns:xhtml="http://www.w3.org/1999/xhtml"; 
xmlns:grddl="http://www.w3.org/2003/g/data-view#"; 
xmlns:officeooo="http://openoffice.org/2009/office"; 
xmlns:tableooo="http://openoffice.org/2009/table"; 
xmlns:drawooo="http://openoffice.org/2010/draw"; 
xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"
 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" 
xmlns:formx="urn:openoffice:names:
 experimental:ooxml-odf-interop:xmlns:form:1.0" 
xmlns:css3t="http://www.w3.org/TR/css3-text/"; office:version="1.2" 
office:mimetype="application/vnd.oasis.opendocument.text">
+  <office:font-face-decls>
+    <style:font-face style:name="Lucida Sans1" svg:font-family="&apos;Lucida 
Sans&apos;" style:font-family-generic="swiss"/>
+    <style:font-face style:name="Liberation Serif" 
svg:font-family="&apos;Liberation Serif&apos;" 
style:font-family-generic="roman" style:font-pitch="variable"/>
+    <style:font-face style:name="Liberation Sans" 
svg:font-family="&apos;Liberation Sans&apos;" style:font-family-generic="swiss" 
style:font-pitch="variable"/>
+    <style:font-face style:name="AR PL SungtiL GB" svg:font-family="&apos;AR 
PL SungtiL GB&apos;" style:font-family-generic="system" 
style:font-pitch="variable"/>
+    <style:font-face style:name="Lucida Sans" svg:font-family="&apos;Lucida 
Sans&apos;" style:font-family-generic="system" style:font-pitch="variable"/>
+  </office:font-face-decls>
+  <office:styles>
+    <style:default-style style:family="graphic">
+      <style:graphic-properties svg:stroke-color="#3465a4" 
draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" 
draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" 
draw:start-line-spacing-vertical="0.283cm" 
draw:end-line-spacing-horizontal="0.283cm" 
draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/>
+      <style:paragraph-properties style:text-autospace="ideograph-alpha" 
style:line-break="strict" style:font-independent-line-spacing="false">
+        <style:tab-stops/>
+      </style:paragraph-properties>
+      <style:text-properties style:use-window-font-color="true" 
style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" 
fo:country="US" style:letter-kerning="true" style:font-name-asian="AR PL 
SungtiL GB" style:font-size-asian="10.5pt" style:language-asian="zh" 
style:country-asian="CN" style:font-name-complex="Lucida Sans" 
style:font-size-complex="12pt" style:language-complex="hi" 
style:country-complex="IN"/>
+    </style:default-style>
+    <style:default-style style:family="paragraph">
+      <style:paragraph-properties fo:orphans="2" fo:widows="2" 
fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" 
style:punctuation-wrap="hanging" style:line-break="strict" 
style:tab-stop-distance="1.251cm" style:writing-mode="page"/>
+      <style:text-properties style:use-window-font-color="true" 
style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" 
fo:country="US" style:letter-kerning="true" style:font-name-asian="AR PL 
SungtiL GB" style:font-size-asian="10.5pt" style:language-asian="zh" 
style:country-asian="CN" style:font-name-complex="Lucida Sans" 
style:font-size-complex="12pt" style:language-complex="hi" 
style:country-complex="IN" fo:hyphenate="false" 
fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/>
+    </style:default-style>
+    <style:default-style style:family="table">
+      <style:table-properties table:border-model="collapsing"/>
+    </style:default-style>
+    <style:default-style style:family="table-row">
+      <style:table-row-properties fo:keep-together="auto"/>
+    </style:default-style>
+    <style:style style:name="Standard" style:family="paragraph" 
style:class="text"/>
+    <style:style style:name="Heading" style:family="paragraph" 
style:parent-style-name="Standard" style:next-style-name="Text_20_body" 
style:class="text">
+      <style:paragraph-properties fo:margin-top="0.423cm" 
fo:margin-bottom="0.212cm" loext:contextual-spacing="false" 
fo:keep-with-next="always"/>
+      <style:text-properties style:font-name="Liberation Sans" 
fo:font-family="&apos;Liberation Sans&apos;" style:font-family-generic="swiss" 
style:font-pitch="variable" fo:font-size="14pt" style:font-name-asian="AR PL 
SungtiL GB" style:font-family-asian="&apos;AR PL SungtiL GB&apos;" 
style:font-family-generic-asian="system" style:font-pitch-asian="variable" 
style:font-size-asian="14pt" style:font-name-complex="Lucida Sans" 
style:font-family-complex="&apos;Lucida Sans&apos;" 
style:font-family-generic-complex="system" style:font-pitch-complex="variable" 
style:font-size-complex="14pt"/>
+    </style:style>
+    <style:style style:name="Text_20_body" style:display-name="Text body" 
style:family="paragraph" style:parent-style-name="Standard" style:class="text">
+      <style:paragraph-properties fo:margin-top="0cm" 
fo:margin-bottom="0.247cm" loext:contextual-spacing="false" 
fo:line-height="115%"/>
+    </style:style>
+    <style:style style:name="List" style:family="paragraph" 
style:parent-style-name="Text_20_body" style:class="list">
+      <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="Caption" style:family="paragraph" 
style:parent-style-name="Standard" style:class="extra">
+      <style:paragraph-properties fo:margin-top="0.212cm" 
fo:margin-bottom="0.212cm" loext:contextual-spacing="false" 
text:number-lines="false" text:line-number="0"/>
+      <style:text-properties fo:font-size="12pt" fo:font-style="italic" 
style:font-size-asian="12pt" style:font-style-asian="italic" 
style:font-name-complex="Lucida Sans1" style:font-family-complex="&apos;Lucida 
Sans&apos;" style:font-family-generic-complex="swiss" 
style:font-size-complex="12pt" style:font-style-complex="italic"/>
+    </style:style>
+    <style:style style:name="Index" style:family="paragraph" 
style:parent-style-name="Standard" style:class="index">
+      <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>
+  </office:styles>
+  <office:automatic-styles>
+    <style:style style:name="P1" style:family="paragraph" 
style:parent-style-name="Standard">
+      <style:text-properties officeooo:paragraph-rsid="001f977c"/>
+    </style:style>
+    <style:style style:name="T1" style:family="text">
+      <style:text-properties officeooo:rsid="001f977c"/>
+    </style:style>
+    <style:page-layout style:name="pm1">
+      <style:page-layout-properties fo:page-width="10.5cm" 
fo:page-height="14.801cm" style:num-format="1" 
style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" 
fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" 
style:footnote-max-height="0cm">
+        <style:footnote-sep style:width="0.018cm" 
style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" 
style:line-style="solid" style:adjustment="left" style:rel-width="25%" 
style:color="#000000"/>
+      </style:page-layout-properties>
+      <style:header-style/>
+      <style:footer-style/>
+    </style:page-layout>
+  </office:automatic-styles>
+  <office:master-styles>
+    <style:master-page style:name="Standard" style:page-layout-name="pm1"/>
+  </office:master-styles>
+  <office:body>
+    <office:text text:use-soft-page-breaks="true">
+      <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 h
 ave 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>
+    </office:text>
+  </office:body>
+</office:document>
diff --git a/writerperfect/source/writer/EPUBExportFilter.cxx 
b/writerperfect/source/writer/EPUBExportFilter.cxx
index 627d5a4af18f..301bdeb6f460 100644
--- a/writerperfect/source/writer/EPUBExportFilter.cxx
+++ b/writerperfect/source/writer/EPUBExportFilter.cxx
@@ -18,12 +18,16 @@
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <com/sun/star/frame/XModel.hpp>
 #include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/text/XPageCursor.hpp>
+#include <com/sun/star/text/XTextViewCursorSupplier.hpp>
 #include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/view/XRenderable.hpp>
 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
 
 #include <comphelper/genericpropertyset.hxx>
 #include <comphelper/propertysetinfo.hxx>
 #include <cppuhelper/supportsservice.hxx>
+#include <svtools/DocumentToGraphicRenderer.hxx>
 
 #include "exp/xmlimp.hxx"
 #include "EPUBPackage.hxx"
@@ -103,7 +107,14 @@ sal_Bool EPUBExportFilter::filter(const 
uno::Sequence<beans::PropertyValue> &rDe
     uno::Reference<frame::XModel> xSourceModel(mxSourceDocument, 
uno::UNO_QUERY);
     if (xSourceModel.is())
         aSourceURL = xSourceModel->getURL();
-    uno::Reference<xml::sax::XDocumentHandler> xExportHandler(new 
exp::XMLImport(mxContext, aGenerator, aSourceURL, rDescriptor));
+
+    std::vector<std::pair<uno::Sequence<sal_Int8>, Size>> aPageMetafiles;
+#if LIBEPUBGEN_VERSION_SUPPORT
+    if (nLayoutMethod == libepubgen::EPUB_LAYOUT_METHOD_FIXED)
+        CreateMetafiles(aPageMetafiles);
+#endif
+
+    uno::Reference<xml::sax::XDocumentHandler> xExportHandler(new 
exp::XMLImport(mxContext, aGenerator, aSourceURL, rDescriptor, aPageMetafiles));
 
     uno::Reference<lang::XInitialization> 
xInitialization(mxContext->getServiceManager()->createInstanceWithContext("com.sun.star.comp.Writer.XMLOasisExporter",
 mxContext), uno::UNO_QUERY);
 
@@ -111,7 +122,7 @@ sal_Bool EPUBExportFilter::filter(const 
uno::Sequence<beans::PropertyValue> &rDe
     comphelper::PropertyMapEntry const aInfoMap[] =
     {
         {OUString("BaseURI"), 0, cppu::UnoType<OUString>::get(), 
beans::PropertyAttribute::MAYBEVOID, 0},
-        {OUString(), 0, css::uno::Type(), 0, 0}
+        {OUString(), 0, uno::Type(), 0, 0}
     };
     uno::Reference<beans::XPropertySet> 
xInfoSet(comphelper::GenericPropertySet_CreateInstance(new 
comphelper::PropertySetInfo(aInfoMap)));
     xInfoSet->setPropertyValue("BaseURI", uno::makeAny(aSourceURL));
@@ -120,9 +131,43 @@ sal_Bool EPUBExportFilter::filter(const 
uno::Sequence<beans::PropertyValue> &rDe
     uno::Reference<document::XExporter> xExporter(xInitialization, 
uno::UNO_QUERY);
     xExporter->setSourceDocument(mxSourceDocument);
     uno::Reference<document::XFilter> xFilter(xInitialization, uno::UNO_QUERY);
+
     return xFilter->filter(rDescriptor);
 }
 
+void 
EPUBExportFilter::CreateMetafiles(std::vector<std::pair<uno::Sequence<sal_Int8>,
 Size>> &rPageMetafiles)
+{
+    DocumentToGraphicRenderer aRenderer(mxSourceDocument, 
/*bSelectionOnly=*/false);
+    uno::Reference<frame::XModel> xModel(mxSourceDocument, uno::UNO_QUERY);
+    if (!xModel.is())
+        return;
+
+    uno::Reference<text::XTextViewCursorSupplier> 
xTextViewCursorSupplier(xModel->getCurrentController(), uno::UNO_QUERY);
+    if (!xTextViewCursorSupplier.is())
+        return;
+
+    uno::Reference<text::XPageCursor> 
xCursor(xTextViewCursorSupplier->getViewCursor(), uno::UNO_QUERY);
+    if (!xCursor.is())
+        return;
+
+    xCursor->jumpToLastPage();
+    sal_Int16 nPages = xCursor->getPage();
+    for (sal_Int16 nPage = 1; nPage <= nPages; ++nPage)
+    {
+        Size aDocumentSizePixel = aRenderer.getDocumentSizeInPixels(nPage);
+        Graphic aGraphic = aRenderer.renderToGraphic(nPage, 
aDocumentSizePixel, aDocumentSizePixel, COL_WHITE);
+        const GDIMetaFile &rGDIMetaFile = aGraphic.GetGDIMetaFile();
+        SvMemoryStream aMemoryStream;
+        const_cast<GDIMetaFile &>(rGDIMetaFile).Write(aMemoryStream);
+        uno::Sequence<sal_Int8> aSequence(static_cast<const sal_Int8 
*>(aMemoryStream.GetData()), aMemoryStream.Tell());
+
+        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);
+        rPageMetafiles.emplace_back(aSequence, aCss);
+    }
+}
+
 void EPUBExportFilter::cancel()
 {
 }
diff --git a/writerperfect/source/writer/EPUBExportFilter.hxx 
b/writerperfect/source/writer/EPUBExportFilter.hxx
index e96b0a84b695..7a97f4a40852 100644
--- a/writerperfect/source/writer/EPUBExportFilter.hxx
+++ b/writerperfect/source/writer/EPUBExportFilter.hxx
@@ -10,12 +10,15 @@
 #ifndef INCLUDED_WRITERPERFECT_SOURCE_WRITER_EPUBEXPORTFILTER_HXX
 #define INCLUDED_WRITERPERFECT_SOURCE_WRITER_EPUBEXPORTFILTER_HXX
 
+#include <vector>
+
 #include <cppuhelper/implbase.hxx>
 
 #include <com/sun/star/document/XFilter.hpp>
 #include <com/sun/star/document/XExporter.hpp>
 #include <com/sun/star/lang/XServiceInfo.hpp>
 #include <com/sun/star/uno/XComponentContext.hpp>
+#include <tools/gen.hxx>
 
 namespace writerperfect
 {
@@ -52,6 +55,10 @@ public:
     static sal_Int32 GetDefaultSplitMethod();
     /// Gives the default layout method.
     static sal_Int32 GetDefaultLayoutMethod();
+
+private:
+    /// Create page metafiles in case of fixed layout.
+    void CreateMetafiles(std::vector<std::pair<css::uno::Sequence<sal_Int8>, 
Size>> &rPageMetafiles);
 };
 
 } // namespace writerperfect
diff --git a/writerperfect/source/writer/exp/xmlimp.cxx 
b/writerperfect/source/writer/exp/xmlimp.cxx
index 1d245401aea6..4686cd95ad64 100644
--- a/writerperfect/source/writer/exp/xmlimp.cxx
+++ b/writerperfect/source/writer/exp/xmlimp.cxx
@@ -12,9 +12,11 @@
 #include <initializer_list>
 #include <unordered_map>
 
+#include <com/sun/star/svg/XSVGWriter.hpp>
 #include <com/sun/star/uri/UriReferenceFactory.hpp>
 #include <com/sun/star/xml/sax/InputSource.hpp>
 #include <com/sun/star/xml/sax/Parser.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
 #include <rtl/uri.hxx>
 #include <tools/stream.hxx>
 #include <tools/urlobj.hxx>
@@ -210,7 +212,7 @@ class XMLBodyContext : public XMLImportContext
 public:
     XMLBodyContext(XMLImport &rImport);
 
-    rtl::Reference<XMLImportContext> CreateChildContext(const OUString &rName, 
const css::uno::Reference<css::xml::sax::XAttributeList> &/*xAttribs*/) 
override;
+    rtl::Reference<XMLImportContext> CreateChildContext(const OUString &rName, 
const uno::Reference<xml::sax::XAttributeList> &/*xAttribs*/) override;
 };
 
 XMLBodyContext::XMLBodyContext(XMLImport &rImport)
@@ -218,7 +220,7 @@ XMLBodyContext::XMLBodyContext(XMLImport &rImport)
 {
 }
 
-rtl::Reference<XMLImportContext> XMLBodyContext::CreateChildContext(const 
OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> 
&/*xAttribs*/)
+rtl::Reference<XMLImportContext> XMLBodyContext::CreateChildContext(const 
OUString &rName, const uno::Reference<xml::sax::XAttributeList> &/*xAttribs*/)
 {
     if (rName == "office:text")
         return new XMLBodyContentContext(mrImport);
@@ -231,7 +233,10 @@ class XMLOfficeDocContext : public XMLImportContext
 public:
     XMLOfficeDocContext(XMLImport &rImport);
 
-    rtl::Reference<XMLImportContext> CreateChildContext(const OUString &rName, 
const css::uno::Reference<css::xml::sax::XAttributeList> &/*xAttribs*/) 
override;
+    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);
 };
 
 XMLOfficeDocContext::XMLOfficeDocContext(XMLImport &rImport)
@@ -239,26 +244,85 @@ XMLOfficeDocContext::XMLOfficeDocContext(XMLImport 
&rImport)
 {
 }
 
-rtl::Reference<XMLImportContext> XMLOfficeDocContext::CreateChildContext(const 
OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> 
&/*xAttribs*/)
+rtl::Reference<XMLImportContext> XMLOfficeDocContext::CreateChildContext(const 
OUString &rName, const uno::Reference<xml::sax::XAttributeList> &/*xAttribs*/)
 {
-    if (rName == "office:body")
-        return new XMLBodyContext(mrImport);
-    else if (rName == "office:meta")
+    if (rName == "office:meta")
         return new XMLMetaDocumentContext(mrImport);
-    else if (rName == "office:automatic-styles")
+    if (rName == "office:automatic-styles")
         return new XMLStylesContext(mrImport, 
XMLStylesContext::StyleType_AUTOMATIC);
-    else if (rName == "office:styles")
+    if (rName == "office:styles")
         return new XMLStylesContext(mrImport, 
XMLStylesContext::StyleType_NONE);
-    else if (rName == "office:font-face-decls")
+    if (rName == "office:font-face-decls")
         return new XMLFontFaceDeclsContext(mrImport);
-    else if (rName == "office:master-styles")
+    if (rName == "office:master-styles")
         return new XMLStylesContext(mrImport, 
XMLStylesContext::StyleType_MASTER);
+    if (rName == "office:body")
+    {
+        if (mrImport.GetPageMetafiles().empty())
+            return new XMLBodyContext(mrImport);
+        else
+        {
+            // Ignore text from doc model in the fixed layout case, instead
+            // insert the page metafiles.
+            bool bFirst = true;
+            for (const auto &rPage : mrImport.GetPageMetafiles())
+            {
+                HandleFixedLayoutPage(rPage.first, rPage.second, bFirst);
+                if (bFirst)
+                    bFirst = false;
+            }
+        }
+    }
     return nullptr;
 }
 
-XMLImport::XMLImport(const uno::Reference<uno::XComponentContext> &xContext, 
librevenge::RVNGTextInterface &rGenerator, const OUString &rURL, const 
uno::Sequence<beans::PropertyValue> &rDescriptor)
+void XMLOfficeDocContext::HandleFixedLayoutPage(const uno::Sequence<sal_Int8> 
&rPage, const Size &rSize, bool bFirst)
+{
+    uno::Reference<uno::XComponentContext> xCtx = 
mrImport.GetComponentContext();
+    uno::Reference<xml::sax::XWriter> xSaxWriter = 
xml::sax::Writer::create(xCtx);
+    if (!xSaxWriter.is())
+        return;
+
+    uno::Sequence<uno::Any> aArguments;
+    uno::Reference<svg::XSVGWriter> 
xSVGWriter(xCtx->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.svg.SVGWriter",
 aArguments, xCtx), uno::UNO_QUERY);
+    if (!xSVGWriter.is())
+        return;
+
+    SvMemoryStream aMemoryStream;
+    xSaxWriter->setOutputStream(new utl::OStreamWrapper(aMemoryStream));
+
+    xSVGWriter->write(xSaxWriter, rPage);
+
+    // Have all the info, invoke libepubgen.
+    librevenge::RVNGPropertyList aPageProperties;
+    // Pixel -> inch.
+    double fWidth = rSize.getWidth();
+    fWidth /= 96;
+    aPageProperties.insert("fo:page-width", fWidth);
+    double fHeight = rSize.getHeight();
+    fHeight /= 96;
+    aPageProperties.insert("fo:page-height", fHeight);
+    mrImport.GetGenerator().openPageSpan(aPageProperties);
+    librevenge::RVNGPropertyList aParagraphProperties;
+    if (!bFirst)
+        // All pages except the first one needs a page break before the page
+        // metafile.
+        aParagraphProperties.insert("fo:break-before", "page");
+    mrImport.GetGenerator().openParagraph(aParagraphProperties);
+    librevenge::RVNGPropertyList aImageProperties;
+    aImageProperties.insert("librevenge:mime-type", "image/svg+xml");
+    librevenge::RVNGBinaryData aBinaryData;
+    aBinaryData.append(static_cast<const unsigned char 
*>(aMemoryStream.GetBuffer()), aMemoryStream.GetSize());
+    aImageProperties.insert("office:binary-data", aBinaryData);
+    mrImport.GetGenerator().insertBinaryObject(aImageProperties);
+    mrImport.GetGenerator().closeParagraph();
+    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)
     : mrGenerator(rGenerator),
-      mxContext(xContext)
+      mxContext(xContext),
+      mrPageMetafiles(rPageMetafiles)
 {
     uno::Sequence<beans::PropertyValue> aFilterData;
     for (sal_Int32 i = 0; i < rDescriptor.getLength(); ++i)
@@ -351,7 +415,17 @@ bool XMLImport::IsPageSpanOpened() const
     return mbPageSpanOpened;
 }
 
-rtl::Reference<XMLImportContext> XMLImport::CreateContext(const OUString 
&rName, const css::uno::Reference<css::xml::sax::XAttributeList> &/*xAttribs*/)
+const std::vector<std::pair<uno::Sequence<sal_Int8>, Size>> 
&XMLImport::GetPageMetafiles() const
+{
+    return mrPageMetafiles;
+}
+
+const uno::Reference<uno::XComponentContext> &XMLImport::GetComponentContext() 
const
+{
+    return mxContext;
+}
+
+rtl::Reference<XMLImportContext> XMLImport::CreateContext(const OUString 
&rName, const uno::Reference<xml::sax::XAttributeList> &/*xAttribs*/)
 {
     if (rName == "office:document")
         return new XMLOfficeDocContext(*this);
@@ -458,7 +532,7 @@ void XMLImport::endDocument()
     mrGenerator.endDocument();
 }
 
-void XMLImport::startElement(const OUString &rName, const 
css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs)
+void XMLImport::startElement(const OUString &rName, const 
uno::Reference<xml::sax::XAttributeList> &xAttribs)
 {
     rtl::Reference<XMLImportContext> xContext;
     if (!maContexts.empty())
@@ -500,7 +574,7 @@ void XMLImport::processingInstruction(const OUString 
&/*rTarget*/, const OUStrin
 {
 }
 
-void XMLImport::setDocumentLocator(const 
css::uno::Reference<css::xml::sax::XLocator> &/*xLocator*/)
+void XMLImport::setDocumentLocator(const uno::Reference<xml::sax::XLocator> 
&/*xLocator*/)
 {
 }
 
diff --git a/writerperfect/source/writer/exp/xmlimp.hxx 
b/writerperfect/source/writer/exp/xmlimp.hxx
index aeec06bde727..c5a84852603b 100644
--- a/writerperfect/source/writer/exp/xmlimp.hxx
+++ b/writerperfect/source/writer/exp/xmlimp.hxx
@@ -12,6 +12,7 @@
 
 #include <map>
 #include <stack>
+#include <vector>
 
 #include <librevenge/librevenge.h>
 
@@ -22,6 +23,7 @@
 
 #include <cppuhelper/implbase.hxx>
 #include <rtl/ref.hxx>
+#include <tools/gen.hxx>
 
 namespace writerperfect
 {
@@ -61,9 +63,10 @@ class XMLImport : public cppu::WeakImplHelper
     css::uno::Reference<css::uri::XUriReferenceFactory> mxUriReferenceFactory;
     OUString maMediaDir;
     bool mbPageSpanOpened = false;
+    const std::vector<std::pair<css::uno::Sequence<sal_Int8>, Size>> 
&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);
+    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);
 
     rtl::Reference<XMLImportContext> CreateContext(const OUString &rName, 
const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs);
 
@@ -89,6 +92,8 @@ public:
     bool FillPopupData(const OUString &rURL, librevenge::RVNGPropertyList 
&rPropList);
     void SetPageSpanOpened(bool bPageSpanOpened);
     bool IsPageSpanOpened() const;
+    const std::vector<std::pair<css::uno::Sequence<sal_Int8>, Size>> 
&GetPageMetafiles() const;
+    const css::uno::Reference<css::uno::XComponentContext> 
&GetComponentContext() const;
 
     // XDocumentHandler
     void SAL_CALL startDocument() override;
_______________________________________________
Libreoffice-commits mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to