comphelper/Library_comphelper.mk                    |    1 
 comphelper/source/misc/graphicmimetype.cxx          |  105 ++++++++++++++++++++
 filter/source/xslt/odf2xhtml/export/common/body.xsl |   52 +++++----
 filter/source/xslt/odf2xhtml/export/xhtml/body.xsl  |   50 +++++----
 include/comphelper/graphicmimetype.hxx              |   35 ++++++
 include/xmloff/xmlexp.hxx                           |    2 
 svx/source/svdraw/svdograf.cxx                      |    5 
 sw/CppunitTest_sw_fodfexport.mk                     |   57 ++++++++++
 sw/Module_sw.mk                                     |    1 
 sw/qa/extras/fodfexport/data/tdf113696.odt          |binary
 sw/qa/extras/fodfexport/fodfexport.cxx              |   44 ++++++++
 sw/qa/extras/inc/swmodeltestbase.hxx                |   11 ++
 sw/qa/extras/odfexport/data/image-mimetype.odt      |binary
 sw/qa/extras/odfexport/odfexport.cxx                |   10 +
 xmloff/source/core/xmlexp.cxx                       |   18 +++
 xmloff/source/draw/shapeexport.cxx                  |   26 ++++
 xmloff/source/text/txtparae.cxx                     |   10 +
 17 files changed, 378 insertions(+), 49 deletions(-)

New commits:
commit a62d4111fd8f740612f4fd4a7ffabb72776c929a
Author: Samuel Mehrbrodt <samuel.mehrbr...@cib.de>
Date:   Thu Nov 30 10:28:33 2017 +0100

    Unit test for tdf#113696
    
    Change-Id: I566cd5d38cf86547b664f0ae9a1c2f8c37edc0ca
    Reviewed-on: https://gerrit.libreoffice.org/45560
    Tested-by: Jenkins <c...@libreoffice.org>
    Reviewed-by: Samuel Mehrbrodt <samuel.mehrbr...@cib.de>

