summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2022-01-13 15:59:49 +0100
committerAndras Timar <andras.timar@collabora.com>2022-02-14 12:09:32 +0100
commit8ad4edf43f7e143967590dac02ca72d843f9ae11 (patch)
tree3ebada26f871c099c7ba6cb1a77d677d021e1d48
parentb900907fde6d4507cff7844c5bcd6cc2f7b3821f (diff)
support for the WebP image format (tdf#114532)
This commit implements a WebP reader and writer for both lossless and lossy WebP, export dialog options for selecting lossless/lossy and quality for lossy, and various internal support for the format. Since writing WebP to e.g. ODT documents would make those images unreadable by previous versions with no WebP support, support for that is explicitly disabled in GraphicFilter, to be enabled somewhen later. Change-Id: I9b10f6da6faa78a0bb74415a92e9f163c14685f7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128920 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r--Makefile.fetch1
-rw-r--r--RepositoryExternal.mk51
-rwxr-xr-xbin/lo-all-static-libs1
-rw-r--r--config_host.mk.in3
-rw-r--r--configure.ac6
-rw-r--r--download.lst2
-rw-r--r--external/Module_external.mk1
-rw-r--r--external/libwebp/ExternalProject_libwebp.mk52
-rw-r--r--external/libwebp/Makefile7
-rw-r--r--external/libwebp/Makefile.vc.patch145
-rw-r--r--external/libwebp/Module_libwebp.mk17
-rw-r--r--external/libwebp/README1
-rw-r--r--external/libwebp/UnpackedTarball_libwebp.mk20
-rw-r--r--filter/Configuration_filter.mk13
-rw-r--r--filter/qa/complex/filter/detection/typeDetection/files.csv1
-rw-r--r--filter/source/config/cache/typedetection.cxx1
-rw-r--r--filter/source/config/fragments/filters/WEBP___WebP.xcu30
-rw-r--r--filter/source/config/fragments/filters/calc_webp_Export.xcu20
-rw-r--r--filter/source/config/fragments/filters/draw_webp_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress_webp_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/writer_web_webp_Export.xcu21
-rw-r--r--filter/source/config/fragments/filters/writer_webp_Export.xcu30
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/webp_Export.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/webp_Import.xcu27
-rw-r--r--filter/source/config/fragments/types/webp_WebP.xcu29
-rw-r--r--icon-themes/breeze/res/sx03223.pngbin0 -> 322 bytes
-rw-r--r--icon-themes/breeze_dark/res/sx03223.pngbin0 -> 322 bytes
-rw-r--r--icon-themes/breeze_dark_svg/res/sx03223.svg1
-rw-r--r--icon-themes/breeze_svg/res/sx03223.svg1
-rw-r--r--include/sal/log-areas.dox1
-rw-r--r--include/svl/inettype.hxx2
-rw-r--r--include/svtools/imagemgr.hxx1
-rw-r--r--include/svx/strings.hrc1
-rw-r--r--include/vcl/gfxlink.hxx5
-rw-r--r--include/vcl/graphicfilter.hxx6
-rw-r--r--include/vcl/salctype.hxx3
-rw-r--r--readlicense_oo/license/license.xml31
-rw-r--r--scp2/source/draw/registryitem_draw.scp1
-rw-r--r--solenv/sanitizers/ui/svt.suppr2
-rw-r--r--svtools/inc/bitmaps.hlst2
-rw-r--r--svtools/source/filter/exportdialog.cxx53
-rw-r--r--svtools/source/filter/exportdialog.hxx9
-rw-r--r--svtools/source/misc/imagemgr.cxx5
-rw-r--r--svtools/uiconfig/ui/graphicexport.ui36
-rw-r--r--svx/source/core/graphichelper.cxx6
-rw-r--r--svx/source/gallery2/galtheme.cxx1
-rw-r--r--svx/source/xml/xmlgrhlp.cxx1
-rw-r--r--svx/source/xoutdev/_xoutbmp.cxx2
-rw-r--r--vcl/CppunitTest_vcl_filters_test.mk1
-rw-r--r--vcl/Executable_webpfuzzer.mk45
-rw-r--r--vcl/Library_vcl.mk3
-rw-r--r--vcl/Module_vcl.mk1
-rw-r--r--vcl/inc/filter/WebpReader.hxx28
-rw-r--r--vcl/inc/filter/WebpWriter.hxx29
-rw-r--r--vcl/inc/graphic/GraphicFormatDetector.hxx1
-rw-r--r--vcl/inc/graphic/UnoGraphicDescriptor.hxx1
-rw-r--r--vcl/qa/cppunit/GraphicDescriptorTest.cxx16
-rw-r--r--vcl/qa/cppunit/GraphicFormatDetectorTest.cxx17
-rw-r--r--vcl/qa/cppunit/GraphicTest.cxx12
-rw-r--r--vcl/qa/cppunit/data/TypeDetectionExample.webpbin0 -> 52 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/webp/alpha_lossless.webpbin0 -> 744 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/webp/alpha_lossy.webpbin0 -> 826 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/webp/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/webp/indeterminate/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/webp/noalpha_lossless.webpbin0 -> 762 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/webp/noalpha_lossy.webpbin0 -> 782 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/webp/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/filters-test.cxx2
-rw-r--r--vcl/qa/cppunit/graphicfilter/filters-webp-test.cxx203
-rw-r--r--vcl/source/filter/FilterConfigCache.cxx6
-rw-r--r--vcl/source/filter/GraphicFormatDetector.cxx22
-rw-r--r--vcl/source/filter/graphicfilter.cxx53
-rw-r--r--vcl/source/filter/graphicfilter2.cxx33
-rw-r--r--vcl/source/filter/webp/reader.cxx318
-rw-r--r--vcl/source/filter/webp/writer.cxx206
-rw-r--r--vcl/source/gdi/gfxlink.cxx1
-rw-r--r--vcl/source/gdi/mtfxmldump.cxx1
-rw-r--r--vcl/source/graphic/UnoGraphicDescriptor.cxx2
-rw-r--r--vcl/workben/fftester.cxx7
-rw-r--r--vcl/workben/webpfuzzer.cxx48
-rw-r--r--vcl/workben/webpfuzzer.options2
81 files changed, 1769 insertions, 25 deletions
diff --git a/Makefile.fetch b/Makefile.fetch
index 407d7d1ab985..87f423971455 100644
--- a/Makefile.fetch
+++ b/Makefile.fetch
@@ -163,6 +163,7 @@ $(WORKDIR)/download: $(BUILDDIR)/config_$(gb_Side).mk $(SRCDIR)/download.lst $(S
$(call fetch_Optional,LIBNUMBERTEXT,LIBNUMBERTEXT_TARBALL) \
$(call fetch_Optional,LIBPNG,LIBPNG_TARBALL) \
$(call fetch_Optional,LIBTOMMATH,LIBTOMMATH_TARBALL) \
+ $(call fetch_Optional,LIBWEBP,LIBWEBP_TARBALL) \
$(call fetch_Optional,LIBXML2,LIBXML_TARBALL) \
$(call fetch_Optional,XMLSEC,XMLSEC_TARBALL) \
$(call fetch_Optional,LIBXSLT,LIBXSLT_TARBALL) \
diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index c374a72847a7..9044f574bc81 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -2734,6 +2734,57 @@ endef
endif # !SYSTEM_LIBPNG
+ifneq ($(SYSTEM_LIBWEBP),)
+
+define gb_LinkTarget__use_libwebp
+$(call gb_LinkTarget_set_include,$(1),\
+ $$(INCLUDE) \
+ $(LIBWEBP_CFLAGS) \
+)
+
+$(call gb_LinkTarget_add_libs,$(1),\
+ $(LIBWEBP_LIBS) \
+)
+
+endef
+
+gb_ExternalProject__use_libwebp :=
+
+else # !SYSTEM_LIBWEBP
+
+define gb_LinkTarget__use_libwebp
+$(call gb_LinkTarget_set_include,$(1),\
+ $(LIBWEBP_CFLAGS) \
+ $$(INCLUDE) \
+)
+
+$(call gb_LinkTarget_set_include,$(1),\
+ -I$(call gb_UnpackedTarball_get_dir,libwebp)/src \
+ $$(INCLUDE) \
+)
+ifeq ($(OS),WNT)
+$(call gb_LinkTarget_add_libs,$(1),\
+ $(call gb_UnpackedTarball_get_dir,libwebp)/output/lib/libwebp$(gb_StaticLibrary_PLAINEXT) \
+)
+else
+$(call gb_LinkTarget_add_libs,$(1),\
+ -L$(call gb_UnpackedTarball_get_dir,libwebp)/src/.libs -lwebp \
+)
+endif
+$(call gb_LinkTarget_use_external_project,$(1),libwebp)
+
+endef
+
+define gb_ExternalProject__use_libwebp
+$(call gb_ExternalProject_use_external_project,$(1),\
+ libwebp \
+)
+
+endef
+
+endif # !SYSTEM_LIBWEBP
+
+
ifneq ($(SYSTEM_CURL),)
define gb_LinkTarget__use_curl
diff --git a/bin/lo-all-static-libs b/bin/lo-all-static-libs
index 11230c695248..fbe6d7010624 100755
--- a/bin/lo-all-static-libs
+++ b/bin/lo-all-static-libs
@@ -123,6 +123,7 @@ echo $INSTDIR/$LIBO_LIB_FOLDER/lib*.a \
$WORKDIR/UnpackedTarball/liborcus/src/*/.libs/*.a \
$WORKDIR/UnpackedTarball/librevenge/src/*/.libs/*.a \
$WORKDIR/UnpackedTarball/libvisio/src/lib/.libs/*.a \
+ $WORKDIR/UnpackedTarball/libwebp/src/.libs/*.a \
$WORKDIR/UnpackedTarball/libwp?/src/lib/.libs/*.a \
$WORKDIR/UnpackedTarball/raptor/src/.libs/*.a \
$WORKDIR/UnpackedTarball/rasqal/src/.libs/*.a \
diff --git a/config_host.mk.in b/config_host.mk.in
index b16826ba1088..f7f42ed45235 100644
--- a/config_host.mk.in
+++ b/config_host.mk.in
@@ -405,6 +405,8 @@ export LIBSERIALIZER_JAR=@LIBSERIALIZER_JAR@
export LIBTOMMATH_CFLAGS=@LIBTOMMATH_CFLAGS@
export LIBTOMMATH_LIBS=@LIBTOMMATH_LIBS@
export LIBTOOL=@LIBTOOL@
+export LIBWEBP_CFLAGS=$(gb_SPACE)@LIBWEBP_CFLAGS@
+export LIBWEBP_LIBS=$(gb_SPACE)@LIBWEBP_LIBS@
export LIBXML_CFLAGS=$(gb_SPACE)@LIBXML_CFLAGS@
export LIBXML_JAR=@LIBXML_JAR@
export LIBXML_LIBS=$(gb_SPACE)@LIBXML_LIBS@
@@ -633,6 +635,7 @@ export SYSTEM_LIBNUMBERTEXT_DATA=@SYSTEM_LIBNUMBERTEXT_DATA@
export SYSTEM_LIBORCUS=@SYSTEM_LIBORCUS@
export SYSTEM_LIBPNG=@SYSTEM_LIBPNG@
export SYSTEM_LIBTOMMATH=@SYSTEM_LIBTOMMATH@
+export SYSTEM_LIBWEBP=@SYSTEM_LIBWEBP@
export SYSTEM_LIBXML=@SYSTEM_LIBXML@
export SYSTEM_LIBXML_FOR_BUILD=@SYSTEM_LIBXML_FOR_BUILD@
export SYSTEM_LIBXSLT=@SYSTEM_LIBXSLT@
diff --git a/configure.ac b/configure.ac
index 633311f0b9f9..5326327f0e52 100644
--- a/configure.ac
+++ b/configure.ac
@@ -13531,6 +13531,12 @@ dnl ===================================================================
libo_CHECK_SYSTEM_MODULE([libpng],[LIBPNG],[libpng],["-I${WORKDIR}/UnpackedTarball/libpng"],["-L${WORKDIR}/LinkTarget/StaticLibrary -llibpng"])
dnl ===================================================================
+dnl Test whether to build libwebp or rely on the system version
+dnl ===================================================================
+
+libo_CHECK_SYSTEM_MODULE([libwebp],[LIBWEBP],[libwebp])
+
+dnl ===================================================================
dnl Check for runtime JVM search path
dnl ===================================================================
if test "$ENABLE_JAVA" != ""; then
diff --git a/download.lst b/download.lst
index 851a1188080e..86dddcb13d4d 100644
--- a/download.lst
+++ b/download.lst
@@ -186,6 +186,8 @@ export LIBNUMBERTEXT_SHA256SUM := db9060d208501bd7bc06300a55d8489d29dd560ee0fbbd
export LIBNUMBERTEXT_TARBALL := libnumbertext-1.0.8.tar.xz
export LIBTOMMATH_SHA256SUM := 083daa92d8ee6f4af96a6143b12d7fc8fe1a547e14f862304f7281f8f7347483
export LIBTOMMATH_TARBALL := ltm-1.0.zip
+export LIBWEBP_SHA256SUM := 808b98d2f5b84e9b27fdef6c5372dac769c3bda4502febbfa5031bd3c4d7d018
+export LIBWEBP_TARBALL := libwebp-1.2.1.tar.gz
export XMLSEC_SHA256SUM := 26041d35a20a245ed5a2fb9ee075f10825664d274220cb5190340fa87a4d0931
export XMLSEC_TARBALL := xmlsec1-1.2.33.tar.gz
export LIBXML_SHA256SUM := c8d6681e38c56f172892c85ddc0852e1fd4b53b4209e7f4ebf17f7e2eae71d92
diff --git a/external/Module_external.mk b/external/Module_external.mk
index fcb6fd6c310f..4e1a04ccc317 100644
--- a/external/Module_external.mk
+++ b/external/Module_external.mk
@@ -63,6 +63,7 @@ $(eval $(call gb_Module_add_moduledirs,external,\
$(call gb_Helper_optional,LIBLANGTAG,liblangtag) \
$(call gb_Helper_optional,LIBNUMBERTEXT,libnumbertext) \
$(call gb_Helper_optional,LIBPNG,libpng) \
+ $(call gb_Helper_optional,LIBWEBP,libwebp) \
$(call gb_Helper_optional,LIBXML2,libxml2) \
$(call gb_Helper_optional,LIBXSLT,libxslt) \
$(call gb_Helper_optional,LPSOLVE,lpsolve) \
diff --git a/external/libwebp/ExternalProject_libwebp.mk b/external/libwebp/ExternalProject_libwebp.mk
new file mode 100644
index 000000000000..beb7a39e7b64
--- /dev/null
+++ b/external/libwebp/ExternalProject_libwebp.mk
@@ -0,0 +1,52 @@
+# -*- 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_ExternalProject_ExternalProject,libwebp))
+
+$(eval $(call gb_ExternalProject_register_targets,libwebp,\
+ build \
+))
+
+ifeq ($(COM),MSC)
+$(eval $(call gb_ExternalProject_use_nmake,libwebp,build))
+
+$(call gb_ExternalProject_get_state_target,libwebp,build):
+ $(call gb_Trace_StartRange,libwebp,EXTERNAL)
+ $(call gb_ExternalProject_run,build,\
+ nmake -nologo -f Makefile.vc CFG=release-static RTLIBCFG=static OBJDIR=output \
+ )
+ $(call gb_Trace_EndRange,libwebp,EXTERNAL)
+else
+$(eval $(call gb_ExternalProject_use_autoconf,libwebp,build))
+
+$(call gb_ExternalProject_get_state_target,libwebp,build) :
+ $(call gb_Trace_StartRange,libwebp,EXTERNAL)
+ $(call gb_ExternalProject_run,build,\
+ export PKG_CONFIG="" \
+ && MAKE=$(MAKE) $(gb_RUN_CONFIGURE) ./configure \
+ --enable-static \
+ --with-pic \
+ --disable-shared \
+ --disable-gl \
+ --disable-sdl \
+ --disable-png \
+ --disable-jpeg \
+ --disable-tiff \
+ --disable-gif \
+ --disable-wic \
+ $(if $(verbose),--disable-silent-rules,--enable-silent-rules) \
+ CXXFLAGS="$(gb_CXXFLAGS) $(if $(ENABLE_OPTIMIZED),$(gb_COMPILEROPTFLAGS),$(gb_COMPILERNOOPTFLAGS))" \
+ CPPFLAGS="$(CPPFLAGS) $(BOOST_CPPFLAGS)" \
+ $(if $(CROSS_COMPILING),--build=$(BUILD_PLATFORM) --host=$(HOST_PLATFORM)) \
+ && $(MAKE) \
+ )
+ $(call gb_Trace_EndRange,libwebp,EXTERNAL)
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/external/libwebp/Makefile b/external/libwebp/Makefile
new file mode 100644
index 000000000000..e4968cf85fb6
--- /dev/null
+++ b/external/libwebp/Makefile
@@ -0,0 +1,7 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+
+module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
+
+include $(module_directory)/../../solenv/gbuild/partial_build.mk
+
+# vim: set noet sw=4 ts=4:
diff --git a/external/libwebp/Makefile.vc.patch b/external/libwebp/Makefile.vc.patch
new file mode 100644
index 000000000000..653998319b82
--- /dev/null
+++ b/external/libwebp/Makefile.vc.patch
@@ -0,0 +1,145 @@
+--- Makefile.vc.sav 2021-07-30 00:55:37.000000000 +0200
++++ Makefile.vc 2022-01-25 17:35:30.206117700 +0100
+@@ -7,11 +7,11 @@
+ LIBWEBPDEMUX_BASENAME = libwebpdemux
+
+ !IFNDEF ARCH
+-!IF ! [ cl 2>&1 | find "x86" > NUL ]
++!IF ! [ $(CC) 2>&1 | grep -q "x86" > NUL ]
+ ARCH = x86
+-!ELSE IF ! [ cl 2>&1 | find "x64" > NUL ]
++!ELSE IF ! [ $(CC) 2>&1 | grep -q "x64" > NUL ]
+ ARCH = x64
+-!ELSE IF ! [ cl 2>&1 | find "ARM" > NUL ]
++!ELSE IF ! [ $(CC) 2>&1 | grep -q "ARM" > NUL ]
+ ARCH = ARM
+ !ELSE
+ !ERROR Unable to auto-detect toolchain architecture! \
+@@ -27,8 +27,8 @@
+ ## Nothing more to do below this line!
+
+ NOLOGO = /nologo
+-CCNODBG = cl.exe $(NOLOGO) /O2 /DNDEBUG
+-CCDEBUG = cl.exe $(NOLOGO) /Od /Zi /D_DEBUG /RTC1
++CCNODBG = $(CC) $(NOLOGO) /O2 /DNDEBUG
++CCDEBUG = $(CC) $(NOLOGO) /Od /Zi /D_DEBUG /RTC1
+ CFLAGS = /I. /Isrc $(NOLOGO) /W3 /EHsc /c
+ CFLAGS = $(CFLAGS) /DWIN32 /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN
+ LDFLAGS = /LARGEADDRESSAWARE /MANIFEST /NXCOMPAT /DYNAMICBASE
+@@ -67,7 +67,7 @@
+ RTLIB = /MD
+ RTLIBD = /MDd
+ !ENDIF
+-DIRBASE = $(OUTDIR)\$(CFG)\$(ARCH)
++DIRBASE = $(OUTDIR)
+ DIROBJ = $(DIRBASE)\obj
+ DIRLIB = $(DIRBASE)\lib
+ DIRINC = $(DIRBASE)\include
+@@ -86,10 +86,10 @@
+
+ # Target configuration
+ !IF "$(CFG)" == "release-static"
+-CC = $(CCNODBG)
++CC_ = $(CCNODBG)
+ STATICLIBBUILD = TRUE
+ !ELSE IF "$(CFG)" == "debug-static"
+-CC = $(CCDEBUG)
++CC_ = $(CCDEBUG)
+ RTLIB = $(RTLIBD)
+ STATICLIBBUILD = TRUE
+ LIBWEBPDECODER_BASENAME = $(LIBWEBPDECODER_BASENAME)_debug
+@@ -97,11 +97,11 @@
+ LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug
+ LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug
+ !ELSE IF "$(CFG)" == "release-dynamic"
+-CC = $(CCNODBG)
++CC_ = $(CCNODBG)
+ RC = $(RCNODBG)
+ DLLBUILD = TRUE
+ !ELSE IF "$(CFG)" == "debug-dynamic"
+-CC = $(CCDEBUG)
++CC_ = $(CCDEBUG)
+ RC = $(RCDEBUG)
+ RTLIB = $(RTLIBD)
+ DLLBUILD = TRUE
+@@ -112,7 +112,7 @@
+ !ENDIF
+
+ !IF "$(STATICLIBBUILD)" == "TRUE"
+-CC = $(CC) $(RTLIB)
++CC_ = $(CC_) $(RTLIB)
+ CFGSET = TRUE
+ LIBWEBPDECODER = $(DIRLIB)\$(LIBWEBPDECODER_BASENAME).lib
+ LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME).lib
+@@ -120,7 +120,7 @@
+ LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPDEMUX_BASENAME).lib
+ !ELSE IF "$(DLLBUILD)" == "TRUE"
+ DLLINC = webp_dll.h
+-CC = $(CC) /I$(DIROBJ) /FI$(DLLINC) $(RTLIB) /DWEBP_DLL
++CC_ = $(CC_) /I$(DIROBJ) /FI$(DLLINC) $(RTLIB) /DWEBP_DLL
+ LIBWEBPDECODER = $(DIRLIB)\$(LIBWEBPDECODER_BASENAME)_dll.lib
+ LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME)_dll.lib
+ LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME)_dll.lib
+@@ -421,7 +421,7 @@
+ $(DIROBJ)\$(DLLINC)
+
+ {$(DIROBJ)}.c{$(DIROBJ)}.obj:
+- $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$@ $<
++ $(CC_) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$@ $<
+
+ {src}.rc{$(DIROBJ)}.res:
+ $(RC) /fo$@ $<
+@@ -461,39 +461,39 @@
+ # File-specific flag builds. Note batch rules take precedence over wildcards,
+ # so for now name each file individually.
+ $(DIROBJ)\examples\anim_diff.obj: examples\anim_diff.c
+- $(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
++ $(CC_) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
+ /Fo$(DIROBJ)\examples\ examples\$(@B).c
+ $(DIROBJ)\examples\anim_dump.obj: examples\anim_dump.c
+- $(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
++ $(CC_) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
+ /Fo$(DIROBJ)\examples\ examples\$(@B).c
+ $(DIROBJ)\examples\anim_util.obj: examples\anim_util.c
+- $(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
++ $(CC_) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
+ /Fo$(DIROBJ)\examples\ examples\$(@B).c
+ $(DIROBJ)\examples\gif2webp.obj: examples\gif2webp.c
+- $(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
++ $(CC_) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
+ /Fo$(DIROBJ)\examples\ examples\$(@B).c
+ $(DIROBJ)\examples\gifdec.obj: examples\gifdec.c
+- $(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
++ $(CC_) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
+ /Fo$(DIROBJ)\examples\ examples\$(@B).c
+ # Batch rules
+ {examples}.c{$(DIROBJ)\examples}.obj::
+- $(CC) $(CFLAGS) /Fd$(DIROBJ)\examples\ /Fo$(DIROBJ)\examples\ $<
++ $(CC_) $(CFLAGS) /Fd$(DIROBJ)\examples\ /Fo$(DIROBJ)\examples\ $<
+ {extras}.c{$(DIROBJ)\extras}.obj::
+- $(CC) $(CFLAGS) /Fd$(DIROBJ)\extras\ /Fo$(DIROBJ)\extras\ $<
++ $(CC_) $(CFLAGS) /Fd$(DIROBJ)\extras\ /Fo$(DIROBJ)\extras\ $<
+ {imageio}.c{$(DIROBJ)\imageio}.obj::
+- $(CC) $(CFLAGS) /Fd$(DIROBJ)\imageio\ /Fo$(DIROBJ)\imageio\ $<
++ $(CC_) $(CFLAGS) /Fd$(DIROBJ)\imageio\ /Fo$(DIROBJ)\imageio\ $<
+ {src\dec}.c{$(DIROBJ)\dec}.obj::
+- $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dec\ $<
++ $(CC_) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dec\ $<
+ {src\demux}.c{$(DIROBJ)\demux}.obj::
+- $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\demux\ $<
++ $(CC_) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\demux\ $<
+ {src\dsp}.c{$(DIROBJ)\dsp}.obj::
+- $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dsp\ $<
++ $(CC_) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dsp\ $<
+ {src\enc}.c{$(DIROBJ)\enc}.obj::
+- $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\enc\ $<
++ $(CC_) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\enc\ $<
+ {src\mux}.c{$(DIROBJ)\mux}.obj::
+- $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\mux\ $<
++ $(CC_) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\mux\ $<
+ {src\utils}.c{$(DIROBJ)\utils}.obj::
+- $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\utils\ $<
++ $(CC_) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\utils\ $<
+
+ LNKLIBS = ole32.lib windowscodecs.lib shlwapi.lib
+ !IF "$(UNICODE)" == "1"
diff --git a/external/libwebp/Module_libwebp.mk b/external/libwebp/Module_libwebp.mk
new file mode 100644
index 000000000000..b89056ac3d35
--- /dev/null
+++ b/external/libwebp/Module_libwebp.mk
@@ -0,0 +1,17 @@
+# -*- 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_Module_Module,libwebp))
+
+$(eval $(call gb_Module_add_targets,libwebp,\
+ ExternalProject_libwebp \
+ UnpackedTarball_libwebp \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/external/libwebp/README b/external/libwebp/README
new file mode 100644
index 000000000000..1308c278baca
--- /dev/null
+++ b/external/libwebp/README
@@ -0,0 +1 @@
+libwebp is a library to encode and decode images in WebP format, from [https://developers.google.com/speed/webp/]
diff --git a/external/libwebp/UnpackedTarball_libwebp.mk b/external/libwebp/UnpackedTarball_libwebp.mk
new file mode 100644
index 000000000000..67f797157717
--- /dev/null
+++ b/external/libwebp/UnpackedTarball_libwebp.mk
@@ -0,0 +1,20 @@
+# -*- 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_UnpackedTarball_UnpackedTarball,libwebp))
+
+$(eval $(call gb_UnpackedTarball_set_tarball,libwebp,$(LIBWEBP_TARBALL)))
+
+$(eval $(call gb_UnpackedTarball_set_patchlevel,libwebp,0))
+
+$(eval $(call gb_UnpackedTarball_add_patches,libwebp,\
+ external/libwebp/Makefile.vc.patch \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Configuration_filter.mk b/filter/Configuration_filter.mk
index dfeacc6a542c..a58b8396c551 100644
--- a/filter/Configuration_filter.mk
+++ b/filter/Configuration_filter.mk
@@ -442,6 +442,7 @@ $(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_web_filters.xc
writer_web_pdf_Export\
writer_web_png_Export\
writer_web_jpg_Export\
+ writer_web_webp_Export\
writerweb8_writer_template\
writerweb8_writer \
))
@@ -715,6 +716,7 @@ $(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_drawgraphics_typ
svm_StarView_Metafile \
tga_Truevision_TARGA \
tif_Tag_Image_File \
+ webp_WebP \
wmf_MS_Windows_Metafile \
xbm_X_Consortium \
xpm_XPM \
@@ -742,6 +744,7 @@ $(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_drawgraphics_f
SVM___StarView_Metafile \
TGA___Truevision_TARGA \
TIF___Tag_Image_File \
+ WEBP___WebP \
WMF___MS_Windows_Metafile \
XBM___X_Consortium \
XPM \
@@ -757,6 +760,7 @@ $(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_drawgraphics_f
draw_png_Export \
draw_svg_Export \
draw_tif_Export \
+ draw_webp_Export \
draw_wmf_Export \
))
@@ -781,6 +785,7 @@ $(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_impressgraphics_
svm_StarView_Metafile \
tif_Tag_Image_File \
wmf_MS_Windows_Metafile \
+ webp_WebP \
xpm_XPM \
))
@@ -795,6 +800,7 @@ $(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_impressgraphic
impress_png_Export \
impress_svg_Export \
impress_tif_Export \
+ impress_webp_Export \
impress_wmf_Export \
))
@@ -809,6 +815,7 @@ $(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_writergraphics
writer_jpg_Export \
writer_png_Export \
writer_svg_Export \
+ writer_webp_Export \
))
# fcfg_calcgraphics
@@ -821,6 +828,7 @@ $(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_calcgraphics_f
calc_jpg_Export \
calc_png_Export \
calc_svg_Export \
+ calc_webp_Export \
))
# fcfg_internalgraphics
@@ -848,6 +856,7 @@ $(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_internalgraphics
svm_StarView_Metafile \
tga_Truevision_TARGA \
tif_Tag_Image_File \
+ webp_WebP \
wmf_MS_Windows_Metafile \
xbm_X_Consortium \
xpm_XPM \
@@ -887,11 +896,13 @@ $(eval $(call filter_Configuration_add_internal_filters,fcfg_langpack,fcfg_inter
tga_Import \
tif_Export \
tif_Import \
+ webp_Export \
+ webp_Import \
wmf_Export \
wmf_Import \
xbm_Import \
xpm_Import \
- mov_Import \
+ mov_Import \
))
# fcfg_xslt
diff --git a/filter/qa/complex/filter/detection/typeDetection/files.csv b/filter/qa/complex/filter/detection/typeDetection/files.csv
index b882ea1179ca..8e558590b4e7 100644
--- a/filter/qa/complex/filter/detection/typeDetection/files.csv
+++ b/filter/qa/complex/filter/detection/typeDetection/files.csv
@@ -111,6 +111,7 @@ ppm;Graphics/pic.ppm;ppm_Portable_Pixelmap;ppm_Portable_Pixelmap
ras;Graphics/pic.ras;ras_Sun_Rasterfile;ras_Sun_Rasterfile
svm;Graphics/pic.svm;svm_StarView_Metafile;svm_StarView_Metafile:generic_Text
tif;Graphics/pic.tif;tif_Tag_Image_File;tif_Tag_Image_File:generic_Text
+webp;Graphics/pic.webp;webp_WebP;webp_WebP
wmf;Graphics/pic.wmf;wmf_MS_Windows_Metafile;wmf_MS_Windows_Metafile:generic_Text
diff --git a/filter/source/config/cache/typedetection.cxx b/filter/source/config/cache/typedetection.cxx
index ac4d9aed9f2a..b91ac31566af 100644
--- a/filter/source/config/cache/typedetection.cxx
+++ b/filter/source/config/cache/typedetection.cxx
@@ -232,6 +232,7 @@ int getFlatTypeRank(const OUString& rType)
"pcd_Photo_CD_Base",
"pcd_Photo_CD_Base4",
"pcd_Photo_CD_Base16",
+ "webp_WebP",
"impress_CGM_Computer_Graphics_Metafile", // There is binary and ascii variants ?
"draw_WordPerfect_Graphics",
"draw_Visio_Document",
diff --git a/filter/source/config/fragments/filters/WEBP___WebP.xcu b/filter/source/config/fragments/filters/WEBP___WebP.xcu
new file mode 100644
index 000000000000..9c650e3de42e
--- /dev/null
+++ b/filter/source/config/fragments/filters/WEBP___WebP.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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 .
+-->
+ <node oor:name="WEBP - WebP" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WEBP - WebP Image</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>webp_WebP</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/calc_webp_Export.xcu b/filter/source/config/fragments/filters/calc_webp_Export.xcu
new file mode 100644
index 000000000000..a6e5d18a3347
--- /dev/null
+++ b/filter/source/config/fragments/filters/calc_webp_Export.xcu
@@ -0,0 +1,20 @@
+<!--
+ * 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/.
+-->
+ <node oor:name="calc_webp_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.GraphicExportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WEBP - WebP Image</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>webp_WebP</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw_webp_Export.xcu b/filter/source/config/fragments/filters/draw_webp_Export.xcu
new file mode 100644
index 000000000000..e6da69197a61
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw_webp_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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 .
+-->
+ <node oor:name="draw_webp_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WEBP - WebP Image</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>webp_WebP</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/impress_webp_Export.xcu b/filter/source/config/fragments/filters/impress_webp_Export.xcu
new file mode 100644
index 000000000000..00284a272cba
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_webp_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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 .
+-->
+ <node oor:name="impress_webp_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WEBP - WebP Image</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>webp_WebP</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_web_webp_Export.xcu b/filter/source/config/fragments/filters/writer_web_webp_Export.xcu
new file mode 100644
index 000000000000..5273bb72228b
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_web_webp_Export.xcu
@@ -0,0 +1,21 @@
+<!--
+ * 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/.
+ *
+-->
+ <node oor:name="writer_web_webp_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.GraphicExportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WEBP - WebP Image</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>webp_WebP</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.WebDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_webp_Export.xcu b/filter/source/config/fragments/filters/writer_webp_Export.xcu
new file mode 100644
index 000000000000..ceb56a8c035f
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_webp_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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 .
+-->
+ <node oor:name="writer_webp_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.GraphicExportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WEBP - WebP Image</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>webp_WebP</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/webp_Export.xcu b/filter/source/config/fragments/internalgraphicfilters/webp_Export.xcu
new file mode 100644
index 000000000000..70ff15429734
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/webp_Export.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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 .
+-->
+ <node oor:name="webp_Export" oor:op="replace" >
+ <prop oor:name="Type"><value>webp_WebP</value></prop>
+ <prop oor:name="FormatName"><value>SVEWEBP</value></prop>
+ <prop oor:name="RealFilterName"/>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WEBP - WebP Image</value>
+ </prop>
+ <prop oor:name="Flags"><value>EXPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/webp_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/webp_Import.xcu
new file mode 100644
index 000000000000..cdce5c9e4047
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/webp_Import.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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 .
+-->
+ <node oor:name="webp_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>webp_WebP</value></prop>
+ <prop oor:name="FormatName"><value>SVIWEBP</value></prop>
+ <prop oor:name="RealFilterName"><value>WEBP - WebP</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WEBP - WebP Image</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/webp_WebP.xcu b/filter/source/config/fragments/types/webp_WebP.xcu
new file mode 100644
index 000000000000..e58984fbedc7
--- /dev/null
+++ b/filter/source/config/fragments/types/webp_WebP.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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 .
+-->
+ <node oor:name="webp_WebP" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>webp</value></prop>
+ <prop oor:name="MediaType"><value>image/webp</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>WEBP - WebP</value></prop>
+ <prop oor:name="UIName">
+ <value>WEBP - WebP Image</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/icon-themes/breeze/res/sx03223.png b/icon-themes/breeze/res/sx03223.png
new file mode 100644
index 000000000000..82e6f7b14f31
--- /dev/null
+++ b/icon-themes/breeze/res/sx03223.png
Binary files differ
diff --git a/icon-themes/breeze_dark/res/sx03223.png b/icon-themes/breeze_dark/res/sx03223.png
new file mode 100644
index 000000000000..82e6f7b14f31
--- /dev/null
+++ b/icon-themes/breeze_dark/res/sx03223.png
Binary files differ
diff --git a/icon-themes/breeze_dark_svg/res/sx03223.svg b/icon-themes/breeze_dark_svg/res/sx03223.svg
new file mode 100644
index 000000000000..576860153fb7
--- /dev/null
+++ b/icon-themes/breeze_dark_svg/res/sx03223.svg
@@ -0,0 +1 @@
+<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m2 2v8.992188l-1 1v.007812h1v2h12v-2.998047h1v-.009765l-1-1.0000005v-7.9921875zm1 1h10v5.9921875l-3.9941406-3.9921875h-.0058594v.0019531h-.0058594l-2.4960937 2.4921875-.4941407-.4941406h-.0039062-.0039062l-2.9960938 2.9941406zm2 1c-.554 0-1 .446-1 1s.446 1 1 1 1-.446 1-1-.446-1-1-1zm4 2.4101562 4 3.9980468v.591797h-2.992188l-2.8007808-2.796875zm-3 2 .5.5 2.0898438 2.0898438h-5.1816407zm-3 3.5898438h6.5898438l.0019531.001953h1.4082031v-.001953h2v1h-10z" fill="#4e9b06"/></svg> \ No newline at end of file
diff --git a/icon-themes/breeze_svg/res/sx03223.svg b/icon-themes/breeze_svg/res/sx03223.svg
new file mode 100644
index 000000000000..576860153fb7
--- /dev/null
+++ b/icon-themes/breeze_svg/res/sx03223.svg
@@ -0,0 +1 @@
+<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m2 2v8.992188l-1 1v.007812h1v2h12v-2.998047h1v-.009765l-1-1.0000005v-7.9921875zm1 1h10v5.9921875l-3.9941406-3.9921875h-.0058594v.0019531h-.0058594l-2.4960937 2.4921875-.4941407-.4941406h-.0039062-.0039062l-2.9960938 2.9941406zm2 1c-.554 0-1 .446-1 1s.446 1 1 1 1-.446 1-1-.446-1-1-1zm4 2.4101562 4 3.9980468v.591797h-2.992188l-2.8007808-2.796875zm-3 2 .5.5 2.0898438 2.0898438h-5.1816407zm-3 3.5898438h6.5898438l.0019531.001953h1.4082031v-.001953h2v1h-10z" fill="#4e9b06"/></svg> \ No newline at end of file
diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox
index 8702656bbb18..9a623b88dc8f 100644
--- a/include/sal/log-areas.dox
+++ b/include/sal/log-areas.dox
@@ -469,6 +469,7 @@ certain functionality.
@li @c vcl.emf - EMF/EMF+ processing
@li @c vcl.eventtesting
@li @c vcl.filter
+@li @c vcl.filter.webp
@li @c vcl.fonts - font-specific code
@li @c vcl.fonts.detail
@li @c vcl.gdi - the GDI part of VCL, devices, bitmaps, etc.
diff --git a/include/svl/inettype.hxx b/include/svl/inettype.hxx
index 13663fd3b260..dc5aa4f3a732 100644
--- a/include/svl/inettype.hxx
+++ b/include/svl/inettype.hxx
@@ -103,6 +103,7 @@ inline constexpr OUStringLiteral CONTENT_TYPE_STR_IMAGE_PCX = u"image/pcx";
inline constexpr OUStringLiteral CONTENT_TYPE_STR_IMAGE_PNG = u"image/png";
inline constexpr OUStringLiteral CONTENT_TYPE_STR_IMAGE_TIFF = u"image/tiff";
inline constexpr OUStringLiteral CONTENT_TYPE_STR_IMAGE_BMP = u"image/x-MS-bmp";
+inline constexpr OUStringLiteral CONTENT_TYPE_STR_IMAGE_WEBP = u"image/webp";
inline constexpr OUStringLiteral CONTENT_TYPE_STR_INET_MSG_RFC822 = u"message/rfc822";
inline constexpr OUStringLiteral CONTENT_TYPE_STR_INET_MULTI_ALTERNATIVE = u"multipart/alternative";
inline constexpr OUStringLiteral CONTENT_TYPE_STR_INET_MULTI_DIGEST = u"multipart/digest";
@@ -178,6 +179,7 @@ enum INetContentType
CONTENT_TYPE_IMAGE_PNG,
CONTENT_TYPE_IMAGE_TIFF,
CONTENT_TYPE_IMAGE_BMP,
+ CONTENT_TYPE_IMAGE_WEBP,
CONTENT_TYPE_TEXT_HTML,
CONTENT_TYPE_TEXT_PLAIN,
CONTENT_TYPE_TEXT_URL,
diff --git a/include/svtools/imagemgr.hxx b/include/svtools/imagemgr.hxx
index 6abe56b08bb0..a2b48247f4d2 100644
--- a/include/svtools/imagemgr.hxx
+++ b/include/svtools/imagemgr.hxx
@@ -37,6 +37,7 @@ enum class SvImageId {
GIF = START + 61,
HTML = START + 63,
JPG = START + 64,
+ WEBP = START + 65,
Math = START + 68,
MathTemplate = START + 69,
File = START + 74,
diff --git a/include/svx/strings.hrc b/include/svx/strings.hrc
index 7a5cbba78dbd..ebf12af91006 100644
--- a/include/svx/strings.hrc
+++ b/include/svx/strings.hrc
@@ -1394,6 +1394,7 @@
#define STR_IMAGE_PCT NC_("STR_IMAGE_PCT", "PCT image")
#define STR_IMAGE_SVG NC_("STR_IMAGE_SVG", "SVG image")
#define STR_IMAGE_BMP NC_("STR_IMAGE_BMP", "BMP image")
+#define STR_IMAGE_WEBP NC_("STR_IMAGE_WEBP", "WebP image")
#define STR_IMAGE_UNKNOWN NC_("STR_IMAGE_UNKNOWN", "Unknown")
#define STR_SWITCH NC_("STR_SWITCH", "Switch")
diff --git a/include/vcl/gfxlink.hxx b/include/vcl/gfxlink.hxx
index ad4caebc7b86..30228f339cd7 100644
--- a/include/vcl/gfxlink.hxx
+++ b/include/vcl/gfxlink.hxx
@@ -47,12 +47,13 @@ enum class GfxLinkType
NativeSvg = 9,
NativeMov = 10,
NativeBmp = 11,
- NativePdf = 12, // If a new type is added, make sure to change NativeLast too
+ NativePdf = 12,
+ NativeWebp = 13, // If a new type is added, make sure to change NativeLast too
// Alias for when the first native type starts and last native
// type ends.
NativeFirst = NativeGif,
- NativeLast = NativePdf,
+ NativeLast = NativeWebp,
};
class Graphic;
diff --git a/include/vcl/graphicfilter.hxx b/include/vcl/graphicfilter.hxx
index b1eba2b141ed..2d2f071e7d71 100644
--- a/include/vcl/graphicfilter.hxx
+++ b/include/vcl/graphicfilter.hxx
@@ -89,6 +89,7 @@ namespace o3tl
#define IMP_PCD "SVPCD"
#define IMP_PBM "SVPBM"
#define IMP_DXF "SVDXF"
+#define IMP_WEBP "SVIWEBP"
#define EXP_BMP "SVBMP"
#define EXP_SVMETAFILE "SVMETAFILE"
@@ -101,6 +102,7 @@ namespace o3tl
#define EXP_TIFF "SVTIFF"
#define EXP_EPS "SVEEPS"
#define EXP_GIF "SVEGIF"
+#define EXP_WEBP "SVEWEBP"
inline constexpr OUStringLiteral BMP_SHORTNAME = u"BMP";
@@ -115,6 +117,7 @@ inline constexpr OUStringLiteral WMF_SHORTNAME = u"WMF";
inline constexpr OUStringLiteral EMF_SHORTNAME = u"EMF";
inline constexpr OUStringLiteral SVG_SHORTNAME = u"SVG";
inline constexpr OUStringLiteral PDF_SHORTNAME = u"PDF";
+inline constexpr OUStringLiteral WEBP_SHORTNAME = u"WEBP";
// Info class for all supported file formats
@@ -137,6 +140,7 @@ enum class GraphicFileFormat
TGA = 0x000e,
PSD = 0x000f,
EPS = 0x0010,
+ WEBP = 0x0011,
DXF = 0x00f1,
MET = 0x00f2,
PCT = 0x00f3,
@@ -184,6 +188,7 @@ class VCL_DLLPUBLIC GraphicDescriptor final
bool ImpDetectTGA( SvStream& rStm, bool bExtendedInfo );
bool ImpDetectPSD( SvStream& rStm, bool bExtendedInfo );
bool ImpDetectEPS( SvStream& rStm, bool bExtendedInfo );
+ bool ImpDetectWEBP( SvStream& rStm, bool bExtendedInfo );
bool ImpDetectDXF( SvStream& rStm, bool bExtendedInfo );
bool ImpDetectMET( SvStream& rStm, bool bExtendedInfo );
bool ImpDetectPCT( SvStream& rStm, bool bExtendedInfo );
@@ -374,6 +379,7 @@ public:
static ErrCode readPCD(SvStream & rStream, Graphic & rGraphic);
static ErrCode readPBM(SvStream & rStream, Graphic & rGraphic);
static ErrCode readDXF(SvStream & rStream, Graphic & rGraphic);
+ static ErrCode readWEBP(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType);
private:
OUString aFilterPath;
diff --git a/include/vcl/salctype.hxx b/include/vcl/salctype.hxx
index 409fc5a79993..71f256b1986e 100644
--- a/include/vcl/salctype.hxx
+++ b/include/vcl/salctype.hxx
@@ -37,7 +37,8 @@ enum class ConvertDataFormat
TIF,
WMF,
EMF,
- SVG
+ SVG,
+ WEBP
};
class SvStream;
diff --git a/readlicense_oo/license/license.xml b/readlicense_oo/license/license.xml
index ae03b3943946..2773e9df790f 100644
--- a/readlicense_oo/license/license.xml
+++ b/readlicense_oo/license/license.xml
@@ -1141,6 +1141,37 @@
glennrp at users.sourceforge.net<br />
February 3, 2011  </p>
</div>
+ <div class="LIBWEBP">
+ <h2>libwebp</h2>
+ <p>The following software may be included in this product: libwebp. Use of any of this software is governed by
+ the terms of the license below:</p>
+ <p>Copyright (c) 2010, Google Inc. All rights reserved.</p>
+ <p>Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:</p>
+ <ol>
+ <li>Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.</li>
+ <li>Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.</li>
+ <li>Neither the name of Google nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.</li>
+ </ol>
+ <p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</p>
+ </div>
<div class="PAGEMAKER">
<h2>libpagemaker</h2>
<p>The following software may be included in this product: libpagemaker. Use of any of this software is governed
diff --git a/scp2/source/draw/registryitem_draw.scp b/scp2/source/draw/registryitem_draw.scp
index 1d1d9d877a3f..66717f972210 100644
--- a/scp2/source/draw/registryitem_draw.scp
+++ b/scp2/source/draw/registryitem_draw.scp
@@ -1092,6 +1092,7 @@ CONDITIONAL_REGISTER_DOC_EXTENSION( Tiff, gid_Module_Prg_Draw_Other_Reg, tiff,
CONDITIONAL_REGISTER_DOC_EXTENSION( Xbm, gid_Module_Prg_Draw_Other_Reg, xbm, XBM, X_BITMAP, 5, sdraw.exe, open, Draw )
CONDITIONAL_REGISTER_DOC_EXTENSION( Xpm, gid_Module_Prg_Draw_Other_Reg, xpm, XPM, X_PIXMAP, 5, sdraw.exe, open, Draw )
CONDITIONAL_REGISTER_DOC_EXTENSION( PCD, gid_Module_Prg_Draw_Other_Reg, pcd, PCD, KODAK_PHOTO_CD_IMAGE, 5, sdraw.exe, open, Draw )
+CONDITIONAL_REGISTER_DOC_EXTENSION( Webp, gid_Module_Prg_Draw_Other_Reg, webp, WEBP, WEBP, 5, sdraw.exe, open, Draw )
// registering ms-visio URI scheme handler
CONDITIONAL_REGISTER_URI_HANDLER( ms-visio, ms_visio, gid_Module_Prg_Draw_MSO_Reg, SELECT_VISIO )
diff --git a/solenv/sanitizers/ui/svt.suppr b/solenv/sanitizers/ui/svt.suppr
index 40c22f896163..188bd9ea0289 100644
--- a/solenv/sanitizers/ui/svt.suppr
+++ b/solenv/sanitizers/ui/svt.suppr
@@ -1,6 +1,6 @@
svtools/uiconfig/ui/checkboxcontrol.ui://GtkCheckButton[@id='checkbox'] button-no-label
svtools/uiconfig/ui/editcontrol.ui://GtkEntry[@id='entry'] no-labelled-by
-svtools/uiconfig/ui/graphicexport.ui://GtkScale[@id='compressionjpgsb'] no-labelled-by
+svtools/uiconfig/ui/graphicexport.ui://GtkScale[@id='compressionjpgwebpsb'] no-labelled-by
svtools/uiconfig/ui/graphicexport.ui://GtkScale[@id='compressionpngsb'] no-labelled-by
svtools/uiconfig/ui/graphicexport.ui://GtkLabel[@id='estsizeft'] orphan-label
svtools/uiconfig/ui/placeedit.ui://GtkButton[@id='repositoriesRefresh'] button-no-label
diff --git a/svtools/inc/bitmaps.hlst b/svtools/inc/bitmaps.hlst
index 35332e05ede0..c9c5bd88dc50 100644
--- a/svtools/inc/bitmaps.hlst
+++ b/svtools/inc/bitmaps.hlst
@@ -39,6 +39,7 @@
#define BMP_MET_SC "res/sx03218.png"
#define BMP_PNG_SC "res/sx03219.png"
#define BMP_SVM_SC "res/sx03222.png"
+#define BMP_WEBP_SC "res/sx03223.png"
#define BMP_GLOBAL_DOC_SC "res/sx03226.png"
#define BMP_DRAW_SC "res/sx03227.png"
#define BMP_DRAWTEMPLATE_SC "res/sx03228.png"
@@ -85,6 +86,7 @@
#define BMP_MET_LC "res/lx03218.png"
#define BMP_PNG_LC "res/lx03219.png"
#define BMP_SVM_LC "res/lx03222.png"
+#define BMP_WEBP_LC "res/lx03223.png"
#define BMP_GLOBAL_DOC_LC "res/lx03226.png"
#define BMP_DRAW_LC "res/lx03227.png"
#define BMP_DRAWTEMPLATE_LC "res/lx03228.png"
diff --git a/svtools/source/filter/exportdialog.cxx b/svtools/source/filter/exportdialog.cxx
index 76d90f7b8e06..2d563e02b274 100644
--- a/svtools/source/filter/exportdialog.cxx
+++ b/svtools/source/filter/exportdialog.cxx
@@ -57,6 +57,7 @@
#define FORMAT_EMF 13
#define FORMAT_EPS 14
#define FORMAT_SVG 16
+#define FORMAT_WEBP 17
#define UNIT_DEFAULT -1
#define UNIT_INCH 0
@@ -89,6 +90,8 @@ static sal_Int16 GetFilterFormat(std::u16string_view rExt)
nFormat = FORMAT_EPS;
else if ( rExt == u"SVG" )
nFormat = FORMAT_SVG;
+ else if ( rExt == u"WEBP" )
+ nFormat = FORMAT_WEBP;
return nFormat;
}
@@ -293,6 +296,15 @@ uno::Sequence< beans::PropertyValue > ExportDialog::GetFilterData( bool bUpdateC
pFilterOptions->WriteInt32("CompressionMode", nCheck);
}
break;
+
+ case FORMAT_WEBP :
+ {
+ assert(mpSbCompression);
+ pFilterOptions->WriteInt32("Quality", static_cast<sal_Int32>(mpSbCompression->get_value()));
+ pFilterOptions->WriteBool("Lossless", mxCbLossless->get_active());
+ }
+ break;
+
}
uno::Sequence< beans::PropertyValue > aRet( pFilterOptions->GetFilterData() );
@@ -582,12 +594,13 @@ ExportDialog::ExportDialog(FltCallDialogParameter& rPara,
, mxLbResolution(m_xBuilder->weld_combo_box("resolutionlb"))
, mxColorDepth(m_xBuilder->weld_widget("colordepth"))
, mxLbColorDepth(m_xBuilder->weld_combo_box("colordepthlb"))
- , mxJPGQuality(m_xBuilder->weld_widget("jpgquality"))
+ , mxJPGWEBPQuality(m_xBuilder->weld_widget("jpgwebpquality"))
, mxPNGCompression(m_xBuilder->weld_widget("pngcompression"))
, mxSbPngCompression(m_xBuilder->weld_scale("compressionpngsb"))
, mxNfPngCompression(m_xBuilder->weld_spin_button("compressionpngnf"))
- , mxSbJpgCompression(m_xBuilder->weld_scale("compressionjpgsb"))
- , mxNfJpgCompression(m_xBuilder->weld_spin_button("compressionjpgnf"))
+ , mxSbJpgWebpCompression(m_xBuilder->weld_scale("compressionjpgwebpsb"))
+ , mxNfJpgWebpCompression(m_xBuilder->weld_spin_button("compressionjpgwebpnf"))
+ , mxCbLossless(m_xBuilder->weld_check_button("losslesscb"))
, mxMode(m_xBuilder->weld_widget("mode"))
, mxCbInterlaced(m_xBuilder->weld_check_button("interlacedcb"))
, mxBMPCompression(m_xBuilder->weld_widget("bmpcompression"))
@@ -681,6 +694,8 @@ ExportDialog::ExportDialog(FltCallDialogParameter& rPara,
mxCbInterlaced->connect_toggled( LINK( this, ExportDialog, UpdateHdl ) );
+ mxCbLossless->connect_toggled( LINK( this, ExportDialog, UpdateHdlLossless ) );
+
mxCbSaveTransparency->connect_toggled( LINK( this, ExportDialog, UpdateHdl ) );
mxModifyDimension->connect_toggled( LINK( this, ExportDialog, UpdateLock ) );
@@ -761,15 +776,16 @@ void ExportDialog::createFilterOptions()
mxColorDepth->show();
// Quality
- mxJPGQuality->show();
+ mxJPGWEBPQuality->show();
sal_Int32 nQuality = mpFilterOptionsItem->ReadInt32("Quality", 75);
if ((nQuality < 1 ) || (nQuality > 100))
nQuality = 75;
- mpSbCompression = mxSbJpgCompression.get();
- mpNfCompression = mxNfJpgCompression.get();
+ mpSbCompression = mxSbJpgWebpCompression.get();
+ mpNfCompression = mxNfJpgWebpCompression.get();
mpSbCompression->set_range(1, 100);
mpNfCompression->set_range(1, 100);
mpNfCompression->set_value(nQuality);
+ mxCbLossless->hide(); // only for WebP
}
break;
case FORMAT_PNG :
@@ -852,6 +868,24 @@ void ExportDialog::createFilterOptions()
mxRbEPSCompressionNone->set_active( nCompr != 1 );
}
break;
+ case FORMAT_WEBP :
+ {
+ // Quality
+ mxJPGWEBPQuality->show();
+ sal_Int32 nQuality = mpFilterOptionsItem->ReadInt32("Quality", 75);
+ if ((nQuality < 1 ) || (nQuality > 100))
+ nQuality = 75;
+ mpSbCompression = mxSbJpgWebpCompression.get();
+ mpNfCompression = mxNfJpgWebpCompression.get();
+ mpSbCompression->set_range(1, 100);
+ mpNfCompression->set_range(1, 100);
+ mpNfCompression->set_value(nQuality);
+
+ // Lossless
+ mxCbLossless->set_active(mpFilterOptionsItem->ReadBool("Lossless", true));
+ UpdateHdlLossless(*mxCbLossless);
+ }
+ break;
}
}
@@ -995,6 +1029,13 @@ IMPL_LINK_NOARG(ExportDialog, UpdateHdl, weld::Toggleable&, void)
updateControls();
}
+IMPL_LINK_NOARG(ExportDialog, UpdateHdlLossless, weld::Toggleable&, void)
+{
+ mpSbCompression->set_sensitive(!mxCbLossless->get_active());
+ mpNfCompression->set_sensitive(!mxCbLossless->get_active());
+ updateControls();
+}
+
IMPL_LINK_NOARG(ExportDialog, UpdateLock, weld::Toggleable&, void)
{
if (mxModifyResolution->get_active())
diff --git a/svtools/source/filter/exportdialog.hxx b/svtools/source/filter/exportdialog.hxx
index 28953ee0224c..1c7c63953a16 100644
--- a/svtools/source/filter/exportdialog.hxx
+++ b/svtools/source/filter/exportdialog.hxx
@@ -104,14 +104,16 @@ private:
std::unique_ptr<weld::Widget> mxColorDepth;
std::unique_ptr<weld::ComboBox> mxLbColorDepth;
- std::unique_ptr<weld::Widget> mxJPGQuality;
+ std::unique_ptr<weld::Widget> mxJPGWEBPQuality;
std::unique_ptr<weld::Widget> mxPNGCompression;
std::unique_ptr<weld::Scale> mxSbPngCompression;
std::unique_ptr<weld::SpinButton> mxNfPngCompression;
- std::unique_ptr<weld::Scale> mxSbJpgCompression;
- std::unique_ptr<weld::SpinButton> mxNfJpgCompression;
+ std::unique_ptr<weld::Scale> mxSbJpgWebpCompression;
+ std::unique_ptr<weld::SpinButton> mxNfJpgWebpCompression;
+
+ std::unique_ptr<weld::CheckButton> mxCbLossless;
std::unique_ptr<weld::Widget> mxMode;
std::unique_ptr<weld::CheckButton> mxCbInterlaced;
@@ -152,6 +154,7 @@ private:
DECL_LINK(UpdateHdlMtfSizeY, weld::SpinButton&, void);
DECL_LINK(UpdateHdlNfResolution, weld::SpinButton&, void);
DECL_LINK(SbCompressionUpdateHdl, weld::Scale&, void);
+ DECL_LINK(UpdateHdlLossless, weld::Toggleable&, void);
DECL_LINK(OK, weld::Button&, void);
diff --git a/svtools/source/misc/imagemgr.cxx b/svtools/source/misc/imagemgr.cxx
index 58cba39f574f..7ac01619162e 100644
--- a/svtools/source/misc/imagemgr.cxx
+++ b/svtools/source/misc/imagemgr.cxx
@@ -153,6 +153,7 @@ SvtExtensionResIdMapping_Impl const ExtensionMap_Impl[] =
{ "url", false, STR_DESCRIPTION_LINK, SvImageId::NONE },
{ "vor", false, STR_DESCRIPTION_SOFFICE_TEMPLATE_DOC, SvImageId::WriterTemplate },
{ "vxd", true, STR_DESCRIPTION_SYSFILE, SvImageId::NONE },
+ { "webp", true, STR_DESCRIPTION_GRAPHIC_DOC, SvImageId::WEBP },
{ "wmf", true, STR_DESCRIPTION_GRAPHIC_DOC, SvImageId::WMF },
{ "xls", false, STR_DESCRIPTION_EXCEL_DOC, SvImageId::Calc },
{ "xlt", false, STR_DESCRIPTION_EXCEL_TEMPLATE_DOC, SvImageId::CalcTemplate },
@@ -568,6 +569,8 @@ static OUString GetImageNameFromList_Impl( SvImageId nImageId, vcl::ImageType eI
return BMP_TEXTFILE_LC;
case SvImageId::TIFF:
return BMP_TIFF_LC;
+ case SvImageId::WEBP:
+ return BMP_WEBP_LC;
case SvImageId::WMF:
return BMP_WMF_LC;
case SvImageId::Writer:
@@ -667,6 +670,8 @@ static OUString GetImageNameFromList_Impl( SvImageId nImageId, vcl::ImageType eI
return BMP_TEXTFILE_SC;
case SvImageId::TIFF:
return BMP_TIFF_SC;
+ case SvImageId::WEBP:
+ return BMP_WEBP_SC;
case SvImageId::WMF:
return BMP_WMF_SC;
case SvImageId::Writer:
diff --git a/svtools/uiconfig/ui/graphicexport.ui b/svtools/uiconfig/ui/graphicexport.ui
index 223dd3dd456c..27cf6d17f04e 100644
--- a/svtools/uiconfig/ui/graphicexport.ui
+++ b/svtools/uiconfig/ui/graphicexport.ui
@@ -368,12 +368,12 @@
</packing>
</child>
<child>
- <object class="GtkFrame" id="jpgquality">
+ <object class="GtkFrame" id="jpgwebpquality">
<property name="can-focus">False</property>
<property name="label-xalign">0</property>
<property name="shadow-type">none</property>
<child>
- <!-- n-columns=2 n-rows=1 -->
+ <!-- n-columns=2 n-rows=2 -->
<object class="GtkGrid" id="grid2">
<property name="visible">True</property>
<property name="can-focus">False</property>
@@ -381,7 +381,27 @@
<property name="margin-top">6</property>
<property name="column-spacing">6</property>
<child>
- <object class="GtkSpinButton" id="compressionjpgnf">
+ <object class="GtkCheckButton" id="losslesscb">
+ <property name="label" translatable="yes" context="graphicexport|losslesscb">Lossless</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="active">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="losslesscb-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="graphicexport|extended_tip|losslesscb">Lossless images do not lose quality but result in larger files.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="compressionjpgwebpnf">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="activates-default">True</property>
@@ -389,18 +409,18 @@
<property name="truncate-multiline">True</property>
<property name="adjustment">adjustment1</property>
<child internal-child="accessible">
- <object class="AtkObject" id="compressionjpgnf-atkobject">
- <property name="AtkObject::accessible-description" translatable="yes" context="graphicexport|extended_tip|compressionjpgnf">Sets the quality for the export. Choose from a low quality with minimal file size, up to a high quality and big file size.</property>
+ <object class="AtkObject" id="compressionjpgwebpnf-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="graphicexport|extended_tip|compressionjpgwebpnf">Sets the quality for the export. Choose from a low quality with minimal file size, up to a high quality and big file size.</property>
</object>
</child>
</object>
<packing>
<property name="left-attach">1</property>
- <property name="top-attach">0</property>
+ <property name="top-attach">1</property>
</packing>
</child>
<child>
- <object class="GtkScale" id="compressionjpgsb">
+ <object class="GtkScale" id="compressionjpgwebpsb">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="valign">center</property>
@@ -410,7 +430,7 @@
</object>
<packing>
<property name="left-attach">0</property>
- <property name="top-attach">0</property>
+ <property name="top-attach">1</property>
</packing>
</child>
</object>
diff --git a/svx/source/core/graphichelper.cxx b/svx/source/core/graphichelper.cxx
index a6b51e62fc5d..1cb36105ed27 100644
--- a/svx/source/core/graphichelper.cxx
+++ b/svx/source/core/graphichelper.cxx
@@ -118,6 +118,9 @@ void GraphicHelper::GetPreferredExtension( OUString& rExtension, const Graphic&
case GfxLinkType::NativePdf:
aExtension = "pdf";
break;
+ case GfxLinkType::NativeWebp:
+ aExtension = "webp";
+ break;
default:
break;
}
@@ -159,6 +162,9 @@ OUString GraphicHelper::GetImageType(const Graphic& rGraphic)
case GfxLinkType::NativeBmp:
aGraphicTypeString = SvxResId(STR_IMAGE_BMP);
break;
+ case GfxLinkType::NativeWebp:
+ aGraphicTypeString = SvxResId(STR_IMAGE_WEBP);
+ break;
default:
break;
}
diff --git a/svx/source/gallery2/galtheme.cxx b/svx/source/gallery2/galtheme.cxx
index dff3696b8cd8..4a9d10e609ff 100644
--- a/svx/source/gallery2/galtheme.cxx
+++ b/svx/source/gallery2/galtheme.cxx
@@ -407,6 +407,7 @@ bool GalleryTheme::InsertGraphic(const Graphic& rGraphic, sal_uInt32 nInsertPos)
case GfxLinkType::NativeMet: nExportFormat = ConvertDataFormat::MET; break;
case GfxLinkType::NativePct: nExportFormat = ConvertDataFormat::PCT; break;
case GfxLinkType::NativeSvg: nExportFormat = ConvertDataFormat::SVG; break;
+ case GfxLinkType::NativeWebp: nExportFormat = ConvertDataFormat::WEBP; break;
default:
break;
}
diff --git a/svx/source/xml/xmlgrhlp.cxx b/svx/source/xml/xmlgrhlp.cxx
index 522e6c076d19..6a8c7c08fce5 100644
--- a/svx/source/xml/xmlgrhlp.cxx
+++ b/svx/source/xml/xmlgrhlp.cxx
@@ -700,6 +700,7 @@ OUString SvXMLGraphicHelper::implSaveGraphic(css::uno::Reference<css::graphic::X
break;
}
case GfxLinkType::NativePdf: aExtension = ".pdf"; break;
+ case GfxLinkType::NativeWebp: aExtension = ".webp"; break;
default:
aExtension = ".grf";
diff --git a/svx/source/xoutdev/_xoutbmp.cxx b/svx/source/xoutdev/_xoutbmp.cxx
index 8eaec8e5a5fc..cb690df32623 100644
--- a/svx/source/xoutdev/_xoutbmp.cxx
+++ b/svx/source/xoutdev/_xoutbmp.cxx
@@ -34,6 +34,7 @@ constexpr OUStringLiteral FORMAT_BMP = u"bmp";
constexpr OUStringLiteral FORMAT_GIF = u"gif";
constexpr OUStringLiteral FORMAT_JPG = u"jpg";
constexpr OUStringLiteral FORMAT_PNG = u"png";
+constexpr OUStringLiteral FORMAT_WEBP = u"webp";
using namespace com::sun::star;
@@ -182,6 +183,7 @@ ErrCode XOutBitmap::WriteGraphic( const Graphic& rGraphic, OUString& rFileName,
case GfxLinkType::NativeJpg: aExt = FORMAT_JPG; break;
case GfxLinkType::NativePng: aExt = FORMAT_PNG; break;
+ case GfxLinkType::NativeWebp: aExt = FORMAT_WEBP; break;
default:
break;
diff --git a/vcl/CppunitTest_vcl_filters_test.mk b/vcl/CppunitTest_vcl_filters_test.mk
index ab5108f51b1c..f9f8e40cca98 100644
--- a/vcl/CppunitTest_vcl_filters_test.mk
+++ b/vcl/CppunitTest_vcl_filters_test.mk
@@ -22,6 +22,7 @@ $(eval $(call gb_CppunitTest_add_exception_objects,vcl_filters_test, \
vcl/qa/cppunit/graphicfilter/filters-test \
vcl/qa/cppunit/graphicfilter/filters-tiff-test \
vcl/qa/cppunit/graphicfilter/filters-tga-test \
+ vcl/qa/cppunit/graphicfilter/filters-webp-test \
))
$(eval $(call gb_CppunitTest_set_include,vcl_filters_test,\
diff --git a/vcl/Executable_webpfuzzer.mk b/vcl/Executable_webpfuzzer.mk
new file mode 100644
index 000000000000..3851fbe52cd1
--- /dev/null
+++ b/vcl/Executable_webpfuzzer.mk
@@ -0,0 +1,45 @@
+# -*- 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/.
+#
+
+include $(SRCDIR)/vcl/commonfuzzer.mk
+
+$(eval $(call gb_Executable_Executable,webpfuzzer))
+
+$(eval $(call gb_Executable_use_api,webpfuzzer,\
+ offapi \
+ udkapi \
+))
+
+$(eval $(call gb_Executable_use_externals,webpfuzzer,\
+ $(fuzzer_externals) \
+))
+
+$(eval $(call gb_Executable_set_include,webpfuzzer,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/vcl/inc \
+))
+
+$(eval $(call gb_Executable_use_libraries,webpfuzzer,\
+ $(fuzzer_core_libraries) \
+))
+
+$(eval $(call gb_Executable_use_static_libraries,webpfuzzer,\
+ $(fuzzer_statics) \
+))
+
+$(eval $(call gb_Executable_add_exception_objects,webpfuzzer,\
+ vcl/workben/webpfuzzer \
+))
+
+$(eval $(call gb_Executable_add_libs,webpfuzzer,\
+ $(LIB_FUZZING_ENGINE) \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 7886b5b271b5..90d432ee559b 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -89,6 +89,7 @@ $(eval $(call gb_Library_use_externals,vcl,\
libeot \
libjpeg \
libpng \
+ libwebp \
mdds_headers \
$(if $(filter PDFIUM,$(BUILD_TYPE)),pdfium) \
))
@@ -470,6 +471,8 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/filter/wmf/wmfwr \
vcl/source/filter/png/PngImageReader \
vcl/source/filter/png/pngwrite \
+ vcl/source/filter/webp/reader \
+ vcl/source/filter/webp/writer \
vcl/source/font/DirectFontSubstitution \
vcl/source/font/Feature \
vcl/source/font/FeatureCollector \
diff --git a/vcl/Module_vcl.mk b/vcl/Module_vcl.mk
index f85bac2f1cb7..23a45b358da3 100644
--- a/vcl/Module_vcl.mk
+++ b/vcl/Module_vcl.mk
@@ -199,6 +199,7 @@ $(eval $(call gb_Module_add_targets,vcl,\
Executable_htmlfuzzer \
Executable_sftfuzzer \
Executable_dbffuzzer \
+ Executable_webpfuzzer \
))
endif
diff --git a/vcl/inc/filter/WebpReader.hxx b/vcl/inc/filter/WebpReader.hxx
new file mode 100644
index 000000000000..fd8cc4894a26
--- /dev/null
+++ b/vcl/inc/filter/WebpReader.hxx
@@ -0,0 +1,28 @@
+/* -*- 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/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <vcl/graph.hxx>
+
+VCL_DLLPUBLIC bool ImportWebpGraphic(SvStream& rStream, Graphic& rGraphic);
+
+bool ReadWebpInfo(SvStream& rStream, Size& pixelSize, sal_uInt16& bitsPerPixel, bool& hasAlpha);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/filter/WebpWriter.hxx b/vcl/inc/filter/WebpWriter.hxx
new file mode 100644
index 000000000000..d3b6431c63ff
--- /dev/null
+++ b/vcl/inc/filter/WebpWriter.hxx
@@ -0,0 +1,29 @@
+/* -*- 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/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <tools/stream.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/FilterConfigItem.hxx>
+
+VCL_DLLPUBLIC bool ExportWebpGraphic(SvStream& rStream, const Graphic& rGraphic,
+ FilterConfigItem* pFilterConfigItem);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/graphic/GraphicFormatDetector.hxx b/vcl/inc/graphic/GraphicFormatDetector.hxx
index f2f0393caeee..34a8b16a2c5d 100644
--- a/vcl/inc/graphic/GraphicFormatDetector.hxx
+++ b/vcl/inc/graphic/GraphicFormatDetector.hxx
@@ -77,6 +77,7 @@ public:
bool checkTGA();
bool checkMOV();
bool checkPDF();
+ bool checkWEBP();
};
}
diff --git a/vcl/inc/graphic/UnoGraphicDescriptor.hxx b/vcl/inc/graphic/UnoGraphicDescriptor.hxx
index 6a233e09ae16..096b30fd694e 100644
--- a/vcl/inc/graphic/UnoGraphicDescriptor.hxx
+++ b/vcl/inc/graphic/UnoGraphicDescriptor.hxx
@@ -51,6 +51,7 @@
#define MIMETYPE_EMF "image/x-emf"
#define MIMETYPE_SVG "image/svg+xml"
#define MIMETYPE_PDF "application/pdf"
+#define MIMETYPE_WEBP "image/webp"
inline constexpr OUStringLiteral MIMETYPE_VCLGRAPHIC = u"image/x-vclgraphic";
namespace comphelper { class PropertySetInfo; }
diff --git a/vcl/qa/cppunit/GraphicDescriptorTest.cxx b/vcl/qa/cppunit/GraphicDescriptorTest.cxx
index 652393ae9b63..865202cedbf5 100644
--- a/vcl/qa/cppunit/GraphicDescriptorTest.cxx
+++ b/vcl/qa/cppunit/GraphicDescriptorTest.cxx
@@ -34,6 +34,7 @@ class GraphicDescriptorTest : public test::BootstrapFixtureBase
void testDetectGIF();
void testDetectTIF();
void testDetectBMP();
+ void testDetectWEBP();
CPPUNIT_TEST_SUITE(GraphicDescriptorTest);
CPPUNIT_TEST(testDetectPNG);
@@ -41,6 +42,7 @@ class GraphicDescriptorTest : public test::BootstrapFixtureBase
CPPUNIT_TEST(testDetectGIF);
CPPUNIT_TEST(testDetectTIF);
CPPUNIT_TEST(testDetectBMP);
+ CPPUNIT_TEST(testDetectWEBP);
CPPUNIT_TEST_SUITE_END();
};
@@ -138,6 +140,20 @@ void GraphicDescriptorTest::testDetectBMP()
CPPUNIT_ASSERT_EQUAL(MapUnit::MapMM, aGraphic.GetPrefMapMode().GetMapUnit());
}
+void GraphicDescriptorTest::testDetectWEBP()
+{
+ SvMemoryStream aStream;
+ createBitmapAndExportForType(aStream, u"webp");
+
+ GraphicDescriptor aDescriptor(aStream, nullptr);
+ aDescriptor.Detect(true);
+
+ CPPUNIT_ASSERT_EQUAL(GraphicFileFormat::WEBP, aDescriptor.GetFileFormat());
+
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aDescriptor.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(100), aDescriptor.GetSizePixel().Height());
+}
+
} // namespace
CPPUNIT_TEST_SUITE_REGISTRATION(GraphicDescriptorTest);
diff --git a/vcl/qa/cppunit/GraphicFormatDetectorTest.cxx b/vcl/qa/cppunit/GraphicFormatDetectorTest.cxx
index 264a0e8cd48d..4c16bfc82e1b 100644
--- a/vcl/qa/cppunit/GraphicFormatDetectorTest.cxx
+++ b/vcl/qa/cppunit/GraphicFormatDetectorTest.cxx
@@ -47,6 +47,7 @@ class GraphicFormatDetectorTest : public test::BootstrapFixtureBase
void testDetectSVGZ();
void testDetectPDF();
void testDetectEPS();
+ void testDetectWEBP();
void testMatchArray();
void testCheckArrayForMatchingStrings();
@@ -67,6 +68,7 @@ class GraphicFormatDetectorTest : public test::BootstrapFixtureBase
CPPUNIT_TEST(testDetectSVGZ);
CPPUNIT_TEST(testDetectPDF);
CPPUNIT_TEST(testDetectEPS);
+ CPPUNIT_TEST(testDetectWEBP);
CPPUNIT_TEST(testMatchArray);
CPPUNIT_TEST(testCheckArrayForMatchingStrings);
CPPUNIT_TEST_SUITE_END();
@@ -312,6 +314,21 @@ void GraphicFormatDetectorTest::testDetectEPS()
CPPUNIT_ASSERT_EQUAL(OUString("EPS"), rFormatExtension);
}
+void GraphicFormatDetectorTest::testDetectWEBP()
+{
+ SvFileStream aFileStream(getFullUrl(u"TypeDetectionExample.webp"), StreamMode::READ);
+ vcl::GraphicFormatDetector aDetector(aFileStream, "WEBP");
+
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkWEBP());
+
+ aFileStream.Seek(aDetector.mnStreamPosition);
+
+ OUString rFormatExtension;
+ CPPUNIT_ASSERT(vcl::peekGraphicFormat(aFileStream, rFormatExtension, false));
+ CPPUNIT_ASSERT_EQUAL(OUString("WEBP"), rFormatExtension);
+}
+
void GraphicFormatDetectorTest::testMatchArray()
{
std::string aString("<?xml version=\"1.0\" standalone=\"no\"?>\n"
diff --git a/vcl/qa/cppunit/GraphicTest.cxx b/vcl/qa/cppunit/GraphicTest.cxx
index 44ad1df12829..2e398c544c79 100644
--- a/vcl/qa/cppunit/GraphicTest.cxx
+++ b/vcl/qa/cppunit/GraphicTest.cxx
@@ -81,6 +81,7 @@ private:
void testLoadXPM();
void testLoadPCX();
void testLoadEPS();
+ void testLoadWEBP();
void testAvailableThreaded();
@@ -118,6 +119,7 @@ private:
CPPUNIT_TEST(testLoadXPM);
CPPUNIT_TEST(testLoadPCX);
CPPUNIT_TEST(testLoadEPS);
+ CPPUNIT_TEST(testLoadWEBP);
CPPUNIT_TEST(testAvailableThreaded);
@@ -305,7 +307,7 @@ void GraphicTest::testUnloadedGraphic()
void GraphicTest::testUnloadedGraphicLoading()
{
- const OUString aFormats[] = { "png", "gif", "jpg", "tif" };
+ const OUString aFormats[] = { "png", "gif", "jpg", "tif", "webp" };
for (OUString const& sFormat : aFormats)
{
@@ -1310,6 +1312,14 @@ void GraphicTest::testLoadEPS()
CPPUNIT_ASSERT_EQUAL(GraphicType::GdiMetafile, aGraphic.GetType());
}
+void GraphicTest::testLoadWEBP()
+{
+ Graphic aGraphic = loadGraphic(u"TypeDetectionExample.webp");
+ CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(10), aGraphic.GetSizePixel().Height());
+}
+
void GraphicTest::testAvailableThreaded()
{
Graphic jpgGraphic1 = importUnloadedGraphic(u"TypeDetectionExample.jpg");
diff --git a/vcl/qa/cppunit/data/TypeDetectionExample.webp b/vcl/qa/cppunit/data/TypeDetectionExample.webp
new file mode 100644
index 000000000000..e85ae121637b
--- /dev/null
+++ b/vcl/qa/cppunit/data/TypeDetectionExample.webp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/webp/alpha_lossless.webp b/vcl/qa/cppunit/graphicfilter/data/webp/alpha_lossless.webp
new file mode 100644
index 000000000000..abb67cc5f4b6
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/webp/alpha_lossless.webp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/webp/alpha_lossy.webp b/vcl/qa/cppunit/graphicfilter/data/webp/alpha_lossy.webp
new file mode 100644
index 000000000000..c587b1bb22c0
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/webp/alpha_lossy.webp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/webp/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/webp/fail/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/webp/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/webp/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/webp/indeterminate/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/webp/indeterminate/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/webp/noalpha_lossless.webp b/vcl/qa/cppunit/graphicfilter/data/webp/noalpha_lossless.webp
new file mode 100644
index 000000000000..b22ebc3b28bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/webp/noalpha_lossless.webp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/webp/noalpha_lossy.webp b/vcl/qa/cppunit/graphicfilter/data/webp/noalpha_lossy.webp
new file mode 100644
index 000000000000..c118febb0e9a
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/webp/noalpha_lossy.webp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/webp/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/webp/pass/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/webp/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/filters-test.cxx b/vcl/qa/cppunit/graphicfilter/filters-test.cxx
index 22078cf9de65..f10de06fc837 100644
--- a/vcl/qa/cppunit/graphicfilter/filters-test.cxx
+++ b/vcl/qa/cppunit/graphicfilter/filters-test.cxx
@@ -145,6 +145,8 @@ void VclFiltersTest::testExportImport()
checkExportImport(u"bmp");
fprintf(stderr, "Check ExportImport TIF\n");
checkExportImport(u"tif");
+ fprintf(stderr, "Check ExportImport WEBP\n");
+ checkExportImport(u"webp");
}
void VclFiltersTest::testCVEs()
diff --git a/vcl/qa/cppunit/graphicfilter/filters-webp-test.cxx b/vcl/qa/cppunit/graphicfilter/filters-webp-test.cxx
new file mode 100644
index 000000000000..90528199c0ba
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/filters-webp-test.cxx
@@ -0,0 +1,203 @@
+/* -*- 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 <unotest/filters-test.hxx>
+#include <test/bootstrapfixture.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include <bitmap/BitmapWriteAccess.hxx>
+#include <tools/stream.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <graphic/GraphicFormatDetector.hxx>
+#include <filter/WebpReader.hxx>
+#include <comphelper/propertyvalue.hxx>
+
+using namespace css;
+
+/* Implementation of Filters test */
+
+class WebpFilterTest : public test::FiltersTest, public test::BootstrapFixture
+{
+public:
+ WebpFilterTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ virtual bool load(const OUString&, const OUString& rURL, const OUString&, SfxFilterFlags,
+ SotClipboardFormatId, unsigned int) override;
+
+ /**
+ * Ensure CVEs remain unbroken
+ */
+ void testCVEs();
+
+ void testRoundtripLossless();
+ void testRoundtripLossy();
+ void testReadAlphaLossless();
+ void testReadAlphaLossy();
+ void testReadNoAlphaLossless();
+ void testReadNoAlphaLossy();
+
+ CPPUNIT_TEST_SUITE(WebpFilterTest);
+ CPPUNIT_TEST(testCVEs);
+ CPPUNIT_TEST(testRoundtripLossless);
+ CPPUNIT_TEST(testRoundtripLossy);
+ CPPUNIT_TEST(testReadAlphaLossless);
+ CPPUNIT_TEST(testReadAlphaLossy);
+ CPPUNIT_TEST(testReadNoAlphaLossless);
+ CPPUNIT_TEST(testReadNoAlphaLossy);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ void testRoundtrip(bool lossy);
+ void testRead(bool lossy, bool alpha);
+};
+
+bool WebpFilterTest::load(const OUString&, const OUString& rURL, const OUString&, SfxFilterFlags,
+ SotClipboardFormatId, unsigned int)
+{
+ SvFileStream aFileStream(rURL, StreamMode::READ);
+ Graphic aGraphic;
+ return ImportWebpGraphic(aFileStream, aGraphic);
+}
+
+void WebpFilterTest::testCVEs()
+{
+#ifndef DISABLE_CVE_TESTS
+ testDir(OUString(), m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/webp/"));
+#endif
+}
+
+void WebpFilterTest::testRoundtripLossless() { testRoundtrip(false); }
+
+void WebpFilterTest::testRoundtripLossy() { testRoundtrip(true); }
+
+void WebpFilterTest::testRoundtrip(bool lossy)
+{
+ // Do not use just 2x2, lossy saving would change colors.
+ Bitmap aBitmap(Size(20, 20), vcl::PixelFormat::N24_BPP);
+ AlphaMask aAlpha(Size(20, 20));
+ {
+ BitmapScopedWriteAccess pAccess(aBitmap);
+ pAccess->SetFillColor(COL_WHITE);
+ pAccess->FillRect(tools::Rectangle(Point(0, 0), Size(10, 10)));
+ pAccess->SetFillColor(COL_BLACK);
+ pAccess->FillRect(tools::Rectangle(Point(10, 0), Size(10, 10)));
+ pAccess->SetFillColor(COL_LIGHTRED);
+ pAccess->FillRect(tools::Rectangle(Point(0, 10), Size(10, 10)));
+ pAccess->SetFillColor(COL_BLUE);
+ pAccess->FillRect(tools::Rectangle(Point(10, 10), Size(10, 10)));
+ AlphaScopedWriteAccess pAccessAlpha(aAlpha);
+ pAccessAlpha->SetFillColor(BitmapColor(0)); // opaque
+ pAccessAlpha->FillRect(tools::Rectangle(Point(0, 0), Size(10, 10)));
+ pAccessAlpha->FillRect(tools::Rectangle(Point(10, 0), Size(10, 10)));
+ pAccessAlpha->FillRect(tools::Rectangle(Point(0, 10), Size(10, 10)));
+ pAccessAlpha->SetFillColor(BitmapColor(64, 64, 64));
+ pAccessAlpha->FillRect(tools::Rectangle(Point(10, 10), Size(10, 10)));
+ }
+ BitmapEx aBitmapEx(aBitmap, aAlpha);
+
+ SvMemoryStream aStream;
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ sal_uInt16 nFilterFormat = rFilter.GetExportFormatNumberForShortName(u"webp");
+ css::uno::Sequence<css::beans::PropertyValue> aFilterData{
+ comphelper::makePropertyValue("Lossless", !lossy),
+ comphelper::makePropertyValue("Quality", sal_Int32(100))
+ };
+ rFilter.ExportGraphic(Graphic(aBitmapEx), "none", aStream, nFilterFormat, &aFilterData);
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ Graphic aGraphic;
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, "none", aStream);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+ CPPUNIT_ASSERT_EQUAL(GfxLinkType::NativeWebp, aGraphic.GetGfxLink().GetType());
+ BitmapEx aResultBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(Size(20, 20), aResultBitmap.GetSizePixel());
+ CPPUNIT_ASSERT(aResultBitmap.IsAlpha());
+
+ {
+ Bitmap tmpBitmap = aResultBitmap.GetBitmap();
+ Bitmap::ScopedReadAccess pAccess(tmpBitmap);
+ // Note that x,y are swapped.
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, Color(pAccess->GetPixel(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLACK, Color(pAccess->GetPixel(0, 19)));
+ if (lossy)
+ {
+ CPPUNIT_ASSERT_LESS(sal_uInt16(3),
+ pAccess->GetPixel(19, 0).GetColorError(COL_LIGHTRED));
+ CPPUNIT_ASSERT_LESS(sal_uInt16(3), pAccess->GetPixel(19, 19).GetColorError(COL_BLUE));
+ }
+ else
+ {
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, Color(pAccess->GetPixel(19, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, Color(pAccess->GetPixel(19, 19)));
+ }
+ AlphaMask tmpAlpha = aResultBitmap.GetAlpha();
+ AlphaMask::ScopedReadAccess pAccessAlpha(tmpAlpha);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt8(0), pAccessAlpha->GetPixelIndex(0, 0));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt8(0), pAccessAlpha->GetPixelIndex(0, 19));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt8(0), pAccessAlpha->GetPixelIndex(19, 0));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt8(64), pAccessAlpha->GetPixelIndex(19, 19));
+ }
+
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+ vcl::GraphicFormatDetector aDetector(aStream, "");
+
+ CPPUNIT_ASSERT_EQUAL(true, aDetector.detect());
+ CPPUNIT_ASSERT_EQUAL(true, aDetector.checkWEBP());
+ CPPUNIT_ASSERT_EQUAL(OUString(u"WEBP"), aDetector.msDetectedFormat);
+}
+
+void WebpFilterTest::testReadAlphaLossless() { testRead(false, true); }
+
+void WebpFilterTest::testReadAlphaLossy() { testRead(true, true); }
+
+void WebpFilterTest::testReadNoAlphaLossless() { testRead(false, false); }
+
+void WebpFilterTest::testReadNoAlphaLossy() { testRead(true, false); }
+
+void WebpFilterTest::testRead(bool lossy, bool alpha)
+{
+ // Read a file created in GIMP and check it's read correctly.
+ OUString file = m_directories.getURLFromSrc(u"/vcl/qa/cppunit/graphicfilter/data/webp/")
+ + (alpha ? u"alpha" : u"noalpha") + "_" + (lossy ? u"lossy" : u"lossless")
+ + ".webp";
+ SvFileStream aFileStream(file, StreamMode::READ);
+ Graphic aGraphic;
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, "none", aFileStream);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+ CPPUNIT_ASSERT_EQUAL(GfxLinkType::NativeWebp, aGraphic.GetGfxLink().GetType());
+ BitmapEx aResultBitmap = aGraphic.GetBitmapEx();
+ CPPUNIT_ASSERT_EQUAL(Size(10, 10), aResultBitmap.GetSizePixel());
+ CPPUNIT_ASSERT_EQUAL(alpha, aResultBitmap.IsAlpha());
+
+ {
+ Bitmap tmpBitmap = aResultBitmap.GetBitmap();
+ Bitmap::ScopedReadAccess pAccess(tmpBitmap);
+ // Note that x,y are swapped.
+ if (lossy)
+ CPPUNIT_ASSERT_LESS(sal_uInt16(2), pAccess->GetPixel(0, 0).GetColorError(COL_LIGHTRED));
+ else
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, Color(pAccess->GetPixel(0, 0)));
+ CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, Color(pAccess->GetPixel(9, 9)));
+ if (alpha)
+ {
+ AlphaMask tmpAlpha = aResultBitmap.GetAlpha();
+ AlphaMask::ScopedReadAccess pAccessAlpha(tmpAlpha);
+ CPPUNIT_ASSERT_EQUAL(sal_uInt8(0), pAccessAlpha->GetPixelIndex(0, 0));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt8(255), pAccessAlpha->GetPixelIndex(0, 9));
+ }
+ }
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(WebpFilterTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/FilterConfigCache.cxx b/vcl/source/filter/FilterConfigCache.cxx
index 370e8cffed8b..3430d0251cd7 100644
--- a/vcl/source/filter/FilterConfigCache.cxx
+++ b/vcl/source/filter/FilterConfigCache.cxx
@@ -41,10 +41,10 @@ using namespace ::com::sun::star::configuration ;
const char* FilterConfigCache::FilterConfigCacheEntry::InternalPixelFilterNameList[] =
{
- IMP_BMP, IMP_GIF, IMP_PNG, IMP_JPEG, IMP_TIFF,
+ IMP_BMP, IMP_GIF, IMP_PNG, IMP_JPEG, IMP_TIFF, IMP_WEBP,
IMP_XBM, IMP_XPM, IMP_TGA, IMP_PICT, IMP_MET, IMP_RAS,
IMP_PCX, IMP_MOV, IMP_PSD, IMP_PCD, IMP_PBM, IMP_DXF,
- EXP_BMP, EXP_GIF, EXP_PNG, EXP_JPEG, EXP_TIFF,
+ EXP_BMP, EXP_GIF, EXP_PNG, EXP_JPEG, EXP_TIFF, EXP_WEBP,
nullptr
};
@@ -226,6 +226,8 @@ const char* FilterConfigCache::InternalFilterListForSvxLight[] =
"xpm","1","SVIXPM",
"svg","1","SVISVG",
"svg","2","SVESVG",
+ "webp","1","SVIWEBP",
+ "webp","2","SVEWEBP",
nullptr
};
diff --git a/vcl/source/filter/GraphicFormatDetector.cxx b/vcl/source/filter/GraphicFormatDetector.cxx
index 6c8df32a456e..2dddcfa0f9ae 100644
--- a/vcl/source/filter/GraphicFormatDetector.cxx
+++ b/vcl/source/filter/GraphicFormatDetector.cxx
@@ -274,6 +274,16 @@ bool peekGraphicFormat(SvStream& rStream, OUString& rFormatExtension, bool bTest
}
}
+ if (!bTest || rFormatExtension.startsWith("WEBP"))
+ {
+ bSomethingTested = true;
+ if (aDetector.checkWEBP())
+ {
+ rFormatExtension = aDetector.msDetectedFormat;
+ return true;
+ }
+ }
+
return bTest && !bSomethingTested;
}
@@ -816,6 +826,18 @@ bool GraphicFormatDetector::checkPDF()
return false;
}
+bool GraphicFormatDetector::checkWEBP()
+{
+ if (maFirstBytes[0] == 'R' && maFirstBytes[1] == 'I' && maFirstBytes[2] == 'F'
+ && maFirstBytes[3] == 'F' && maFirstBytes[8] == 'W' && maFirstBytes[9] == 'E'
+ && maFirstBytes[10] == 'B' && maFirstBytes[11] == 'P')
+ {
+ msDetectedFormat = "WEBP";
+ return true;
+ }
+ return false;
+}
+
} // vcl namespace
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/graphicfilter.cxx b/vcl/source/filter/graphicfilter.cxx
index add513e1b72e..17710e85650c 100644
--- a/vcl/source/filter/graphicfilter.cxx
+++ b/vcl/source/filter/graphicfilter.cxx
@@ -64,6 +64,8 @@
#include <filter/GifWriter.hxx>
#include <filter/BmpReader.hxx>
#include <filter/BmpWriter.hxx>
+#include <filter/WebpReader.hxx>
+#include <filter/WebpWriter.hxx>
#include <osl/module.hxx>
#include <com/sun/star/uno/Reference.h>
#include <com/sun/star/awt/Size.hpp>
@@ -82,6 +84,7 @@
#include <memory>
#include <mutex>
#include <string_view>
+#include <o3tl/string_view.hxx>
#include <vcl/TypeSerializer.hxx>
#include "FilterConfigCache.hxx"
@@ -90,6 +93,24 @@
#include <graphic/GraphicFormatDetector.hxx>
#include <graphic/GraphicReader.hxx>
+// Support for GfxLinkType::NativeWebp is so far disabled,
+// as enabling it would write .webp images e.g. to .odt documents,
+// making those images unreadable for older readers. So for now
+// disable the support so that .webp images will be written out as .png,
+// and somewhen later enable the support unconditionally.
+static bool supportNativeWebp()
+{
+ const char* const testname = getenv("LO_TESTNAME");
+ if(testname == nullptr)
+ return false;
+ // Enable support only for those unittests that test it.
+ if( std::string_view("_anonymous_namespace___GraphicTest__testUnloadedGraphicLoading_") == testname
+ || std::string_view("VclFiltersTest__testExportImport_") == testname
+ || o3tl::starts_with(std::string_view(testname), "WebpFilterTest__"))
+ return true;
+ return false;
+}
+
static std::vector< GraphicFilter* > gaFilterHdlList;
static std::mutex& getListMutex()
@@ -899,6 +920,13 @@ Graphic GraphicFilter::ImportUnloadedGraphic(SvStream& rIStream, sal_uInt64 size
{
eLinkType = GfxLinkType::NativeMet;
}
+ else if (aFilterName.equalsIgnoreAsciiCase(IMP_WEBP))
+ {
+ if(supportNativeWebp())
+ eLinkType = GfxLinkType::NativeWebp;
+ else
+ nStatus = ERRCODE_GRFILTER_FILTERERROR;
+ }
else
{
nStatus = ERRCODE_GRFILTER_FILTERERROR;
@@ -1305,6 +1333,18 @@ ErrCode GraphicFilter::readDXF(SvStream & rStream, Graphic & rGraphic)
return ERRCODE_GRFILTER_FILTERERROR;
}
+ErrCode GraphicFilter::readWEBP(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType)
+{
+ if (ImportWebpGraphic(rStream, rGraphic))
+ {
+ if(supportNativeWebp())
+ rLinkType = GfxLinkType::NativeWebp;
+ return ERRCODE_NONE;
+ }
+ else
+ return ERRCODE_GRFILTER_FILTERERROR;
+}
+
ErrCode GraphicFilter::ImportGraphic( Graphic& rGraphic, const OUString& rPath, SvStream& rIStream,
sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat, GraphicFilterImportFlags nImportFlags,
const css::uno::Sequence< css::beans::PropertyValue >* /*pFilterData*/,
@@ -1455,6 +1495,10 @@ ErrCode GraphicFilter::ImportGraphic( Graphic& rGraphic, const OUString& rPath,
{
nStatus = readDXF(rIStream, rGraphic);
}
+ else if (aFilterName.equalsIgnoreAsciiCase(IMP_WEBP))
+ {
+ nStatus = readWEBP(rIStream, rGraphic, eLinkType);
+ }
else
nStatus = ERRCODE_GRFILTER_FILTERERROR;
}
@@ -1840,6 +1884,14 @@ ErrCode GraphicFilter::ExportGraphic( const Graphic& rGraphic, const OUString& r
}
}
}
+ else if (aFilterName.equalsIgnoreAsciiCase(EXP_WEBP))
+ {
+ if (!ExportWebpGraphic(rOStm, aGraphic, &aConfigItem))
+ nStatus = ERRCODE_GRFILTER_FORMATERROR;
+
+ if( rOStm.GetError() )
+ nStatus = ERRCODE_GRFILTER_IOERROR;
+ }
else
nStatus = ERRCODE_GRFILTER_FILTERERROR;
}
@@ -1882,6 +1934,7 @@ IMPL_LINK( GraphicFilter, FilterCallback, ConvertData&, rData, bool )
case ConvertDataFormat::WMF: aShortName = WMF_SHORTNAME; break;
case ConvertDataFormat::EMF: aShortName = EMF_SHORTNAME; break;
case ConvertDataFormat::SVG: aShortName = SVG_SHORTNAME; break;
+ case ConvertDataFormat::WEBP: aShortName = WEBP_SHORTNAME; break;
default:
break;
diff --git a/vcl/source/filter/graphicfilter2.cxx b/vcl/source/filter/graphicfilter2.cxx
index 0360c51d3347..5f73d570d9f6 100644
--- a/vcl/source/filter/graphicfilter2.cxx
+++ b/vcl/source/filter/graphicfilter2.cxx
@@ -25,6 +25,7 @@
#include <vcl/outdev.hxx>
#include <vcl/graphicfilter.hxx>
#include <unotools/ucbstreamhelper.hxx>
+#include <filter/WebpReader.hxx>
#include "graphicfilter_internal.hxx"
#define DATA_SIZE 640
@@ -87,6 +88,7 @@ bool GraphicDescriptor::Detect( bool bExtendedInfo )
else if ( ImpDetectPSD( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectEPS( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectPCD( rStm, bExtendedInfo ) ) bRet = true;
+ else if ( ImpDetectWEBP( rStm, bExtendedInfo ) ) bRet = true;
rStm.SetEndian( nOldFormat );
}
@@ -1142,6 +1144,36 @@ bool GraphicDescriptor::ImpDetectSVG( SvStream& /*rStm*/, bool /*bExtendedInfo*/
return bRet;
}
+bool GraphicDescriptor::ImpDetectWEBP( SvStream& rStm, bool bExtendedInfo )
+{
+ sal_uInt32 nTemp32 = 0;
+ bool bRet = false;
+
+ sal_Int32 nStmPos = rStm.Tell();
+ rStm.SetEndian( SvStreamEndian::BIG );
+ rStm.ReadUInt32( nTemp32 );
+
+ if ( nTemp32 == 0x52494646 )
+ {
+ rStm.ReadUInt32( nTemp32 ); // skip
+ rStm.ReadUInt32( nTemp32 );
+ if ( nTemp32 == 0x57454250 )
+ {
+ nFormat = GraphicFileFormat::WEBP;
+ bRet = true;
+
+ if ( bExtendedInfo )
+ {
+ rStm.Seek(nStmPos);
+ ReadWebpInfo(rStm, aPixSize, nBitsPerPixel, bIsAlpha );
+ bIsTransparent = bIsAlpha;
+ }
+ }
+ }
+ rStm.Seek( nStmPos );
+ return bRet;
+}
+
OUString GraphicDescriptor::GetImportFormatShortName( GraphicFileFormat nFormat )
{
const char *pKeyName = nullptr;
@@ -1171,6 +1203,7 @@ OUString GraphicDescriptor::GetImportFormatShortName( GraphicFileFormat nFormat
case GraphicFileFormat::WMF : pKeyName = "wmf"; break;
case GraphicFileFormat::EMF : pKeyName = "emf"; break;
case GraphicFileFormat::SVG : pKeyName = "svg"; break;
+ case GraphicFileFormat::WEBP : pKeyName = "webp"; break;
default: assert(false);
}
diff --git a/vcl/source/filter/webp/reader.cxx b/vcl/source/filter/webp/reader.cxx
new file mode 100644
index 000000000000..e8c885053965
--- /dev/null
+++ b/vcl/source/filter/webp/reader.cxx
@@ -0,0 +1,318 @@
+/* -*- 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/.
+ *
+ * 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 <memory>
+#include <vcl/graph.hxx>
+#include <tools/stream.hxx>
+#include <filter/WebpReader.hxx>
+#include <bitmap/BitmapWriteAccess.hxx>
+#include <salinst.hxx>
+#include <sal/log.hxx>
+#include <unotools/configmgr.hxx>
+#include <svdata.hxx>
+
+#include <webp/decode.h>
+
+static bool readWebpInfo(SvStream& stream, std::vector<uint8_t>& data,
+ WebPBitstreamFeatures& features)
+{
+ for (;;)
+ {
+ // Read 4096 (more) bytes.
+ size_t lastSize = data.size();
+ data.resize(data.size() + 4096);
+ sal_Size nBytesRead = stream.ReadBytes(data.data() + lastSize, 4096);
+ if (nBytesRead <= 0)
+ return false;
+ data.resize(lastSize + nBytesRead);
+ int status = WebPGetFeatures(data.data(), data.size(), &features);
+ if (status == VP8_STATUS_OK)
+ break;
+ if (status == VP8_STATUS_NOT_ENOUGH_DATA)
+ continue; // Try again with 4096 more bytes read.
+ return false;
+ }
+ return true;
+}
+
+static bool readWebp(SvStream& stream, Graphic& graphic)
+{
+ WebPDecoderConfig config;
+ if (!WebPInitDecoderConfig(&config))
+ {
+ SAL_WARN("vcl.filter.webp", "WebPInitDecoderConfig() failed");
+ return false;
+ }
+ // This unique_ptr is here just to ensure WebPFreeDecBuffer() is called at the end,
+ // it doesn't actually own the data as such.
+ std::unique_ptr<WebPDecBuffer, decltype(&WebPFreeDecBuffer)> freeBuffer(&config.output,
+ WebPFreeDecBuffer);
+ std::vector<uint8_t> data;
+ if (!readWebpInfo(stream, data, config.input))
+ return false;
+ // Here various parts of 'config' can be altered if wanted.
+ const int& width = config.input.width;
+ const int& height = config.input.height;
+ const int& has_alpha = config.input.has_alpha;
+
+ if (width > SAL_MAX_INT32 / 8 || height > SAL_MAX_INT32 / 8)
+ return false; // avoid overflows later
+
+ const bool bFuzzing = utl::ConfigManager::IsFuzzing();
+ const bool bSupportsBitmap32 = bFuzzing || ImplGetSVData()->mpDefInst->supportsBitmap32();
+
+ Bitmap bitmap;
+ AlphaMask bitmapAlpha;
+ if (bSupportsBitmap32 && has_alpha)
+ {
+ bitmap = Bitmap(Size(width, height), vcl::PixelFormat::N32_BPP);
+ }
+ else
+ {
+ bitmap = Bitmap(Size(width, height), vcl::PixelFormat::N24_BPP);
+ if (has_alpha)
+ bitmapAlpha = AlphaMask(Size(width, height));
+ }
+
+ BitmapScopedWriteAccess access(bitmap);
+ // If data cannot be read directly into the bitmap, read data first to this buffer and then convert.
+ std::vector<uint8_t> tmpRgbaData;
+ enum class PixelMode
+ {
+ DirectRead, // read data directly to the bitmap
+ Split, // read to tmp buffer and split to rgb and alpha
+ SetPixel // read to tmp buffer and use setPixel()
+ };
+ PixelMode pixelMode = PixelMode::SetPixel;
+
+ config.output.width = width;
+ config.output.height = height;
+ config.output.is_external_memory = 1;
+ if (bSupportsBitmap32 && has_alpha)
+ {
+ switch (RemoveScanline(access->GetScanlineFormat()))
+ {
+ // Our bitmap32 code expects premultiplied.
+ case ScanlineFormat::N32BitTcRgba:
+ config.output.colorspace = MODE_rgbA;
+ pixelMode = PixelMode::DirectRead;
+ break;
+ case ScanlineFormat::N32BitTcBgra:
+ config.output.colorspace = MODE_bgrA;
+ pixelMode = PixelMode::DirectRead;
+ break;
+ case ScanlineFormat::N32BitTcArgb:
+ config.output.colorspace = MODE_Argb;
+ pixelMode = PixelMode::DirectRead;
+ break;
+ default:
+ config.output.colorspace = MODE_RGBA;
+ pixelMode = PixelMode::SetPixel;
+ break;
+ }
+ }
+ else
+ {
+ if (has_alpha)
+ {
+ switch (RemoveScanline(access->GetScanlineFormat()))
+ {
+ case ScanlineFormat::N24BitTcRgb:
+ config.output.colorspace = MODE_RGBA;
+ pixelMode = PixelMode::Split;
+ break;
+ case ScanlineFormat::N24BitTcBgr:
+ config.output.colorspace = MODE_BGRA;
+ pixelMode = PixelMode::Split;
+ break;
+ default:
+ config.output.colorspace = MODE_RGBA;
+ pixelMode = PixelMode::SetPixel;
+ break;
+ }
+ }
+ else
+ {
+ switch (RemoveScanline(access->GetScanlineFormat()))
+ {
+ case ScanlineFormat::N24BitTcRgb:
+ config.output.colorspace = MODE_RGB;
+ pixelMode = PixelMode::DirectRead;
+ break;
+ case ScanlineFormat::N24BitTcBgr:
+ config.output.colorspace = MODE_BGR;
+ pixelMode = PixelMode::DirectRead;
+ break;
+ default:
+ config.output.colorspace = MODE_RGBA;
+ pixelMode = PixelMode::SetPixel;
+ break;
+ }
+ }
+ }
+ if (pixelMode == PixelMode::DirectRead)
+ {
+ config.output.u.RGBA.rgba = access->GetBuffer();
+ config.output.u.RGBA.stride = access->GetScanlineSize();
+ config.output.u.RGBA.size = access->GetScanlineSize() * access->Height();
+ }
+ else
+ {
+ tmpRgbaData.resize(width * height * 4);
+ config.output.u.RGBA.rgba = tmpRgbaData.data();
+ config.output.u.RGBA.stride = width * 4;
+ config.output.u.RGBA.size = tmpRgbaData.size();
+ }
+
+ std::unique_ptr<WebPIDecoder, decltype(&WebPIDelete)> decoder(WebPIDecode(nullptr, 0, &config),
+ WebPIDelete);
+
+ bool success = true;
+ for (;;)
+ {
+ // During first iteration, use data read while reading the header.
+ int status = WebPIAppend(decoder.get(), data.data(), data.size());
+ if (status == VP8_STATUS_OK)
+ break;
+ if (status != VP8_STATUS_SUSPENDED)
+ {
+ // An error, still try to return at least a partially read bitmap,
+ // even if returning an error flag.
+ success = false;
+ break;
+ }
+ // If more data is needed, reading 4096 bytes more and repeat.
+ data.resize(4096);
+ sal_Size nBytesRead = stream.ReadBytes(data.data(), 4096);
+ if (nBytesRead <= 0)
+ {
+ // Truncated file, again try to return at least something.
+ success = false;
+ break;
+ }
+ data.resize(nBytesRead);
+ }
+
+ switch (pixelMode)
+ {
+ case PixelMode::DirectRead:
+ {
+ // Adjust for IsBottomUp() if necessary.
+ if (access->IsBottomUp())
+ {
+ std::vector<char> tmp;
+ const sal_uInt32 lineSize = access->GetScanlineSize();
+ tmp.resize(lineSize);
+ for (tools::Long y = 0; y < access->Height() / 2; ++y)
+ {
+ tools::Long otherY = access->Height() - 1 - y;
+ memcpy(tmp.data(), access->GetScanline(y), lineSize);
+ memcpy(access->GetScanline(y), access->GetScanline(otherY), lineSize);
+ memcpy(access->GetScanline(otherY), tmp.data(), lineSize);
+ }
+ }
+ break;
+ }
+ case PixelMode::Split:
+ {
+ // Split to normal and alpha bitmaps.
+ AlphaScopedWriteAccess accessAlpha(bitmapAlpha);
+ for (tools::Long y = 0; y < access->Height(); ++y)
+ {
+ const unsigned char* src = tmpRgbaData.data() + width * 4 * y;
+ unsigned char* dstB = access->GetScanline(y);
+ unsigned char* dstA = accessAlpha->GetScanline(y);
+ for (tools::Long x = 0; x < access->Width(); ++x)
+ {
+ memcpy(dstB, src, 3);
+ *dstA = 255 - *(src + 3);
+ src += 4;
+ dstB += 3;
+ dstA += 1;
+ }
+ }
+ break;
+ }
+ case PixelMode::SetPixel:
+ {
+ for (tools::Long y = 0; y < access->Height(); ++y)
+ {
+ const unsigned char* src = tmpRgbaData.data() + width * 4 * y;
+ for (tools::Long x = 0; x < access->Width(); ++x)
+ {
+ sal_uInt8 r = src[0];
+ sal_uInt8 g = src[1];
+ sal_uInt8 b = src[2];
+ sal_uInt8 a = src[3];
+ access->SetPixel(y, x, Color(ColorAlpha, a, r, g, b));
+ src += 4;
+ }
+ }
+ if (!bitmapAlpha.IsEmpty())
+ {
+ AlphaScopedWriteAccess accessAlpha(bitmapAlpha);
+ for (tools::Long y = 0; y < accessAlpha->Height(); ++y)
+ {
+ const unsigned char* src = tmpRgbaData.data() + width * 4 * y;
+ for (tools::Long x = 0; x < accessAlpha->Width(); ++x)
+ {
+ sal_uInt8 a = src[3];
+ accessAlpha->SetPixelIndex(y, x, 255 - a);
+ src += 4;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ access.reset(); // Flush BitmapScopedWriteAccess.
+ if (bSupportsBitmap32 && has_alpha)
+ graphic = BitmapEx(bitmap);
+ else
+ {
+ if (has_alpha)
+ graphic = BitmapEx(bitmap, bitmapAlpha);
+ else
+ graphic = BitmapEx(bitmap);
+ }
+ return success;
+}
+
+bool ImportWebpGraphic(SvStream& rStream, Graphic& rGraphic)
+{
+ bool bRetValue = readWebp(rStream, rGraphic);
+ if (!bRetValue)
+ rStream.SetError(SVSTREAM_FILEFORMAT_ERROR);
+ return bRetValue;
+}
+
+bool ReadWebpInfo(SvStream& stream, Size& pixelSize, sal_uInt16& bitsPerPixel, bool& hasAlpha)
+{
+ std::vector<uint8_t> data;
+ WebPBitstreamFeatures features;
+ if (!readWebpInfo(stream, data, features))
+ return false;
+ pixelSize = Size(features.width, features.height);
+ bitsPerPixel = features.has_alpha ? 32 : 24;
+ hasAlpha = features.has_alpha;
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/webp/writer.cxx b/vcl/source/filter/webp/writer.cxx
new file mode 100644
index 000000000000..32da25e93ca3
--- /dev/null
+++ b/vcl/source/filter/webp/writer.cxx
@@ -0,0 +1,206 @@
+/* -*- 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/.
+ *
+ * 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 <memory>
+#include <vcl/graph.hxx>
+#include <tools/stream.hxx>
+#include <filter/WebpWriter.hxx>
+#include <vcl/BitmapReadAccess.hxx>
+#include <sal/log.hxx>
+
+#include <webp/encode.h>
+
+static int writerFunction(const uint8_t* data, size_t size, const WebPPicture* picture)
+{
+ SvStream* stream = static_cast<SvStream*>(picture->custom_ptr);
+ return stream->WriteBytes(data, size) == size ? 1 : 0;
+}
+
+static WebPPreset presetToValue(const OUString& preset)
+{
+ if (preset.equalsIgnoreAsciiCase("picture"))
+ return WEBP_PRESET_PICTURE;
+ if (preset.equalsIgnoreAsciiCase("photo"))
+ return WEBP_PRESET_PHOTO;
+ if (preset.equalsIgnoreAsciiCase("drawing"))
+ return WEBP_PRESET_DRAWING;
+ if (preset.equalsIgnoreAsciiCase("icon"))
+ return WEBP_PRESET_ICON;
+ if (preset.equalsIgnoreAsciiCase("text"))
+ return WEBP_PRESET_TEXT;
+ return WEBP_PRESET_DEFAULT;
+}
+
+static bool writeWebp(SvStream& rStream, const BitmapEx& bitmapEx, bool lossless,
+ const OUString& preset, int quality)
+{
+ WebPConfig config;
+ if (!WebPConfigInit(&config))
+ {
+ SAL_WARN("vcl.filter.webp", "WebPConfigInit() failed");
+ return false;
+ }
+ if (lossless)
+ {
+ if (!WebPConfigLosslessPreset(&config, 6))
+ {
+ SAL_WARN("vcl.filter.webp", "WebPConfigLosslessPreset() failed");
+ return false;
+ }
+ }
+ else
+ {
+ if (!WebPConfigPreset(&config, presetToValue(preset), quality))
+ {
+ SAL_WARN("vcl.filter.webp", "WebPConfigPreset() failed");
+ return false;
+ }
+ }
+ // Here various parts of 'config' can be altered if wanted.
+ assert(WebPValidateConfig(&config));
+
+ const int width = bitmapEx.GetSizePixel().Width();
+ const int height = bitmapEx.GetSizePixel().Height();
+
+ WebPPicture picture;
+ if (!WebPPictureInit(&picture))
+ {
+ SAL_WARN("vcl.filter.webp", "WebPPictureInit() failed");
+ return false;
+ }
+ picture.width = width;
+ picture.height = height;
+ picture.use_argb = lossless ? 1 : 0; // libwebp recommends argb only for lossless
+ // This unique_ptr is here just to ensure WebPPictureFree() is called at the end,
+ // it doesn't actually own the data as such.
+ std::unique_ptr<WebPPicture, decltype(&WebPPictureFree)> freePicture(&picture, WebPPictureFree);
+
+ // Apparently libwebp needs the entire image data at once in WebPPicture,
+ // so allocate it and copy there.
+ Bitmap bitmap(bitmapEx.GetBitmap());
+ AlphaMask bitmapAlpha;
+ if (bitmapEx.IsAlpha())
+ bitmapAlpha = bitmapEx.GetAlpha();
+ Bitmap::ScopedReadAccess access(bitmap);
+ AlphaMask::ScopedReadAccess accessAlpha(bitmapAlpha);
+ bool dataDone = false;
+ if (!access->IsBottomUp() && bitmapAlpha.IsEmpty())
+ {
+ // Try to directly copy the bitmap data.
+ switch (access->GetScanlineFormat())
+ {
+ case ScanlineFormat::N24BitTcRgb:
+ if (!WebPPictureImportRGB(&picture, access->GetBuffer(), access->GetScanlineSize()))
+ {
+ SAL_WARN("vcl.filter.webp", "WebPPictureImportRGB() failed");
+ return false;
+ }
+ dataDone = true;
+ break;
+ case ScanlineFormat::N24BitTcBgr:
+ if (!WebPPictureImportBGR(&picture, access->GetBuffer(), access->GetScanlineSize()))
+ {
+ SAL_WARN("vcl.filter.webp", "WebPPictureImportBGR() failed");
+ return false;
+ }
+ dataDone = true;
+ break;
+ // Our argb formats are premultiplied, so can't read directly using libwebp functions.
+ default:
+ break;
+ }
+ }
+ if (!dataDone)
+ {
+ // It would be simpler to convert the bitmap to 32bpp, but our 32bpp support is broken
+ // (it's unspecified whether it's premultiplied or not, for example). So handle this manually.
+ // Special handling for some common cases, generic otherwise.
+ if (!WebPPictureAlloc(&picture))
+ {
+ SAL_WARN("vcl.filter.webp", "WebPPictureAlloc() failed");
+ return false;
+ }
+ std::vector<uint8_t> data;
+ const int bpp = 4;
+ data.resize(width * height * bpp);
+ if (!bitmapAlpha.IsEmpty())
+ {
+ for (tools::Long y = 0; y < access->Height(); ++y)
+ {
+ unsigned char* dst = data.data() + width * bpp * y;
+ const sal_uInt8* srcB = access->GetScanline(y);
+ const sal_uInt8* srcA = accessAlpha->GetScanline(y);
+ for (tools::Long x = 0; x < access->Width(); ++x)
+ {
+ BitmapColor color = access->GetPixelFromData(srcB, x);
+ BitmapColor transparency = accessAlpha->GetPixelFromData(srcA, x);
+ color.SetAlpha(255 - transparency.GetIndex());
+ dst[0] = color.GetRed();
+ dst[1] = color.GetGreen();
+ dst[2] = color.GetBlue();
+ dst[3] = color.GetAlpha();
+ dst += bpp;
+ }
+ }
+ }
+ else
+ {
+ for (tools::Long y = 0; y < access->Height(); ++y)
+ {
+ unsigned char* dst = data.data() + width * bpp * y;
+ const sal_uInt8* src = access->GetScanline(y);
+ for (tools::Long x = 0; x < access->Width(); ++x)
+ {
+ Color color = access->GetPixelFromData(src, x);
+ dst[0] = color.GetRed();
+ dst[1] = color.GetGreen();
+ dst[2] = color.GetBlue();
+ dst[3] = color.GetAlpha();
+ dst += bpp;
+ }
+ }
+ }
+ // And now import from the temporary data. Use the import function rather
+ // than writing the data directly to avoid the need to write the data
+ // in the exact format WebPPicture wants (YUV, etc.).
+ if (!WebPPictureImportRGBA(&picture, data.data(), width * bpp))
+ {
+ SAL_WARN("vcl.filter.webp", "WebPPictureImportRGBA() failed");
+ return false;
+ }
+ }
+
+ picture.writer = writerFunction;
+ picture.custom_ptr = &rStream;
+ return WebPEncode(&config, &picture);
+}
+
+bool ExportWebpGraphic(SvStream& rStream, const Graphic& rGraphic,
+ FilterConfigItem* pFilterConfigItem)
+{
+ BitmapEx bitmap = rGraphic.GetBitmapEx();
+ // If lossless, neither presets nor quality matter.
+ bool lossless = pFilterConfigItem->ReadBool("Lossless", true);
+ // Preset is WebPPreset values.
+ const OUString preset = pFilterConfigItem->ReadString("Preset", "");
+ int quality = pFilterConfigItem->ReadInt32("Quality", 75);
+ return writeWebp(rStream, bitmap, lossless, preset, quality);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/gfxlink.cxx b/vcl/source/gdi/gfxlink.cxx
index 147f89febc85..0baddbf931ae 100644
--- a/vcl/source/gdi/gfxlink.cxx
+++ b/vcl/source/gdi/gfxlink.cxx
@@ -134,6 +134,7 @@ bool GfxLink::LoadNative( Graphic& rGraphic ) const
case GfxLinkType::NativeSvg: aShortName = SVG_SHORTNAME; break;
case GfxLinkType::NativeBmp: aShortName = BMP_SHORTNAME; break;
case GfxLinkType::NativePdf: aShortName = PDF_SHORTNAME; break;
+ case GfxLinkType::NativeWebp: aShortName = WEBP_SHORTNAME; break;
default: break;
}
if (!aShortName.isEmpty())
diff --git a/vcl/source/gdi/mtfxmldump.cxx b/vcl/source/gdi/mtfxmldump.cxx
index 11c76ac5af5c..52acaff36e09 100644
--- a/vcl/source/gdi/mtfxmldump.cxx
+++ b/vcl/source/gdi/mtfxmldump.cxx
@@ -466,6 +466,7 @@ OUString convertGfxLinkTypeToString(GfxLinkType eGfxLinkType)
case GfxLinkType::NativeSvg: return "NativeSvg";
case GfxLinkType::NativeTif: return "NativeTif";
case GfxLinkType::NativeWmf: return "NativeWmf";
+ case GfxLinkType::NativeWebp: return "NativeWebp";
case GfxLinkType::NONE: return "None";
}
return OUString();
diff --git a/vcl/source/graphic/UnoGraphicDescriptor.cxx b/vcl/source/graphic/UnoGraphicDescriptor.cxx
index 60f2dcaa4c8b..a4d21c4420e6 100644
--- a/vcl/source/graphic/UnoGraphicDescriptor.cxx
+++ b/vcl/source/graphic/UnoGraphicDescriptor.cxx
@@ -127,6 +127,7 @@ void GraphicDescriptor::implCreate( SvStream& rIStm, const OUString* pURL )
case GraphicFileFormat::RAS: pMimeType = MIMETYPE_RAS; cType = graphic::GraphicType::PIXEL; break;
case GraphicFileFormat::TGA: pMimeType = MIMETYPE_TGA; cType = graphic::GraphicType::PIXEL; break;
case GraphicFileFormat::PSD: pMimeType = MIMETYPE_PSD; cType = graphic::GraphicType::PIXEL; break;
+ case GraphicFileFormat::WEBP: pMimeType = MIMETYPE_WEBP; cType = graphic::GraphicType::PIXEL; break;
case GraphicFileFormat::EPS: pMimeType = MIMETYPE_EPS; cType = graphic::GraphicType::VECTOR; break;
case GraphicFileFormat::DXF: pMimeType = MIMETYPE_DXF; cType = graphic::GraphicType::VECTOR; break;
@@ -298,6 +299,7 @@ void GraphicDescriptor::_getPropertyValues( const comphelper::PropertyMapEntry**
case GfxLinkType::NativeWmf: pMimeType = MIMETYPE_WMF; break;
case GfxLinkType::NativeMet: pMimeType = MIMETYPE_MET; break;
case GfxLinkType::NativePct: pMimeType = MIMETYPE_PCT; break;
+ case GfxLinkType::NativeWebp: pMimeType = MIMETYPE_WEBP; break;
// added Svg mimetype support
case GfxLinkType::NativeSvg: pMimeType = MIMETYPE_SVG; break;
diff --git a/vcl/workben/fftester.cxx b/vcl/workben/fftester.cxx
index 218909dde6c7..d69c07708841 100644
--- a/vcl/workben/fftester.cxx
+++ b/vcl/workben/fftester.cxx
@@ -62,6 +62,7 @@
#include <filter/PcdReader.hxx>
#include <filter/PbmReader.hxx>
#include <filter/DxfReader.hxx>
+#include <filter/WebpReader.hxx>
#include <filter/XpmReader.hxx>
#include <osl/file.hxx>
#include <osl/module.hxx>
@@ -252,6 +253,12 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv)
SvFileStream aFileStream(out, StreamMode::READ);
ret = static_cast<int>(ImportTiffGraphicImport(aFileStream, aGraphic));
}
+ else if (strcmp(argv[2], "webp") == 0)
+ {
+ Graphic aGraphic;
+ SvFileStream aFileStream(out, StreamMode::READ);
+ ret = static_cast<int>(ImportWebpGraphic(aFileStream, aGraphic));
+ }
#ifndef DISABLE_DYNLOADING
else if ((strcmp(argv[2], "doc") == 0) || (strcmp(argv[2], "ww8") == 0))
{
diff --git a/vcl/workben/webpfuzzer.cxx b/vcl/workben/webpfuzzer.cxx
new file mode 100644
index 000000000000..b7ae8f741447
--- /dev/null
+++ b/vcl/workben/webpfuzzer.cxx
@@ -0,0 +1,48 @@
+/* -*- 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 <tools/stream.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include "commonfuzzer.hxx"
+#include <filter/WebpReader.hxx>
+
+#include <config_features.h>
+#include <osl/detail/component-mapping.h>
+
+const lib_to_factory_mapping* lo_get_factory_map(void)
+{
+ static lib_to_factory_mapping map[] = { { 0, 0 } };
+
+ return map;
+}
+
+const lib_to_constructor_mapping* lo_get_constructor_map(void)
+{
+ static lib_to_constructor_mapping map[] = { { 0, 0 } };
+
+ return map;
+}
+
+extern "C" void* lo_get_custom_widget_func(const char*) { return nullptr; }
+
+extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv)
+{
+ TypicalFuzzerInitialize(argc, argv);
+ return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
+{
+ SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
+ Graphic aGraphic;
+ (void)ImportWebpGraphic(aStream, aGraphic);
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/workben/webpfuzzer.options b/vcl/workben/webpfuzzer.options
new file mode 100644
index 000000000000..678d526b1ea9
--- /dev/null
+++ b/vcl/workben/webpfuzzer.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+max_len = 65536