summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Davenport <qball@gmpclient.org>2020-10-18 21:37:05 +0200
committerDave Davenport <qball@gmpclient.org>2020-10-18 21:37:05 +0200
commit5994df7f048492b234c2827cf9a7e313b356c6b8 (patch)
treecf3c4d12c01685570b9b8393d51f331698885a01
parentd8a420c95275117b0efd32b6e3b61847f58ad37c (diff)
[IconLoader] add optional gif loader.
-rw-r--r--Makefile.am1
-rw-r--r--configure.ac33
-rw-r--r--meson.build4
-rw-r--r--source/dialogs/filebrowser.c11
-rw-r--r--source/rofi-icon-fetcher.c71
5 files changed, 116 insertions, 4 deletions
diff --git a/Makefile.am b/Makefile.am
index 6d1fa925..d979dba8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -168,6 +168,7 @@ rofi_LDADD=\
$(cairo_LIBS)\
$(librsvg_LIBS)\
$(libjpeg_LIBS)\
+ $(libgif_LIBS)\
$(LIBS)
##
diff --git a/configure.ac b/configure.ac
index f05ee356..bb9ac057 100644
--- a/configure.ac
+++ b/configure.ac
@@ -165,7 +165,38 @@ dnl Gets the resource compile tool path.
dnl ---------------------------------------------------------------------
AM_PATH_GLIB_2_0
-
+dnl Test for libgif or libungif
+AC_ARG_WITH([libgif],
+ AS_HELP_STRING([--with-libgif=PREFIX],
+ [Prefix where libgif is installed, or 'no' to disable]),
+ [libgif_prefix="$withval"], [libgif_prefix="${prefix}"])
+
+ if test x$with_libgif != xno && test -z "$libgif_LIBS"; then
+ GIF_CFLAGS="-I${libgif_prefix}/include"
+ GIF_LIBS="-L${libgif_prefix}/lib"
+ save_cflags=$CFLAGS; CFLAGS=$GIF_CFLAGS
+ save_libs=$LIBS; LIBS=$GIF_LIBS
+ AC_CHECK_LIB(gif, DGifOpenFileName,
+ [AC_CHECK_HEADER(gif_lib.h,
+ GIF='gif'; libgif_LIBS='-lgif'; gif_ok=yes,
+ AC_MSG_WARN(*** GIF loader will not be built (giflibrary not found) ***))],
+ AC_MSG_WARN(*** GIF loader will not be built (giflibrary not found) ***))
+
+ AC_CHECK_LIB(ungif, DGifOpenFileName,
+ [AC_CHECK_HEADER(gif_lib.h,
+ GIF='ungif'; libgif_LIBS='-lungif'; gif_ok=yes,
+ AC_MSG_WARN(*** GIF loader will not be built (ungiflibrary not found) ***))],
+ AC_MSG_WARN(*** GIF loader will not be built (ungiflibrary not found) ***))
+ CFLAGS+=$save_cflags
+ LIBS+=$save_libs
+ fi
+
+if test x$GIF != x; then
+ AC_SUBST(libgif_LIBS)
+ AC_DEFINE(HAVE_LIBGIF, 1, Define if gif support is available)
+else
+ gif_ok="no (See http://sourceforge.net/projects/libgif)"
+fi
dnl ---------------------------------------------------------------------
dnl Add extra compiler flags
dnl ---------------------------------------------------------------------
diff --git a/meson.build b/meson.build
index d220b030..09335107 100644
--- a/meson.build
+++ b/meson.build
@@ -69,6 +69,9 @@ deps += [
dependency('libstartup-notification-1.0'),
]
+libgif = c_compiler.find_library('libgif', required: false)
+deps += [ libgif ]
+
check = dependency('check', version: '>= 0.11.0', required: get_option('check'))
header_conf = configuration_data()
@@ -88,6 +91,7 @@ header_conf.set('GLIB_VERSION_MIN_REQUIRED', '(G_ENCODE_VERSION(@0@,@1@))'.forma
header_conf.set('GLIB_VERSION_MAX_ALLOWED', '(G_ENCODE_VERSION(@0@,@1@))'.format(glib_min_major, glib_min_minor))
header_conf.set('ENABLE_DRUN', get_option('drun'))
+header_conf.set('HAVE_LIBGIF', libgif.found())
header_conf.set('WINDOW_MODE', get_option('window'))
header_conf.set_quoted('MANPAGE_PATH', join_paths(get_option('prefix'), get_option('mandir')))
diff --git a/source/dialogs/filebrowser.c b/source/dialogs/filebrowser.c
index 201d1ac7..426e3127 100644
--- a/source/dialogs/filebrowser.c
+++ b/source/dialogs/filebrowser.c
@@ -35,6 +35,9 @@
#include <sys/stat.h>
#include <dirent.h>
+
+#include <config.h>
+
#include "mode.h"
#include "helper.h"
#include "mode-private.h"
@@ -341,7 +344,11 @@ static int file_browser_token_match ( const Mode *sw, rofi_int_matcher **tokens,
}
-const char * const image_exts[] = {".png",".PNG",".jpg",".JPG",".jpeg",".JPEG",".svg",".SVG"};
+const char * const image_exts[] = {".png",".PNG",".jpg",".JPG",".jpeg",".JPEG",".svg",".SVG"
+#ifdef HAVE_LIBGIF
+ ,".gif",".GIF"
+#endif
+};
static gboolean file_browser_is_image ( const char * const path )
{
if ( path == NULL ) {
@@ -351,7 +358,7 @@ static gboolean file_browser_is_image ( const char * const path )
if ( suf == NULL ) {
return FALSE;
}
- for ( uint32_t i = 0; i < (sizeof (image_exts)/sizeof(char*)); i++ ) {
+ for ( uint32_t i = 0; i < G_N_ELEMENTS(image_exts); i++ ) {
if ( g_strcmp0(suf,image_exts[i]) == 0 ) {
return TRUE;
}
diff --git a/source/rofi-icon-fetcher.c b/source/rofi-icon-fetcher.c
index e718d19d..f0216473 100644
--- a/source/rofi-icon-fetcher.c
+++ b/source/rofi-icon-fetcher.c
@@ -28,6 +28,7 @@
/** The log domain of this Helper. */
#define G_LOG_DOMAIN "Helpers.IconFetcher"
+
#include "rofi-icon-fetcher.h"
#include "rofi-types.h"
#include "helper.h"
@@ -44,6 +45,7 @@
#include <setjmp.h>
+#include <config.h>
typedef struct
{
// Context for icon-themes.
@@ -187,7 +189,7 @@ static void jpegErrorExit (j_common_ptr cinfo)
/* Create the message */
( *(cinfo->err->format_message) ) (cinfo, jpegLastErrorMsg);
- g_warning ( jpegLastErrorMsg );
+ g_warning ( jpegLastErrorMsg, NULL );
/* Jump to the setjmp point */
longjmp(myerr->setjmp_buffer, 1);
@@ -224,6 +226,68 @@ static cairo_surface_t* cairo_image_surface_create_from_jpeg ( const char* file
return surface;
}
+#ifdef HAVE_LIBGIF
+#include <gif_lib.h>
+
+static cairo_surface_t* cairo_image_surface_create_from_gif(const char* file )
+{
+ cairo_surface_t* img = NULL;
+
+ int err;
+ GifFileType* gif = DGifOpenFileName(file, &err);
+ if (!gif) {
+ g_warning( "[%i] %s", err, GifErrorString(err));
+ return NULL;
+ }
+
+ // decode with high-level API
+ if (DGifSlurp(gif) != GIF_OK) {
+ g_warning("Decoder error: %s", GifErrorString(gif->Error));
+ goto done;
+ }
+ if (!gif->SavedImages) {
+ g_warning("No saved images");
+ goto done;
+ }
+
+ // create canvas
+ img = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, gif->SWidth, gif->SHeight);
+ if (cairo_surface_status(img) != CAIRO_STATUS_SUCCESS) {
+ g_warning("Unable to create surface: %s",
+ cairo_status_to_string(cairo_surface_status(img)));
+ cairo_surface_destroy(img);
+ img = NULL;
+ goto done;
+ }
+
+ // we don't support animation, show the first frame only
+ const GifImageDesc* frame = &gif->SavedImages->ImageDesc;
+ const GifColorType* colors = gif->SColorMap ? gif->SColorMap->Colors :
+ frame->ColorMap->Colors;
+ uint32_t* base = (uint32_t*)(cairo_image_surface_get_data(img) +
+ frame->Top * cairo_image_surface_get_stride(img));
+ for (int y = 0; y < frame->Height; ++y) {
+ uint32_t* pixel = base + y * gif->SWidth + frame->Left;
+ const uint8_t* raster = &gif->SavedImages->RasterBits[y * gif->SWidth];
+ for (int x = 0; x < frame->Width; ++x) {
+ const uint8_t color = raster[x];
+ if (color != gif->SBackGroundColor) {
+ const GifColorType* rgb = &colors[color];
+ *pixel = 0xff000000 |
+ rgb->Red << 16 | rgb->Green << 8 | rgb->Blue;
+ }
+ ++pixel;
+ }
+ }
+
+ cairo_surface_mark_dirty(img);
+
+done:
+ DGifCloseFile(gif, NULL);
+ return img;
+}
+#endif
+
static void rofi_icon_fetcher_worker ( thread_state *sdata, G_GNUC_UNUSED gpointer user_data )
{
g_debug ( "starting up icon fetching thread." );
@@ -255,6 +319,11 @@ static void rofi_icon_fetcher_worker ( thread_state *sdata, G_GNUC_UNUSED gpoint
if ( g_str_has_suffix ( icon_path, ".png" ) || g_str_has_suffix ( icon_path, ".PNG" ) ) {
icon_surf = cairo_image_surface_create_from_png ( icon_path );
}
+#ifdef HAVE_LIBGIF
+ else if ( g_str_has_suffix ( icon_path, ".gif" ) || g_str_has_suffix ( icon_path, ".GIF" ) ) {
+ icon_surf = cairo_image_surface_create_from_gif ( icon_path );
+ }
+#endif
else if ( g_str_has_suffix ( icon_path, ".jpeg" ) || g_str_has_suffix ( icon_path, ".jpg" ) ||
g_str_has_suffix ( icon_path, ".JPEG" ) || g_str_has_suffix ( icon_path, ".JPG" )
) {