summaryrefslogtreecommitdiff
path: root/gtk/gtkpicture.c
diff options
context:
space:
mode:
authorMarco Melorio <marco.melorio@protonmail.com>2022-07-15 18:18:26 +0200
committerMarco Melorio <marco.melorio@protonmail.com>2022-07-15 23:01:23 +0200
commitd8a73cbd03118e94bd75f5fa183a646fecb053ce (patch)
tree3a5766db3af7a9b714c2cb7a62d76af8cfe15213 /gtk/gtkpicture.c
parent7743f359720686b1183172a073fa210ba23faf15 (diff)
downloadgtk+-d8a73cbd03118e94bd75f5fa183a646fecb053ce.tar.gz
picture: Add content-fit property
It allows to specify the resize mode of the paintable inside the GtkPicture allocation. This also deprecates the keep-aspect-ratio property. Fixes #5027.
Diffstat (limited to 'gtk/gtkpicture.c')
-rw-r--r--gtk/gtkpicture.c152
1 files changed, 131 insertions, 21 deletions
diff --git a/gtk/gtkpicture.c b/gtk/gtkpicture.c
index 0712d1844f..eaabda7c74 100644
--- a/gtk/gtkpicture.c
+++ b/gtk/gtkpicture.c
@@ -27,6 +27,7 @@
#include "gtkintl.h"
#include "gtkprivate.h"
#include "gtksnapshot.h"
+#include "gtktypebuiltins.h"
#include "gtkwidgetprivate.h"
#include "gdkpixbufutilsprivate.h"
@@ -89,6 +90,7 @@ enum
PROP_ALTERNATIVE_TEXT,
PROP_KEEP_ASPECT_RATIO,
PROP_CAN_SHRINK,
+ PROP_CONTENT_FIT,
NUM_PROPERTIES
};
@@ -100,8 +102,8 @@ struct _GtkPicture
GFile *file;
char *alternative_text;
- guint keep_aspect_ratio : 1;
guint can_shrink : 1;
+ GtkContentFit content_fit;
};
struct _GtkPictureClass
@@ -129,23 +131,47 @@ gtk_picture_snapshot (GtkWidget *widget,
height = gtk_widget_get_height (widget);
ratio = gdk_paintable_get_intrinsic_aspect_ratio (self->paintable);
- if (!self->keep_aspect_ratio || ratio == 0)
+ if (self->content_fit == GTK_CONTENT_FIT_FILL || ratio == 0)
{
gdk_paintable_snapshot (self->paintable, snapshot, width, height);
}
else
{
double picture_ratio = (double) width / height;
+ int paintable_width = gdk_paintable_get_intrinsic_width (self->paintable);
+ int paintable_height = gdk_paintable_get_intrinsic_height (self->paintable);
- if (ratio > picture_ratio)
+ if (self->content_fit == GTK_CONTENT_FIT_SCALE_DOWN &&
+ width >= paintable_width && height >= paintable_height)
{
- w = width;
- h = width / ratio;
+ w = paintable_width;
+ h = paintable_height;
+ }
+ else if (ratio > picture_ratio)
+ {
+ if (self->content_fit == GTK_CONTENT_FIT_COVER)
+ {
+ w = height * ratio;
+ h = height;
+ }
+ else
+ {
+ w = width;
+ h = width / ratio;
+ }
}
else
{
- w = height * ratio;
- h = height;
+ if (self->content_fit == GTK_CONTENT_FIT_COVER)
+ {
+ w = width;
+ h = width / ratio;
+ }
+ else
+ {
+ w = height * ratio;
+ h = height;
+ }
}
x = (width - ceil (w)) / 2;
@@ -246,13 +272,19 @@ gtk_picture_set_property (GObject *object,
break;
case PROP_KEEP_ASPECT_RATIO:
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
gtk_picture_set_keep_aspect_ratio (self, g_value_get_boolean (value));
+ G_GNUC_END_IGNORE_DEPRECATIONS
break;
case PROP_CAN_SHRINK:
gtk_picture_set_can_shrink (self, g_value_get_boolean (value));
break;
+ case PROP_CONTENT_FIT:
+ gtk_picture_set_content_fit (self, g_value_get_enum (value));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -282,13 +314,19 @@ gtk_picture_get_property (GObject *object,
break;
case PROP_KEEP_ASPECT_RATIO:
- g_value_set_boolean (value, self->keep_aspect_ratio);
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ g_value_set_boolean (value, gtk_picture_get_keep_aspect_ratio (self));
+ G_GNUC_END_IGNORE_DEPRECATIONS
break;
case PROP_CAN_SHRINK:
g_value_set_boolean (value, self->can_shrink);
break;
+ case PROP_CONTENT_FIT:
+ g_value_set_enum (value, self->content_fit);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -394,11 +432,15 @@ gtk_picture_class_init (GtkPictureClass *class)
*
* Whether the GtkPicture will render its contents trying to preserve the aspect
* ratio.
+ *
+ * Deprecated: 4.8: Use [property@Gtk.Picture:content-fit] instead.
*/
properties[PROP_KEEP_ASPECT_RATIO] =
g_param_spec_boolean ("keep-aspect-ratio", NULL, NULL,
TRUE,
- GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+ GTK_PARAM_READWRITE |
+ G_PARAM_EXPLICIT_NOTIFY |
+ G_PARAM_DEPRECATED);
/**
* GtkPicture:can-shrink: (attributes org.gtk.Property.get=gtk_picture_get_can_shrink org.gtk.Property.set=gtk_picture_set_can_shrink)
@@ -410,6 +452,17 @@ gtk_picture_class_init (GtkPictureClass *class)
TRUE,
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+ /**
+ * GtkPicture:content-fit: (attributes org.gtk.Property.get=gtk_picture_get_content_fit org.gtk.Property.set=gtk_picture_set_content_fit)
+ *
+ * How the content should be resized to fit inside the `GtkPicture`.
+ */
+ properties[PROP_CONTENT_FIT] =
+ g_param_spec_enum ("content-fit", NULL, NULL,
+ GTK_TYPE_CONTENT_FIT,
+ GTK_CONTENT_FIT_CONTAIN,
+ GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
gtk_widget_class_set_css_name (widget_class, I_("picture"));
@@ -420,7 +473,7 @@ static void
gtk_picture_init (GtkPicture *self)
{
self->can_shrink = TRUE;
- self->keep_aspect_ratio = TRUE;
+ self->content_fit = GTK_CONTENT_FIT_CONTAIN;
}
/**
@@ -827,21 +880,20 @@ gtk_picture_get_paintable (GtkPicture *self)
*
* If set to %FALSE or if the contents provide no aspect ratio,
* the contents will be stretched over the picture's whole area.
+ *
+ * Deprecated: 4.8: Use [method@Gtk.Picture.set_content_fit] instead. If still
+ * used, this method will always set the [property@Gtk.Picture:content-fit]
+ * property to `GTK_CONTENT_FIT_CONTAIN` if @keep_aspect_ratio is true,
+ * otherwise it will set it to `GTK_CONTENT_FIT_FILL`.
*/
void
gtk_picture_set_keep_aspect_ratio (GtkPicture *self,
gboolean keep_aspect_ratio)
{
- g_return_if_fail (GTK_IS_PICTURE (self));
-
- if (self->keep_aspect_ratio == keep_aspect_ratio)
- return;
-
- self->keep_aspect_ratio = keep_aspect_ratio;
-
- gtk_widget_queue_draw (GTK_WIDGET (self));
-
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_KEEP_ASPECT_RATIO]);
+ if (keep_aspect_ratio)
+ gtk_picture_set_content_fit (self, GTK_CONTENT_FIT_CONTAIN);
+ else
+ gtk_picture_set_content_fit (self, GTK_CONTENT_FIT_FILL);
}
/**
@@ -851,13 +903,17 @@ gtk_picture_set_keep_aspect_ratio (GtkPicture *self,
* Returns whether the `GtkPicture` preserves its contents aspect ratio.
*
* Returns: %TRUE if the self tries to keep the contents' aspect ratio
+ *
+ * Deprecated: 4.8: Use [method@Gtk.Picture.get_content_fit] instead. This will
+ * now return `FALSE` only if [property@Gtk.Picture:content-fit] is
+ * `GTK_CONTENT_FIT_FILL`. Returns `TRUE` otherwise.
*/
gboolean
gtk_picture_get_keep_aspect_ratio (GtkPicture *self)
{
g_return_val_if_fail (GTK_IS_PICTURE (self), TRUE);
- return self->keep_aspect_ratio;
+ return self->content_fit != GTK_CONTENT_FIT_FILL;
}
/**
@@ -909,6 +965,60 @@ gtk_picture_get_can_shrink (GtkPicture *self)
}
/**
+ * gtk_picture_set_content_fit: (attributes org.gtk.Method.set_property=content-fit)
+ * @self: a `GtkPicture`
+ * @content_fit: the content fit mode
+ *
+ * Sets how the content should be resized to fit the `GtkPicture`.
+ *
+ * See [enum@Gtk.ContentFit] for details.
+ *
+ * If you use `GTK_CONTENT_FIT_COVER`, you may also want to set the
+ * [property@Gtk.Widget:overflow] to `GTK_OVERFLOW_HIDDEN`, otherwise the
+ * paintable will overflow the widget allocation if the aspect ratio of the
+ * paintable is different from the one of the `GtkPicture` allocation.
+ */
+void
+gtk_picture_set_content_fit (GtkPicture *self,
+ GtkContentFit content_fit)
+{
+ g_return_if_fail (GTK_IS_PICTURE (self));
+
+ if (self->content_fit == content_fit)
+ return;
+
+ gboolean notify_keep_aspect_ratio = (content_fit == GTK_CONTENT_FIT_FILL ||
+ self->content_fit == GTK_CONTENT_FIT_FILL);
+
+ self->content_fit = content_fit;
+
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CONTENT_FIT]);
+
+ if (notify_keep_aspect_ratio)
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_KEEP_ASPECT_RATIO]);
+}
+
+/**
+ * gtk_picture_get_content_fit: (attributes org.gtk.Method.get_property=content-fit)
+ * @self: a `GtkPicture`
+ *
+ * Returns the fit mode for the content of the `GtkPicture`.
+ *
+ * See [enum@Gtk.ContentFit] for details.
+ *
+ * Returns: the content fit mode
+ */
+GtkContentFit
+gtk_picture_get_content_fit (GtkPicture *self)
+{
+ g_return_val_if_fail (GTK_IS_PICTURE (self), FALSE);
+
+ return self->content_fit;
+}
+
+/**
* gtk_picture_set_alternative_text: (attributes org.gtk.Method.set_property=alternative-text)
* @self: a `GtkPicture`
* @alternative_text: (nullable): a textual description of the contents