/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * Copyright (C) 2003 Richard Hult <richard@imendio.com>
 *
 * 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 of the
 * License, 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 <config.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include "drw-utils.h"

static GdkPixbuf *
create_tile_pixbuf (GdkPixbuf    *dest_pixbuf,
		    GdkPixbuf    *src_pixbuf,
		    GdkRectangle *field_geom,
		    guint         alpha,
		    GdkColor     *bg_color) 
{
	gboolean need_composite;
	gboolean use_simple;
	gdouble  cx, cy;
	gdouble  colorv;
	gint     pwidth, pheight;

	need_composite = (alpha < 255 || gdk_pixbuf_get_has_alpha (src_pixbuf));
	use_simple = (dest_pixbuf == NULL);

	if (dest_pixbuf == NULL)
		dest_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
					      FALSE, 8,
					      field_geom->width, field_geom->height);

	if (need_composite && use_simple)
		colorv = ((bg_color->red & 0xff00) << 8) |
			(bg_color->green & 0xff00) |
			((bg_color->blue & 0xff00) >> 8);
	else
		colorv = 0;

	pwidth = gdk_pixbuf_get_width (src_pixbuf);
	pheight = gdk_pixbuf_get_height (src_pixbuf);

	for (cy = 0; cy < field_geom->height; cy += pheight) {
		for (cx = 0; cx < field_geom->width; cx += pwidth) {
			if (need_composite && !use_simple)
				gdk_pixbuf_composite (src_pixbuf, dest_pixbuf,
						      cx, cy,
						      MIN (pwidth, field_geom->width - cx), 
						      MIN (pheight, field_geom->height - cy),
						      cx, cy,
						      1.0, 1.0,
						      GDK_INTERP_BILINEAR,
						      alpha);
			else if (need_composite && use_simple)
				gdk_pixbuf_composite_color (src_pixbuf, dest_pixbuf,
							    cx, cy,
							    MIN (pwidth, field_geom->width - cx), 
							    MIN (pheight, field_geom->height - cy),
							    cx, cy,
							    1.0, 1.0,
							    GDK_INTERP_BILINEAR,
							    alpha,
							    65536, 65536, 65536,
							    colorv, colorv);
			else
				gdk_pixbuf_copy_area (src_pixbuf,
						      0, 0,
						      MIN (pwidth, field_geom->width - cx),
						      MIN (pheight, field_geom->height - cy),
						      dest_pixbuf,
						      cx, cy);
		}
	}

	return dest_pixbuf;
}

static gboolean
window_expose_event (GtkWidget      *widget,
		     GdkEventExpose *event,
		     gpointer        data)
{
	cairo_t         *context;
	cairo_t         *cr;
	cairo_surface_t *surface;
	int              width;
	int              height;

	context = gdk_cairo_create (widget->window);

	cairo_set_operator (context, CAIRO_OPERATOR_SOURCE);
	gtk_window_get_size (GTK_WINDOW (widget), &width, &height);

	surface = cairo_surface_create_similar (cairo_get_target (context),
						CAIRO_CONTENT_COLOR_ALPHA,
						width,
						height);

	if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS) {
		goto done;
	}

	cr = cairo_create (surface);
	if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) {
		goto done;
	}
	cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0);
	cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
	cairo_paint (cr);

	/* draw a box */
	cairo_rectangle (cr, 0, 0, width, height);
	cairo_set_source_rgba (cr, 0.2, 0.2, 0.2, 0.5);
	cairo_fill (cr);

	cairo_destroy (cr);

	cairo_set_source_surface (context, surface, 0, 0);
	cairo_paint (context);

 done:
	if (surface != NULL) {
		cairo_surface_destroy (surface);
	}
	cairo_destroy (context);

	return FALSE;
}

static void
set_pixmap_background (GtkWidget *window)
{
	GdkScreen    *screen;
	GdkPixbuf    *tmp_pixbuf, *pixbuf, *tile_pixbuf;
	GdkPixmap    *pixmap;
	GdkRectangle  rect;
	GdkColor      color;
	gint          width, height;

	gtk_widget_realize (window);

	screen = gtk_widget_get_screen (window);
	width = gdk_screen_get_width (screen);
	height = gdk_screen_get_height (screen);

	tmp_pixbuf = gdk_pixbuf_get_from_drawable (NULL,
						   gdk_screen_get_root_window (screen),
						   gdk_screen_get_system_colormap (screen),
						   0,
						   0,
						   0,
						   0,
						   width, height);

	pixbuf = gdk_pixbuf_new_from_file (IMAGEDIR "/ocean-stripes.png", NULL);

	rect.x = 0;
	rect.y = 0;
	rect.width = width;
	rect.height = height;

	color.red = 0;
	color.blue = 0;
	color.green = 0;

	tile_pixbuf = create_tile_pixbuf (NULL,
					  pixbuf,
					  &rect,
					  155,
					  &color);

	g_object_unref (pixbuf);

	gdk_pixbuf_composite (tile_pixbuf,
			      tmp_pixbuf,
			      0,
			      0,
			      width,
			      height,
			      0,
			      0,
			      1,
			      1,
			      GDK_INTERP_NEAREST,
			      225);

	g_object_unref (tile_pixbuf);

	pixmap = gdk_pixmap_new (GTK_WIDGET (window)->window,
				 width,
				 height,
				 -1);

	gdk_pixbuf_render_to_drawable_alpha (tmp_pixbuf,
					     pixmap,
					     0,
					     0,
					     0,
					     0,
					     width,
					     height,
					     GDK_PIXBUF_ALPHA_BILEVEL,
					     0,
					     GDK_RGB_DITHER_NONE,
					     0,
					     0);
	g_object_unref (tmp_pixbuf);

	gdk_window_set_back_pixmap (window->window, pixmap, FALSE);
	g_object_unref (pixmap);
}

void
drw_setup_background (GtkWidget *window)
{
	GdkScreen    *screen;
	GdkColormap  *colormap;
	gboolean      is_composited;

	screen = gtk_widget_get_screen (window);
	colormap = gdk_screen_get_rgba_colormap (screen);

	if (colormap != NULL && gdk_screen_is_composited (screen)) {
		gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
		is_composited = TRUE;
	} else {
		is_composited = FALSE;
	}

	if (is_composited) {
		g_signal_connect (window, "expose-event", G_CALLBACK (window_expose_event), window);
	} else {
		set_pixmap_background (window);
	}
}

