Scale icons during loading to get best quality for e.g. vector images
This commit is contained in:
		
							parent
							
								
									ab3b5c2805
								
							
						
					
					
						commit
						364bce1ed0
					
				
							
								
								
									
										65
									
								
								src/icon.c
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								src/icon.c
									
									
									
									
									
								
							| @ -110,16 +110,18 @@ cairo_surface_t *gdk_pixbuf_to_cairo_surface(GdkPixbuf *pixbuf) | |||||||
|         return icon_surface; |         return icon_surface; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf) | /**
 | ||||||
| { |  * Scales the given image dimensions if necessary according to the settings. | ||||||
|         ASSERT_OR_RET(pixbuf, NULL); |  * | ||||||
| 
 |  * @param w a pointer to the image width, to be modified in-place | ||||||
|         int w = gdk_pixbuf_get_width(pixbuf); |  * @param h a pointer to the image height, to be modified in-place | ||||||
|         int h = gdk_pixbuf_get_height(pixbuf); |  */ | ||||||
|         int landscape = w > h; | static bool icon_size_clamp(int *w, int *h) { | ||||||
|         int orig_larger = landscape ? w : h; |         int _w = *w, _h = *h; | ||||||
|  |         int landscape = _w > _h; | ||||||
|  |         int orig_larger = landscape ? _w : _h; | ||||||
|         double larger = orig_larger; |         double larger = orig_larger; | ||||||
|         double smaller = landscape ? h : w; |         double smaller = landscape ? _h : _w; | ||||||
|         if (settings.min_icon_size && smaller < settings.min_icon_size) { |         if (settings.min_icon_size && smaller < settings.min_icon_size) { | ||||||
|                 larger = larger / smaller * settings.min_icon_size; |                 larger = larger / smaller * settings.min_icon_size; | ||||||
|                 smaller = settings.min_icon_size; |                 smaller = settings.min_icon_size; | ||||||
| @ -129,11 +131,35 @@ GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf) | |||||||
|                 larger = settings.max_icon_size; |                 larger = settings.max_icon_size; | ||||||
|         } |         } | ||||||
|         if ((int) larger != orig_larger) { |         if ((int) larger != orig_larger) { | ||||||
|  |                 *w = (int) (landscape ? larger : smaller); | ||||||
|  |                 *h = (int) (landscape ? smaller : larger); | ||||||
|  |                 return TRUE; | ||||||
|  |         } | ||||||
|  |         return FALSE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Scales the given GdkPixbuf if necessary according to the settings. | ||||||
|  |  * | ||||||
|  |  * @param pixbuf (nullable) The pixbuf, which may be too big. | ||||||
|  |  *                          Takes ownership of the reference. | ||||||
|  |  * @return the scaled version of the pixbuf. If scaling wasn't | ||||||
|  |  *         necessary, it returns the same pixbuf. Transfers full | ||||||
|  |  *         ownership of the reference. | ||||||
|  |  */ | ||||||
|  | static GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf) | ||||||
|  | { | ||||||
|  |         ASSERT_OR_RET(pixbuf, NULL); | ||||||
|  | 
 | ||||||
|  |         int w = gdk_pixbuf_get_width(pixbuf); | ||||||
|  |         int h = gdk_pixbuf_get_height(pixbuf); | ||||||
|  | 
 | ||||||
|  |         if (icon_size_clamp(&w, &h)) { | ||||||
|                 GdkPixbuf *scaled; |                 GdkPixbuf *scaled; | ||||||
|                 scaled = gdk_pixbuf_scale_simple(pixbuf, |                 scaled = gdk_pixbuf_scale_simple(pixbuf, | ||||||
|                                 (int) (landscape ? larger : smaller), |                                                  w, | ||||||
|                                 (int) (landscape ? smaller : larger), |                                                  h, | ||||||
|                                 GDK_INTERP_BILINEAR); |                                                  GDK_INTERP_BILINEAR); | ||||||
|                 g_object_unref(pixbuf); |                 g_object_unref(pixbuf); | ||||||
|                 pixbuf = scaled; |                 pixbuf = scaled; | ||||||
|         } |         } | ||||||
| @ -145,8 +171,19 @@ GdkPixbuf *get_pixbuf_from_file(const char *filename) | |||||||
| { | { | ||||||
|         char *path = string_to_path(g_strdup(filename)); |         char *path = string_to_path(g_strdup(filename)); | ||||||
|         GError *error = NULL; |         GError *error = NULL; | ||||||
|  |         gint w, h; | ||||||
| 
 | 
 | ||||||
|         GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &error); |         if (!gdk_pixbuf_get_file_info (path, &w, &h)) { | ||||||
|  |                 LOG_W("Failed to load image info for %s", filename); | ||||||
|  |                 g_error_free(error); | ||||||
|  |                 return NULL; | ||||||
|  |         } | ||||||
|  |         icon_size_clamp(&w, &h); | ||||||
|  |         GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_scale(path, | ||||||
|  |                                                               w, | ||||||
|  |                                                               h, | ||||||
|  |                                                               TRUE, | ||||||
|  |                                                               &error); | ||||||
| 
 | 
 | ||||||
|         if (error) { |         if (error) { | ||||||
|                 LOG_W("%s", error->message); |                 LOG_W("%s", error->message); | ||||||
| @ -324,6 +361,8 @@ GdkPixbuf *icon_get_for_data(GVariant *data, char **id) | |||||||
|         g_free(data_chk); |         g_free(data_chk); | ||||||
|         g_variant_unref(data_variant); |         g_variant_unref(data_variant); | ||||||
| 
 | 
 | ||||||
|  |         pixbuf = icon_pixbuf_scale(pixbuf); | ||||||
|  | 
 | ||||||
|         return pixbuf; |         return pixbuf; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										19
									
								
								src/icon.h
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								src/icon.h
									
									
									
									
									
								
							| @ -8,18 +8,7 @@ | |||||||
| 
 | 
 | ||||||
| cairo_surface_t *gdk_pixbuf_to_cairo_surface(GdkPixbuf *pixbuf); | cairo_surface_t *gdk_pixbuf_to_cairo_surface(GdkPixbuf *pixbuf); | ||||||
| 
 | 
 | ||||||
| /**
 | /** Retrieve an icon by its full filepath, scaled according to settings.
 | ||||||
|  * Scales the given GdkPixbuf if necessary according to the settings. |  | ||||||
|  * |  | ||||||
|  * @param pixbuf (nullable) The pixbuf, which may be too big. |  | ||||||
|  *                          Takes ownership of the reference. |  | ||||||
|  * @return the scaled version of the pixbuf. If scaling wasn't |  | ||||||
|  *         necessary, it returns the same pixbuf. Transfers full |  | ||||||
|  *         ownership of the reference. |  | ||||||
|  */ |  | ||||||
| GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf); |  | ||||||
| 
 |  | ||||||
| /** Retrieve an icon by its full filepath.
 |  | ||||||
|  * |  * | ||||||
|  * @param filename A string representing a readable file path |  * @param filename A string representing a readable file path | ||||||
|  * |  * | ||||||
| @ -28,7 +17,7 @@ GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf); | |||||||
|  */ |  */ | ||||||
| GdkPixbuf *get_pixbuf_from_file(const char *filename); | GdkPixbuf *get_pixbuf_from_file(const char *filename); | ||||||
| 
 | 
 | ||||||
| /** Retrieve an icon by its name sent via the notification bus
 | /** Retrieve an icon by its name sent via the notification bus, scaled according to settings
 | ||||||
|  * |  * | ||||||
|  * @param iconname A string describing a `file://` URL, an arbitary filename
 |  * @param iconname A string describing a `file://` URL, an arbitary filename
 | ||||||
|  *                 or an icon name, which then gets searched for in the |  *                 or an icon name, which then gets searched for in the | ||||||
| @ -39,7 +28,7 @@ GdkPixbuf *get_pixbuf_from_file(const char *filename); | |||||||
|  */ |  */ | ||||||
| GdkPixbuf *get_pixbuf_from_icon(const char *iconname); | GdkPixbuf *get_pixbuf_from_icon(const char *iconname); | ||||||
| 
 | 
 | ||||||
| /** Read an icon from disk and convert it to a GdkPixbuf.
 | /** Read an icon from disk and convert it to a GdkPixbuf, scaled according to settings
 | ||||||
|  * |  * | ||||||
|  * The returned id will be a unique identifier. To check if two given |  * The returned id will be a unique identifier. To check if two given | ||||||
|  * GdkPixbufs are equal, it's sufficient to just compare the id strings. |  * GdkPixbufs are equal, it's sufficient to just compare the id strings. | ||||||
| @ -54,7 +43,7 @@ GdkPixbuf *get_pixbuf_from_icon(const char *iconname); | |||||||
|  */ |  */ | ||||||
| GdkPixbuf *icon_get_for_name(const char *name, char **id); | GdkPixbuf *icon_get_for_name(const char *name, char **id); | ||||||
| 
 | 
 | ||||||
| /** Convert a GVariant like described in GdkPixbuf
 | /** Convert a GVariant like described in GdkPixbuf, scaled according to settings
 | ||||||
|  * |  * | ||||||
|  * The returned id will be a unique identifier. To check if two given |  * The returned id will be a unique identifier. To check if two given | ||||||
|  * GdkPixbufs are equal, it's sufficient to just compare the id strings. |  * GdkPixbufs are equal, it's sufficient to just compare the id strings. | ||||||
|  | |||||||
| @ -252,7 +252,6 @@ void notification_icon_replace_path(struct notification *n, const char *new_icon | |||||||
|         g_clear_pointer(&n->icon_id, g_free); |         g_clear_pointer(&n->icon_id, g_free); | ||||||
| 
 | 
 | ||||||
|         n->icon = icon_get_for_name(new_icon, &n->icon_id); |         n->icon = icon_get_for_name(new_icon, &n->icon_id); | ||||||
|         n->icon = icon_pixbuf_scale(n->icon); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void notification_icon_replace_data(struct notification *n, GVariant *new_icon) | void notification_icon_replace_data(struct notification *n, GVariant *new_icon) | ||||||
| @ -264,7 +263,6 @@ void notification_icon_replace_data(struct notification *n, GVariant *new_icon) | |||||||
|         g_clear_pointer(&n->icon_id, g_free); |         g_clear_pointer(&n->icon_id, g_free); | ||||||
| 
 | 
 | ||||||
|         n->icon = icon_get_for_data(new_icon, &n->icon_id); |         n->icon = icon_get_for_data(new_icon, &n->icon_id); | ||||||
|         n->icon = icon_pixbuf_scale(n->icon); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* see notification.h */ | /* see notification.h */ | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Jonas Berlin
						Jonas Berlin