gtkimage.c 56.9 KB
Newer Older
Cody Russell's avatar
Cody Russell committed
1
/* GTK - The GIMP Toolkit
Elliot Lee's avatar
Elliot Lee committed
2 3 4
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
6 7 8 9 10 11
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
Javier Jardón's avatar
Javier Jardón committed
15
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
Elliot Lee's avatar
Elliot Lee committed
16
 */
17 18

/*
19
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
20 21 22 23 24
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

25
#include "config.h"
26

27
#include <math.h>
28
#include <string.h>
29
#include <cairo-gobject.h>
30

Elliot Lee's avatar
Elliot Lee committed
31
#include "gtkcontainer.h"
32
#include "gtkcssstylepropertyprivate.h"
33
#include "gtkiconhelperprivate.h"
34
#include "gtkimageprivate.h"
35 36
#include "deprecated/gtkiconfactory.h"
#include "deprecated/gtkstock.h"
37
#include "gtkicontheme.h"
38
#include "gtksizerequest.h"
Havoc Pennington's avatar
Havoc Pennington committed
39
#include "gtkintl.h"
40
#include "gtkprivate.h"
41
#include "gtktypebuiltins.h"
42 43 44
#include "gtkcssshadowsvalueprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtkwidgetprivate.h"
Matthias Clasen's avatar
Matthias Clasen committed
45
#include "gtkcsscustomgadgetprivate.h"
Elliot Lee's avatar
Elliot Lee committed
46

47 48
#include "a11y/gtkimageaccessible.h"

49 50 51 52 53 54 55 56 57
/**
 * SECTION:gtkimage
 * @Short_description: A widget displaying an image
 * @Title: GtkImage
 * @See_also:#GdkPixbuf
 *
 * The #GtkImage widget displays an image. Various kinds of object
 * can be displayed as an image; most typically, you would load a
 * #GdkPixbuf ("pixel buffer") from a file, and then display that.
58
 * There’s a convenience function to do this, gtk_image_new_from_file(),
59
 * used as follows:
60
 * |[<!-- language="C" -->
61 62
 *   GtkWidget *image;
 *   image = gtk_image_new_from_file ("myfile.png");
63
 * ]|
64
 * If the file isn’t loaded successfully, the image will contain a
65
 * “broken image” icon similar to that used in many web browsers.
66 67 68 69 70 71 72 73 74 75 76 77
 * If you want to handle errors in loading the file yourself,
 * for example by displaying an error message, then load the image with
 * gdk_pixbuf_new_from_file(), then create the #GtkImage with
 * gtk_image_new_from_pixbuf().
 *
 * The image file may contain an animation, if so the #GtkImage will
 * display an animation (#GdkPixbufAnimation) instead of a static image.
 *
 * #GtkImage is a subclass of #GtkMisc, which implies that you can
 * align it (center, left, right) and add padding to it, using
 * #GtkMisc methods.
 *
78
 * #GtkImage is a “no window” widget (has no #GdkWindow of its own),
79 80 81
 * so by default does not receive events. If you want to receive events
 * on the image, such as button clicks, place the image inside a
 * #GtkEventBox, then connect to the event signals on the event box.
82 83 84
 *
 * ## Handling button press events on a #GtkImage.
 *
85
 * |[<!-- language="C" -->
86 87 88 89 90
 *   static gboolean
 *   button_press_callback (GtkWidget      *event_box,
 *                          GdkEventButton *event,
 *                          gpointer        data)
 *   {
91
 *     g_print ("Event box clicked at coordinates %f,%f\n",
92 93
 *              event->x, event->y);
 *
94 95 96
 *     // Returning TRUE means we handled the event, so the signal
 *     // emission should be stopped (don’t call any further callbacks
 *     // that may be connected). Return FALSE to continue invoking callbacks.
97 98 99 100 101 102 103 104 105 106 107
 *     return TRUE;
 *   }
 *
 *   static GtkWidget*
 *   create_image (void)
 *   {
 *     GtkWidget *image;
 *     GtkWidget *event_box;
 *
 *     image = gtk_image_new_from_file ("myfile.png");
 *
108
 *     event_box = gtk_event_box_new ();
109 110 111 112 113 114 115 116 117 118
 *
 *     gtk_container_add (GTK_CONTAINER (event_box), image);
 *
 *     g_signal_connect (G_OBJECT (event_box),
 *                       "button_press_event",
 *                       G_CALLBACK (button_press_callback),
 *                       image);
 *
 *     return image;
 *   }
119
 * ]|
120 121 122 123 124 125 126 127 128 129
 *
 * When handling events on the event box, keep in mind that coordinates
 * in the image may be different from event box coordinates due to
 * the alignment and padding settings on the image (see #GtkMisc).
 * The simplest way to solve this is to set the alignment to 0.0
 * (left/top), and set the padding to zero. Then the origin of
 * the image will be the same as the origin of the event box.
 *
 * Sometimes an application will want to avoid depending on external data
 * files, such as image files. GTK+ comes with a program to avoid this,
130
 * called “gdk-pixbuf-csource”. This library
131 132 133
 * allows you to convert an image into a C variable declaration, which
 * can then be loaded into a #GdkPixbuf using
 * gdk_pixbuf_new_from_inline().
134 135 136 137
 *
 * # CSS nodes
 *
 * GtkImage has a single CSS node with the name image.
138 139
 */

140

141
struct _GtkImagePrivate
142
{
143 144 145
  GtkIconHelper *icon_helper;

  GdkPixbufAnimationIter *animation_iter;
146 147
  gint animation_timeout;

Matthias Clasen's avatar
Matthias Clasen committed
148 149
  GtkCssGadget *gadget;

150
  float baseline_align;
151 152

  gchar                *filename;       /* Only used with GTK_IMAGE_ANIMATION, GTK_IMAGE_PIXBUF */
153
  gchar                *resource_path;  /* Only used with GTK_IMAGE_PIXBUF */
154 155
};

156

Havoc Pennington's avatar
Havoc Pennington committed
157
#define DEFAULT_ICON_SIZE GTK_ICON_SIZE_BUTTON
158 159
static gint gtk_image_draw                 (GtkWidget    *widget,
                                            cairo_t      *cr);
160 161
static void gtk_image_size_allocate        (GtkWidget    *widget,
                                            GtkAllocation*allocation);
162 163 164 165 166 167 168 169
static void gtk_image_unmap                (GtkWidget    *widget);
static void gtk_image_unrealize            (GtkWidget    *widget);
static void gtk_image_get_preferred_width  (GtkWidget    *widget,
                                            gint         *minimum,
                                            gint         *natural);
static void gtk_image_get_preferred_height (GtkWidget    *widget,
                                            gint         *minimum,
                                            gint         *natural);
170 171 172 173 174 175
static void gtk_image_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
								   gint       width,
								   gint      *minimum,
								   gint      *natural,
								   gint      *minimum_baseline,
								   gint      *natural_baseline);
176

