[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.2' - filter/CppunitTest_filter_svg.mk filter/Module_filter.mk filter/qa filter/source

Miklos Vajna (via logerrit) logerrit at kemper.freedesktop.org
Wed Feb 26 16:04:20 UTC 2020


 filter/CppunitTest_filter_svg.mk     |   46 +++++++++++++
 filter/Module_filter.mk              |    1 
 filter/qa/unit/data/preserve-jpg.odt |binary
 filter/qa/unit/svg.cxx               |  123 +++++++++++++++++++++++++++++++++++
 filter/source/svg/svgexport.cxx      |   17 +++-
 filter/source/svg/svgwriter.cxx      |   52 +++++++-------
 6 files changed, 207 insertions(+), 32 deletions(-)

New commits:
commit 31b2a9b2c17f7dbf6c2ef4998c9d192ca5c70f98
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Wed Feb 26 13:03:17 2020 +0100
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Wed Feb 26 17:03:49 2020 +0100

    sw SVG export: try to reuse original bitmap data for JPG and PNG bitmaps
    
    Writer shapes are implemented using SwXShape, Impress shapes use
    SdrGrafObj. So switch to working with the XShape interface, which is
    supported by both.
    
    Also, don't work with the transformed graphic if it has the same
    checksum as the original graphic: the transformed graphic is not linked
    to the original JPG/PNG data.
    
    Now selecting an image in Writer Online has the same speedup that
    Impress Online already had.
    
    Change-Id: Iab2791c5f5c7a2754e3de0ebb2d6ea664f6c77e4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/89542
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>

diff --git a/filter/CppunitTest_filter_svg.mk b/filter/CppunitTest_filter_svg.mk
new file mode 100644
index 000000000000..0b22e11a6dab
--- /dev/null
+++ b/filter/CppunitTest_filter_svg.mk
@@ -0,0 +1,46 @@
+# -*- 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,filter_svg))
+
+$(eval $(call gb_CppunitTest_use_externals,filter_svg,\
+	boost_headers \
+	libxml2 \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,filter_svg, \
+    filter/qa/unit/svg \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,filter_svg, \
+    comphelper \
+    cppu \
+    sal \
+    test \
+    unotest \
+    utl \
+    tl \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,filter_svg))
+
+$(eval $(call gb_CppunitTest_use_ure,filter_svg))
+$(eval $(call gb_CppunitTest_use_vcl,filter_svg))
+
+$(eval $(call gb_CppunitTest_use_rdb,filter_svg,services))
+
+$(eval $(call gb_CppunitTest_use_custom_headers,filter_svg,\
+	officecfg/registry \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,filter_svg))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Module_filter.mk b/filter/Module_filter.mk
index 2d380fbd91ac..a01baa0b48a7 100644
--- a/filter/Module_filter.mk
+++ b/filter/Module_filter.mk
@@ -67,6 +67,7 @@ $(eval $(call gb_Module_add_check_targets,filter,\
     CppunitTest_filter_ras_test \
     CppunitTest_filter_tiff_test \
     CppunitTest_filter_tga_test \
+    CppunitTest_filter_svg \
 ))
 endif
 
diff --git a/filter/qa/unit/data/preserve-jpg.odt b/filter/qa/unit/data/preserve-jpg.odt
new file mode 100644
index 000000000000..83768bd47afb
Binary files /dev/null and b/filter/qa/unit/data/preserve-jpg.odt differ
diff --git a/filter/qa/unit/svg.cxx b/filter/qa/unit/svg.cxx
new file mode 100644
index 000000000000..379189b98365
--- /dev/null
+++ b/filter/qa/unit/svg.cxx
@@ -0,0 +1,123 @@
+/* -*- 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 <test/bootstrapfixture.hxx>
+#include <unotest/macros_test.hxx>
+#include <test/xmltesttools.hxx>
+
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/frame/DispatchHelper.hpp>
+#include <unotools/streamwrap.hxx>
+#include <unotools/mediadescriptor.hxx>
+#include <tools/stream.hxx>
+#include <comphelper/processfactory.hxx>
+
+using namespace ::com::sun::star;
+
+char const DATA_DIRECTORY[] = "/filter/qa/unit/data/";
+
+namespace
+{
+void dispatchCommand(const uno::Reference<lang::XComponent>& xComponent, const OUString& rCommand,
+                     const uno::Sequence<beans::PropertyValue>& rPropertyValues)
+{
+    uno::Reference<frame::XController> xController
+        = uno::Reference<frame::XModel>(xComponent, uno::UNO_QUERY_THROW)->getCurrentController();
+    CPPUNIT_ASSERT(xController.is());
+    uno::Reference<frame::XDispatchProvider> xFrame(xController->getFrame(), uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xFrame.is());
+
+    uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
+    uno::Reference<frame::XDispatchHelper> xDispatchHelper(frame::DispatchHelper::create(xContext));
+    CPPUNIT_ASSERT(xDispatchHelper.is());
+
+    xDispatchHelper->executeDispatch(xFrame, rCommand, OUString(), 0, rPropertyValues);
+}
+}
+
+/// SVG filter tests.
+class SvgFilterTest : public test::BootstrapFixture, public unotest::MacrosTest, public XmlTestTools
+{
+private:
+    uno::Reference<uno::XComponentContext> mxComponentContext;
+    uno::Reference<lang::XComponent> mxComponent;
+
+public:
+    void setUp() override;
+    void tearDown() override;
+    void registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) override;
+    uno::Reference<lang::XComponent>& getComponent() { return mxComponent; }
+    void load(const OUString& rURL);
+};
+
+void SvgFilterTest::setUp()
+{
+    test::BootstrapFixture::setUp();
+
+    mxComponentContext.set(comphelper::getComponentContext(getMultiServiceFactory()));
+    mxDesktop.set(frame::Desktop::create(mxComponentContext));
+}
+
+void SvgFilterTest::tearDown()
+{
+    if (mxComponent.is())
+        mxComponent->dispose();
+
+    test::BootstrapFixture::tearDown();
+}
+
+void SvgFilterTest::load(const OUString& rFileName)
+{
+    OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + rFileName;
+    mxComponent = loadFromDesktop(aURL);
+}
+
+void SvgFilterTest::registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx)
+{
+    xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("svg"), BAD_CAST("http://www.w3.org/2000/svg"));
+}
+
+CPPUNIT_TEST_FIXTURE(SvgFilterTest, testPreserveJpg)
+{
+#if !defined(MACOSX)
+    // Load a document with a jpeg image in it.
+    load("preserve-jpg.odt");
+
+    // Select the image.
+    dispatchCommand(getComponent(), ".uno:JumpToNextFrame", {});
+
+    // Export the selection to SVG.
+    uno::Reference<frame::XStorable> xStorable(getComponent(), uno::UNO_QUERY_THROW);
+    SvMemoryStream aStream;
+    uno::Reference<io::XOutputStream> xOut = new utl::OOutputStreamWrapper(aStream);
+    utl::MediaDescriptor aMediaDescriptor;
+    aMediaDescriptor["FilterName"] <<= OUString("writer_svg_Export");
+    aMediaDescriptor["SelectionOnly"] <<= true;
+    aMediaDescriptor["OutputStream"] <<= xOut;
+    xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList());
+    aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+    // Make sure the the original JPG data is reused and we don't perform a PNG re-compress.
+    xmlDocPtr pXmlDoc = parseXmlStream(&aStream);
+    OUString aAttributeValue = getXPath(pXmlDoc, "//svg:image", "href");
+
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expression: aAttributeValue.startsWith("data:image/jpeg")
+    // i.e. the SVG export result re-compressed the image as PNG, even if the original and the
+    // transformed image is the same, so there is no need for that.
+    CPPUNIT_ASSERT(aAttributeValue.startsWith("data:image/jpeg"));
+#endif
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx
index e0d33036646d..accbab0d6965 100644
--- a/filter/source/svg/svgexport.cxx
+++ b/filter/source/svg/svgexport.cxx
@@ -687,13 +687,20 @@ bool SVGFilter::implExportWriterTextGraphic( const Reference< view::XSelectionSu
     if (xSelection.is() && xSelection->supportsService("com.sun.star.text.TextGraphicObject"))
     {
         uno::Reference<beans::XPropertySet> xPropertySet(xSelection, uno::UNO_QUERY);
-        uno::Reference<graphic::XGraphic> xGraphic;
-        xPropertySet->getPropertyValue("TransformedGraphic") >>= xGraphic;
 
-        if (!xGraphic.is())
-            return false;
+        uno::Reference<graphic::XGraphic> xOriginalGraphic;
+        xPropertySet->getPropertyValue("Graphic") >>= xOriginalGraphic;
+        const Graphic aOriginalGraphic(xOriginalGraphic);
+
+        uno::Reference<graphic::XGraphic> xTransformedGraphic;
+        xPropertySet->getPropertyValue("TransformedGraphic") >>= xTransformedGraphic;
 
-        const Graphic aGraphic(xGraphic);
+        if (!xTransformedGraphic.is())
+            return false;
+        const Graphic aTransformedGraphic(xTransformedGraphic);
+        bool bChecksumMatches = aOriginalGraphic.GetChecksum() == aTransformedGraphic.GetChecksum();
+        const Graphic aGraphic = bChecksumMatches ? aOriginalGraphic : aTransformedGraphic;
+        uno::Reference<graphic::XGraphic> xGraphic = bChecksumMatches ? xOriginalGraphic : xTransformedGraphic;
 
         // Calculate size from Graphic
         Point aPos( OutputDevice::LogicToLogic(aGraphic.GetPrefMapMode().GetOrigin(), aGraphic.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index d9f7dc48bf08..1ea8af01e6eb 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -2679,20 +2679,22 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText,
 
 namespace
 {
-SdrGrafObj* GetSdrGrafObjFromXShape(const css::uno::Reference<css::drawing::XShape>* pShape)
+void GetGraphicFromXShape(const css::uno::Reference<css::drawing::XShape>* pShape, Graphic& rGraphic)
 {
     if (!pShape)
     {
-        return nullptr;
+        return;
     }
 
-    auto pObject = dynamic_cast<SvxGraphicObject*>(pShape->get());
-    if (!pObject)
+    uno::Reference<beans::XPropertySet> xPropertySet(*pShape, uno::UNO_QUERY);
+    if (!xPropertySet.is())
     {
-        return nullptr;
+        return;
     }
 
-    return dynamic_cast<SdrGrafObj*>(pObject->GetSdrObject());
+    uno::Reference<graphic::XGraphic> xGraphic;
+    xPropertySet->getPropertyValue("Graphic") >>= xGraphic;
+    rGraphic= Graphic(xGraphic);
 }
 }
 
@@ -2715,34 +2717,30 @@ void SVGActionWriter::ImplWriteBmp( const BitmapEx& rBmpEx,
             SvMemoryStream aOStm( 65535, 65535 );
 
             bool bCached = false;
-            SdrGrafObj* pGrafObj = nullptr;
+            Graphic aGraphic;
             bool bPNG = false;
             bool bJPG = false;
             if (pShape)
             {
-                pGrafObj = GetSdrGrafObjFromXShape(pShape);
-                if (pGrafObj)
+                GetGraphicFromXShape(pShape, aGraphic);
+                if (aGraphic.GetType() == GraphicType::Bitmap)
                 {
-                    const Graphic& rGraphic = pGrafObj->GetGraphic();
-                    if (rGraphic.GetType() == GraphicType::Bitmap)
+                    const BitmapEx& rGraphicBitmap = aGraphic.GetBitmapExRef();
+                    if (rGraphicBitmap.GetChecksum() == rBmpEx.GetChecksum())
                     {
-                        const BitmapEx& rGraphicBitmap = rGraphic.GetBitmapExRef();
-                        if (rGraphicBitmap.GetChecksum() == rBmpEx.GetChecksum())
+                        GfxLink aGfxLink = aGraphic.GetGfxLink();
+                        if (aGfxLink.GetType() == GfxLinkType::NativePng)
                         {
-                            GfxLink aGfxLink = rGraphic.GetGfxLink();
-                            if (aGfxLink.GetType() == GfxLinkType::NativePng)
-                            {
-                                bPNG = true;
-                            }
-                            else if (aGfxLink.GetType() == GfxLinkType::NativeJpg)
-                            {
-                                bJPG = true;
-                            }
-                            if (bPNG || bJPG)
-                            {
-                                aOStm.WriteBytes(aGfxLink.GetData(), aGfxLink.GetDataSize());
-                                bCached = true;
-                            }
+                            bPNG = true;
+                        }
+                        else if (aGfxLink.GetType() == GfxLinkType::NativeJpg)
+                        {
+                            bJPG = true;
+                        }
+                        if (bPNG || bJPG)
+                        {
+                            aOStm.WriteBytes(aGfxLink.GetData(), aGfxLink.GetDataSize());
+                            bCached = true;
                         }
                     }
                 }


More information about the Libreoffice-commits mailing list