Mercurial > pidgin.yaz
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; |