Matthias Clasen's avatar
Matthias Clasen committed
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
static void gtk_image_get_content_size (GtkCssGadget   *gadget,
                                        GtkOrientation  orientation,
                                        gint            for_size,
                                        gint           *minimum,
                                        gint           *natural,
                                        gint           *minimum_baseline,
                                        gint           *natural_baseline,
                                        gpointer        unused);
static gboolean gtk_image_render_contents (GtkCssGadget *gadget,
                                           cairo_t      *cr,
                                           int           x,
                                           int           y,
                                           int           width,
                                           int           height,
                                           gpointer      data);

193
static void gtk_image_style_updated        (GtkWidget    *widget);
194
static void gtk_image_finalize             (GObject      *object);
195 196 197 198 199 200 201 202 203 204 205
static void gtk_image_reset                (GtkImage     *image);

static void gtk_image_set_property         (GObject      *object,
                                            guint         prop_id,
                                            const GValue *value,
                                            GParamSpec   *pspec);
static void gtk_image_get_property         (GObject      *object,
                                            guint         prop_id,
                                            GValue       *value,
                                            GParamSpec   *pspec);

Havoc Pennington's avatar
Havoc Pennington committed
206 207 208 209
enum
{
  PROP_0,
  PROP_PIXBUF,
210
  PROP_SURFACE,
Havoc Pennington's avatar
Havoc Pennington committed
211 212 213 214
  PROP_FILE,
  PROP_STOCK,
  PROP_ICON_SET,
  PROP_ICON_SIZE,
215
  PROP_PIXEL_SIZE,
Havoc Pennington's avatar
Havoc Pennington committed
216
  PROP_PIXBUF_ANIMATION,
217
  PROP_ICON_NAME,
218
  PROP_STORAGE_TYPE,
219
  PROP_GICON,
220
  PROP_RESOURCE,
221 222
  PROP_USE_FALLBACK,
  NUM_PROPERTIES
Havoc Pennington's avatar
Havoc Pennington committed
223 224
};

225 226
static GParamSpec *image_props[NUM_PROPERTIES] = { NULL, };

Matthias Clasen's avatar
Matthias Clasen committed
227
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
228
G_DEFINE_TYPE_WITH_PRIVATE (GtkImage, gtk_image, GTK_TYPE_MISC)
Matthias Clasen's avatar
Matthias Clasen committed
229
G_GNUC_END_IGNORE_DEPRECATIONS
Elliot Lee's avatar
Elliot Lee committed
230 231 232 233

static void
gtk_image_class_init (GtkImageClass *class)
{
Havoc Pennington's avatar
Havoc Pennington committed
234
  GObjectClass *gobject_class;
Elliot Lee's avatar
Elliot Lee committed
235 236
  GtkWidgetClass *widget_class;

Havoc Pennington's avatar
Havoc Pennington committed
237 238 239 240
  gobject_class = G_OBJECT_CLASS (class);
  
  gobject_class->set_property = gtk_image_set_property;
  gobject_class->get_property = gtk_image_get_property;
241
  gobject_class->finalize = gtk_image_finalize;
242

Havoc Pennington's avatar
Havoc Pennington committed
243
  widget_class = GTK_WIDGET_CLASS (class);
244
  widget_class->draw = gtk_image_draw;
245 246
  widget_class->get_preferred_width = gtk_image_get_preferred_width;
  widget_class->get_preferred_height = gtk_image_get_preferred_height;
247
  widget_class->get_preferred_height_and_baseline_for_width = gtk_image_get_preferred_height_and_baseline_for_width;
248
  widget_class->size_allocate = gtk_image_size_allocate;
Havoc Pennington's avatar
Havoc Pennington committed
249
  widget_class->unmap = gtk_image_unmap;
250
  widget_class->unrealize = gtk_image_unrealize;
251
  widget_class->style_updated = gtk_image_style_updated;
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272

  image_props[PROP_PIXBUF] =
      g_param_spec_object ("pixbuf",
                           P_("Pixbuf"),
                           P_("A GdkPixbuf to display"),
                           GDK_TYPE_PIXBUF,
                           GTK_PARAM_READWRITE);

  image_props[PROP_SURFACE] =
      g_param_spec_boxed ("surface",
                          P_("Surface"),
                          P_("A cairo_surface_t to display"),
                          CAIRO_GOBJECT_TYPE_SURFACE,
                          GTK_PARAM_READWRITE);

  image_props[PROP_FILE] =
      g_param_spec_string ("file",
                           P_("Filename"),
                           P_("Filename to load and display"),
                           NULL,
                           GTK_PARAM_READWRITE);
Havoc Pennington's avatar
Havoc Pennington committed
273

274 275 276 277 278
  /**
   * GtkImage:stock:
   *
   * Deprecated: 3.10: Use #GtkImage:icon-name instead.
   */
279 280 281 282 283 284 285
  image_props[PROP_STOCK] =
      g_param_spec_string ("stock",
                           P_("Stock ID"),
                           P_("Stock ID for a stock image to display"),
                           NULL,
                           GTK_PARAM_READWRITE | G_PARAM_DEPRECATED);

286 287 288 289 290 291
  /**
   * GtkImage:icon-set:
   *
   * Deprecated: 3.10: Use #GtkImage:icon-name instead.
   */
  G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
292 293 294 295 296 297
  image_props[PROP_ICON_SET] =
      g_param_spec_boxed ("icon-set",
                          P_("Icon set"),
                          P_("Icon set to display"),
                          GTK_TYPE_ICON_SET,
                          GTK_PARAM_READWRITE | G_PARAM_DEPRECATED);
298 299
  G_GNUC_END_IGNORE_DEPRECATIONS;

300 301 302 303 304 305 306 307
  image_props[PROP_ICON_SIZE] =
      g_param_spec_int ("icon-size",
                        P_("Icon size"),
                        P_("Symbolic size to use for stock icon, icon set or named icon"),
                        0, G_MAXINT,
                        DEFAULT_ICON_SIZE,
                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);

308 309 310
  /**
   * GtkImage:pixel-size:
   *
311
   * The "pixel-size" property can be used to specify a fixed size
312 313
   * overriding the #GtkImage:icon-size property for images of type
   * %GTK_IMAGE_ICON_NAME.
314 315 316
   *
   * Since: 2.6
   */
317 318 319 320 321 322 323 324 325 326 327 328 329 330
  image_props[PROP_PIXEL_SIZE] =
      g_param_spec_int ("pixel-size",
                        P_("Pixel size"),
                        P_("Pixel size to use for named icon"),
                        -1, G_MAXINT,
                        -1,
                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);

  image_props[PROP_PIXBUF_ANIMATION] =
      g_param_spec_object ("pixbuf-animation",
                           P_("Animation"),
                           P_("GdkPixbufAnimation to display"),
                           GDK_TYPE_PIXBUF_ANIMATION,
                           GTK_PARAM_READWRITE);
331 332 333 334

  /**
   * GtkImage:icon-name:
   *
335
   * The name of the icon in the icon theme. If the icon theme is
336 337 338 339
   * changed, the image will be updated automatically.
   *
   * Since: 2.6
   */
340 341 342 343 344 345 346
  image_props[PROP_ICON_NAME] =
      g_param_spec_string ("icon-name",
                           P_("Icon Name"),
                           P_("The name of the icon from the icon theme"),
                           NULL,
                           GTK_PARAM_READWRITE);

347 348 349 350 351 352 353 354 355
  /**
   * GtkImage:gicon:
   *
   * The GIcon displayed in the GtkImage. For themed icons,
   * If the icon theme is changed, the image will be updated
   * automatically.
   *
   * Since: 2.14
   */
356 357 358 359 360 361
  image_props[PROP_GICON] =
      g_param_spec_object ("gicon",
                           P_("Icon"),
                           P_("The GIcon being displayed"),
                           G_TYPE_ICON,
                           GTK_PARAM_READWRITE);
362 363 364 365 366 367 368 369

  /**
   * GtkImage:resource:
   *
   * A path to a resource file to display.
   *
   * Since: 3.8
   */
370 371 372 373 374 375 376 377 378 379 380 381 382 383
  image_props[PROP_RESOURCE] =
      g_param_spec_string ("resource",
                           P_("Resource"),
                           P_("The resource path being displayed"),
                           NULL,
                           GTK_PARAM_READWRITE);

  image_props[PROP_STORAGE_TYPE] =
      g_param_spec_enum ("storage-type",
                         P_("Storage type"),
                         P_("The representation being used for image data"),
                         GTK_TYPE_IMAGE_TYPE,
                         GTK_IMAGE_EMPTY,
                         GTK_PARAM_READABLE);
384

385 386 387 388 389 390 391 392 393 394
  /**
   * GtkImage:use-fallback:
   *
   * Whether the icon displayed in the GtkImage will use
   * standard icon names fallback. The value of this property
   * is only relevant for images of type %GTK_IMAGE_ICON_NAME
   * and %GTK_IMAGE_GICON.
   *
   * Since: 3.0
   */
395 396 397 398 399 400 401 402
  image_props[PROP_USE_FALLBACK] =
      g_param_spec_boolean ("use-fallback",
                            P_("Use Fallback"),
                            P_("Whether to use icon names fallback"),
                            FALSE,
                            GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);

  g_object_class_install_properties (gobject_class, NUM_PROPERTIES, image_props);
403

404
  gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_IMAGE_ACCESSIBLE);
