1
0
Fork 0
mirror of https://github.com/davatorium/rofi.git synced 2024-11-18 13:54:36 -05:00

[IconFetcher] Add jpeg support, scale on load.

TODO: fix scaling speed.
This commit is contained in:
Dave Davenport 2020-02-14 14:27:03 +01:00
parent 3bf9d3d3b1
commit 855d09ded7
4 changed files with 95 additions and 0 deletions

View file

@ -34,6 +34,7 @@ You can also use [Meson](https://mesonbuild.com/) as an alternative.
* 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)

View file

@ -165,6 +165,7 @@ rofi_LDADD=\
$(pango_LIBS)\
$(cairo_LIBS)\
$(librsvg_LIBS)\
$(libjpeg_LIBS)\
$(LIBS)
##
@ -321,6 +322,7 @@ textbox_test_CFLAGS=\
$(cairo_CFLAGS)\
$(libsn_CFLAGS)\
$(librsvg_CFLAGS)\
$(libjpeg_CFLAGS)\
-DPLUGIN_PATH=\"${libdir}/rofi\"\
-DTHEME_DIR=\"$(themedir)\"\
-I$(top_srcdir)/include/\

View file

@ -128,6 +128,7 @@ 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])
dnl ---------------------------------------------------------------------
dnl check - Unit testing.

View file

@ -39,6 +39,9 @@
#include "nkutils-xdg-theme.h"
#include <stdint.h>
#include <jpeglib.h>
typedef struct
{
// Context for icon-themes.
@ -129,6 +132,67 @@ void rofi_icon_fetcher_destroy ( void )
g_free ( rofi_icon_fetcher_data );
}
static cairo_surface_t* cairo_image_surface_create_from_jpeg_private(struct jpeg_decompress_struct* cinfo) {
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];
}
}
free(rgb);
jpeg_finish_decompress(cinfo);
jpeg_destroy_decompress(cinfo);
cairo_surface_mark_dirty(surface);
return surface;
}
static cairo_surface_t* cairo_image_surface_create_from_jpeg(const char* file) {
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cairo_surface_t* surface;
FILE* infile;
if((infile = fopen(file, "rb")) == NULL) return NULL;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, infile);
surface = cairo_image_surface_create_from_jpeg_private(&cinfo);
fclose(infile);
return surface;
}
static void rofi_icon_fetcher_worker ( thread_state *sdata, G_GNUC_UNUSED gpointer user_data )
{
g_debug ( "starting up icon fetching thread." );
@ -160,6 +224,9 @@ static void rofi_icon_fetcher_worker ( thread_state *sdata, G_GNUC_UNUSED gpoint
if ( g_str_has_suffix ( icon_path, ".png" ) ) {
icon_surf = cairo_image_surface_create_from_png ( icon_path );
}
else if ( g_str_has_suffix ( icon_path, ".jpeg" ) || g_str_has_suffix ( icon_path, ".jpg" ) ) {
icon_surf = cairo_image_surface_create_from_jpeg ( icon_path );
}
else if ( g_str_has_suffix ( icon_path, ".svg" ) ) {
icon_surf = cairo_image_surface_create_from_svg ( icon_path, sentry->size );
}
@ -167,6 +234,30 @@ static void rofi_icon_fetcher_worker ( thread_state *sdata, G_GNUC_UNUSED gpoint
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_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 );