use the cache, since we set it up. (efhd_image): added a (private!) format
2005-07-05 Not Zed <NotZed@Ximian.com> * em-format-html-display.c (efhd_attachment_image): use the cache, since we set it up. (efhd_image): added a (private!) format handler for all the image types so we intercept them and handle them directly. (efhd_image_fit, efhd_image_unfit): replace the resize callback with two much simpler ones. * em-icon-stream.c (em_icon_stream_get_image): added 'fit to' arguments. Changed dramatically to get approximate fit-to image, update cache, etc. (em_icon_stream_is_resized): added 'fit to' arguments. changed to manipulate the cache properly. (emis_fit): helper to fit an image to a size. (em_icon_stream_new): added 'fit to' arguments rather than poking structures. * em-format-html-display.c (efhd_attachment_image): fixed a memory leak, various style issues. Removed all scaling code. (efhd_attachment_popup): show menu's appropriately. add back the hide/show menu always. (efhd_image_popup): fix formatting. ** Applied patch from Srini for scaling images to fit by default. svn path=/trunk/; revision=29640
This commit is contained in:
@ -1,3 +1,29 @@
|
||||
2005-07-05 Not Zed <NotZed@Ximian.com>
|
||||
|
||||
* em-format-html-display.c (efhd_attachment_image): use the cache,
|
||||
since we set it up.
|
||||
(efhd_image): added a (private!) format handler for all the image
|
||||
types so we intercept them and handle them directly.
|
||||
(efhd_image_fit, efhd_image_unfit): replace the resize callback
|
||||
with two much simpler ones.
|
||||
|
||||
* em-icon-stream.c (em_icon_stream_get_image): added 'fit to'
|
||||
arguments. Changed dramatically to get approximate fit-to image,
|
||||
update cache, etc.
|
||||
(em_icon_stream_is_resized): added 'fit to' arguments. changed to
|
||||
manipulate the cache properly.
|
||||
(emis_fit): helper to fit an image to a size.
|
||||
(em_icon_stream_new): added 'fit to' arguments rather than poking
|
||||
structures.
|
||||
|
||||
* em-format-html-display.c (efhd_attachment_image): fixed a memory
|
||||
leak, various style issues. Removed all scaling code.
|
||||
(efhd_attachment_popup): show menu's appropriately. add back the
|
||||
hide/show menu always.
|
||||
(efhd_image_popup): fix formatting.
|
||||
|
||||
** Applied patch from Srini for scaling images to fit by default.
|
||||
|
||||
2005-07-04 Veerapuram Varadhan <vvaradhan@novell.com>
|
||||
|
||||
* mail-component.c: (handleuri_got_folder): Added "forward"
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#include <gtkhtml/gtkhtml-embedded.h>
|
||||
#include <gtkhtml/gtkhtml-search.h>
|
||||
|
||||
#include <gtk/gtkeventbox.h>
|
||||
#include <gtk/gtkvbox.h>
|
||||
#include <gtk/gtkhbox.h>
|
||||
#include <gtk/gtkbutton.h>
|
||||
@ -106,6 +107,9 @@ static int efhd_html_button_press_event (GtkWidget *widget, GdkEventButton *even
|
||||
static void efhd_html_link_clicked (GtkHTML *html, const char *url, EMFormatHTMLDisplay *efhd);
|
||||
static void efhd_html_on_url (GtkHTML *html, const char *url, EMFormatHTMLDisplay *efhd);
|
||||
|
||||
static void efhd_attachment_frame(EMFormat *emf, CamelStream *stream, EMFormatPURI *puri);
|
||||
static gboolean efhd_attachment_image(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject);
|
||||
|
||||
struct _attach_puri {
|
||||
EMFormatPURI puri;
|
||||
|
||||
@ -119,8 +123,14 @@ struct _attach_puri {
|
||||
GtkHTML *frame;
|
||||
CamelStream *output;
|
||||
unsigned int shown:1;
|
||||
|
||||
/* image stuff */
|
||||
int fit_width;
|
||||
int fit_height;
|
||||
GtkImage *image;
|
||||
};
|
||||
|
||||
|
||||
static void efhd_iframe_created(GtkHTML *html, GtkHTML *iframe, EMFormatHTMLDisplay *efh);
|
||||
/*static void efhd_url_requested(GtkHTML *html, const char *url, GtkHTMLStream *handle, EMFormatHTMLDisplay *efh);
|
||||
static gboolean efhd_object_requested(GtkHTML *html, GtkHTMLEmbedded *eb, EMFormatHTMLDisplay *efh);*/
|
||||
@ -903,9 +913,51 @@ efhd_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, Came
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
efhd_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;
|
||||
info->fit_width = ((GtkWidget *)((EMFormatHTML *)info->puri.format)->html)->allocation.width - 12;
|
||||
|
||||
camel_stream_printf(stream, "<td><object classid=\"%s\"></object></td>", classid);
|
||||
g_free(classid);
|
||||
}
|
||||
|
||||
/* ********************************************************************** */
|
||||
|
||||
static EMFormatHandler type_builtin_table[] = {
|
||||
{ "image/gif", (EMFormatFunc)efhd_image },
|
||||
{ "image/jpeg", (EMFormatFunc)efhd_image },
|
||||
{ "image/png", (EMFormatFunc)efhd_image },
|
||||
{ "image/x-png", (EMFormatFunc)efhd_image },
|
||||
{ "image/tiff", (EMFormatFunc)efhd_image },
|
||||
{ "image/x-bmp", (EMFormatFunc)efhd_image },
|
||||
{ "image/bmp", (EMFormatFunc)efhd_image },
|
||||
{ "image/svg", (EMFormatFunc)efhd_image },
|
||||
{ "image/x-cmu-raster", (EMFormatFunc)efhd_image },
|
||||
{ "image/x-ico", (EMFormatFunc)efhd_image },
|
||||
{ "image/x-portable-anymap", (EMFormatFunc)efhd_image },
|
||||
{ "image/x-portable-bitmap", (EMFormatFunc)efhd_image },
|
||||
{ "image/x-portable-graymap", (EMFormatFunc)efhd_image },
|
||||
{ "image/x-portable-pixmap", (EMFormatFunc)efhd_image },
|
||||
{ "image/x-xpixmap", (EMFormatFunc)efhd_image },
|
||||
|
||||
/* This is where one adds those busted, non-registered types,
|
||||
that some idiot mailer writers out there decide to pull out
|
||||
of their proverbials at random. */
|
||||
|
||||
{ "image/jpg", (EMFormatFunc)efhd_image },
|
||||
{ "image/pjpeg", (EMFormatFunc)efhd_image },
|
||||
|
||||
{ "x-evolution/message/prefix", (EMFormatFunc)efhd_message_prefix },
|
||||
};
|
||||
|
||||
@ -1059,10 +1111,30 @@ efhd_attachment_button_show(GtkWidget *w, void *data)
|
||||
efhd_attachment_show(NULL, NULL, data);
|
||||
}
|
||||
|
||||
static void
|
||||
efhd_image_fit(EPopup *ep, EPopupItem *item, void *data)
|
||||
{
|
||||
struct _attach_puri *info = data;
|
||||
|
||||
info->fit_width = ((GtkWidget *)((EMFormatHTML *)info->puri.format)->html)->allocation.width - 12;
|
||||
gtk_image_set_from_pixbuf(info->image, em_icon_stream_get_image(info->puri.cid, info->fit_width, info->fit_height));
|
||||
}
|
||||
|
||||
static void
|
||||
efhd_image_unfit(EPopup *ep, EPopupItem *item, void *data)
|
||||
{
|
||||
struct _attach_puri *info = data;
|
||||
|
||||
info->fit_width = 0;
|
||||
gtk_image_set_from_pixbuf((GtkImage *)info->image, em_icon_stream_get_image(info->puri.cid, info->fit_width, info->fit_height));
|
||||
}
|
||||
|
||||
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_fit, NULL, NULL, EM_POPUP_PART_IMAGE },
|
||||
{ E_POPUP_ITEM, "05.display.01", N_("Show _Original Size"), efhd_image_unfit, NULL, NULL, EM_POPUP_PART_IMAGE },
|
||||
};
|
||||
|
||||
static void
|
||||
@ -1088,7 +1160,6 @@ efhd_attachment_popup(GtkWidget *w, GdkEventButton *event, struct _attach_puri *
|
||||
GSList *menus = NULL;
|
||||
EMPopup *emp;
|
||||
EMPopupTargetPart *target;
|
||||
EPopupItem *item;
|
||||
|
||||
d(printf("attachment popup, button %d\n", event->button));
|
||||
|
||||
@ -1113,8 +1184,14 @@ efhd_attachment_popup(GtkWidget *w, GdkEventButton *event, struct _attach_puri *
|
||||
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);
|
||||
menus = g_slist_prepend(menus, &efhd_menu_items[info->shown?2:1]);
|
||||
if (info->shown && info->image) {
|
||||
if (info->fit_width != 0) {
|
||||
if (em_icon_stream_is_resized(info->puri.cid, info->fit_width, info->fit_height))
|
||||
menus = g_slist_prepend(menus, &efhd_menu_items[4]);
|
||||
} else
|
||||
menus = g_slist_prepend(menus, &efhd_menu_items[3]);
|
||||
}
|
||||
}
|
||||
|
||||
e_popup_add_items((EPopup *)emp, menus, NULL, efhd_menu_items_free, info);
|
||||
@ -1128,6 +1205,15 @@ efhd_attachment_popup(GtkWidget *w, GdkEventButton *event, struct _attach_puri *
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -1213,6 +1299,73 @@ efhd_write_icon_job(struct _EMFormatHTMLJob *job, int cancelled)
|
||||
camel_stream_close(job->stream);
|
||||
}
|
||||
|
||||
static void
|
||||
efhd_image_resized(GtkWidget *w, GtkAllocation *event, struct _attach_puri *info)
|
||||
{
|
||||
GdkPixbuf *pb;
|
||||
int width;
|
||||
|
||||
if (info->fit_width == 0)
|
||||
return;
|
||||
|
||||
width = ((GtkWidget *)((EMFormatHTML *)info->puri.format)->html)->allocation.width - 12;
|
||||
if (info->fit_width == width)
|
||||
return;
|
||||
info->fit_width = width;
|
||||
pb = em_icon_stream_get_image(info->puri.cid, info->fit_width, info->fit_height);
|
||||
gtk_image_set_from_pixbuf(info->image, pb);
|
||||
g_object_unref(pb);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
efhd_attachment_image(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject)
|
||||
{
|
||||
GtkWidget *box;
|
||||
EMFormatHTMLJob *job;
|
||||
struct _attach_puri *info;
|
||||
GdkPixbuf *pixbuf;
|
||||
GtkTargetEntry drag_types[] = {
|
||||
{ NULL, 0, 0 },
|
||||
{ "text/uri-list", 0, 1 },
|
||||
};
|
||||
char *simple_type;
|
||||
|
||||
info = (struct _attach_puri *)em_format_find_puri((EMFormat *)efh, pobject->classid);
|
||||
|
||||
info->image = (GtkImage *)gtk_image_new();
|
||||
pixbuf = em_icon_stream_get_image(pobject->classid, info->fit_width, info->fit_height);
|
||||
if (pixbuf) {
|
||||
gtk_image_set_from_pixbuf(info->image, pixbuf);
|
||||
g_object_unref(pixbuf);
|
||||
} else {
|
||||
job = em_format_html_job_new(efh, efhd_write_icon_job, pobject);
|
||||
job->stream = (CamelStream *)em_icon_stream_new((GtkImage *)info->image, pobject->classid, info->fit_width, info->fit_height, TRUE);
|
||||
em_format_html_job_queue(efh, job);
|
||||
}
|
||||
|
||||
box = gtk_event_box_new();
|
||||
gtk_container_add((GtkContainer *)box, (GtkWidget *)info->image);
|
||||
gtk_widget_show_all(box);
|
||||
gtk_container_add((GtkContainer *)eb, box);
|
||||
|
||||
g_signal_connect(eb, "size_allocate", G_CALLBACK(efhd_image_resized), 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_free(simple_type);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* attachment button callback */
|
||||
static gboolean
|
||||
efhd_attachment_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject)
|
||||
@ -1266,13 +1419,13 @@ efhd_attachment_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObje
|
||||
camel_strdown(simple_type);
|
||||
|
||||
/* FIXME: offline parts, just get icon */
|
||||
if (camel_content_type_is (((CamelDataWrapper *)pobject->part)->mime_type, "image", "*")) {
|
||||
if (camel_content_type_is(((CamelDataWrapper *)pobject->part)->mime_type, "image", "*")) {
|
||||
EMFormatHTMLJob *job;
|
||||
GdkPixbuf *mini;
|
||||
char *key;
|
||||
|
||||
key = pobject->classid;
|
||||
mini = em_icon_stream_get_image(key);
|
||||
mini = em_icon_stream_get_image(key, 24, 24);
|
||||
if (mini) {
|
||||
d(printf("got image from cache '%s'\n", key));
|
||||
gtk_image_set_from_pixbuf((GtkImage *)w, mini);
|
||||
@ -1280,7 +1433,7 @@ efhd_attachment_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObje
|
||||
} else {
|
||||
d(printf("need to create icon image '%s'\n", key));
|
||||
job = em_format_html_job_new(efh, efhd_write_icon_job, pobject);
|
||||
job->stream = (CamelStream *)em_icon_stream_new((GtkImage *)w, key);
|
||||
job->stream = (CamelStream *)em_icon_stream_new((GtkImage *)w, key, 24, 24, FALSE);
|
||||
em_format_html_job_queue(efh, job);
|
||||
}
|
||||
} else {
|
||||
@ -1308,7 +1461,6 @@ efhd_attachment_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObje
|
||||
a11y = gtk_widget_get_accessible (button);
|
||||
atk_object_set_name (a11y, _("Attachment Button"));
|
||||
|
||||
|
||||
g_signal_connect(button, "button_press_event", G_CALLBACK(efhd_attachment_popup), info);
|
||||
g_signal_connect(button, "popup_menu", G_CALLBACK(efhd_attachment_popup_menu), info);
|
||||
g_signal_connect(button, "clicked", G_CALLBACK(efhd_attachment_popup_menu), info);
|
||||
|
||||
@ -26,6 +26,8 @@
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf-loader.h>
|
||||
#ifdef HAVE_LIBGNOMEUI_GNOME_THUMBNAIL_H
|
||||
@ -38,6 +40,9 @@
|
||||
|
||||
#define d(x)
|
||||
|
||||
/* fixed-point scale factor for scaled images in cache */
|
||||
#define EMIS_SCALE (1024)
|
||||
|
||||
struct _emis_cache_node {
|
||||
EMCacheNode node;
|
||||
|
||||
@ -98,8 +103,7 @@ em_icon_stream_init (CamelObject *object)
|
||||
{
|
||||
EMIconStream *emis = (EMIconStream *)object;
|
||||
|
||||
emis->width = 24;
|
||||
emis->height = 24;
|
||||
emis = emis;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -153,13 +157,47 @@ emis_sync_flush(CamelStream *stream)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static GdkPixbuf *
|
||||
emis_fit(GdkPixbuf *pixbuf, int maxwidth, int maxheight, int *scale)
|
||||
{
|
||||
GdkPixbuf *mini = NULL;
|
||||
int width, height;
|
||||
|
||||
width = gdk_pixbuf_get_width(pixbuf);
|
||||
height = gdk_pixbuf_get_height(pixbuf);
|
||||
|
||||
if ((maxwidth && width > maxwidth)
|
||||
|| (maxheight && height > maxheight)) {
|
||||
if (width >= height) {
|
||||
if (scale)
|
||||
*scale = maxwidth * EMIS_SCALE / width;
|
||||
height = height * maxwidth / width;
|
||||
width = maxwidth;
|
||||
} else {
|
||||
if (scale)
|
||||
*scale = maxheight * EMIS_SCALE / height;
|
||||
width = width * maxheight / height;
|
||||
height = maxheight;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBGNOMEUI_GNOME_THUMBNAIL_H
|
||||
mini = gnome_thumbnail_scale_down_pixbuf(pixbuf, width, height);
|
||||
#else
|
||||
mini = gdk_pixbuf_scale_simple(pixbuf, width, height, GDK_INTERP_BILINEAR);
|
||||
#endif
|
||||
}
|
||||
|
||||
return mini;
|
||||
}
|
||||
|
||||
static int
|
||||
emis_sync_close(CamelStream *stream)
|
||||
{
|
||||
EMIconStream *emis = (EMIconStream *)stream;
|
||||
int width, height, ratio;
|
||||
GdkPixbuf *pixbuf, *mini;
|
||||
struct _emis_cache_node *node;
|
||||
char *scalekey;
|
||||
int scale;
|
||||
|
||||
if (emis->loader == NULL)
|
||||
return -1;
|
||||
@ -173,39 +211,22 @@ emis_sync_close(CamelStream *stream)
|
||||
return -1;
|
||||
}
|
||||
|
||||
width = gdk_pixbuf_get_width(pixbuf);
|
||||
height = gdk_pixbuf_get_height(pixbuf);
|
||||
mini = emis_fit(pixbuf, emis->width, emis->height, &scale);
|
||||
gtk_image_set_from_pixbuf(emis->image, mini?mini:pixbuf);
|
||||
|
||||
if (width != emis->width || height != emis->height) {
|
||||
if (width >= height) {
|
||||
if (width > emis->width) {
|
||||
ratio = width / emis->width;
|
||||
width = emis->width;
|
||||
height /= ratio;
|
||||
}
|
||||
} else {
|
||||
if (height > emis->height) {
|
||||
ratio = height / emis->height;
|
||||
height = emis->height;
|
||||
width /= ratio;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBGNOMEUI_GNOME_THUMBNAIL_H
|
||||
mini = gnome_thumbnail_scale_down_pixbuf (pixbuf, width, height);
|
||||
#else
|
||||
mini = gdk_pixbuf_scale_simple(pixbuf, width, height, GDK_INTERP_BILINEAR);
|
||||
#endif
|
||||
gtk_image_set_from_pixbuf(emis->image, mini);
|
||||
pixbuf = mini;
|
||||
} else {
|
||||
g_object_ref(pixbuf);
|
||||
gtk_image_set_from_pixbuf(emis->image, pixbuf);
|
||||
if (emis->keep) {
|
||||
node = (struct _emis_cache_node *)em_cache_node_new(emis_cache, emis->key);
|
||||
node->pixbuf = g_object_ref(pixbuf);
|
||||
em_cache_add(emis_cache, (EMCacheNode *)node);
|
||||
}
|
||||
|
||||
node = (struct _emis_cache_node *)em_cache_node_new(emis_cache, emis->key);
|
||||
node->pixbuf = pixbuf;
|
||||
em_cache_add(emis_cache, (EMCacheNode *)node);
|
||||
if (!emis->keep || mini) {
|
||||
scalekey = g_alloca(strlen(emis->key) + 20);
|
||||
sprintf(scalekey, "%s.%x", emis->key, scale);
|
||||
node = (struct _emis_cache_node *)em_cache_node_new(emis_cache, scalekey);
|
||||
node->pixbuf = mini?mini:g_object_ref(pixbuf);
|
||||
em_cache_add(emis_cache, (EMCacheNode *)node);
|
||||
}
|
||||
|
||||
g_object_unref(emis->loader);
|
||||
emis->loader = NULL;
|
||||
@ -223,12 +244,15 @@ emis_image_destroy(struct _GtkImage *image, EMIconStream *emis)
|
||||
}
|
||||
|
||||
CamelStream *
|
||||
em_icon_stream_new(GtkImage *image, const char *key)
|
||||
em_icon_stream_new(GtkImage *image, const char *key, unsigned int maxwidth, unsigned int maxheight, int keep)
|
||||
{
|
||||
EMIconStream *new;
|
||||
|
||||
new = EM_ICON_STREAM(camel_object_new(EM_ICON_STREAM_TYPE));
|
||||
new->width = maxwidth;
|
||||
new->height = maxheight;
|
||||
new->image = image;
|
||||
new->keep = keep;
|
||||
new->destroy_id = g_signal_connect(image, "destroy", G_CALLBACK(emis_image_destroy), new);
|
||||
new->loader = gdk_pixbuf_loader_new();
|
||||
new->key = g_strdup(key);
|
||||
@ -237,22 +261,77 @@ em_icon_stream_new(GtkImage *image, const char *key)
|
||||
}
|
||||
|
||||
GdkPixbuf *
|
||||
em_icon_stream_get_image(const char *key)
|
||||
em_icon_stream_get_image(const char *key, unsigned int maxwidth, unsigned int maxheight)
|
||||
{
|
||||
struct _emis_cache_node *node;
|
||||
GdkPixbuf *pb = NULL;
|
||||
|
||||
/* 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) {
|
||||
int width, height;
|
||||
|
||||
pb = node->pixbuf;
|
||||
g_object_ref(pb);
|
||||
em_cache_node_unref(emis_cache, (EMCacheNode *)node);
|
||||
|
||||
width = gdk_pixbuf_get_width(pb);
|
||||
height = gdk_pixbuf_get_height(pb);
|
||||
|
||||
if ((maxwidth && width > maxwidth)
|
||||
|| (maxheight && height > maxheight)) {
|
||||
unsigned int scale;
|
||||
char *realkey;
|
||||
|
||||
if (width >= height)
|
||||
scale = width * EMIS_SCALE / maxwidth;
|
||||
else
|
||||
scale = height * EMIS_SCALE / maxheight;
|
||||
|
||||
realkey = g_alloca(strlen(key)+20);
|
||||
sprintf(realkey, "%s.%x", key, scale);
|
||||
node = (struct _emis_cache_node *)em_cache_lookup(emis_cache, realkey);
|
||||
if (node) {
|
||||
g_object_unref(pb);
|
||||
pb = node->pixbuf;
|
||||
g_object_ref(pb);
|
||||
em_cache_node_unref(emis_cache, (EMCacheNode *)node);
|
||||
} else {
|
||||
GdkPixbuf *mini = emis_fit(pb, maxwidth, maxheight, NULL);
|
||||
|
||||
g_object_unref(pb);
|
||||
pb = mini;
|
||||
node = (struct _emis_cache_node *)em_cache_node_new(emis_cache, realkey);
|
||||
node->pixbuf = pb;
|
||||
g_object_ref(pb);
|
||||
em_cache_add(emis_cache, (EMCacheNode *)node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pb;
|
||||
}
|
||||
|
||||
int
|
||||
em_icon_stream_is_resized(const char *key, unsigned int maxwidth, unsigned int maxheight)
|
||||
{
|
||||
int res = FALSE;
|
||||
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) {
|
||||
pb = node->pixbuf;
|
||||
g_object_ref(pb);
|
||||
res = (maxwidth && gdk_pixbuf_get_width(node->pixbuf) > maxwidth)
|
||||
|| (maxheight && gdk_pixbuf_get_width(node->pixbuf) > maxheight);
|
||||
|
||||
em_cache_node_unref(emis_cache, (EMCacheNode *)node);
|
||||
}
|
||||
|
||||
return pb;
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@ -46,6 +46,8 @@ typedef struct _EMIconStream {
|
||||
struct _GdkPixbufLoader *loader;
|
||||
struct _GtkImage *image;
|
||||
char *key;
|
||||
|
||||
int keep:1;
|
||||
} EMIconStream;
|
||||
|
||||
typedef struct {
|
||||
@ -53,9 +55,11 @@ typedef struct {
|
||||
} EMIconStreamClass;
|
||||
|
||||
CamelType em_icon_stream_get_type (void);
|
||||
CamelStream *em_icon_stream_new(GtkImage *image, const char *key, unsigned int maxwidth, unsigned int maxheight, int keep);
|
||||
|
||||
struct _GdkPixbuf *em_icon_stream_get_image(const char *key, unsigned int maxwidth, unsigned int maxheight);
|
||||
int em_icon_stream_is_resized(const char *key, unsigned int maxwidth, unsigned int maxheight);
|
||||
|
||||
CamelStream *em_icon_stream_new(GtkImage *image, const char *key);
|
||||
struct _GdkPixbuf *em_icon_stream_get_image(const char *key);
|
||||
void em_icon_stream_clear_cache(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
Reference in New Issue
Block a user