add more stuff to my patches branch

This commit is contained in:
Havoc Pennington
2000-06-26 02:08:28 +00:00
parent 73efaabf4f
commit a1f0128134
16 changed files with 1726 additions and 2 deletions

View File

@@ -37,6 +37,11 @@ noinst_PROGRAMS = \
testpixbuf-scale \
pixbuf-demo
BUILT_SOURCES=test-inline-pixbufs.h
test-inline-pixbufs.h: $(top_builddir)/gdk-pixbuf/make-inline-pixbuf apple-red.png gnome-foot.png
GDK_PIXBUF_MODULEDIR=$(top_builddir)/gdk-pixbuf/.libs $(top_builddir)/gdk-pixbuf/make-inline-pixbuf test-inline-pixbufs.h apple_red apple-red.png gnome_foot gnome-foot.png
testpixbuf_DEPENDENCIES = $(DEPS)
testpixbuf_drawable_DEPENDENCIES = $(DEPS)
testpixbuf_scale_DEPENDENCIES = $(DEPS)

View File

@@ -25,6 +25,8 @@
#include <gtk/gtk.h>
#include <gtk/gdk-pixbuf-loader.h>
#include "test-inline-pixbufs.h"
typedef struct {
FILE *imagefile;
GdkPixbufLoader *loader;
@@ -375,7 +377,7 @@ new_testrgb_window (GdkPixbuf *pixbuf, gchar *title)
window = gtk_widget_new (gtk_window_get_type (),
"GtkObject::user_data", NULL,
"GtkWindow::type", GTK_WINDOW_TOPLEVEL,
"GtkWindow::title", "testrgb",
"GtkWindow::title", title ? title : "testrgb",
"GtkWindow::allow_shrink", TRUE,
NULL);
gtk_signal_connect (GTK_OBJECT (window), "destroy",
@@ -536,6 +538,13 @@ main (int argc, char **argv)
new_testrgb_window (pixbuf, NULL);
++xpmp;
}
/* Test loading from inline data. */
pixbuf = gdk_pixbuf_new_from_inline (apple_red, FALSE);
new_testrgb_window (pixbuf, "Red apple from inline data");
pixbuf = gdk_pixbuf_new_from_inline (gnome_foot, TRUE);
new_testrgb_window (pixbuf, "Foot from inline data");
found_valid = TRUE;
} else {

View File

@@ -1,3 +1,14 @@
2000-06-23 Havoc Pennington <hp@redhat.com>
* image-to-inline.c: Small program that creates C variable
declarations of inline pixbuf data. This can be read
by gdk_pixbuf_new_from_inline.
* gdk-pixbuf.h (gdk_pixbuf_new_from_inline): New function to read
inline pixbuf data and create a pixbuf from it.
* gdk-pixbuf-data.c (gdk_pixbuf_new_from_inline): implement here
2000-06-21 Havoc Pennington <hp@pobox.com>
* gdk-pixbuf.c: Convert GdkPixbuf to GObject, leaving it opaque

View File

@@ -138,6 +138,12 @@ LDADDS = libgdk_pixbuf.la $(GLIB_LIBS) $(STATIC_LIB_DEPS)
test_gdk_pixbuf_LDADD = $(LDADDS) -lgmodule
bin_PROGRAMS=make-inline-pixbuf
make_inline_pixbuf_SOURCES=make-inline-pixbuf.c
make_inline_pixbuf_LDADD = $(LDADDS) -lgmodule
GDK_PIXBUF_LIBS = $(GLIB_LIBS)
#

View File

@@ -75,3 +75,98 @@ gdk_pixbuf_new_from_data (const guchar *data, GdkColorspace colorspace, gboolean
return pixbuf;
}
int
read_int (const guchar **p)
{
guint32 num;
num = g_ntohl (* (guint32*) *p);
*p += 4;
return num;
}
gboolean
read_bool (const guchar **p)
{
gboolean val = **p != 0;
++(*p);
return val;
}
/* sync with image-to-inline.c */
#define MAGIC_NUMBER 1804289383
static void
free_buffer (guchar *pixels, gpointer data)
{
free (pixels);
}
/**
* gdk_pixbuf_new_from_inline:
* @data: An inlined GdkPixbuf
* @copy_pixels: whether to copy the pixels out of the inline data, or to use them in-place
*
* Create a #GdkPixbuf from a custom format invented to store pixbuf
* data in C program code. This library comes with a program called "image-to-inline"
* that can write out a variable definition containing an inlined pixbuf.
* This is useful if you want to ship a program with images, but
* don't want to depend on any external files.
*
* The inline data format contains the pixels in #GdkPixbuf's native format.
* Since the inline pixbuf is static data, you don't really need to copy it.
* However it's typically in read-only memory, so if you plan to modify
* it you must copy it.
*
* Return value: A newly-created #GdkPixbuf structure with a reference count of
* 1.
**/
GdkPixbuf*
gdk_pixbuf_new_from_inline (const guchar *inline_pixbuf,
gboolean copy_pixels)
{
const guchar *p;
GdkPixbuf *pixbuf;
p = inline_pixbuf;
if (read_int (&p) != MAGIC_NUMBER) {
g_warning ("Bad inline data; wrong magic number");
return NULL;
}
pixbuf = GDK_PIXBUF (g_type_create_instance (GDK_TYPE_PIXBUF));
pixbuf->rowstride = read_int (&p);
pixbuf->width = read_int (&p);
pixbuf->height = read_int (&p);
pixbuf->has_alpha = read_bool (&p);
pixbuf->colorspace = read_int (&p);
pixbuf->n_channels = read_int (&p);
pixbuf->bits_per_sample = read_int (&p);
if (copy_pixels) {
pixbuf->pixels = malloc (pixbuf->height * pixbuf->rowstride);
if (pixbuf->pixels == NULL) {
g_object_unref (G_OBJECT (pixbuf));
return NULL;
}
pixbuf->destroy_fn = free_buffer;
pixbuf->destroy_fn_data = NULL;
memcpy (pixbuf->pixels, p, pixbuf->height * pixbuf->rowstride);
} else {
pixbuf->pixels = (guchar *) p;
}
return pixbuf;
}

View File

@@ -103,6 +103,10 @@ GdkPixbuf *gdk_pixbuf_new_from_data (const guchar *data,
GdkPixbuf *gdk_pixbuf_new_from_xpm_data (const char **data);
/* Read an inline pixbuf */
GdkPixbuf *gdk_pixbuf_new_from_inline (const guchar *inline_pixbuf,
gboolean copy_pixels);
/* Adding an alpha channel */
GdkPixbuf *gdk_pixbuf_add_alpha (const GdkPixbuf *pixbuf, gboolean substitute_color,
guchar r, guchar g, guchar b);

View File

@@ -0,0 +1,211 @@
/* Program to convert an image file to inline C data
*
* Copyright (C) 2000 Red Hat, Inc.
*
* Developed by Havoc Pennington <hp@redhat.com>
*
* 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.
*/
#include <config.h>
#include "gdk-pixbuf.h"
#include <stdio.h>
#include <errno.h>
#include <string.h>
/* sync with gdk-pixbuf-data.c */
#define MAGIC_NUMBER 1804289383
void
output_int (FILE *outfile, int number, const char *comment)
{
guchar bytes[4];
guint32 num;
g_assert (sizeof (bytes) == sizeof (num));
num = number;
*((guint32*)bytes) = g_htonl (num);
fprintf(outfile, " /* %s (decimal: %u) */\n 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x,\n",
comment, num,
bytes[0], bytes[1], bytes[2], bytes[3]);
}
void
output_bool (FILE *outfile, gboolean val, const char *comment)
{
fprintf(outfile, " /* %s (%s) */\n 0x%.2x,\n",
comment,
val ? "TRUE" : "FALSE",
val ? 1 : 0);
}
void
output_pixbuf (FILE *outfile, gboolean ext_symbols,
const char *varname,
GdkPixbuf *pixbuf)
{
const char *modifier;
const guchar *p;
const guchar *end;
gboolean has_alpha;
int column;
modifier = "static ";
if (ext_symbols)
modifier = "";
fprintf (outfile, "%sconst guchar ", modifier);
fputs (varname, outfile);
fputs (" [] =\n", outfile);
fputs ("{\n", outfile);
p = gdk_pixbuf_get_pixels (pixbuf);
end = p + gdk_pixbuf_get_rowstride (pixbuf) * gdk_pixbuf_get_height (pixbuf);
has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
/* Sync the order of writing with the order of reading in
* gdk-pixbuf-data.c
*/
output_int (outfile, MAGIC_NUMBER, "File magic");
output_int (outfile, gdk_pixbuf_get_rowstride (pixbuf), "Rowstride");
output_int (outfile, gdk_pixbuf_get_width (pixbuf), "Width");
output_int (outfile, gdk_pixbuf_get_height (pixbuf), "Height");
output_bool (outfile, has_alpha, "Has an alpha channel");
output_int (outfile, gdk_pixbuf_get_colorspace (pixbuf), "Colorspace (0 == RGB, no other options implemented)");
output_int (outfile, gdk_pixbuf_get_n_channels (pixbuf), "Number of channels");
output_int (outfile, gdk_pixbuf_get_bits_per_sample (pixbuf), "Bits per sample");
fputs (" /* Image data */\n", outfile);
/* Copy the data in the pixbuf */
column = 0;
while (p != end)
{
guchar r, g, b, a;
r = *p;
++p;
g = *p;
++p;
b = *p;
++p;
if (has_alpha)
{
a = *p;
++p;
}
else
a = 0;
if (has_alpha)
fprintf(outfile, " 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x", r, g, b, a);
else
fprintf(outfile, " 0x%.2x, 0x%.2x, 0x%.2x", r, g, b);
if (p != end)
fputs (",", outfile);
else
fputs ("\n", outfile);
++column;
if (column > 2)
{
fputs ("\n", outfile);
column = 0;
}
}
fputs ("};\n\n", outfile);
}
void
usage (void)
{
fprintf (stderr, "Usage: image-to-inline [--extern-symbols] OUTFILE varname1 imagefile1 varname2 imagefile2 ...\n");
exit (1);
}
int
main (int argc, char **argv)
{
gboolean ext_symbols = FALSE;
FILE *outfile;
int i;
gdk_pixbuf_init ();
if (argc < 4)
usage ();
i = 1;
if (strcmp (argv[i], "--extern-symbols") == 0)
{
ext_symbols = TRUE;
++i;
if (argc < 5)
usage ();
}
outfile = fopen (argv[i], "w");
if (outfile == NULL)
{
fprintf (stderr, "Failed to open output file `%s': %s\n",
argv[i], strerror (errno));
exit (1);
}
++i;
fputs ("/* This file was automatically generated by the image-to-inline program.\n"
" * It contains inline RGB image data.\n"
" */\n\n", outfile);
while (i < argc)
{
GdkPixbuf *pixbuf;
if ((i + 1) == argc)
usage ();
pixbuf = gdk_pixbuf_new_from_file (argv[i+1]);
if (pixbuf == NULL)
{
fprintf (stderr, "Failed to open image file `%s': %s\n",
argv[i+1], strerror (errno));
exit (1);
}
output_pixbuf (outfile, ext_symbols, argv[i], pixbuf);
gdk_pixbuf_unref (pixbuf);
i += 2;
}
fclose (outfile);
return 0;
}

View File

@@ -95,6 +95,7 @@ gtk_public_h_sources = @STRIP_BEGIN@ \
gtkhscrollbar.h \
gtkhseparator.h \
gtkhsv.h \
gtkiconfactory.h \
gtkimage.h \
gtkimcontext.h \
gtkimmulticontext.h \
@@ -140,6 +141,7 @@ gtk_public_h_sources = @STRIP_BEGIN@ \
gtkspinbutton.h \
gtkstyle.h \
gtkstatusbar.h \
gtkstock.h \
gtktable.h \
gtktearoffmenuitem.h \
gtktextbuffer.h \
@@ -234,6 +236,7 @@ gtk_c_sources = @STRIP_BEGIN@ \
gtkhscrollbar.c \
gtkhseparator.c \
gtkhsv.c \
gtkiconfactory.c \
gtkimage.c \
gtkimcontext.c \
gtkimcontextsimple.c \
@@ -279,6 +282,7 @@ gtk_c_sources = @STRIP_BEGIN@ \
gtksignal.c \
gtksocket.c \
gtkspinbutton.c \
gtkstock.c \
gtkstyle.c \
gtkstatusbar.c \
gtktable.c \

761
gtk/gtkiconfactory.c Normal file
View File

@@ -0,0 +1,761 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* 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.
*/
/*
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "gtkiconfactory.h"
static gpointer parent_class = NULL;
static void gtk_icon_factory_init (GtkIconFactory *icon_factory);
static void gtk_icon_factory_class_init (GtkIconFactoryClass *klass);
static void gtk_icon_factory_finalize (GObject *object);
GType
gtk_icon_factory_get_type (void)
{
static GType object_type = 0;
if (!object_type)
{
static const GTypeInfo object_info =
{
sizeof (GtkIconFactoryClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) gtk_icon_factory_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkIconFactory),
0, /* n_preallocs */
(GInstanceInitFunc) gtk_icon_factory_init,
};
object_type = g_type_register_static (G_TYPE_OBJECT,
"GtkIconFactory",
&object_info);
}
return object_type;
}
static void
gtk_icon_factory_init (GtkIconFactory *factory)
{
factory->icons = g_hash_table_new (g_str_hash, g_str_equal);
}
static void
gtk_icon_factory_class_init (GtkIconFactoryClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
object_class->finalize = gtk_icon_factory_finalize;
}
static void
free_icon_set (gpointer key, gpointer value, gpointer data)
{
g_free (key);
gtk_icon_set_unref (value);
}
static void
gtk_icon_factory_finalize (GObject *object)
{
GtkIconFactory *factory = GTK_ICON_FACTORY (object);
g_hash_table_foreach (factory->icons, free_icon_set, NULL);
g_hash_table_destroy (factory->icons);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
GtkIconFactory*
gtk_icon_factory_new (void)
{
return GTK_ICON_FACTORY (g_type_create_instance (GTK_TYPE_ICON_FACTORY));
}
void
gtk_icon_factory_add (GtkIconFactory *factory,
const gchar *stock_id,
GtkIconSet *icon_set)
{
gpointer old_key = NULL;
gpointer old_value = NULL;
g_return_if_fail (GTK_IS_ICON_FACTORY (factory));
g_return_if_fail (stock_id != NULL);
g_return_if_fail (icon_set != NULL);
g_hash_table_lookup_extended (factory->icons, stock_id,
&old_key, &old_value);
if (old_value == icon_set)
return;
gtk_icon_set_ref (icon_set);
g_hash_table_insert (factory->icons, g_strdup (stock_id), icon_set);
if (old_key)
g_free (old_key);
if (old_value)
gtk_icon_set_unref (old_value);
}
GtkIconSet *
gtk_icon_factory_lookup (GtkIconFactory *factory,
const gchar *stock_id)
{
g_return_val_if_fail (GTK_IS_ICON_FACTORY (factory), NULL);
g_return_val_if_fail (stock_id != NULL, NULL);
return g_hash_table_lookup (factory->icons, stock_id);
}
static GtkIconFactory *gtk_default_icons = NULL;
static GSList *default_factories = NULL;
void
gtk_push_default_icon_factory (GtkIconFactory *factory)
{
g_return_if_fail (GTK_IS_ICON_FACTORY (factory));
g_object_ref (G_OBJECT (factory));
default_factories = g_slist_prepend (default_factories, factory);
}
GtkIconSet *
gtk_default_icon_lookup (const gchar *stock_id)
{
GSList *iter;
g_return_val_if_fail (stock_id != NULL, NULL);
iter = default_factories;
while (iter != NULL)
{
GtkIconSet *icon_set =
gtk_icon_factory_lookup (GTK_ICON_FACTORY (iter->data),
stock_id);
if (icon_set)
return icon_set;
iter = g_slist_next (iter);
}
if (gtk_default_icons == NULL)
{
/* FIXME create our default icons, should be kept
* in sync with the default stock items.
*/
gtk_default_icons = gtk_icon_factory_new ();
}
return gtk_icon_factory_lookup (gtk_default_icons, stock_id);
}
/* Sizes */
/* FIXME this shouldn't be hard-coded forever. Eventually
* it will somehow be user-configurable.
*/
static gint widths[] =
{
16, /* menu */
24, /* button */
18, /* small toolbar */
24 /* large toolbar */
};
static gint heights[] =
{
16, /* menu */
24, /* button */
18, /* small toolbar */
24 /* large toolbar */
};
void
gtk_get_icon_size (GtkIconSizeType semantic_size,
gint *width,
gint *height)
{
g_return_if_fail (semantic_size < G_N_ELEMENTS (widths));
if (width)
*width = widths[semantic_size];
if (height)
*height = heights[semantic_size];
}
/* Icon Set */
static GdkPixbuf *find_in_cache (GtkIconSet *icon_set,
GtkStyle *style,
GtkTextDirection direction,
GtkStateType state,
GtkIconSizeType size);
static void add_to_cache (GtkIconSet *icon_set,
GtkStyle *style,
GtkTextDirection direction,
GtkStateType state,
GtkIconSizeType size,
GdkPixbuf *pixbuf);
static void clear_cache (GtkIconSet *icon_set);
static GSList* copy_cache (GtkIconSet *icon_set);
static GSList* direction_state_size_matches (GSList *sources,
GtkTextDirection direction,
GtkStateType state,
GtkIconSizeType size);
static GSList* state_size_matches (GSList *sources,
GtkStateType state,
GtkIconSizeType size);
static GSList* size_matches (GSList *sources,
GtkIconSizeType size);
struct _GtkIconSet
{
guint ref_count;
GSList *sources;
/* Cache of the last few rendered versions of the icon. */
GSList *cache;
guint cache_size;
};
GtkIconSet*
gtk_icon_set_new (void)
{
GtkIconSet *icon_set;
icon_set = g_new (GtkIconSet, 1);
icon_set->ref_count = 1;
icon_set->sources = NULL;
icon_set->cache = NULL;
icon_set->cache_size = 0;
return icon_set;
}
GtkIconSet*
gtk_icon_set_ref (GtkIconSet *icon_set)
{
g_return_val_if_fail (icon_set != NULL, NULL);
g_return_val_if_fail (icon_set->ref_count > 0, NULL);
icon_set->ref_count += 1;
return icon_set;
}
void
gtk_icon_set_unref (GtkIconSet *icon_set)
{
g_return_if_fail (icon_set != NULL);
g_return_if_fail (icon_set->ref_count > 0);
icon_set->ref_count -= 1;
if (icon_set->ref_count == 0)
{
GSList *iter = icon_set->sources;
while (iter != NULL)
{
gtk_icon_source_free (iter->data);
iter = g_slist_next (iter);
}
clear_cache (icon_set);
g_free (icon_set);
}
}
GtkIconSet*
gtk_icon_set_copy (GtkIconSet *icon_set)
{
GtkIconSet *copy;
GSList *iter;
copy = gtk_icon_set_new ();
iter = icon_set->sources;
while (iter != NULL)
{
copy->sources = g_slist_prepend (copy->sources,
gtk_icon_source_copy (iter->data));
iter = g_slist_next (iter);
}
copy->sources = g_slist_reverse (copy->sources);
copy->cache = copy_cache (icon_set);
copy->cache_size = icon_set->cache_size;
return copy;
}
GdkPixbuf*
gtk_icon_set_get_icon (GtkIconSet *icon_set,
GtkStyle *style,
GtkTextDirection direction,
GtkStateType state,
GtkIconSizeType size,
GtkWidget *widget,
const char *detail)
{
GdkPixbuf *icon;
GSList *candidates = NULL;
GtkIconSource *source;
/* FIXME conceivably, everywhere this function
* returns NULL, we should return some default
* dummy icon like a question mark or the image icon
* from netscape
*/
g_return_val_if_fail (icon_set != NULL, NULL);
if (icon_set->sources == NULL)
return NULL;
icon = find_in_cache (icon_set, style, direction,
state, size);
if (icon)
{
g_object_ref (G_OBJECT (icon));
add_to_cache (icon_set, style, direction, state, size, icon);
return icon;
}
/* We need to find the best icon source. Direction matters more
* than state, state matters more than size.
*/
candidates = direction_state_size_matches (icon_set->sources,
direction,
state,
size);
if (candidates == NULL)
return NULL; /* No sources were found. */
/* If multiple candidates were returned, it basically means the
* RC file contained stupidness. We just pick one at random.
*/
source = candidates->data;
g_slist_free (candidates);
if (source->pixbuf == NULL)
{
if (source->filename == NULL)
{
g_warning ("Useless GtkIconSource contains NULL filename and pixbuf");
return NULL;
}
source->pixbuf = gdk_pixbuf_new_from_file (source->filename);
/* This needs to fail silently and do something sane.
* A good argument for returning a default icon.
*/
if (source->pixbuf == NULL)
return NULL;
}
g_assert (source->pixbuf != NULL);
if (style)
{
icon = gtk_style_render_icon (style,
source,
direction,
state,
size,
widget,
detail);
}
else
{
/* Internal function used here and in the default theme. */
icon = _gtk_default_render_icon (style,
source,
direction,
state,
size,
widget,
detail);
}
g_assert (icon != NULL);
add_to_cache (icon_set, style, direction, state, size, icon);
return icon;
}
void
gtk_icon_set_add_source (GtkIconSet *icon_set,
const GtkIconSource *source)
{
g_return_if_fail (icon_set != NULL);
g_return_if_fail (source != NULL);
icon_set->sources = g_slist_prepend (icon_set->sources,
gtk_icon_source_copy (source));
}
GtkIconSource *
gtk_icon_source_copy (const GtkIconSource *source)
{
GtkIconSource *copy;
g_return_val_if_fail (source != NULL, NULL);
copy = g_new (GtkIconSource, 1);
*copy = *source;
copy->filename = g_strdup (source->filename);
if (copy->pixbuf)
g_object_ref (G_OBJECT (copy->pixbuf));
return copy;
}
void
gtk_icon_source_free (GtkIconSource *source)
{
g_return_if_fail (source != NULL);
g_free ((char*) source->filename);
if (source->pixbuf)
g_object_unref (G_OBJECT (source->pixbuf));
g_free (source);
}
void
gtk_icon_set_clear (GtkIconSet *icon_set)
{
GSList *iter;
g_return_if_fail (icon_set != NULL);
iter = icon_set->sources;
while (iter != NULL)
{
gtk_icon_source_free (iter->data);
iter = g_slist_next (iter);
}
clear_cache (icon_set);
}
/* Note that the logical maximum is 20 per GtkTextDirection, so we could
* eventually set this to >20 to never throw anything out.
*/
#define NUM_CACHED_ICONS 8
typedef struct _CachedIcon CachedIcon;
struct _CachedIcon
{
/* These must all match to use the cached pixbuf.
* If any don't match, we must re-render the pixbuf. */
GtkStyle *style;
GtkTextDirection direction;
GtkStateType state;
GtkIconSizeType size;
GdkPixbuf *pixbuf;
};
static GdkPixbuf *
find_in_cache (GtkIconSet *icon_set,
GtkStyle *style,
GtkTextDirection direction,
GtkStateType state,
GtkIconSizeType size)
{
GSList *iter;
iter = icon_set->cache;
while (iter != NULL)
{
CachedIcon *icon = iter->data;
if (icon->style == style &&
icon->direction == direction &&
icon->state == state &&
icon->size == size)
return icon->pixbuf;
iter = g_slist_next (iter);
}
return NULL;
}
static void
add_to_cache (GtkIconSet *icon_set,
GtkStyle *style,
GtkTextDirection direction,
GtkStateType state,
GtkIconSizeType size,
GdkPixbuf *pixbuf)
{
CachedIcon *icon;
g_object_ref (G_OBJECT (pixbuf));
/* We have to ref the style, since if the style was finalized
* its address could be reused by another style, creating a
* really weird bug
*/
if (style)
g_object_ref (G_OBJECT (style));
icon = g_new (CachedIcon, 1);
icon_set->cache = g_slist_prepend (icon_set->cache, icon);
icon->style = style;
icon->direction = direction;
icon->state = state;
icon->size = size;
icon->pixbuf = pixbuf;
if (icon_set->cache_size >= NUM_CACHED_ICONS)
{
/* Remove oldest item in the cache */
GSList *iter;
iter = icon_set->cache;
/* Find next-to-last link */
g_assert (NUM_CACHED_ICONS > 2);
while (iter->next->next)
iter = iter->next;
g_assert (iter != NULL);
g_assert (iter->next != NULL);
g_assert (iter->next->next == NULL);
icon = iter->next->data;
g_slist_free (iter->next);
iter->next = NULL;
g_object_unref (G_OBJECT (icon->pixbuf));
if (icon->style)
g_object_unref (G_OBJECT (icon->style));
}
}
static void
clear_cache (GtkIconSet *icon_set)
{
GSList *iter;
iter = icon_set->cache;
while (iter != NULL)
{
CachedIcon *icon = iter->data;
g_object_unref (G_OBJECT (icon->pixbuf));
if (icon->style)
g_object_unref (G_OBJECT (icon->style));
g_free (icon);
iter = g_slist_next (iter);
}
g_slist_free (icon_set->cache);
icon_set->cache = NULL;
icon_set->cache_size = 0;
}
static GSList*
copy_cache (GtkIconSet *icon_set)
{
GSList *iter;
GSList *copy = NULL;
iter = icon_set->cache;
while (iter != NULL)
{
CachedIcon *icon = iter->data;
CachedIcon *icon_copy = g_new (CachedIcon, 1);
*icon_copy = *icon;
if (icon_copy->style)
g_object_ref (G_OBJECT (icon_copy->style));
g_object_ref (G_OBJECT (icon_copy->pixbuf));
copy = g_slist_prepend (copy, icon_copy);
iter = g_slist_next (iter);
}
return g_slist_reverse (copy);
}
static GSList*
direction_state_size_matches (GSList *sources,
GtkTextDirection direction,
GtkStateType state,
GtkIconSizeType size)
{
GSList *direction_matches = NULL;
GSList *direction_wild = NULL;
GSList *candidates;
GSList *iter;
iter = sources;
while (iter != NULL)
{
GtkIconSource *source = iter->data;
if (!source->any_direction &&
source->direction == direction)
direction_matches = g_slist_prepend (direction_matches, source);
else if (source->any_direction)
direction_wild = g_slist_prepend (direction_wild, source);
iter = g_slist_next (iter);
}
/* First look for a matching source among exact direction matches,
* then look for a matching source among wildcard direction sources
*/
candidates = state_size_matches (direction_matches, state, size);
if (candidates == NULL)
candidates = state_size_matches (direction_wild, state, size);
g_slist_free (direction_wild);
g_slist_free (direction_matches);
return candidates;
}
static GSList*
state_size_matches (GSList *sources,
GtkStateType state,
GtkIconSizeType size)
{
GSList *state_matches = NULL;
GSList *state_wild = NULL;
GSList *candidates;
GSList *iter;
iter = sources;
while (iter != NULL)
{
GtkIconSource *source = iter->data;
if (!source->any_state &&
source->state == state)
state_matches = g_slist_prepend (state_matches, source);
else if (source->any_state)
state_wild = g_slist_prepend (state_wild, source);
iter = g_slist_next (iter);
}
/* First look for a matching source among exact state matches,
* then look for a matching source among wildcard state sources
*/
candidates = size_matches (state_matches, size);
if (candidates == NULL)
candidates = size_matches (state_wild, size);
g_slist_free (state_wild);
g_slist_free (state_matches);
return candidates;
}
static GSList*
size_matches (GSList *sources,
GtkIconSizeType size)
{
GSList *size_matches = NULL;
GSList *size_wild = NULL;
GSList *iter;
iter = sources;
while (iter != NULL)
{
GtkIconSource *source = iter->data;
if (!source->any_size &&
source->size == size)
size_matches = g_slist_prepend (size_matches, source);
else if (source->any_size)
size_wild = g_slist_prepend (size_wild, source);
iter = g_slist_next (iter);
}
/* Prefer exact size matches, return wildcard sizes otherwise. */
if (size_matches)
{
g_slist_free (size_wild);
return size_matches;
}
else
{
return size_wild;
}
}

137
gtk/gtkiconfactory.h Normal file
View File

@@ -0,0 +1,137 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* 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.
*/
/*
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __GTK_ICON_FACTORY_H__
#define __GTK_ICON_FACTORY_H__
#include <gdk/gdk.h>
#include <gtk/gtkstyle.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct _GtkIconFactory GtkIconFactory;
typedef struct _GtkIconFactoryClass GtkIconFactoryClass;
#define GTK_TYPE_ICON_FACTORY (gtk_icon_factory_get_type ())
#define GTK_ICON_FACTORY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GTK_TYPE_ICON_FACTORY, GtkIconFactory))
#define GTK_ICON_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_ICON_FACTORY, GtkIconFactoryClass))
#define GTK_IS_ICON_FACTORY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_ICON_FACTORY))
#define GTK_IS_ICON_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_ICON_FACTORY))
#define GTK_ICON_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ICON_FACTORY, GtkIconFactoryClass))
struct _GtkIconFactory
{
GObject parent_instance;
GHashTable *icons;
};
struct _GtkIconFactoryClass
{
GObjectClass parent_class;
};
GType gtk_icon_factory_get_type (void);
GtkIconFactory* gtk_icon_factory_new (void);
void gtk_icon_factory_add (GtkIconFactory *factory,
const gchar *stock_id,
GtkIconSet *icon_set);
GtkIconSet * gtk_icon_factory_lookup (GtkIconFactory *factory,
const gchar *stock_id);
/* Manage the default icon factory stack */
void gtk_push_default_icon_factory (GtkIconFactory *factory);
GtkIconSet *gtk_default_icon_lookup (const gchar *stock_id);
/* Get real size from semantic size (eventually user-configurable) */
void gtk_get_icon_size (GtkIconSizeType semantic_size,
gint *width,
gint *height);
/* Icon sets */
GtkIconSet* gtk_icon_set_ref (GtkIconSet *icon_set);
void gtk_icon_set_unref (GtkIconSet *icon_set);
GtkIconSet* gtk_icon_set_copy (GtkIconSet *icon_set);
/* Get one of the icon variants in the set, creating the variant if
* necessary.
*/
GdkPixbuf* gtk_icon_set_get_icon (GtkIconSet *icon_set,
GtkStyle *style,
GtkTextDirection direction,
GtkStateType state,
GtkIconSizeType size,
GtkWidget *widget,
const char *detail);
GtkIconSet* gtk_icon_set_new (void);
struct _GtkIconSource
{
/* Either filename or pixbuf can be NULL. If both are non-NULL,
* the filename gets ignored.
*/
const char *filename;
GdkPixbuf *pixbuf;
GtkTextDirection direction;
GtkStateType state;
GtkIconSizeType size;
/* If TRUE, then the parameter is wildcarded, and the above
* fields should be ignored. If FALSE, the parameter is
* specified, and the above fields should be valid.
*/
guint any_direction : 1;
guint any_state : 1;
guint any_size : 1;
};
void gtk_icon_set_add_source (GtkIconSet *icon_set,
const GtkIconSource *source);
GtkIconSource *gtk_icon_source_copy (const GtkIconSource *source);
void gtk_icon_source_free (GtkIconSource *source);
/* Clear icon set contents, drop references to all contained
* GdkPixbuf objects and forget all GtkIconSources. Used to
* recycle an icon set.
*/
void gtk_icon_set_clear (GtkIconSet *icon_set);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_ICON_FACTORY_H__ */

145
gtk/gtkstock.c Normal file
View File

@@ -0,0 +1,145 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* 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.
*/
/*
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "gtkstock.h"
#include "gtkintl.h"
#include <gdk/gdkkeysyms.h>
static GHashTable *stock_hash = NULL;
static void init_stock_hash (void);
static void
real_add (const GtkStockItem *items,
guint n_items,
gboolean copy)
{
int i;
init_stock_hash ();
if (n_items == 0)
return;
i = 0;
while (i < n_items)
{
const GtkStockItem * item = &items[i];
if (copy)
item = gtk_stock_item_copy (item);
g_hash_table_insert (stock_hash,
(gchar*)item->stock_id, (GtkStockItem*)item);
++i;
}
}
void
gtk_stock_add (const GtkStockItem *items,
guint n_items)
{
g_return_if_fail (items != NULL);
real_add (items, n_items, TRUE);
}
void
gtk_stock_add_static (const GtkStockItem *items,
guint n_items)
{
g_return_if_fail (items != NULL);
real_add (items, n_items, FALSE);
}
gboolean
gtk_stock_lookup (const gchar *stock_id,
GtkStockItem *item)
{
const GtkStockItem *found;
g_return_val_if_fail (stock_id != NULL, FALSE);
g_return_val_if_fail (item != NULL, FALSE);
init_stock_hash ();
found = g_hash_table_lookup (stock_hash, stock_id);
if (found)
*item = *found;
return found != NULL;
}
GtkStockItem *
gtk_stock_item_copy (const GtkStockItem *item)
{
GtkStockItem *copy;
g_return_val_if_fail (item != NULL, NULL);
copy = g_new (GtkStockItem, 1);
*copy = *item;
copy->stock_id = g_strdup (item->stock_id);
copy->label = g_strdup (item->label);
copy->translation_domain = g_strdup (item->translation_domain);
return copy;
}
void
gtk_stock_item_free (GtkStockItem *item)
{
g_return_if_fail (item != NULL);
g_free ((gchar*)item->stock_id);
g_free ((gchar*)item->label);
g_free ((gchar*)item->translation_domain);
g_free (item);
}
static GtkStockItem builtin_items [] =
{
/* FIXME these are just examples */
/* and the OK accelerator is wrong, Return means default button,
OK should have its own accelerator */
{ GTK_STOCK_OK, N_("OK"), 0, GDK_Return, "gtk+" },
{ GTK_STOCK_EXIT, N_("Exit"), GDK_CONTROL_MASK, GDK_x, "gtk+" }
};
static void
init_stock_hash (void)
{
if (stock_hash == NULL)
{
stock_hash = g_hash_table_new (g_str_hash, g_str_equal);
gtk_stock_add_static (builtin_items, G_N_ELEMENTS (builtin_items));
}
}

