/* * Copyright (C) 2011 Benjamin Otte * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "game-private.h" #include "game-image-resource.h" #include #include "game-image.h" enum { PROP_0, PROP_DATA, PROP_SIZE, PROP_SURFACE }; G_DEFINE_TYPE (GameImageResource, game_image_resource, GAME_TYPE_DATA_RESOURCE) static const GameRectangle game_image_resource_default_size = { 0, 0, 1, 1 }; static void game_image_resource_get_property (GObject *object, guint param_id, GValue *value, GParamSpec * pspec) { GameImageResource *resource = GAME_IMAGE_RESOURCE (object); switch (param_id) { case PROP_DATA: g_value_set_object (value, resource->data); break; case PROP_SIZE: g_value_set_boxed (value, &resource->size); break; case PROP_SURFACE: g_value_set_boxed (value, resource->surface); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; } } static void game_image_resource_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec) { GameImageResource *resource = GAME_IMAGE_RESOURCE (object); switch (param_id) { case PROP_DATA: game_image_resource_set_data (resource, g_value_get_object (value)); break; case PROP_SIZE: game_image_resource_set_size (resource, g_value_get_boxed (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; } } static void game_image_resource_dispose (GObject *object) { GameImageResource *resource = GAME_IMAGE_RESOURCE (object); game_image_resource_set_data (resource, NULL); G_OBJECT_CLASS (game_image_resource_parent_class)->dispose (object); } static gboolean game_image_resource_load (GameResource *res, GVariantIter *iter) { GameImageResource *resource = GAME_IMAGE_RESOURCE (res); GameDataResource *data; GVariant *variant; if (!GAME_RESOURCE_CLASS (game_image_resource_parent_class)->load (res, iter)) return FALSE; if (!g_variant_iter_next (iter, "d", &resource->size.x1) || !g_variant_iter_next (iter, "d", &resource->size.y1) || !g_variant_iter_next (iter, "d", &resource->size.x2) || !g_variant_iter_next (iter, "d", &resource->size.y2) || !g_variant_iter_next (iter, "v", &variant)) return FALSE; resource->size.x2 += resource->size.x1; resource->size.y2 += resource->size.y1; data = GAME_DATA_RESOURCE (game_resource_load (GAME_OBJECT (resource)->game, variant)); game_image_resource_set_data (resource, data); g_object_unref (data); g_variant_unref (variant); return TRUE; } static void game_image_resource_save (GameResource *res, GVariantBuilder *builder) { GameImageResource *resource = GAME_IMAGE_RESOURCE (res); GVariant *variant; GAME_RESOURCE_CLASS (game_image_resource_parent_class)->save (res, builder); variant = game_resource_save (GAME_RESOURCE (resource->data)); g_variant_builder_add (builder, "ddddv", resource->size.x1, resource->size.y1, resource->size.x2 - resource->size.x1, resource->size.y2 - resource->size.y1, variant); g_variant_unref (variant); } static GameObject * game_image_resource_spawn (GameResource *res) { GameImageResource *resource = GAME_IMAGE_RESOURCE (res); return game_game_add_object (GAME_OBJECT (resource)->game, GAME_TYPE_IMAGE, "x", resource->size.x1, "y", resource->size.y1, "width", resource->size.x2 - resource->size.x1, "height", resource->size.y2 - resource->size.y1, "surface", resource->surface, NULL); } static void game_image_resource_class_init (GameImageResourceClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GameResourceClass *resource_class = GAME_RESOURCE_CLASS (klass); object_class->set_property = game_image_resource_set_property; object_class->get_property = game_image_resource_get_property; object_class->dispose = game_image_resource_dispose; g_object_class_install_property (object_class, PROP_DATA, g_param_spec_object ("data", _("data"), _("resource providing image data"), GAME_TYPE_DATA_RESOURCE, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_SURFACE, g_param_spec_boxed ("surface", _("surface"), _("surface created from image data"), CAIRO_GOBJECT_TYPE_SURFACE, G_PARAM_READABLE)); g_object_class_install_property (object_class, PROP_SIZE, g_param_spec_boxed ("sizee", _("size"), _("size the surface should be scaled to"), GAME_TYPE_RECTANGLE, G_PARAM_READWRITE)); resource_class->load = game_image_resource_load; resource_class->save = game_image_resource_save; resource_class->spawn = game_image_resource_spawn; } static void game_image_resource_init (GameImageResource *resource) { resource->size = game_image_resource_default_size; } cairo_surface_t * game_image_resource_get_surface (GameImageResource *resource) { g_return_val_if_fail (GAME_IS_IMAGE_RESOURCE (resource), NULL); return resource->surface; } GameDataResource * game_image_resource_get_data (GameImageResource *resource) { g_return_val_if_fail (GAME_IS_IMAGE_RESOURCE (resource), NULL); return resource->data; } cairo_surface_t * game_image_resource_load_surface (GameDataResource *data) { GdkPixbufLoader *loader; cairo_surface_t *surface; GError *error = NULL; loader = gdk_pixbuf_loader_new (); if (!gdk_pixbuf_loader_write (loader, game_data_resource_get_data (data), game_data_resource_get_size (data), &error) || !gdk_pixbuf_loader_close (loader, &error)) { g_warning ("Could not load image: %s", error->message); g_error_free (error); return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0); } surface = game_cairo_surface_from_pixbuf (gdk_pixbuf_loader_get_pixbuf (loader)); g_object_unref (loader); return surface; } void game_image_resource_set_data (GameImageResource *resource, GameDataResource *data) { g_return_if_fail (GAME_IS_IMAGE_RESOURCE (resource)); g_return_if_fail (data == NULL || GAME_IS_DATA_RESOURCE (data)); if (resource->data) { g_object_unref (resource->data); resource->data = NULL; cairo_surface_destroy (resource->surface); resource->surface = NULL; } if (data) { resource->data = g_object_ref (data); resource->surface = game_image_resource_load_surface (resource->data); } g_object_notify (G_OBJECT (resource), "data"); g_object_notify (G_OBJECT (resource), "surface"); } const GameRectangle * game_image_resource_get_size (GameImageResource *resource) { g_return_val_if_fail (GAME_IS_IMAGE_RESOURCE (resource), NULL); return &resource->size; } void game_image_resource_set_size (GameImageResource * resource, const GameRectangle *rect) { g_return_if_fail (GAME_IS_IMAGE_RESOURCE (resource)); if (rect == NULL) rect = &game_image_resource_default_size; resource->size = *rect; g_object_notify (G_OBJECT (resource), "size"); }