diff options
author | Miklos Vajna <vmiklos@collabora.co.uk> | 2017-11-30 16:33:03 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2017-12-01 09:17:01 +0100 |
commit | 7dcb4fef3b2383f4dd4d5d5c9ebbe8f19f8f4c8e (patch) | |
tree | 1f98cde1b37dc8fce39a571243435e4e9cbb6409 /writerperfect | |
parent | 553a35bed7a7ffb5bcda98987eb4af8b79bc031f (diff) |
EPUB export: support image popup for images and text
Handle relative links on image / text as data for a popup. Pick the images up
from <base directory>/<base name>/<relative url> as a start.
Change-Id: I9b6183d554e3792aa71dfffc19a671a0e4c302cc
Reviewed-on: https://gerrit.libreoffice.org/45601
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
Diffstat (limited to 'writerperfect')
-rw-r--r-- | writerperfect/qa/unit/EPUBExportTest.cxx | 22 | ||||
-rw-r--r-- | writerperfect/qa/unit/data/writer/epubexport/popup.odt | bin | 0 -> 10103 bytes | |||
-rw-r--r-- | writerperfect/qa/unit/data/writer/epubexport/popup/libreoffice.png | bin | 0 -> 766 bytes | |||
-rw-r--r-- | writerperfect/source/writer/EPUBExportFilter.cxx | 16 | ||||
-rw-r--r-- | writerperfect/source/writer/exp/txtparai.cxx | 6 | ||||
-rw-r--r-- | writerperfect/source/writer/exp/xmlimp.cxx | 54 | ||||
-rw-r--r-- | writerperfect/source/writer/exp/xmlimp.hxx | 4 |
7 files changed, 100 insertions, 2 deletions
diff --git a/writerperfect/qa/unit/EPUBExportTest.cxx b/writerperfect/qa/unit/EPUBExportTest.cxx index 04df33257b6d..1f7b64250724 100644 --- a/writerperfect/qa/unit/EPUBExportTest.cxx +++ b/writerperfect/qa/unit/EPUBExportTest.cxx @@ -89,6 +89,7 @@ public: void testFontEmbedding(); void testImageLink(); void testFootnote(); + void testPopup(); CPPUNIT_TEST_SUITE(EPUBExportTest); CPPUNIT_TEST(testOutlineLevel); @@ -126,6 +127,7 @@ public: CPPUNIT_TEST(testFontEmbedding); CPPUNIT_TEST(testImageLink); CPPUNIT_TEST(testFootnote); + CPPUNIT_TEST(testPopup); CPPUNIT_TEST_SUITE_END(); }; @@ -702,6 +704,26 @@ void EPUBExportTest::testFootnote() assertXPath(mpXmlDoc, "//xhtml:body/xhtml:aside", "type", "footnote"); } +void EPUBExportTest::testPopup() +{ + createDoc("popup.odt", {}); + + mpXmlDoc = parseExport("OEBPS/sections/section0001.xhtml"); + // Test image popup anchor. + assertXPath(mpXmlDoc, "//xhtml:body/xhtml:p[1]/xhtml:a", "type", "noteref"); + assertXPath(mpXmlDoc, "//xhtml:body/xhtml:p[1]/xhtml:a/xhtml:img", 1); + // Test image popup content. + assertXPath(mpXmlDoc, "//xhtml:body/xhtml:aside[1]", "type", "footnote"); + assertXPath(mpXmlDoc, "//xhtml:body/xhtml:aside[1]/xhtml:img", 1); + + // Test text popup anchor. + assertXPath(mpXmlDoc, "//xhtml:body/xhtml:p[2]/xhtml:span/xhtml:a", "type", "noteref"); + assertXPathContent(mpXmlDoc, "//xhtml:body/xhtml:p[2]/xhtml:span/xhtml:a", "link"); + // Test text popup content. + assertXPath(mpXmlDoc, "//xhtml:body/xhtml:aside[2]", "type", "footnote"); + assertXPath(mpXmlDoc, "//xhtml:body/xhtml:aside[2]/xhtml:img", 1); +} + CPPUNIT_TEST_SUITE_REGISTRATION(EPUBExportTest); } diff --git a/writerperfect/qa/unit/data/writer/epubexport/popup.odt b/writerperfect/qa/unit/data/writer/epubexport/popup.odt Binary files differnew file mode 100644 index 000000000000..30f4cc8f526e --- /dev/null +++ b/writerperfect/qa/unit/data/writer/epubexport/popup.odt diff --git a/writerperfect/qa/unit/data/writer/epubexport/popup/libreoffice.png b/writerperfect/qa/unit/data/writer/epubexport/popup/libreoffice.png Binary files differnew file mode 100644 index 000000000000..fdad35484e7c --- /dev/null +++ b/writerperfect/qa/unit/data/writer/epubexport/popup/libreoffice.png diff --git a/writerperfect/source/writer/EPUBExportFilter.cxx b/writerperfect/source/writer/EPUBExportFilter.cxx index 8463c7c88165..ba9e30d85df9 100644 --- a/writerperfect/source/writer/EPUBExportFilter.cxx +++ b/writerperfect/source/writer/EPUBExportFilter.cxx @@ -14,11 +14,15 @@ #include <libepubgen/EPUBTextGenerator.h> #include <libepubgen/libepubgen-decls.h> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#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/uno/XComponentContext.hpp> #include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <comphelper/genericpropertyset.hxx> +#include <comphelper/propertysetinfo.hxx> #include <cppuhelper/supportsservice.hxx> #include "exp/xmlimp.hxx" @@ -82,7 +86,17 @@ sal_Bool EPUBExportFilter::filter(const uno::Sequence<beans::PropertyValue> &rDe uno::Reference<xml::sax::XDocumentHandler> xExportHandler(new exp::XMLImport(mxContext, aGenerator, aSourceURL, rDescriptor)); uno::Reference<lang::XInitialization> xInitialization(mxContext->getServiceManager()->createInstanceWithContext("com.sun.star.comp.Writer.XMLOasisExporter", mxContext), uno::UNO_QUERY); - xInitialization->initialize({uno::makeAny(xExportHandler)}); + + // A subset of parameters are passed in as a property set. + comphelper::PropertyMapEntry const aInfoMap[] = + { + {OUString("BaseURI"), 0, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0}, + {OUString(), 0, css::uno::Type(), 0, 0} + }; + uno::Reference<beans::XPropertySet> xInfoSet(comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap))); + xInfoSet->setPropertyValue("BaseURI", uno::makeAny(aSourceURL)); + + xInitialization->initialize({uno::makeAny(xExportHandler), uno::makeAny(xInfoSet)}); uno::Reference<document::XExporter> xExporter(xInitialization, uno::UNO_QUERY); xExporter->setSourceDocument(mxSourceDocument); uno::Reference<document::XFilter> xFilter(xInitialization, uno::UNO_QUERY); diff --git a/writerperfect/source/writer/exp/txtparai.cxx b/writerperfect/source/writer/exp/txtparai.cxx index bfd1b2842a83..309f80ce607a 100644 --- a/writerperfect/source/writer/exp/txtparai.cxx +++ b/writerperfect/source/writer/exp/txtparai.cxx @@ -265,6 +265,9 @@ void XMLTextFrameHyperlinkContext::startElement(const OUString &/*rName*/, const FillStyles(rAttributeValue, mrImport.GetAutomaticTextStyles(), mrImport.GetTextStyles(), m_aPropertyList); else { + if (rAttributeName == "xlink:href" && mrImport.FillPopupData(rAttributeValue, aPropertyList)) + continue; + // This affects the link's properties. OString sName = OUStringToOString(rAttributeName, RTL_TEXTENCODING_UTF8); OString sValue = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8); @@ -331,6 +334,9 @@ void XMLHyperlinkContext::startElement(const OUString &/*rName*/, const css::uno FillStyles(rAttributeValue, mrImport.GetAutomaticTextStyles(), mrImport.GetTextStyles(), m_aPropertyList); else { + if (rAttributeName == "xlink:href" && mrImport.FillPopupData(rAttributeValue, aPropertyList)) + continue; + // This affects the link's properties. OString sName = OUStringToOString(rAttributeName, RTL_TEXTENCODING_UTF8); OString sValue = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8); diff --git a/writerperfect/source/writer/exp/xmlimp.cxx b/writerperfect/source/writer/exp/xmlimp.cxx index bb3d067660b7..fdbc1d398243 100644 --- a/writerperfect/source/writer/exp/xmlimp.cxx +++ b/writerperfect/source/writer/exp/xmlimp.cxx @@ -12,6 +12,7 @@ #include <initializer_list> #include <unordered_map> +#include <com/sun/star/uri/UriReferenceFactory.hpp> #include <com/sun/star/xml/sax/InputSource.hpp> #include <com/sun/star/xml/sax/Parser.hpp> #include <rtl/uri.hxx> @@ -242,7 +243,8 @@ rtl::Reference<XMLImportContext> XMLOfficeDocContext::CreateChildContext(const O XMLImport::XMLImport(const uno::Reference<uno::XComponentContext> &xContext, librevenge::RVNGTextInterface &rGenerator, const OUString &rURL, const uno::Sequence<beans::PropertyValue> &rDescriptor) : mrGenerator(rGenerator), - mxContext(xContext) + mxContext(xContext), + maDocumentBaseURL(rURL) { uno::Sequence<beans::PropertyValue> aFilterData; for (sal_Int32 i = 0; i < rDescriptor.getLength(); ++i) @@ -270,6 +272,8 @@ XMLImport::XMLImport(const uno::Reference<uno::XComponentContext> &xContext, lib } FindXMPMetadata(mxContext, rURL, aFilterData, maMetaData); + + mxUriReferenceFactory = uri::UriReferenceFactory::create(mxContext); } const librevenge::RVNGPropertyListVector &XMLImport::GetCoverImages() @@ -282,6 +286,54 @@ const librevenge::RVNGPropertyList &XMLImport::GetMetaData() return maMetaData; } +bool XMLImport::FillPopupData(const OUString &rURL, librevenge::RVNGPropertyList &rPropList) +{ + uno::Reference<uri::XUriReference> xUriRef; + try + { + xUriRef = mxUriReferenceFactory->parse(rURL); + } + catch (const uno::Exception &rException) + { + SAL_WARN("writerperfect", "XMLImport::FillPopupData: XUriReference::parse() failed:" << rException.Message); + } + bool bRelative = false; + if (xUriRef.is()) + bRelative = !xUriRef->isAbsolute(); + if (!bRelative) + return false; + + OUString aAbs; + INetURLObject aBaseURL(maDocumentBaseURL); + try + { + aAbs = rtl::Uri::convertRelToAbs(maDocumentBaseURL, aBaseURL.GetBase() + "/" + rURL); + } + catch (const rtl::MalformedUriException &rException) + { + SAL_WARN("writerperfect", "XMLImport::FillPopupData: convertRelToAbs() failed:" << rException.getMessage()); + } + if (aAbs.isEmpty()) + return false; + + SvFileStream aStream(aAbs, StreamMode::READ); + if (aStream.IsOpen()) + { + librevenge::RVNGBinaryData aBinaryData; + SvMemoryStream aMemoryStream; + aMemoryStream.WriteStream(aStream); + aBinaryData.append(static_cast<const unsigned char *>(aMemoryStream.GetBuffer()), aMemoryStream.GetSize()); + rPropList.insert("office:binary-data", aBinaryData); + + INetURLObject aAbsURL(aAbs); + OUString aMimeType = GetMimeType(aAbsURL.GetExtension()); + rPropList.insert("librevenge:mime-type", aMimeType.toUtf8().getStr()); + return true; + } + + return false; +} + rtl::Reference<XMLImportContext> XMLImport::CreateContext(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &/*xAttribs*/) { if (rName == "office:document") diff --git a/writerperfect/source/writer/exp/xmlimp.hxx b/writerperfect/source/writer/exp/xmlimp.hxx index 90a9762bb9b6..7b517cbe1325 100644 --- a/writerperfect/source/writer/exp/xmlimp.hxx +++ b/writerperfect/source/writer/exp/xmlimp.hxx @@ -17,6 +17,7 @@ #include <com/sun/star/beans/PropertyValue.hpp> #include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/uri/XUriReferenceFactory.hpp> #include <com/sun/star/xml/sax/XDocumentHandler.hpp> #include <cppuhelper/implbase.hxx> @@ -55,6 +56,8 @@ class XMLImport : public cppu::WeakImplHelper /// Author, date, etc -- overwrites what would be from the document out of the box. librevenge::RVNGPropertyList maMetaData; const css::uno::Reference<css::uno::XComponentContext> &mxContext; + css::uno::Reference<css::uri::XUriReferenceFactory> mxUriReferenceFactory; + OUString maDocumentBaseURL; public: XMLImport(const css::uno::Reference<css::uno::XComponentContext> &xContext, librevenge::RVNGTextInterface &rGenerator, const OUString &rURL, const css::uno::Sequence<css::beans::PropertyValue> &rDescriptor); @@ -78,6 +81,7 @@ public: std::map<OUString, librevenge::RVNGPropertyList> &GetGraphicStyles(); const librevenge::RVNGPropertyListVector &GetCoverImages(); const librevenge::RVNGPropertyList &GetMetaData(); + bool FillPopupData(const OUString &rURL, librevenge::RVNGPropertyList &rPropList); // XDocumentHandler void SAL_CALL startDocument() override; |