/* -*- Mode: C; indent-tabs-mode: nil; tab-width: 2 -*-
 *
 * Copyright (C) 2009 Canonical Ltd.
 * Authors:
 *  Gustavo Sverzut Barbieri <gustavo.barbieri@canonical.com>
 *
 * This file is part of Netbook Launcher EFL.
 *
 * Netbook Launcher EFL 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, version 3 of the License.
 *
 * Netbook Launcher EFL 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 Netbook Launcher EFL.  If not, see <http://www.gnu.org/licenses/>.
 *
 * NOTE: this file is basically Esmart_Cairo from esmart package, that
 *       Gustavo Sverzut Barbieri (in this case, myself), wrote. It's
 *       copied here to save on distribution and packaging
 *       things. Since he wrote the file, he licensed it to GPLv3, as
 *       allowed by copyright laws and also original license.
 */

#include "netbook-launcher.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>

static const char DATA_KEY[] = "evas_cairo_surface";

static void
_evas_image_cairo_destroy_surface(Evas_Object *o)
{
   cairo_surface_t *surface;

   surface = evas_object_data_del(o, DATA_KEY);
   if (!surface)
     return;

   cairo_surface_destroy(surface);
}

static void
_evas_image_cairo_died(void *data, Evas *e, Evas_Object *o, void *einfo)
{
   _evas_image_cairo_destroy_surface(o);
}

Evas_Object *
evas_image_cairo_new(Evas *evas, Evas_Coord w, Evas_Coord h, Eina_Bool alpha)
{
   cairo_surface_t *surface;
   cairo_format_t format;

   if (alpha)
     format = CAIRO_FORMAT_ARGB32;
   else
     format = CAIRO_FORMAT_RGB24;

   surface = cairo_image_surface_create(format, w, h);

   return evas_image_cairo_new_from_surface(evas, surface);
}

Evas_Object *
evas_image_cairo_new_from_surface(Evas *evas, cairo_surface_t *cairo_surface)
{
   Evas_Object *o;

   o = evas_object_image_add(evas);
   if (!o)
     return NULL;

   if (!evas_image_cairo_surface_set(o, cairo_surface))
     {
	evas_object_del(o);
	return NULL;
     }

   return o;
}

cairo_surface_t *
evas_image_cairo_surface_get(Evas_Object *o)
{
   return evas_object_data_get(o, DATA_KEY);
}

Eina_Bool
evas_image_cairo_surface_set(Evas_Object *o, cairo_surface_t *cairo_surface)
{
   cairo_status_t status;
   cairo_format_t format;
   cairo_surface_type_t type;
   Evas_Coord w, h;
   int has_alpha;

   if (!o)
     {
	ERR("o == NULL");
	return 0;
     }

   if (!cairo_surface)
     {
	evas_object_event_callback_del(
           o, EVAS_CALLBACK_DEL, _evas_image_cairo_died);
	_evas_image_cairo_destroy_surface(o);
	return 1;
     }

   status = cairo_surface_status(cairo_surface);
   if (status != CAIRO_STATUS_SUCCESS)
     {
	ERR("invalid status for cairo surface: %s",
	    cairo_status_to_string(status));
	return 0;
     }

   type = cairo_surface_get_type(cairo_surface);
   if (type != CAIRO_SURFACE_TYPE_IMAGE)
     {
	ERR("invalid surface type: %d, expected %d",
	    type, CAIRO_SURFACE_TYPE_IMAGE);
	return 0;
     }

   format = cairo_image_surface_get_format(cairo_surface);
   if (format == CAIRO_FORMAT_ARGB32)
     has_alpha = 1;
   else if (format == CAIRO_FORMAT_RGB24)
     has_alpha = 0;
   else
     {
	ERR("unsupported format for given surface: %d", format);
	return 0;
     }

   _evas_image_cairo_destroy_surface(o);

   w = cairo_image_surface_get_width(cairo_surface);
   h = cairo_image_surface_get_height(cairo_surface);

   evas_object_image_alpha_set(o, has_alpha);
   evas_object_image_size_set(o, w, h);
   evas_object_image_fill_set(o, 0, 0, w, h);
   evas_object_image_data_set(o, cairo_image_surface_get_data(cairo_surface));
   evas_object_resize(o, w, h);

   evas_object_data_set(o, DATA_KEY, cairo_surface);

   evas_object_event_callback_del(
      o, EVAS_CALLBACK_DEL, _evas_image_cairo_died);
   evas_object_event_callback_add(
      o, EVAS_CALLBACK_DEL, _evas_image_cairo_died, NULL);

   return 1;
}

static void
_evas_image_cairo_fill_auto(Evas_Object *o)
{
   Evas_Coord w, h;

   evas_object_geometry_get(o, NULL, NULL, &w, &h);
   evas_object_image_fill_set(o, 0, 0, w, h);
}

static void
_evas_image_cairo_resized(void *data, Evas *e, Evas_Object *o, void *einfo)
{
   _evas_image_cairo_fill_auto(o);
}

void
evas_image_cairo_fill_auto_set(Evas_Object *o, Eina_Bool enable)
{
   evas_object_event_callback_del(
      o, EVAS_CALLBACK_RESIZE, _evas_image_cairo_resized);

   if (enable)
     {
	evas_object_event_callback_add(
           o, EVAS_CALLBACK_RESIZE, _evas_image_cairo_resized, NULL);
	_evas_image_cairo_fill_auto(o);
     }
   else
     {
	cairo_surface_t *cairo_surface;
	int w, h;

	cairo_surface = evas_object_data_get(o, DATA_KEY);
	if (!cairo_surface)
	  {
	     ERR("no cairo surface found for object");
	     return;
	  }

	w = cairo_image_surface_get_width(cairo_surface);
	h = cairo_image_surface_get_height(cairo_surface);
	evas_object_image_fill_set(o, 0, 0, w, h);
     }
}