405
  gtk_widget_class_set_css_name (widget_class, "image");
Elliot Lee's avatar
Elliot Lee committed
406 407 408 409 410
}

static void
gtk_image_init (GtkImage *image)
{
411
  GtkImagePrivate *priv;
Matthias Clasen's avatar
Matthias Clasen committed
412
  GtkCssNode *widget_node;
413

414
  image->priv = gtk_image_get_instance_private (image);
415
  priv = image->priv;
416

417
  widget_node = gtk_widget_get_css_node (GTK_WIDGET (image));
418
  gtk_widget_set_has_window (GTK_WIDGET (image), FALSE);
419 420

  priv->icon_helper = gtk_icon_helper_new (widget_node, GTK_WIDGET (image));
421
  _gtk_icon_helper_set_icon_size (priv->icon_helper, DEFAULT_ICON_SIZE);
Matthias Clasen's avatar
Matthias Clasen committed
422 423 424 425 426 427 428 429

  priv->gadget = gtk_css_custom_gadget_new_for_node (widget_node,
                                                     GTK_WIDGET (image),
                                                     gtk_image_get_content_size,
                                                     NULL,
                                                     gtk_image_render_contents,
                                                     NULL, NULL);

Elliot Lee's avatar
Elliot Lee committed
430 431
}

432
static void
433
gtk_image_finalize (GObject *object)
434
{
435
  GtkImage *image = GTK_IMAGE (object);
436

437
  g_clear_object (&image->priv->icon_helper);
Matthias Clasen's avatar
Matthias Clasen committed
438 439
  g_clear_object (&image->priv->gadget);

440
  g_free (image->priv->filename);
441
  g_free (image->priv->resource_path);
442

443 444
  G_OBJECT_CLASS (gtk_image_parent_class)->finalize (object);
};
445