71
gtk/gtkstock.h Normal file
View File

@@ -0,0 +1,71 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* 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.
*/
/*
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __GTK_STOCK_H__
#define __GTK_STOCK_H__
#include <gdk/gdk.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct _GtkStockItem GtkStockItem;
struct _GtkStockItem
{
const char *stock_id;
const char *label;
GdkModifierType modifier;
guint keyval;
const char *translation_domain;
};
void gtk_stock_add (const GtkStockItem *item,
guint n_items);
void gtk_stock_add_static (const GtkStockItem *item,
guint n_items);
gboolean gtk_stock_lookup (const gchar *stock_id,
GtkStockItem *item);
GtkStockItem *gtk_stock_item_copy (const GtkStockItem *item);
void gtk_stock_item_free (GtkStockItem *item);
/* Stock IDs */
#define GTK_STOCK_OK "OK"
#define GTK_STOCK_CANCEL "Cancel"
#define GTK_STOCK_EXIT "Exit"
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_STOCK_H__ */

View File

@@ -31,7 +31,7 @@
#include "gtkstyle.h"
#include "gtkwidget.h"
#include "gtkthemes.h"
#include "gtkiconfactory.h"
#define LIGHTNESS_MULT 1.3
#define DARKNESS_MULT 0.7
@@ -432,6 +432,7 @@ gtk_style_class_init (GtkStyleClass *klass)
object_class->finalize = gtk_style_finalize;
klass->render_icon = _gtk_default_render_icon;
klass->draw_hline = gtk_default_draw_hline;
klass->draw_vline = gtk_default_draw_vline;
klass->draw_shadow = gtk_default_draw_shadow;
@@ -795,6 +796,28 @@ gtk_style_realize (GtkStyle *style,
style->engine->realize_style (style);
}
GtkIconSet*
gtk_style_lookup_icon (GtkStyle *style,
const char *stock_id)
{
GSList *iter;
iter = style->icon_factories;
while (iter != NULL)
{
GtkIconSet *icon_set =
gtk_icon_factory_lookup (GTK_ICON_FACTORY (iter->data),
stock_id);
if (icon_set)
return icon_set;
iter = g_slist_next (iter);
}
return gtk_default_icon_lookup (stock_id);
}
void
gtk_draw_hline (GtkStyle *style,
GdkWindow *window,
@@ -1176,6 +1199,22 @@ gtk_style_set_background (GtkStyle *style,
}
GdkPixbuf *
gtk_style_render_icon (GtkStyle *style,
const GtkIconSource *source,
GtkTextDirection direction,
GtkStateType state,
GtkIconSizeType size,
GtkWidget *widget,
const gchar *detail)
{
g_return_val_if_fail (style != NULL, NULL);
g_return_val_if_fail (GTK_STYLE_GET_CLASS (style)->render_icon != NULL, NULL);
return GTK_STYLE_GET_CLASS (style)->render_icon (style, source, direction, state,
size, widget, detail);
}
/* Default functions */
void
gtk_style_apply_default_background (GtkStyle *style,
@@ -1241,6 +1280,157 @@ gtk_style_apply_default_background (GtkStyle *style,
}
}
#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
static void
gdk_pixbuf_saturate_and_pixelate(const GdkPixbuf *src,
GdkPixbuf *dest,
gfloat saturation,
gboolean pixelate)
{
/* NOTE that src and dest MAY be the same pixbuf! */
g_return_if_fail (src != NULL);
g_return_if_fail (dest != NULL);
g_return_if_fail (gdk_pixbuf_get_height (src) == gdk_pixbuf_get_height (dest));
g_return_if_fail (gdk_pixbuf_get_width (src) == gdk_pixbuf_get_width (dest));
g_return_if_fail (gdk_pixbuf_get_rowstride (src) == gdk_pixbuf_get_rowstride (dest));
g_return_if_fail (gdk_pixbuf_get_colorspace (src) == gdk_pixbuf_get_colorspace (dest));
if (saturation == 1.0 && !pixelate)
{
if (dest != src)
memcpy (gdk_pixbuf_get_pixels (dest),
gdk_pixbuf_get_pixels (src),
gdk_pixbuf_get_height (src) * gdk_pixbuf_get_rowstride (src));
return;
}
else
{
gint i, j;
gint width, height, has_alpha, rowstride;
guchar *target_pixels;
guchar *original_pixels;
guchar *current_pixel;
guchar intensity;
has_alpha = gdk_pixbuf_get_has_alpha (src);
width = gdk_pixbuf_get_width (src);
height = gdk_pixbuf_get_height (src);
rowstride = gdk_pixbuf_get_rowstride (src);
target_pixels = gdk_pixbuf_get_pixels (dest);
original_pixels = gdk_pixbuf_get_pixels (src);
for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
current_pixel = original_pixels + i*rowstride + j*(has_alpha?4:3);
intensity = INTENSITY (*(current_pixel), *(current_pixel + 1), *(current_pixel + 2));
if (pixelate && (i+j)%2 == 0)
{
*(target_pixels + i*rowstride + j*(has_alpha?4:3)) = intensity/2 + 127;
*(target_pixels + i*rowstride + j*(has_alpha?4:3) + 1) = intensity/2 + 127;
*(target_pixels + i*rowstride + j*(has_alpha?4:3) + 2) = intensity/2 + 127;
}
else if (pixelate)
{
#define DARK_FACTOR 0.7
*(target_pixels + i*rowstride + j*(has_alpha?4:3)) =
(guchar) (((1.0 - saturation) * intensity
+ saturation * (*(current_pixel)))) * DARK_FACTOR;
*(target_pixels + i*rowstride + j*(has_alpha?4:3) + 1) =
(guchar) (((1.0 - saturation) * intensity
+ saturation * (*(current_pixel + 1)))) * DARK_FACTOR;
*(target_pixels + i*rowstride + j*(has_alpha?4:3) + 2) =
(guchar) (((1.0 - saturation) * intensity
+ saturation * (*(current_pixel + 2)))) * DARK_FACTOR;
}
else
{
*(target_pixels + i*rowstride + j*(has_alpha?4:3)) =
(guchar) ((1.0 - saturation) * intensity
+ saturation * (*(current_pixel)));
*(target_pixels + i*rowstride + j*(has_alpha?4:3) + 1) =
(guchar) ((1.0 - saturation) * intensity
+ saturation * (*(current_pixel + 1)));
*(target_pixels + i*rowstride + j*(has_alpha?4:3) + 2) =
(guchar) ((1.0 - saturation) * intensity
+ saturation * (*(current_pixel + 2)));
}
if (has_alpha)
*(target_pixels + i*rowstride + j*(has_alpha?4:3) + 3) = *(current_pixel + 3);
}
}
return;
}
}
static GdkPixbuf*
scale_or_ref (GdkPixbuf *src,
gint width,
gint height)
{
if (width == gdk_pixbuf_get_width (src) &&
height == gdk_pixbuf_get_height (src))
{
gdk_pixbuf_ref (src);
return src;
}
else
{
return gdk_pixbuf_scale_simple (src,
width, height,
GDK_INTERP_BILINEAR);
}
}
GdkPixbuf *
_gtk_default_render_icon (GtkStyle *style,
const GtkIconSource *source,
GtkTextDirection direction,
GtkStateType state,
GtkIconSizeType size,
GtkWidget *widget,
const gchar *detail)
{
gint width = 1;
gint height = 1;
GdkPixbuf *scaled;
GdkPixbuf *stated;
/* Oddly, style can be NULL in this function, because
* GtkIconSet can be used without a style and if so
* it uses this function.
*/
g_return_val_if_fail (source->pixbuf != NULL, NULL);
gtk_get_icon_size (size, &width, &height);
scaled = scale_or_ref (source->pixbuf, width, height);
if (state == GTK_STATE_INSENSITIVE)
{
stated = gdk_pixbuf_copy (scaled);
gdk_pixbuf_saturate_and_pixelate (scaled, stated,
0.8, TRUE);
gdk_pixbuf_unref (scaled);
}
else
{
stated = scaled;
}
return stated;
}
static void
gtk_default_draw_hline (GtkStyle *style,
GdkWindow *window,

View File

@@ -51,7 +51,16 @@ typedef struct _GtkStyleClass GtkStyleClass;
*/
typedef struct _GtkThemeEngine GtkThemeEngine;
typedef struct _GtkRcStyle GtkRcStyle;
typedef struct _GtkIconSet GtkIconSet;
typedef struct _GtkIconSource GtkIconSource;
typedef enum
{
GTK_ICON_MENU,
GTK_ICON_BUTTON,
GTK_ICON_SMALL_TOOLBAR,
GTK_ICON_LARGE_TOOLBAR
} GtkIconSizeType;
/* We make this forward declaration here, since we pass
* GtkWidgt's to the draw functions.
@@ -114,11 +123,21 @@ struct _GtkStyle
* was created
*/
GSList *styles;
GSList *icon_factories;
};
struct _GtkStyleClass
{
GObjectClass parent_class;
GdkPixbuf * (* render_icon) (GtkStyle *style,
const GtkIconSource *source,
GtkTextDirection direction,
GtkStateType state,
GtkIconSizeType size,
GtkWidget *widget,
const gchar *detail);
void (*draw_hline) (GtkStyle *style,
GdkWindow *window,
@@ -377,6 +396,16 @@ void gtk_style_apply_default_background (GtkStyle *style,
gint width,
gint height);
GtkIconSet* gtk_style_lookup_icon (GtkStyle *style,
const char *stock_id);
GdkPixbuf * gtk_style_render_icon (GtkStyle *style,
const GtkIconSource *source,
GtkTextDirection direction,
GtkStateType state,
GtkIconSizeType size,
GtkWidget *widget,
const gchar *detail);
void gtk_draw_hline (GtkStyle *style,
GdkWindow *window,
GtkStateType state_type,
@@ -784,6 +813,17 @@ void gtk_paint_handle (GtkStyle *style,
gint height,
GtkOrientation orientation);
/* Internal */
GdkPixbuf * _gtk_default_render_icon (GtkStyle *style,
const GtkIconSource *source,
GtkTextDirection direction,
GtkStateType state,
GtkIconSizeType size,
GtkWidget *widget,
const gchar *detail);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@@ -28,6 +28,7 @@
#include <string.h>
#include <locale.h>
#include "gtkcontainer.h"
#include "gtkiconfactory.h"
#include "gtkmain.h"
#include "gtkrc.h"
#include "gtkselection.h"
@@ -3190,6 +3191,35 @@ gtk_widget_pop_style (void)
}
}
GdkPixbuf*
gtk_widget_get_icon (GtkWidget *widget,
const gchar *stock_id,
GtkIconSizeType size,
const gchar *detail)
{
GtkIconSet *icon_set;
GdkPixbuf *retval;
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
gtk_widget_ensure_style (widget);
icon_set = gtk_style_lookup_icon (widget->style, stock_id);
if (icon_set == NULL)
return NULL;
retval = gtk_icon_set_get_icon (icon_set,
widget->style,
gtk_widget_get_direction (widget),
GTK_WIDGET_STATE (widget),
size,
widget,
detail);
return retval;
}
/**
* gtk_widget_create_pango_context:
* @widget: a #PangoWidget

View File

@@ -576,6 +576,11 @@ void gtk_widget_restore_default_style (GtkWidget *widget);
void gtk_widget_modify_style (GtkWidget *widget,
GtkRcStyle *style);
GdkPixbuf* gtk_widget_get_icon (GtkWidget *widget,
const gchar *stock_id,
GtkIconSizeType size,
const gchar *detail);
PangoContext *gtk_widget_create_pango_context (GtkWidget *widget);
PangoLayout *gtk_widget_create_pango_layout (GtkWidget *widget);