vcl/CppunitTest_vcl_filter_igif.mk                  |   46 +++++++++++++++++++
 vcl/Module_vcl.mk                                   |    1 
 vcl/qa/cppunit/filter/igif/data/logic-lazy-read.gif |binary
 vcl/qa/cppunit/filter/igif/igif.cxx                 |   47 ++++++++++++++++++++
 vcl/source/filter/graphicfilter.cxx                 |    7 ++
 vcl/source/filter/igif/gifread.cxx                  |   10 +++-
 vcl/source/filter/igif/gifread.hxx                  |    2 
 7 files changed, 110 insertions(+), 3 deletions(-)

New commits:
commit 1248e84a49d777ae93beffff5dae96583a4f8df9
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon Dec 21 21:03:36 2020 +0100
Commit:     Gabor Kelemen <kelemen.gab...@nisz.hu>
CommitDate: Wed Mar 3 08:26:17 2021 +0100

    tdf#138801 vcl: fix lazy-loading of GIF images with logic size
    
    Regression from commit edda1e5fc8113aa4744e32f97c96a3cc311485ca (DOCX
    import: lazy-read images without external headers, 2018-04-20), the
    immediate problem is that GIF images from docx are now lazy-loaded.
    
    The deeper problem is that GIF images normally only have pixel size and
    can have an optional logic size as well (LO-specific extension).
    
    The bugdoc in question is a DOCX file, which contains a .png stream,
    which is in fact a GIF image, with that STARDIV extension in it.
    
    Now the initial parsing (that only extracts the metadata) didn't read
    the logic size, so the preferred map mode was pixels, but later when the
    actual read happened, the preferred map mode changed to mm100.
    
    Thid does not play nicely with writerfilter/ code that sets a different
    wrap polygon depending on if the (assumed to be final) map mode is
    pixels or not.
    
    Fix the problem by reusing the "is this an animation" GIF parser to also
    extract the logic size of the GIF image, if it has one. This way we
    still lazy-load the GIF image, but the preferred map mode won't hange
    from pixels to mm100 during the real read.
    
    Change-Id: Ia6c66e1c4fa0cb23a1daf537e7179b081ef90def
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/108125
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    (cherry picked from commit c24d9447b809416575972585a5ad48e14f8d9ad9)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/108182
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/108664
    (cherry picked from commit bc8fa345ff2a20d9f39c22afa67cf158e6368efd)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111791
    Tested-by: Gabor Kelemen <kelemen.gab...@nisz.hu>
    Reviewed-by: Gabor Kelemen <kelemen.gab...@nisz.hu>

diff --git a/vcl/CppunitTest_vcl_filter_igif.mk 
b/vcl/CppunitTest_vcl_filter_igif.mk
new file mode 100644
index 000000000000..c6b6759899b0
--- /dev/null
+++ b/vcl/CppunitTest_vcl_filter_igif.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,vcl_filter_igif))
+
+$(eval $(call gb_CppunitTest_use_externals,vcl_filter_igif,\
+       boost_headers \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,vcl_filter_igif, \
+    vcl/qa/cppunit/filter/igif/igif \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,vcl_filter_igif, \
+    comphelper \
+    cppu \
+    sal \
+    test \
+    tl \
+    unotest \
+    utl \
+    vcl \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,vcl_filter_igif))
+
+$(eval $(call gb_CppunitTest_use_ure,vcl_filter_igif))
+$(eval $(call gb_CppunitTest_use_vcl,vcl_filter_igif))
+
+$(eval $(call gb_CppunitTest_use_rdb,vcl_filter_igif,services))
+
+$(eval $(call gb_CppunitTest_use_custom_headers,vcl_filter_igif,\
+       officecfg/registry \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,vcl_filter_igif))
+
+# vim: set noet sw=4 ts=4:
diff --git a/vcl/Module_vcl.mk b/vcl/Module_vcl.mk
index 938cd32014bd..8c7213938795 100644
--- a/vcl/Module_vcl.mk
+++ b/vcl/Module_vcl.mk
@@ -207,6 +207,7 @@ $(eval $(call gb_Module_add_check_targets,vcl,\
     CppunitTest_vcl_backend_test \
     CppunitTest_vcl_blocklistparser_test \
     CppunitTest_vcl_type_serializer_test \
+    CppunitTest_vcl_filter_igif \
 ))
 
 ifeq ($(USING_X11),TRUE)