Matthias Clasen's avatar
Matthias Clasen committed
446
static void
Havoc Pennington's avatar
Havoc Pennington committed
447 448 449 450 451
gtk_image_set_property (GObject      *object,
			guint         prop_id,
			const GValue *value,
			GParamSpec   *pspec)
{
452
  GtkImage *image = GTK_IMAGE (object);
453
  GtkImagePrivate *priv = image->priv;
454
  GtkIconSize icon_size = _gtk_icon_helper_get_icon_size (priv->icon_helper);
Havoc Pennington's avatar
Havoc Pennington committed
455

456 457 458
  if (icon_size == GTK_ICON_SIZE_INVALID)
    icon_size = DEFAULT_ICON_SIZE;

Havoc Pennington's avatar
Havoc Pennington committed
459 460 461
  switch (prop_id)
    {
    case PROP_PIXBUF:
462
      gtk_image_set_from_pixbuf (image, g_value_get_object (value));
Havoc Pennington's avatar
Havoc Pennington committed
463
      break;
464
    case PROP_SURFACE:
465
      gtk_image_set_from_surface (image, g_value_get_boxed (value));
466
      break;
Havoc Pennington's avatar
Havoc Pennington committed
467
    case PROP_FILE:
468
      gtk_image_set_from_file (image, g_value_get_string (value));
Havoc Pennington's avatar
Havoc Pennington committed
469 470
      break;
    case PROP_STOCK:
471
      G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
472
      gtk_image_set_from_stock (image, g_value_get_string (value), icon_size);
473
      G_GNUC_END_IGNORE_DEPRECATIONS;
Havoc Pennington's avatar
Havoc Pennington committed
474 475
      break;
    case PROP_ICON_SET:
476
      G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
477
      gtk_image_set_from_icon_set (image, g_value_get_boxed (value), icon_size);
478
      G_GNUC_END_IGNORE_DEPRECATIONS;
Havoc Pennington's avatar
Havoc Pennington committed
479 480
      break;
    case PROP_ICON_SIZE:
481
      if (_gtk_icon_helper_set_icon_size (priv->icon_helper, g_value_get_int (value)))
482 483 484 485
        {
          g_object_notify_by_pspec (object, pspec);
          gtk_widget_queue_resize (GTK_WIDGET (image));
        }
Havoc Pennington's avatar
Havoc Pennington committed
486
      break;
487
    case PROP_PIXEL_SIZE:
488
      gtk_image_set_pixel_size (image, g_value_get_int (value));
489
      break;
Havoc Pennington's avatar
Havoc Pennington committed
490
    case PROP_PIXBUF_ANIMATION:
491
      gtk_image_set_from_animation (image, g_value_get_object (value));
Havoc Pennington's avatar
Havoc Pennington committed
492
      break;
493
    case PROP_ICON_NAME:
494
      gtk_image_set_from_icon_name (image, g_value_get_string (value), icon_size);
495
      break;
496
    case PROP_GICON:
497
      gtk_image_set_from_gicon (image, g_value_get_object (value), icon_size);
498
      break;
499 500 501
    case PROP_RESOURCE:
      gtk_image_set_from_resource (image, g_value_get_string (value));
      break;
502

503
    case PROP_USE_FALLBACK:
504 505
      if (_gtk_icon_helper_set_use_fallback (priv->icon_helper, g_value_get_boolean (value)))
        g_object_notify_by_pspec (object, pspec);
506 507
      break;

Havoc Pennington's avatar
Havoc Pennington committed
508 509 510 511 512 513 514 515 516 517 518 519
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

static void 
gtk_image_get_property (GObject     *object,
			guint        prop_id,
			GValue      *value,
			GParamSpec  *pspec)
{
520
  GtkImage *image = GTK_IMAGE (object);
521
  GtkImagePrivate *priv = image->priv;
Havoc Pennington's avatar
Havoc Pennington committed
522 523 524 525

  switch (prop_id)
    {
    case PROP_PIXBUF:
Cosimo Cecchi's avatar
Cosimo Cecchi committed
526
      g_value_set_object (value, _gtk_icon_helper_peek_pixbuf (priv->icon_helper));
Havoc Pennington's avatar
Havoc Pennington committed
527
      break;
528 529 530
    case PROP_SURFACE:
      g_value_set_boxed (value, _gtk_icon_helper_peek_surface (priv->icon_helper));
      break;
531 532 533
    case PROP_FILE:
      g_value_set_string (value, priv->filename);
      break;
Havoc Pennington's avatar
Havoc Pennington committed
534
    case PROP_STOCK:
535
      g_value_set_string (value, _gtk_icon_helper_get_stock_id (priv->icon_helper));
Havoc Pennington's avatar
Havoc Pennington committed
536 537
      break;
    case PROP_ICON_SET:
538
      G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
539
      g_value_set_boxed (value, _gtk_icon_helper_peek_icon_set (priv->icon_helper));
540 541
      G_GNUC_END_IGNORE_DEPRECATIONS;
      break;
Havoc Pennington's avatar
Havoc Pennington committed
542
    case PROP_ICON_SIZE:
543
      g_value_set_int (value, _gtk_icon_helper_get_icon_size (priv->icon_helper));
Havoc Pennington's avatar
Havoc Pennington committed
544
      break;
545
    case PROP_PIXEL_SIZE:
546
      g_value_set_int (value, _gtk_icon_helper_get_pixel_size (priv->icon_helper));
547
      break;
Havoc Pennington's avatar
Havoc Pennington committed
548
    case PROP_PIXBUF_ANIMATION:
Cosimo Cecchi's avatar
Cosimo Cecchi committed
549
      g_value_set_object (value, _gtk_icon_helper_peek_animation (priv->icon_helper));
Havoc Pennington's avatar
Havoc Pennington committed
550
      break;
551
    case PROP_ICON_NAME:
Cosimo Cecchi's avatar
Cosimo Cecchi committed
552
      g_value_set_string (value, _gtk_icon_helper_get_icon_name (priv->icon_helper));
553
      break;
554
    case PROP_GICON:
Cosimo Cecchi's avatar
Cosimo Cecchi committed
555
      g_value_set_object (value, _gtk_icon_helper_peek_gicon (priv->icon_helper));
Havoc Pennington's avatar
Havoc Pennington committed
556
      break;
557 558 559
    case PROP_RESOURCE:
      g_value_set_string (value, priv->resource_path);
      break;
560
    case PROP_USE_FALLBACK:
561
      g_value_set_boolean (value, _gtk_icon_helper_get_use_fallback (priv->icon_helper));
562
      break;
563 564 565
    case PROP_STORAGE_TYPE:
      g_value_set_enum (value, _gtk_icon_helper_get_storage_type (priv->icon_helper));
      break;
Havoc Pennington's avatar
Havoc Pennington committed
566 567 568 569 570 571
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

572

573 574
/**
 * gtk_image_new_from_file:
575
 * @filename: (type filename): a filename
576
 * 
Havoc Pennington's avatar
Havoc Pennington committed
577
 * Creates a new #GtkImage displaying the file @filename. If the file
578
 * isn’t found or can’t be loaded, the resulting #GtkImage will
579
 * display a “broken image” icon. This function never returns %NULL,
Havoc Pennington's avatar
Havoc Pennington committed
580 581 582 583 584 585 586 587 588 589 590 591 592
 * it always returns a valid #GtkImage widget.
 *
 * If the file contains an animation, the image will contain an
 * animation.
 *
 * If you need to detect failures to load the file, use
 * gdk_pixbuf_new_from_file() to load the file yourself, then create
 * the #GtkImage from the pixbuf. (Or for animations, use
 * gdk_pixbuf_animation_new_from_file()).
 *
 * The storage type (gtk_image_get_storage_type()) of the returned
 * image is not defined, it will be whatever is appropriate for
 * displaying the file.
593
 * 
594
 * Returns: a new #GtkImage
595
 **/
596 597 598 599 600
GtkWidget*
gtk_image_new_from_file   (const gchar *filename)
{
  GtkImage *image;

Manish Singh's avatar
Manish Singh committed
601
  image = g_object_new (GTK_TYPE_IMAGE, NULL);
602 603 604 605 606 607

  gtk_image_set_from_file (image, filename);

  return GTK_WIDGET (image);
}

608 609 610 611 612
/**
 * gtk_image_new_from_resource:
 * @resource_path: a resource path
 *
 * Creates a new #GtkImage displaying the resource file @resource_path. If the file
613
 * isn’t found or can’t be loaded, the resulting #GtkImage will
614
 * display a “broken image” icon. This function never returns %NULL,
615 616 617 618 619 620 621 622 623 624 625 626 627 628
 * it always returns a valid #GtkImage widget.
 *
 * If the file contains an animation, the image will contain an
 * animation.
 *
 * If you need to detect failures to load the file, use
 * gdk_pixbuf_new_from_file() to load the file yourself, then create
 * the #GtkImage from the pixbuf. (Or for animations, use
 * gdk_pixbuf_animation_new_from_file()).
 *
 * The storage type (gtk_image_get_storage_type()) of the returned
 * image is not defined, it will be whatever is appropriate for
 * displaying the file.
 *
629
 * Returns: a new #GtkImage
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644
 *
 * Since: 3.4
 **/
GtkWidget*
gtk_image_new_from_resource (const gchar *resource_path)
{
  GtkImage *image;

  image = g_object_new (GTK_TYPE_IMAGE, NULL);

  gtk_image_set_from_resource (image, resource_path);

  return GTK_WIDGET (image);
}

645 646
/**
 * gtk_image_new_from_pixbuf:
647 648
 * @pixbuf: (allow-none): a #GdkPixbuf, or %NULL
 *
649 650 651 652 653
 * Creates a new #GtkImage displaying @pixbuf.
 * The #GtkImage does not assume a reference to the
 * pixbuf; you still need to unref it if you own references.
 * #GtkImage will add its own reference rather than adopting yours.
 * 
654 655
 * Note that this function just creates an #GtkImage from the pixbuf. The
 * #GtkImage created will not react to state changes. Should you want that, 
656
 * you should use gtk_image_new_from_icon_name().
657
 * 
658
 * Returns: a new #GtkImage
659
 **/
660 661 662 663 664
GtkWidget*
gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf)
{
  GtkImage *image;

Manish Singh's avatar
Manish Singh committed
665
  image = g_object_new (GTK_TYPE_IMAGE, NULL);
666 667 668 669 670 671

  gtk_image_set_from_pixbuf (image, pixbuf);

  return GTK_WIDGET (image);  
}

672 673 674 675 676 677 678 679 680
/**
 * gtk_image_new_from_surface:
 * @surface: (allow-none): a #cairo_surface_t, or %NULL
 *
 * Creates a new #GtkImage displaying @surface.
 * The #GtkImage does not assume a reference to the
 * surface; you still need to unref it if you own references.
 * #GtkImage will add its own reference rather than adopting yours.
 * 
681
 * Returns: a new #GtkImage
682 683
 *
 * Since: 3.10
684 685 686 687 688 689 690 691 692 693 694 695 696
 **/
GtkWidget*
gtk_image_new_from_surface (cairo_surface_t *surface)
{
  GtkImage *image;

  image = g_object_new (GTK_TYPE_IMAGE, NULL);

  gtk_image_set_from_surface (image, surface);

  return GTK_WIDGET (image);  
}

697 698 699
/**
 * gtk_image_new_from_stock:
 * @stock_id: a stock icon name
700
 * @size: (type int): a stock icon size (#GtkIconSize)
701 702
 * 
 * Creates a #GtkImage displaying a stock icon. Sample stock icon
703
 * names are #GTK_STOCK_OPEN, #GTK_STOCK_QUIT. Sample stock sizes
704
 * are #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. If the stock
705
 * icon name isn’t known, the image will be empty.
706 707
 * You can register your own stock icon names, see
 * gtk_icon_factory_add_default() and gtk_icon_factory_add().
708
 * 
709
 * Returns: a new #GtkImage displaying the stock icon
710 711
 *
 * Deprecated: 3.10: Use gtk_image_new_from_icon_name() instead.
712
 **/
713 714
GtkWidget*
gtk_image_new_from_stock (const gchar    *stock_id,
715
                          GtkIconSize     size)
716 717 718
{
  GtkImage *image;

Manish Singh's avatar
Manish Singh committed
719
  image = g_object_new (GTK_TYPE_IMAGE, NULL);
720

721
  G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
722
  gtk_image_set_from_stock (image, stock_id, size);
723
  G_GNUC_END_IGNORE_DEPRECATIONS;
724 725 726 727

  return GTK_WIDGET (image);
}

728 729 730
/**
 * gtk_image_new_from_icon_set:
 * @icon_set: a #GtkIconSet
731
 * @size: (type int): a stock icon size (#GtkIconSize)
732 733 734
 *
 * Creates a #GtkImage displaying an icon set. Sample stock sizes are
 * #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. Instead of using
735
 * this function, usually it’s better to create a #GtkIconFactory, put
736 737 738 739 740 741 742 743 744
 * your icon sets in the icon factory, add the icon factory to the
 * list of default factories with gtk_icon_factory_add_default(), and
 * then use gtk_image_new_from_stock(). This will allow themes to
 * override the icon you ship with your application.
 *
 * The #GtkImage does not assume a reference to the
 * icon set; you still need to unref it if you own references.
 * #GtkImage will add its own reference rather than adopting yours.
 * 
745
 * Returns: a new #GtkImage
746 747
 *
 * Deprecated: 3.10: Use gtk_image_new_from_icon_name() instead.
748
 **/
749 750
GtkWidget*
gtk_image_new_from_icon_set (GtkIconSet     *icon_set,
751
                             GtkIconSize     size)
752 753 754
{
  GtkImage *image;

Manish Singh's avatar
Manish Singh committed
755
  image = g_object_new (GTK_TYPE_IMAGE, NULL);
756

757 758
  G_GNUC_BEGIN_IGNORE_DEPRECATIONS;

759
  gtk_image_set_from_icon_set (image, icon_set, size);
Elliot Lee's avatar
Elliot Lee committed
760

761 762
  G_GNUC_END_IGNORE_DEPRECATIONS;

Elliot Lee's avatar
Elliot Lee committed
763 764 765
  return GTK_WIDGET (image);
}

Havoc Pennington's avatar
Havoc Pennington committed
766 767 768 769 770 771 772 773
/**
 * gtk_image_new_from_animation:
 * @animation: an animation
 * 
 * Creates a #GtkImage displaying the given animation.
 * The #GtkImage does not assume a reference to the
 * animation; you still need to unref it if you own references.
 * #GtkImage will add its own reference rather than adopting yours.
774 775 776 777 778 779
 *
 * Note that the animation frames are shown using a timeout with
 * #G_PRIORITY_DEFAULT. When using animations to indicate busyness,
 * keep in mind that the animation will only be shown if the main loop
 * is not busy with something that has a higher priority.
 *
780
 * Returns: a new #GtkImage widget
Havoc Pennington's avatar
Havoc Pennington committed
781 782 783 784 785 786 787 788
 **/
GtkWidget*
gtk_image_new_from_animation (GdkPixbufAnimation *animation)
{
  GtkImage *image;

  g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), NULL);
  
Manish Singh's avatar
Manish Singh committed
789
  image = g_object_new (GTK_TYPE_IMAGE, NULL);
Havoc Pennington's avatar
Havoc Pennington committed
790 791 792 793 794 795

  gtk_image_set_from_animation (image, animation);

  return GTK_WIDGET (image);
}

796 797
/**
 * gtk_image_new_from_icon_name:
798
 * @icon_name: (nullable): an icon name or %NULL
799
 * @size: (type int): a stock icon size (#GtkIconSize)
800 801
 * 
 * Creates a #GtkImage displaying an icon from the current icon theme.
802
 * If the icon name isn’t known, a “broken image” icon will be
803 804 805
 * displayed instead.  If the current icon theme is changed, the icon
 * will be updated appropriately.
 * 
806
 * Returns: a new #GtkImage displaying the themed icon
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822
 *
 * Since: 2.6
 **/
GtkWidget*
gtk_image_new_from_icon_name (const gchar    *icon_name,
			      GtkIconSize     size)
{
  GtkImage *image;

  image = g_object_new (GTK_TYPE_IMAGE, NULL);

  gtk_image_set_from_icon_name (image, icon_name, size);

  return GTK_WIDGET (image);
}

823 824 825
/**
 * gtk_image_new_from_gicon:
 * @icon: an icon
826
 * @size: (type int): a stock icon size (#GtkIconSize)
827 828
 * 
 * Creates a #GtkImage displaying an icon from the current icon theme.
829
 * If the icon name isn’t known, a “broken image” icon will be
830 831 832
 * displayed instead.  If the current icon theme is changed, the icon
 * will be updated appropriately.
 * 
833
 * Returns: a new #GtkImage displaying the themed icon
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849
 *
 * Since: 2.14
 **/
GtkWidget*
gtk_image_new_from_gicon (GIcon *icon,
			  GtkIconSize     size)
{
  GtkImage *image;

  image = g_object_new (GTK_TYPE_IMAGE, NULL);

  gtk_image_set_from_gicon (image, icon, size);

  return GTK_WIDGET (image);
}

850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
typedef struct {
  GtkImage *image;
  gint scale_factor;
} LoaderData;

static void
on_loader_size_prepared (GdkPixbufLoader *loader,
			 gint             width,
			 gint             height,
			 gpointer         user_data)
{
  LoaderData *loader_data = user_data;
  gint scale_factor;
  GdkPixbufFormat *format;

  /* Let the regular icon helper code path handle non-scalable images */
  format = gdk_pixbuf_loader_get_format (loader);
  if (!gdk_pixbuf_format_is_scalable (format))
    {
      loader_data->scale_factor = 1;
      return;
    }

  scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (loader_data->image));
  gdk_pixbuf_loader_set_size (loader, width * scale_factor, height * scale_factor);
  loader_data->scale_factor = scale_factor;
}

