mirror of
https://github.com/davatorium/rofi.git
synced 2024-11-25 13:55:34 -05:00
[IconFetcher] Add jpeg support, scale on load.
TODO: fix scaling speed.
This commit is contained in:
parent
3bf9d3d3b1
commit
855d09ded7
4 changed files with 95 additions and 0 deletions
|
@ -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)
|
||||
|
|
|
@ -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/\
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in a new issue