summaryrefslogtreecommitdiff
path: root/writerperfect/source/writer/exp/xmlimp.cxx
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2017-12-01 10:58:05 +0100
committerMiklos Vajna <vmiklos@collabora.co.uk>2017-12-04 09:06:56 +0100
commit3ed8466b55ace15a28761e06b6bb76ebd8758106 (patch)
tree15ef97033abe22882a78ea7c795b5df95362033d /writerperfect/source/writer/exp/xmlimp.cxx
parentd1e2205c6ec1b6e4c36192acc2e5b344e2ccc70d (diff)
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 <ci@libreoffice.org> Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
Diffstat (limited to 'writerperfect/source/writer/exp/xmlimp.cxx')
-rw-r--r--writerperfect/source/writer/exp/xmlimp.cxx106
1 files changed, 90 insertions, 16 deletions
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*/)
{
}