static GdkPixbufAnimation *
load_scalable_with_loader (GtkImage    *image,
			   const gchar *file_path,
			   const gchar *resource_path,
			   gint        *scale_factor_out)
{
  GdkPixbufLoader *loader;
  GBytes *bytes;
  char *contents;
  gsize length;
  gboolean res;
  GdkPixbufAnimation *animation;
  LoaderData loader_data;

  animation = NULL;
  bytes = NULL;

  loader = gdk_pixbuf_loader_new ();
  loader_data.image = image;

  g_signal_connect (loader, "size-prepared", G_CALLBACK (on_loader_size_prepared), &loader_data);

  if (resource_path != NULL)
    {
      bytes = g_resources_lookup_data (resource_path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
    }
  else if (file_path != NULL)
    {
      res = g_file_get_contents (file_path, &contents, &length, NULL);
      if (res)
	bytes = g_bytes_new_take (contents, length);
    }
  else
    {
      g_assert_not_reached ();
    }

  if (!bytes)
    goto out;

  if (!gdk_pixbuf_loader_write_bytes (loader, bytes, NULL))
    goto out;

  if (!gdk_pixbuf_loader_close (loader, NULL))
    goto out;

  animation = gdk_pixbuf_loader_get_animation (loader);
  if (animation != NULL)
    {
      g_object_ref (animation);
      if (scale_factor_out != NULL)
	*scale_factor_out = loader_data.scale_factor;
    }

 out:
933
  gdk_pixbuf_loader_close (loader, NULL);
934 935 936 937 938 939
  g_object_unref (loader);
  g_bytes_unref (bytes);

  return animation;
}

940 941 942
/**
 * gtk_image_set_from_file:
 * @image: a #GtkImage
943
 * @filename: (type filename) (allow-none): a filename or %NULL
944 945 946
 *
 * See gtk_image_new_from_file() for details.
 **/
947 948 949 950
void
gtk_image_set_from_file   (GtkImage    *image,
                           const gchar *filename)
{
951
  GtkImagePrivate *priv;
Havoc Pennington's avatar
Havoc Pennington committed
952
  GdkPixbufAnimation *anim;
953
  gint scale_factor;
954
  
955
  g_return_if_fail (GTK_IS_IMAGE (image));
Havoc Pennington's avatar
Havoc Pennington committed
956

957 958
  priv = image->priv;

Havoc Pennington's avatar
Havoc Pennington committed
959
  g_object_freeze_notify (G_OBJECT (image));
960 961
  
  gtk_image_clear (image);
962 963

  if (filename == NULL)
Havoc Pennington's avatar
Havoc Pennington committed
964
    {
965
      priv->filename = NULL;
Havoc Pennington's avatar
Havoc Pennington committed
966 967 968
      g_object_thaw_notify (G_OBJECT (image));
      return;
    }
969

970
  anim = load_scalable_with_loader (image, filename, NULL, &scale_factor);
971

Havoc Pennington's avatar
Havoc Pennington committed
972
  if (anim == NULL)
973
    {
974 975 976
      gtk_image_set_from_icon_name (image,
                                    "image-missing",
                                    DEFAULT_ICON_SIZE);
Havoc Pennington's avatar
Havoc Pennington committed
977
      g_object_thaw_notify (G_OBJECT (image));
978 979
      return;
    }
980

Havoc Pennington's avatar
Havoc Pennington committed
981 982 983 984
  /* We could just unconditionally set_from_animation,
   * but it's nicer for memory if we toss the animation
   * if it's just a single pixbuf
   */
985

Havoc Pennington's avatar
Havoc Pennington committed
986
  if (gdk_pixbuf_animation_is_static_image (anim))
987 988
    gtk_image_set_from_pixbuf (image,
			       gdk_pixbuf_animation_get_static_image (anim));
Havoc Pennington's avatar
Havoc Pennington committed
989
  else
990
    gtk_image_set_from_animation (image, anim);
Havoc Pennington's avatar
Havoc Pennington committed
991

992 993
  _gtk_icon_helper_set_pixbuf_scale (priv->icon_helper, scale_factor);

Manish Singh's avatar
Manish Singh committed
994
  g_object_unref (anim);
Havoc Pennington's avatar
Havoc Pennington committed
995

996
  priv->filename = g_strdup (filename);
997
  
Havoc Pennington's avatar
Havoc Pennington committed
998
  g_object_thaw_notify (G_OBJECT (image));
999 1000
}

1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
#ifndef GDK_PIXBUF_MAGIC_NUMBER
#define GDK_PIXBUF_MAGIC_NUMBER (0x47646b50)    /* 'GdkP' */
#endif

static gboolean
resource_is_pixdata (const gchar *resource_path)
{
  const guint8 *stream;
  guint32 magic;
  gsize data_size;
  GBytes *bytes;
  gboolean ret = FALSE;

  bytes = g_resources_lookup_data (resource_path, 0, NULL);
  if (bytes == NULL)
    return FALSE;

  stream = g_bytes_get_data (bytes, &data_size);
  if (data_size < sizeof(guint32))
    goto out;

  magic = (stream[0] << 24) + (stream[1] << 16) + (stream[2] << 8) + stream[3];
  if (magic == GDK_PIXBUF_MAGIC_NUMBER)
    ret = TRUE;

out:
  g_bytes_unref (bytes);
  return ret;
}

1031 1032 1033 1034 1035 1036 1037 1038
/**
 * gtk_image_set_from_resource:
 * @image: a #GtkImage
 * @resource_path: (allow-none): a resource path or %NULL
 *
 * See gtk_image_new_from_resource() for details.
 **/
void
Benjamin Otte's avatar
Benjamin Otte committed
1039 1040
gtk_image_set_from_resource (GtkImage    *image,
			     const gchar *resource_path)
1041
{
1042
  GtkImagePrivate *priv;
1043
  GdkPixbufAnimation *animation;
1044
  gint scale_factor = 1;
1045 1046 1047

  g_return_if_fail (GTK_IS_IMAGE (image));

1048 1049
  priv = image->priv;

1050 1051 1052 1053 1054 1055 1056 1057 1058 1059
  g_object_freeze_notify (G_OBJECT (image));

  gtk_image_clear (image);

  if (resource_path == NULL)
    {
      g_object_thaw_notify (G_OBJECT (image));
      return;
    }

1060 1061 1062 1063
  if (resource_is_pixdata (resource_path))
    animation = gdk_pixbuf_animation_new_from_resource (resource_path, NULL);
  else
    animation = load_scalable_with_loader (image, NULL, resource_path, &scale_factor);
1064

1065
  if (animation == NULL)
1066
    {
1067 1068 1069
      gtk_image_set_from_icon_name (image,
                                    "image-missing",
                                    DEFAULT_ICON_SIZE);
1070 1071 1072 1073
      g_object_thaw_notify (G_OBJECT (image));
      return;
    }

1074 1075 1076 1077
  if (gdk_pixbuf_animation_is_static_image (animation))
    gtk_image_set_from_pixbuf (image, gdk_pixbuf_animation_get_static_image (animation));
  else
    gtk_image_set_from_animation (image, animation);
1078 1079

  _gtk_icon_helper_set_pixbuf_scale (priv->icon_helper, scale_factor);
1080

1081 1082
  priv->resource_path = g_strdup (resource_path);

1083
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_RESOURCE]);
1084

