8 #include <yui/Libyui_config.h>
9 #include "ygdkmngloader.h"
10 #include "ygtkimage.h"
13 G_DEFINE_TYPE (
YGtkImage, ygtk_image, GTK_TYPE_DRAWING_AREA)
15 static
void ygtk_image_init (
YGtkImage *image)
19 static void ygtk_image_free_pixbuf (
YGtkImage *image)
21 if (image->animated) {
22 if (image->animation) {
23 g_object_unref (G_OBJECT (image->animation->pixbuf));
24 if (image->animation->timeout_id)
25 g_source_remove (image->animation->timeout_id);
26 g_free (image->animation);
27 image->animation = NULL;
32 g_object_unref (G_OBJECT (image->pixbuf));
38 static void ygtk_image_destroy (GtkWidget *widget)
42 g_free (image->alt_text);
43 image->alt_text = NULL;
44 ygtk_image_free_pixbuf (image);
45 GTK_WIDGET_CLASS (ygtk_image_parent_class)->destroy (widget);
48 static void ygtk_image_set_pixbuf (
YGtkImage *image, GdkPixbuf *pixbuf,
const char *error_msg)
50 ygtk_image_free_pixbuf (image);
51 gtk_widget_queue_resize (GTK_WIDGET (image));
54 image->animated = FALSE;
55 image->pixbuf = pixbuf;
62 static gboolean ygtk_image_advance_frame_cb (gpointer data)
67 if (!animation->frame)
68 animation->frame = gdk_pixbuf_animation_get_iter (animation->pixbuf, NULL);
70 if (gdk_pixbuf_animation_iter_advance (animation->frame, NULL))
71 gtk_widget_queue_draw (GTK_WIDGET (image));
74 int delay = gdk_pixbuf_animation_iter_get_delay_time (animation->frame);
76 animation->timeout_id = g_timeout_add (delay, ygtk_image_advance_frame_cb, data);
80 static void ygtk_image_set_animation (
YGtkImage *image, GdkPixbufAnimation *pixbuf,
81 const char *error_msg)
83 ygtk_image_free_pixbuf (image);
84 gtk_widget_queue_resize (GTK_WIDGET (image));
87 image->animated = TRUE;
89 image->animation->pixbuf = pixbuf;
91 ygtk_image_advance_frame_cb (image);
94 g_warning (
"Couldn't load image - %s", error_msg);
97 void ygtk_image_set_from_file (
YGtkImage *image,
const char *filename, gboolean anim)
101 GdkPixbufAnimation *pixbuf;
102 if (ygdk_mng_pixbuf_is_file_mng (filename))
103 pixbuf = ygdk_mng_pixbuf_new_from_file (filename, &error);
105 pixbuf = gdk_pixbuf_animation_new_from_file (filename, &error);
106 ygtk_image_set_animation (image, pixbuf, error ? error->message :
"(undefined)");
109 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (filename, &error);
110 ygtk_image_set_pixbuf (image, pixbuf, error ? error->message :
"(undefined)");
114 void ygtk_image_set_from_pixbuf (
YGtkImage *image, GdkPixbuf *pixbuf)
116 ygtk_image_set_pixbuf (image, pixbuf, NULL);
119 static void ygtk_image_loaded_cb (GdkPixbufLoader *loader,
YGtkImage *image)
121 if (image->animated) {
122 if (image->animation) {
124 if (gdk_pixbuf_animation_iter_on_currently_loading_frame
125 (image->animation->frame))
126 gtk_widget_queue_draw (GTK_WIDGET (image));
129 GdkPixbufAnimation *pixbuf = gdk_pixbuf_loader_get_animation (loader);
130 g_object_ref (G_OBJECT (pixbuf));
131 ygtk_image_set_animation (image, pixbuf,
"on block data reading callback");
135 GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
136 g_object_ref (G_OBJECT (pixbuf));
137 ygtk_image_set_pixbuf (image, pixbuf,
"on block data reading callback");
141 void ygtk_image_set_from_data (
YGtkImage *image,
const guint8 *data,
long data_size, gboolean anim)
144 if (anim && ygdk_mng_pixbuf_is_data_mng (data, data_size)) {
145 GdkPixbufAnimation *pixbuf;
146 pixbuf = ygdk_mng_pixbuf_new_from_data (data, data_size, &error);
147 ygtk_image_set_animation (image, pixbuf, error ? error->message :
"(undefined)");
150 image->animated = anim;
151 GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
152 g_signal_connect (G_OBJECT (loader),
"area-prepared",
153 G_CALLBACK (ygtk_image_loaded_cb), image);
154 if (!gdk_pixbuf_loader_write (loader, data, data_size, &error))
155 g_warning (
"Could not load image from data blocks: %s", error->message);
156 gdk_pixbuf_loader_close (loader, &error);
160 void ygtk_image_set_props (
YGtkImage *image, YGtkImageAlign align,
const gchar *alt_text)
162 image->align = align;
164 g_free (image->alt_text);
166 image->alt_text = g_strdup (alt_text);
167 gtk_widget_queue_draw (GTK_WIDGET (image));
170 static void ygtk_image_size_request (GtkWidget *widget, GtkRequisition *requisition)
173 int width = 0, height = 0;
175 if (image->animated) {
176 width = gdk_pixbuf_animation_get_width (image->animation->pixbuf);
177 height = gdk_pixbuf_animation_get_height (image->animation->pixbuf);
180 width = gdk_pixbuf_get_width (image->pixbuf);
181 height = gdk_pixbuf_get_height (image->pixbuf);
184 else if (image->alt_text) {
186 layout = gtk_widget_create_pango_layout (widget, image->alt_text);
187 pango_layout_get_pixel_size (layout, &width, &height);
189 requisition->width = width;
190 requisition->height = height;
194 ygtk_image_get_preferred_width (GtkWidget *widget,
198 GtkRequisition requisition;
199 ygtk_image_size_request (widget, &requisition);
200 *minimal_width = *natural_width = requisition.width;
204 ygtk_image_get_preferred_height (GtkWidget *widget,
205 gint *minimal_height,
206 gint *natural_height)
208 GtkRequisition requisition;
209 ygtk_image_size_request (widget, &requisition);
210 *minimal_height = *natural_height = requisition.height;
213 static gboolean ygtk_image_draw_event (GtkWidget *widget, cairo_t *cr)
218 gtk_widget_get_preferred_size (widget, &req, NULL);
219 int width = gtk_widget_get_allocated_width(widget);
220 int height = gtk_widget_get_allocated_height(widget);
222 if (!image->loaded) {
223 if (image->alt_text) {
226 layout = gtk_widget_create_pango_layout (widget, image->alt_text);
229 x = (width - req.width) / 2;
230 y = (height - req.height) / 2;
232 cairo_move_to (cr, x, y);
233 pango_cairo_show_layout (cr, layout);
235 g_object_unref (layout);
242 pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (image->animation->frame);
244 pixbuf = image->pixbuf;
247 if (image->align == CENTER_IMAGE_ALIGN) {
248 x = (width - req.width) / 2;
249 y = (height - req.height) / 2;
252 gdk_cairo_set_source_pixbuf (cr, pixbuf, x, y);
254 switch (image->align) {
255 case CENTER_IMAGE_ALIGN:
257 case SCALE_IMAGE_ALIGN:
259 double scale_x = (double) gdk_pixbuf_get_width (pixbuf) / width;
260 double scale_y = (double) gdk_pixbuf_get_height (pixbuf) / height;
261 cairo_matrix_t matrix;
262 cairo_matrix_init_scale (&matrix, scale_x, scale_y);
263 cairo_pattern_set_matrix (cairo_get_source (cr), &matrix);
266 case TILE_IMAGE_ALIGN:
267 cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
271 cairo_rectangle (cr, x, y, width, height);
277 static void ygtk_image_state_flags_changed (GtkWidget *widget, GtkStateFlags old_flags)
280 gtk_widget_queue_draw (widget);
283 GtkWidget* ygtk_image_new (
void)
285 return g_object_new (YGTK_TYPE_IMAGE, NULL);
290 GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
291 widget_class->draw = ygtk_image_draw_event;
292 widget_class->get_preferred_width = ygtk_image_get_preferred_width;
293 widget_class->get_preferred_height = ygtk_image_get_preferred_height;
294 widget_class->destroy = ygtk_image_destroy;
295 widget_class->state_flags_changed = ygtk_image_state_flags_changed;