diff --git a/sw/CppunitTest_sw_fodfexport.mk b/sw/CppunitTest_sw_fodfexport.mk
new file mode 100644
index 000000000000..4703b85435f7
--- /dev/null
+++ b/sw/CppunitTest_sw_fodfexport.mk
@@ -0,0 +1,57 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,sw_fodfexport))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,sw_fodfexport, \
+       sw/qa/extras/fodfexport/fodfexport \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,sw_fodfexport, \
+       comphelper \
+       cppu \
+       cppuhelper \
+       sal \
+       sfx \
+       sw \
+       test \
+       tl \
+       unotest \
+       utl \
+       vcl \
+))
+
+$(eval $(call gb_CppunitTest_use_externals,sw_fodfexport,\
+       boost_headers \
+       libxml2 \
+))
+
+$(eval $(call gb_CppunitTest_set_include,sw_fodfexport,\
+       -I$(SRCDIR)/sw/inc \
+       -I$(SRCDIR)/sw/source/core/inc \
+       -I$(SRCDIR)/sw/qa/extras/inc \
+       $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,sw_fodfexport))
+
+$(eval $(call gb_CppunitTest_use_ure,sw_fodfexport))
+$(eval $(call gb_CppunitTest_use_vcl,sw_fodfexport))
+
+$(eval $(call gb_CppunitTest_use_rdb,sw_fodfexport,services))
+
+$(eval $(call gb_CppunitTest_use_custom_headers,sw_fodfexport,\
+       officecfg/registry \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,sw_fodfexport))
+
+# vim: set noet sw=4 ts=4:
diff --git a/sw/Module_sw.mk b/sw/Module_sw.mk
index f4371dfa20cf..a9de6cd82943 100644
--- a/sw/Module_sw.mk
+++ b/sw/Module_sw.mk
@@ -49,6 +49,7 @@ $(eval $(call gb_Module_add_slowcheck_targets,sw,\
        $(if $(and $(filter $(COM),MSC),$(MERGELIBS)),, \
                CppunitTest_sw_uwriter) \
     CppunitTest_sw_docbookexport \
+    CppunitTest_sw_fodfexport \
     CppunitTest_sw_htmlexport \
     CppunitTest_sw_htmlimport \
     CppunitTest_sw_macros_test \
diff --git a/sw/qa/extras/fodfexport/data/tdf113696.odt 
b/sw/qa/extras/fodfexport/data/tdf113696.odt
new file mode 100644
index 000000000000..03e0612a3d14
Binary files /dev/null and b/sw/qa/extras/fodfexport/data/tdf113696.odt differ
diff --git a/sw/qa/extras/fodfexport/fodfexport.cxx 
b/sw/qa/extras/fodfexport/fodfexport.cxx
new file mode 100644
index 000000000000..6cd00b49ba47
--- /dev/null
+++ b/sw/qa/extras/fodfexport/fodfexport.cxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <swmodeltestbase.hxx>
+
+class Test : public SwModelTestBase
+{
+public:
+    Test()
+        : SwModelTestBase("/sw/qa/extras/fodfexport/data/", "OpenDocument Text 
Flat XML")
+    {
+    }
+
+    /**
+     * Blacklist handling
+     */
+    bool mustTestImportOf(const char* filename) const override
+    {
+        // Only test import of .fodt document
+        return OString(filename).endsWith(".odt") || 
OString(filename).endsWith(".fodt");
+    }
+};
+
+DECLARE_FODFEXPORT_TEST(testTdf113696, "tdf113696.odt")
+{
+    // Test that an image which is written in svm format (image/x-vclgraphic)
+    // is accompanied by a png fallback graphic.
+    if (xmlDocPtr pXmlDoc = parseExportedFile())
+    {
+        assertXPath(pXmlDoc, 
"/office:document/office:body/office:text/text:p/draw:frame/"
+                             
"draw:image[@loext:mime-type='image/x-vclgraphic']");
+        assertXPath(pXmlDoc, 
"/office:document/office:body/office:text/text:p/draw:frame/"
+                             "draw:image[@loext:mime-type='image/png']");
+    }
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/inc/swmodeltestbase.hxx 
b/sw/qa/extras/inc/swmodeltestbase.hxx
index fca647b6b6d0..69578263d846 100644
--- a/sw/qa/extras/inc/swmodeltestbase.hxx
+++ b/sw/qa/extras/inc/swmodeltestbase.hxx
@@ -91,6 +91,7 @@ using namespace css;
 #define DECLARE_RTFEXPORT_TEST(TestName, filename) 
DECLARE_SW_ROUNDTRIP_TEST(TestName, filename, Test)
 #define DECLARE_ODFIMPORT_TEST(TestName, filename) 
DECLARE_SW_IMPORT_TEST(TestName, filename, Test)
 #define DECLARE_ODFEXPORT_TEST(TestName, filename) 
DECLARE_SW_ROUNDTRIP_TEST(TestName, filename, Test)
+#define DECLARE_FODFEXPORT_TEST(TestName, filename) 
DECLARE_SW_ROUNDTRIP_TEST(TestName, filename, Test)
 #define DECLARE_WW8EXPORT_TEST(TestName, filename) 
DECLARE_SW_ROUNDTRIP_TEST(TestName, filename, Test)
 
 #define DECLARE_SW_IMPORT_TEST(TestName, filename, BaseClass) \
@@ -698,6 +699,16 @@ protected:
         return parseExportInternal( maTempFile.GetURL(), rStreamName );
     }
 
+    /**
+     * Returns an xml stream of a an exported file.
+     * To be used when the exporter doesn't create zip archives, but single 
files
+     * (like Flat ODF Export)
+     */
+    xmlDocPtr parseExportedFile()
+    {
+        return parseXmlStream(maTempFile.GetStream(StreamMode::READ));
+    }
+
     xmlDocPtr parseExportInternal( const OUString& url, const OUString& 
rStreamName )
     {
         // Read the XML stream we're interested in.
commit f717460c16cb558e8049f906771fe223b6eb69f9
Author: Samuel Mehrbrodt <samuel.mehrbr...@cib.de>
Date:   Fri Dec 1 09:35:41 2017 +0100

    tdf#113696 XHTML Export: Prefer fallback graphic
    
    Which is usually png and browsers can read that,
    but they can't read our internal metafile format (svm)
    
    Change-Id: Idfd82da630ead69f508b74285081e32315030825
    Reviewed-on: https://gerrit.libreoffice.org/45590
    Tested-by: Jenkins <c...@libreoffice.org>
    Reviewed-by: Samuel Mehrbrodt <samuel.mehrbr...@cib.de>

diff --git a/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl 
b/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl
index 8cce4595d3ea..f594ebcd29e5 100644
--- a/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl
+++ b/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl
@@ -1487,27 +1487,32 @@
        <xsl:template match="draw:image | draw:object-ole">
                <xsl:param name="globalData"/>
 
-               <xsl:choose>
-                       <xsl:when test="ancestor::text:p or parent::text:span 
or parent::text:h or parent::draw:a or parent::text:a or text:ruby-base">
-                               <!-- XHTML does not allow the mapped elements 
to contain paragraphs -->
-                               <xsl:call-template name="create-image-element">
-                                       <xsl:with-param name="globalData" 
select="$globalData"/>
-                               </xsl:call-template>
-                       </xsl:when>
-                       <xsl:otherwise>
-                               <!-- images are embedded in a paragraph, but 
are in CSS not able to express a horizontal alignment for themself.
-                                       A 'div' element taking over the image 
style would solve that problem, but is invalid as child of a paragraph -->
-                               <xsl:element name="p">
-                                       <xsl:apply-templates 
select="@draw:style-name">
-                                               <xsl:with-param 
name="globalData" select="$globalData"/>
-                                       </xsl:apply-templates>
-
-                                       <xsl:call-template 
name="create-image-element">
-                                               <xsl:with-param 
name="globalData" select="$globalData"/>
-                                       </xsl:call-template>
-                               </xsl:element>
-                       </xsl:otherwise>
-               </xsl:choose>
+        <!-- If there is a replacement graphic, we take it.
+             It is a png which browsers are more likely able to render than 
the original graphic
+             which might have arbitrary formats. -->
+        <xsl:if test="not(following-sibling::draw:image)">
+            <xsl:choose>
+                <xsl:when test="ancestor::text:p or parent::text:span or 
parent::text:h or parent::draw:a or parent::text:a or text:ruby-base">
+                    <!-- XHTML does not allow the mapped elements to contain 
paragraphs -->
+                    <xsl:call-template name="create-image-element">
+                        <xsl:with-param name="globalData" 
select="$globalData"/>
+                    </xsl:call-template>
+                </xsl:when>
+                <xsl:otherwise>
+                    <!-- images are embedded in a paragraph, but are in CSS 
not able to express a horizontal alignment for themself.
+                        A 'div' element taking over the image style would 
solve that problem, but is invalid as child of a paragraph -->
+                    <xsl:element name="p">
+                        <xsl:apply-templates select="@draw:style-name">
+                            <xsl:with-param name="globalData" 
select="$globalData"/>
+                        </xsl:apply-templates>
+
+                        <xsl:call-template name="create-image-element">
+                            <xsl:with-param name="globalData" 
select="$globalData"/>
+                        </xsl:call-template>
+                    </xsl:element>
+                </xsl:otherwise>
+            </xsl:choose>
+        </xsl:if>
        </xsl:template>
 
        <xsl:template name="create-image-element">
commit bdf1f65efad90a727b51ab3cb69d0af69d7eb1cb
Author: Samuel Mehrbrodt <samuel.mehrbr...@cib.de>
Date:   Thu Nov 30 14:36:14 2017 +0100

    tdf#113696 Add mimetype also to fallback graphic
    
    Change-Id: I6eb7bb66aa688b5668d0eacd2ec7131bec2b6955
    Reviewed-on: https://gerrit.libreoffice.org/45585
    Tested-by: Jenkins <c...@libreoffice.org>
    Reviewed-by: Samuel Mehrbrodt <samuel.mehrbr...@cib.de>

diff --git a/xmloff/source/draw/shapeexport.cxx 
b/xmloff/source/draw/shapeexport.cxx
index 0f961a95aa3e..1fe976433eae 100644
--- a/xmloff/source/draw/shapeexport.cxx
+++ b/xmloff/source/draw/shapeexport.cxx
@@ -2387,6 +2387,13 @@ void XMLShapeExport::ImpExportGraphicObjectShape(
                         mrExport.AddAttribute(XML_NAMESPACE_XLINK, 
XML_ACTUATE, XML_ONLOAD );
                     }
 
+                    uno::Reference<io::XInputStream> xInputStream(
+                        
mrExport.GetEmbeddedGraphicObjectStream(aReplacementUrl));
+                    OUString aMimeType(
+                        
comphelper::GraphicMimeTypeHelper::GetMimeTypeForImageStream(xInputStream));
+                    if (!aMimeType.isEmpty())
+                        GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, 
"mime-type", aMimeType);
+
                      SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, 
XML_IMAGE, true, true);
 
                     // optional office:binary-data
commit 7d12302c671dd86a247f8b669fd31fcbe8a641bd
Author: Samuel Mehrbrodt <samuel.mehrbr...@cib.de>
Date:   Thu Nov 30 12:45:26 2017 +0100

    tdf#113696 Write replacement graphic also to flat odf
    
    Not only to zipped ODF
    
    Change-Id: Ic86656aea31c9fc20862628cdd31698b9904e999
    Reviewed-on: https://gerrit.libreoffice.org/45568
    Tested-by: Jenkins <c...@libreoffice.org>
    Reviewed-by: Samuel Mehrbrodt <samuel.mehrbr...@cib.de>

diff --git a/xmloff/source/draw/shapeexport.cxx 
b/xmloff/source/draw/shapeexport.cxx
index 2a010f9cfd15..0f961a95aa3e 100644
--- a/xmloff/source/draw/shapeexport.cxx
+++ b/xmloff/source/draw/shapeexport.cxx
@@ -2385,13 +2385,12 @@ void XMLShapeExport::ImpExportGraphicObjectShape(
                         mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, 
XML_SIMPLE );
                         mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, 
XML_EMBED );
                         mrExport.AddAttribute(XML_NAMESPACE_XLINK, 
XML_ACTUATE, XML_ONLOAD );
+                    }
 
