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:
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
|
* libstartup-notification-1.0
|
||||||
* libxkbcommon >= 0.4.1
|
* libxkbcommon >= 0.4.1
|
||||||
* libxkbcommon-x11
|
* libxkbcommon-x11
|
||||||
|
* libjpeg
|
||||||
* libxcb (sometimes split, you need libxcb, libxcb-xkb and libxcb-randr libxcb-xinerama)
|
* libxcb (sometimes split, you need libxcb, libxcb-xkb and libxcb-randr libxcb-xinerama)
|
||||||
* xcb-util
|
* xcb-util
|
||||||
* xcb-util-wm (sometimes split as libxcb-ewmh and libxcb-icccm)
|
* xcb-util-wm (sometimes split as libxcb-ewmh and libxcb-icccm)
|
||||||
|
|
|
@ -165,6 +165,7 @@ rofi_LDADD=\
|
||||||
$(pango_LIBS)\
|
$(pango_LIBS)\
|
||||||
$(cairo_LIBS)\
|
$(cairo_LIBS)\
|
||||||
$(librsvg_LIBS)\
|
$(librsvg_LIBS)\
|
||||||
|
$(libjpeg_LIBS)\
|
||||||
$(LIBS)
|
$(LIBS)
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -321,6 +322,7 @@ textbox_test_CFLAGS=\
|
||||||
$(cairo_CFLAGS)\
|
$(cairo_CFLAGS)\
|
||||||
$(libsn_CFLAGS)\
|
$(libsn_CFLAGS)\
|
||||||
$(librsvg_CFLAGS)\
|
$(librsvg_CFLAGS)\
|
||||||
|
$(libjpeg_CFLAGS)\
|
||||||
-DPLUGIN_PATH=\"${libdir}/rofi\"\
|
-DPLUGIN_PATH=\"${libdir}/rofi\"\
|
||||||
-DTHEME_DIR=\"$(themedir)\"\
|
-DTHEME_DIR=\"$(themedir)\"\
|
||||||
-I$(top_srcdir)/include/\
|
-I$(top_srcdir)/include/\
|
||||||
|
|
|
@ -128,6 +128,7 @@ PKG_CHECK_MODULES([pango], [pango pangocairo])
|
||||||
PKG_CHECK_MODULES([cairo], [cairo cairo-xcb])
|
PKG_CHECK_MODULES([cairo], [cairo cairo-xcb])
|
||||||
PKG_CHECK_MODULES([libsn], [libstartup-notification-1.0 ])
|
PKG_CHECK_MODULES([libsn], [libstartup-notification-1.0 ])
|
||||||
PKG_CHECK_MODULES([librsvg], [librsvg-2.0 ])
|
PKG_CHECK_MODULES([librsvg], [librsvg-2.0 ])
|
||||||
|
PKG_CHECK_MODULES([libjpeg], [libjpeg])
|
||||||
|
|
||||||
dnl ---------------------------------------------------------------------
|
dnl ---------------------------------------------------------------------
|
||||||
dnl check - Unit testing.
|
dnl check - Unit testing.
|
||||||
|
|
|
@ -39,6 +39,9 @@
|
||||||
|
|
||||||
#include "nkutils-xdg-theme.h"
|
#include "nkutils-xdg-theme.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <jpeglib.h>
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
// Context for icon-themes.
|
// Context for icon-themes.
|
||||||
|
@ -129,6 +132,67 @@ void rofi_icon_fetcher_destroy ( void )
|
||||||
|
|
||||||
g_free ( rofi_icon_fetcher_data );
|
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 )
|
static void rofi_icon_fetcher_worker ( thread_state *sdata, G_GNUC_UNUSED gpointer user_data )
|
||||||
{
|
{
|
||||||
g_debug ( "starting up icon fetching thread." );
|
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" ) ) {
|
if ( g_str_has_suffix ( icon_path, ".png" ) ) {
|
||||||
icon_surf = cairo_image_surface_create_from_png ( icon_path );
|
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" ) ) {
|
else if ( g_str_has_suffix ( icon_path, ".svg" ) ) {
|
||||||
icon_surf = cairo_image_surface_create_from_svg ( icon_path, sentry->size );
|
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 );
|
g_debug ( "icon type not yet supported: %s", icon_path );
|
||||||
}
|
}
|
||||||
if ( icon_surf ) {
|
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.
|
// check if surface is valid.
|
||||||
if ( cairo_surface_status ( icon_surf ) != CAIRO_STATUS_SUCCESS ) {
|
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 );
|
g_debug ( "icon failed to open: %s(%d): %s", sentry->entry->name, sentry->size, icon_path );
|
||||||
|
|
Loading…
Reference in a new issue