1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 #include "../config.h"
22 /* Needed for SEEK_END in SunOS */
27 #include "gdkprivate.h"
37 gdk_pixmap_new (GdkWindow *window,
43 GdkWindowPrivate *private;
44 GdkWindowPrivate *window_private;
46 g_return_val_if_fail ((window != NULL) || (depth != -1), NULL);
49 window = (GdkWindow*) &gdk_root_parent;
51 window_private = (GdkWindowPrivate*) window;
52 if (window_private->destroyed)
56 gdk_window_get_geometry (window, NULL, NULL, NULL, NULL, &depth);
58 private = g_new (GdkWindowPrivate, 1);
59 pixmap = (GdkPixmap*) private;
61 private->xdisplay = window_private->xdisplay;
62 private->window_type = GDK_WINDOW_PIXMAP;
63 private->xwindow = XCreatePixmap (private->xdisplay, window_private->xwindow,
64 width, height, depth);
65 private->parent = NULL;
68 private->width = width;
69 private->height = height;
70 private->resize_count = 0;
71 private->ref_count = 1;
72 private->destroyed = 0;
74 gdk_xid_table_insert (&private->xwindow, pixmap);
80 gdk_bitmap_create_from_data (GdkWindow *window,
86 GdkWindowPrivate *private;
87 GdkWindowPrivate *window_private;
89 g_return_val_if_fail (data != NULL, NULL);
92 window = (GdkWindow*) &gdk_root_parent;
94 window_private = (GdkWindowPrivate*) window;
95 if (window_private->destroyed)
98 private = g_new (GdkWindowPrivate, 1);
99 pixmap = (GdkPixmap*) private;
101 private->parent = NULL;
102 private->xdisplay = window_private->xdisplay;
103 private->window_type = GDK_WINDOW_PIXMAP;
106 private->width = width;
107 private->height = height;
108 private->resize_count = 0;
109 private->ref_count = 1;
110 private->destroyed = FALSE;
112 private->xwindow = XCreateBitmapFromData (private->xdisplay,
113 window_private->xwindow,
114 data, width, height);
116 gdk_xid_table_insert (&private->xwindow, pixmap);
122 gdk_pixmap_create_from_data (GdkWindow *window,
131 GdkWindowPrivate *private;
132 GdkWindowPrivate *window_private;
134 g_return_val_if_fail (data != NULL, NULL);
135 g_return_val_if_fail (fg != NULL, NULL);
136 g_return_val_if_fail (bg != NULL, NULL);
137 g_return_val_if_fail ((window != NULL) || (depth != -1), NULL);
140 window = (GdkWindow*) &gdk_root_parent;
142 window_private = (GdkWindowPrivate*) window;
143 if (window_private->destroyed)
147 gdk_window_get_geometry (window, NULL, NULL, NULL, NULL, &depth);
149 private = g_new (GdkWindowPrivate, 1);
150 pixmap = (GdkPixmap*) private;
152 private->parent = NULL;
153 private->xdisplay = window_private->xdisplay;
154 private->window_type = GDK_WINDOW_PIXMAP;
157 private->width = width;
158 private->height = height;
159 private->resize_count = 0;
160 private->ref_count = 1;
161 private->destroyed = FALSE;
163 private->xwindow = XCreatePixmapFromBitmapData (private->xdisplay,
164 window_private->xwindow,
166 fg->pixel, bg->pixel, depth);
168 gdk_xid_table_insert (&private->xwindow, pixmap);
174 gdk_pixmap_seek_string (FILE *infile,
180 while (!feof (infile))
182 fscanf (infile, "%s", instr);
183 if (skip_comments == TRUE && strcmp (instr, "/*") == 0)
185 fscanf (infile, "%s", instr);
186 while (!feof (infile) && strcmp (instr, "*/") != 0)
187 fscanf (infile, "%s", instr);
188 fscanf(infile, "%s", instr);
190 if (strcmp (instr, str)==0)
198 gdk_pixmap_seek_char (FILE *infile,
203 while (!feof (infile))
205 fscanf(infile, "%c", &b);
206 if (c != b && b == '/')
208 fscanf (infile, "%c", &b);
212 while (!feof (infile) && !(oldb == '*' && b == '/'))
215 fscanf (infile, "%c", &b);
217 fscanf (infile, "%c", &b);
228 gdk_pixmap_read_string (FILE *infile,
235 if ((*buffer) == NULL)
237 (*buffer_size) = 10 * sizeof (gchar);
238 (*buffer) = (gchar *) malloc (*buffer_size);
242 fscanf (infile, "%c", &c);
243 while (!feof (infile) && c != '"');
248 while (!feof (infile))
250 fscanf (infile, "%c", &c);
252 if (cnt == (*buffer_size))
255 (*buffer) = (gchar *) realloc ((*buffer), *buffer_size);
259 (*buffer)[cnt++] = c;
262 (*buffer)[cnt++] = 0;
271 gdk_pixmap_skip_whitespaces (gchar *buffer)
275 while (buffer[index] != 0 && (buffer[index] == 0x20 || buffer[index] == 0x09))
278 return &buffer[index];
282 gdk_pixmap_skip_string (gchar *buffer)
286 while (buffer[index] != 0 && buffer[index] != 0x20 && buffer[index] != 0x09)
289 return &buffer[index];
293 gdk_pixmap_extract_color (gchar *buffer)
295 gint counter, finished = FALSE, numnames;
296 gchar *ptr = NULL, ch, temp[128];
297 gchar color[128], *retcol;
302 if (buffer[counter] == 'c')
304 ch = buffer[counter + 1];
305 if (ch == 0x20 || ch == 0x09)
306 ptr = &buffer[counter + 1];
308 else if (buffer[counter] == 0)
317 ptr = gdk_pixmap_skip_whitespaces (ptr);
321 else if (ptr[0] == '#')
323 retcol = g_strdup (ptr);
330 while (finished == FALSE)
332 sscanf (ptr, "%s", temp);
334 if ((gint)ptr[0] == 0 || strcmp ("s", temp) == 0 || strcmp ("m", temp) == 0 ||
335 strcmp ("g", temp) == 0 || strcmp ("g4", temp) == 0)
341 strcat (color, temp);
342 ptr = gdk_pixmap_skip_string (ptr);
343 ptr = gdk_pixmap_skip_whitespaces (ptr);
348 retcol = g_strdup (color);
354 gdk_pixmap_colormap_create_from_xpm (GdkWindow *window,
355 GdkColormap *colormap,
357 GdkColor *transparent_color,
358 const gchar *filename)
361 GdkPixmap *pixmap = NULL;
362 GdkImage *image = NULL;
366 gint width, height, num_cols, cpp, cnt, n, ns, xcnt, ycnt;
367 gchar *buffer = NULL, pixel_str[32];
368 guint buffer_size = 0;
369 _GdkPixmapColor *colors = NULL, *color = NULL;
372 if ((window == NULL) && (colormap == NULL))
373 g_warning ("Creating pixmap from xpm with NULL window and colormap");
376 window = (GdkWindow *)&gdk_root_parent;
378 if (colormap == NULL)
380 colormap = gdk_window_get_colormap (window);
381 visual = gdk_window_get_visual (window);
384 visual = ((GdkColormapPrivate *)colormap)->visual;
386 infile = fopen (filename, "rb");
389 if (gdk_pixmap_seek_string (infile, "XPM", FALSE) == TRUE)
391 if (gdk_pixmap_seek_char (infile,'{') == TRUE)
393 gdk_pixmap_seek_char (infile, '"');
394 fseek (infile, -1, SEEK_CUR);
395 gdk_pixmap_read_string (infile, &buffer, &buffer_size);
397 sscanf (buffer,"%d %d %d %d", &width, &height, &num_cols, &cpp);
399 colors = g_new(_GdkPixmapColor, num_cols);
401 if (transparent_color == NULL)
403 gdk_color_white (colormap, &tmp_color);
404 transparent_color = &tmp_color;
407 for (cnt = 0; cnt < num_cols; cnt++)
411 gdk_pixmap_seek_char (infile, '"');
412 fseek (infile, -1, SEEK_CUR);
413 gdk_pixmap_read_string (infile, &buffer, &buffer_size);
415 colors[cnt].color_string = g_new(gchar, cpp + 1);
416 for (n = 0; n < cpp; n++)
417 colors[cnt].color_string[n] = buffer[n];
418 colors[cnt].color_string[n] = 0;
419 colors[cnt].transparent = FALSE;
421 color_name = gdk_pixmap_extract_color (&buffer[cpp]);
423 if (color_name != NULL)
425 if (gdk_color_parse (color_name, &colors[cnt].color) == FALSE)
427 colors[cnt].color = *transparent_color;
428 colors[cnt].transparent = TRUE;
433 colors[cnt].color = *transparent_color;
434 colors[cnt].transparent = TRUE;
439 gdk_color_alloc (colormap, &colors[cnt].color);
443 image = gdk_image_new (GDK_IMAGE_FASTEST, visual, width, height);
448 /* The pixmap mask is just a bits pattern.
449 * Color 0 is used for background and 1 for foreground.
450 * We don't care about the colormap, we just need 0 and 1.
452 GdkColor mask_pattern;
454 *mask = gdk_pixmap_new (window, width, height, 1);
455 gc = gdk_gc_new (*mask);
457 mask_pattern.pixel = 0;
458 gdk_gc_set_foreground (gc, &mask_pattern);
459 gdk_draw_rectangle (*mask, gc, TRUE, 0, 0, -1, -1);
461 mask_pattern.pixel = 1;
462 gdk_gc_set_foreground (gc, &mask_pattern);
465 for (ycnt = 0; ycnt < height; ycnt++)
467 gdk_pixmap_read_string (infile, &buffer, &buffer_size);
469 for (n = 0, cnt = 0, xcnt = 0; n < (width * cpp); n += cpp, xcnt++)
471 strncpy (pixel_str, &buffer[n], cpp);
476 while ((color == NULL) && (ns < num_cols))
478 if (strcmp (pixel_str, colors[ns].color_string) == 0)
484 if (!color) /* screwed up XPM file */
487 gdk_image_put_pixel (image, xcnt, ycnt, color->color.pixel);
489 if (mask && color->transparent)
492 gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
497 if (mask && (cnt < xcnt))
498 gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
504 pixmap = gdk_pixmap_new (window, width, height, visual->depth);
506 gc = gdk_gc_new (pixmap);
507 gdk_gc_set_foreground (gc, transparent_color);
508 gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
510 gdk_image_destroy (image);
519 for (cnt = 0; cnt < num_cols; cnt++)
520 g_free (colors[cnt].color_string);
529 gdk_pixmap_create_from_xpm (GdkWindow *window,
531 GdkColor *transparent_color,
532 const gchar *filename)
534 return gdk_pixmap_colormap_create_from_xpm (window, NULL, mask,
535 transparent_color, filename);
540 gdk_pixmap_colormap_create_from_xpm_d (GdkWindow *window,
541 GdkColormap *colormap,
543 GdkColor *transparent_color,
546 GdkPixmap *pixmap = NULL;
547 GdkImage *image = NULL;
551 gint width, height, num_cols, cpp, cnt, n, ns, xcnt, ycnt, i;
552 gchar *buffer, pixel_str[32];
553 _GdkPixmapColor *colors = NULL, *color = NULL;
556 if ((window == NULL) && (colormap == NULL))
557 g_warning ("Creating pixmap from xpm with NULL window and colormap");
560 window = (GdkWindow *)&gdk_root_parent;
562 if (colormap == NULL)
564 colormap = gdk_window_get_colormap (window);
565 visual = gdk_window_get_visual (window);
568 visual = ((GdkColormapPrivate *)colormap)->visual;
572 sscanf (buffer,"%d %d %d %d", &width, &height, &num_cols, &cpp);
574 colors = g_new(_GdkPixmapColor, num_cols);
576 if (transparent_color == NULL)
578 gdk_color_white (colormap, &tmp_color);
579 transparent_color = &tmp_color;
582 for (cnt = 0; cnt < num_cols; cnt++)
588 colors[cnt].color_string = g_new(gchar, cpp + 1);
589 for (n = 0; n < cpp; n++)
590 colors[cnt].color_string[n] = buffer[n];
591 colors[cnt].color_string[n] = 0;
592 colors[cnt].transparent = FALSE;
594 color_name = gdk_pixmap_extract_color (&buffer[cpp]);
596 if (color_name != NULL)
598 if (gdk_color_parse (color_name, &colors[cnt].color) == FALSE)
600 colors[cnt].color = *transparent_color;
601 colors[cnt].transparent = TRUE;
606 colors[cnt].color = *transparent_color;
607 colors[cnt].transparent = TRUE;
612 gdk_color_alloc (colormap, &colors[cnt].color);
616 image = gdk_image_new (GDK_IMAGE_FASTEST, visual, width, height);
621 /* The pixmap mask is just a bits pattern.
622 * Color 0 is used for background and 1 for foreground.
623 * We don't care about the colormap, we just need 0 and 1.
625 GdkColor mask_pattern;
627 *mask = gdk_pixmap_new (window, width, height, 1);
628 gc = gdk_gc_new (*mask);
630 mask_pattern.pixel = 0;
631 gdk_gc_set_foreground (gc, &mask_pattern);
632 gdk_draw_rectangle (*mask, gc, TRUE, 0, 0, -1, -1);
634 mask_pattern.pixel = 1;
635 gdk_gc_set_foreground (gc, &mask_pattern);
638 for (ycnt = 0; ycnt < height; ycnt++)
642 for (n = 0, cnt = 0, xcnt = 0; n < (width * cpp); n += cpp, xcnt++)
644 strncpy (pixel_str, &buffer[n], cpp);
649 while ((color == NULL) && (ns < num_cols))
651 if (strcmp (pixel_str, colors[ns].color_string) == 0)
657 if (!color) /* screwed up XPM file */
660 gdk_image_put_pixel (image, xcnt, ycnt, color->color.pixel);
662 if (mask && color->transparent)
665 gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
670 if (mask && (cnt < xcnt))
671 gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
677 pixmap = gdk_pixmap_new (window, width, height, visual->depth);
679 gc = gdk_gc_new (pixmap);
680 gdk_gc_set_foreground (gc, transparent_color);
681 gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
683 gdk_image_destroy (image);
687 for (cnt = 0; cnt < num_cols; cnt++)
688 g_free (colors[cnt].color_string);
696 gdk_pixmap_create_from_xpm_d (GdkWindow *window,
698 GdkColor *transparent_color,
701 return gdk_pixmap_colormap_create_from_xpm_d (window, NULL, mask,
702 transparent_color, data);
706 gdk_pixmap_ref (GdkPixmap *pixmap)
708 GdkWindowPrivate *private = (GdkWindowPrivate *)pixmap;
709 g_return_val_if_fail (pixmap != NULL, NULL);
711 private->ref_count += 1;
716 gdk_pixmap_unref (GdkPixmap *pixmap)
718 GdkWindowPrivate *private = (GdkWindowPrivate *)pixmap;
719 g_return_if_fail(pixmap != NULL);
721 private->ref_count -= 1;
722 if (private->ref_count == 0)
724 XFreePixmap (private->xdisplay, private->xwindow);
725 gdk_xid_table_remove (private->xwindow);
731 gdk_bitmap_ref (GdkBitmap *bitmap)
733 return (GdkBitmap *)gdk_pixmap_ref ((GdkPixmap *)bitmap);
737 gdk_bitmap_unref (GdkBitmap *bitmap)
739 gdk_pixmap_unref ((GdkPixmap *)bitmap);