2002-01-06 04:51:53 +00:00
|
|
|
/* Metacity Theme Rendering */
|
2001-05-31 16:18:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2001 Havoc Pennington
|
|
|
|
*
|
|
|
|
* 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 "theme.h"
|
2001-06-03 21:39:57 +00:00
|
|
|
#include "util.h"
|
2002-01-06 17:52:21 +00:00
|
|
|
#include "gradient.h"
|
2002-01-06 04:51:53 +00:00
|
|
|
#include <string.h>
|
2001-05-31 16:18:40 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
|
|
|
|
MetaGradientSpec*
|
|
|
|
meta_gradient_spec_new (MetaGradientType type)
|
2001-06-03 21:39:57 +00:00
|
|
|
{
|
2002-01-08 07:23:35 +00:00
|
|
|
MetaGradientSpec *spec;
|
|
|
|
|
|
|
|
spec = g_new (MetaGradientSpec, 1);
|
|
|
|
|
|
|
|
spec->type = type;
|
|
|
|
spec->color_specs = NULL;
|
2002-01-06 04:51:53 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
return spec;
|
2002-01-06 04:51:53 +00:00
|
|
|
}
|
2001-06-03 21:39:57 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
void
|
|
|
|
meta_gradient_spec_free (MetaGradientSpec *spec)
|
2002-01-06 04:51:53 +00:00
|
|
|
{
|
2002-01-08 07:23:35 +00:00
|
|
|
g_return_if_fail (spec != NULL);
|
|
|
|
|
|
|
|
g_slist_foreach (spec->color_specs, (GFunc) meta_color_spec_free, NULL);
|
|
|
|
g_slist_free (spec->color_specs);
|
|
|
|
g_free (spec);
|
|
|
|
}
|
2001-06-03 21:39:57 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
GdkPixbuf*
|
|
|
|
meta_gradient_spec_render (const MetaGradientSpec *spec,
|
|
|
|
GtkWidget *widget,
|
|
|
|
int width,
|
|
|
|
int height)
|
|
|
|
{
|
|
|
|
int n_colors;
|
|
|
|
GdkColor *colors;
|
|
|
|
GSList *tmp;
|
|
|
|
int i;
|
|
|
|
GdkPixbuf *pixbuf;
|
|
|
|
|
|
|
|
n_colors = g_slist_length (spec->color_specs);
|
2001-06-03 21:39:57 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
if (n_colors == 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
colors = g_new (GdkColor, n_colors);
|
2001-06-03 21:39:57 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
i = 0;
|
|
|
|
tmp = spec->color_specs;
|
|
|
|
while (tmp != NULL)
|
|
|
|
{
|
|
|
|
meta_color_spec_render (tmp->data, widget, &colors[i]);
|
|
|
|
|
|
|
|
tmp = tmp->next;
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
|
|
|
|
pixbuf = meta_gradient_create_multi (width, height,
|
|
|
|
colors, n_colors,
|
|
|
|
spec->type);
|
2001-06-03 21:39:57 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
g_free (colors);
|
2001-06-03 21:39:57 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
return pixbuf;
|
2001-06-03 18:33:59 +00:00
|
|
|
}
|
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
MetaColorSpec*
|
|
|
|
meta_color_spec_new (MetaColorSpecType type)
|
2001-06-03 18:33:59 +00:00
|
|
|
{
|
2002-01-08 07:23:35 +00:00
|
|
|
MetaColorSpec *spec;
|
|
|
|
MetaColorSpec dummy;
|
|
|
|
int size;
|
|
|
|
|
|
|
|
size = G_STRUCT_OFFSET (MetaColorSpec, data);
|
2001-06-01 03:00:01 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case META_COLOR_SPEC_BASIC:
|
|
|
|
size += sizeof (dummy.data.basic);
|
|
|
|
break;
|
2001-05-31 16:18:40 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
case META_COLOR_SPEC_GTK:
|
|
|
|
size += sizeof (dummy.data.gtk);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_COLOR_SPEC_BLEND:
|
|
|
|
size += sizeof (dummy.data.blend);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
spec = g_malloc0 (size);
|
2001-06-03 21:39:57 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
spec->type = type;
|
2001-06-03 21:39:57 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
return spec;
|
2002-01-06 04:51:53 +00:00
|
|
|
}
|
2001-06-03 21:39:57 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
void
|
|
|
|
meta_color_spec_free (MetaColorSpec *spec)
|
2002-01-06 04:51:53 +00:00
|
|
|
{
|
2002-01-08 07:23:35 +00:00
|
|
|
g_return_if_fail (spec != NULL);
|
|
|
|
|
|
|
|
switch (spec->type)
|
|
|
|
{
|
|
|
|
case META_COLOR_SPEC_BASIC:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_COLOR_SPEC_GTK:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_COLOR_SPEC_BLEND:
|
|
|
|
if (spec->data.blend.foreground)
|
|
|
|
meta_color_spec_free (spec->data.blend.foreground);
|
|
|
|
if (spec->data.blend.background)
|
|
|
|
meta_color_spec_free (spec->data.blend.background);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (spec);
|
2001-06-03 21:39:57 +00:00
|
|
|
}
|
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
void
|
|
|
|
meta_color_spec_render (MetaColorSpec *spec,
|
|
|
|
GtkWidget *widget,
|
|
|
|
GdkColor *color)
|
2001-06-03 21:39:57 +00:00
|
|
|
{
|
2002-01-08 07:23:35 +00:00
|
|
|
g_return_if_fail (spec != NULL);
|
|
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
g_return_if_fail (widget->style != NULL);
|
2002-01-06 04:51:53 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
switch (spec->type)
|
|
|
|
{
|
|
|
|
case META_COLOR_SPEC_BASIC:
|
|
|
|
*color = spec->data.basic.color;
|
|
|
|
break;
|
2001-06-03 21:39:57 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
case META_COLOR_SPEC_GTK:
|
|
|
|
switch (spec->data.gtk.component)
|
|
|
|
{
|
|
|
|
case GTK_RC_BG:
|
|
|
|
*color = widget->style->bg[spec->data.gtk.state];
|
|
|
|
break;
|
|
|
|
case GTK_RC_FG:
|
|
|
|
*color = widget->style->fg[spec->data.gtk.state];
|
|
|
|
break;
|
|
|
|
case GTK_RC_BASE:
|
|
|
|
*color = widget->style->base[spec->data.gtk.state];
|
|
|
|
break;
|
|
|
|
case GTK_RC_TEXT:
|
|
|
|
*color = widget->style->text[spec->data.gtk.state];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_COLOR_SPEC_BLEND:
|
|
|
|
{
|
|
|
|
GdkColor fg, bg;
|
|
|
|
int alpha;
|
|
|
|
|
|
|
|
meta_color_spec_render (spec->data.blend.foreground, widget, &fg);
|
|
|
|
meta_color_spec_render (spec->data.blend.background, widget, &bg);
|
|
|
|
|
|
|
|
*color = fg;
|
|
|
|
alpha = spec->data.blend.alpha * 0xffff;
|
|
|
|
color->red = color->red + (((bg.red - color->red) * alpha + 0x8000) >> 16);
|
|
|
|
color->green = color->green + (((bg.green - color->green) * alpha + 0x8000) >> 16);
|
|
|
|
color->blue = color->blue + (((bg.blue - color->blue) * alpha + 0x8000) >> 16);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2001-06-03 21:39:57 +00:00
|
|
|
|
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
MetaTextureSpec*
|
|
|
|
meta_texture_spec_new (MetaTextureType type)
|
|
|
|
{
|
|
|
|
MetaTextureSpec *spec;
|
|
|
|
MetaTextureSpec dummy;
|
|
|
|
int size;
|
2001-06-06 04:47:37 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
size = G_STRUCT_OFFSET (MetaTextureSpec, data);
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case META_TEXTURE_SOLID:
|
|
|
|
size += sizeof (dummy.data.solid);
|
|
|
|
break;
|
2001-06-06 04:47:37 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
case META_TEXTURE_GRADIENT:
|
|
|
|
size += sizeof (dummy.data.gradient);
|
|
|
|
break;
|
2001-06-06 04:47:37 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
case META_TEXTURE_IMAGE:
|
|
|
|
size += sizeof (dummy.data.image);
|
|
|
|
break;
|
2002-01-06 04:51:53 +00:00
|
|
|
}
|
2002-01-08 07:23:35 +00:00
|
|
|
|
|
|
|
spec = g_malloc0 (size);
|
2001-06-06 04:47:37 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
spec->type = type;
|
|
|
|
|
|
|
|
return spec;
|
2001-06-06 04:47:37 +00:00
|
|
|
}
|
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
void
|
|
|
|
meta_texture_spec_free (MetaTextureSpec *spec)
|
2001-05-31 16:18:40 +00:00
|
|
|
{
|
2002-01-08 07:23:35 +00:00
|
|
|
g_return_if_fail (spec != NULL);
|
2001-06-01 03:00:01 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
switch (spec->type)
|
2001-06-04 04:58:22 +00:00
|
|
|
{
|
2002-01-08 07:23:35 +00:00
|
|
|
case META_TEXTURE_SOLID:
|
|
|
|
if (spec->data.solid.color_spec)
|
|
|
|
meta_color_spec_free (spec->data.solid.color_spec);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_TEXTURE_GRADIENT:
|
|
|
|
if (spec->data.gradient.gradient_spec)
|
|
|
|
meta_gradient_spec_free (spec->data.gradient.gradient_spec);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_TEXTURE_IMAGE:
|
|
|
|
if (spec->data.image.pixbuf)
|
|
|
|
g_object_unref (G_OBJECT (spec->data.image.pixbuf));
|
|
|
|
break;
|
2001-06-04 04:58:22 +00:00
|
|
|
}
|
2001-06-06 04:47:37 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
g_free (spec);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
render_pixbuf (GdkDrawable *drawable,
|
|
|
|
const GdkRectangle *clip,
|
|
|
|
GdkPixbuf *pixbuf,
|
|
|
|
int x,
|
|
|
|
int y)
|
|
|
|
{
|
|
|
|
/* grumble, render_to_drawable_alpha does not accept a clip
|
|
|
|
* mask, so we have to go through some BS
|
|
|
|
*/
|
|
|
|
GdkRectangle pixbuf_rect;
|
|
|
|
GdkRectangle draw_rect;
|
2001-06-04 04:58:22 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
pixbuf_rect.x = x;
|
|
|
|
pixbuf_rect.y = y;
|
|
|
|
pixbuf_rect.width = gdk_pixbuf_get_width (pixbuf);
|
|
|
|
pixbuf_rect.height = gdk_pixbuf_get_height (pixbuf);
|
2001-06-03 21:39:57 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
if (clip)
|
2001-06-06 04:47:37 +00:00
|
|
|
{
|
2002-01-08 07:23:35 +00:00
|
|
|
if (!gdk_rectangle_intersect ((GdkRectangle*)clip,
|
|
|
|
&pixbuf_rect, &draw_rect))
|
|
|
|
return;
|
2001-06-03 21:39:57 +00:00
|
|
|
}
|
2002-01-08 07:23:35 +00:00
|
|
|
else
|
2002-01-06 17:52:21 +00:00
|
|
|
{
|
2002-01-08 07:23:35 +00:00
|
|
|
draw_rect = pixbuf_rect;
|
2002-01-06 17:52:21 +00:00
|
|
|
}
|
2001-06-03 21:39:57 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
gdk_pixbuf_render_to_drawable_alpha (pixbuf,
|
|
|
|
drawable,
|
|
|
|
draw_rect.x - pixbuf_rect.x,
|
|
|
|
draw_rect.y - pixbuf_rect.y,
|
|
|
|
draw_rect.x, draw_rect.y,
|
|
|
|
draw_rect.width,
|
|
|
|
draw_rect.height,
|
|
|
|
GDK_PIXBUF_ALPHA_FULL, /* ignored */
|
|
|
|
128, /* ignored */
|
|
|
|
GDK_RGB_DITHER_NORMAL,
|
|
|
|
draw_rect.x - pixbuf_rect.x,
|
|
|
|
draw_rect.y - pixbuf_rect.y);
|
|
|
|
}
|
2001-06-06 04:47:37 +00:00
|
|
|
|
2002-01-06 17:52:21 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
void
|
|
|
|
meta_texture_spec_draw (const MetaTextureSpec *spec,
|
|
|
|
GtkWidget *widget,
|
|
|
|
GdkDrawable *drawable,
|
|
|
|
const GdkRectangle *clip,
|
|
|
|
MetaTextureDrawMode mode,
|
|
|
|
int x,
|
|
|
|
int y,
|
|
|
|
int width,
|
|
|
|
int height)
|
|
|
|
{
|
|
|
|
g_return_if_fail (spec != NULL);
|
|
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
g_return_if_fail (GDK_IS_DRAWABLE (drawable));
|
|
|
|
g_return_if_fail (widget->style != NULL);
|
2001-06-02 04:14:18 +00:00
|
|
|
|
2002-01-08 07:23:35 +00:00
|
|
|
switch (spec->type)
|
|
|
|
{
|
|
|
|
case META_TEXTURE_SOLID:
|
|
|
|
{
|
|
|
|
GdkGC *gc;
|
|
|
|
GdkGCValues values;
|
|
|
|
|
|
|
|
g_return_if_fail (spec->data.solid.color_spec != NULL);
|
|
|
|
|
|
|
|
meta_color_spec_render (spec->data.solid.color_spec,
|
|
|
|
widget,
|
|
|
|
&values.foreground);
|
|
|
|
|
|
|
|
gdk_rgb_find_color (widget->style->colormap, &values.foreground);
|
|
|
|
gc = gdk_gc_new_with_values (drawable, &values, GDK_GC_FOREGROUND);
|
|
|
|
|
|
|
|
gdk_draw_rectangle (drawable,
|
|
|
|
gc, TRUE, x, y, width, height);
|
|
|
|
|
|
|
|
g_object_unref (G_OBJECT (gc));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_TEXTURE_GRADIENT:
|
|
|
|
{
|
|
|
|
GdkPixbuf *pixbuf;
|
|
|
|
|
|
|
|
g_return_if_fail (spec->data.gradient.gradient_spec != NULL);
|
|
|
|
|
|
|
|
pixbuf = meta_gradient_spec_render (spec->data.gradient.gradient_spec,
|
|
|
|
widget, width, height);
|
|
|
|
|
|
|
|
if (pixbuf == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
render_pixbuf (drawable, clip, pixbuf, x, y);
|
|
|
|
|
|
|
|
g_object_unref (G_OBJECT (pixbuf));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_TEXTURE_IMAGE:
|
|
|
|
{
|
|
|
|
GdkPixbuf *pixbuf;
|
|
|
|
|
|
|
|
g_return_if_fail (spec->data.image.pixbuf != NULL);
|
|
|
|
|
|
|
|
pixbuf = NULL;
|
|
|
|
|
|
|
|
switch (mode)
|
|
|
|
{
|
|
|
|
case META_TEXTURE_DRAW_UNSCALED:
|
|
|
|
pixbuf = spec->data.image.pixbuf;
|
|
|
|
g_object_ref (G_OBJECT (pixbuf));
|
|
|
|
break;
|
|
|
|
case META_TEXTURE_DRAW_SCALED_VERTICALLY:
|
|
|
|
pixbuf = spec->data.image.pixbuf;
|
|
|
|
if (gdk_pixbuf_get_height (pixbuf) == height)
|
|
|
|
{
|
|
|
|
g_object_ref (G_OBJECT (pixbuf));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pixbuf = gdk_pixbuf_scale_simple (pixbuf,
|
|
|
|
gdk_pixbuf_get_width (pixbuf),
|
|
|
|
height,
|
|
|
|
GDK_INTERP_BILINEAR);
|
|
|
|
if (pixbuf == NULL)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case META_TEXTURE_DRAW_SCALED_HORIZONTALLY:
|
|
|
|
pixbuf = spec->data.image.pixbuf;
|
|
|
|
if (gdk_pixbuf_get_width (pixbuf) == width)
|
|
|
|
{
|
|
|
|
g_object_ref (G_OBJECT (pixbuf));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pixbuf = gdk_pixbuf_scale_simple (pixbuf,
|
|
|
|
width,
|
|
|
|
gdk_pixbuf_get_height (pixbuf),
|
|
|
|
GDK_INTERP_BILINEAR);
|
|
|
|
if (pixbuf == NULL)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case META_TEXTURE_DRAW_SCALED_BOTH:
|
|
|
|
pixbuf = spec->data.image.pixbuf;
|
|
|
|
if (gdk_pixbuf_get_width (pixbuf) == width &&
|
|
|
|
gdk_pixbuf_get_height (pixbuf) == height)
|
|
|
|
{
|
|
|
|
g_object_ref (G_OBJECT (pixbuf));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pixbuf = gdk_pixbuf_scale_simple (pixbuf,
|
|
|
|
width, height,
|
|
|
|
GDK_INTERP_BILINEAR);
|
|
|
|
if (pixbuf == NULL)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_return_if_fail (pixbuf != NULL);
|
|
|
|
|
|
|
|
render_pixbuf (drawable, clip, pixbuf, x, y);
|
|
|
|
|
|
|
|
g_object_unref (G_OBJECT (pixbuf));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2001-05-31 16:18:40 +00:00
|
|
|
}
|