summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Davenport <qball@gmpclient.org>2020-02-14 14:27:03 +0100
committerDave Davenport <qball@gmpclient.org>2020-02-14 14:27:03 +0100
commit855d09ded7a711dae050e2140a71698ee40a1470 (patch)
tree96d16cc0eaacb3ca4b4745142530aba36e1339d7
parent3bf9d3d3b160e5a17ac9ec1eb7887374b580670d (diff)
[IconFetcher] Add jpeg support, scale on load.
TODO: fix scaling speed.
-rw-r--r--INSTALL.md1
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac1
-rw-r--r--source/rofi-icon-fetcher.c91
4 files changed, 95 insertions, 0 deletions
diff --git a/INSTALL.md b/INSTALL.md
index a855e9cc..1c2f8f58 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -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)
diff --git a/Makefile.am b/Makefile.am
index 481b4c85..97a6f387 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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/\
diff --git a/configure.ac b/configure.ac
index 349508a0..9526b291 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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.
diff --git a/source/rofi-icon-fetcher.c b/source/rofi-icon-fetcher.c
index e67e2f24..e0917248 100644
--- a/source/rofi-icon-fetcher.c
+++ b/source/rofi-icon-fetcher.c
@@ -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 );