From 88d9244b988146281fc041202f5efcfb2302e86f Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 13 Mar 2023 08:11:29 +0100 Subject: [PATCH 1/3] gtk4-demo: Fix rotation handling in image scaling We weren't sizing the widget correctly in rotated cases. --- demos/gtk-demo/demo3widget.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/demos/gtk-demo/demo3widget.c b/demos/gtk-demo/demo3widget.c index 756cb7565d..6fc935cffd 100644 --- a/demos/gtk-demo/demo3widget.c +++ b/demos/gtk-demo/demo3widget.c @@ -67,15 +67,13 @@ demo3_widget_snapshot (GtkWidget *widget, if (G_APPROX_VALUE (self->angle, 90.f, FLT_EPSILON) || G_APPROX_VALUE (self->angle, 270.f, FLT_EPSILON)) { - double s; - - s = w2; + double s = w2; w2 = h2; h2 = s; } - x = MAX (0, (width - ceil (w2)) / 2); - y = MAX (0, (height - ceil (h2)) / 2); + x = (width - ceil (w2)) / 2; + y = (height - ceil (h2)) / 2; gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (0, 0, width, height)); gtk_snapshot_save (snapshot); @@ -102,14 +100,26 @@ demo3_widget_measure (GtkWidget *widget, int *natural_baseline) { Demo3Widget *self = DEMO3_WIDGET (widget); + int width, height; int size; - if (orientation == GTK_ORIENTATION_HORIZONTAL) - size = gdk_texture_get_width (self->texture); - else - size = gdk_texture_get_height (self->texture); + width = gdk_texture_get_width (self->texture); + height = gdk_texture_get_height (self->texture); - *minimum = *natural = self->scale * size; + if (G_APPROX_VALUE (self->angle, 90.f, FLT_EPSILON) || + G_APPROX_VALUE (self->angle, 270.f, FLT_EPSILON)) + { + int s = width; + width = height; + height = s; + } + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + size = width; + else + size = height; + + *minimum = *natural = (int) ceil (self->scale * size); } static void From 517b4d584ced71a7c6ba0f7af8f4c3bdbeb7ee8d Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 13 Mar 2023 08:21:10 +0100 Subject: [PATCH 2/3] gtk4-demo: Scale logarithmically in image scaling --- demos/gtk-demo/demo3widget.c | 2 +- demos/gtk-demo/menu.c | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/demos/gtk-demo/demo3widget.c b/demos/gtk-demo/demo3widget.c index 6fc935cffd..95a1479e8f 100644 --- a/demos/gtk-demo/demo3widget.c +++ b/demos/gtk-demo/demo3widget.c @@ -277,7 +277,7 @@ demo3_widget_class_init (Demo3WidgetClass *class) g_object_class_install_property (object_class, PROP_SCALE, g_param_spec_float ("scale", NULL, NULL, - 0.0, 10.0, 1.0, + 0.0, 1024.0, 1.0, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_ANGLE, diff --git a/demos/gtk-demo/menu.c b/demos/gtk-demo/menu.c index 768e32a5be..2b057b25c1 100644 --- a/demos/gtk-demo/menu.c +++ b/demos/gtk-demo/menu.c @@ -84,6 +84,16 @@ rotate (GtkWidget *button, g_object_set (demo, "angle", angle, NULL); } +static void +scale_changed (GtkRange *range, + GtkWidget *widget) +{ + float scale; + + scale = (float) pow (2., gtk_range_get_value (range)); + g_object_set (widget, "scale", scale, NULL); +} + GtkWidget * do_menu (GtkWidget *do_widget) { @@ -129,7 +139,7 @@ do_menu (GtkWidget *do_widget) g_signal_connect (button, "clicked", G_CALLBACK (rotate), widget); gtk_box_append (GTK_BOX (box2), button); - scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0.01, 10.0, 0.1); + scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, -10, 10.0, 0.1); gtk_widget_set_tooltip_text (scale, "Zoom"); gtk_range_set_value (GTK_RANGE (scale), 1.0); gtk_widget_set_hexpand (scale, TRUE); @@ -140,10 +150,8 @@ do_menu (GtkWidget *do_widget) gtk_box_append (GTK_BOX (box2), dropdown); g_object_bind_property (dropdown, "selected", widget, "filter", G_BINDING_DEFAULT); - - g_object_bind_property (gtk_range_get_adjustment (GTK_RANGE (scale)), "value", - widget, "scale", - G_BINDING_BIDIRECTIONAL); + + g_signal_connect (scale, "value-changed", G_CALLBACK (scale_changed), widget); } if (!gtk_widget_get_visible (window)) From 7bdb1464739f63cf1141c9014bc1ba42556724b8 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 13 Mar 2023 08:38:58 +0100 Subject: [PATCH 3/3] docs: Details about texture scale nodes Add some more details about filtering, to clarify things a bit. --- gsk/gskrendernodeimpl.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c index 8e0b0a8415..6dcad3002f 100644 --- a/gsk/gskrendernodeimpl.c +++ b/gsk/gskrendernodeimpl.c @@ -1573,6 +1573,10 @@ gsk_texture_node_get_texture (const GskRenderNode *node) * Creates a `GskRenderNode` that will render the given * @texture into the area given by @bounds. * + * Note that GSK applies linear filtering when textures are + * scaled and transformed. See [class@Gsk.TextureScaleNode] + * for a way to influence filtering. + * * Returns: (transfer full) (type GskTextureNode): A new `GskRenderNode` */ GskRenderNode * @@ -1754,7 +1758,11 @@ gsk_texture_scale_node_get_filter (const GskRenderNode *node) * @filter: how to scale the texture * * Creates a node that scales the texture to the size given by the - * bounds and the filter and then places it at the bounds' position. + * bounds using the filter and then places it at the bounds' position. + * + * Note that further scaling and other transformations which are + * applied to the node will apply linear filtering to the resulting + * texture, as usual. * * This node is intended for tight control over scaling applied * to a texture, such as in image editors and requires the