From f4352524926eda5e69631311d42139796f8edb8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Eric=20Janouch?= Date: Mon, 20 Dec 2021 11:08:36 +0100 Subject: [PATCH] Add a checkerboard toggle --- fastiv.c | 13 +++- fiv-view.c | 38 +++++++-- fiv-view.h | 1 + resources/checkerboard-symbolic.svg | 115 ++++++++++++++++++++++++++++ resources/resources.gresource.xml | 1 + 5 files changed, 160 insertions(+), 8 deletions(-) create mode 100644 resources/checkerboard-symbolic.svg diff --git a/fastiv.c b/fastiv.c index 4013a91..71960dc 100644 --- a/fastiv.c +++ b/fastiv.c @@ -56,7 +56,6 @@ exit_fatal(const gchar *format, ...) // TODO(p): See if it's possible to give separators room to shrink // by some minor amount of pixels, margin-wise. -// TODO(p): Add a toggle for a checkerboard background. // TODO(p): Implement commented-out actions. #define B make_toolbar_button #define T make_toolbar_toggle @@ -84,6 +83,7 @@ exit_fatal(const gchar *format, ...) /* XX(PIN, B("view-pin-symbolic", "Keep view configuration")) */ \ /* Or perhaps "blur-symbolic", also in the extended set. */ \ XX(SMOOTH, T("blend-tool-symbolic", "Smooth scaling")) \ + XX(CHECKERBOARD, T("checkerboard-symbolic", "Highlight transparency")) \ /* XX(COLOR, B("preferences-color-symbolic", "Color management")) */ \ XX(SAVE, B("document-save-as-symbolic", "Save as...")) \ XX(PRINT, B("document-print-symbolic", "Print...")) \ @@ -759,6 +759,7 @@ on_view_actions_changed(void) gtk_widget_set_sensitive(g.toolbar[TOOLBAR_FIT], has_image); gtk_widget_set_sensitive(g.toolbar[TOOLBAR_SMOOTH], has_image); + gtk_widget_set_sensitive(g.toolbar[TOOLBAR_CHECKERBOARD], has_image); gtk_widget_set_sensitive(g.toolbar[TOOLBAR_SAVE], has_image); gtk_widget_set_sensitive(g.toolbar[TOOLBAR_PRINT], has_image); @@ -902,6 +903,7 @@ make_view_toolbar(void) toolbar_command(TOOLBAR_ONE, FIV_VIEW_COMMAND_ZOOM_1); toolbar_toggler(TOOLBAR_FIT, "scale-to-fit"); toolbar_toggler(TOOLBAR_SMOOTH, "filter"); + toolbar_toggler(TOOLBAR_CHECKERBOARD, "checkerboard"); toolbar_command(TOOLBAR_PRINT, FIV_VIEW_COMMAND_PRINT); toolbar_command(TOOLBAR_SAVE, FIV_VIEW_COMMAND_SAVE_PAGE); toolbar_command(TOOLBAR_LEFT, FIV_VIEW_COMMAND_ROTATE_LEFT); @@ -917,11 +919,14 @@ make_view_toolbar(void) G_CALLBACK(on_notify_view_boolean), g.toolbar[TOOLBAR_FIT]); g_signal_connect(g.view, "notify::filter", G_CALLBACK(on_notify_view_boolean), g.toolbar[TOOLBAR_SMOOTH]); + g_signal_connect(g.view, "notify::checkerboard", + G_CALLBACK(on_notify_view_boolean), g.toolbar[TOOLBAR_CHECKERBOARD]); g_object_notify(G_OBJECT(g.view), "scale"); g_object_notify(G_OBJECT(g.view), "playing"); g_object_notify(G_OBJECT(g.view), "scale-to-fit"); g_object_notify(G_OBJECT(g.view), "filter"); + g_object_notify(G_OBJECT(g.view), "checkerboard"); GCallback callback = G_CALLBACK(on_view_actions_changed); g_signal_connect(g.view, "notify::has-image", callback, NULL); @@ -995,8 +1000,10 @@ main(int argc, char *argv[]) fiv-browser { padding: 5px; } \ fiv-browser.item { \ color: mix(#000, @content_view_bg, 0.625); margin: 8px; \ - border: 2px solid #fff; background: @theme_bg_color; \ - background-image: \ + border: 2px solid #fff; \ + } \ + fiv-browser.item, fiv-view.checkerboard { \ + background: @theme_bg_color; background-image: \ linear-gradient(45deg, @fiv-tile 26%, transparent 26%), \ linear-gradient(-45deg, @fiv-tile 26%, transparent 26%), \ linear-gradient(45deg, transparent 74%, @fiv-tile 74%), \ diff --git a/fiv-view.c b/fiv-view.c index f67a464..893c327 100644 --- a/fiv-view.c +++ b/fiv-view.c @@ -38,6 +38,7 @@ struct _FivView { cairo_surface_t *frame; ///< Current frame within page, weak FivIoOrientation orientation; ///< Current page orientation bool filter; ///< Smooth scaling toggle + bool checkerboard; ///< Show checkerboard background bool scale_to_fit; ///< Image no larger than the allocation double scale; ///< Scaling factor @@ -88,6 +89,7 @@ enum { PROP_SCALE = 1, PROP_SCALE_TO_FIT, PROP_FILTER, + PROP_CHECKERBOARD, PROP_PLAYING, PROP_HAS_IMAGE, PROP_CAN_ANIMATE, @@ -122,6 +124,9 @@ fiv_view_get_property( case PROP_FILTER: g_value_set_boolean(value, self->filter); break; + case PROP_CHECKERBOARD: + g_value_set_boolean(value, self->checkerboard); + break; case PROP_PLAYING: g_value_set_boolean(value, !!self->frame_update_connection); break; @@ -158,6 +163,10 @@ fiv_view_set_property( if (self->filter != g_value_get_boolean(value)) fiv_view_command(self, FIV_VIEW_COMMAND_TOGGLE_FILTER); break; + case PROP_CHECKERBOARD: + if (self->checkerboard != g_value_get_boolean(value)) + fiv_view_command(self, FIV_VIEW_COMMAND_TOGGLE_CHECKERBOARD); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); } @@ -356,8 +365,8 @@ fiv_view_draw(GtkWidget *widget, cairo_t *cr) // which makes the widget have no double buffering or default background. GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); - gtk_render_background(gtk_widget_get_style_context(widget), cr, 0, 0, - allocation.width, allocation.height); + GtkStyleContext *style = gtk_widget_get_style_context(widget); + gtk_render_background(style, cr, 0, 0, allocation.width, allocation.height); FivView *self = FIV_VIEW(widget); if (!self->image || @@ -376,10 +385,17 @@ fiv_view_draw(GtkWidget *widget, cairo_t *cr) if (h < allocation.height) y = round((allocation.height - h) / 2.); - // FIXME: Recording surfaces do not work well with CAIRO_SURFACE_TYPE_XLIB, - // we always get a shitty pixmap, where transparency contains junk. cairo_matrix_t matrix = get_orientation_matrix(self->orientation, sw, sh); cairo_translate(cr, x, y); + if (self->checkerboard) { + gtk_style_context_save(style); + gtk_style_context_add_class(style, "checkerboard"); + gtk_render_background(style, cr, 0, 0, w, h); + gtk_style_context_restore(style); + } + + // FIXME: Recording surfaces do not work well with CAIRO_SURFACE_TYPE_XLIB, + // we always get a shitty pixmap, where transparency contains junk. if (cairo_surface_get_type(self->frame) == CAIRO_SURFACE_TYPE_RECORDING) { cairo_surface_t *image = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); @@ -804,6 +820,8 @@ fiv_view_key_press_event(GtkWidget *widget, GdkEventKey *event) return command(self, FIV_VIEW_COMMAND_TOGGLE_SCALE_TO_FIT); case GDK_KEY_i: return command(self, FIV_VIEW_COMMAND_TOGGLE_FILTER); + case GDK_KEY_t: + return command(self, FIV_VIEW_COMMAND_TOGGLE_CHECKERBOARD); case GDK_KEY_less: return command(self, FIV_VIEW_COMMAND_ROTATE_LEFT); @@ -844,6 +862,9 @@ fiv_view_class_init(FivViewClass *klass) view_properties[PROP_FILTER] = g_param_spec_boolean( "filter", "Use filtering", "Scale images smoothly", TRUE, G_PARAM_READWRITE); + view_properties[PROP_CHECKERBOARD] = g_param_spec_boolean( + "checkerboard", "Show checkerboard", "Highlight transparent background", + TRUE, G_PARAM_READWRITE); view_properties[PROP_PLAYING] = g_param_spec_boolean( "playing", "Playing animation", "An animation is running", FALSE, G_PARAM_READABLE); @@ -885,6 +906,7 @@ fiv_view_init(FivView *self) gtk_widget_set_can_focus(GTK_WIDGET(self), TRUE); self->filter = true; + self->checkerboard = false; self->scale = 1.0; } @@ -975,7 +997,13 @@ fiv_view_command(FivView *self, FivViewCommand command) break; case FIV_VIEW_COMMAND_TOGGLE_FILTER: self->filter = !self->filter; - g_object_notify_by_pspec(G_OBJECT(self), view_properties[PROP_FILTER]); + g_object_notify_by_pspec( + G_OBJECT(self), view_properties[PROP_FILTER]); + gtk_widget_queue_draw(widget); + break; case FIV_VIEW_COMMAND_TOGGLE_CHECKERBOARD: + self->checkerboard = !self->checkerboard; + g_object_notify_by_pspec( + G_OBJECT(self), view_properties[PROP_CHECKERBOARD]); gtk_widget_queue_draw(widget); break; case FIV_VIEW_COMMAND_PRINT: print(self); diff --git a/fiv-view.h b/fiv-view.h index 88c8445..c8b3a28 100644 --- a/fiv-view.h +++ b/fiv-view.h @@ -42,6 +42,7 @@ typedef enum _FivViewCommand { FIV_VIEW_COMMAND_TOGGLE_PLAYBACK, FIV_VIEW_COMMAND_TOGGLE_FILTER, + FIV_VIEW_COMMAND_TOGGLE_CHECKERBOARD, FIV_VIEW_COMMAND_PRINT, FIV_VIEW_COMMAND_SAVE_PAGE, diff --git a/resources/checkerboard-symbolic.svg b/resources/checkerboard-symbolic.svg new file mode 100644 index 0000000..b22ee66 --- /dev/null +++ b/resources/checkerboard-symbolic.svg @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/resources.gresource.xml b/resources/resources.gresource.xml index ab85308..1a99827 100644 --- a/resources/resources.gresource.xml +++ b/resources/resources.gresource.xml @@ -4,5 +4,6 @@ circle-filled-symbolic.svg funnel-symbolic.svg blend-tool-symbolic.svg + checkerboard-symbolic.svg