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)
478 if (strcmp (pixel_str, colors[ns].color_string) == 0)
484 gdk_image_put_pixel (image, xcnt, ycnt, color->color.pixel);
486 if (mask && color->transparent)
489 gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
494 if (mask && (cnt < xcnt))
495 gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
501 pixmap = gdk_pixmap_new (window, width, height, visual->depth);
503 gc = gdk_gc_new (pixmap);
504 gdk_gc_set_foreground (gc, transparent_color);
505 gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
507 gdk_image_destroy (image);
516 for (cnt = 0; cnt < num_cols; cnt++)
517 g_free (colors[cnt].color_string);
526 gdk_pixmap_create_from_xpm (GdkWindow *window,
528 GdkColor *transparent_color,
529 const gchar *filename)
531 return gdk_pixmap_colormap_create_from_xpm (window, NULL, mask,
532 transparent_color, filename);
537 gdk_pixmap_colormap_create_from_xpm_d (GdkWindow *window,
538 GdkColormap *colormap,
540 GdkColor *transparent_color,
543 GdkPixmap *pixmap = NULL;
544 GdkImage *image = NULL;
548 gint width, height, num_cols, cpp, cnt, n, ns, xcnt, ycnt, i;
549 gchar *buffer, pixel_str[32];
550 _GdkPixmapColor *colors = NULL, *color = NULL;
553 if ((window == NULL) && (colormap == NULL))
554 g_warning ("Creating pixmap from xpm with NULL window and colormap");
557 window = (GdkWindow *)&gdk_root_parent;
559 if (colormap == NULL)
561 colormap = gdk_window_get_colormap (window);
562 visual = gdk_window_get_visual (window);
565 visual = ((GdkColormapPrivate *)colormap)->visual;
569 sscanf (buffer,"%d %d %d %d", &width, &height, &num_cols, &cpp);
571 colors = g_new(_GdkPixmapColor, num_cols);
573 if (transparent_color == NULL)
575 gdk_color_white (colormap, &tmp_color);
576 transparent_color = &tmp_color;
579 for (cnt = 0; cnt < num_cols; cnt++)
585 colors[cnt].color_string = g_new(gchar, cpp + 1);
586 for (n = 0; n < cpp; n++)
587 colors[cnt].color_string[n] = buffer[n];
588 colors[cnt].color_string[n] = 0;
589 colors[cnt].transparent = FALSE;
591 color_name = gdk_pixmap_extract_color (&buffer[cpp]);
593 if (color_name != NULL)
595 if (gdk_color_parse (color_name, &colors[cnt].color) == FALSE)
597 colors[cnt].color = *transparent_color;
598 colors[cnt].transparent = TRUE;
603 colors[cnt].color = *transparent_color;
604 colors[cnt].transparent = TRUE;
609 gdk_color_alloc (colormap, &colors[cnt].color);
613 image = gdk_image_new (GDK_IMAGE_FASTEST, visual, width, height);
618 /* The pixmap mask is just a bits pattern.
619 * Color 0 is used for background and 1 for foreground.
620 * We don't care about the colormap, we just need 0 and 1.
622 GdkColor mask_pattern;
624 *mask = gdk_pixmap_new (window, width, height, 1);
625 gc = gdk_gc_new (*mask);
627 mask_pattern.pixel = 0;
628 gdk_gc_set_foreground (gc, &mask_pattern);
629 gdk_draw_rectangle (*mask, gc, TRUE, 0, 0, -1, -1);
631 mask_pattern.pixel = 1;
632 gdk_gc_set_foreground (gc, &mask_pattern);
635 for (ycnt = 0; ycnt < height; ycnt++)
639 for (n = 0, cnt = 0, xcnt = 0; n < (width * cpp); n += cpp, xcnt++)
641 strncpy (pixel_str, &buffer[n], cpp);
646 while (color == NULL)
648 if (strcmp (pixel_str, colors[ns].color_string) == 0)
654 gdk_image_put_pixel (image, xcnt, ycnt, color->color.pixel);
656 if (mask && color->transparent)
659 gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
664 if (mask && (cnt < xcnt))
665 gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
671 pixmap = gdk_pixmap_new (window, width, height, visual->depth);
673 gc = gdk_gc_new (pixmap);
674 gdk_gc_set_foreground (gc, transparent_color);
675 gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
677 gdk_image_destroy (image);
681 for (cnt = 0; cnt < num_cols; cnt++)
682 g_free (colors[cnt].color_string);
690 gdk_pixmap_create_from_xpm_d (GdkWindow *window,
692 GdkColor *transparent_color,
695 return gdk_pixmap_colormap_create_from_xpm_d (window, NULL, mask,
696 transparent_color, data);
700 gdk_pixmap_ref (GdkPixmap *pixmap)
702 GdkWindowPrivate *private = (GdkWindowPrivate *)pixmap;
703 g_return_val_if_fail (pixmap != NULL, NULL);
705 private->ref_count += 1;
710 gdk_pixmap_unref (GdkPixmap *pixmap)
712 GdkWindowPrivate *private = (GdkWindowPrivate *)pixmap;
713 g_return_if_fail(pixmap != NULL);
715 private->ref_count -= 1;
716 if (private->ref_count == 0)
718 XFreePixmap (private->xdisplay, private->xwindow);
719 gdk_xid_table_remove (private->xwindow);
725 gdk_bitmap_ref (GdkBitmap *bitmap)
727 return (GdkBitmap *)gdk_pixmap_ref ((GdkPixmap *)bitmap);
731 gdk_bitmap_unref (GdkBitmap *bitmap)
733 gdk_pixmap_unref ((GdkPixmap *)bitmap);