Initial revision

This commit is contained in:
Owen Taylor 2000-02-07 02:36:39 +00:00
parent 45cb0268b9
commit 1ac1bfb995
6 changed files with 2549 additions and 0 deletions

View File

@ -0,0 +1,88 @@
Sun Feb 6 21:34:30 2000 Owen Taylor <otaylor@redhat.com>
* Started ChangeLog for pixbuf engine, check sources
into CVS.
========== ChangeLog for pixmap engine ===================
1999-11-22 Martin Baulig <martin@home-of-linux.org>
* pixmap_theme_main.c (theme_duplicate_style): Really copy the
`src_data->img_list', not just the pointer that points to it.
Tue Oct 5 15:13:29 1999 Owen Taylor <otaylor@redhat.com>
* pixmap_theme_draw.c (apply_theme_image): Don't set
background pixmap on pixmaps.
1999-02-14 Raja R Harinath <harinath@cs.umn.edu>
* Theme/gtk/Makefile.am.in (Makefile.am): Handle the case when
files are deleted.
Thu Feb 11 21:16:53 1999 Owen Taylor <otaylor@redhat.com>
* pixmap_theme_main.c (theme_data_unref): Free the
theme data structure as well as the contents.
1999-02-03 Raja R Harinath <harinath@cs.umn.edu>
* Theme/gtk/Makefile.am.in: New file. Theme/gtk/Makefile.am is
generated from this file when new *.png files are added.
1999-01-23 Miguel de Icaza <miguel@nuclecu.unam.mx>
* pixmap_theme_main.c (theme_init): Turn on pixmap cache.
Mon Jan 18 13:37:23 1999 Owen Taylor <otaylor@redhat.com>
* Theme/gtk/gtkrc: Give buttons a gray background
color so they look a little less funny when initially
drawing.
Wed Jan 13 18:58:25 1999 Owen Taylor <otaylor@redhat.com>
* pixmap_theme_draw.c: Fixed pervasive mis-bracketing
that was causing drawing if the drawn region and
clipping region did NOT intersect, and a couple
of errors in computing source and destination
regions.
1998-11-09 Federico Mena Quintero <federico@nuclecu.unam.mx>
* pixmap_theme_draw.c: #include <math.h>
1998-11-07 Raja R Harinath <harinath@cs.umn.edu>
* Theme/gtk/Makefile.am (theme_DATA):
Update to new directory contents.
* configure.in: Remove.
Fri Nov 6 17:26:12 1998 Owen Taylor <otaylor@redhat.com>
* pixmap_theme_main.c: Removed some debugging
printf's.
* Theme/gtk/notebook1.c Theme/gtk/menubar.png: new
bigger pixmaps to reduce pixelation.
* Theme/gtk/gtkrc: Reorganized to use several styles
instead of one huge style. Change clist backgrounds
to be prettier.
Thu Nov 5 10:23:46 1998 Owen Taylor <otaylor@redhat.com>
* pixmap_theme_draw.c (draw_shadow_gap): Fixed hard-coded
gap_side of '0'.
Mon Nov 2 14:46:02 1998 Owen Taylor <otaylor@redhat.com>
* pixmap_theme_draw.c (apply_theme_image_shadow_gap): Removed
several hundred lines of duplicated code with a bit of
reoriganization.
Wed Oct 28 16:18:04 1998 Owen Taylor <otaylor@redhat.com>
* pixmap_theme_main.c (theme_symbols): Removed lots
and lots of white space.

View File

@ -0,0 +1,17 @@
The code in this directory is a GTK+ theme engine based on the earlier
pixmap theme engine.
The config files are meant to be compatible, but instead of rendering
using Imlib, it renders using GdkPixbuf. This makes the memory
management much more understandable, and also allows us to use
GdkPixbuf's high quality scaling.
Most of the code was reworked/rewritten in the process to make it more
understandable and maintainable.
There are lots of bugs here, a considersable number of bugs. But it's
cleaned up a great deal from the older pixmap engine. Please don't
make it uglier again.
Owen Taylor <otaylor@redhat.com>
6 February 2000

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,878 @@
/* GTK+ Pixbuf Engine
* Copyright (C) 1998-2000 Red Hat Software
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Written by Owen Taylor <otaylor@redhat.com>, based on code by
* Carsten Haitzler <raster@rasterman.com>
*/
#include "pixmap_theme.h"
#include "pixmap_theme.h"
#include <gmodule.h>
/* Theme functions to export */
void theme_init(GtkThemeEngine * engine);
void theme_exit(void);
static struct
{
gchar *name;
guint token;
}
theme_symbols[] =
{
{ "image", TOKEN_IMAGE },
{ "function", TOKEN_FUNCTION },
{ "file", TOKEN_FILE },
{ "stretch", TOKEN_STRETCH },
{ "recolorable", TOKEN_RECOLORABLE },
{ "border", TOKEN_BORDER },
{ "detail", TOKEN_DETAIL },
{ "state", TOKEN_STATE },
{ "shadow", TOKEN_SHADOW },
{ "gap_side", TOKEN_GAP_SIDE },
{ "gap_file", TOKEN_GAP_FILE },
{ "gap_border", TOKEN_GAP_BORDER },
{ "gap_start_file", TOKEN_GAP_START_FILE },
{ "gap_start_border", TOKEN_GAP_START_BORDER },
{ "gap_end_file", TOKEN_GAP_END_FILE },
{ "gap_end_border", TOKEN_GAP_END_BORDER },
{ "overlay_file", TOKEN_OVERLAY_FILE },
{ "overlay_border", TOKEN_OVERLAY_BORDER },
{ "overlay_stretch", TOKEN_OVERLAY_STRETCH },
{ "arrow_direction", TOKEN_ARROW_DIRECTION },
{ "orientation", TOKEN_ORIENTATION },
{ "HLINE", TOKEN_D_HLINE },
{ "VLINE", TOKEN_D_VLINE },
{ "SHADOW", TOKEN_D_SHADOW },
{ "POLYGON", TOKEN_D_POLYGON },
{ "ARROW", TOKEN_D_ARROW },
{ "DIAMOND", TOKEN_D_DIAMOND },
{ "OVAL", TOKEN_D_OVAL },
{ "STRING", TOKEN_D_STRING },
{ "BOX", TOKEN_D_BOX },
{ "FLAT_BOX", TOKEN_D_FLAT_BOX },
{ "CHECK", TOKEN_D_CHECK },
{ "OPTION", TOKEN_D_OPTION },
{ "CROSS", TOKEN_D_CROSS },
{ "RAMP", TOKEN_D_RAMP },
{ "TAB", TOKEN_D_TAB },
{ "SHADOW_GAP", TOKEN_D_SHADOW_GAP },
{ "BOX_GAP", TOKEN_D_BOX_GAP },
{ "EXTENSION", TOKEN_D_EXTENSION },
{ "FOCUS", TOKEN_D_FOCUS },
{ "SLIDER", TOKEN_D_SLIDER },
{ "ENTRY", TOKEN_D_ENTRY },
{ "HANDLE", TOKEN_D_HANDLE },
{ "TRUE", TOKEN_TRUE },
{ "FALSE", TOKEN_FALSE },
{ "TOP", TOKEN_TOP },
{ "UP", TOKEN_UP },
{ "BOTTOM", TOKEN_BOTTOM },
{ "DOWN", TOKEN_DOWN },
{ "LEFT", TOKEN_LEFT },
{ "RIGHT", TOKEN_RIGHT },
{ "NORMAL", TOKEN_NORMAL },
{ "ACTIVE", TOKEN_ACTIVE },
{ "PRELIGHT", TOKEN_PRELIGHT },
{ "SELECTED", TOKEN_SELECTED },
{ "INSENSITIVE", TOKEN_INSENSITIVE },
{ "NONE", TOKEN_NONE },
{ "IN", TOKEN_IN },
{ "OUT", TOKEN_OUT },
{ "ETCHED_IN", TOKEN_ETCHED_IN },
{ "ETCHED_OUT", TOKEN_ETCHED_OUT },
{ "HORIZONTAL", TOKEN_HORIZONTAL },
{ "VERTICAL", TOKEN_VERTICAL },
};
static guint n_theme_symbols = sizeof(theme_symbols) / sizeof(theme_symbols[0]);
static guint
theme_parse_file(GScanner *scanner,
ThemePixbuf **theme_pb)
{
guint token;
gchar *pixmap;
/* Skip 'blah_file' */
token = g_scanner_get_next_token(scanner);
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN)
return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_STRING)
return G_TOKEN_STRING;
if (!*theme_pb)
*theme_pb = theme_pixbuf_new ();
pixmap = gtk_rc_find_pixmap_in_path(scanner, scanner->value.v_string);
if (pixmap)
{
theme_pixbuf_set_filename (*theme_pb, pixmap);
g_free (pixmap);
}
return G_TOKEN_NONE;
}
static guint
theme_parse_border (GScanner *scanner,
ThemePixbuf **theme_pb)
{
guint token;
gint left, right, top, bottom;
/* Skip 'blah_border' */
token = g_scanner_get_next_token(scanner);
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN)
return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_LEFT_CURLY)
return G_TOKEN_LEFT_CURLY;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_INT)
return G_TOKEN_INT;
left = scanner->value.v_int;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_COMMA)
return G_TOKEN_COMMA;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_INT)
return G_TOKEN_INT;
right = scanner->value.v_int;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_COMMA)
return G_TOKEN_COMMA;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_INT)
return G_TOKEN_INT;
top = scanner->value.v_int;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_COMMA)
return G_TOKEN_COMMA;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_INT)
return G_TOKEN_INT;
bottom = scanner->value.v_int;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_RIGHT_CURLY)
return G_TOKEN_RIGHT_CURLY;
if (!*theme_pb)
*theme_pb = theme_pixbuf_new ();
theme_pixbuf_set_border (*theme_pb, left, right, top, bottom);
return G_TOKEN_NONE;
}
static guint
theme_parse_stretch(GScanner *scanner,
ThemePixbuf **theme_pb)
{
guint token;
gboolean stretch;
/* Skip 'blah_stretch' */
token = g_scanner_get_next_token(scanner);
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN)
return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token == TOKEN_TRUE)
stretch = TRUE;
else if (token == TOKEN_FALSE)
stretch = FALSE;
else
return TOKEN_TRUE;
if (!*theme_pb)
*theme_pb = theme_pixbuf_new ();
theme_pixbuf_set_stretch (*theme_pb, stretch);
return G_TOKEN_NONE;
}
static guint
theme_parse_recolorable(GScanner * scanner,
ThemeImage * data)
{
guint token;
token = g_scanner_get_next_token(scanner);
if (token != TOKEN_RECOLORABLE)
return TOKEN_RECOLORABLE;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN)
return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token == TOKEN_TRUE)
data->recolorable = 1;
else if (token == TOKEN_FALSE)
data->recolorable = 0;
else
return TOKEN_TRUE;
return G_TOKEN_NONE;
}
static guint
theme_parse_function(GScanner * scanner,
ThemeImage *data)
{
guint token;
token = g_scanner_get_next_token(scanner);
if (token != TOKEN_FUNCTION)
return TOKEN_FUNCTION;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN)
return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if ((token >= TOKEN_D_HLINE) && (token <= TOKEN_D_HANDLE))
data->match_data.function = token;
return G_TOKEN_NONE;
}
static guint
theme_parse_detail(GScanner * scanner,
ThemeImage * data)
{
guint token;
token = g_scanner_get_next_token(scanner);
if (token != TOKEN_DETAIL)
return TOKEN_DETAIL;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN)
return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_STRING)
return G_TOKEN_STRING;
if (data->match_data.detail)
g_free (data->match_data.detail);
data->match_data.detail = g_strdup(scanner->value.v_string);
return G_TOKEN_NONE;
}
static guint
theme_parse_state(GScanner * scanner,
ThemeImage * data)
{
guint token;
token = g_scanner_get_next_token(scanner);
if (token != TOKEN_STATE)
return TOKEN_STATE;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN)
return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token == TOKEN_NORMAL)
data->match_data.state = GTK_STATE_NORMAL;
else if (token == TOKEN_ACTIVE)
data->match_data.state = GTK_STATE_ACTIVE;
else if (token == TOKEN_PRELIGHT)
data->match_data.state = GTK_STATE_PRELIGHT;
else if (token == TOKEN_SELECTED)
data->match_data.state = GTK_STATE_SELECTED;
else if (token == TOKEN_INSENSITIVE)
data->match_data.state = GTK_STATE_INSENSITIVE;
else
return TOKEN_NORMAL;
data->match_data.flags |= THEME_MATCH_STATE;
return G_TOKEN_NONE;
}
static guint
theme_parse_shadow(GScanner * scanner,
ThemeImage * data)
{
guint token;
token = g_scanner_get_next_token(scanner);
if (token != TOKEN_SHADOW)
return TOKEN_SHADOW;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN)
return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token == TOKEN_NONE)
data->match_data.shadow = GTK_SHADOW_NONE;
else if (token == TOKEN_IN)
data->match_data.shadow = GTK_SHADOW_IN;
else if (token == TOKEN_OUT)
data->match_data.shadow = GTK_SHADOW_OUT;
else if (token == TOKEN_ETCHED_IN)
data->match_data.shadow = GTK_SHADOW_ETCHED_IN;
else if (token == TOKEN_ETCHED_OUT)
data->match_data.shadow = GTK_SHADOW_ETCHED_OUT;
else
return TOKEN_NONE;
data->match_data.flags |= THEME_MATCH_SHADOW;
return G_TOKEN_NONE;
}
static guint
theme_parse_arrow_direction(GScanner * scanner,
ThemeImage * data)
{
guint token;
token = g_scanner_get_next_token(scanner);
if (token != TOKEN_ARROW_DIRECTION)
return TOKEN_ARROW_DIRECTION;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN)
return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token == TOKEN_UP)
data->match_data.arrow_direction = GTK_ARROW_UP;
else if (token == TOKEN_DOWN)
data->match_data.arrow_direction = GTK_ARROW_DOWN;
else if (token == TOKEN_LEFT)
data->match_data.arrow_direction = GTK_ARROW_LEFT;
else if (token == TOKEN_RIGHT)
data->match_data.arrow_direction = GTK_ARROW_RIGHT;
else
return TOKEN_UP;
data->match_data.flags |= THEME_MATCH_ARROW_DIRECTION;
return G_TOKEN_NONE;
}
static guint
theme_parse_gap_side(GScanner * scanner,
ThemeImage * data)
{
guint token;
token = g_scanner_get_next_token(scanner);
if (token != TOKEN_GAP_SIDE)
return TOKEN_GAP_SIDE;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN)
return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token == TOKEN_TOP)
data->match_data.gap_side = GTK_POS_TOP;
else if (token == TOKEN_BOTTOM)
data->match_data.gap_side = GTK_POS_BOTTOM;
else if (token == TOKEN_LEFT)
data->match_data.gap_side = GTK_POS_LEFT;
else if (token == TOKEN_RIGHT)
data->match_data.gap_side = GTK_POS_RIGHT;
else
return TOKEN_TOP;
data->match_data.flags |= THEME_MATCH_GAP_SIDE;
return G_TOKEN_NONE;
}
static guint
theme_parse_orientation(GScanner * scanner,
ThemeImage * data)
{
guint token;
token = g_scanner_get_next_token(scanner);
if (token != TOKEN_ORIENTATION)
return TOKEN_ORIENTATION;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN)
return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token == TOKEN_HORIZONTAL)
data->match_data.orientation = GTK_ORIENTATION_HORIZONTAL;
else if (token == TOKEN_VERTICAL)
data->match_data.orientation = GTK_ORIENTATION_VERTICAL;
else
return TOKEN_HORIZONTAL;
data->match_data.flags |= THEME_MATCH_ORIENTATION;
return G_TOKEN_NONE;
}
static void
theme_image_ref (ThemeImage *data)
{
data->refcount++;
}
static void
theme_image_unref (ThemeImage *data)
{
data->refcount--;
if (data->refcount == 0)
{
if (data->match_data.detail)
g_free (data->match_data.detail);
if (data->background)
theme_pixbuf_destroy (data->background);
if (data->overlay)
theme_pixbuf_destroy (data->overlay);
if (data->gap_start)
theme_pixbuf_destroy (data->gap_start);
if (data->gap)
theme_pixbuf_destroy (data->gap);
if (data->gap_end)
theme_pixbuf_destroy (data->gap_end);
g_free (data);
}
}
static void
theme_data_ref (ThemeData *theme_data)
{
theme_data->refcount++;
}
static void
theme_data_unref (ThemeData *theme_data)
{
theme_data->refcount--;
if (theme_data->refcount == 0)
{
g_list_foreach (theme_data->img_list, (GFunc) theme_image_unref, NULL);
g_list_free (theme_data->img_list);
g_free (theme_data);
}
}
static guint
theme_parse_image(GScanner *scanner,
ThemeData *theme_data,
ThemeImage **data_return)
{
guint token;
ThemeImage *data;
data = NULL;
token = g_scanner_get_next_token(scanner);
if (token != TOKEN_IMAGE)
return TOKEN_IMAGE;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_LEFT_CURLY)
return G_TOKEN_LEFT_CURLY;
data = g_malloc(sizeof(ThemeImage));
data->refcount = 1;
data->background = NULL;
data->overlay = NULL;
data->gap_start = NULL;
data->gap = NULL;
data->gap_end = NULL;
data->recolorable = FALSE;
data->match_data.function = 0;
data->match_data.detail = NULL;
data->match_data.flags = 0;
token = g_scanner_peek_next_token(scanner);
while (token != G_TOKEN_RIGHT_CURLY)
{
switch (token)
{
case TOKEN_FUNCTION:
token = theme_parse_function(scanner, data);
break;
case TOKEN_RECOLORABLE:
token = theme_parse_recolorable(scanner, data);
break;
case TOKEN_DETAIL:
token = theme_parse_detail(scanner, data);
break;
case TOKEN_STATE:
token = theme_parse_state(scanner, data);
break;
case TOKEN_SHADOW:
token = theme_parse_shadow(scanner, data);
break;
case TOKEN_GAP_SIDE:
token = theme_parse_gap_side(scanner, data);
break;
case TOKEN_ARROW_DIRECTION:
token = theme_parse_arrow_direction(scanner, data);
break;
case TOKEN_ORIENTATION:
token = theme_parse_orientation(scanner, data);
break;
case TOKEN_FILE:
token = theme_parse_file(scanner, &data->background);
break;
case TOKEN_BORDER:
token = theme_parse_border(scanner, &data->background);
break;
case TOKEN_STRETCH:
token = theme_parse_stretch(scanner, &data->background);
break;
case TOKEN_GAP_FILE:
token = theme_parse_file(scanner, &data->gap);
break;
case TOKEN_GAP_BORDER:
token = theme_parse_border(scanner, &data->gap);
break;
case TOKEN_GAP_START_FILE:
token = theme_parse_file(scanner, &data->gap_start);
break;
case TOKEN_GAP_START_BORDER:
token = theme_parse_border(scanner, &data->gap_start);
break;
case TOKEN_GAP_END_FILE:
token = theme_parse_file(scanner, &data->gap_end);
break;
case TOKEN_GAP_END_BORDER:
token = theme_parse_border(scanner, &data->gap_end);
break;
case TOKEN_OVERLAY_FILE:
token = theme_parse_file(scanner, &data->overlay);
break;
case TOKEN_OVERLAY_BORDER:
token = theme_parse_border(scanner, &data->overlay);
break;
case TOKEN_OVERLAY_STRETCH:
token = theme_parse_stretch(scanner, &data->overlay);
break;
default:
g_scanner_get_next_token(scanner);
token = G_TOKEN_RIGHT_CURLY;
break;
}
if (token != G_TOKEN_NONE)
{
/* error - cleanup for exit */
theme_image_unref (data);
*data_return = NULL;
return token;
}
token = g_scanner_peek_next_token(scanner);
}
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_RIGHT_CURLY)
{
/* error - cleanup for exit */
theme_image_unref (data);
*data_return = NULL;
return G_TOKEN_RIGHT_CURLY;
}
/* everything is fine now - insert yer cruft */
*data_return = data;
return G_TOKEN_NONE;
}
static guint
theme_parse_rc_style(GScanner * scanner,
GtkRcStyle * rc_style)
{
static GQuark scope_id = 0;
ThemeData *theme_data;
guint old_scope;
guint token;
gint i;
ThemeImage *img;
/* Set up a new scope in this scanner. */
if (!scope_id)
scope_id = g_quark_from_string("theme_engine");
/* If we bail out due to errors, we *don't* reset the scope, so the
* error messaging code can make sense of our tokens.
*/
old_scope = g_scanner_set_scope(scanner, scope_id);
/* Now check if we already added our symbols to this scope
* (in some previous call to theme_parse_rc_style for the
* same scanner.
*/
if (!g_scanner_lookup_symbol(scanner, theme_symbols[0].name))
{
g_scanner_freeze_symbol_table(scanner);
for (i = 0; i < n_theme_symbols; i++)
g_scanner_scope_add_symbol(scanner, scope_id,
theme_symbols[i].name,
GINT_TO_POINTER(theme_symbols[i].token));
g_scanner_thaw_symbol_table(scanner);
}
/* We're ready to go, now parse the top level */
theme_data = g_new(ThemeData, 1);
theme_data->img_list = NULL;
theme_data->refcount = 1;
token = g_scanner_peek_next_token(scanner);
while (token != G_TOKEN_RIGHT_CURLY)
{
switch (token)
{
case TOKEN_IMAGE:
img = NULL;
token = theme_parse_image(scanner, theme_data, &img);
break;
default:
g_scanner_get_next_token(scanner);
token = G_TOKEN_RIGHT_CURLY;
break;
}
if (token != G_TOKEN_NONE)
{
g_list_foreach (theme_data->img_list, (GFunc)theme_image_unref, NULL);
g_list_free (theme_data->img_list);
g_free (theme_data);
return token;
}
else
{
theme_data->img_list = g_list_append(theme_data->img_list, img);
}
token = g_scanner_peek_next_token(scanner);
}
g_scanner_get_next_token(scanner);
rc_style->engine_data = theme_data;
g_scanner_set_scope(scanner, old_scope);
return G_TOKEN_NONE;
}
static void
theme_merge_rc_style(GtkRcStyle * dest,
GtkRcStyle * src)
{
ThemeData *src_data = src->engine_data;
ThemeData *dest_data = dest->engine_data;
GList *tmp_list1, *tmp_list2;
if (!dest_data)
{
dest_data = g_new(ThemeData, 1);
dest_data->img_list = NULL;
dest_data->refcount = 1;
dest->engine_data = dest_data;
}
if (src_data->img_list)
{
/* Copy src image list and append to dest image list */
tmp_list2 = g_list_last (dest_data->img_list);
tmp_list1 = src_data->img_list;
while (tmp_list1)
{
if (tmp_list2)
{
tmp_list2->next = g_list_alloc();
tmp_list2->next->data = tmp_list1->data;
tmp_list2->next->prev = tmp_list2;
tmp_list2 = tmp_list2->next;
}
else
{
dest_data->img_list = g_list_append (NULL, tmp_list1->data);
tmp_list2 = dest_data->img_list;
}
theme_data_ref (tmp_list1->data);
tmp_list1 = tmp_list1->next;
}
}
}
static void
theme_rc_style_to_style(GtkStyle * style,
GtkRcStyle * rc_style)
{
ThemeData *data = rc_style->engine_data;
style->klass = &pixmap_default_class;
style->engine_data = data;
theme_data_ref (data);
}
static void
theme_duplicate_style(GtkStyle * dest,
GtkStyle * src)
{
ThemeData *src_data = src->engine_data;
ThemeData *dest_data;
dest_data = g_new(ThemeData, 1);
dest_data->img_list = g_list_copy (src_data->img_list);
g_list_foreach (dest_data->img_list, (GFunc)theme_image_ref, NULL);
dest->klass = &pixmap_default_class;
dest->engine_data = dest_data;
theme_data_ref (dest_data);
}
static void
theme_realize_style(GtkStyle * style)
{
}
static void
theme_unrealize_style(GtkStyle * style)
{
}
static void
theme_destroy_rc_style(GtkRcStyle * rc_style)
{
theme_data_unref (rc_style->engine_data);
}
static void
theme_destroy_style(GtkStyle * style)
{
theme_data_unref (style->engine_data);
}
static void
theme_set_background(GtkStyle * style,
GdkWindow * window,
GtkStateType state_type)
{
GdkPixmap *pixmap;
gint parent_relative;
g_return_if_fail(style != NULL);
g_return_if_fail(window != NULL);
if (style->bg_pixmap[state_type])
{
if (style->bg_pixmap[state_type] == (GdkPixmap *) GDK_PARENT_RELATIVE)
{
pixmap = NULL;
parent_relative = TRUE;
}
else
{
pixmap = style->bg_pixmap[state_type];
parent_relative = FALSE;
}
gdk_window_set_back_pixmap(window, pixmap, parent_relative);
}
else
gdk_window_set_background(window, &style->bg[state_type]);
}
void
theme_init(GtkThemeEngine * engine)
{
engine->parse_rc_style = theme_parse_rc_style;
engine->merge_rc_style = theme_merge_rc_style;
engine->rc_style_to_style = theme_rc_style_to_style;
engine->duplicate_style = theme_duplicate_style;
engine->realize_style = theme_realize_style;
engine->unrealize_style = theme_unrealize_style;
engine->destroy_rc_style = theme_destroy_rc_style;
engine->destroy_style = theme_destroy_style;
engine->set_background = theme_set_background;
gdk_rgb_init();
/*
* We enable the caches unconditionally (the -1 is used
* to inform gnome-libs to ignore its setting for the
* cache
*/
#if 0
gtk_widget_push_visual(gdk_imlib_get_visual());
gtk_widget_push_colormap(gdk_imlib_get_colormap());
#endif /* 0 */
}
void
theme_exit(void)
{
}
/* The following function will be called by GTK+ when the module
* is loaded and checks to see if we are compatible with the
* version of GTK+ that loads us.
*/
G_MODULE_EXPORT const gchar* g_module_check_init (GModule *module);
const gchar*
g_module_check_init (GModule *module)
{
return gtk_check_version (GTK_MAJOR_VERSION,
GTK_MINOR_VERSION,
GTK_MICRO_VERSION - GTK_INTERFACE_AGE);
}

View File

@ -0,0 +1,356 @@
/* GTK+ Pixbuf Engine
* Copyright (C) 1998-2000 Red Hat Software
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Written by Owen Taylor <otaylor@redhat.com>, based on code by
* Carsten Haitzler <raster@rasterman.com>
*/
#include "pixmap_theme.h"
#include <gdk-pixbuf/gdk-pixbuf.h>
GCache *pixbuf_cache = NULL;
static void
pixbuf_render (GdkPixbuf *src,
GdkWindow *window,
GdkBitmap *mask,
GdkRectangle *clip_rect,
gint src_x,
gint src_y,
gint src_width,
gint src_height,
gint dest_x,
gint dest_y,
gint dest_width,
gint dest_height)
{
GdkPixbuf *tmp_pixbuf;
GdkRectangle rect;
int x_offset, y_offset;
art_u32 bg_color = 0xffffff;
if (dest_width <= 0 || dest_height <= 0)
return;
rect.x = dest_x;
rect.y = dest_y;
rect.width = dest_width;
rect.height = dest_height;
/* FIXME: we need the full mask, not a partial mask; the following is, however,
* horribly expensive
*/
if (!mask && clip_rect && !gdk_rectangle_intersect (clip_rect, &rect, &rect))
return;
if (dest_width != src->art_pixbuf->width ||
dest_height != src->art_pixbuf->height)
{
ArtPixBuf *partial_src_art;
GdkPixbuf *partial_src_gdk;
if (src->art_pixbuf->n_channels == 3)
{
partial_src_art =
art_pixbuf_new_const_rgb (src->art_pixbuf->pixels + src_y * src->art_pixbuf->rowstride + src_x * src->art_pixbuf->n_channels,
src_width,
src_height,
src->art_pixbuf->rowstride);
}
else
{
partial_src_art =
art_pixbuf_new_const_rgba (src->art_pixbuf->pixels + src_y * src->art_pixbuf->rowstride + src_x * src->art_pixbuf->n_channels,
src_width,
src_height,
src->art_pixbuf->rowstride);
}
partial_src_gdk = gdk_pixbuf_new_from_art_pixbuf (partial_src_art);
tmp_pixbuf = gdk_pixbuf_new (ART_PIX_RGB, src->art_pixbuf->has_alpha, 8, rect.width, rect.height);
if (mask)
{
gdk_pixbuf_scale (partial_src_gdk, tmp_pixbuf, 0, 0, rect.width, rect.height,
dest_x - rect.x, dest_y - rect.y,
(double)dest_width / src_width, (double)dest_height / src_height,
ART_FILTER_BILINEAR);
}
else
{
gdk_pixbuf_composite_color (partial_src_gdk, tmp_pixbuf, 0, 0, rect.width, rect.height,
dest_x - rect.x, dest_y - rect.y,
(double)dest_width / src_width, (double)dest_height / src_height,
ART_FILTER_BILINEAR, 255, 0, 0, 16, bg_color, bg_color);
}
gdk_pixbuf_unref (partial_src_gdk);
x_offset = 0;
y_offset = 0;
}
else
{
tmp_pixbuf = src;
gdk_pixbuf_ref (tmp_pixbuf);
x_offset = src_x + rect.x - dest_x;
y_offset = src_y + rect.y - dest_y;
}
if (mask)
{
GdkGC *tmp_gc;
gdk_pixbuf_render_threshold_alpha (tmp_pixbuf, mask,
x_offset, y_offset,
rect.x, rect.y,
rect.width, rect.height,
128);
tmp_gc = gdk_gc_new (window);
gdk_pixbuf_render_to_drawable (tmp_pixbuf, window, tmp_gc,
x_offset, y_offset,
rect.x, rect.y,
rect.width, rect.height,
GDK_RGB_DITHER_NORMAL,
0, 0);
gdk_gc_unref (tmp_gc);
}
else
gdk_pixbuf_render_to_drawable_alpha (tmp_pixbuf, window,
x_offset, y_offset,
rect.x, rect.y,
rect.width, rect.height,
GDK_PIXBUF_ALPHA_BILEVEL, 128,
GDK_RGB_DITHER_NORMAL,
0, 0);
gdk_pixbuf_unref (tmp_pixbuf);
}
ThemePixbuf *
theme_pixbuf_new (void)
{
ThemePixbuf *result = g_new (ThemePixbuf, 1);
result->filename = NULL;
result->pixbuf = NULL;
result->stretch = TRUE;
result->border_left = 0;
result->border_right = 0;
result->border_bottom = 0;
result->border_top = 0;
return result;
}
void
theme_pixbuf_destroy (ThemePixbuf *theme_pb)
{
if (theme_pb->pixbuf)
g_cache_remove (pixbuf_cache, theme_pb->pixbuf);
}
void
theme_pixbuf_set_filename (ThemePixbuf *theme_pb,
const char *filename)
{
if (theme_pb->pixbuf)
{
g_cache_remove (pixbuf_cache, theme_pb->pixbuf);
theme_pb->pixbuf = NULL;
}
if (theme_pb->filename)
g_free (theme_pb->filename);
theme_pb->filename = g_strdup (filename);
}
void
theme_pixbuf_set_border (ThemePixbuf *theme_pb,
gint left,
gint right,
gint top,
gint bottom)
{
theme_pb->border_left = left;
theme_pb->border_right = right;
theme_pb->border_top = top;
theme_pb->border_bottom = bottom;
}
void
theme_pixbuf_set_stretch (ThemePixbuf *theme_pb,
gboolean stretch)
{
theme_pb->stretch = stretch;
}
GdkPixbuf *
pixbuf_cache_value_new (gchar *filename)
{
GdkPixbuf *result = gdk_pixbuf_new_from_file (filename);
if (!result)
g_warning("Pixbuf theme: Cannot load pixmap file %s\n", filename);
return result;
}
GdkPixbuf *
theme_pixbuf_get_pixbuf (ThemePixbuf *theme_pb)
{
if (!theme_pb->pixbuf)
{
if (!pixbuf_cache)
pixbuf_cache = g_cache_new ((GCacheNewFunc)pixbuf_cache_value_new,
(GCacheDestroyFunc)gdk_pixbuf_unref,
(GCacheDupFunc)g_strdup,
(GCacheDestroyFunc)g_free,
g_str_hash, g_direct_hash, g_str_equal);
theme_pb->pixbuf = g_cache_insert (pixbuf_cache, theme_pb->filename);
}
return theme_pb->pixbuf;
}
void
theme_pixbuf_render (ThemePixbuf *theme_pb,
GdkWindow *window,
GdkBitmap *mask,
GdkRectangle *clip_rect,
guint component_mask,
gboolean center,
gint x,
gint y,
gint width,
gint height)
{
GdkPixbuf *pixbuf = theme_pixbuf_get_pixbuf (theme_pb);
gint src_x[4], src_y[4], dest_x[4], dest_y[4];
if (!pixbuf)
return;
if (theme_pb->stretch)
{
src_x[0] = 0;
src_x[1] = theme_pb->border_left;
src_x[2] = pixbuf->art_pixbuf->width - theme_pb->border_right;
src_x[3] = pixbuf->art_pixbuf->width;
src_y[0] = 0;
src_y[1] = theme_pb->border_top;
src_y[2] = pixbuf->art_pixbuf->height - theme_pb->border_bottom;
src_y[3] = pixbuf->art_pixbuf->height;
dest_x[0] = x;
dest_x[1] = x + theme_pb->border_left;
dest_x[2] = x + width - theme_pb->border_right;
dest_x[3] = x + width;
dest_y[0] = y;
dest_y[1] = y + theme_pb->border_top;
dest_y[2] = y + height - theme_pb->border_bottom;
dest_y[3] = y + height;
if (component_mask & COMPONENT_ALL)
component_mask = (COMPONENT_ALL - 1) & ~component_mask;
#define RENDER_COMPONENT(X1,X2,Y1,Y2) \
pixbuf_render (pixbuf, window, mask, clip_rect, \
src_x[X1], src_y[Y1], \
src_x[X2] - src_x[X1], src_y[Y2] - src_y[Y1], \
dest_x[X1], dest_y[Y1], \
dest_x[X2] - dest_x[X1], dest_y[Y2] - dest_y[Y1]);
if (component_mask & COMPONENT_NORTH_WEST)
RENDER_COMPONENT (0, 1, 0, 1);
if (component_mask & COMPONENT_NORTH)
RENDER_COMPONENT (1, 2, 0, 1);
if (component_mask & COMPONENT_NORTH_EAST)
RENDER_COMPONENT (2, 3, 0, 1);
if (component_mask & COMPONENT_WEST)
RENDER_COMPONENT (0, 1, 1, 2);
if (component_mask & COMPONENT_CENTER)
RENDER_COMPONENT (1, 2, 1, 2);
if (component_mask & COMPONENT_EAST)
RENDER_COMPONENT (2, 3, 1, 2);
if (component_mask & COMPONENT_SOUTH_WEST)
RENDER_COMPONENT (0, 1, 2, 3);
if (component_mask & COMPONENT_SOUTH)
RENDER_COMPONENT (1, 2, 2, 3);
if (component_mask & COMPONENT_SOUTH_EAST)
RENDER_COMPONENT (2, 3, 2, 3);
}
else
{
if (center)
{
x += (width - pixbuf->art_pixbuf->width) / 2;
y += (height - pixbuf->art_pixbuf->height) / 2;
pixbuf_render (pixbuf, window, NULL, clip_rect,
0, 0,
pixbuf->art_pixbuf->width, pixbuf->art_pixbuf->height,
x, y,
pixbuf->art_pixbuf->width, pixbuf->art_pixbuf->height);
}
else
{
GdkPixmap *tmp_pixmap;
GdkGC *tmp_gc;
GdkGCValues gc_values;
tmp_pixmap = gdk_pixmap_new (window,
pixbuf->art_pixbuf->width,
pixbuf->art_pixbuf->height,
-1);
tmp_gc = gdk_gc_new (tmp_pixmap);
gdk_pixbuf_render_to_drawable (pixbuf, tmp_pixmap, tmp_gc,
0, 0,
0, 0,
pixbuf->art_pixbuf->width, pixbuf->art_pixbuf->height,
GDK_RGB_DITHER_NORMAL,
0, 0);
gdk_gc_unref (tmp_gc);
gc_values.fill = GDK_TILED;
gc_values.tile = tmp_pixmap;
tmp_gc = gdk_gc_new_with_values (window,
&gc_values, GDK_GC_FILL | GDK_GC_TILE);
if (clip_rect)
gdk_draw_rectangle (window, tmp_gc, TRUE,
clip_rect->x, clip_rect->y, clip_rect->width, clip_rect->height);
else
gdk_draw_rectangle (window, tmp_gc, TRUE, x, y, width, height);
gdk_gc_unref (tmp_gc);
gdk_pixmap_unref (tmp_pixmap);
}
}
}

View File

@ -0,0 +1,172 @@
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
/* internals */
typedef struct _ThemeData ThemeData;
typedef struct _ThemeImage ThemeImage;
typedef struct _ThemeMatchData ThemeMatchData;
typedef struct _ThemePixbuf ThemePixbuf;
enum
{
TOKEN_IMAGE = G_TOKEN_LAST + 1,
TOKEN_FUNCTION,
TOKEN_FILE,
TOKEN_STRETCH,
TOKEN_RECOLORABLE,
TOKEN_BORDER,
TOKEN_DETAIL,
TOKEN_STATE,
TOKEN_SHADOW,
TOKEN_GAP_SIDE,
TOKEN_GAP_FILE,
TOKEN_GAP_BORDER,
TOKEN_GAP_START_FILE,
TOKEN_GAP_START_BORDER,
TOKEN_GAP_END_FILE,
TOKEN_GAP_END_BORDER,
TOKEN_OVERLAY_FILE,
TOKEN_OVERLAY_BORDER,
TOKEN_OVERLAY_STRETCH,
TOKEN_ARROW_DIRECTION,
TOKEN_D_HLINE,
TOKEN_D_VLINE,
TOKEN_D_SHADOW,
TOKEN_D_POLYGON,
TOKEN_D_ARROW,
TOKEN_D_DIAMOND,
TOKEN_D_OVAL,
TOKEN_D_STRING,
TOKEN_D_BOX,
TOKEN_D_FLAT_BOX,
TOKEN_D_CHECK,
TOKEN_D_OPTION,
TOKEN_D_CROSS,
TOKEN_D_RAMP,
TOKEN_D_TAB,
TOKEN_D_SHADOW_GAP,
TOKEN_D_BOX_GAP,
TOKEN_D_EXTENSION,
TOKEN_D_FOCUS,
TOKEN_D_SLIDER,
TOKEN_D_ENTRY,
TOKEN_D_HANDLE,
TOKEN_TRUE,
TOKEN_FALSE,
TOKEN_TOP,
TOKEN_UP,
TOKEN_BOTTOM,
TOKEN_DOWN,
TOKEN_LEFT,
TOKEN_RIGHT,
TOKEN_NORMAL,
TOKEN_ACTIVE,
TOKEN_PRELIGHT,
TOKEN_SELECTED,
TOKEN_INSENSITIVE,
TOKEN_NONE,
TOKEN_IN,
TOKEN_OUT,
TOKEN_ETCHED_IN,
TOKEN_ETCHED_OUT,
TOKEN_ORIENTATION,
TOKEN_HORIZONTAL,
TOKEN_VERTICAL,
};
typedef enum
{
COMPONENT_NORTH_WEST = 1 << 0,
COMPONENT_NORTH = 1 << 1,
COMPONENT_NORTH_EAST = 1 << 2,
COMPONENT_WEST = 1 << 3,
COMPONENT_CENTER = 1 << 4,
COMPONENT_EAST = 1 << 5,
COMPONENT_SOUTH_EAST = 1 << 6,
COMPONENT_SOUTH = 1 << 7,
COMPONENT_SOUTH_WEST = 1 << 8,
COMPONENT_ALL = 1 << 9
} ThemePixbufComponent;
typedef enum {
THEME_MATCH_GAP_SIDE = 1 << 0,
THEME_MATCH_ORIENTATION = 1 << 1,
THEME_MATCH_STATE = 1 << 2,
THEME_MATCH_SHADOW = 1 << 3,
THEME_MATCH_ARROW_DIRECTION = 1 << 4
} ThemeMatchFlags;
struct _ThemeData
{
guint refcount;
GList *img_list;
};
struct _ThemePixbuf
{
gchar *filename;
GdkPixbuf *pixbuf;
gboolean stretch;
gint border_left;
gint border_right;
gint border_bottom;
gint border_top;
};
struct _ThemeMatchData
{
guint function; /* Mandatory */
gchar *detail;
ThemeMatchFlags flags;
GtkPositionType gap_side;
GtkOrientation orientation;
GtkStateType state;
GtkShadowType shadow;
GtkArrowType arrow_direction;
};
struct _ThemeImage
{
guint refcount;
ThemePixbuf *background;
ThemePixbuf *overlay;
ThemePixbuf *gap_start;
ThemePixbuf *gap;
ThemePixbuf *gap_end;
gchar recolorable;
ThemeMatchData match_data;
};
ThemePixbuf *theme_pixbuf_new (void);
void theme_pixbuf_destroy (ThemePixbuf *theme_pb);
void theme_pixbuf_set_filename (ThemePixbuf *theme_pb,
const char *filename);
GdkPixbuf * theme_pixbuf_get_pixbuf (ThemePixbuf *theme_pb);
void theme_pixbuf_set_border (ThemePixbuf *theme_pb,
gint left,
gint right,
gint top,
gint bottom);
void theme_pixbuf_set_stretch (ThemePixbuf *theme_pb,
gboolean stretch);
void theme_pixbuf_render (ThemePixbuf *theme_pb,
GdkWindow *window,
GdkBitmap *mask,
GdkRectangle *clip_rect,
guint component_mask,
gboolean center,
gint dest_x,
gint dest_y,
gint dest_width,
gint dest_height);
extern GtkStyleClass pixmap_default_class;