comparison pidgin/gtkimhtml.c @ 18089:1f6599cd2d2b

When an animated image is inserted into a conversation window, animate it. Fixes #912.
author Mark Doliner <mark@kingant.net>
date Mon, 11 Jun 2007 07:48:49 +0000
parents 6f7f54765822
children 40d51793f2d7
comparison
equal deleted inserted replaced
18088:c138916a49b3 18089:1f6599cd2d2b
3163 3163
3164 /* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */ 3164 /* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */
3165 GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id) 3165 GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id)
3166 { 3166 {
3167 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); 3167 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage));
3168 GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixbuf(img));
3169 3168
3170 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; 3169 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale;
3171 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; 3170 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to;
3172 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free; 3171 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free;
3173 3172
3174 im_image->pixbuf = img; 3173 im_image->pixbuf = img;
3175 im_image->image = image; 3174 im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf));
3176 im_image->width = gdk_pixbuf_get_width(img); 3175 im_image->width = gdk_pixbuf_get_width(img);
3177 im_image->height = gdk_pixbuf_get_height(img); 3176 im_image->height = gdk_pixbuf_get_height(img);
3178 im_image->mark = NULL; 3177 im_image->mark = NULL;
3179 im_image->filename = g_strdup(filename); 3178 im_image->filename = g_strdup(filename);
3180 im_image->id = id; 3179 im_image->id = id;
3181 im_image->filesel = NULL; 3180 im_image->filesel = NULL;
3182 3181
3183 g_object_ref(img); 3182 g_object_ref(img);
3183 return GTK_IMHTML_SCALABLE(im_image);
3184 }
3185
3186 static gboolean
3187 animate_image_cb(gpointer data)
3188 {
3189 GtkIMHtmlImage *im_image;
3190 int width, height;
3191 int delay;
3192
3193 im_image = data;
3194
3195 /* Update the pointer to this GdkPixbuf frame of the animation */
3196 g_object_unref(G_OBJECT(im_image->pixbuf));
3197 gdk_pixbuf_animation_iter_advance(GTK_IMHTML_ANIMATION(im_image)->iter, NULL);
3198 im_image->pixbuf = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter);
3199 g_object_ref(G_OBJECT(im_image->pixbuf));
3200
3201 /* Update the displayed GtkImage */
3202 width = gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image));
3203 height = gdk_pixbuf_get_height(gtk_image_get_pixbuf(im_image->image));
3204 if (width > 0 && height > 0)
3205 {
3206 /* Need to scale the new frame to the same size as the old frame */
3207 GdkPixbuf *tmp;
3208 tmp = gdk_pixbuf_scale_simple(im_image->pixbuf, width, height, GDK_INTERP_BILINEAR);
3209 gtk_image_set_from_pixbuf(im_image->image, tmp);
3210 g_object_unref(G_OBJECT(tmp));
3211 } else {
3212 /* Display at full-size */
3213 gtk_image_set_from_pixbuf(im_image->image, im_image->pixbuf);
3214 }
3215
3216 delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100);
3217 GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image);
3218
3219 return FALSE;
3220 }
3221
3222 GtkIMHtmlScalable *gtk_imhtml_animation_new(GdkPixbufAnimation *anim, const gchar *filename, int id)
3223 {
3224 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlAnimation));
3225
3226 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale;
3227 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to;
3228 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_animation_free;
3229
3230 GTK_IMHTML_ANIMATION(im_image)->anim = anim;
3231 if (gdk_pixbuf_animation_is_static_image(anim)) {
3232 GTK_IMHTML_ANIMATION(im_image)->iter = NULL;
3233 im_image->pixbuf = gdk_pixbuf_animation_get_static_image(anim);
3234 GTK_IMHTML_ANIMATION(im_image)->timer = 0;
3235 } else {
3236 int delay;
3237 GTK_IMHTML_ANIMATION(im_image)->iter = gdk_pixbuf_animation_get_iter(anim, NULL);
3238 im_image->pixbuf = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter);
3239 delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100);
3240 GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image);
3241 }
3242 im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf));
3243 im_image->width = gdk_pixbuf_animation_get_width(anim);
3244 im_image->height = gdk_pixbuf_animation_get_height(anim);
3245 im_image->mark = NULL;
3246 im_image->filename = g_strdup(filename);
3247 im_image->id = id;
3248 im_image->filesel = NULL;
3249
3250 g_object_ref(anim);
3251 g_object_ref(im_image->pixbuf);
3252
3184 return GTK_IMHTML_SCALABLE(im_image); 3253 return GTK_IMHTML_SCALABLE(im_image);
3185 } 3254 }
3186 3255
3187 void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height) 3256 void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height)
3188 { 3257 {
3440 } 3509 }
3441 3510
3442 static gboolean gtk_imhtml_smiley_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlSmiley *smiley) 3511 static gboolean gtk_imhtml_smiley_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlSmiley *smiley)
3443 { 3512 {
3444 GdkPixbufAnimation *anim = NULL; 3513 GdkPixbufAnimation *anim = NULL;
3445 GdkPixbuf *pix = NULL;
3446 GtkIMHtmlScalable *image = NULL; 3514 GtkIMHtmlScalable *image = NULL;
3447 gboolean ret; 3515 gboolean ret;
3448 3516
3449 if (event->type != GDK_BUTTON_RELEASE || ((GdkEventButton*)event)->button != 3) 3517 if (event->type != GDK_BUTTON_RELEASE || ((GdkEventButton*)event)->button != 3)
3450 return FALSE; 3518 return FALSE;
3451 3519
3452 anim = gtk_smiley_get_image(smiley); 3520 anim = gtk_smiley_get_image(smiley);
3453 if (!anim) 3521 if (!anim)
3454 return FALSE; 3522 return FALSE;
3455 3523
3456 pix = gdk_pixbuf_animation_get_static_image(anim); 3524 image = gtk_imhtml_animation_new(anim, smiley->smile, 0);
3457 image = gtk_imhtml_image_new(pix, smiley->smile, 0);
3458 ret = gtk_imhtml_image_clicked(w, event, (GtkIMHtmlImage*)image); 3525 ret = gtk_imhtml_image_clicked(w, event, (GtkIMHtmlImage*)image);
3459 g_object_set_data_full(G_OBJECT(w), "image-data", image, (GDestroyNotify)gtk_imhtml_image_free); 3526 g_object_set_data_full(G_OBJECT(w), "image-data", image, (GDestroyNotify)gtk_imhtml_image_free);
3460 g_object_unref(G_OBJECT(pix));
3461 return ret; 3527 return ret;
3462 } 3528 }
3463 3529
3464 void gtk_imhtml_image_free(GtkIMHtmlScalable *scale) 3530 void gtk_imhtml_image_free(GtkIMHtmlScalable *scale)
3465 { 3531 {
3468 g_object_unref(image->pixbuf); 3534 g_object_unref(image->pixbuf);
3469 g_free(image->filename); 3535 g_free(image->filename);
3470 if (image->filesel) 3536 if (image->filesel)
3471 gtk_widget_destroy(image->filesel); 3537 gtk_widget_destroy(image->filesel);
3472 g_free(scale); 3538 g_free(scale);
3539 }
3540
3541 void gtk_imhtml_animation_free(GtkIMHtmlScalable *scale)
3542 {
3543 GtkIMHtmlAnimation *animation = (GtkIMHtmlAnimation *)scale;
3544
3545 if (animation->timer > 0)
3546 g_source_remove(animation->timer);
3547 if (animation->iter != NULL)
3548 g_object_unref(animation->iter);
3549 g_object_unref(animation->anim);
3550
3551 gtk_imhtml_image_free(scale);
3473 } 3552 }
3474 3553
3475 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) 3554 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter)
3476 { 3555 {
3477 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; 3556 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale;
4550 g_free(unescaped); 4629 g_free(unescaped);
4551 } 4630 }
4552 4631
4553 void gtk_imhtml_insert_image_at_iter(GtkIMHtml *imhtml, int id, GtkTextIter *iter) 4632 void gtk_imhtml_insert_image_at_iter(GtkIMHtml *imhtml, int id, GtkTextIter *iter)
4554 { 4633 {
4555 GdkPixbuf *pixbuf = NULL; 4634 GdkPixbufAnimation *anim = NULL;
4556 const char *filename = NULL; 4635 const char *filename = NULL;
4557 gpointer image; 4636 gpointer image;
4558 GdkRectangle rect; 4637 GdkRectangle rect;
4559 GtkIMHtmlScalable *scalable = NULL; 4638 GtkIMHtmlScalable *scalable = NULL;
4560 struct scalable_data *sd; 4639 struct scalable_data *sd;
4577 4656
4578 if (data && len) { 4657 if (data && len) {
4579 GdkPixbufLoader *loader = gdk_pixbuf_loader_new(); 4658 GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
4580 gdk_pixbuf_loader_write(loader, data, len, NULL); 4659 gdk_pixbuf_loader_write(loader, data, len, NULL);
4581 gdk_pixbuf_loader_close(loader, NULL); 4660 gdk_pixbuf_loader_close(loader, NULL);
4582 pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); 4661 anim = gdk_pixbuf_loader_get_animation(loader);
4583 if (pixbuf) 4662 if (anim)
4584 g_object_ref(G_OBJECT(pixbuf)); 4663 g_object_ref(G_OBJECT(anim));
4585 g_object_unref(G_OBJECT(loader)); 4664 g_object_unref(G_OBJECT(loader));
4586 } 4665 }
4587 4666
4588 } 4667 }
4589 4668
4590 if (pixbuf) { 4669 if (anim) {
4591 struct im_image_data *t = g_new(struct im_image_data, 1); 4670 struct im_image_data *t = g_new(struct im_image_data, 1);
4592 filename = imhtml->funcs->image_get_filename(image); 4671 filename = imhtml->funcs->image_get_filename(image);
4593 imhtml->funcs->image_ref(id); 4672 imhtml->funcs->image_ref(id);
4594 t->id = id; 4673 t->id = id;
4595 t->mark = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, iter, TRUE); 4674 t->mark = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, iter, TRUE);
4596 imhtml->im_images = g_slist_prepend(imhtml->im_images, t); 4675 imhtml->im_images = g_slist_prepend(imhtml->im_images, t);
4676 scalable = gtk_imhtml_animation_new(anim, filename, id);
4677 g_object_unref(G_OBJECT(anim));
4597 } else { 4678 } else {
4679 GdkPixbuf *pixbuf;
4598 pixbuf = gtk_widget_render_icon(GTK_WIDGET(imhtml), GTK_STOCK_MISSING_IMAGE, 4680 pixbuf = gtk_widget_render_icon(GTK_WIDGET(imhtml), GTK_STOCK_MISSING_IMAGE,
4599 GTK_ICON_SIZE_BUTTON, "gtkimhtml-missing-image"); 4681 GTK_ICON_SIZE_BUTTON, "gtkimhtml-missing-image");
4682 scalable = gtk_imhtml_image_new(pixbuf, filename, id);
4683 g_object_unref(G_OBJECT(pixbuf));
4600 } 4684 }
4601 4685
4602 sd = g_new(struct scalable_data, 1); 4686 sd = g_new(struct scalable_data, 1);
4603 sd->scalable = scalable = gtk_imhtml_image_new(pixbuf, filename, id); 4687 sd->scalable = scalable;
4604 sd->mark = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, iter, TRUE); 4688 sd->mark = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, iter, TRUE);
4605 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); 4689 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect);
4606 scalable->add_to(scalable, imhtml, iter); 4690 scalable->add_to(scalable, imhtml, iter);
4607 minus = gtk_text_view_get_left_margin(GTK_TEXT_VIEW(imhtml)) + 4691 minus = gtk_text_view_get_left_margin(GTK_TEXT_VIEW(imhtml)) +
4608 gtk_text_view_get_right_margin(GTK_TEXT_VIEW(imhtml)); 4692 gtk_text_view_get_right_margin(GTK_TEXT_VIEW(imhtml));
4609 scalable->scale(scalable, rect.width - minus, rect.height); 4693 scalable->scale(scalable, rect.width - minus, rect.height);
4610 imhtml->scalables = g_list_append(imhtml->scalables, sd); 4694 imhtml->scalables = g_list_append(imhtml->scalables, sd);
4611
4612 g_object_unref(G_OBJECT(pixbuf));
4613 } 4695 }
4614 4696
4615 static const gchar *tag_to_html_start(GtkTextTag *tag) 4697 static const gchar *tag_to_html_start(GtkTextTag *tag)
4616 { 4698 {
4617 const gchar *name; 4699 const gchar *name;