1085
  g_object_unref (animation);
1086 1087 1088 1089 1090

  g_object_thaw_notify (G_OBJECT (image));
}


1091 1092 1093
/**
 * gtk_image_set_from_pixbuf:
 * @image: a #GtkImage
1094
 * @pixbuf: (allow-none): a #GdkPixbuf or %NULL
1095
 *
1096
 * See gtk_image_new_from_pixbuf() for details.
1097
 **/
1098 1099 1100 1101
void
gtk_image_set_from_pixbuf (GtkImage  *image,
                           GdkPixbuf *pixbuf)
{
1102
  GtkImagePrivate *priv;
1103

1104
  g_return_if_fail (GTK_IS_IMAGE (image));
1105 1106
  g_return_if_fail (pixbuf == NULL ||
                    GDK_IS_PIXBUF (pixbuf));
Havoc Pennington's avatar
Havoc Pennington committed
1107

1108 1109
  priv = image->priv;

Havoc Pennington's avatar
Havoc Pennington committed
1110
  g_object_freeze_notify (G_OBJECT (image));
1111 1112
  
  gtk_image_clear (image);
1113 1114

  if (pixbuf != NULL)
1115
    _gtk_icon_helper_set_pixbuf (priv->icon_helper, pixbuf);
Havoc Pennington's avatar
Havoc Pennington committed
1116

1117
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_PIXBUF]);
1118
  
