| 
						
					 | 
					 | 
					@@ -16,6 +16,7 @@
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					//
 | 
					 | 
					 | 
					 | 
					//
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#include <math.h>
 | 
					 | 
					 | 
					 | 
					#include <math.h>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					#include <pixman.h>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#include "fastiv-browser.h"
 | 
					 | 
					 | 
					 | 
					#include "fastiv-browser.h"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#include "fastiv-io.h"
 | 
					 | 
					 | 
					 | 
					#include "fastiv-io.h"
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -36,6 +37,8 @@ entry_free(Entry *self)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							cairo_surface_destroy(self->thumbnail);
 | 
					 | 
					 | 
					 | 
							cairo_surface_destroy(self->thumbnail);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					static const double g_row_height = 256;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// --- Boilerplate -------------------------------------------------------------
 | 
					 | 
					 | 
					 | 
					// --- Boilerplate -------------------------------------------------------------
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					struct _FastivBrowser {
 | 
					 | 
					 | 
					 | 
					struct _FastivBrowser {
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -134,8 +137,6 @@ fastiv_browser_draw(GtkWidget *widget, cairo_t *cr)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						gtk_render_background(gtk_widget_get_style_context(widget), cr, 0, 0,
 | 
					 | 
					 | 
					 | 
						gtk_render_background(gtk_widget_get_style_context(widget), cr, 0, 0,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							allocation.width, allocation.height);
 | 
					 | 
					 | 
					 | 
							allocation.width, allocation.height);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const double row_height = 256;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						gint occupied_width = 0, y = 0;
 | 
					 | 
					 | 
					 | 
						gint occupied_width = 0, y = 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						for (guint i = 0; i < self->entries->len; i++) {
 | 
					 | 
					 | 
					 | 
						for (guint i = 0; i < self->entries->len; i++) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							const Entry *entry = &g_array_index(self->entries, Entry, i);
 | 
					 | 
					 | 
					 | 
							const Entry *entry = &g_array_index(self->entries, Entry, i);
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -144,28 +145,19 @@ fastiv_browser_draw(GtkWidget *widget, cairo_t *cr)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							int width = cairo_image_surface_get_width(entry->thumbnail);
 | 
					 | 
					 | 
					 | 
							int width = cairo_image_surface_get_width(entry->thumbnail);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							int height = cairo_image_surface_get_height(entry->thumbnail);
 | 
					 | 
					 | 
					 | 
							int height = cairo_image_surface_get_height(entry->thumbnail);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							double scale = row_height / height;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (width * scale > 2 * row_height)
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								scale = 2 * row_height / width;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							int projected_width = round(scale * width);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							int projected_height = round(scale * height);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (occupied_width != 0 &&
 | 
					 | 
					 | 
					 | 
							if (occupied_width != 0 &&
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								occupied_width + projected_width > allocation.width) {
 | 
					 | 
					 | 
					 | 
								occupied_width + width > allocation.width) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								occupied_width = 0;
 | 
					 | 
					 | 
					 | 
								occupied_width = 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								y += row_height;
 | 
					 | 
					 | 
					 | 
								y += g_row_height;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							}
 | 
					 | 
					 | 
					 | 
							}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							cairo_save(cr);
 | 
					 | 
					 | 
					 | 
							cairo_save(cr);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							cairo_translate(cr, occupied_width, y + row_height - projected_height);
 | 
					 | 
					 | 
					 | 
							cairo_translate(cr, occupied_width, y + g_row_height - height);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							cairo_scale(cr, scale, scale);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							cairo_set_source_surface(cr, entry->thumbnail, 0, 0);
 | 
					 | 
					 | 
					 | 
							cairo_set_source_surface(cr, entry->thumbnail, 0, 0);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							cairo_paint(cr);
 | 
					 | 
					 | 
					 | 
							cairo_paint(cr);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							cairo_restore(cr);
 | 
					 | 
					 | 
					 | 
							cairo_restore(cr);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							occupied_width += projected_width;
 | 
					 | 
					 | 
					 | 
							occupied_width += width;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						}
 | 
					 | 
					 | 
					 | 
						}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						return TRUE;
 | 
					 | 
					 | 
					 | 
						return TRUE;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -203,6 +195,64 @@ fastiv_browser_init(FastivBrowser *self)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						self->selected = -1;
 | 
					 | 
					 | 
					 | 
						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
 | 
					 | 
					 | 
					 | 
					void
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					fastiv_browser_load(FastivBrowser *self, const char *path)
 | 
					 | 
					 | 
					 | 
					fastiv_browser_load(FastivBrowser *self, const char *path)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{
 | 
					 | 
					 | 
					 | 
					{
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -221,7 +271,8 @@ fastiv_browser_load(FastivBrowser *self, const char *path)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							gchar *subpath = g_build_filename(path, filename, NULL);
 | 
					 | 
					 | 
					 | 
							gchar *subpath = g_build_filename(path, filename, NULL);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							g_array_append_val(self->entries,
 | 
					 | 
					 | 
					 | 
							g_array_append_val(self->entries,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								((Entry){
 | 
					 | 
					 | 
					 | 
								((Entry){
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									.thumbnail = fastiv_io_lookup_thumbnail(subpath),
 | 
					 | 
					 | 
					 | 
									.thumbnail =
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
										rescale_thumbnail(fastiv_io_lookup_thumbnail(subpath)),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									.filename = subpath,
 | 
					 | 
					 | 
					 | 
									.filename = subpath,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								}));
 | 
					 | 
					 | 
					 | 
								}));
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						}
 | 
					 | 
					 | 
					 | 
						}
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					 
 |