diff --git a/ChangeLog b/ChangeLog index 5f114570d..4a36e016b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2002-01-06 Havoc Pennington + + * src/theme.c (meta_theme_get_gradient): change to use spiffy + gradient code. + + * src/gradient.c: copy lovely gradient code from WindowMaker, + as usual Dan and Alfredo have very nice code + 2002-01-06 Fatih Demir * configure.in: Added "tr" to the languages list. @@ -9,7 +17,7 @@ dumb-looking * src/theme.c: replace old theme.[hc] contents with newer stuff - that doesn't do anything + that doesn't do anything 2002-01-05 Havoc Pennington diff --git a/src/Makefile.am b/src/Makefile.am index 7bca75d24..81f254349 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,6 +21,8 @@ metacity_SOURCES= \ frame.h \ frames.c \ frames.h \ + gradient.c \ + gradient.h \ inlinepixbufs.h \ keybindings.c \ keybindings.h \ @@ -57,6 +59,12 @@ bin_PROGRAMS=metacity metacity_LDADD= @METACITY_LIBS@ +testgradient_SOURCES=gradient.h gradient.c testgradient.c + +noinst_PROGRAMS=testgradient + +testgradient_LDADD= @METACITY_LIBS@ + desktopfilesdir=$(datadir)/gnome/wm-properties desktopfiles_DATA=metacity.desktop diff --git a/src/frames.c b/src/frames.c index 6a6549ae1..10dd5af71 100644 --- a/src/frames.c +++ b/src/frames.c @@ -1758,41 +1758,42 @@ meta_frames_expose_event (GtkWidget *widget, layout_gc = widget->style->fg_gc[GTK_STATE_NORMAL]; if (flags & META_FRAME_HAS_FOCUS) { + GdkPixbuf *gradient; + layout_gc = widget->style->fg_gc[GTK_STATE_SELECTED]; -#if 0 - /* Draw blue background */ - gdk_draw_rectangle (frame->window, - widget->style->bg_gc[GTK_STATE_SELECTED], - TRUE, - fgeom.title_rect.x, - fgeom.title_rect.y, - fgeom.title_rect.width, - fgeom.title_rect.height); -#else - { - GdkPixbuf *gradient; + gradient = meta_theme_get_gradient (META_GRADIENT_DIAGONAL, + &widget->style->bg[GTK_STATE_SELECTED], + &widget->style->bg[GTK_STATE_NORMAL], + fgeom.title_rect.width, + fgeom.title_rect.height); - gradient = meta_theme_get_gradient (META_GRADIENT_HORIZONTAL, - &widget->style->bg[GTK_STATE_SELECTED], - &widget->style->bg[GTK_STATE_NORMAL], - fgeom.title_rect.width, - fgeom.title_rect.height); - - gdk_pixbuf_render_to_drawable (gradient, - frame->window, - widget->style->bg_gc[GTK_STATE_SELECTED], - 0, 0, - fgeom.title_rect.x, - fgeom.title_rect.y, - fgeom.title_rect.width, - fgeom.title_rect.height, - GDK_RGB_DITHER_NORMAL, - 0, 0); - - g_object_unref (G_OBJECT (gradient)); - } -#endif + if (gradient != NULL) + { + gdk_pixbuf_render_to_drawable (gradient, + frame->window, + widget->style->bg_gc[GTK_STATE_SELECTED], + 0, 0, + fgeom.title_rect.x, + fgeom.title_rect.y, + fgeom.title_rect.width, + fgeom.title_rect.height, + GDK_RGB_DITHER_NORMAL, + 0, 0); + + g_object_unref (G_OBJECT (gradient)); + } + else + { + /* Fallback to plain selection color */ + gdk_draw_rectangle (frame->window, + widget->style->bg_gc[GTK_STATE_SELECTED], + TRUE, + fgeom.title_rect.x, + fgeom.title_rect.y, + fgeom.title_rect.width, + fgeom.title_rect.height); + } } if (frame->layout) diff --git a/src/gradient.c b/src/gradient.c new file mode 100644 index 000000000..61cb32bf1 --- /dev/null +++ b/src/gradient.c @@ -0,0 +1,853 @@ +/* Metacity gradient rendering */ + +/* + * Copyright (C) 2001 Havoc Pennington, 99% copied from wrlib in + * WindowMaker, Copyright (C) 1997-2000 Dan Pascu and Alfredo Kojima + * + * 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 "gradient.h" +#include + +/* This is all Alfredo's and Dan's usual very nice WindowMaker code, + * slightly GTK-ized + */ +static GdkPixbuf* meta_gradient_create_horizontal (int width, + int height, + const GdkColor *from, + const GdkColor *to); +static GdkPixbuf* meta_gradient_create_vertical (int width, + int height, + const GdkColor *from, + const GdkColor *to); +static GdkPixbuf* meta_gradient_create_diagonal (int width, + int height, + const GdkColor *from, + const GdkColor *to); +static GdkPixbuf* meta_gradient_create_multi_horizontal (int width, + int height, + const GdkColor *colors, + int count); +static GdkPixbuf* meta_gradient_create_multi_vertical (int width, + int height, + const GdkColor *colors, + int count); +static GdkPixbuf* meta_gradient_create_multi_diagonal (int width, + int height, + const GdkColor *colors, + int count); + + +/* Used as the destroy notification function for gdk_pixbuf_new() */ +static void +free_buffer (guchar *pixels, gpointer data) +{ + g_free (pixels); +} + +static GdkPixbuf* +blank_pixbuf (int width, int height, gboolean no_padding) +{ + guchar *buf; + int rowstride; + + g_return_val_if_fail (width > 0, NULL); + g_return_val_if_fail (height > 0, NULL); + + if (no_padding) + rowstride = width * 3; + else + /* Always align rows to 32-bit boundaries */ + rowstride = 4 * ((3 * width + 3) / 4); + + buf = g_try_malloc (height * rowstride); + if (!buf) + return NULL; + + return gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB, + FALSE, 8, + width, height, rowstride, + free_buffer, NULL); +} + +GdkPixbuf* +meta_gradient_create_simple (int width, + int height, + const GdkColor *from, + const GdkColor *to, + MetaGradientType style) +{ + switch (style) + { + case META_GRADIENT_HORIZONTAL: + return meta_gradient_create_horizontal (width, height, + from, to); + case META_GRADIENT_VERTICAL: + return meta_gradient_create_vertical (width, height, + from, to); + + case META_GRADIENT_DIAGONAL: + return meta_gradient_create_diagonal (width, height, + from, to); + } + g_assert_not_reached (); + return NULL; +} + +GdkPixbuf* +meta_gradient_create_multi (int width, + int height, + const GdkColor *colors, + int n_colors, + MetaGradientType style) +{ + + if (n_colors > 2) + { + switch (style) + { + case META_GRADIENT_HORIZONTAL: + return meta_gradient_create_multi_horizontal (width, height, colors, n_colors); + case META_GRADIENT_VERTICAL: + return meta_gradient_create_multi_vertical (width, height, colors, n_colors); + case META_GRADIENT_DIAGONAL: + return meta_gradient_create_multi_diagonal (width, height, colors, n_colors); + } + } + else if (n_colors > 1) + { + return meta_gradient_create_simple (width, height, &colors[0], &colors[1], + style); + } + else if (n_colors > 0) + { + return meta_gradient_create_simple (width, height, &colors[0], &colors[0], + style); + } + g_assert_not_reached (); + return NULL; +} + +/* Interwoven essentially means we have two vertical gradients, + * cut into horizontal strips of the given thickness, and then the strips + * are alternated. I'm not sure what it's good for, just copied since + * WindowMaker had it. + */ +GdkPixbuf* +meta_gradient_create_interwoven (int width, + int height, + const GdkColor colors1[2], + int thickness1, + const GdkColor colors2[2], + int thickness2) +{ + + int i, j, k, l, ll; + long r1, g1, b1, dr1, dg1, db1; + long r2, g2, b2, dr2, dg2, db2; + GdkPixbuf *pixbuf; + unsigned char *ptr; + unsigned char rr, gg, bb; + unsigned char *pixels; + int rowstride; + + pixbuf = blank_pixbuf (width, height, FALSE); + if (pixbuf == NULL) + return NULL; + + pixels = gdk_pixbuf_get_pixels (pixbuf); + rowstride = gdk_pixbuf_get_rowstride (pixbuf); + + r1 = colors1[0].red<<8; + g1 = colors1[0].green<<8; + b1 = colors1[0].blue<<8; + + r2 = colors2[0].red<<8; + g2 = colors2[0].green<<8; + b2 = colors2[0].blue<<8; + + dr1 = ((colors1[1].red-colors1[0].red)<<8)/(int)height; + dg1 = ((colors1[1].green-colors1[0].green)<<8)/(int)height; + db1 = ((colors1[1].blue-colors1[0].blue)<<8)/(int)height; + + dr2 = ((colors2[1].red-colors2[0].red)<<8)/(int)height; + dg2 = ((colors2[1].green-colors2[0].green)<<8)/(int)height; + db2 = ((colors2[1].blue-colors2[0].blue)<<8)/(int)height; + + for (i=0,k=0,l=0,ll=thickness1; i>16; + gg = g1>>16; + bb = b1>>16; + } + else + { + rr = r2>>16; + gg = g2>>16; + bb = b2>>16; + } + for (j=0; jred / 256.0); + g0 = (guchar) (from->green / 256.0); + b0 = (guchar) (from->blue / 256.0); + rf = (guchar) (to->red / 256.0); + gf = (guchar) (to->green / 256.0); + bf = (guchar) (to->blue / 256.0); + + r = r0 << 16; + g = g0 << 16; + b = b0 << 16; + + dr = ((rf-r0)<<16)/(int)width; + dg = ((gf-g0)<<16)/(int)width; + db = ((bf-b0)<<16)/(int)width; + /* render the first line */ + for (i=0; i>16); + *(ptr++) = (unsigned char)(g>>16); + *(ptr++) = (unsigned char)(b>>16); + r += dr; + g += dg; + b += db; + } + + /* copy the first line to the other lines */ + for (i=1; ired / 256.0); + g0 = (guchar) (from->green / 256.0); + b0 = (guchar) (from->blue / 256.0); + rf = (guchar) (to->red / 256.0); + gf = (guchar) (to->green / 256.0); + bf = (guchar) (to->blue / 256.0); + + r = r0<<16; + g = g0<<16; + b = b0<<16; + + dr = ((rf-r0)<<16)/(int)height; + dg = ((gf-g0)<<16)/(int)height; + db = ((bf-b0)<<16)/(int)height; + + for (i=0; i>16; + gg = g>>16; + bb = b>>16; + for (j=0; jred / 256.0); + g0 = (guchar) (from->green / 256.0); + b0 = (guchar) (from->blue / 256.0); + rf = (guchar) (to->red / 256.0); + gf = (guchar) (to->green / 256.0); + bf = (guchar) (to->blue / 256.0); + + ptr = gdk_pixbuf_get_pixels (tmp); + + a = ((float)(width - 1))/((float)(height - 1)); + width = width * 3; + + /* copy the first line to the other lines with corresponding offset */ + for (j=0, offset=0.0; j 2, NULL); + + pixbuf = blank_pixbuf (width, height, FALSE); + if (pixbuf == NULL) + return NULL; + + pixels = gdk_pixbuf_get_pixels (pixbuf); + rowstride = gdk_pixbuf_get_rowstride (pixbuf); + ptr = pixels; + + if (count > width) + count = width; + + if (count > 1) + width2 = width/(count-1); + else + width2 = width; + + k = 0; + + r = colors[0].red << 8; + g = colors[0].green << 8; + b = colors[0].blue << 8; + + /* render the first line */ + for (i=1; i>16); + *ptr++ = (unsigned char)(g>>16); + *ptr++ = (unsigned char)(b>>16); + r += dr; + g += dg; + b += db; + k++; + } + r = colors[i].red << 8; + g = colors[i].green << 8; + b = colors[i].blue << 8; + } + for (j=k; j>16); + *ptr++ = (unsigned char)(g>>16); + *ptr++ = (unsigned char)(b>>16); + } + + /* copy the first line to the other lines */ + for (i=1; i 2, NULL); + + pixbuf = blank_pixbuf (width, height, FALSE); + if (pixbuf == NULL) + return NULL; + + pixels = gdk_pixbuf_get_pixels (pixbuf); + rowstride = gdk_pixbuf_get_rowstride (pixbuf); + pad = rowstride - (width * 3); + ptr = pixels; + + if (count > height) + count = height; + + if (count > 1) + height2 = height/(count-1); + else + height2 = height; + + k = 0; + + r = colors[0].red << 8; + g = colors[0].green << 8; + b = colors[0].blue << 8; + + for (i=1; i>16; + gg = g>>16; + bb = b>>16; + + for (x=0; x>16; + gg = g>>16; + bb = b>>16; + + if (k 2, NULL); + + if (width == 1) + return meta_gradient_create_multi_vertical (width, height, colors, count); + else if (height == 1) + return meta_gradient_create_multi_horizontal (width, height, colors, count); + + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, + width, height); + if (pixbuf == NULL) + return NULL; + + pixels = gdk_pixbuf_get_pixels (pixbuf); + rowstride = gdk_pixbuf_get_rowstride (pixbuf); + + if (count > width) + count = width; + if (count > height) + count = height; + + /* FIXME here again is a bug that requires multi_horizontal + * to have width == rowstride + */ + if (count > 2) + tmp = meta_gradient_create_multi_horizontal (2*width-1, 1, colors, count); + else + /* wrlib multiplies these colors by 256 before passing them in, but + * I think it's a bug in wrlib, so changed here. I could be wrong + * though, if we notice two-color multi diagonals not working. + */ + tmp = meta_gradient_create_horizontal (2*width-1, 1, + &colors[0], &colors[1]); + + if (!tmp) + { + g_object_unref (G_OBJECT (pixbuf)); + return NULL; + } + ptr = gdk_pixbuf_get_pixels (tmp); + + a = ((float)(width - 1))/((float)(height - 1)); + width = width * 3; + + /* copy the first line to the other lines with corresponding offset */ + for (j=0, offset=0; j + +typedef void (* RenderGradientFunc) (GdkDrawable *drawable, + GdkGC *gc, + int width, + int height); + +static void +render_simple (GdkDrawable *drawable, + GdkGC *gc, + int width, int height, + MetaGradientType type) +{ + GdkPixbuf *pixbuf; + GdkColor from, to; + + gdk_color_parse ("blue", &from); + gdk_color_parse ("green", &to); + + pixbuf = meta_gradient_create_simple (width, height, + &from, &to, + type); + + gdk_pixbuf_render_to_drawable (pixbuf, + drawable, + gc, + 0, 0, + 0, 0, width, height, + GDK_RGB_DITHER_NORMAL, + 0, 0); + + g_object_unref (G_OBJECT (pixbuf)); +} + +static void +render_vertical_func (GdkDrawable *drawable, + GdkGC *gc, + int width, int height) +{ + render_simple (drawable, gc, width, height, META_GRADIENT_VERTICAL); +} + +static void +render_horizontal_func (GdkDrawable *drawable, + GdkGC *gc, + int width, int height) +{ + render_simple (drawable, gc, width, height, META_GRADIENT_HORIZONTAL); +} + +static void +render_diagonal_func (GdkDrawable *drawable, + GdkGC *gc, + int width, int height) +{ + render_simple (drawable, gc, width, height, META_GRADIENT_DIAGONAL); +} + +static gboolean +expose_callback (GtkWidget *widget, + GdkEventExpose *event, + gpointer data) +{ + RenderGradientFunc func = data; + + (* func) (widget->window, + widget->style->fg_gc[widget->state], + widget->allocation.width, + widget->allocation.height); + + return TRUE; +} + +static GtkWidget* +create_gradient_window (RenderGradientFunc func) +{ + GtkWidget *window; + GtkWidget *drawing_area; + + window = gtk_window_new (GTK_WINDOW_POPUP); + + drawing_area = gtk_drawing_area_new (); + + gtk_widget_set_size_request (drawing_area, 175, 175); + + g_signal_connect (G_OBJECT (drawing_area), + "expose_event", + G_CALLBACK (expose_callback), + func); + + gtk_container_add (GTK_CONTAINER (window), drawing_area); + + return window; +} + +void +meta_gradient_test (void) +{ + GtkWidget *window; + + window = create_gradient_window (render_vertical_func); + gtk_window_move (GTK_WINDOW (window), 0, 0); + gtk_widget_show_all (window); + + window = create_gradient_window (render_horizontal_func); + gtk_window_move (GTK_WINDOW (window), 0, 200); + gtk_widget_show_all (window); + + window = create_gradient_window (render_diagonal_func); + gtk_window_move (GTK_WINDOW (window), 200, 0); + gtk_widget_show_all (window); +} +#endif + diff --git a/src/gradient.h b/src/gradient.h new file mode 100644 index 000000000..079150cac --- /dev/null +++ b/src/gradient.h @@ -0,0 +1,53 @@ +/* Metacity gradient rendering */ + +/* + * Copyright (C) 2001 Havoc Pennington, 99% copied from wrlib in + * WindowMaker, Copyright (C) 1997-2000 Dan Pascu and Alfredo Kojima + * + * 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. */ + +#ifndef META_GRADIENT_H +#define META_GRADIENT_H + +#include +#include + +typedef enum +{ + META_GRADIENT_VERTICAL, + META_GRADIENT_HORIZONTAL, + META_GRADIENT_DIAGONAL +} MetaGradientType; + + +GdkPixbuf* meta_gradient_create_simple (int width, + int height, + const GdkColor *from, + const GdkColor *to, + MetaGradientType style); +GdkPixbuf* meta_gradient_create_multi (int width, + int height, + const GdkColor *colors, + int n_colors, + MetaGradientType style); +GdkPixbuf* meta_gradient_create_interwoven (int width, + int height, + const GdkColor colors1[2], + int thickness1, + const GdkColor colors2[2], + int thickness2); + +#endif diff --git a/src/testgradient.c b/src/testgradient.c new file mode 100644 index 000000000..aac882a3a --- /dev/null +++ b/src/testgradient.c @@ -0,0 +1,246 @@ +/* Metacity gradient test program */ + +/* + * Copyright (C) 2002 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 "gradient.h" +#include + +typedef void (* RenderGradientFunc) (GdkDrawable *drawable, + GdkGC *gc, + int width, + int height); + +static void +render_simple (GdkDrawable *drawable, + GdkGC *gc, + int width, int height, + MetaGradientType type) +{ + GdkPixbuf *pixbuf; + GdkColor from, to; + + gdk_color_parse ("blue", &from); + gdk_color_parse ("green", &to); + + pixbuf = meta_gradient_create_simple (width, height, + &from, &to, + type); + + gdk_pixbuf_render_to_drawable (pixbuf, + drawable, + gc, + 0, 0, + 0, 0, width, height, + GDK_RGB_DITHER_NORMAL, + 0, 0); + + g_object_unref (G_OBJECT (pixbuf)); +} + +static void +render_vertical_func (GdkDrawable *drawable, + GdkGC *gc, + int width, int height) +{ + render_simple (drawable, gc, width, height, META_GRADIENT_VERTICAL); +} + +static void +render_horizontal_func (GdkDrawable *drawable, + GdkGC *gc, + int width, int height) +{ + render_simple (drawable, gc, width, height, META_GRADIENT_HORIZONTAL); +} + +static void +render_diagonal_func (GdkDrawable *drawable, + GdkGC *gc, + int width, int height) +{ + render_simple (drawable, gc, width, height, META_GRADIENT_DIAGONAL); +} + +static void +render_multi (GdkDrawable *drawable, + GdkGC *gc, + int width, int height, + MetaGradientType type) +{ + GdkPixbuf *pixbuf; +#define N_COLORS 5 + GdkColor colors[N_COLORS]; + + gdk_color_parse ("red", &colors[0]); + gdk_color_parse ("blue", &colors[1]); + gdk_color_parse ("orange", &colors[2]); + gdk_color_parse ("pink", &colors[3]); + gdk_color_parse ("green", &colors[4]); + + pixbuf = meta_gradient_create_multi (width, height, + colors, N_COLORS, + type); + + gdk_pixbuf_render_to_drawable (pixbuf, + drawable, + gc, + 0, 0, + 0, 0, width, height, + GDK_RGB_DITHER_NORMAL, + 0, 0); + + g_object_unref (G_OBJECT (pixbuf)); +} + +static void +render_vertical_multi_func (GdkDrawable *drawable, + GdkGC *gc, + int width, int height) +{ + render_multi (drawable, gc, width, height, META_GRADIENT_VERTICAL); +} + +static void +render_horizontal_multi_func (GdkDrawable *drawable, + GdkGC *gc, + int width, int height) +{ + render_multi (drawable, gc, width, height, META_GRADIENT_HORIZONTAL); +} + +static void +render_diagonal_multi_func (GdkDrawable *drawable, + GdkGC *gc, + int width, int height) +{ + render_multi (drawable, gc, width, height, META_GRADIENT_DIAGONAL); +} + +static void +render_interwoven_func (GdkDrawable *drawable, + GdkGC *gc, + int width, int height) +{ + GdkPixbuf *pixbuf; +#define N_COLORS 4 + GdkColor colors[N_COLORS]; + + gdk_color_parse ("red", &colors[0]); + gdk_color_parse ("blue", &colors[1]); + gdk_color_parse ("pink", &colors[2]); + gdk_color_parse ("green", &colors[3]); + + pixbuf = meta_gradient_create_interwoven (width, height, + colors, height / 10, + colors + 2, height / 14); + + gdk_pixbuf_render_to_drawable (pixbuf, + drawable, + gc, + 0, 0, + 0, 0, width, height, + GDK_RGB_DITHER_NORMAL, + 0, 0); + + g_object_unref (G_OBJECT (pixbuf)); +} + +static gboolean +expose_callback (GtkWidget *widget, + GdkEventExpose *event, + gpointer data) +{ + RenderGradientFunc func = data; + + (* func) (widget->window, + widget->style->fg_gc[widget->state], + widget->allocation.width, + widget->allocation.height); + + return TRUE; +} + +static GtkWidget* +create_gradient_window (const char *title, + RenderGradientFunc func) +{ + GtkWidget *window; + GtkWidget *drawing_area; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + + gtk_window_set_title (GTK_WINDOW (window), title); + + drawing_area = gtk_drawing_area_new (); + + gtk_widget_set_size_request (drawing_area, 1, 1); + + gtk_window_set_default_size (GTK_WINDOW (window), 175, 175); + + g_signal_connect (G_OBJECT (drawing_area), + "expose_event", + G_CALLBACK (expose_callback), + func); + + gtk_container_add (GTK_CONTAINER (window), drawing_area); + + gtk_widget_show_all (window); + + return window; +} + +static void +meta_gradient_test (void) +{ + GtkWidget *window; + + window = create_gradient_window ("Simple vertical", + render_vertical_func); + + window = create_gradient_window ("Simple horizontal", + render_horizontal_func); + + window = create_gradient_window ("Simple diagonal", + render_diagonal_func); + + window = create_gradient_window ("Multi vertical", + render_vertical_multi_func); + + window = create_gradient_window ("Multi horizontal", + render_horizontal_multi_func); + + window = create_gradient_window ("Multi diagonal", + render_diagonal_multi_func); + + window = create_gradient_window ("Interwoven", + render_interwoven_func); +} + +int +main (int argc, char **argv) +{ + gtk_init (&argc, &argv); + + meta_gradient_test (); + + gtk_main (); + + return 0; +} + diff --git a/src/theme.c b/src/theme.c index ada597a93..c42a33677 100644 --- a/src/theme.c +++ b/src/theme.c @@ -21,8 +21,10 @@ #include "theme.h" #include "util.h" +#include "gradient.h" #include +#if 0 /* fill_gradient routine from GNOME background-properties, CVS says * Michael Fulbright checked it in, Copyright 1998 Red Hat Inc. */ @@ -101,6 +103,7 @@ fill_gradient (GdkPixbuf *pixbuf, g_free (row); } +#endif typedef struct _CachedGradient CachedGradient; @@ -236,8 +239,8 @@ meta_theme_get_gradient (MetaGradientType type, "Requesting %s gradient one %d/%d/%d two %d/%d/%d " "%d x %d\n", type == META_GRADIENT_VERTICAL ? "vertical" : "horizontal", - color_one->red / 255, color_one->green / 255, color_one->blue / 255, - color_two->red / 255, color_two->green / 255, color_two->blue / 255, + color_one->red / 256, color_one->green / 256, color_one->blue / 256, + color_two->red / 256, color_two->green / 256, color_two->blue / 256, width, height); if (gradient_cache == NULL) @@ -266,6 +269,7 @@ meta_theme_get_gradient (MetaGradientType type, return cached->pixbuf; } +#if 0 gradient.pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, gradient.width, gradient.height); @@ -276,24 +280,50 @@ meta_theme_get_gradient (MetaGradientType type, gradient.width, gradient.height, 0, 0); +#else + gradient.pixbuf = meta_gradient_create_simple (gradient.width, + gradient.height, + &gradient.color_one, + &gradient.color_two, + type); - cached = g_new (CachedGradient, 1); - *cached = gradient; + if (gradient.pixbuf == NULL) + { + meta_topic (META_DEBUG_GRADIENT_CACHE, + "Not enough memory to create gradient of size %d bytes\n", + GRADIENT_SIZE (&gradient)); + return NULL; + } +#endif - g_hash_table_insert (gradient_cache, cached, cached); + if (GRADIENT_SIZE (&gradient) > MAX_CACHE_SIZE) + { + cached = g_new (CachedGradient, 1); + *cached = gradient; + + g_hash_table_insert (gradient_cache, cached, cached); - meta_topic (META_DEBUG_GRADIENT_CACHE, - "Caching newly-created gradient, size is %d bytes, total cache size %d bytes %d gradients, maximum %d bytes\n", - GRADIENT_SIZE (cached), - cache_size, g_hash_table_size (gradient_cache), MAX_CACHE_SIZE); + meta_topic (META_DEBUG_GRADIENT_CACHE, + "Caching newly-created gradient, size is %d bytes, total cache size %d bytes %d gradients, maximum %d bytes\n", + GRADIENT_SIZE (cached), + cache_size, g_hash_table_size (gradient_cache), MAX_CACHE_SIZE); - cache_size += GRADIENT_SIZE (cached); + cache_size += GRADIENT_SIZE (cached); + + g_object_ref (G_OBJECT (cached->pixbuf)); /* to return to caller */ + retval = cached->pixbuf; - g_object_ref (G_OBJECT (cached->pixbuf)); /* to return to caller */ - retval = cached->pixbuf; - - if (cache_size > MAX_CACHE_SIZE) - expire_some_old_gradients (); /* may unref "cached->pixbuf" and free "cached" */ + if (cache_size > MAX_CACHE_SIZE) + expire_some_old_gradients (); /* may unref "cached->pixbuf" and free "cached" */ + } + else + { + meta_topic (META_DEBUG_GRADIENT_CACHE, + "Gradient of size %d bytes is too large to cache\n", + GRADIENT_SIZE (&gradient)); + + retval = gradient.pixbuf; + } return retval; } diff --git a/src/theme.h b/src/theme.h index ee273678a..8a3cbae98 100644 --- a/src/theme.h +++ b/src/theme.h @@ -23,16 +23,12 @@ #define META_THEME_H #include "frames.h" +#include "gradient.h" /* theme.[hc] is basically responsible for drawing parts of the UI using * theme data */ -typedef enum -{ - META_GRADIENT_VERTICAL, - META_GRADIENT_HORIZONTAL -} MetaGradientType; GdkPixbuf* meta_theme_get_gradient (MetaGradientType type, const GdkColor *color_one,