/*
* image-inline.c
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) version 3.
*
* This program 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with the program; if not, see
*
*
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include
#include
#include
#include
#include
#include
#include
#include "mail/em-format-hook.h"
#include "mail/em-format-html.h"
static gint org_gnome_image_inline_classid;
/* Forward Declarations */
void org_gnome_image_inline_format (gpointer ep, EMFormatHookTarget *target);
typedef struct _ImageInlinePObject ImageInlinePObject;
struct _ImageInlinePObject {
EMFormatHTMLPObject object;
GdkPixbuf *pixbuf;
GtkWidget *widget;
};
static void
size_allocate_cb (GtkHTMLEmbedded *embedded,
GtkAllocation *event,
ImageInlinePObject *image_object)
{
GtkWidget *widget;
gint pixbuf_width;
gint pixbuf_height;
gint widget_width;
gint widget_height;
gdouble zoom;
widget = GTK_WIDGET (image_object->object.format->html);
widget_width = widget->allocation.width - 12;
pixbuf_width = gdk_pixbuf_get_width (image_object->pixbuf);
pixbuf_height = gdk_pixbuf_get_height (image_object->pixbuf);
if (pixbuf_width <= widget_width)
zoom = 1.0;
else
zoom = (gdouble) widget_width / pixbuf_width;
widget_width = MIN (widget_width, pixbuf_width);
widget_height = (gint) (zoom * pixbuf_height);
gtk_widget_set_size_request (
image_object->widget, widget_width, widget_height);
}
static void
org_gnome_image_inline_pobject_free (EMFormatHTMLPObject *object)
{
ImageInlinePObject *image_object;
image_object = (ImageInlinePObject *) object;
if (image_object->pixbuf != NULL) {
g_object_unref (image_object->pixbuf);
image_object->pixbuf = NULL;
}
if (image_object->widget != NULL) {
g_object_unref (image_object->widget);
image_object->widget = NULL;
}
}
static void
org_gnome_image_inline_decode (ImageInlinePObject *image_object,
CamelMimePart *mime_part)
{
GdkPixbuf *pixbuf;
GdkPixbufLoader *loader;
CamelContentType *content_type;
CamelDataWrapper *data_wrapper;
CamelMedium *medium;
CamelStream *stream;
GByteArray *array;
gchar *mime_type;
GError *error = NULL;
array = g_byte_array_new ();
medium = CAMEL_MEDIUM (mime_part);
/* Stream takes ownership of the byte array. */
stream = camel_stream_mem_new_with_byte_array (array);
data_wrapper = camel_medium_get_content_object (medium);
camel_data_wrapper_decode_to_stream (data_wrapper, stream);
content_type = camel_mime_part_get_content_type (mime_part);
mime_type = camel_content_type_simple (content_type);
loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, &error);
g_free (mime_type);
if (error != NULL) {
g_warning ("%s", error->message);
g_error_free (error);
goto exit;
}
gdk_pixbuf_loader_write (loader, array->data, array->len, &error);
if (error != NULL) {
g_warning ("%s", error->message);
g_error_free (error);
goto exit;
}
pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
if (pixbuf != NULL)
image_object->pixbuf = g_object_ref (pixbuf);
gdk_pixbuf_loader_close (loader, &error);
if (error != NULL) {
g_warning ("%s", error->message);
g_error_free (error);
goto exit;
}
exit:
camel_object_unref (mime_part);
camel_object_unref (stream);
}
static gboolean
org_gnome_image_inline_embed (EMFormatHTML *format,
GtkHTMLEmbedded *embedded,
EMFormatHTMLPObject *object)
{
ImageInlinePObject *image_object;
GtkImageView *image_view;
GtkWidget *container;
GtkWidget *widget;
image_object = (ImageInlinePObject *) object;
if (image_object->pixbuf == NULL)
return FALSE;
container = GTK_WIDGET (embedded);
widget = gtk_image_view_new ();
image_view = GTK_IMAGE_VIEW (widget);
gtk_widget_show (widget);
widget = gtk_image_scroll_win_new (image_view);
gtk_container_add (GTK_CONTAINER (container), widget);
image_object->widget = g_object_ref (widget);
gtk_widget_show (widget);
gtk_image_view_set_pixbuf (
image_view, image_object->pixbuf, TRUE);
g_signal_connect (
embedded, "size-allocate",
G_CALLBACK (size_allocate_cb), image_object);
return TRUE;
}
void
org_gnome_image_inline_format (gpointer ep, EMFormatHookTarget *target)
{
ImageInlinePObject *image_object;
gchar *classid;
classid = g_strdup_printf (
"org-gnome-image-inline-display-%d",
org_gnome_image_inline_classid++);
image_object = (ImageInlinePObject *)
em_format_html_add_pobject (
EM_FORMAT_HTML (target->format),
sizeof (ImageInlinePObject),
classid, target->part,
org_gnome_image_inline_embed);
camel_object_ref (target->part);
image_object->object.free = org_gnome_image_inline_pobject_free;
org_gnome_image_inline_decode (image_object, target->part);
camel_stream_printf (
target->stream, "", classid);
g_free (classid);
}