|
Packit |
b00eeb |
/*
|
|
Packit |
b00eeb |
* Copyright (C) 2011 Collabora Ltd.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
b00eeb |
* it under the terms of the GNU Lesser General Public License as
|
|
Packit |
b00eeb |
* published by the Free Software Foundation; either version 2.1 of
|
|
Packit |
b00eeb |
* the License, or (at your option) any later version.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* This program is distributed in the hope that it will be useful, but
|
|
Packit |
b00eeb |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
b00eeb |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
b00eeb |
* Lesser General Public License for more details.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
b00eeb |
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Author: Stef Walter <stefw@collabora.co.uk>
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include "config.h"
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include "gcr-memory-icon.h"
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include <string.h>
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
struct _GcrMemoryIconPrivate {
|
|
Packit |
b00eeb |
gpointer data;
|
|
Packit |
b00eeb |
gsize n_data;
|
|
Packit |
b00eeb |
goffset offset;
|
|
Packit |
b00eeb |
gchar *image_type;
|
|
Packit |
b00eeb |
GDestroyNotify destroy;
|
|
Packit |
b00eeb |
};
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Forward declarations */
|
|
Packit |
b00eeb |
static void _gcr_memory_icon_iface_icon (GIconIface *iface);
|
|
Packit |
b00eeb |
static void _gcr_memory_icon_iface_loadable_icon (GLoadableIconIface *iface);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
G_DEFINE_TYPE_WITH_CODE (GcrMemoryIcon, _gcr_memory_icon, G_TYPE_OBJECT,
|
|
Packit |
b00eeb |
G_IMPLEMENT_INTERFACE (G_TYPE_ICON, _gcr_memory_icon_iface_icon);
|
|
Packit |
b00eeb |
G_IMPLEMENT_INTERFACE (G_TYPE_LOADABLE_ICON, _gcr_memory_icon_iface_loadable_icon);
|
|
Packit |
b00eeb |
);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_memory_icon_init (GcrMemoryIcon *self)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_MEMORY_ICON, GcrMemoryIconPrivate));
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_memory_icon_finalize (GObject *obj)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrMemoryIcon *self = GCR_MEMORY_ICON (obj);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->destroy)
|
|
Packit |
b00eeb |
(self->pv->destroy) (self->pv->data);
|
|
Packit |
b00eeb |
g_free (self->pv->image_type);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
G_OBJECT_CLASS (_gcr_memory_icon_parent_class)->finalize (obj);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_memory_icon_class_init (GcrMemoryIconClass *klass)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_type_class_add_private (klass, sizeof (GcrMemoryIconPrivate));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
gobject_class->finalize = _gcr_memory_icon_finalize;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static gboolean
|
|
Packit |
b00eeb |
_gcr_memory_icon_equal (GIcon *icon1, GIcon *icon2)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrMemoryIcon *one = GCR_MEMORY_ICON (icon1);
|
|
Packit |
b00eeb |
GcrMemoryIcon *two = GCR_MEMORY_ICON (icon2);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (icon1 == icon2)
|
|
Packit |
b00eeb |
return TRUE;
|
|
Packit |
b00eeb |
if (!g_str_equal (one->pv->image_type, two->pv->image_type))
|
|
Packit |
b00eeb |
return FALSE;
|
|
Packit |
b00eeb |
if ((one->pv->n_data - one->pv->offset) != (two->pv->n_data - two->pv->offset))
|
|
Packit |
b00eeb |
return FALSE;
|
|
Packit |
b00eeb |
return memcmp ((guchar*)one->pv->data + one->pv->offset,
|
|
Packit |
b00eeb |
(guchar*)two->pv->data + two->pv->offset,
|
|
Packit |
b00eeb |
one->pv->n_data - one->pv->offset) == 0;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static guint
|
|
Packit |
b00eeb |
_gcr_memory_icon_hash (GIcon *icon)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrMemoryIcon *self = GCR_MEMORY_ICON (icon);
|
|
Packit |
b00eeb |
const signed char *p, *end;
|
|
Packit |
b00eeb |
guint32 hash;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
hash = g_str_hash (self->pv->image_type);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Adapted from g_str_hash */
|
|
Packit |
b00eeb |
p = self->pv->data;
|
|
Packit |
b00eeb |
end = p + self->pv->n_data;
|
|
Packit |
b00eeb |
p += self->pv->offset;
|
|
Packit |
b00eeb |
while (p < end)
|
|
Packit |
b00eeb |
hash = (hash << 5) + hash + *(p++);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return hash;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_memory_icon_iface_icon (GIconIface *iface)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
iface->equal = _gcr_memory_icon_equal;
|
|
Packit |
b00eeb |
iface->hash = _gcr_memory_icon_hash;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static GInputStream *
|
|
Packit |
b00eeb |
_gcr_memory_icon_load (GLoadableIcon *icon, int size, gchar **type,
|
|
Packit |
b00eeb |
GCancellable *cancellable, GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrMemoryIcon *self = GCR_MEMORY_ICON (icon);
|
|
Packit |
b00eeb |
GInputStream *is;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (type != NULL)
|
|
Packit |
b00eeb |
*type = g_strdup (self->pv->image_type);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
is = g_memory_input_stream_new_from_data ((guchar*)self->pv->data + self->pv->offset,
|
|
Packit |
b00eeb |
self->pv->n_data, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/*
|
|
Packit |
b00eeb |
* Hold a reference to this object from the stream, so that we can rely
|
|
Packit |
b00eeb |
* on the data hanging around.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
g_object_set_data_full (G_OBJECT (is), "back-reference", g_object_ref (self),
|
|
Packit |
b00eeb |
g_object_unref);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return is;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_memory_icon_load_async (GLoadableIcon *icon, int size, GCancellable *cancellable,
|
|
Packit |
b00eeb |
GAsyncReadyCallback callback, gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
res = g_simple_async_result_new (G_OBJECT (icon), callback, user_data,
|
|
Packit |
b00eeb |
_gcr_memory_icon_load_async);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_simple_async_result_complete_in_idle (res);
|
|
Packit |
b00eeb |
g_object_unref (res);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static GInputStream*
|
|
Packit |
b00eeb |
_gcr_memory_icon_finish (GLoadableIcon *icon, GAsyncResult *res, char **type,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_fail (g_simple_async_result_is_valid (res, G_OBJECT (icon),
|
|
Packit |
b00eeb |
_gcr_memory_icon_load_async), NULL);
|
|
Packit |
b00eeb |
return _gcr_memory_icon_load (icon, 0, type, NULL, error);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_memory_icon_iface_loadable_icon (GLoadableIconIface *iface)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
iface->load = _gcr_memory_icon_load;
|
|
Packit |
b00eeb |
iface->load_async = _gcr_memory_icon_load_async;
|
|
Packit |
b00eeb |
iface->load_finish = _gcr_memory_icon_finish;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* _gcr_memory_icon_new:
|
|
Packit |
b00eeb |
* @image_type: MIME content-type of the image.
|
|
Packit |
b00eeb |
* @data: Data for the image.
|
|
Packit |
b00eeb |
* @n_data: Length of data.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Create a new GIcon based on image data in memory. The data will be copied
|
|
Packit |
b00eeb |
* by the new icon.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: (transfer full) (type Gcr.MemoryIcon): A newly allocated icon.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
GIcon*
|
|
Packit |
b00eeb |
_gcr_memory_icon_new (const gchar *image_type, gconstpointer data, gsize n_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_fail (image_type != NULL, NULL);
|
|
Packit |
b00eeb |
g_return_val_if_fail (data != NULL, NULL);
|
|
Packit |
b00eeb |
g_return_val_if_fail (n_data != 0, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return _gcr_memory_icon_new_full (image_type, g_memdup (data, n_data),
|
|
Packit |
b00eeb |
n_data, 0, g_free);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* _gcr_memory_icon_new_full:
|
|
Packit |
b00eeb |
* @image_type: MIME content-type of the image.
|
|
Packit |
b00eeb |
* @data: Data for the image.
|
|
Packit |
b00eeb |
* @n_data: Length of data.
|
|
Packit |
b00eeb |
* @offset: Offset of the start of the image in @data.
|
|
Packit |
b00eeb |
* @destroy: Callback to free or release @data when no longer needed.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Create a new GIcon based on image data in memory. The data will be used
|
|
Packit |
b00eeb |
* directly from the @data passed. Use @destroy to control the lifetime of
|
|
Packit |
b00eeb |
* the data in memory.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: (transfer full): A newly allocated icon.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
GIcon*
|
|
Packit |
b00eeb |
_gcr_memory_icon_new_full (const gchar *image_type, gpointer data, gsize n_data,
|
|
Packit |
b00eeb |
goffset offset, GDestroyNotify destroy)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrMemoryIcon *self;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_val_if_fail (image_type != NULL, NULL);
|
|
Packit |
b00eeb |
g_return_val_if_fail (data != NULL, NULL);
|
|
Packit |
b00eeb |
g_return_val_if_fail (offset < n_data, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
self = g_object_new (GCR_TYPE_MEMORY_ICON, NULL);
|
|
Packit |
b00eeb |
self->pv->data = data;
|
|
Packit |
b00eeb |
self->pv->n_data = n_data;
|
|
Packit |
b00eeb |
self->pv->offset = offset;
|
|
Packit |
b00eeb |
self->pv->destroy = destroy;
|
|
Packit |
b00eeb |
self->pv->image_type = g_strdup (image_type);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return G_ICON (self);
|
|
Packit |
b00eeb |
}
|