mirror of
https://github.com/davatorium/rofi.git
synced 2024-11-18 13:54:36 -05:00
[RofiIconFetcher] Switch to gdk-pixbuf.
This commit is contained in:
parent
4fd7128d4c
commit
deb1e6a208
7 changed files with 169 additions and 348 deletions
|
@ -31,17 +31,15 @@ You can also use [Meson](https://mesonbuild.com/) as an alternative.
|
|||
* libglib2.0 >= 2.40
|
||||
* gmodule-2.0
|
||||
* gio-unix-2.0
|
||||
* librsvg2.0
|
||||
* libgdk-pixbuf-2.0
|
||||
* libstartup-notification-1.0
|
||||
* libxkbcommon >= 0.4.1
|
||||
* libxkbcommon-x11
|
||||
* libjpeg
|
||||
* libxcb (sometimes split, you need libxcb, libxcb-xkb and libxcb-randr libxcb-xinerama)
|
||||
* xcb-util
|
||||
* xcb-util-wm (sometimes split as libxcb-ewmh and libxcb-icccm)
|
||||
* xcb-util-xrm [new module might not be available in your distribution. The source can be found
|
||||
here](https://github.com/Airblader/xcb-util-xrm/)
|
||||
* libgif (optional)
|
||||
|
||||
On debian based systems, the developer packages are in the form of: `<package>-dev` on rpm based
|
||||
`<package>-devel`.
|
||||
|
|
13
Makefile.am
13
Makefile.am
|
@ -145,7 +145,7 @@ rofi_CFLAGS=\
|
|||
$(pango_CFLAGS)\
|
||||
$(libsn_CFLAGS)\
|
||||
$(cairo_CFLAGS)\
|
||||
$(librsvg_CFLAGS)\
|
||||
$(gdkpixbuf_CFLAGS)\
|
||||
-DMANPAGE_PATH="\"$(mandir)/\""\
|
||||
-I$(top_srcdir)/include/\
|
||||
-I$(top_builddir)/lexer/\
|
||||
|
@ -166,9 +166,7 @@ rofi_LDADD=\
|
|||
$(libsn_LIBS)\
|
||||
$(pango_LIBS)\
|
||||
$(cairo_LIBS)\
|
||||
$(librsvg_LIBS)\
|
||||
$(libjpeg_LIBS)\
|
||||
$(libgif_LIBS)\
|
||||
$(gdkpixbuf_LIBS)\
|
||||
$(LIBS)
|
||||
|
||||
##
|
||||
|
@ -326,8 +324,7 @@ textbox_test_CFLAGS=\
|
|||
$(GW_XCB_CFLAGS)\
|
||||
$(cairo_CFLAGS)\
|
||||
$(libsn_CFLAGS)\
|
||||
$(librsvg_CFLAGS)\
|
||||
$(libjpeg_CFLAGS)\
|
||||
$(gdkpixbuf_CFLAGS)\
|
||||
-DPLUGIN_PATH=\"${libdir}/rofi\"\
|
||||
-DTHEME_DIR=\"$(themedir)\"\
|
||||
-I$(top_srcdir)/include/\
|
||||
|
@ -342,7 +339,6 @@ textbox_test_LDADD=\
|
|||
$(NKUTILS_LIBS)\
|
||||
$(GW_XCB_LIBS)\
|
||||
$(cairo_LIBS)\
|
||||
$(librsvg_LIBS)\
|
||||
$(libsn_LIBS)
|
||||
|
||||
helper_pidfile_CFLAGS=$(textbox_test_CFLAGS)
|
||||
|
@ -479,7 +475,7 @@ helper_test_CFLAGS=\
|
|||
$(NKUTILS_CFLAGS)\
|
||||
$(GW_XCB_CFLAGS)\
|
||||
$(cairo_CFLAGS)\
|
||||
$(librsvg_CFLAGS)\
|
||||
$(gdkpixbuf_CFLAGS)\
|
||||
$(libsn_CFLAGS)\
|
||||
-DPLUGIN_PATH=\"${libdir}/rofi\"\
|
||||
-DTHEME_DIR=\"$(themedir)\"\
|
||||
|
@ -495,7 +491,6 @@ helper_test_LDADD=\
|
|||
$(NKUTILS_LIBS)\
|
||||
$(GW_XCB_LIBS)\
|
||||
$(libsn_LIBS)\
|
||||
$(librsvg_LIBS)\
|
||||
$(cairo_LIBS)
|
||||
|
||||
|
||||
|
|
35
configure.ac
35
configure.ac
|
@ -148,8 +148,7 @@ GW_CHECK_XCB([xcb-aux xcb-xkb xkbcommon xkbcommon-x11 xcb-ewmh xcb-icccm xcb-xrm
|
|||
PKG_CHECK_MODULES([pango], [pango pangocairo])
|
||||
PKG_CHECK_MODULES([cairo], [cairo cairo-xcb])
|
||||
PKG_CHECK_MODULES([libsn], [libstartup-notification-1.0 ])
|
||||
PKG_CHECK_MODULES([librsvg], [librsvg-2.0 ])
|
||||
PKG_CHECK_MODULES([libjpeg], [libjpeg])
|
||||
PKG_CHECK_MODULES([gdkpixbuf], [gdk-pixbuf-2.0])
|
||||
|
||||
dnl ---------------------------------------------------------------------
|
||||
dnl check - Unit testing.
|
||||
|
@ -165,38 +164,6 @@ 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 ---------------------------------------------------------------------
|
||||
|
|
|
@ -47,9 +47,7 @@ deps = [
|
|||
dependency('pango'),
|
||||
dependency('pangocairo'),
|
||||
dependency('xkbcommon'),
|
||||
dependency('librsvg-2.0'),
|
||||
dependency('libjpeg'),
|
||||
c_compiler.find_library('m', required: false),
|
||||
dependency('gdk-pixbuf-2.0'),
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
#include <pango/pango.h>
|
||||
#include <pango/pango-fontmap.h>
|
||||
#include <pango/pangocairo.h>
|
||||
#include <librsvg/rsvg.h>
|
||||
#include "display.h"
|
||||
#include "xcb.h"
|
||||
#include "helper.h"
|
||||
|
@ -1137,50 +1136,6 @@ char *helper_get_theme_path ( const char *file )
|
|||
return filename;
|
||||
}
|
||||
|
||||
cairo_surface_t* cairo_image_surface_create_from_svg ( const gchar* file, int height )
|
||||
{
|
||||
GError *error = NULL;
|
||||
cairo_surface_t *surface = NULL;
|
||||
RsvgHandle * handle;
|
||||
|
||||
handle = rsvg_handle_new_from_file ( file, &error );
|
||||
if ( G_LIKELY ( handle != NULL ) ) {
|
||||
RsvgDimensionData dimensions;
|
||||
// Update DPI.
|
||||
rsvg_handle_set_dpi ( handle, config.dpi );
|
||||
// Get size.
|
||||
rsvg_handle_get_dimensions ( handle, &dimensions );
|
||||
// Create cairo surface in the right size.
|
||||
double scale = (double) height / dimensions.height;
|
||||
surface = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32,
|
||||
(double) dimensions.width * scale,
|
||||
(double) dimensions.height * scale );
|
||||
gboolean failed = cairo_surface_status ( surface ) != CAIRO_STATUS_SUCCESS;
|
||||
if ( G_LIKELY ( failed == FALSE ) ) {
|
||||
cairo_t *cr = cairo_create ( surface );
|
||||
cairo_scale ( cr, scale, scale );
|
||||
failed = rsvg_handle_render_cairo ( handle, cr ) == FALSE;
|
||||
cairo_destroy ( cr );
|
||||
}
|
||||
|
||||
rsvg_handle_close ( handle, &error );
|
||||
g_object_unref ( handle );
|
||||
|
||||
/** Rendering fails */
|
||||
if ( G_UNLIKELY ( failed ) ) {
|
||||
g_warning ( "Failed to render file: '%s'", file );
|
||||
cairo_surface_destroy ( surface );
|
||||
surface = NULL;
|
||||
}
|
||||
}
|
||||
if ( G_UNLIKELY ( error != NULL ) ) {
|
||||
g_warning ( "Failed to render SVG file: '%s': %s", file, error->message );
|
||||
g_error_free ( error );
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
static void parse_pair ( char *input, rofi_range_pair *item )
|
||||
{
|
||||
// Skip leading blanks.
|
||||
|
|
|
@ -44,9 +44,8 @@
|
|||
#include "nkutils-enum.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <jpeglib.h>
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -58,6 +57,8 @@ typedef struct
|
|||
// On uid.
|
||||
GHashTable *icon_cache_uid;
|
||||
|
||||
// list extensions
|
||||
GList *supported_extensions;
|
||||
uint32_t last_uid;
|
||||
} IconFetcher;
|
||||
|
||||
|
@ -87,6 +88,7 @@ typedef struct
|
|||
*/
|
||||
IconFetcher *rofi_icon_fetcher_data = NULL;
|
||||
|
||||
|
||||
static void rofi_icon_fetch_entry_free ( gpointer data )
|
||||
{
|
||||
IconFetcherNameEntry *entry = (IconFetcherNameEntry *) data;
|
||||
|
@ -123,6 +125,22 @@ void rofi_icon_fetcher_init ( void )
|
|||
|
||||
rofi_icon_fetcher_data->icon_cache_uid = g_hash_table_new ( g_direct_hash, g_direct_equal );
|
||||
rofi_icon_fetcher_data->icon_cache = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, rofi_icon_fetch_entry_free );
|
||||
|
||||
|
||||
GSList *l = gdk_pixbuf_get_formats();
|
||||
for ( GSList *li = l; li != NULL; li = g_slist_next(li))
|
||||
{
|
||||
gchar **exts = gdk_pixbuf_format_get_extensions ( (GdkPixbufFormat *)li->data );
|
||||
|
||||
for ( unsigned int i = 0; exts && exts[i]; i ++ ) {
|
||||
rofi_icon_fetcher_data->supported_extensions = g_list_append ( rofi_icon_fetcher_data->supported_extensions, exts[i]);
|
||||
exts[i] = NULL;
|
||||
}
|
||||
|
||||
g_free ( exts );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void rofi_icon_fetcher_destroy ( void )
|
||||
|
@ -136,180 +154,106 @@ void rofi_icon_fetcher_destroy ( void )
|
|||
g_hash_table_unref ( rofi_icon_fetcher_data->icon_cache_uid );
|
||||
g_hash_table_unref ( rofi_icon_fetcher_data->icon_cache );
|
||||
|
||||
|
||||
g_list_foreach ( rofi_icon_fetcher_data->supported_extensions, (GFunc)g_free, NULL );
|
||||
g_list_free ( rofi_icon_fetcher_data->supported_extensions );
|
||||
g_free ( rofi_icon_fetcher_data );
|
||||
}
|
||||
|
||||
static cairo_surface_t* cairo_image_surface_create_from_jpeg_private ( struct jpeg_decompress_struct* cinfo )
|
||||
/*
|
||||
* _rofi_icon_fetcher_get_icon_surface and alpha_mult
|
||||
* are inspired by gdk_cairo_set_source_pixbuf
|
||||
* GDK is:
|
||||
* Copyright (C) 2011-2018 Red Hat, Inc.
|
||||
*/
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
#define RED_BYTE 2
|
||||
#define GREEN_BYTE 1
|
||||
#define BLUE_BYTE 0
|
||||
#define ALPHA_BYTE 3
|
||||
#else
|
||||
#define RED_BYTE 1
|
||||
#define GREEN_BYTE 2
|
||||
#define BLUE_BYTE 3
|
||||
#define ALPHA_BYTE 0
|
||||
#endif
|
||||
|
||||
static inline guchar alpha_mult(guchar c, guchar a)
|
||||
{
|
||||
cairo_surface_t* surface = 0;
|
||||
unsigned char * data = 0;
|
||||
unsigned char * rgb = 0;
|
||||
|
||||
jpeg_read_header ( cinfo, TRUE );
|
||||
jpeg_start_decompress ( cinfo );
|
||||
|
||||
surface = cairo_image_surface_create ( CAIRO_FORMAT_RGB24, cinfo->image_width, cinfo->image_height );
|
||||
data = cairo_image_surface_get_data ( surface );
|
||||
rgb = (unsigned char *) ( malloc ( cinfo->output_width * cinfo->output_components ) );
|
||||
|
||||
while ( cinfo->output_scanline < cinfo->output_height ) {
|
||||
unsigned int i;
|
||||
int scanline = cinfo->output_scanline * cairo_image_surface_get_stride ( surface );
|
||||
|
||||
jpeg_read_scanlines ( cinfo, &rgb, 1 );
|
||||
|
||||
for ( i = 0; i < cinfo->output_width; i++ ) {
|
||||
int offset = scanline + ( i * 4 );
|
||||
|
||||
data[offset + 3] = 255;
|
||||
data[offset + 2] = rgb[( i * 3 )];
|
||||
data[offset + 1] = rgb[( i * 3 ) + 1];
|
||||
data[offset ] = rgb[( i * 3 ) + 2];
|
||||
guint16 t;
|
||||
switch ( a )
|
||||
{
|
||||
case 0xff:
|
||||
return c;
|
||||
case 0x00:
|
||||
return 0x00;
|
||||
default:
|
||||
t = c * a + 0x7f;
|
||||
return ((t >> 8) + t) >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_surface_t * rofi_icon_fetcher_get_surface_from_pixbuf(GdkPixbuf
|
||||
*pixbuf)
|
||||
{
|
||||
gint width, height;
|
||||
const guchar *pixels;
|
||||
gint stride;
|
||||
gboolean alpha;
|
||||
|
||||
if ( pixbuf == NULL )
|
||||
return NULL;
|
||||
|
||||
width = gdk_pixbuf_get_width(pixbuf);
|
||||
height = gdk_pixbuf_get_height(pixbuf);
|
||||
pixels = gdk_pixbuf_read_pixels(pixbuf);
|
||||
stride = gdk_pixbuf_get_rowstride(pixbuf);
|
||||
alpha = gdk_pixbuf_get_has_alpha(pixbuf);
|
||||
|
||||
cairo_surface_t *surface = NULL;
|
||||
|
||||
gint cstride;
|
||||
guint lo, o;
|
||||
guchar a = 0xff;
|
||||
const guchar *pixels_end, *line, *line_end;
|
||||
guchar *cpixels, *cline;
|
||||
|
||||
pixels_end = pixels + height * stride;
|
||||
o = alpha ? 4 : 3;
|
||||
lo = o * width;
|
||||
|
||||
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
|
||||
cpixels = cairo_image_surface_get_data(surface);
|
||||
cstride = cairo_image_surface_get_stride(surface);
|
||||
|
||||
cairo_surface_flush(surface);
|
||||
while ( pixels < pixels_end )
|
||||
{
|
||||
line = pixels;
|
||||
line_end = line + lo;
|
||||
cline = cpixels;
|
||||
|
||||
while ( line < line_end )
|
||||
{
|
||||
if ( alpha )
|
||||
a = line[3];
|
||||
cline[RED_BYTE] = alpha_mult(line[0], a);
|
||||
cline[GREEN_BYTE] = alpha_mult(line[1], a);
|
||||
cline[BLUE_BYTE] = alpha_mult(line[2], a);
|
||||
cline[ALPHA_BYTE] = a;
|
||||
|
||||
line += o;
|
||||
cline += 4;
|
||||
}
|
||||
|
||||
free ( rgb );
|
||||
|
||||
jpeg_finish_decompress ( cinfo );
|
||||
jpeg_destroy_decompress ( cinfo );
|
||||
|
||||
cairo_surface_mark_dirty ( surface );
|
||||
pixels += stride;
|
||||
cpixels += cstride;
|
||||
}
|
||||
cairo_surface_mark_dirty(surface);
|
||||
cairo_surface_flush(surface);
|
||||
|
||||
return surface;
|
||||
}
|
||||
struct jpegErrorManager {
|
||||
/* "public" fields */
|
||||
struct jpeg_error_mgr pub;
|
||||
/* for return to caller */
|
||||
jmp_buf setjmp_buffer;
|
||||
};
|
||||
char jpegLastErrorMsg[JMSG_LENGTH_MAX];
|
||||
static void jpegErrorExit (j_common_ptr cinfo)
|
||||
{
|
||||
/* cinfo->err actually points to a jpegErrorManager struct */
|
||||
struct jpegErrorManager* myerr = (struct jpegErrorManager*) cinfo->err;
|
||||
|
||||
/* Create the message */
|
||||
( *(cinfo->err->format_message) ) (cinfo, jpegLastErrorMsg);
|
||||
g_warning ( jpegLastErrorMsg, NULL );
|
||||
|
||||
/* Jump to the setjmp point */
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
static cairo_surface_t* cairo_image_surface_create_from_jpeg ( const char* file )
|
||||
{
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
cairo_surface_t * surface;
|
||||
FILE * infile;
|
||||
|
||||
if ( ( infile = fopen ( file, "rb" ) ) == NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct jpegErrorManager jerr;
|
||||
cinfo.err = jpeg_std_error( &jerr.pub);
|
||||
jerr.pub.error_exit = jpegErrorExit;
|
||||
/* Establish the setjmp return context for my_error_exit to use. */
|
||||
if (setjmp(jerr.setjmp_buffer)) {
|
||||
/* If we get here, the JPEG code has signaled an error. */
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fclose(infile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jpeg_create_decompress ( &cinfo );
|
||||
jpeg_stdio_src ( &cinfo, infile );
|
||||
|
||||
surface = cairo_image_surface_create_from_jpeg_private ( &cinfo );
|
||||
|
||||
fclose ( infile );
|
||||
|
||||
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
|
||||
|
||||
enum {
|
||||
IMAGE_PNG,
|
||||
IMAGE_JPG,
|
||||
IMAGE_JPEG,
|
||||
IMAGE_SVG,
|
||||
#ifdef HAVE_LIBGIF
|
||||
IMAGE_GIF,
|
||||
#endif
|
||||
IMAGE_MAX_VALUES
|
||||
} RofiIconFetchDecoder;
|
||||
|
||||
static const gchar * const _image_exts[IMAGE_MAX_VALUES] = {
|
||||
[IMAGE_PNG] = ".png",
|
||||
[IMAGE_JPG] = ".jpg",
|
||||
[IMAGE_JPEG] = ".jpeg",
|
||||
[IMAGE_SVG] = ".svg",
|
||||
#ifdef HAVE_LIBGIF
|
||||
[IMAGE_GIF] = ".gif",
|
||||
#endif
|
||||
};
|
||||
|
||||
gboolean rofi_icon_fetcher_file_is_image ( const char * const path )
|
||||
{
|
||||
|
@ -320,10 +264,14 @@ gboolean rofi_icon_fetcher_file_is_image ( const char * const path )
|
|||
if ( suf == NULL ) {
|
||||
return FALSE;
|
||||
}
|
||||
suf++;
|
||||
|
||||
guint64 type;
|
||||
gboolean r = nk_enum_parse ( suf, _image_exts, G_N_ELEMENTS(_image_exts), TRUE, FALSE, &type );
|
||||
return r;
|
||||
for ( GList *iter = rofi_icon_fetcher_data->supported_extensions; iter != NULL ; iter = g_list_next ( iter ) ) {
|
||||
if ( g_ascii_strcasecmp(iter->data, suf ) == 0 ) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void rofi_icon_fetcher_worker ( thread_state *sdata, G_GNUC_UNUSED gpointer user_data )
|
||||
|
@ -360,59 +308,20 @@ static void rofi_icon_fetcher_worker ( thread_state *sdata, G_GNUC_UNUSED gpoint
|
|||
return ;
|
||||
}
|
||||
|
||||
guint64 type;
|
||||
gboolean is_image = nk_enum_parse ( suf, _image_exts, G_N_ELEMENTS(_image_exts), TRUE, FALSE, &type );
|
||||
if ( is_image )
|
||||
{
|
||||
if ( type == IMAGE_PNG ) {
|
||||
icon_surf = cairo_image_surface_create_from_png ( icon_path );
|
||||
GError *error = NULL;
|
||||
GdkPixbuf *pb = gdk_pixbuf_new_from_file_at_scale ( icon_path, sentry->size, sentry->size, TRUE, &error );
|
||||
if ( error != NULL ) {
|
||||
g_warning ( "Failed to load image: %s", error->message);
|
||||
g_error_free( error );
|
||||
if ( pb ) {
|
||||
g_object_unref ( pb );
|
||||
}
|
||||
#ifdef HAVE_LIBGIF
|
||||
else if ( type == IMAGE_GIF ) {
|
||||
icon_surf = cairo_image_surface_create_from_gif ( icon_path );
|
||||
} else {
|
||||
icon_surf = rofi_icon_fetcher_get_surface_from_pixbuf(pb );
|
||||
g_object_unref ( pb );
|
||||
}
|
||||
#endif
|
||||
else if ( type == IMAGE_JPG || type == IMAGE_JPEG ) {
|
||||
icon_surf = cairo_image_surface_create_from_jpeg ( icon_path );
|
||||
}
|
||||
else if ( type == IMAGE_SVG ) {
|
||||
icon_surf = cairo_image_surface_create_from_svg ( icon_path, sentry->size );
|
||||
}
|
||||
else {
|
||||
g_debug ( "icon type not yet supported: %s", icon_path );
|
||||
}
|
||||
}
|
||||
if ( icon_surf ) {
|
||||
if ( cairo_surface_status ( icon_surf ) == CAIRO_STATUS_SUCCESS ) {
|
||||
float sw = sentry->size / (float) cairo_image_surface_get_width ( icon_surf );
|
||||
float sh = sentry->size / (float) cairo_image_surface_get_height ( icon_surf );
|
||||
|
||||
float scale = ( sw > sh ) ? sh : sw;
|
||||
if ( scale < 0.5 ) {
|
||||
cairo_surface_t * surface = cairo_image_surface_create (
|
||||
cairo_image_surface_get_format ( icon_surf ),
|
||||
cairo_image_surface_get_width ( icon_surf ) * scale,
|
||||
cairo_image_surface_get_height ( icon_surf ) * scale );
|
||||
|
||||
cairo_t *d = cairo_create ( surface );
|
||||
cairo_scale ( d, scale, scale );
|
||||
cairo_set_source_surface ( d, icon_surf, 0.0, 0.0 );
|
||||
cairo_pattern_set_filter ( cairo_get_source ( d ), CAIRO_FILTER_FAST );
|
||||
cairo_paint ( d );
|
||||
|
||||
cairo_destroy ( d );
|
||||
cairo_surface_destroy ( icon_surf );
|
||||
icon_surf = surface;
|
||||
}
|
||||
}
|
||||
// check if surface is valid.
|
||||
if ( cairo_surface_status ( icon_surf ) != CAIRO_STATUS_SUCCESS ) {
|
||||
g_debug ( "icon failed to open: %s(%d): %s", sentry->entry->name, sentry->size, icon_path );
|
||||
cairo_surface_destroy ( icon_surf );
|
||||
icon_surf = NULL;
|
||||
}
|
||||
sentry->surface = icon_surf;
|
||||
}
|
||||
g_free ( icon_path_ );
|
||||
rofi_view_reload ();
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include <glib.h>
|
||||
#include <cairo.h>
|
||||
#include <cairo-xcb.h>
|
||||
#include <librsvg/rsvg.h>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xcb_aux.h>
|
||||
|
|
Loading…
Reference in a new issue