forked from AuroraMiddleware/gtk
image: Add gtk_image_set_keep_aspect_ratio()
If set, the image will draw its contents while keeping their aspect ratio. That means empty areas show up on the top/bottom or left/right. Also move the special-case snapshotting code for icons to GtkIconHelper. That's where it belongs.
This commit is contained in:
parent
0a08c03885
commit
c6541853ab
@ -1505,6 +1505,8 @@ gtk_image_set_pixel_size
|
|||||||
gtk_image_get_pixel_size
|
gtk_image_get_pixel_size
|
||||||
gtk_image_set_icon_size
|
gtk_image_set_icon_size
|
||||||
gtk_image_get_icon_size
|
gtk_image_get_icon_size
|
||||||
|
gtk_image_set_keep_aspect_ratio
|
||||||
|
gtk_image_get_keep_aspect_ratio
|
||||||
<SUBSECTION Standard>
|
<SUBSECTION Standard>
|
||||||
GTK_IMAGE
|
GTK_IMAGE
|
||||||
GTK_IS_IMAGE
|
GTK_IS_IMAGE
|
||||||
|
@ -249,11 +249,41 @@ gtk_icon_helper_paintable_snapshot (GdkPaintable *paintable,
|
|||||||
if (self->paintable == NULL)
|
if (self->paintable == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gtk_css_style_snapshot_icon_paintable (style,
|
switch (gtk_image_definition_get_storage_type (self->def))
|
||||||
snapshot,
|
{
|
||||||
self->paintable,
|
case GTK_IMAGE_ICON_NAME:
|
||||||
width, height,
|
case GTK_IMAGE_GICON:
|
||||||
self->texture_is_symbolic);
|
{
|
||||||
|
double x, y, w, h;
|
||||||
|
|
||||||
|
/* Never scale up icons. */
|
||||||
|
w = gdk_paintable_get_intrinsic_width (self->paintable);
|
||||||
|
h = gdk_paintable_get_intrinsic_height (self->paintable);
|
||||||
|
w = MIN (w, width);
|
||||||
|
h = MIN (h, height);
|
||||||
|
x = (width - w) / 2;
|
||||||
|
y = (height - h) / 2;
|
||||||
|
gtk_snapshot_offset (snapshot, x, y);
|
||||||
|
gtk_css_style_snapshot_icon_paintable (style,
|
||||||
|
snapshot,
|
||||||
|
self->paintable,
|
||||||
|
w, h,
|
||||||
|
self->texture_is_symbolic);
|
||||||
|
gtk_snapshot_offset (snapshot, -x, -y);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_IMAGE_TEXTURE:
|
||||||
|
case GTK_IMAGE_PAINTABLE:
|
||||||
|
case GTK_IMAGE_EMPTY:
|
||||||
|
default:
|
||||||
|
gtk_css_style_snapshot_icon_paintable (style,
|
||||||
|
snapshot,
|
||||||
|
self->paintable,
|
||||||
|
width, height,
|
||||||
|
self->texture_is_symbolic);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GdkPaintable *
|
static GdkPaintable *
|
||||||
|
@ -86,6 +86,8 @@ struct _GtkImagePrivate
|
|||||||
|
|
||||||
gchar *filename; /* Only used with GTK_IMAGE_SURFACE */
|
gchar *filename; /* Only used with GTK_IMAGE_SURFACE */
|
||||||
gchar *resource_path; /* Only used with GTK_IMAGE_SURFACE */
|
gchar *resource_path; /* Only used with GTK_IMAGE_SURFACE */
|
||||||
|
|
||||||
|
guint keep_aspect_ratio : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -129,6 +131,7 @@ enum
|
|||||||
PROP_GICON,
|
PROP_GICON,
|
||||||
PROP_RESOURCE,
|
PROP_RESOURCE,
|
||||||
PROP_USE_FALLBACK,
|
PROP_USE_FALLBACK,
|
||||||
|
PROP_KEEP_ASPECT_RATIO,
|
||||||
NUM_PROPERTIES
|
NUM_PROPERTIES
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -261,6 +264,19 @@ gtk_image_class_init (GtkImageClass *class)
|
|||||||
FALSE,
|
FALSE,
|
||||||
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GtkImage:keep-aspect-ratio:
|
||||||
|
*
|
||||||
|
* Whether the GtkImage will render its contents trying to preserve the aspect
|
||||||
|
* ratio of the contents.
|
||||||
|
*/
|
||||||
|
image_props[PROP_KEEP_ASPECT_RATIO] =
|
||||||
|
g_param_spec_boolean ("keep-aspect-ratio",
|
||||||
|
P_("Keep aspect ratio"),
|
||||||
|
P_("Render contents respecting the aspect ratio"),
|
||||||
|
TRUE,
|
||||||
|
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
|
||||||
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, image_props);
|
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, image_props);
|
||||||
|
|
||||||
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_IMAGE_ACCESSIBLE);
|
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_IMAGE_ACCESSIBLE);
|
||||||
@ -277,6 +293,7 @@ gtk_image_init (GtkImage *image)
|
|||||||
gtk_widget_set_has_window (GTK_WIDGET (image), FALSE);
|
gtk_widget_set_has_window (GTK_WIDGET (image), FALSE);
|
||||||
|
|
||||||
priv->icon_helper = gtk_icon_helper_new (widget_node, GTK_WIDGET (image));
|
priv->icon_helper = gtk_icon_helper_new (widget_node, GTK_WIDGET (image));
|
||||||
|
priv->keep_aspect_ratio = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -336,6 +353,10 @@ gtk_image_set_property (GObject *object,
|
|||||||
g_object_notify_by_pspec (object, pspec);
|
g_object_notify_by_pspec (object, pspec);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_KEEP_ASPECT_RATIO:
|
||||||
|
gtk_image_set_keep_aspect_ratio (image, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -380,6 +401,9 @@ gtk_image_get_property (GObject *object,
|
|||||||
case PROP_USE_FALLBACK:
|
case PROP_USE_FALLBACK:
|
||||||
g_value_set_boolean (value, _gtk_icon_helper_get_use_fallback (priv->icon_helper));
|
g_value_set_boolean (value, _gtk_icon_helper_get_use_fallback (priv->icon_helper));
|
||||||
break;
|
break;
|
||||||
|
case PROP_KEEP_ASPECT_RATIO:
|
||||||
|
g_value_set_boolean (value, priv->keep_aspect_ratio);
|
||||||
|
break;
|
||||||
case PROP_STORAGE_TYPE:
|
case PROP_STORAGE_TYPE:
|
||||||
g_value_set_enum (value, _gtk_icon_helper_get_storage_type (priv->icon_helper));
|
g_value_set_enum (value, _gtk_icon_helper_get_storage_type (priv->icon_helper));
|
||||||
break;
|
break;
|
||||||
@ -1203,27 +1227,40 @@ gtk_image_snapshot (GtkWidget *widget,
|
|||||||
{
|
{
|
||||||
GtkImage *image = GTK_IMAGE (widget);
|
GtkImage *image = GTK_IMAGE (widget);
|
||||||
GtkImagePrivate *priv = gtk_image_get_instance_private (image);
|
GtkImagePrivate *priv = gtk_image_get_instance_private (image);
|
||||||
int x, y, width, height;
|
double ratio;
|
||||||
gint w, h, baseline;
|
int x, y, width, height, baseline;
|
||||||
|
double w, h;
|
||||||
|
|
||||||
width = gtk_widget_get_width (widget);
|
width = gtk_widget_get_width (widget);
|
||||||
height = gtk_widget_get_height (widget);
|
height = gtk_widget_get_height (widget);
|
||||||
|
ratio = gdk_paintable_get_intrinsic_aspect_ratio (GDK_PAINTABLE (priv->icon_helper));
|
||||||
|
|
||||||
if (_gtk_icon_helper_get_storage_type (priv->icon_helper) == GTK_IMAGE_PAINTABLE)
|
if (!priv->keep_aspect_ratio || ratio == 0)
|
||||||
{
|
{
|
||||||
gdk_paintable_snapshot (GDK_PAINTABLE (priv->icon_helper), snapshot, width, height);
|
gdk_paintable_snapshot (GDK_PAINTABLE (priv->icon_helper), snapshot, width, height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_gtk_icon_helper_get_size (priv->icon_helper, &w, &h);
|
double image_ratio = (double) width / height;
|
||||||
x = (width - w) / 2;
|
|
||||||
|
if (ratio > image_ratio)
|
||||||
|
{
|
||||||
|
w = width;
|
||||||
|
h = width / ratio;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
w = height * ratio;
|
||||||
|
h = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = (width - ceil (w)) / 2;
|
||||||
|
|
||||||
baseline = gtk_widget_get_allocated_baseline (widget);
|
baseline = gtk_widget_get_allocated_baseline (widget);
|
||||||
|
|
||||||
if (baseline == -1)
|
if (baseline == -1)
|
||||||
y = floor(height - h) / 2;
|
y = floor(height - ceil (h)) / 2;
|
||||||
else
|
else
|
||||||
y = CLAMP (baseline - h * gtk_image_get_baseline_align (image), 0, height - h);
|
y = CLAMP (baseline - h * gtk_image_get_baseline_align (image), 0, height - ceil (h));
|
||||||
|
|
||||||
gtk_snapshot_offset (snapshot, x, y);
|
gtk_snapshot_offset (snapshot, x, y);
|
||||||
gdk_paintable_snapshot (GDK_PAINTABLE (priv->icon_helper), snapshot, w, h);
|
gdk_paintable_snapshot (GDK_PAINTABLE (priv->icon_helper), snapshot, w, h);
|
||||||
@ -1463,6 +1500,51 @@ gtk_image_get_icon_size (GtkImage *image)
|
|||||||
return priv->icon_size;
|
return priv->icon_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_image_set_keep_aspect_ratio:
|
||||||
|
* @image: a #GtkImage
|
||||||
|
* @keep_aspect_ratio: whether to keep aspect ratio
|
||||||
|
*
|
||||||
|
* If set to %TRUE, the @image will render its contents according to
|
||||||
|
* their aspect ratio. That means that empty space may show up at the
|
||||||
|
* top/bottom or left/right of @image.
|
||||||
|
*
|
||||||
|
* If set to %FALSE or if the contents provide no aspect ratio, the
|
||||||
|
* contents will be stretched over the image's whole area.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gtk_image_set_keep_aspect_ratio (GtkImage *image,
|
||||||
|
gboolean keep_aspect_ratio)
|
||||||
|
{
|
||||||
|
GtkImagePrivate *priv = gtk_image_get_instance_private (image);
|
||||||
|
|
||||||
|
g_return_if_fail (GTK_IS_IMAGE (image));
|
||||||
|
|
||||||
|
if (priv->keep_aspect_ratio == keep_aspect_ratio)
|
||||||
|
return;
|
||||||
|
|
||||||
|
priv->keep_aspect_ratio = keep_aspect_ratio;
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_KEEP_ASPECT_RATIO]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_image_get_keep_aspect_ratio:
|
||||||
|
* @image: a #GtkImage
|
||||||
|
*
|
||||||
|
* Gets the value set via gtk_image_set_keep_aspect_ratio().
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the image tries to keep the contents' aspect ratio
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
gtk_image_get_keep_aspect_ratio (GtkImage *image)
|
||||||
|
{
|
||||||
|
GtkImagePrivate *priv = gtk_image_get_instance_private (image);
|
||||||
|
|
||||||
|
g_return_val_if_fail (GTK_IS_IMAGE (image), TRUE);
|
||||||
|
|
||||||
|
return priv->keep_aspect_ratio;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gtk_image_get_image_size (GtkImage *image,
|
gtk_image_get_image_size (GtkImage *image,
|
||||||
int *width,
|
int *width,
|
||||||
|
@ -148,6 +148,9 @@ void gtk_image_set_pixel_size (GtkImage *image,
|
|||||||
GDK_AVAILABLE_IN_ALL
|
GDK_AVAILABLE_IN_ALL
|
||||||
void gtk_image_set_icon_size (GtkImage *image,
|
void gtk_image_set_icon_size (GtkImage *image,
|
||||||
GtkIconSize icon_size);
|
GtkIconSize icon_size);
|
||||||
|
GDK_AVAILABLE_IN_ALL
|
||||||
|
void gtk_image_set_keep_aspect_ratio (GtkImage *image,
|
||||||
|
gboolean keep_aspect_ratio);
|
||||||
|
|
||||||
GDK_AVAILABLE_IN_ALL
|
GDK_AVAILABLE_IN_ALL
|
||||||
GtkImageType gtk_image_get_storage_type (GtkImage *image);
|
GtkImageType gtk_image_get_storage_type (GtkImage *image);
|
||||||
@ -165,6 +168,8 @@ GDK_AVAILABLE_IN_ALL
|
|||||||
gint gtk_image_get_pixel_size (GtkImage *image);
|
gint gtk_image_get_pixel_size (GtkImage *image);
|
||||||
GDK_AVAILABLE_IN_ALL
|
GDK_AVAILABLE_IN_ALL
|
||||||
GtkIconSize gtk_image_get_icon_size (GtkImage *image);
|
GtkIconSize gtk_image_get_icon_size (GtkImage *image);
|
||||||
|
GDK_AVAILABLE_IN_ALL
|
||||||
|
gboolean gtk_image_get_keep_aspect_ratio (GtkImage *image);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user