diff options
| -rw-r--r-- | fastiv-browser.c | 121 | 
1 files changed, 67 insertions, 54 deletions
| diff --git a/fastiv-browser.c b/fastiv-browser.c index ba6d8a3..818006c 100644 --- a/fastiv-browser.c +++ b/fastiv-browser.c @@ -37,6 +37,8 @@ entry_free(Entry *self)  		cairo_surface_destroy(self->thumbnail);  } +static const double g_row_height = 256; +  // --- Boilerplate -------------------------------------------------------------  struct _FastivBrowser { @@ -135,8 +137,6 @@ fastiv_browser_draw(GtkWidget *widget, cairo_t *cr)  	gtk_render_background(gtk_widget_get_style_context(widget), cr, 0, 0,  		allocation.width, allocation.height); -	const double row_height = 256; -  	gint occupied_width = 0, y = 0;  	for (guint i = 0; i < self->entries->len; i++) {  		const Entry *entry = &g_array_index(self->entries, Entry, i); @@ -145,65 +145,19 @@ fastiv_browser_draw(GtkWidget *widget, cairo_t *cr)  		int width = cairo_image_surface_get_width(entry->thumbnail);  		int height = cairo_image_surface_get_height(entry->thumbnail); - -		double scale_x = 1; -		double scale_y = 1; -		if (width > 2 * height) { -			scale_x = 2 * row_height / width; -			scale_y = round(scale_x * height) / height; -		} else { -			scale_y = row_height / height; -			scale_x = round(scale_y * width) / width; -		} - -		int projected_width = round(scale_x * width); -		int projected_height = round(scale_y * height); -		cairo_surface_t *scaled = cairo_image_surface_create( -			CAIRO_FORMAT_ARGB32, projected_width, projected_height); - -		// pixman can take gamma into account when scaling, unlike Cairo. -		struct pixman_f_transform xform_floating; -		struct pixman_transform xform; - -		pixman_image_t *src = pixman_image_create_bits( -			PIXMAN_a8r8g8b8_sRGB, width, height, -			(uint32_t *) cairo_image_surface_get_data(entry->thumbnail), -			cairo_image_surface_get_stride(entry->thumbnail)); -		pixman_image_t *dest = pixman_image_create_bits( -			PIXMAN_a8r8g8b8_sRGB, -			cairo_image_surface_get_width(scaled), -			cairo_image_surface_get_height(scaled), -			(uint32_t *) cairo_image_surface_get_data(scaled), -			cairo_image_surface_get_stride(scaled)); - -		pixman_f_transform_init_scale(&xform_floating, scale_x, scale_y); -		pixman_f_transform_invert(&xform_floating, &xform_floating); -		pixman_transform_from_pixman_f_transform(&xform, &xform_floating); -		pixman_image_set_transform(src, &xform); -		pixman_image_set_filter(src, PIXMAN_FILTER_BILINEAR, NULL, 0); -		pixman_image_set_repeat(src, PIXMAN_REPEAT_PAD); - -		pixman_image_composite(PIXMAN_OP_SRC, src, NULL, dest, 0, 0, 0, 0, 0, 0, -			projected_width, projected_height); -		pixman_image_unref(src); -		pixman_image_unref(dest); - -		cairo_surface_mark_dirty(scaled); -  		if (occupied_width != 0 && -			occupied_width + projected_width > allocation.width) { +			occupied_width + width > allocation.width) {  			occupied_width = 0; -			y += row_height; +			y += g_row_height;  		}  		cairo_save(cr); -		cairo_translate(cr, occupied_width, y + row_height - projected_height); -		cairo_set_source_surface(cr, scaled, 0, 0); -		cairo_surface_destroy(scaled); +		cairo_translate(cr, occupied_width, y + g_row_height - height); +		cairo_set_source_surface(cr, entry->thumbnail, 0, 0);  		cairo_paint(cr);  		cairo_restore(cr); -		occupied_width += projected_width; +		occupied_width += width;  	}  	return TRUE;  } @@ -241,6 +195,64 @@ fastiv_browser_init(FastivBrowser *self)  	self->selected = -1;  } +static cairo_surface_t * +rescale_thumbnail(cairo_surface_t *thumbnail) +{ +	if (!thumbnail) +		return thumbnail; + +	int width = cairo_image_surface_get_width(thumbnail); +	int height = cairo_image_surface_get_height(thumbnail); + +	double scale_x = 1; +	double scale_y = 1; +	if (width > 2 * height) { +		scale_x = 2 * g_row_height / width; +		scale_y = round(scale_x * height) / height; +	} else { +		scale_y = g_row_height / height; +		scale_x = round(scale_y * width) / width; +	} +	if (scale_x == 1 && scale_y == 1) +		return thumbnail; + +	int projected_width = round(scale_x * width); +	int projected_height = round(scale_y * height); +	cairo_surface_t *scaled = cairo_image_surface_create( +		CAIRO_FORMAT_ARGB32, projected_width, projected_height); + +	// pixman can take gamma into account when scaling, unlike Cairo. +	struct pixman_f_transform xform_floating; +	struct pixman_transform xform; + +	pixman_image_t *src = pixman_image_create_bits( +		PIXMAN_a8r8g8b8_sRGB, width, height, +		(uint32_t *) cairo_image_surface_get_data(thumbnail), +		cairo_image_surface_get_stride(thumbnail)); +	pixman_image_t *dest = pixman_image_create_bits( +		PIXMAN_a8r8g8b8_sRGB, +		cairo_image_surface_get_width(scaled), +		cairo_image_surface_get_height(scaled), +		(uint32_t *) cairo_image_surface_get_data(scaled), +		cairo_image_surface_get_stride(scaled)); + +	pixman_f_transform_init_scale(&xform_floating, scale_x, scale_y); +	pixman_f_transform_invert(&xform_floating, &xform_floating); +	pixman_transform_from_pixman_f_transform(&xform, &xform_floating); +	pixman_image_set_transform(src, &xform); +	pixman_image_set_filter(src, PIXMAN_FILTER_BILINEAR, NULL, 0); +	pixman_image_set_repeat(src, PIXMAN_REPEAT_PAD); + +	pixman_image_composite(PIXMAN_OP_SRC, src, NULL, dest, 0, 0, 0, 0, 0, 0, +		projected_width, projected_height); +	pixman_image_unref(src); +	pixman_image_unref(dest); + +	cairo_surface_destroy(thumbnail); +	cairo_surface_mark_dirty(scaled); +	return scaled; +} +  void  fastiv_browser_load(FastivBrowser *self, const char *path)  { @@ -259,7 +271,8 @@ fastiv_browser_load(FastivBrowser *self, const char *path)  		gchar *subpath = g_build_filename(path, filename, NULL);  		g_array_append_val(self->entries,  			((Entry){ -				.thumbnail = fastiv_io_lookup_thumbnail(subpath), +				.thumbnail = +					rescale_thumbnail(fastiv_io_lookup_thumbnail(subpath)),  				.filename = subpath,  			}));  	} | 
