X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gdk%2Fx11%2Fgdkpixmap-x11.c;h=45807cb6136ceb6051577fc62afb7c92448634fd;hb=10ba4fd066042b4335ae45e7560565872f71ba9b;hp=799bd8d462192f57598cf92771d2cae2c26183ab;hpb=e17f31db8f295f229a992fcd45912d3ef2b08b57;p=~andy%2Fgtk diff --git a/gdk/x11/gdkpixmap-x11.c b/gdk/x11/gdkpixmap-x11.c index 799bd8d46..45807cb61 100644 --- a/gdk/x11/gdkpixmap-x11.c +++ b/gdk/x11/gdkpixmap-x11.c @@ -16,7 +16,15 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ -#include "../config.h" + +/* + * 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 "config.h" #include #include #include @@ -24,8 +32,9 @@ #include #include -#include "gdk.h" +#include "gdkpixmap.h" #include "gdkprivate.h" +#include "gdkx.h" typedef struct { @@ -34,6 +43,51 @@ typedef struct gint transparent; } _GdkPixmapColor; +typedef struct +{ + guint ncolors; + GdkColormap *colormap; + gulong pixels[1]; +} _GdkPixmapInfo; + +GdkDrawableClass _gdk_x11_pixmap_class; + +static void +gdk_x11_pixmap_destroy (GdkPixmap *pixmap) +{ + XFreePixmap (GDK_DRAWABLE_XDISPLAY (pixmap), GDK_DRAWABLE_XID (pixmap)); + gdk_xid_table_remove (GDK_DRAWABLE_XID (pixmap)); + + g_free (GDK_DRAWABLE_XDATA (pixmap)); +} + +static GdkDrawable * +gdk_x11_pixmap_alloc (void) +{ + GdkDrawable *drawable; + GdkDrawablePrivate *private; + + static GdkDrawableClass klass; + static gboolean initialized = FALSE; + + if (!initialized) + { + initialized = TRUE; + + klass = _gdk_x11_drawable_class; + klass.destroy = gdk_x11_pixmap_destroy; + } + + drawable = gdk_drawable_alloc (); + private = (GdkDrawablePrivate *)drawable; + + private->klass = &klass; + private->klass_data = g_new (GdkDrawableXData, 1); + private->window_type = GDK_DRAWABLE_PIXMAP; + + return drawable; +} + GdkPixmap* gdk_pixmap_new (GdkWindow *window, gint width, @@ -41,100 +95,84 @@ gdk_pixmap_new (GdkWindow *window, gint depth) { GdkPixmap *pixmap; - GdkWindowPrivate *private; - GdkWindowPrivate *window_private; + GdkDrawablePrivate *private; + g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL); g_return_val_if_fail ((window != NULL) || (depth != -1), NULL); g_return_val_if_fail ((width != 0) && (height != 0), NULL); - + if (!window) - window = (GdkWindow*) &gdk_root_parent; + window = gdk_parent_root; - window_private = (GdkWindowPrivate*) window; - if (window_private->destroyed) + if (GDK_DRAWABLE_DESTROYED (window)) return NULL; if (depth == -1) - depth = gdk_window_get_visual (window)->depth; - - private = g_new (GdkWindowPrivate, 1); - pixmap = (GdkPixmap*) private; - - private->xdisplay = window_private->xdisplay; - private->window_type = GDK_WINDOW_PIXMAP; - private->xwindow = XCreatePixmap (private->xdisplay, window_private->xwindow, - width, height, depth); - private->colormap = NULL; - private->parent = NULL; - private->x = 0; - private->y = 0; + depth = gdk_drawable_get_visual (window)->depth; + + pixmap = gdk_x11_pixmap_alloc (); + private = (GdkDrawablePrivate *)pixmap; + + GDK_DRAWABLE_XDATA (private)->xdisplay = GDK_DRAWABLE_XDISPLAY (window); + GDK_DRAWABLE_XDATA (private)->xid = XCreatePixmap (GDK_DRAWABLE_XDISPLAY (pixmap), + GDK_DRAWABLE_XID (window), + width, height, depth); private->width = width; private->height = height; - private->resize_count = 0; - private->ref_count = 1; - private->destroyed = 0; - gdk_xid_table_insert (&private->xwindow, pixmap); + gdk_xid_table_insert (&GDK_DRAWABLE_XID (pixmap), pixmap); return pixmap; } GdkPixmap * -gdk_bitmap_create_from_data (GdkWindow *window, - gchar *data, - gint width, - gint height) +gdk_bitmap_create_from_data (GdkWindow *window, + const gchar *data, + gint width, + gint height) { GdkPixmap *pixmap; - GdkWindowPrivate *private; - GdkWindowPrivate *window_private; + GdkDrawablePrivate *private; g_return_val_if_fail (data != NULL, NULL); g_return_val_if_fail ((width != 0) && (height != 0), NULL); + g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL); if (!window) - window = (GdkWindow*) &gdk_root_parent; + window = gdk_parent_root; - window_private = (GdkWindowPrivate*) window; - if (window_private->destroyed) + if (GDK_DRAWABLE_DESTROYED (window)) return NULL; - private = g_new (GdkWindowPrivate, 1); - pixmap = (GdkPixmap*) private; + pixmap = gdk_x11_pixmap_alloc (); + private = (GdkDrawablePrivate *)pixmap; - private->parent = NULL; - private->xdisplay = window_private->xdisplay; - private->window_type = GDK_WINDOW_PIXMAP; - private->x = 0; - private->y = 0; private->width = width; private->height = height; - private->resize_count = 0; - private->ref_count = 1; - private->destroyed = FALSE; - private->xwindow = XCreateBitmapFromData (private->xdisplay, - window_private->xwindow, - data, width, height); + GDK_DRAWABLE_XDATA (private)->xdisplay = GDK_DRAWABLE_XDISPLAY (window); + GDK_DRAWABLE_XDATA (private)->xid = XCreateBitmapFromData (GDK_DRAWABLE_XDISPLAY (window), + GDK_DRAWABLE_XID (window), + (char *)data, width, height); - gdk_xid_table_insert (&private->xwindow, pixmap); + gdk_xid_table_insert (&GDK_DRAWABLE_XID (pixmap), pixmap); return pixmap; } GdkPixmap* -gdk_pixmap_create_from_data (GdkWindow *window, - gchar *data, - gint width, - gint height, - gint depth, - GdkColor *fg, - GdkColor *bg) +gdk_pixmap_create_from_data (GdkWindow *window, + const gchar *data, + gint width, + gint height, + gint depth, + GdkColor *fg, + GdkColor *bg) { GdkPixmap *pixmap; - GdkWindowPrivate *private; - GdkWindowPrivate *window_private; + GdkDrawablePrivate *private; + g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL); g_return_val_if_fail (data != NULL, NULL); g_return_val_if_fail (fg != NULL, NULL); g_return_val_if_fail (bg != NULL, NULL); @@ -142,64 +180,58 @@ gdk_pixmap_create_from_data (GdkWindow *window, g_return_val_if_fail ((width != 0) && (height != 0), NULL); if (!window) - window = (GdkWindow*) &gdk_root_parent; + window = gdk_parent_root; - window_private = (GdkWindowPrivate*) window; - if (window_private->destroyed) + if (GDK_DRAWABLE_DESTROYED (window)) return NULL; if (depth == -1) - depth = gdk_window_get_visual (window)->depth; + depth = gdk_drawable_get_visual (window)->depth; - private = g_new (GdkWindowPrivate, 1); - pixmap = (GdkPixmap*) private; + pixmap = gdk_x11_pixmap_alloc (); + private = (GdkDrawablePrivate *)pixmap; - private->parent = NULL; - private->xdisplay = window_private->xdisplay; - private->window_type = GDK_WINDOW_PIXMAP; - private->x = 0; - private->y = 0; private->width = width; private->height = height; - private->resize_count = 0; - private->ref_count = 1; - private->destroyed = FALSE; - private->xwindow = XCreatePixmapFromBitmapData (private->xdisplay, - window_private->xwindow, - data, width, height, - fg->pixel, bg->pixel, depth); + GDK_DRAWABLE_XDATA (private)->xdisplay = GDK_DRAWABLE_XDISPLAY (window); + GDK_DRAWABLE_XDATA (private)->xid = XCreatePixmapFromBitmapData (GDK_DRAWABLE_XDISPLAY (window), + GDK_DRAWABLE_XID (window), + (char *)data, width, height, + fg->pixel, bg->pixel, depth); - gdk_xid_table_insert (&private->xwindow, pixmap); + gdk_xid_table_insert (&GDK_DRAWABLE_XID (pixmap), pixmap); return pixmap; } -gint +static gint gdk_pixmap_seek_string (FILE *infile, const gchar *str, gint skip_comments) { char instr[1024]; - while (!feof (infile)) + while (1) { - fscanf (infile, "%1023s", instr); + if (fscanf (infile, "%1023s", instr) != 1) + return FALSE; + if (skip_comments == TRUE && strcmp (instr, "/*") == 0) { - fscanf (infile, "%1023s", instr); - while (!feof (infile) && strcmp (instr, "*/") != 0) - fscanf (infile, "%1023s", instr); - fscanf(infile, "%1023s", instr); + do + { + if (fscanf (infile, "%1023s", instr) != 1) + return FALSE; + } + while (strcmp (instr, "*/") != 0); } - if (strcmp (instr, str)==0) + else if (strcmp (instr, str) == 0) return TRUE; } - - return FALSE; } -gint +static gint gdk_pixmap_seek_char (FILE *infile, gchar c) { @@ -231,7 +263,7 @@ gdk_pixmap_seek_char (FILE *infile, return FALSE; } -gint +static gint gdk_pixmap_read_string (FILE *infile, gchar **buffer, guint *buffer_size) @@ -286,7 +318,7 @@ gdk_pixmap_read_string (FILE *infile, return ret; } -gchar* +static gchar* gdk_pixmap_skip_whitespaces (gchar *buffer) { gint32 index = 0; @@ -297,7 +329,7 @@ gdk_pixmap_skip_whitespaces (gchar *buffer) return &buffer[index]; } -gchar* +static gchar* gdk_pixmap_skip_string (gchar *buffer) { gint32 index = 0; @@ -311,7 +343,7 @@ gdk_pixmap_skip_string (gchar *buffer) /* Xlib crashed ince at a color name lengths around 125 */ #define MAX_COLOR_LEN 120 -gchar* +static gchar* gdk_pixmap_extract_color (gchar *buffer) { gint counter, numnames; @@ -388,13 +420,6 @@ gdk_pixmap_extract_color (gchar *buffer) return retcol; } -static void -free_color (gpointer key, gpointer value, gpointer user_data) -{ - g_free (key); - g_free (value); -} - enum buffer_op { @@ -403,6 +428,23 @@ enum buffer_op op_body }; + +static void +gdk_xpm_destroy_notify (gpointer data) +{ + _GdkPixmapInfo *info = (_GdkPixmapInfo *)data; + GdkColor color; + int i; + + for (i=0; incolors; i++) + { + color.pixel = info->pixels[i]; + gdk_colormap_free_colors (info->colormap, &color, 1); + } + + gdk_colormap_unref (info->colormap); + g_free (info); +} static GdkPixmap * _gdk_pixmap_create_from_xpm (GdkWindow *window, @@ -420,20 +462,23 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, GdkColor tmp_color; gint width, height, num_cols, cpp, n, ns, cnt, xcnt, ycnt, wbytes; gchar *buffer, pixel_str[32]; + gchar *name_buf; _GdkPixmapColor *color = NULL, *fallbackcolor = NULL; + _GdkPixmapColor *colors = NULL; gulong index; - GHashTable *colors = NULL; + GHashTable *color_hash = NULL; + _GdkPixmapInfo *color_info = NULL; if ((window == NULL) && (colormap == NULL)) g_warning ("Creating pixmap from xpm with NULL window and colormap"); if (window == NULL) - window = (GdkWindow *)&gdk_root_parent; + window = gdk_parent_root; if (colormap == NULL) { - colormap = gdk_window_get_colormap (window); - visual = gdk_window_get_visual (window); + colormap = gdk_drawable_get_colormap (window); + visual = gdk_drawable_get_visual (window); } else visual = ((GdkColormapPrivate *)colormap)->visual; @@ -449,14 +494,30 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, return NULL; } - colors = g_hash_table_new (g_str_hash, g_str_equal); + color_hash = g_hash_table_new (g_str_hash, g_str_equal); if (transparent_color == NULL) { gdk_color_white (colormap, &tmp_color); transparent_color = &tmp_color; } - + + /* For pseudo-color and grayscale visuals, we have to remember + * the colors we allocated, so we can free them later. + */ + if ((visual->type == GDK_VISUAL_PSEUDO_COLOR) || + (visual->type == GDK_VISUAL_GRAYSCALE)) + { + color_info = g_malloc (sizeof (_GdkPixmapInfo) + + sizeof(gulong) * (num_cols - 1)); + color_info->ncolors = num_cols; + color_info->colormap = colormap; + gdk_colormap_ref (colormap); + } + + name_buf = g_new (gchar, num_cols * (cpp+1)); + colors = g_new (_GdkPixmapColor, num_cols); + for (cnt = 0; cnt < num_cols; cnt++) { gchar *color_name; @@ -465,8 +526,8 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, if (buffer == NULL) goto error; - color = g_new (_GdkPixmapColor, 1); - color->color_string = g_new (gchar, cpp + 1); + color = &colors[cnt]; + color->color_string = &name_buf [cnt * (cpp + 1)]; strncpy (color->color_string, buffer, cpp); color->color_string[cpp] = 0; buffer += strlen (color->color_string); @@ -474,7 +535,7 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, color_name = gdk_pixmap_extract_color (buffer); - if (color_name == NULL || + if (color_name == NULL || g_strcasecmp (color_name, "None") == 0 || gdk_color_parse (color_name, &color->color) == FALSE) { color->color = *transparent_color; @@ -486,7 +547,11 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, /* FIXME: The remaining slowness appears to happen in this function. */ gdk_color_alloc (colormap, &color->color); - g_hash_table_insert (colors, color->color_string, color); + + if (color_info) + color_info->pixels[cnt] = color->color.pixel; + + g_hash_table_insert (color_hash, color->color_string, color); if (cnt == 0) fallbackcolor = color; } @@ -531,7 +596,7 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, pixel_str[cpp] = 0; ns = 0; - color = g_hash_table_lookup (colors, pixel_str); + color = g_hash_table_lookup (color_hash, pixel_str); if (!color) /* screwed up XPM file */ color = fallbackcolor; @@ -553,25 +618,34 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, error: if (mask) - gdk_gc_destroy (gc); + gdk_gc_unref (gc); if (image != NULL) { pixmap = gdk_pixmap_new (window, width, height, visual->depth); + + if (color_info) + gdk_drawable_set_data (pixmap, "gdk-xpm", color_info, + gdk_xpm_destroy_notify); gc = gdk_gc_new (pixmap); gdk_gc_set_foreground (gc, transparent_color); gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height); - gdk_gc_destroy (gc); - gdk_image_destroy (image); + gdk_gc_unref (gc); + gdk_image_unref (image); } + else if (color_info) + gdk_xpm_destroy_notify (color_info); + if (color_hash != NULL) + g_hash_table_destroy (color_hash); + if (colors != NULL) - { - g_hash_table_foreach (colors, free_color, 0); - g_hash_table_destroy (colors); - } - + g_free (colors); + + if (name_buf != NULL) + g_free (name_buf); + return pixmap; } @@ -700,38 +774,38 @@ gdk_pixmap_create_from_xpm_d (GdkWindow *window, } GdkPixmap* -gdk_pixmap_ref (GdkPixmap *pixmap) -{ - GdkWindowPrivate *private = (GdkWindowPrivate *)pixmap; - g_return_val_if_fail (pixmap != NULL, NULL); - - private->ref_count += 1; - return pixmap; -} - -void -gdk_pixmap_unref (GdkPixmap *pixmap) +gdk_pixmap_foreign_new (guint32 anid) { - GdkWindowPrivate *private = (GdkWindowPrivate *)pixmap; - g_return_if_fail(pixmap != NULL); + GdkPixmap *pixmap; + GdkDrawablePrivate *private; + Pixmap xpixmap; + Window root_return; + unsigned int x_ret, y_ret, w_ret, h_ret, bw_ret, depth_ret; + + /* check to make sure we were passed something at + least a little sane */ + g_return_val_if_fail((anid != 0), NULL); + + /* set the pixmap to the passed in value */ + xpixmap = anid; + + /* get information about the Pixmap to fill in the structure for + the gdk window */ + if (!XGetGeometry(GDK_DISPLAY(), + xpixmap, &root_return, + &x_ret, &y_ret, &w_ret, &h_ret, &bw_ret, &depth_ret)) + return NULL; + + pixmap = gdk_x11_pixmap_alloc (); + private = (GdkDrawablePrivate *)pixmap; - private->ref_count -= 1; - if (private->ref_count == 0) - { - XFreePixmap (private->xdisplay, private->xwindow); - gdk_xid_table_remove (private->xwindow); - g_free (private); - } -} + GDK_DRAWABLE_XDATA (private)->xdisplay = GDK_DISPLAY (); + GDK_DRAWABLE_XDATA (private)->xid = xpixmap; -GdkBitmap * -gdk_bitmap_ref (GdkBitmap *bitmap) -{ - return (GdkBitmap *)gdk_pixmap_ref ((GdkPixmap *)bitmap); -} + private->width = w_ret; + private->height = h_ret; + + gdk_xid_table_insert(&GDK_DRAWABLE_XID (pixmap), pixmap); -void -gdk_bitmap_unref (GdkBitmap *bitmap) -{ - gdk_pixmap_unref ((GdkPixmap *)bitmap); + return pixmap; }