diff options
Diffstat (limited to 'writerperfect/source')
-rw-r--r-- | writerperfect/source/writer/EPUBExportFilter.cxx | 49 | ||||
-rw-r--r-- | writerperfect/source/writer/EPUBExportFilter.hxx | 7 | ||||
-rw-r--r-- | writerperfect/source/writer/exp/xmlimp.cxx | 106 | ||||
-rw-r--r-- | writerperfect/source/writer/exp/xmlimp.hxx | 7 |
4 files changed, 150 insertions, 19 deletions
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; |