-                        // xlink:href for replacement, only written for Svg 
content
-                        SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, 
XML_IMAGE, true, true);
+                     SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, 
XML_IMAGE, true, true);
 
-                        // optional office:binary-data
-                        
mrExport.AddEmbeddedGraphicObjectAsBase64(aReplacementUrl);
-                    }
+                    // optional office:binary-data
+                    mrExport.AddEmbeddedGraphicObjectAsBase64(aReplacementUrl);
                 }
             }
         }
commit b12d18575b2a92bf3ed707a14378bb65f56ae423
Author: Samuel Mehrbrodt <samuel.mehrbr...@cib.de>
Date:   Thu Nov 30 12:42:10 2017 +0100

    Related tdf#72966 Provide replacement graphic also for metafiles
    
    With this, SVM files are still written to ODF, but accompanied
    by a replacement png graphic.
    
    Change-Id: I2c949f100dd5197a10c741baa42ea740f3a1415a
    Reviewed-on: https://gerrit.libreoffice.org/45567
    Tested-by: Jenkins <c...@libreoffice.org>
    Reviewed-by: Armin Le Grand <armin.le.gr...@cib.de>
    Reviewed-by: Thorsten Behrens <thorsten.behr...@cib.de>

diff --git a/svx/source/svdraw/svdograf.cxx b/svx/source/svdraw/svdograf.cxx
index ad51e4a6af38..656b3f8c61cb 100644
--- a/svx/source/svdraw/svdograf.cxx
+++ b/svx/source/svdraw/svdograf.cxx
@@ -446,6 +446,11 @@ const GraphicObject* 
SdrGrafObj::GetReplacementGraphicObject() const
         {
             const_cast< SdrGrafObj* >(this)->mpReplacementGraphic = new 
GraphicObject(rSvgDataPtr->getReplacement());
         }
