Compare commits

...

3 Commits

Author SHA1 Message Date
ada67f044a
Optimize thumbnail rendering
Massive responsivity gains have been achieved here.

Rescaling performance doesn't seem to be particularly affected.
2021-12-20 04:40:35 +01:00
63955e881d
Add a convenience dark theme variant toggle 2021-12-20 03:55:53 +01:00
6130f527d4
Mark a dead end 2021-12-20 03:49:35 +01:00
3 changed files with 38 additions and 16 deletions

View File

@ -548,6 +548,15 @@ on_key_press(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event,
G_GNUC_UNUSED gpointer data) G_GNUC_UNUSED gpointer data)
{ {
switch (event->state & gtk_accelerator_get_default_mod_mask()) { switch (event->state & gtk_accelerator_get_default_mod_mask()) {
case GDK_MOD1_MASK | GDK_SHIFT_MASK:
if (event->keyval == GDK_KEY_D) {
GtkSettings *settings = gtk_settings_get_default();
const char *property = "gtk-application-prefer-dark-theme";
gboolean set = FALSE;
g_object_get(settings, property, &set, NULL);
g_object_set(settings, property, !set, NULL);
}
break;
case GDK_CONTROL_MASK: case GDK_CONTROL_MASK:
switch (event->keyval) { switch (event->keyval) {
case GDK_KEY_o: case GDK_KEY_o:
@ -837,12 +846,16 @@ toolbar_connect(int index, GCallback callback)
g_signal_connect_swapped(g.toolbar[index], "clicked", callback, NULL); g_signal_connect_swapped(g.toolbar[index], "clicked", callback, NULL);
} }
// TODO(p): The toolbar should not be visible in fullscreen, // TODO(p): The text and icons should be faded, unless the mouse cursor is
// or show up only when the cursor reaches the bottom of the screen. // on the toolbar. However, GtkEventBox is of no use, because either buttons
// Presumably, GtkOverlay could be used for this. Proximity-based? // steal our {enter,leave}-notify-events, or we steal all their input.
// Might want to make the toolbar normally translucent. // Not even connecting to these signals on children works, insensitive buttons
// TODO(p): The text and icons should be faded, unless the mouse cursor // will not trigger anything.
// is on the toolbar. // TODO(p): The toolbar should not be visible in fullscreen, or should show up
// only when the cursor reaches the top of the screen. Translucency sounds
// like a good mechanism here. Presumably, GtkOverlay could be used for this,
// but it faces the same problem as above--the input model sucks.
// TODO(p): Simply hide it in fullscreen and add a replacement context menu.
static GtkWidget * static GtkWidget *
make_view_toolbar(void) make_view_toolbar(void)
{ {
@ -1002,7 +1015,7 @@ main(int argc, char *argv[])
G_CALLBACK(on_button_press_view), NULL); G_CALLBACK(on_button_press_view), NULL);
gtk_container_add(GTK_CONTAINER(view_scroller), g.view); gtk_container_add(GTK_CONTAINER(view_scroller), g.view);
// Maybe our custom widgets should derive colours from the theme instead. // TODO(p): Base most colours on the theme, and make this configurable.
g_object_set(gtk_settings_get_default(), g_object_set(gtk_settings_get_default(),
"gtk-application-prefer-dark-theme", TRUE, NULL); "gtk-application-prefer-dark-theme", TRUE, NULL);

View File

@ -254,8 +254,12 @@ draw_row(FivBrowser *self, cairo_t *cr, const Row *row)
border.top + extents.height + border.bottom); border.top + extents.height + border.bottom);
} }
gtk_render_background( // Performance optimization--specifically targeting the checkerboard.
style, cr, border.left, border.top, extents.width, extents.height); if (cairo_image_surface_get_format(item->entry->thumbnail) !=
CAIRO_FORMAT_RGB24) {
gtk_render_background(style, cr, border.left, border.top,
extents.width, extents.height);
}
gtk_render_frame(style, cr, 0, 0, gtk_render_frame(style, cr, 0, 0,
border.left + extents.width + border.right, border.left + extents.width + border.right,
@ -306,8 +310,9 @@ rescale_thumbnail(cairo_surface_t *thumbnail, double row_height)
int projected_width = round(scale_x * width); int projected_width = round(scale_x * width);
int projected_height = round(scale_y * height); int projected_height = round(scale_y * height);
cairo_format_t cairo_format = cairo_image_surface_get_format(thumbnail);
cairo_surface_t *scaled = cairo_image_surface_create( cairo_surface_t *scaled = cairo_image_surface_create(
CAIRO_FORMAT_ARGB32, projected_width, projected_height); cairo_format, projected_width, projected_height);
// pixman can take gamma into account when scaling, unlike Cairo. // pixman can take gamma into account when scaling, unlike Cairo.
struct pixman_f_transform xform_floating; struct pixman_f_transform xform_floating;
@ -315,7 +320,8 @@ rescale_thumbnail(cairo_surface_t *thumbnail, double row_height)
// PIXMAN_a8r8g8b8_sRGB can be used for gamma-correct results, // PIXMAN_a8r8g8b8_sRGB can be used for gamma-correct results,
// but it's an incredibly slow transformation // but it's an incredibly slow transformation
pixman_format_code_t format = PIXMAN_a8r8g8b8; pixman_format_code_t format =
cairo_format == CAIRO_FORMAT_RGB24 ? PIXMAN_x8r8g8b8 : PIXMAN_a8r8g8b8;
pixman_image_t *src = pixman_image_create_bits(format, width, height, pixman_image_t *src = pixman_image_create_bits(format, width, height,
(uint32_t *) cairo_image_surface_get_data(thumbnail), (uint32_t *) cairo_image_surface_get_data(thumbnail),

View File

@ -2366,9 +2366,15 @@ read_spng_thumbnail(
} }
struct spng_ihdr ihdr = {}; struct spng_ihdr ihdr = {};
struct spng_trns trns = {};
spng_get_ihdr(ctx, &ihdr); spng_get_ihdr(ctx, &ihdr);
bool may_be_translucent = !spng_get_trns(ctx, &trns) ||
ihdr.color_type == SPNG_COLOR_TYPE_GRAYSCALE_ALPHA ||
ihdr.color_type == SPNG_COLOR_TYPE_TRUECOLOR_ALPHA;
cairo_surface_t *surface = cairo_image_surface_create( cairo_surface_t *surface = cairo_image_surface_create(
CAIRO_FORMAT_ARGB32, ihdr.width, ihdr.height); may_be_translucent ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24,
ihdr.width, ihdr.height);
cairo_status_t surface_status = cairo_surface_status(surface); cairo_status_t surface_status = cairo_surface_status(surface);
if (surface_status != CAIRO_STATUS_SUCCESS) { if (surface_status != CAIRO_STATUS_SUCCESS) {
@ -2396,10 +2402,7 @@ read_spng_thumbnail(
} }
// pixman can be mildly abused to do this operation, but it won't be faster. // pixman can be mildly abused to do this operation, but it won't be faster.
struct spng_trns trns = {}; if (may_be_translucent) {
if (ihdr.color_type == SPNG_COLOR_TYPE_GRAYSCALE_ALPHA ||
ihdr.color_type == SPNG_COLOR_TYPE_TRUECOLOR_ALPHA ||
!spng_get_trns(ctx, &trns)) {
for (size_t i = size / sizeof *data; i--; ) { for (size_t i = size / sizeof *data; i--; ) {
const uint8_t *unit = (const uint8_t *) &data[i]; const uint8_t *unit = (const uint8_t *) &data[i];
uint32_t a = unit[3], uint32_t a = unit[3],