diff options
| author | Přemysl Eric Janouch <p@janouch.name> | 2021-12-20 11:08:36 +0100 | 
|---|---|---|
| committer | Přemysl Eric Janouch <p@janouch.name> | 2021-12-20 11:53:17 +0100 | 
| commit | f4352524926eda5e69631311d42139796f8edb8d (patch) | |
| tree | 09a4798c009cfe2b3a4d22e0b709c462ebb099b4 | |
| parent | dfa1fed18b3e55b8244c0c35d2cb511f1ad36c1a (diff) | |
| download | fiv-f4352524926eda5e69631311d42139796f8edb8d.tar.gz fiv-f4352524926eda5e69631311d42139796f8edb8d.tar.xz fiv-f4352524926eda5e69631311d42139796f8edb8d.zip  | |
Add a checkerboard toggle
| -rw-r--r-- | fastiv.c | 13 | ||||
| -rw-r--r-- | fiv-view.c | 38 | ||||
| -rw-r--r-- | fiv-view.h | 1 | ||||
| -rw-r--r-- | resources/checkerboard-symbolic.svg | 115 | ||||
| -rw-r--r-- | resources/resources.gresource.xml | 1 | 
5 files changed, 160 insertions, 8 deletions
@@ -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%), \ @@ -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); @@ -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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +    <filter id="a" height="100%" width="100%" x="0%" y="0%"> +        <feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/> +    </filter> +    <mask id="b"> +        <g filter="url(#a)"> +            <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.3"/> +        </g> +    </mask> +    <clipPath id="c"> +        <path d="m 0 0 h 1600 v 1200 h -1600 z"/> +    </clipPath> +    <mask id="d"> +        <g filter="url(#a)"> +            <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/> +        </g> +    </mask> +    <clipPath id="e"> +        <path d="m 0 0 h 1600 v 1200 h -1600 z"/> +    </clipPath> +    <mask id="f"> +        <g filter="url(#a)"> +            <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/> +        </g> +    </mask> +    <clipPath id="g"> +        <path d="m 0 0 h 1600 v 1200 h -1600 z"/> +    </clipPath> +    <mask id="h"> +        <g filter="url(#a)"> +            <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/> +        </g> +    </mask> +    <clipPath id="i"> +        <path d="m 0 0 h 1600 v 1200 h -1600 z"/> +    </clipPath> +    <mask id="j"> +        <g filter="url(#a)"> +            <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/> +        </g> +    </mask> +    <clipPath id="k"> +        <path d="m 0 0 h 1600 v 1200 h -1600 z"/> +    </clipPath> +    <mask id="l"> +        <g filter="url(#a)"> +            <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/> +        </g> +    </mask> +    <clipPath id="m"> +        <path d="m 0 0 h 1600 v 1200 h -1600 z"/> +    </clipPath> +    <mask id="n"> +        <g filter="url(#a)"> +            <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/> +        </g> +    </mask> +    <clipPath id="o"> +        <path d="m 0 0 h 1600 v 1200 h -1600 z"/> +    </clipPath> +    <mask id="p"> +        <g filter="url(#a)"> +            <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.3"/> +        </g> +    </mask> +    <clipPath id="q"> +        <path d="m 0 0 h 1600 v 1200 h -1600 z"/> +    </clipPath> +    <mask id="r"> +        <g filter="url(#a)"> +            <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.5"/> +        </g> +    </mask> +    <clipPath id="s"> +        <path d="m 0 0 h 1600 v 1200 h -1600 z"/> +    </clipPath> +    <g clip-path="url(#c)" mask="url(#b)" transform="matrix(1 0 0 1 -256 -756)"> +        <path d="m 562.460938 212.058594 h 10.449218 c -1.183594 0.492187 -1.296875 2.460937 0 3 h -10.449218 z m 0 0" fill="#2e3436"/> +    </g> +    <g clip-path="url(#e)" mask="url(#d)" transform="matrix(1 0 0 1 -256 -756)"> +        <path d="m 16 748 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/> +    </g> +    <g clip-path="url(#g)" mask="url(#f)" transform="matrix(1 0 0 1 -256 -756)"> +        <path d="m 17 747 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/> +    </g> +    <g clip-path="url(#i)" mask="url(#h)" transform="matrix(1 0 0 1 -256 -756)"> +        <path d="m 18 750 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/> +    </g> +    <g clip-path="url(#k)" mask="url(#j)" transform="matrix(1 0 0 1 -256 -756)"> +        <path d="m 16 750 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/> +    </g> +    <g clip-path="url(#m)" mask="url(#l)" transform="matrix(1 0 0 1 -256 -756)"> +        <path d="m 17 751 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/> +    </g> +    <g clip-path="url(#o)" mask="url(#n)" transform="matrix(1 0 0 1 -256 -756)"> +        <path d="m 19 751 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/> +    </g> +    <g clip-path="url(#q)" mask="url(#p)" transform="matrix(1 0 0 1 -256 -756)"> +        <path d="m 136 776 v 7 h 7 v -7 z m 0 0" fill="#2e3436"/> +    </g> +    <g clip-path="url(#s)" mask="url(#r)" transform="matrix(1 0 0 1 -256 -756)"> +        <path d="m 219 758 h 3 v 12 h -3 z m 0 0" fill="#2e3436"/> +    </g> +    <g fill="#2e3436"> +        <path d="m 14 5 v -3 h -3 v 3 z m 0 0"/> +        <path d="m 11 8 v -3 h -3 v 3 z m 0 0"/> +        <path d="m 14 11 v -3 h -3 v 3 z m 0 0"/> +        <path d="m 11 14 v -3 h -3 v 3 z m 0 0"/> +        <path d="m 8 11 v -3 h -3 v 3 z m 0 0"/> +        <path d="m 5 14 v -3 h -3 v 3 z m 0 0"/> +        <path d="m 5 8 v -3 h -3 v 3 z m 0 0"/> +        <path d="m 8 5 v -3 h -3 v 3 z m 0 0"/> +    </g> +</svg> 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 @@  		<file preprocess="xml-stripblanks">circle-filled-symbolic.svg</file>  		<file preprocess="xml-stripblanks">funnel-symbolic.svg</file>  		<file preprocess="xml-stripblanks">blend-tool-symbolic.svg</file> +		<file preprocess="xml-stripblanks">checkerboard-symbolic.svg</file>  	</gresource>  </gresources>  | 