diff --git a/vcl/qa/cppunit/filter/igif/data/logic-lazy-read.gif 
b/vcl/qa/cppunit/filter/igif/data/logic-lazy-read.gif
new file mode 100644
index 000000000000..3d18891f7b6a
Binary files /dev/null and 
b/vcl/qa/cppunit/filter/igif/data/logic-lazy-read.gif differ
diff --git a/vcl/qa/cppunit/filter/igif/igif.cxx 
b/vcl/qa/cppunit/filter/igif/igif.cxx
new file mode 100644
index 000000000000..8dea02ca529b
--- /dev/null
+++ b/vcl/qa/cppunit/filter/igif/igif.cxx
@@ -0,0 +1,47 @@
+/* -*- 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 <sal/config.h>
+
+#include <test/bootstrapfixture.hxx>
+
+#include <tools/stream.hxx>
+#include <unotest/directories.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/graphicfilter.hxx>
+
+using namespace com::sun::star;
+
+namespace
+{
+char const DATA_DIRECTORY[] = "/vcl/qa/cppunit/filter/igif/data/";
+
+/// Covers vcl/source/filter/igif/ fixes.
+class Test : public test::BootstrapFixture
+{
+};
+
+CPPUNIT_TEST_FIXTURE(Test, testLogicLazyRead)
+{
+    GraphicFilter aGraphicFilter;
+    test::Directories aDirectories;
+    OUString aURL = aDirectories.getURLFromSrc(DATA_DIRECTORY) + 
"logic-lazy-read.gif";
+    SvFileStream aStream(aURL, StreamMode::READ);
+    Graphic aGraphic = aGraphicFilter.ImportUnloadedGraphic(aStream);
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 0
+    // - Actual  : 10
+    // i.e. the preferred unit was pixels, not mm100.
+    CPPUNIT_ASSERT_EQUAL(MapUnit::Map100thMM, 
aGraphic.GetPrefMapMode().GetMapUnit());
+}
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/graphicfilter.cxx 
b/vcl/source/filter/graphicfilter.cxx
index 9593847dd276..c014cfc7a118 100644
--- a/vcl/source/filter/graphicfilter.cxx
+++ b/vcl/source/filter/graphicfilter.cxx
@@ -1362,10 +1362,15 @@ Graphic GraphicFilter::ImportUnloadedGraphic(SvStream& 
rIStream, sal_uInt64 size
         if( nStatus == ERRCODE_NONE )
         {
             bool bAnimated = false;
+            Size aLogicSize;
             if (eLinkType == GfxLinkType::NativeGif)
             {
                 SvMemoryStream aMemoryStream(pGraphicContent.get(), 
nGraphicContentSize, StreamMode::READ);
-                bAnimated = IsGIFAnimated(aMemoryStream);
+                bAnimated = IsGIFAnimated(aMemoryStream, aLogicSize);
+                if (!pSizeHint && aLogicSize.getWidth() && 
aLogicSize.getHeight())
+                {
+                    pSizeHint = &aLogicSize;
+                }
             }
             
aGraphic.SetGfxLink(std::make_shared<GfxLink>(std::move(pGraphicContent), 
nGraphicContentSize, eLinkType));
             aGraphic.ImplGetImpGraphic()->ImplSetPrepared(bAnimated, 
pSizeHint);
diff --git a/vcl/source/filter/igif/gifread.cxx 
b/vcl/source/filter/igif/gifread.cxx
index 47d9acb53c2a..8933874dff3a 100644
--- a/vcl/source/filter/igif/gifread.cxx
+++ b/vcl/source/filter/igif/gifread.cxx
@@ -115,6 +115,7 @@ public:
 
     ReadState           ReadGIF( Graphic& rGraphic );
     bool                ReadIsAnimated();
+    void GetLogicSize(Size& rLogicSize);
     Graphic             GetIntermediateGraphic();
 
     explicit            GIFReader( SvStream& rStm );
@@ -910,6 +911,12 @@ bool GIFReader::ReadIsAnimated()
     return false;
 }
 
+void GIFReader::GetLogicSize(Size& rLogicSize)
+{
+    rLogicSize.setWidth(nLogWidth100);
+    rLogicSize.setHeight(nLogHeight100);
+}
+
 ReadState GIFReader::ReadGIF( Graphic& rGraphic )
 {
     ReadState eReadState;
@@ -946,13 +953,14 @@ ReadState GIFReader::ReadGIF( Graphic& rGraphic )
     return eReadState;
 }
 
-bool IsGIFAnimated(SvStream & rStm)
+bool IsGIFAnimated(SvStream & rStm, Size& rLogicSize)
 {
     GIFReader aReader(rStm);
 
     SvStreamEndian nOldFormat = rStm.GetEndian();
     rStm.SetEndian(SvStreamEndian::LITTLE);
     bool bResult = aReader.ReadIsAnimated();
+    aReader.GetLogicSize(rLogicSize);
     rStm.SetEndian(nOldFormat);
 
     return bResult;
diff --git a/vcl/source/filter/igif/gifread.hxx 
b/vcl/source/filter/igif/gifread.hxx
index 25e72f6cc3d2..68809f50eb7b 100644
--- a/vcl/source/filter/igif/gifread.hxx
+++ b/vcl/source/filter/igif/gifread.hxx
@@ -23,7 +23,7 @@
 #include <vcl/graph.hxx>
 
 VCL_DLLPUBLIC bool ImportGIF( SvStream& rStream, Graphic& rGraphic );
-bool IsGIFAnimated(SvStream& rStream);
+bool IsGIFAnimated(SvStream& rStream, Size& rLogicSize);
 
 #endif // INCLUDED_VCL_SOURCE_FILTER_IGIF_GIFREAD_HXX
 
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to