Re: [evolution-patches] Patch to resize images
- From: Srinivasa Ragavan <sragavan novell com>
- To: Not Zed <notzed novell com>
- Cc: evolution-patches lists ximian com
- Subject: Re: [evolution-patches] Patch to resize images
- Date: Mon, 27 Jun 2005 15:27:58 +0530
Hah, I hope i have worked on most of the comments...
- I have reused em-icon-stream
- Using my own puri
- Fixed Object hierarchy issue
- reduced the complexity of the resize function
- Closed most of the memory leaks
-Srini.
On Fri, 2005-06-24 at 12:33 +0800, Not Zed wrote:
> On Thu, 2005-06-23 at 15:47 +0530, Srinivasa Ragavan wrote:
> > +++ em-image-stream.c 2005-06-23 10:18:05.000000000 +0530
>
> Instead of copying em-icon-stream and making minor changes, can't you
> just re-use em-icon-stream directly? All you really need to do is add
> an api to say how big you want the image and whether to keep the
> original sized image around as well.
>
> > message-list.h \
> > - mail-vfolder.h
> > + mail-vfolder.h \
> > + em-image-stream.h
>
> It shouldn't be needed anymore, but for future reference add new files
> to these lists in alphabetic order.
>
> > +{
> > + struct _attach_puri *info = data;
> > + GdkPixbuf *tmp;
> > +
> > + if (info->image) {
> > + /* Swap the alt pixbuf and the current pixbuf of the
> > shown GtkImage */
> > + tmp = g_object_steal_data (info->image, "alt-image");
> > + g_object_set_data_full (info->image, "alt-image",
> > gtk_image_get_pixbuf (info->image), g_object_unref);
> > + gtk_image_set_from_pixbuf (info->image, tmp);
> > + info->size = ~info->size;
> > + gtk_widget_show (info->image);
> > + }
>
> I'm not sure you want to pass all these pixbufs around. Once you've
> made the image, and you no longer need to manipulate it, you should be
> using pixmaps. Anyway, if you change emiconstream slightly all this
> messy stealing stuff can be done away with and you can just get the
> normal or resized image from there.
>
> > +static void
> > +efhd_image_resize_callback (GtkWidget *w, GtkAllocation *event,
> > struct _attach_puri *info)
> > +{
>
> This function seems awfully complicated. All you need to do is: work
> out if you need to resize, what the new size is, calculate the new
> image. It seems to do all this work 2 or 4 times.
>
> Also, no need to pass all this g_object_set rubbish around - you already
> have an object under your control, the puri, so put stuff you need in
> there.
>
> > + GdkPixbuf *original, *reduced, *shrunk;
> > + int new_width = ((GtkWidget *)((EMFormatHTML
> > *)info->puri.format)->html)->allocation.width;
> > + int width, height;
> > + float ratio;
> > +
> > + new_width = new_width * 95 / 100;
> > +
> > + if (g_object_get_data (info->image, "re-sized")) {
> > + /* It is a resized image */
> > + width = g_object_get_data (info->image,
> > "original-width");
> > + height = g_object_get_data (info->image,
> > "original-height");
> > + ratio = (float)width / (float) new_width;
> > +
> > + if (new_width > width) {
> > + /* If the window size go beyond the image
> > size, lets not resize any more */
> > + if (info->size) {
> > + /* Restore the original image */
> > + original = gdk_pixbuf_copy
> > (g_object_get_data (info->image, "alt-image"));
> > + gtk_image_set_from_pixbuf
> > (info->image, original);
> > + }
> > + g_object_set_data (info->image, "re-sized",
> > 0);
> > + return;
> > + }
> > +
> > + width = new_width;
> > + height = (int) (height/ratio);
>
> This calculation is more accurately done as:
> height = height * new_width / width;
> (although you have to be careful of overflows, or cast to floats).
>
> > + /* To keep the quality of image, we always resize from
> > the original image */
> > + if (info->size) {
> > + /* Original is the alt image */
> > + original = gdk_pixbuf_copy (g_object_get_data
> > (info->image, "alt-image"));
> > + reduced = gtk_image_get_pixbuf (info->image);
> > + } else {
> > + /* The original image is only shown */
> > + original = gtk_image_get_pixbuf (info->image);
> > + reduced = gdk_pixbuf_copy (g_object_get_data
> > (info->image, "alt-image"));
> > + }
> > +
> > + /* Dont resize, if the reduced size is equal to the
> > available width */
> > + if (gdk_pixbuf_get_width(reduced) == new_width) {
> > + return;
> > + }
> > +
> > +#ifdef HAVE_LIBGNOMEUI_GNOME_THUMBNAIL_H
> > + shrunk = gnome_thumbnail_scale_down_pixbuf (original,
> > width, height);
> > +#else
> > + shrunk = gdk_pixbuf_scale_simple(original, width,
> > height, GDK_INTERP_BILINEAR);
> > +#endif
> > +
> > + if (info->size) {
> > + gtk_image_set_from_pixbuf (info->image,
> > shrunk);
> > + if (info->shown)
> > + gtk_widget_show (info->image);
> > + else
> > + gtk_widget_hide (info->image);
> > + } else {
> > + g_object_set_data_full (info->image,
> > "alt-image", shrunk, g_object_unref);
> > + g_object_unref (reduced);
> > + }
> > +
> > + } else {
> > + /* Time to shrink the image and store it
> > + * It is also possible that the image size is smaller
> > than the window size, when the window
> > + * is expanded too much.
> > + */
> > +
> > + original = gtk_image_get_pixbuf (info->image);
> > + if (!original)
> > + return;
> > + width = gdk_pixbuf_get_width(original);
> > + height = gdk_pixbuf_get_height(original);
> > + if (width <= new_width)
> > + return;
> > +
> > + g_object_set_data (info->image, "re-sized", 1);
> > +
> > + /* Check of it is already an altered image */
> > + if (!g_object_get_data (info->image, "alt-image"))
> > + info->size = 1;
> > +
> > + if (info->size) { /* Ok. We are resizing for the first
> > time */
> > + g_object_set_data_full (info->image,
> > "alt-image", original, g_object_unref);
> > + g_object_set_data (info->image,
> > "original-width", width);
> > + g_object_set_data (info->image,
> > "original-height", height);
> > + reduced = gdk_pixbuf_copy
> > (original);
> > + shrunk = gdk_pixbuf_scale_simple (reduced,
> > width, height, GDK_INTERP_BILINEAR);
> > + gtk_image_set_from_pixbuf (info->image,
> > shrunk);
> > + }
> > + }
> > +
> > +}
> > +
> > +static gboolean
> > +efhd_attachment_image (EMFormatHTML *efh, GtkHTMLEmbedded *eb,
> > EMFormatHTMLPObject *pobject)
> > +{
> > + GtkWidget *box;
> > + EMFormatHTMLJob *job;
> > + struct _attach_puri *info;
> > + GtkTargetEntry drag_types[] = {
> > + { NULL, 0, 0 },
> > + { "text/uri-list", 0, 1 },
> > + };
> > + char *simple_type;
> > + int width = ((GtkWidget *)efh->html)->allocation.width * 95 /
> > 100;
> > +
> > + /* FIXME: Dirty hack to get the part-id */
> > + info = em_format_find_puri(efh, g_strdup_printf("attachment%
> > s", &(pobject->classid[5])));
>
> Umm, memory leak?
>
> You can't steal someone elses 'pobject' and start using it as your own.
> That is the one for the attachment bar, not for your use as an attachee.
>
> You need to create your own info and use that. The same way the
> attachment bar does.
>
> > + info->image = gtk_image_new();
> > + job = em_format_html_job_new(efh, efhd_write_icon_job,
> > pobject);
> > + job->stream = (CamelStream *)em_image_stream_new((GtkImage
> > *)info->image, pobject->classid, width);
> > + em_format_html_job_queue(efh, job);
> > +
> > + box = gtk_event_box_new ();
> > + gtk_container_add ((GtkContainer *) box, info->image);
> > + gtk_widget_show_all (box);
> > + gtk_container_add ((GtkContainer *) eb, box);
> > +
> > + /* By default fit to width*/
> > + info->size = 1;
> > +
> > + g_signal_connect (eb, "size_allocate",
> > G_CALLBACK(efhd_image_resize_callback), info);
> > +
> > + simple_type = camel_content_type_simple (((CamelDataWrapper
> > *)pobject->part)->mime_type);
> > + camel_strdown(simple_type);
> > +
> > + drag_types[0].target = simple_type;
> > + gtk_drag_source_set(box, GDK_BUTTON1_MASK, drag_types,
> > sizeof(drag_types)/sizeof(drag_types[0]), GDK_ACTION_COPY);
> > +
> > + g_signal_connect(box, "drag-data-get",
> > G_CALLBACK(efhd_drag_data_get), pobject);
> > + g_signal_connect (box, "drag-data-delete",
> > G_CALLBACK(efhd_drag_data_delete), pobject);
> > +
> > + g_signal_connect(box, "button_press_event",
> > G_CALLBACK(efhd_image_popup), info);
> > + g_signal_connect(box, "popup_menu",
> > G_CALLBACK(efhd_attachment_popup_menu), info);
> > + return TRUE;
> > +}
> > +
> > +void
> > +em_format_html_display_handle_image (EMFormatHTML *efh, CamelStream
> > *stream, CamelMimePart *part, EMFormatHandler *info)
> > +{
> > + char *classid;
> > +
> > + classid = g_strdup_printf("image%s", ((EMFormat
> > *)efh)->part_id->str);
> > + em_format_html_add_pobject(efh, sizeof(EMFormatHTMLPObject),
> > classid, part, efhd_attachment_image);
>
>
> As above, you need to create your own puri (which can contain all the
> fields you're currently object get/setting) and reference that.
>
> And uh, clean up your memory. There shouldn't be so many obvious memory
> leaks in patches by now, even preliminary ones like this.
>
> > + camel_stream_printf(stream, "<td><object classid=\"%s
> > \"></object></td>", classid);
> > }
> >
> > static void
> > Index: em-format-html-display.h
> > ===================================================================
> > RCS file: /cvs/gnome/evolution/mail/em-format-html-display.h,v
> > retrieving revision 1.5
> > diff -u -r1.5 em-format-html-display.h
> > --- em-format-html-display.h 16 May 2005 07:53:53 -0000 1.5
> > +++ em-format-html-display.h 23 Jun 2005 09:19:20 -0000
> > @@ -58,6 +58,8 @@
> > void em_format_html_display_zoom_out (EMFormatHTMLDisplay *efhd);
> > void em_format_html_display_zoom_reset (EMFormatHTMLDisplay *efhd);
> >
> > +void em_format_html_display_handle_image (EMFormatHTML *efh,
> > CamelStream *stream, CamelMimePart *part, EMFormatHandler *info);
>
> This is internal DO NOT EXPORT IT. Its use is already provided by the
> object, subclasses already inherit that behaviour, and parent
> classes ... well, ... uh.
>
> > gboolean em_format_html_display_popup_menu (EMFormatHTMLDisplay
> > *efhd);
> >
> > /* experimental */
> > Index: em-format-html.c
> > ===================================================================
> > RCS file: /cvs/gnome/evolution/mail/em-format-html.c,v
> > retrieving revision 1.78
> > diff -u -r1.78 em-format-html.c
> > --- em-format-html.c 19 May 2005 06:06:35 -0000 1.78
> > +++ em-format-html.c 23 Jun 2005 09:19:20 -0000
> > @@ -65,6 +65,7 @@
> > #include "mail-mt.h"
> >
> > #include "em-format-html.h"
> > +#include "em-format-html-display.h"
> > #include "em-html-stream.h"
> > #include "em-utils.h"
>
> Oh my god!!!!! NO!!!!!!!
>
> You CANNOT include em-format-html-display stuff in em-format-html! This
> is a sub-class relationship and it is STRICTLY forbidden to break this
> abstraction boundary in the wrong direction.
>
> I shouldn't need to explain why this is so completely and obviously
> wrong - it is *utterly* *basic* object design.
>
> >
> > @@ -1075,22 +1076,23 @@
> > camel_stream_printf(stream, "<img hspace=10 vspace=10 src=\"%s
> > \">", puri->cid);
> > }
> >
> > +
> > static EMFormatHandler type_builtin_table[] = {
> > - { "image/gif", (EMFormatFunc)efh_image },
> > - { "image/jpeg", (EMFormatFunc)efh_image },
> > - { "image/png", (EMFormatFunc)efh_image },
> > - { "image/x-png", (EMFormatFunc)efh_image },
> > - { "image/tiff", (EMFormatFunc)efh_image },
> > - { "image/x-bmp", (EMFormatFunc)efh_image },
> > - { "image/bmp", (EMFormatFunc)efh_image },
> > - { "image/svg", (EMFormatFunc)efh_image },
> > - { "image/x-cmu-raster", (EMFormatFunc)efh_image },
> > - { "image/x-ico", (EMFormatFunc)efh_image },
> > - { "image/x-portable-anymap", (EMFormatFunc)efh_image },
> > - { "image/x-portable-bitmap", (EMFormatFunc)efh_image },
> > - { "image/x-portable-graymap", (EMFormatFunc)efh_image },
> > - { "image/x-portable-pixmap", (EMFormatFunc)efh_image },
> > - { "image/x-xpixmap", (EMFormatFunc)efh_image },
> > + { "image/gif",
> > (EMFormatFunc)em_format_html_display_handle_image },
> > + { "image/jpeg",
> > (EMFormatFunc)em_format_html_display_handle_image },
> > + { "image/png",
> > (EMFormatFunc)em_format_html_display_handle_image },
> > + { "image/x-png",
> > (EMFormatFunc)em_format_html_display_handle_image },
> > + { "image/tiff",
> > (EMFormatFunc)em_format_html_display_handle_image },
> > + { "image/x-bmp",
> > (EMFormatFunc)em_format_html_display_handle_image },
> > + { "image/bmp",
> > (EMFormatFunc)em_format_html_display_handle_image },
> > + { "image/svg",
> > (EMFormatFunc)em_format_html_display_handle_image },
> > + { "image/x-cmu-raster",
> > (EMFormatFunc)em_format_html_display_handle_image },
> > + { "image/x-ico",
> > (EMFormatFunc)em_format_html_display_handle_image },
> > + { "image/x-portable-anymap",
> > (EMFormatFunc)em_format_html_display_handle_image },
> > + { "image/x-portable-bitmap",
> > (EMFormatFunc)em_format_html_display_handle_image },
> > + { "image/x-portable-graymap",
> > (EMFormatFunc)em_format_html_display_handle_image },
> > + { "image/x-portable-pixmap",
> > (EMFormatFunc)em_format_html_display_handle_image },
> > + { "image/x-xpixmap",
> > (EMFormatFunc)em_format_html_display_handle_image },
> > { "text/enriched", (EMFormatFunc)efh_text_enriched },
> > { "text/plain", (EMFormatFunc)efh_text_plain },
> > { "text/html", (EMFormatFunc)efh_text_html },
> > @@ -1104,8 +1106,8 @@
> > that some idiot mailer writers out there decide to pull out
> > of their proverbials at random. */
> >
> > - { "image/jpg", (EMFormatFunc)efh_image },
> > - { "image/pjpeg", (EMFormatFunc)efh_image },
> > + { "image/jpg",
> > (EMFormatFunc)em_format_html_display_handle_image },
> > + { "image/pjpeg",
> > (EMFormatFunc)em_format_html_display_handle_image },
> >
> > /* special internal types */
>
> Yeah, so tried printing yet? Fix this, it is bad bad BAD BAD.
>
>
>
>
> _______________________________________________
> evolution-patches mailing list
> evolution-patches lists ximian com
> http://lists.ximian.com/mailman/listinfo/evolution-patches
Index: em-format-html-display.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format-html-display.c,v
retrieving revision 1.68
diff -u -p -r1.68 em-format-html-display.c
--- em-format-html-display.c 17 Jun 2005 15:20:29 -0000 1.68
+++ em-format-html-display.c 27 Jun 2005 09:53:20 -0000
@@ -30,6 +30,7 @@
#include <gtkhtml/gtkhtml-embedded.h>
#include <gtkhtml/gtkhtml-search.h>
+#include <gtk/gtk.h>
#include <gtk/gtkvbox.h>
#include <gtk/gtkhbox.h>
#include <gtk/gtkbutton.h>
@@ -50,6 +51,10 @@
#include <libgnomevfs/gnome-vfs-mime-handlers.h>
#include <libgnome/gnome-i18n.h>
+#ifdef HAVE_LIBGNOMEUI_GNOME_THUMBNAIL_H
+#include <libgnomeui/gnome-thumbnail.h>
+#endif
+
#include <bonobo/bonobo-control-frame.h>
#include <bonobo/bonobo-stream-memory.h>
#include <bonobo/bonobo-widget.h>
@@ -119,6 +124,9 @@ struct _attach_puri {
GtkHTML *frame;
CamelStream *output;
unsigned int shown:1;
+ int size;
+ GtkWidget *image;
+ char *key;
};
static void efhd_iframe_created(GtkHTML *html, GtkHTML *iframe, EMFormatHTMLDisplay *efh);
@@ -1059,10 +1067,29 @@ efhd_attachment_button_show(GtkWidget *w
efhd_attachment_show(NULL, NULL, data);
}
+static void
+efhd_image_resize (EPopup *ep, EPopupItem *item, void *data)
+{
+ struct _attach_puri *info = data;
+ GdkPixbuf *tmp;
+
+ if (info->image) {
+ /* Swap the alt pixbuf and the current pixbuf of the shown GtkImage */
+ tmp = em_icon_stream_replace_pixbuf (info->key, gtk_image_get_pixbuf ((GtkImage *)info->image));
+ gtk_image_set_from_pixbuf ((GtkImage *)info->image, tmp);
+
+ info->size = (info->size == 0);
+ gtk_widget_show (info->image);
+ }
+}
+
static EPopupItem efhd_menu_items[] = {
{ E_POPUP_BAR, "05.display", },
{ E_POPUP_ITEM, "05.display.00", N_("_View Inline"), efhd_attachment_show },
{ E_POPUP_ITEM, "05.display.00", N_("_Hide"), efhd_attachment_show },
+ { E_POPUP_ITEM, "05.display.01", N_("_Fit to Width"), efhd_image_resize, NULL, NULL, EM_POPUP_PART_IMAGE },
+ { E_POPUP_ITEM, "05.display.01", N_("Show _Original Size"), efhd_image_resize, NULL, NULL, EM_POPUP_PART_IMAGE },
+
};
static void
@@ -1113,8 +1140,13 @@ efhd_attachment_popup(GtkWidget *w, GdkE
if (info->handle) {
/* show/hide menus, only if we have an inline handler */
menus = g_slist_prepend(menus, &efhd_menu_items[0]);
- item = &efhd_menu_items[info->shown?2:1];
- menus = g_slist_prepend(menus, item);
+ if (info->size == -1) {
+ item = &efhd_menu_items[info->shown?2:1];
+ menus = g_slist_prepend(menus, item);
+ } else if ( info->shown && info->image && g_object_get_data ((GObject *)info->image, "re-sized")) {
+ item = &efhd_menu_items[info->size?4:3];
+ menus = g_slist_prepend(menus, item);
+ }
}
e_popup_add_items((EPopup *)emp, menus, NULL, efhd_menu_items_free, info);
@@ -1129,6 +1161,16 @@ efhd_attachment_popup(GtkWidget *w, GdkE
}
static gboolean
+efhd_image_popup(GtkWidget *w, GdkEventButton *event, struct _attach_puri *info)
+{
+ if (event && event->button != 3) {
+ return FALSE;
+ }
+ return efhd_attachment_popup(w, event, info);
+
+}
+
+static gboolean
efhd_attachment_popup_menu(GtkWidget *w, struct _attach_puri *info)
{
return efhd_attachment_popup(w, NULL, info);
@@ -1492,6 +1534,168 @@ type_ok:
}
static void
+efhd_image_resize_callback (GtkWidget *w, GtkAllocation *event, struct _attach_puri *info)
+{
+ GdkPixbuf *original, *reduced = NULL, *shrunk;
+ int new_width = ((GtkWidget *)((EMFormatHTML *)info->puri.format)->html)->allocation.width;
+ int width, height;
+
+ new_width = new_width * 95 / 100;
+
+ if (info->size == -1)
+ return;
+
+ width = (int) g_object_get_data ((GObject *)info->image, "original-width");
+ height = (int) g_object_get_data ((GObject *)info->image, "original-height");
+
+ if (!g_object_get_data ((GObject *)info->image, "re-sized")) {
+
+ /* Time to shrink the image and store it
+ * It is also possible that the image size is smaller than the window size, when the window
+ * is expanded too much.
+ */
+ if (width <= new_width)
+ return;
+
+ original = gtk_image_get_pixbuf ((GtkImage *)info->image);
+
+ g_object_set_data ((GObject *)info->image, "re-sized", (gpointer) 1);
+
+ reduced = gdk_pixbuf_copy(original);
+
+ em_icon_stream_set_pixbuf (info->key, reduced);
+
+ } else {
+ /* It is a resized image */
+
+ /* To keep the quality of image, we always resize from the original image */
+ if (info->size) {
+ /* Original is the alt image */
+ original = gdk_pixbuf_copy (em_icon_stream_find_pixbuf(info->key));
+ reduced = gtk_image_get_pixbuf ((GtkImage *)info->image);
+ } else {
+ /* The original image is only shown */
+ original = gtk_image_get_pixbuf ((GtkImage *)info->image);
+ reduced = gdk_pixbuf_copy (em_icon_stream_find_pixbuf(info->key));
+ }
+ }
+
+ /* Dont resize, if the reduced size is equal to the available width */
+ if (gdk_pixbuf_get_width(reduced) == new_width)
+ return;
+
+ if (new_width > width) {
+ /* If the window size go beyond the image size, lets not resize any more
+ * Just have one image copy and free the other
+ * Also always free the manipulated pixbuf
+ */
+
+ if (info->size) {
+ /* Restore the original image */
+ g_object_unref (original);
+ g_object_unref (gtk_image_get_pixbuf ((GtkImage *)info->image));
+ original = em_icon_stream_find_pixbuf (info->key);
+ gtk_image_set_from_pixbuf ((GtkImage *)info->image, original);
+ } else {
+ g_object_unref (em_icon_stream_find_pixbuf (info->key));
+ g_object_unref (reduced);
+ em_icon_stream_set_pixbuf (info->key, gtk_image_get_pixbuf ((GtkImage *)info->image));
+ }
+ g_object_set_data ((GObject *)info->image, "re-sized", (gpointer)0);
+ return;
+ }
+
+ height = height * new_width / width;
+ width = new_width;
+
+
+#ifdef HAVE_LIBGNOMEUI_GNOME_THUMBNAIL_H
+ shrunk = gnome_thumbnail_scale_down_pixbuf (original, width, height);
+#else
+ shrunk = gdk_pixbuf_scale_simple(original, width, height, GDK_INTERP_BILINEAR);
+#endif
+
+ if (info->size) {
+ gtk_image_set_from_pixbuf ((GtkImage *)info->image, shrunk);
+ if (info->shown)
+ gtk_widget_show (info->image);
+ else
+ gtk_widget_hide (info->image);
+ } else {
+ em_icon_stream_set_pixbuf (info->key, shrunk);
+ g_object_unref (reduced);
+ }
+
+}
+
+static gboolean
+efhd_attachment_image (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject)
+{
+ GtkWidget *box;
+ EMFormatHTMLJob *job;
+ struct _attach_puri *info;
+ GtkTargetEntry drag_types[] = {
+ { NULL, 0, 0 },
+ { "text/uri-list", 0, 1 },
+ };
+ char *simple_type;
+ int width = ((GtkWidget *)efh->html)->allocation.width * 95 / 100;
+
+ info = (struct _attach_puri *) em_format_find_puri((EMFormat *)efh, pobject->classid);
+
+ info->image = gtk_image_new();
+ job = em_format_html_job_new(efh, efhd_write_icon_job, pobject);
+ job->stream = (CamelStream *)em_icon_stream_new((GtkImage *)info->image, pobject->classid);
+ ((EMIconStream *) job->stream)->width = width;
+ ((EMIconStream *) job->stream)->height = -1;
+
+ em_format_html_job_queue(efh, job);
+
+ box = gtk_event_box_new ();
+ gtk_container_add ((GtkContainer *) box, info->image);
+ gtk_widget_show_all (box);
+ gtk_container_add ((GtkContainer *) eb, box);
+
+ g_signal_connect (eb, "size_allocate", G_CALLBACK(efhd_image_resize_callback), info);
+
+ simple_type = camel_content_type_simple (((CamelDataWrapper *)pobject->part)->mime_type);
+ camel_strdown(simple_type);
+
+ drag_types[0].target = simple_type;
+ gtk_drag_source_set(box, GDK_BUTTON1_MASK, drag_types, sizeof(drag_types)/sizeof(drag_types[0]), GDK_ACTION_COPY);
+
+ g_signal_connect(box, "drag-data-get", G_CALLBACK(efhd_drag_data_get), pobject);
+ g_signal_connect (box, "drag-data-delete", G_CALLBACK(efhd_drag_data_delete), pobject);
+
+ g_signal_connect(box, "button_press_event", G_CALLBACK(efhd_image_popup), info);
+ g_signal_connect(box, "popup_menu", G_CALLBACK(efhd_attachment_popup_menu), info);
+ return TRUE;
+}
+
+void
+em_format_html_display_handle_image (EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFormatHandler *handle)
+{
+ char *classid;
+ struct _attach_puri *info;
+
+ classid = g_strdup_printf("image%s", ((EMFormat *)efh)->part_id->str);
+ info = (struct _attach_puri *) em_format_add_puri ((EMFormat *)efh, sizeof(*info), classid, part, efhd_attachment_frame);
+ em_format_html_add_pobject(efh, sizeof(EMFormatHTMLPObject), classid, part, efhd_attachment_image);
+
+ info->handle = handle;
+ info->shown = TRUE;
+ info->snoop_mime_type = ((EMFormat *) efh)->snoop_mime_type;
+ /*FIXME: How to free this? */
+ info->key = g_strdup(classid);
+
+ /* By default fit to width*/
+ info->size = 1;
+
+ camel_stream_printf(stream, "<td><object classid=\"%s\"></object></td>", classid);
+ g_free (classid);
+}
+
+static void
efhd_format_attachment(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const char *mime_type, const EMFormatHandler *handle)
{
char *classid, *text, *html;
@@ -1503,6 +1707,7 @@ efhd_format_attachment(EMFormat *emf, Ca
info->handle = handle;
info->shown = em_format_is_inline(emf, info->puri.part_id, info->puri.part, handle);
info->snoop_mime_type = emf->snoop_mime_type;
+ info->size = -1;
camel_stream_write_string(stream,
EM_FORMAT_HTML_VPAD
Index: em-format-html.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format-html.c,v
retrieving revision 1.78
diff -u -p -r1.78 em-format-html.c
--- em-format-html.c 19 May 2005 06:06:35 -0000 1.78
+++ em-format-html.c 27 Jun 2005 09:53:20 -0000
@@ -1068,12 +1068,10 @@ efh_write_image(EMFormat *emf, CamelStre
static void
efh_image(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFormatHandler *info)
{
- EMFormatPURI *puri;
-
- puri = em_format_add_puri((EMFormat *)efh, sizeof(EMFormatPURI), NULL, part, efh_write_image);
- d(printf("adding image '%s'\n", puri->cid));
- camel_stream_printf(stream, "<img hspace=10 vspace=10 src=\"%s\">", puri->cid);
+ em_format_html_display_handle_image (efh, stream, part, info);
}
+
+void efhd_handle_image(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFormatHandler *info);
static EMFormatHandler type_builtin_table[] = {
{ "image/gif", (EMFormatFunc)efh_image },
Index: em-icon-stream.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-icon-stream.c,v
retrieving revision 1.6
diff -u -p -r1.6 em-icon-stream.c
--- em-icon-stream.c 2 Mar 2005 05:23:45 -0000 1.6
+++ em-icon-stream.c 27 Jun 2005 09:53:20 -0000
@@ -157,8 +157,8 @@ static int
emis_sync_close(CamelStream *stream)
{
EMIconStream *emis = (EMIconStream *)stream;
- int width, height, ratio;
- GdkPixbuf *pixbuf, *mini;
+ int width, height;
+ GdkPixbuf *pixbuf, *mini, *orig = NULL;
struct _emis_cache_node *node;
if (emis->loader == NULL)
@@ -176,19 +176,19 @@ emis_sync_close(CamelStream *stream)
width = gdk_pixbuf_get_width(pixbuf);
height = gdk_pixbuf_get_height(pixbuf);
- if (width != emis->width || height != emis->height) {
- if (width >= height) {
- if (width > emis->width) {
- ratio = width / emis->width;
- width = emis->width;
- height /= ratio;
- }
+ if (width > emis->width || (height > emis->height && emis->height != -1)) {
+ if (width >= height || emis->height == -1) {
+ if (emis->height == -1) {
+ orig = pixbuf;
+ g_object_set_data ((GObject *)emis->image, "re-sized", (gpointer)1);
+ g_object_set_data ((GObject *)emis->image, "original-width", (gpointer)width);
+ g_object_set_data ((GObject *)emis->image, "original-height", (gpointer)height);
+ }
+ height = height * emis->width / width;
+ width = emis->width;
} else {
- if (height > emis->height) {
- ratio = height / emis->height;
- height = emis->height;
- width /= ratio;
- }
+ width = width * emis->height / height;
+ height = emis->height;
}
#ifdef HAVE_LIBGNOMEUI_GNOME_THUMBNAIL_H
@@ -200,12 +200,26 @@ emis_sync_close(CamelStream *stream)
pixbuf = mini;
} else {
g_object_ref(pixbuf);
- gtk_image_set_from_pixbuf(emis->image, pixbuf);
+ gtk_image_set_from_pixbuf((GtkImage *)emis->image, pixbuf);
+ g_object_set_data ((GObject *)emis->image, "original-width", (gpointer)width);
+ g_object_set_data ((GObject *)emis->image, "original-height", (gpointer)height);
}
- node = (struct _emis_cache_node *)em_cache_node_new(emis_cache, emis->key);
- node->pixbuf = pixbuf;
- em_cache_add(emis_cache, (EMCacheNode *)node);
+ if (orig) {
+ pixbuf = orig;
+ g_object_ref (pixbuf);
+ }
+
+ node = (struct _emis_cache_node *)em_cache_lookup(emis_cache, emis->key);
+
+ if (node) {
+ g_object_unref (node->pixbuf);
+ node->pixbuf = pixbuf;
+ } else {
+ node = (struct _emis_cache_node *)em_cache_node_new(emis_cache, emis->key);
+ node->pixbuf = pixbuf;
+ em_cache_add(emis_cache, (EMCacheNode *)node);
+ }
g_object_unref(emis->loader);
emis->loader = NULL;
@@ -254,6 +268,56 @@ em_icon_stream_get_image(const char *key
return pb;
}
+
+GdkPixbuf *
+em_icon_stream_replace_pixbuf (const char *key, GdkPixbuf * src)
+{
+ GdkPixbuf *alt;
+ struct _emis_cache_node *node;
+
+ /* forces the cache to be setup if not */
+ em_icon_stream_get_type();
+
+ node = (struct _emis_cache_node *)em_cache_lookup(emis_cache, key);
+ if (node) {
+ alt = node->pixbuf;
+ node->pixbuf = src;
+ return alt;
+ }
+ return NULL;
+
+}
+
+GdkPixbuf *
+em_icon_stream_find_pixbuf (const char *key)
+{
+ struct _emis_cache_node *node;
+
+ /* forces the cache to be setup if not */
+ em_icon_stream_get_type();
+
+ node = (struct _emis_cache_node *)em_cache_lookup(emis_cache, key);
+ if (node)
+ return node->pixbuf;
+
+ return NULL;
+}
+
+void
+em_icon_stream_set_pixbuf (const char *key, GdkPixbuf *pb)
+{
+ struct _emis_cache_node *node;
+
+ /* forces the cache to be setup if not */
+ em_icon_stream_get_type();
+
+ node = (struct _emis_cache_node *)em_cache_lookup(emis_cache, key);
+ if (node)
+ node->pixbuf = pb;
+
+}
+
+
void
em_icon_stream_clear_cache(void)
Index: em-icon-stream.h
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-icon-stream.h,v
retrieving revision 1.4
diff -u -p -r1.4 em-icon-stream.h
--- em-icon-stream.h 16 May 2005 07:53:53 -0000 1.4
+++ em-icon-stream.h 27 Jun 2005 09:53:20 -0000
@@ -56,6 +56,10 @@ CamelType em_icon_stream_get_type (vo
CamelStream *em_icon_stream_new(GtkImage *image, const char *key);
struct _GdkPixbuf *em_icon_stream_get_image(const char *key);
+GdkPixbuf * em_icon_stream_replace_pixbuf (const char *key, GdkPixbuf * src);
+GdkPixbuf * em_icon_stream_find_pixbuf (const char *key);
+void em_icon_stream_set_pixbuf (const char *key, GdkPixbuf *pb);
+
void em_icon_stream_clear_cache(void);
#ifdef __cplusplus
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]