+        else if (pGraphic->GetGraphic().GetType() == GRAPHIC_GDIMETAFILE)
+        {
+            // Replacement graphic for PDF and metafiles is just the bitmap.
+            const_cast<SdrGrafObj*>(this)->mpReplacementGraphic = new 
GraphicObject(pGraphic->GetGraphic().GetBitmapEx());
+        }
     }
 
     return mpReplacementGraphic;
commit ee28a7908f42775d135bd87d83c27671b27c110e
Author: Samuel Mehrbrodt <samuel.mehrbr...@cib.de>
Date:   Wed Nov 29 21:12:32 2017 +0100

    tdf#113696 Add mimetype to image element
    
    Otherwise browsers don't recognize base64 encoded svg files.
    
    Change-Id: I54d0b87c52a1ca9da1d820751ae32159b88ed28f

diff --git a/comphelper/Library_comphelper.mk b/comphelper/Library_comphelper.mk
index 4d4e7345298d..c267711126da 100644
--- a/comphelper/Library_comphelper.mk
+++ b/comphelper/Library_comphelper.mk
@@ -91,6 +91,7 @@ $(eval $(call gb_Library_add_exception_objects,comphelper,\
     comphelper/source/misc/evtmethodhelper \
     comphelper/source/misc/fileurl \
     comphelper/source/misc/getexpandeduri \
+    comphelper/source/misc/graphicmimetype \
     comphelper/source/misc/instancelocker \
     comphelper/source/misc/interaction \
     comphelper/source/misc/listenernotification \
diff --git a/comphelper/source/misc/graphicmimetype.cxx 
b/comphelper/source/misc/graphicmimetype.cxx
new file mode 100644
index 000000000000..bf88312304b1
--- /dev/null
+++ b/comphelper/source/misc/graphicmimetype.cxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <comphelper/graphicmimetype.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/graphic/GraphicProvider.hpp>
+#include <com/sun/star/graphic/XGraphicProvider.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <comphelper/processfactory.hxx>
+
+using namespace css;
+using namespace css::beans;
+using namespace css::graphic;
+using namespace css::io;
+using namespace css::uno;
+
+namespace comphelper
+{
+OUString GraphicMimeTypeHelper::GetMimeTypeForExtension(const OString& rExt)
+{
+    struct XMLGraphicMimeTypeMapper
+    {
+        const char* pExt;
+        const char* pMimeType;
+    };
+
+    static const XMLGraphicMimeTypeMapper aMapper[]
+        = { { "gif", "image/gif" },   { "png", "image/png" },     { "jpg", 
"image/jpeg" },
+            { "tif", "image/tiff" },  { "svg", "image/svg+xml" }, { "pdf", 
"application/pdf" },
+            { "wmf", "image/x-wmf" }, { "eps", "image/x-eps" },   { "bmp", 
"image/bmp" },
+            { "pct", "image/x-pict" } };
+
+    OUString aMimeType;
+
+    long const nCount = SAL_N_ELEMENTS(aMapper);
+    for (long i = 0; (i < nCount) && aMimeType.isEmpty(); ++i)
+    {
+        if (rExt == aMapper[i].pExt)
+            aMimeType = OUString(aMapper[i].pMimeType, 
strlen(aMapper[i].pMimeType),
+                                 RTL_TEXTENCODING_ASCII_US);
+    }
+
+    return aMimeType;
+}
+
+OUString GraphicMimeTypeHelper::GetMimeTypeForXGraphic(Reference<XGraphic> 
xGraphic)
+{
+    OUString aSourceMimeType;
+    Reference<XPropertySet> const xGraphicPropertySet(xGraphic, UNO_QUERY);
+    if (xGraphicPropertySet.is() && // it's null if it's an external link
+        (xGraphicPropertySet->getPropertyValue("MimeType") >>= 
aSourceMimeType))
+    {
+        return aSourceMimeType;
+    }
+    return OUString("");
+}
+
+OUString GraphicMimeTypeHelper::GetMimeTypeForImageUrl(const OUString& 
rImageUrl)
+{
+    // Create the graphic to retrieve the mimetype from it
+    Reference<XGraphicProvider> xProvider
+        = 
css::graphic::GraphicProvider::create(comphelper::getProcessComponentContext());
+    Sequence<PropertyValue> aMediaProperties(1);
+    aMediaProperties[0].Name = "URL";
+    aMediaProperties[0].Value <<= rImageUrl;
+    Reference<XGraphic> xGraphic(xProvider->queryGraphic(aMediaProperties));
+
+    return GetMimeTypeForXGraphic(xGraphic);
+}
+
+OUString 
GraphicMimeTypeHelper::GetMimeTypeForImageStream(Reference<XInputStream> 
xInputStream)
+{
+    // Create the graphic to retrieve the mimetype from it
+    Reference<XGraphicProvider> xProvider
+        = 
css::graphic::GraphicProvider::create(comphelper::getProcessComponentContext());
+    Sequence<PropertyValue> aMediaProperties(1);
+    aMediaProperties[0].Name = "InputStream";
+    aMediaProperties[0].Value <<= xInputStream;
+    Reference<XGraphic> xGraphic(xProvider->queryGraphic(aMediaProperties));
+
+    return GetMimeTypeForXGraphic(xGraphic);
+}
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/comphelper/graphicmimetype.hxx 
b/include/comphelper/graphicmimetype.hxx
new file mode 100644
index 000000000000..970342f2e5f5
--- /dev/null
+++ b/include/comphelper/graphicmimetype.hxx
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_COMPHELPER_GMH_HXX
+#define INCLUDED_COMPHELPER_GMH_HXX
+
+#include <comphelper/comphelperdllapi.h>
+#include <rtl/ustring.hxx>
+
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+
+namespace comphelper
+{
+class COMPHELPER_DLLPUBLIC GraphicMimeTypeHelper
+{
+public:
+    static OUString GetMimeTypeForExtension(const OString& rExt);
+    static OUString 
GetMimeTypeForXGraphic(css::uno::Reference<css::graphic::XGraphic> xGraphic);
+    static OUString GetMimeTypeForImageUrl(const OUString& rImageUrl);
+    static OUString
+    GetMimeTypeForImageStream(css::uno::Reference<css::io::XInputStream> 
xInputStream);
+};
+}
+
+#endif // INCLUDED_COMPHELPER_GMH_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/xmloff/xmlexp.hxx b/include/xmloff/xmlexp.hxx
index 41e8ddd8d417..f95e71d86a38 100644
--- a/include/xmloff/xmlexp.hxx
+++ b/include/xmloff/xmlexp.hxx
@@ -468,6 +468,8 @@ public:
 
     OUString AddEmbeddedGraphicObject(
                             const OUString& rGraphicObjectURL );
+    css::uno::Reference<css::io::XInputStream> GetEmbeddedGraphicObjectStream(
+        const OUString& rGraphicObjectURL);
     bool AddEmbeddedGraphicObjectAsBase64(
                             const OUString& rGraphicObjectURL );
 
diff --git a/xmloff/source/core/xmlexp.cxx b/xmloff/source/core/xmlexp.cxx
index 8ed21181dff9..484216087e0d 100644
--- a/xmloff/source/core/xmlexp.cxx
+++ b/xmloff/source/core/xmlexp.cxx
@@ -1901,6 +1901,24 @@ OUString SvXMLExport::AddEmbeddedGraphicObject( const 
OUString& rGraphicObjectUR
     return sRet;
 }
 
+Reference< XInputStream > SvXMLExport::GetEmbeddedGraphicObjectStream( const 
OUString& rGraphicObjectURL )
+{
+    if( (getExportFlags() & SvXMLExportFlags::EMBEDDED) &&
+        rGraphicObjectURL.startsWith( msGraphicObjectProtocol ) &&
+        mxGraphicResolver.is() )
+    {
+        Reference< XBinaryStreamResolver > xStmResolver( mxGraphicResolver, 
UNO_QUERY );
+
+        if( xStmResolver.is() )
+        {
+            Reference< XInputStream > xIn( xStmResolver->getInputStream( 
rGraphicObjectURL ) );
+            return xIn;
+        }
+    }
+
+    return nullptr;
+}
+
 bool SvXMLExport::AddEmbeddedGraphicObjectAsBase64( const OUString& 
rGraphicObjectURL )
 {
     bool bRet = false;
diff --git a/xmloff/source/draw/shapeexport.cxx 
b/xmloff/source/draw/shapeexport.cxx
index 04fb1772064f..2a010f9cfd15 100644
--- a/xmloff/source/draw/shapeexport.cxx
+++ b/xmloff/source/draw/shapeexport.cxx
@@ -82,6 +82,7 @@
 #include <com/sun/star/document/XStorageBasedDocument.hpp>
 
 #include <comphelper/classids.hxx>
+#include <comphelper/graphicmimetype.hxx>
 #include <comphelper/processfactory.hxx>
 #include <comphelper/storagehelper.hxx>
 
@@ -2346,6 +2347,15 @@ void XMLShapeExport::ImpExportGraphicObjectShape(
             }
 
             {
+                // We can't guess the mimetype from sImageURL because the 
image type might be changed
+                // while creating the stream (by SvXMLGraphicInputStream). So 
we first need to create
+                // the stream, get the mime type and then write the stream.
+                uno::Reference<io::XInputStream> xInputStream(
+                    mrExport.GetEmbeddedGraphicObjectStream(sImageURL));
+                OUString aMimeType(
+                    
comphelper::GraphicMimeTypeHelper::GetMimeTypeForImageStream(xInputStream));
+                GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, "mime-type", 
aMimeType);
+
                 SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, 
XML_IMAGE, true, true);
 
                 if( !sImageURL.isEmpty() )
diff --git a/xmloff/source/text/txtparae.cxx b/xmloff/source/text/txtparae.cxx
index 12355f2a254a..462f655d642f 100644
--- a/xmloff/source/text/txtparae.cxx
+++ b/xmloff/source/text/txtparae.cxx
@@ -113,7 +113,7 @@
 #include <vector>
 #include <algorithm>
 #include <iterator>
-#include <comphelper/processfactory.hxx>
+#include <comphelper/graphicmimetype.hxx>
 
 using namespace ::std;
 using namespace ::com::sun::star;
@@ -3046,22 +3046,6 @@ void XMLTextParagraphExport::exportContour(
                               true, true );
 }
 
-static OUString getMimeType(const OUString& sImageUrl)
-{
-    // Create the graphic to retrieve the mimetype from it
-    Reference< XGraphicProvider > xProvider = 
css::graphic::GraphicProvider::create(comphelper::getProcessComponentContext());
-    Sequence< PropertyValue > aMediaProperties( 1 );
-    aMediaProperties[0].Name = "URL";
-    aMediaProperties[0].Value <<= sImageUrl;
-    Reference< XGraphic > xGraphic( xProvider->queryGraphic( aMediaProperties 
) );
-
-    OUString aSourceMimeType;
-    Reference< XPropertySet > xGraphicPropertySet( xGraphic, UNO_QUERY_THROW );
-    if ( xGraphicPropertySet->getPropertyValue( "MimeType" ) >>= 
aSourceMimeType )
-        return aSourceMimeType;
-    return OUString("");
-}
-
 void XMLTextParagraphExport::_exportTextGraphic(
         const Reference < XPropertySet > & rPropSet,
         const Reference < XPropertySetInfo > & rPropSetInfo )
@@ -3124,7 +3108,7 @@ void XMLTextParagraphExport::_exportTextGraphic(
                                   sGrfFilter );
 
     // Add mimetype to make it easier for readers to get the base64 image type 
right, tdf#109202
-    OUString aSourceMimeType = getMimeType(sOrigURL);
+    OUString aSourceMimeType = 
comphelper::GraphicMimeTypeHelper::GetMimeTypeForImageUrl(sOrigURL);
     if ( !aSourceMimeType.isEmpty() )
         GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, "mime-type", 
aSourceMimeType);
 
commit a3523631dbc46a80b77696a1ed53530e70b76374
Author: Samuel Mehrbrodt <samuel.mehrbr...@cib.de>
Date:   Mon Jul 24 15:46:06 2017 +0200

    tdf#109202 Add mimetype to image element
    
    Browsers don't recognize base64 svg if the mimetype is missing.
    So we add the image mimetype to our flat odf export, which the xhtml
    export uses and transforms it into an xhtml document.
    
    Change-Id: I21aafdb97b4104e14e2d40abda73a526bb37041a
    Reviewed-on: https://gerrit.libreoffice.org/40371
    Reviewed-by: Michael Stahl <mst...@redhat.com>
    Tested-by: Samuel Mehrbrodt <samuel.mehrbr...@cib.de>

diff --git a/filter/source/xslt/odf2xhtml/export/common/body.xsl 
b/filter/source/xslt/odf2xhtml/export/common/body.xsl
index 3196facc8092..05b78a5ed43e 100644
--- a/filter/source/xslt/odf2xhtml/export/common/body.xsl
+++ b/filter/source/xslt/odf2xhtml/export/common/body.xsl
@@ -1,21 +1,21 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements. See the NOTICE file distributed
- *   with this work for additional information regarding copyright
- *   ownership. The ASF licenses this file to you under the Apache
- *   License, Version 2.0 (the "License"); you may not use this file
- *   except in compliance with the License. You may obtain a copy of
- *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
- -->
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
 <!--
        For further documentation and updates visit 
http://xml.openoffice.org/odf2xhtml
 -->
@@ -317,6 +317,7 @@
 
        <xsl:template name="create-href">
                <xsl:param name="href"/>
+               <xsl:param name="mimetype"/>
 
                <xsl:choose>
                        <!-- internal OOo URL used in content tables -->
@@ -332,7 +333,14 @@
                                <xsl:value-of select="concat('a_', 
translate(normalize-space($title), '.,;: %()[]/\+', '_____________'))"/>
                        </xsl:when>
                        <xsl:when test="self::draw:image[office:binary-data]">
