33#include <assert.h>
44#include <cairo.h>
55#include <gdk-pixbuf/gdk-pixbuf.h>
6+ #include <librsvg/rsvg.h>
67#include <stdbool.h>
78#include <string.h>
89#include <math.h>
910
1011#include "log.h"
11- #include "notification.h"
1212#include "settings.h"
1313#include "utils.h"
1414#include "icon-lookup.h"
@@ -205,7 +205,7 @@ static char *get_id_from_data(const uint8_t *data_pb, size_t width, size_t heigh
205205 return id ;
206206}
207207
208- GdkPixbuf * get_pixbuf_from_file (const char * filename , char * * id , int min_size , int max_size , double scale )
208+ cairo_surface_t * get_cairo_surface_from_file (const char * filename , char * * id , struct color fg_color , int min_size , int max_size , double scale )
209209{
210210 GError * error = NULL ;
211211 gint w , h ;
@@ -217,28 +217,74 @@ GdkPixbuf *get_pixbuf_from_file(const char *filename, char **id, int min_size, i
217217 LOG_W ("Failed to load image info for %s" , STR_NN (filename ));
218218 return NULL ;
219219 }
220- GdkPixbuf * pixbuf = NULL ;
220+
221221 // TODO immediately rescale icon upon scale changes
222222 icon_size_clamp (& w , & h , min_size , max_size );
223- pixbuf = gdk_pixbuf_new_from_file_at_scale (filename ,
223+ cairo_surface_t * icon_surface = cairo_image_surface_create (
224+ CAIRO_FORMAT_ARGB32 ,
224225 round (w * scale ),
225- round (h * scale ),
226- TRUE,
227- & error );
226+ round (h * scale )
227+ );
228+ const char * ext = strrchr (filename , '.' );
229+ if (ext && !strcmp (ext , ".svg" )) {
230+ RsvgHandle * handle = rsvg_handle_new_from_file (filename , & error );
231+ const guint8 stylesheet [37 ];
232+ const size_t stylesheet_len = sizeof (stylesheet ) / sizeof (guint8 );
233+
234+ g_snprintf ((char * )stylesheet , stylesheet_len , "path { fill: #%02x%02x%02x%02x !important; }" ,
235+ (int )(fg_color .r * 255 ),
236+ (int )(fg_color .g * 255 ),
237+ (int )(fg_color .b * 255 ),
238+ (int )(fg_color .a * 255 ));
239+ rsvg_handle_set_stylesheet (handle , stylesheet , stylesheet_len , & error );
240+
241+ cairo_t * cr = cairo_create (icon_surface );
242+ RsvgRectangle viewport = {
243+ 0 ,
244+ 0 ,
245+ cairo_image_surface_get_width (icon_surface ),
246+ cairo_image_surface_get_height (icon_surface )
247+ };
248+ rsvg_handle_render_document (handle , cr , & viewport , & error );
249+ cairo_destroy (cr );
250+ g_object_unref (handle );
251+ } else {
252+ GdkPixbuf * pixbuf = gdk_pixbuf_new_from_file_at_scale (filename ,
253+ round (w * scale ),
254+ round (h * scale ),
255+ TRUE,
256+ & error );
257+ icon_surface = gdk_pixbuf_to_cairo_surface (pixbuf );
258+ g_object_unref (pixbuf );
259+ }
228260
229261 if (error ) {
230262 LOG_W ("%s" , error -> message );
231263 g_error_free (error );
232264 }
233265
234- const uint8_t * data = gdk_pixbuf_get_pixels (pixbuf );
235- size_t rowstride = gdk_pixbuf_get_rowstride (pixbuf );
236- size_t n_channels = gdk_pixbuf_get_n_channels (pixbuf );
237- size_t bits_per_sample = gdk_pixbuf_get_bits_per_sample (pixbuf );
238- size_t pixelstride = (n_channels * bits_per_sample + 7 )/8 ;
266+ const uint8_t * data = cairo_image_surface_get_data (icon_surface );
267+ size_t rowstride = cairo_image_surface_get_stride (icon_surface );
268+
269+ int pixelstride ;
270+ switch (cairo_image_surface_get_format (icon_surface )) {
271+ case CAIRO_FORMAT_A8 :
272+ pixelstride = 1 ;
273+ break ;
274+ case CAIRO_FORMAT_RGB24 :
275+ pixelstride = 3 ;
276+ break ;
277+ case CAIRO_FORMAT_ARGB32 :
278+ pixelstride = 4 ;
279+ break ;
280+ default :
281+ LOG_W ("Unsupported cairo format %d" , cairo_image_surface_get_format (icon_surface ));
282+ cairo_surface_destroy (icon_surface );
283+ return NULL ;
284+ }
239285
240286 * id = get_id_from_data (data , w , h , pixelstride , rowstride );
241- return pixbuf ;
287+ return icon_surface ;
242288}
243289
244290char * get_path_from_icon_name (const char * iconname , int size )
0 commit comments