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; | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
|         int landscape = w > h; | ||||
|         int orig_larger = landscape ? w : h; | ||||
| /**
 | ||||
|  * Scales the given image dimensions if necessary according to the settings. | ||||
|  * | ||||
|  * @param w a pointer to the image width, to be modified in-place | ||||
|  * @param h a pointer to the image height, to be modified in-place | ||||
|  */ | ||||
| static bool icon_size_clamp(int *w, int *h) { | ||||
|         int _w = *w, _h = *h; | ||||
|         int landscape = _w > _h; | ||||
|         int orig_larger = landscape ? _w : _h; | ||||
|         double larger = orig_larger; | ||||
|         double smaller = landscape ? h : w; | ||||
|         double smaller = landscape ? _h : _w; | ||||
|         if (settings.min_icon_size && smaller < settings.min_icon_size) { | ||||
|                 larger = larger / 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; | ||||
|         } | ||||
|         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; | ||||
|                 scaled = gdk_pixbuf_scale_simple(pixbuf, | ||||
|                                 (int) (landscape ? larger : smaller), | ||||
|                                 (int) (landscape ? smaller : larger), | ||||
|                                 GDK_INTERP_BILINEAR); | ||||
|                                                  w, | ||||
|                                                  h, | ||||
|                                                  GDK_INTERP_BILINEAR); | ||||
|                 g_object_unref(pixbuf); | ||||
|                 pixbuf = scaled; | ||||
|         } | ||||
| @ -145,8 +171,19 @@ GdkPixbuf *get_pixbuf_from_file(const char *filename) | ||||
| { | ||||
|         char *path = string_to_path(g_strdup(filename)); | ||||
|         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) { | ||||
|                 LOG_W("%s", error->message); | ||||
| @ -324,6 +361,8 @@ GdkPixbuf *icon_get_for_data(GVariant *data, char **id) | ||||
|         g_free(data_chk); | ||||
|         g_variant_unref(data_variant); | ||||
| 
 | ||||
|         pixbuf = icon_pixbuf_scale(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); | ||||
| 
 | ||||
| /**
 | ||||
|  * 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.
 | ||||
| /** Retrieve an icon by its full filepath, scaled according to settings.
 | ||||
|  * | ||||
|  * @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); | ||||
| 
 | ||||
| /** 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
 | ||||
|  *                 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); | ||||
| 
 | ||||
| /** 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 | ||||
|  * 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); | ||||
| 
 | ||||
| /** 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 | ||||
|  * 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); | ||||
| 
 | ||||
|         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) | ||||
| @ -264,7 +263,6 @@ void notification_icon_replace_data(struct notification *n, GVariant *new_icon) | ||||
|         g_clear_pointer(&n->icon_id, g_free); | ||||
| 
 | ||||
|         n->icon = icon_get_for_data(new_icon, &n->icon_id); | ||||
|         n->icon = icon_pixbuf_scale(n->icon); | ||||
| } | ||||
| 
 | ||||
| /* see notification.h */ | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Jonas Berlin
						Jonas Berlin