-                               
<xsl:text>data:image/*;base64,</xsl:text><xsl:value-of 
select="office:binary-data"/>
+                <xsl:choose>
+                    <xsl:when test="$mimetype">
+                        <xsl:text>data:</xsl:text><xsl:value-of 
select="$mimetype"/><xsl:text>;base64,</xsl:text><xsl:value-of 
select="office:binary-data"/>
+                    </xsl:when>
+                    <xsl:otherwise>
+                        <xsl:text>data:image/*;base64,</xsl:text><xsl:value-of 
select="office:binary-data"/>
+                    </xsl:otherwise>
+                </xsl:choose>
                        </xsl:when>
                        <xsl:otherwise>
                                <xsl:choose>
@@ -361,10 +369,10 @@
                                                                <xsl:value-of 
select="concat($href, $optionalURLSuffix)"/>
                                                        </xsl:when>
                                                         <!-- for relative URLs 
-->
-                                                        <xsl:when 
test="starts-with($href, '#')">
-                                                          <!-- intra document 
ref -->
-                                                          <xsl:value-of 
select="$href"/>
-                                                        </xsl:when>
+                                                        <xsl:when 
test="starts-with($href, '#')">
+                                                          <!-- intra document 
ref -->
+                                                          <xsl:value-of 
select="$href"/>
+                                                        </xsl:when>
                                                        <xsl:otherwise>
                                                                <xsl:value-of 
select="concat($sourceBaseURL, $href, $optionalURLSuffix)"/>
                                                        </xsl:otherwise>
diff --git a/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl 
b/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl
index baee18241128..8cce4595d3ea 100644
--- a/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl
+++ b/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl
@@ -19,7 +19,7 @@
 <!--
        For further documentation and updates visit 
http://xml.openoffice.org/odf2xhtml
 -->
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; 
xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" 
xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" 
xmlns:dc="http://purl.org/dc/elements/1.1/"; 
xmlns:dom="http://www.w3.org/2001/xml-events"; 
xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d: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:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" 
xmlns:math="http://www.w3.org/1998/Math/MathML"; 
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" 
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:ooo="http://openoffice.org/2004/office"; 
xmlns:oooc="http://openoffice.org/2004/calc"; 
xmlns:ooow="http://openoffice.org/2004/writer"; 
xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:s
 tyle="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:xforms="http://www.w3.org/2002/xforms"; 
xmlns:xlink="http://www.w3.org/1999/xlink"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns:xt="http://www.jclark.com/xt"; xmlns:common="http://exslt.org/common"; 
xmlns:xalan="http://xml.apache.org/xalan"; exclude-result-prefixes="chart config 
dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg 
table text xforms xlink xsd xsi xt common xalan" 
xmlns="http://www.w3.org/1999/xhtml";>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; 
xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" 
xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" 
xmlns:dc="http://purl.org/dc/elements/1.1/"; 
xmlns:dom="http://www.w3.org/2001/xml-events"; 
xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d: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:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" 
xmlns:math="http://www.w3.org/1998/Math/MathML"; 
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" 
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:ooo="http://openoffice.org/2004/office"; 
xmlns:oooc="http://openoffice.org/2004/calc"; 
xmlns:ooow="http://openoffice.org/2004/writer"; 
xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:s
 tyle="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:xforms="http://www.w3.org/2002/xforms"; 
xmlns:xlink="http://www.w3.org/1999/xlink"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns:xt="http://www.jclark.com/xt"; xmlns:common="http://exslt.org/common"; 
xmlns:xalan="http://xml.apache.org/xalan"; 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta 
number office ooo oooc ooow script style svg table text xforms xlink xsd xsi xt 
common xalan" xmlns="http://www.w3.org/1999/xhtml";>
 
 
        <!--+++++ INCLUDED XSL MODULES +++++-->
@@ -1551,6 +1551,7 @@
                        <xsl:attribute name="src">
                                <xsl:call-template name="create-href">
                                        <xsl:with-param name="href" 
select="@xlink:href"/>
+                                       <xsl:with-param name="mimetype" 
select="@loext:mime-type"/>
                                </xsl:call-template>
                        </xsl:attribute>
 
diff --git a/sw/qa/extras/odfexport/data/image-mimetype.odt 
b/sw/qa/extras/odfexport/data/image-mimetype.odt
new file mode 100644
index 000000000000..4c4924a1b254
Binary files /dev/null and b/sw/qa/extras/odfexport/data/image-mimetype.odt 
differ
diff --git a/sw/qa/extras/odfexport/odfexport.cxx 
b/sw/qa/extras/odfexport/odfexport.cxx
index 8c827404769f..83848a81a124 100644
--- a/sw/qa/extras/odfexport/odfexport.cxx
+++ b/sw/qa/extras/odfexport/odfexport.cxx
@@ -846,6 +846,16 @@ DECLARE_ODFEXPORT_TEST(testCellUserDefineAttr, 
"userdefattr-tablecell.odt")
     getUserDefineAttribute(uno::makeAny(xCellC1), "proName", "v3");
 }
 
+DECLARE_ODFEXPORT_TEST(testImageMimetype, "image-mimetype.odt")
+{
+    // Test that the loext:mimetype attribute is written for exported images, 
tdf#109202
+    if (xmlDocPtr pXmlDoc = parseExport("content.xml"))
+    {
+        // Original image (svg)
+        assertXPath(pXmlDoc, 
"/office:document-content/office:body/office:text/text:p/draw:frame/draw:image[@loext:mime-type='image/svg+xml']");
+    }
+}
+
 #endif
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/xmloff/source/text/txtparae.cxx b/xmloff/source/text/txtparae.cxx
index a809bf0b758c..12355f2a254a 100644
--- a/xmloff/source/text/txtparae.cxx
+++ b/xmloff/source/text/txtparae.cxx
@@ -28,6 +28,9 @@
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <com/sun/star/beans/XMultiPropertySet.hpp>
 #include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/graphic/GraphicProvider.hpp>
+#include <com/sun/star/graphic/XGraphicProvider.hpp>
 #include <com/sun/star/text/XTextDocument.hpp>
 #include <com/sun/star/text/XTextSectionsSupplier.hpp>
 #include <com/sun/star/text/XTextTablesSupplier.hpp>
@@ -110,6 +113,7 @@
 #include <vector>
 #include <algorithm>
 #include <iterator>
+#include <comphelper/processfactory.hxx>
 
 using namespace ::std;
 using namespace ::com::sun::star;
@@ -123,6 +127,7 @@ using namespace ::com::sun::star::util;
 using namespace ::com::sun::star::drawing;
 using namespace ::com::sun::star::document;
 using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::graphic;
 using namespace ::xmloff;
 using namespace ::xmloff::token;
 
@@ -3041,6 +3046,22 @@ void XMLTextParagraphExport::exportContour(
                               true, true );
 }
 
+static OUString getMimeType(const OUString& sImageUrl)
+{
+    // Create the graphic to retrieve the mimetype from it
+    Reference< XGraphicProvider > xProvider = 
css::graphic::GraphicProvider::create(comphelper::getProcessComponentContext());
+    Sequence< PropertyValue > aMediaProperties( 1 );
+    aMediaProperties[0].Name = "URL";
+    aMediaProperties[0].Value <<= sImageUrl;
+    Reference< XGraphic > xGraphic( xProvider->queryGraphic( aMediaProperties 
) );
+
+    OUString aSourceMimeType;
+    Reference< XPropertySet > xGraphicPropertySet( xGraphic, UNO_QUERY_THROW );
+    if ( xGraphicPropertySet->getPropertyValue( "MimeType" ) >>= 
aSourceMimeType )
+        return aSourceMimeType;
+    return OUString("");
+}
+
 void XMLTextParagraphExport::_exportTextGraphic(
         const Reference < XPropertySet > & rPropSet,
         const Reference < XPropertySetInfo > & rPropSetInfo )
@@ -3102,6 +3123,11 @@ void XMLTextParagraphExport::_exportTextGraphic(
         GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_FILTER_NAME,
                                   sGrfFilter );
 
+    // Add mimetype to make it easier for readers to get the base64 image type 
right, tdf#109202
+    OUString aSourceMimeType = getMimeType(sOrigURL);
+    if ( !aSourceMimeType.isEmpty() )
+        GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, "mime-type", 
aSourceMimeType);
+
     {
         SvXMLElementExport aElement( GetExport(), XML_NAMESPACE_DRAW,
                                   XML_IMAGE, false, true );
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to