Havoc Pennington's avatar
Havoc Pennington committed
1119
  g_object_thaw_notify (G_OBJECT (image));
1120 1121
}

1122 1123 1124 1125
/**
 * gtk_image_set_from_stock:
 * @image: a #GtkImage
 * @stock_id: a stock icon name
1126
 * @size: (type int): a stock icon size (#GtkIconSize)
1127
 *
1128
 * See gtk_image_new_from_stock() for details.
1129 1130
 *
 * Deprecated: 3.10: Use gtk_image_set_from_icon_name() instead.
1131
 **/
1132 1133 1134
void
gtk_image_set_from_stock  (GtkImage       *image,
                           const gchar    *stock_id,
1135
                           GtkIconSize     size)
1136
{
1137
  GtkImagePrivate *priv;
Havoc Pennington's avatar
Havoc Pennington committed
1138
  gchar *new_id;
1139

1140
  g_return_if_fail (GTK_IS_IMAGE (image));
Havoc Pennington's avatar
Havoc Pennington committed
1141

1142 1143
  priv = image->priv;

Havoc Pennington's avatar
Havoc Pennington committed
1144 1145 1146
  g_object_freeze_notify (G_OBJECT (image));

  new_id = g_strdup (stock_id);
1147
  gtk_image_clear (image);
1148

Havoc Pennington's avatar
Havoc Pennington committed
1149 1150
  if (new_id)
    {
1151 1152
      _gtk_icon_helper_set_stock_id (priv->icon_helper, new_id, size);
      g_free (new_id);
1153
    }
Havoc Pennington's avatar
Havoc Pennington committed
1154

1155 1156 1157
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_STOCK]);
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_ICON_SIZE]);

Havoc Pennington's avatar
Havoc Pennington committed
1158
  g_object_thaw_notify (G_OBJECT (image));
1159 1160
}

1161 1162 1163 1164
/**
 * gtk_image_set_from_icon_set:
 * @image: a #GtkImage
 * @icon_set: a #GtkIconSet
1165
 * @size: (type int): a stock icon size (#GtkIconSize)
1166 1167
 *
 * See gtk_image_new_from_icon_set() for details.
1168 1169
 *
 * Deprecated: 3.10: Use gtk_image_set_from_icon_name() instead.
1170
 **/
1171 1172 1173
void
gtk_image_set_from_icon_set  (GtkImage       *image,
                              GtkIconSet     *icon_set,
1174
                              GtkIconSize     size)
1175
{
1176
  GtkImagePrivate *priv;
1177

1178 1179
  g_return_if_fail (GTK_IS_IMAGE (image));

1180 1181
  priv = image->priv;

Havoc Pennington's avatar
Havoc Pennington committed
1182
  g_object_freeze_notify (G_OBJECT (image));
1183

1184 1185
  G_GNUC_BEGIN_IGNORE_DEPRECATIONS;

1186 1187
  if (icon_set)
    gtk_icon_set_ref (icon_set);
1188

1189
  gtk_image_clear (image);
1190 1191

  if (icon_set)
1192
    {
1193 1194
      _gtk_icon_helper_set_icon_set (priv->icon_helper, icon_set, size);
      gtk_icon_set_unref (icon_set);
1195
    }
1196 1197 1198

  G_GNUC_END_IGNORE_DEPRECATIONS;

1199 1200 1201
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_ICON_SET]);
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_ICON_SIZE]);

Havoc Pennington's avatar
Havoc Pennington committed
1202
  g_object_thaw_notify (G_OBJECT (image));
1203 1204
}

Havoc Pennington's avatar
Havoc Pennington committed
1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216
/**
 * gtk_image_set_from_animation:
 * @image: a #GtkImage
 * @animation: the #GdkPixbufAnimation
 * 
 * Causes the #GtkImage to display the given animation (or display
 * nothing, if you set the animation to %NULL).
 **/
