aboutsummaryrefslogtreecommitdiff
path: root/fastiv-browser.c
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2021-11-03 14:15:05 +0100
committerPřemysl Eric Janouch <p@janouch.name>2021-11-03 14:15:34 +0100
commitcdb8d852a6e458ff9fe5f9e7f58aaa55f8ddb1cf (patch)
tree7a0055c8f4da60049d9c9d02ba7599b6c7139dca /fastiv-browser.c
parentdbc500ae9f715b57deef27046c37bd2655f482e2 (diff)
downloadfiv-cdb8d852a6e458ff9fe5f9e7f58aaa55f8ddb1cf.tar.gz
fiv-cdb8d852a6e458ff9fe5f9e7f58aaa55f8ddb1cf.tar.xz
fiv-cdb8d852a6e458ff9fe5f9e7f58aaa55f8ddb1cf.zip
Pre-scale loaded thumbnails, and only when needed
Diffstat (limited to 'fastiv-browser.c')
-rw-r--r--fastiv-browser.c121
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,
}));
}