From 389f7b9581ebd6420a8b9f815807d957608ce8a8 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Wed, 29 Nov 2017 11:44:55 +0100 Subject: EPUB export: add support for cover images Pick them up from /.cover-image. as a start. Change-Id: Ie5ee7c02d6b3271e6e850ca9a2a10ed0bb4a598d Reviewed-on: https://gerrit.libreoffice.org/45483 Tested-by: Jenkins Reviewed-by: Miklos Vajna --- writerperfect/qa/unit/EPUBExportTest.cxx | 5 ++ .../data/writer/epubexport/meta.cover-image.png | Bin 0 -> 766 bytes writerperfect/source/writer/EPUBExportFilter.cxx | 7 +- writerperfect/source/writer/exp/xmlimp.cxx | 92 ++++++++++++++++++++- writerperfect/source/writer/exp/xmlimp.hxx | 5 +- writerperfect/source/writer/exp/xmlmetai.cxx | 1 + 6 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 writerperfect/qa/unit/data/writer/epubexport/meta.cover-image.png (limited to 'writerperfect') diff --git a/writerperfect/qa/unit/EPUBExportTest.cxx b/writerperfect/qa/unit/EPUBExportTest.cxx index c8fe9a3491bd..e038a7ef6135 100644 --- a/writerperfect/qa/unit/EPUBExportTest.cxx +++ b/writerperfect/qa/unit/EPUBExportTest.cxx @@ -326,6 +326,11 @@ void EPUBExportTest::testMeta() assertXPathContent(mpXmlDoc, "/opf:package/opf:metadata/dc:title", "Title"); assertXPathContent(mpXmlDoc, "/opf:package/opf:metadata/dc:language", "hu"); assertXPathContent(mpXmlDoc, "/opf:package/opf:metadata/opf:meta[@property='dcterms:modified']", "2017-09-27T09:51:19Z"); + + // Make sure that cover image next to the source document is picked up. + assertXPath(mpXmlDoc, "/opf:package/opf:manifest/opf:item[@href='images/image0001.png']", "properties", "cover-image"); + assertXPath(mpXmlDoc, "/opf:package/opf:manifest/opf:item[@href='images/image0001.png']", "media-type", "image/png"); + CPPUNIT_ASSERT(mxZipFile->hasByName("OEBPS/images/image0001.png")); } void EPUBExportTest::testParaNamedstyle() diff --git a/writerperfect/qa/unit/data/writer/epubexport/meta.cover-image.png b/writerperfect/qa/unit/data/writer/epubexport/meta.cover-image.png new file mode 100644 index 000000000000..fdad35484e7c Binary files /dev/null and b/writerperfect/qa/unit/data/writer/epubexport/meta.cover-image.png differ diff --git a/writerperfect/source/writer/EPUBExportFilter.cxx b/writerperfect/source/writer/EPUBExportFilter.cxx index b17c57aa784e..2454adddc781 100644 --- a/writerperfect/source/writer/EPUBExportFilter.cxx +++ b/writerperfect/source/writer/EPUBExportFilter.cxx @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -74,7 +75,11 @@ sal_Bool EPUBExportFilter::filter(const uno::Sequence &rDe , nVersion #endif ); - uno::Reference xExportHandler(new exp::XMLImport(aGenerator)); + OUString aSourceURL; + uno::Reference xSourceModel(mxSourceDocument, uno::UNO_QUERY); + if (xSourceModel.is()) + aSourceURL = xSourceModel->getURL(); + uno::Reference xExportHandler(new exp::XMLImport(aGenerator, aSourceURL, rDescriptor)); uno::Reference xInitialization(mxContext->getServiceManager()->createInstanceWithContext("com.sun.star.comp.Writer.XMLOasisExporter", mxContext), uno::UNO_QUERY); xInitialization->initialize({uno::makeAny(xExportHandler)}); diff --git a/writerperfect/source/writer/exp/xmlimp.cxx b/writerperfect/source/writer/exp/xmlimp.cxx index 30a7ee03d404..3d7f99cc399e 100644 --- a/writerperfect/source/writer/exp/xmlimp.cxx +++ b/writerperfect/source/writer/exp/xmlimp.cxx @@ -9,6 +9,13 @@ #include "xmlimp.hxx" +#include +#include + +#include +#include +#include + #include "xmlfmt.hxx" #include "xmlictxt.hxx" #include "xmlmetai.hxx" @@ -21,6 +28,70 @@ namespace writerperfect namespace exp { +namespace +{ +/// Looks up mime type for a given image extension. +OUString GetMimeType(const OUString &rExtension) +{ + static const std::unordered_map vMimeTypes = + { + {"gif", "image/gif"}, + {"jpg", "image/jpeg"}, + {"png", "image/png"}, + {"svg", "image/svg+xml"}, + }; + + auto it = vMimeTypes.find(rExtension); + return it == vMimeTypes.end() ? OUString() : it->second; +} + +/// Picks up a cover image from the base directory. +OUString FindCoverImage(const OUString &rDocumentBaseURL, OUString &rMimeType) +{ + OUString aRet; + + if (rDocumentBaseURL.isEmpty()) + return aRet; + + INetURLObject aDocumentBaseURL(rDocumentBaseURL); + + static const std::initializer_list vExtensions = + { + "gif", + "jpg", + "png", + "svg" + }; + + for (const auto &rExtension : vExtensions) + { + try + { + aRet = rtl::Uri::convertRelToAbs(rDocumentBaseURL, aDocumentBaseURL.GetBase() + ".cover-image." + rExtension); + } + catch (const rtl::MalformedUriException &rException) + { + SAL_WARN("writerfilter", "FindCoverImage: convertRelToAbs() failed:" << rException.getMessage()); + } + + if (!aRet.isEmpty()) + { + SvFileStream aStream(aRet, StreamMode::READ); + if (aStream.IsOpen()) + { + rMimeType = GetMimeType(rExtension); + // File exists. + return aRet; + } + else + aRet.clear(); + } + } + + return aRet; +} +} + /// Handler for . class XMLBodyContext : public XMLImportContext { @@ -71,9 +142,28 @@ rtl::Reference XMLOfficeDocContext::CreateChildContext(const O return nullptr; } -XMLImport::XMLImport(librevenge::RVNGTextInterface &rGenerator) +XMLImport::XMLImport(librevenge::RVNGTextInterface &rGenerator, const OUString &rURL, const uno::Sequence &/*rDescriptor*/) : mrGenerator(rGenerator) { + OUString aMimeType; + OUString aCoverImage = FindCoverImage(rURL, aMimeType); + if (!aCoverImage.isEmpty()) + { + librevenge::RVNGBinaryData aBinaryData; + SvFileStream aStream(aCoverImage, StreamMode::READ); + SvMemoryStream aMemoryStream; + aMemoryStream.WriteStream(aStream); + aBinaryData.append(static_cast(aMemoryStream.GetBuffer()), aMemoryStream.GetSize()); + librevenge::RVNGPropertyList aCoverImageProperties; + aCoverImageProperties.insert("office:binary-data", aBinaryData); + aCoverImageProperties.insert("librevenge:mime-type", aMimeType.toUtf8().getStr()); + maCoverImages.append(aCoverImageProperties); + } +} + +const librevenge::RVNGPropertyListVector &XMLImport::GetCoverImages() +{ + return maCoverImages; } rtl::Reference XMLImport::CreateContext(const OUString &rName, const css::uno::Reference &/*xAttribs*/) diff --git a/writerperfect/source/writer/exp/xmlimp.hxx b/writerperfect/source/writer/exp/xmlimp.hxx index e1b80571d278..b1008f00dbf0 100644 --- a/writerperfect/source/writer/exp/xmlimp.hxx +++ b/writerperfect/source/writer/exp/xmlimp.hxx @@ -15,6 +15,7 @@ #include +#include #include #include @@ -49,9 +50,10 @@ class XMLImport : public cppu::WeakImplHelper std::map maTableStyles; std::map maAutomaticGraphicStyles; std::map maGraphicStyles; + librevenge::RVNGPropertyListVector maCoverImages; public: - XMLImport(librevenge::RVNGTextInterface &rGenerator); + XMLImport(librevenge::RVNGTextInterface &rGenerator, const OUString &rURL, const css::uno::Sequence &rDescriptor); rtl::Reference CreateContext(const OUString &rName, const css::uno::Reference &xAttribs); @@ -70,6 +72,7 @@ public: std::map &GetRowStyles(); std::map &GetTableStyles(); std::map &GetGraphicStyles(); + const librevenge::RVNGPropertyListVector &GetCoverImages(); // XDocumentHandler void SAL_CALL startDocument() override; diff --git a/writerperfect/source/writer/exp/xmlmetai.cxx b/writerperfect/source/writer/exp/xmlmetai.cxx index 0d804833bc7a..ad39aa8c39f1 100644 --- a/writerperfect/source/writer/exp/xmlmetai.cxx +++ b/writerperfect/source/writer/exp/xmlmetai.cxx @@ -131,6 +131,7 @@ void XMLMetaInitialCreatorContext::characters(const OUString &rChars) XMLMetaDocumentContext::XMLMetaDocumentContext(XMLImport &rImport) : XMLImportContext(rImport) { + m_aPropertyList.insert("librevenge:cover-images", mrImport.GetCoverImages()); } rtl::Reference XMLMetaDocumentContext::CreateChildContext(const OUString &rName, const css::uno::Reference &/*xAttribs*/) -- cgit