void
gtk_image_set_from_animation (GtkImage           *image,
                              GdkPixbufAnimation *animation)
{
1217
  GtkImagePrivate *priv;
1218

Havoc Pennington's avatar
Havoc Pennington committed
1219 1220 1221
  g_return_if_fail (GTK_IS_IMAGE (image));
  g_return_if_fail (animation == NULL ||
                    GDK_IS_PIXBUF_ANIMATION (animation));
Havoc Pennington's avatar
Havoc Pennington committed
1222

1223 1224
  priv = image->priv;

Havoc Pennington's avatar
Havoc Pennington committed
1225
  g_object_freeze_notify (G_OBJECT (image));
Havoc Pennington's avatar
Havoc Pennington committed
1226 1227
  
  if (animation)
Manish Singh's avatar
Manish Singh committed
1228
    g_object_ref (animation);
Havoc Pennington's avatar
Havoc Pennington committed
1229

1230
  gtk_image_clear (image);
Havoc Pennington's avatar
Havoc Pennington committed
1231 1232 1233

  if (animation != NULL)
    {
1234 1235
      _gtk_icon_helper_set_animation (priv->icon_helper, animation);
      g_object_unref (animation);
Havoc Pennington's avatar
Havoc Pennington committed
1236
    }
Havoc Pennington's avatar
Havoc Pennington committed
1237

1238 1239
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_PIXBUF_ANIMATION]);

Havoc Pennington's avatar
Havoc Pennington committed
1240
  g_object_thaw_notify (G_OBJECT (image));
Havoc Pennington's avatar
Havoc Pennington committed
1241 1242
}

1243 1244 1245
/**
 * gtk_image_set_from_icon_name:
 * @image: a #GtkImage
1246
 * @icon_name: (nullable): an icon name or %NULL
1247
 * @size: (type int): an icon size (#GtkIconSize)
1248 1249 1250 1251 1252 1253 1254 1255 1256 1257
 *
 * See gtk_image_new_from_icon_name() for details.
 * 
 * Since: 2.6
 **/
void
gtk_image_set_from_icon_name  (GtkImage       *image,
			       const gchar    *icon_name,
			       GtkIconSize     size)
{
1258
  GtkImagePrivate *priv;
1259

1260 1261
  g_return_if_fail (GTK_IS_IMAGE (image));

1262 1263
  priv = image->priv;

1264 1265
  g_object_freeze_notify (G_OBJECT (image));

1266
  gtk_image_clear (image);
1267

1268 1269
  if (icon_name)
    _gtk_icon_helper_set_icon_name (priv->icon_helper, icon_name, size);
1270

1271 1272
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_ICON_NAME]);
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_ICON_SIZE]);
1273

1274 1275 1276
  g_object_thaw_notify (G_OBJECT (image));
}

1277 1278 1279 1280
/**
 * gtk_image_set_from_gicon:
 * @image: a #GtkImage
 * @icon: an icon
1281
 * @size: (type int): an icon size (#GtkIconSize)
1282 1283 1284 1285 1286 1287 1288 1289 1290 1291
 *
 * See gtk_image_new_from_gicon() for details.
 * 
 * Since: 2.14
 **/
void
gtk_image_set_from_gicon  (GtkImage       *image,
			   GIcon          *icon,
			   GtkIconSize     size)
{
1292
  GtkImagePrivate *priv;
1293

1294 1295
  g_return_if_fail (GTK_IS_IMAGE (image));

1296 1297
  priv = image->priv;

1298 1299 1300 1301
  g_object_freeze_notify (G_OBJECT (image));

  if (icon)
    g_object_ref (icon);
1302

1303
  gtk_image_clear (image);
1304 1305 1306

  if (icon)
    {
1307 1308
      _gtk_icon_helper_set_gicon (priv->icon_helper, icon, size);
      g_object_unref (icon);
1309 1310
    }

1311 1312
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_GICON]);
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_ICON_SIZE]);
1313
  
1314 1315 1316
  g_object_thaw_notify (G_OBJECT (image));
}

1317 1318 1319
/**
 * gtk_image_set_from_surface:
 * @image: a #GtkImage
1320
 * @surface: (nullable): a cairo_surface_t or %NULL
1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340
 *
 * See gtk_image_new_from_surface() for details.
 * 
 * Since: 3.10
 **/
void
gtk_image_set_from_surface (GtkImage       *image,
			    cairo_surface_t *surface)
{
  GtkImagePrivate *priv;

  g_return_if_fail (GTK_IS_IMAGE (image));

  priv = image->priv;

  g_object_freeze_notify (G_OBJECT (image));

  if (surface)
    cairo_surface_reference (surface);

1341
  gtk_image_clear (image);
1342 1343 1344 1345 1346 1347 1348

  if (surface)
    {
      _gtk_icon_helper_set_surface (priv->icon_helper, surface);
      cairo_surface_destroy (surface);
    }

1349
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_SURFACE]);
1350
  
1351 1352 1353
  g_object_thaw_notify (G_OBJECT (image));
}

1354 1355 1356 1357 1358 1359 1360 1361
/**
 * gtk_image_get_storage_type:
 * @image: a #GtkImage
 * 
 * Gets the type of representation being used by the #GtkImage
 * to store image data. If the #GtkImage has no image data,
 * the return value will be %GTK_IMAGE_EMPTY.
 * 
1362
 * Returns: image representation being used
1363
 **/
1364 1365 1366 1367 1368
GtkImageType
gtk_image_get_storage_type (GtkImage *image)
{
  g_return_val_if_fail (GTK_IS_IMAGE (image), GTK_IMAGE_EMPTY);

1369
  return _gtk_icon_helper_get_storage_type (image->priv->icon_helper);
1370 1371
}

1372 1373 1374 1375 1376 1377 1378 1379 1380 1381
/**
 * gtk_image_get_pixbuf:
 * @image: a #GtkImage
 *
 * Gets the #GdkPixbuf being displayed by the #GtkImage.
 * The storage type of the image must be %GTK_IMAGE_EMPTY or
 * %GTK_IMAGE_PIXBUF (see gtk_image_get_storage_type()).
 * The caller of this function does not own a reference to the
 * returned pixbuf.
 * 
1382
 * Returns: (nullable) (transfer none): the displayed pixbuf, or %NULL if
1383
 * the image is empty
1384
 **/
1385 1386 1387 1388 1389
GdkPixbuf*
gtk_image_get_pixbuf (GtkImage *image)
{
  g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);

1390
  return _gtk_icon_helper_peek_pixbuf (image->priv->icon_helper);
1391 1392
}

1393 1394 1395
/**
 * gtk_image_get_stock:
 * @image: a #GtkImage
1396 1397
 * @stock_id: (out) (transfer none) (allow-none): place to store a
 *     stock icon name, or %NULL
1398
 * @size: (out) (allow-none) (type int): place to store a stock icon
1399
 *     size (#GtkIconSize), or %NULL
1400 1401 1402 1403
 *
 * Gets the stock icon name and size being displayed by the #GtkImage.
 * The storage type of the image must be %GTK_IMAGE_EMPTY or
 * %GTK_IMAGE_STOCK (see gtk_image_get_storage_type()).
1404
 * The returned string is owned by the #GtkImage and should not
1405
 * be freed.
1406 1407
 *
 * Deprecated: 3.10: Use gtk_image_get_icon_name() instead.