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
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
19 #include "../config.h"
23 /* Needed for SEEK_END in SunOS */
28 #include "gdkprivate.h"
38 gdk_pixmap_new (GdkWindow *window,
44 GdkWindowPrivate *private;
45 GdkWindowPrivate *window_private;
47 g_return_val_if_fail ((window != NULL) || (depth != -1), NULL);
48 g_return_val_if_fail ((width != 0) && (height != 0), NULL);
51 window = (GdkWindow*) &gdk_root_parent;
53 window_private = (GdkWindowPrivate*) window;
54 if (window_private->destroyed)
58 gdk_window_get_geometry (window, NULL, NULL, NULL, NULL, &depth);
60 private = g_new (GdkWindowPrivate, 1);
61 pixmap = (GdkPixmap*) private;
63 private->xdisplay = window_private->xdisplay;
64 private->window_type = GDK_WINDOW_PIXMAP;
65 private->xwindow = XCreatePixmap (private->xdisplay, window_private->xwindow,
66 width, height, depth);
67 private->parent = NULL;
70 private->width = width;
71 private->height = height;
72 private->resize_count = 0;
73 private->ref_count = 1;
74 private->destroyed = 0;
76 gdk_xid_table_insert (&private->xwindow, pixmap);
82 gdk_bitmap_create_from_data (GdkWindow *window,
88 GdkWindowPrivate *private;
89 GdkWindowPrivate *window_private;
91 g_return_val_if_fail (data != NULL, NULL);
92 g_return_val_if_fail ((width != 0) && (height != 0), NULL);
95 window = (GdkWindow*) &gdk_root_parent;
97 window_private = (GdkWindowPrivate*) window;
98 if (window_private->destroyed)
101 private = g_new (GdkWindowPrivate, 1);
102 pixmap = (GdkPixmap*) private;
104 private->parent = NULL;
105 private->xdisplay = window_private->xdisplay;
106 private->window_type = GDK_WINDOW_PIXMAP;
109 private->width = width;
110 private->height = height;
111 private->resize_count = 0;
112 private->ref_count = 1;
113 private->destroyed = FALSE;
115 private->xwindow = XCreateBitmapFromData (private->xdisplay,
116 window_private->xwindow,
117 data, width, height);
119 gdk_xid_table_insert (&private->xwindow, pixmap);
125 gdk_pixmap_create_from_data (GdkWindow *window,
134 GdkWindowPrivate *private;
135 GdkWindowPrivate *window_private;
137 g_return_val_if_fail (data != NULL, NULL);
138 g_return_val_if_fail (fg != NULL, NULL);
139 g_return_val_if_fail (bg != NULL, NULL);
140 g_return_val_if_fail ((window != NULL) || (depth != -1), NULL);
141 g_return_val_if_fail ((width != 0) && (height != 0), NULL);
144 window = (GdkWindow*) &gdk_root_parent;
146 window_private = (GdkWindowPrivate*) window;
147 if (window_private->destroyed)
151 gdk_window_get_geometry (window, NULL, NULL, NULL, NULL, &depth);
153 private = g_new (GdkWindowPrivate, 1);
154 pixmap = (GdkPixmap*) private;
156 private->parent = NULL;
157 private->xdisplay = window_private->xdisplay;
158 private->window_type = GDK_WINDOW_PIXMAP;
161 private->width = width;
162 private->height = height;
163 private->resize_count = 0;
164 private->ref_count = 1;
165 private->destroyed = FALSE;
167 private->xwindow = XCreatePixmapFromBitmapData (private->xdisplay,
168 window_private->xwindow,
170 fg->pixel, bg->pixel, depth);
172 gdk_xid_table_insert (&private->xwindow, pixmap);
178 gdk_pixmap_seek_string (FILE *infile,
184 while (!feof (infile))
186 fscanf (infile, "%1023s", instr);
187 if (skip_comments == TRUE && strcmp (instr, "/*") == 0)
189 fscanf (infile, "%1023s", instr);
190 while (!feof (infile) && strcmp (instr, "*/") != 0)
191 fscanf (infile, "%1023s", instr);
192 fscanf(infile, "%1023s", instr);
194 if (strcmp (instr, str)==0)
202 gdk_pixmap_seek_char (FILE *infile,
207 while ((b = getc(infile)) != EOF)
209 if (c != b && b == '/')
214 else if (b == '*') /* we have a comment */
224 while (!(oldb == '*' && b == '/'));
234 gdk_pixmap_read_string (FILE *infile,
241 if ((*buffer) == NULL)
243 (*buffer_size) = 10 * sizeof (gchar);
244 (*buffer) = g_new(gchar, *buffer_size);
249 while (c != EOF && c != '"');
254 while ((c = getc(infile)) != EOF)
256 if (cnt == (*buffer_size))
259 (*buffer) = (gchar *) g_realloc ((*buffer), *buffer_size); }
262 (*buffer)[cnt++] = c;
265 (*buffer)[cnt++] = 0;
274 gdk_pixmap_skip_whitespaces (gchar *buffer)
278 while (buffer[index] != 0 && (buffer[index] == 0x20 || buffer[index] == 0x09))
281 return &buffer[index];
285 gdk_pixmap_skip_string (gchar *buffer)
289 while (buffer[index] != 0 && buffer[index] != 0x20 && buffer[index] != 0x09)
292 return &buffer[index];
296 gdk_pixmap_extract_color (gchar *buffer)
298 gint counter, finished = FALSE, numnames;
299 gchar *ptr = NULL, ch, temp[128];
300 gchar color[128], *retcol;
305 if (buffer[counter] == 'c')
307 ch = buffer[counter + 1];
308 if (ch == 0x20 || ch == 0x09)
309 ptr = &buffer[counter + 1];
311 else if (buffer[counter] == 0)
320 ptr = gdk_pixmap_skip_whitespaces (ptr);
324 else if (ptr[0] == '#')
326 retcol = g_strdup (ptr);
333 while (finished == FALSE)
335 sscanf (ptr, "%127s", temp);
337 if ((gint)ptr[0] == 0 || strcmp ("s", temp) == 0 || strcmp ("m", temp) == 0 ||
338 strcmp ("g", temp) == 0 || strcmp ("g4", temp) == 0)
344 strcat (color, temp);
345 ptr = gdk_pixmap_skip_string (ptr);
346 ptr = gdk_pixmap_skip_whitespaces (ptr);
351 retcol = g_strdup (color);
357 gdk_pixmap_colormap_create_from_xpm (GdkWindow *window,
358 GdkColormap *colormap,
360 GdkColor *transparent_color,
361 const gchar *filename)
364 GdkPixmap *pixmap = NULL;
365 GdkImage *image = NULL;
369 gint width, height, num_cols, cpp, cnt, n, ns, xcnt, ycnt;
370 gchar *buffer = NULL, pixel_str[32];
371 guint buffer_size = 0;
372 _GdkPixmapColor *colors = NULL, *color = NULL;
375 if ((window == NULL) && (colormap == NULL))
376 g_warning ("Creating pixmap from xpm with NULL window and colormap");
379 window = (GdkWindow *)&gdk_root_parent;
381 if (colormap == NULL)
383 colormap = gdk_window_get_colormap (window);
384 visual = gdk_window_get_visual (window);
387 visual = ((GdkColormapPrivate *)colormap)->visual;
389 infile = fopen (filename, "rb");
392 if (gdk_pixmap_seek_string (infile, "XPM", FALSE) == TRUE)
394 if (gdk_pixmap_seek_char (infile,'{') == TRUE)
396 gdk_pixmap_seek_char (infile, '"');
397 fseek (infile, -1, SEEK_CUR);
398 gdk_pixmap_read_string (infile, &buffer, &buffer_size);
400 sscanf (buffer,"%d %d %d %d", &width, &height, &num_cols, &cpp);
402 colors = g_new(_GdkPixmapColor, num_cols);
404 if (transparent_color == NULL)
406 gdk_color_white (colormap, &tmp_color);
407 transparent_color = &tmp_color;
410 for (cnt = 0; cnt < num_cols; cnt++)
414 gdk_pixmap_seek_char (infile, '"');
415 fseek (infile, -1, SEEK_CUR);
416 gdk_pixmap_read_string (infile, &buffer, &buffer_size);
418 colors[cnt].color_string = g_new(gchar, cpp + 1);
419 for (n = 0; n < cpp; n++)
420 colors[cnt].color_string[n] = buffer[n];
421 colors[cnt].color_string[n] = 0;
422 colors[cnt].transparent = FALSE;
424 color_name = gdk_pixmap_extract_color (&buffer[cpp]);
426 if (color_name != NULL)
428 if (gdk_color_parse (color_name, &colors[cnt].color) == FALSE)
430 colors[cnt].color = *transparent_color;
431 colors[cnt].transparent = TRUE;
436 colors[cnt].color = *transparent_color;
437 colors[cnt].transparent = TRUE;
442 gdk_color_alloc (colormap, &colors[cnt].color);
446 image = gdk_image_new (GDK_IMAGE_FASTEST, visual, width, height);
451 /* The pixmap mask is just a bits pattern.
452 * Color 0 is used for background and 1 for foreground.
453 * We don't care about the colormap, we just need 0 and 1.
455 GdkColor mask_pattern;
457 *mask = gdk_pixmap_new (window, width, height, 1);
458 gc = gdk_gc_new (*mask);
460 mask_pattern.pixel = 0;
461 gdk_gc_set_foreground (gc, &mask_pattern);
462 gdk_draw_rectangle (*mask, gc, TRUE, 0, 0, -1, -1);
464 mask_pattern.pixel = 1;
465 gdk_gc_set_foreground (gc, &mask_pattern);
468 for (ycnt = 0; ycnt < height; ycnt++)
470 gdk_pixmap_read_string (infile, &buffer, &buffer_size);
472 for (n = 0, cnt = 0, xcnt = 0; n < (width * cpp); n += cpp, xcnt++)
474 strncpy (pixel_str, &buffer[n], cpp);
479 while ((color == NULL) && (ns < num_cols))
481 if (strcmp (pixel_str, colors[ns].color_string) == 0)
487 if (!color) /* screwed up XPM file */
490 gdk_image_put_pixel (image, xcnt, ycnt, color->color.pixel);
492 if (mask && color->transparent)
495 gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
500 if (mask && (cnt < xcnt))
501 gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
507 pixmap = gdk_pixmap_new (window, width, height, visual->depth);
509 gc = gdk_gc_new (pixmap);
510 gdk_gc_set_foreground (gc, transparent_color);
511 gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
513 gdk_image_destroy (image);
522 for (cnt = 0; cnt < num_cols; cnt++)
523 g_free (colors[cnt].color_string);
532 gdk_pixmap_create_from_xpm (GdkWindow *window,
534 GdkColor *transparent_color,
535 const gchar *filename)
537 return gdk_pixmap_colormap_create_from_xpm (window, NULL, mask,
538 transparent_color, filename);
543 gdk_pixmap_colormap_create_from_xpm_d (GdkWindow *window,
544 GdkColormap *colormap,
546 GdkColor *transparent_color,
549 GdkPixmap *pixmap = NULL;
550 GdkImage *image = NULL;
554 gint width, height, num_cols, cpp, cnt, n, ns, xcnt, ycnt, i;
555 gchar *buffer, pixel_str[32];
556 _GdkPixmapColor *colors = NULL, *color = NULL;
559 if ((window == NULL) && (colormap == NULL))
560 g_warning ("Creating pixmap from xpm with NULL window and colormap");
563 window = (GdkWindow *)&gdk_root_parent;
565 if (colormap == NULL)
567 colormap = gdk_window_get_colormap (window);
568 visual = gdk_window_get_visual (window);
571 visual = ((GdkColormapPrivate *)colormap)->visual;
575 sscanf (buffer,"%d %d %d %d", &width, &height, &num_cols, &cpp);
577 colors = g_new(_GdkPixmapColor, num_cols);
579 if (transparent_color == NULL)
581 gdk_color_white (colormap, &tmp_color);
582 transparent_color = &tmp_color;
585 for (cnt = 0; cnt < num_cols; cnt++)
591 colors[cnt].color_string = g_new(gchar, cpp + 1);
592 for (n = 0; n < cpp; n++)
593 colors[cnt].color_string[n] = buffer[n];
594 colors[cnt].color_string[n] = 0;
595 colors[cnt].transparent = FALSE;
597 color_name = gdk_pixmap_extract_color (&buffer[cpp]);
599 if (color_name != NULL)
601 if (gdk_color_parse (color_name, &colors[cnt].color) == FALSE)
603 colors[cnt].color = *transparent_color;
604 colors[cnt].transparent = TRUE;
609 colors[cnt].color = *transparent_color;
610 colors[cnt].transparent = TRUE;
615 gdk_color_alloc (colormap, &colors[cnt].color);
619 image = gdk_image_new (GDK_IMAGE_FASTEST, visual, width, height);
624 /* The pixmap mask is just a bits pattern.
625 * Color 0 is used for background and 1 for foreground.
626 * We don't care about the colormap, we just need 0 and 1.
628 GdkColor mask_pattern;
630 *mask = gdk_pixmap_new (window, width, height, 1);
631 gc = gdk_gc_new (*mask);
633 mask_pattern.pixel = 0;
634 gdk_gc_set_foreground (gc, &mask_pattern);
635 gdk_draw_rectangle (*mask, gc, TRUE, 0, 0, -1, -1);
637 mask_pattern.pixel = 1;
638 gdk_gc_set_foreground (gc, &mask_pattern);
641 for (ycnt = 0; ycnt < height; ycnt++)
645 for (n = 0, cnt = 0, xcnt = 0; n < (width * cpp); n += cpp, xcnt++)
647 strncpy (pixel_str, &buffer[n], cpp);
652 while ((color == NULL) && (ns < num_cols))
654 if (strcmp (pixel_str, colors[ns].color_string) == 0)
660 if (!color) /* screwed up XPM file */
663 gdk_image_put_pixel (image, xcnt, ycnt, color->color.pixel);
665 if (mask && color->transparent)
668 gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
673 if (mask && (cnt < xcnt))
674 gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
680 pixmap = gdk_pixmap_new (window, width, height, visual->depth);
682 gc = gdk_gc_new (pixmap);
683 gdk_gc_set_foreground (gc, transparent_color);
684 gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
686 gdk_image_destroy (image);
690 for (cnt = 0; cnt < num_cols; cnt++)
691 g_free (colors[cnt].color_string);
699 gdk_pixmap_create_from_xpm_d (GdkWindow *window,
701 GdkColor *transparent_color,
704 return gdk_pixmap_colormap_create_from_xpm_d (window, NULL, mask,
705 transparent_color, data);
709 gdk_pixmap_ref (GdkPixmap *pixmap)
711 GdkWindowPrivate *private = (GdkWindowPrivate *)pixmap;
712 g_return_val_if_fail (pixmap != NULL, NULL);
714 private->ref_count += 1;
719 gdk_pixmap_unref (GdkPixmap *pixmap)
721 GdkWindowPrivate *private = (GdkWindowPrivate *)pixmap;
722 g_return_if_fail(pixmap != NULL);
724 private->ref_count -= 1;
725 if (private->ref_count == 0)
727 XFreePixmap (private->xdisplay, private->xwindow);
728 gdk_xid_table_remove (private->xwindow);
734 gdk_bitmap_ref (GdkBitmap *bitmap)
736 return (GdkBitmap *)gdk_pixmap_ref ((GdkPixmap *)bitmap);
740 gdk_bitmap_unref (GdkBitmap *bitmap)
742 gdk_pixmap_unref ((GdkPixmap *)bitmap);