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_new(gchar, strlen (ptr) + 1);
324 strcpy (retcol, ptr);
331 while (finished == FALSE)
333 sscanf (ptr, "%s", temp);
335 if ((gint)ptr[0] == 0 || strcmp ("s", temp) == 0 || strcmp ("m", temp) == 0 ||
336 strcmp ("g", temp) == 0 || strcmp ("g4", temp) == 0)
342 strcat (color, temp);
343 ptr = gdk_pixmap_skip_string (ptr);
344 ptr = gdk_pixmap_skip_whitespaces (ptr);
349 retcol = g_new(gchar, strlen (color) + 1);
350 strcpy (retcol, color);
356 gdk_pixmap_create_from_xpm (GdkWindow *window,
358 GdkColor *transparent_color,
359 const gchar *filename)
362 GdkPixmap *pixmap = NULL;
363 GdkImage *image = NULL;
364 GdkColormap *colormap;
368 gint width, height, num_cols, cpp, cnt, n, ns, xcnt, ycnt;
369 gchar *buffer = NULL, *color_name = NULL, pixel_str[32];
370 guint buffer_size = 0;
371 _GdkPixmapColor *colors = NULL, *color = NULL;
374 g_return_val_if_fail (window != NULL, NULL);
376 infile = fopen (filename, "rb");
379 if (gdk_pixmap_seek_string (infile, "XPM", FALSE) == TRUE)
381 if (gdk_pixmap_seek_char (infile,'{') == TRUE)
383 gdk_pixmap_seek_char (infile, '"');
384 fseek (infile, -1, SEEK_CUR);
385 gdk_pixmap_read_string (infile, &buffer, &buffer_size);
387 sscanf (buffer,"%d %d %d %d", &width, &height, &num_cols, &cpp);
389 colors = g_new(_GdkPixmapColor, num_cols);
391 colormap = gdk_window_get_colormap (window);
392 visual = gdk_window_get_visual (window);
394 if (transparent_color == NULL)
396 gdk_color_white (colormap, &tmp_color);
397 transparent_color = &tmp_color;
400 for (cnt = 0; cnt < num_cols; cnt++)
402 gdk_pixmap_seek_char (infile, '"');
403 fseek (infile, -1, SEEK_CUR);
404 gdk_pixmap_read_string (infile, &buffer, &buffer_size);
406 colors[cnt].color_string = g_new(gchar, cpp + 1);
407 for (n = 0; n < cpp; n++)
408 colors[cnt].color_string[n] = buffer[n];
409 colors[cnt].color_string[n] = 0;
410 colors[cnt].transparent = FALSE;
412 if (color_name != NULL)
415 color_name = gdk_pixmap_extract_color (&buffer[cpp]);
417 if (color_name != NULL)
419 if (gdk_color_parse (color_name, &colors[cnt].color) == FALSE)
421 colors[cnt].color = *transparent_color;
422 colors[cnt].transparent = TRUE;
427 colors[cnt].color = *transparent_color;
428 colors[cnt].transparent = TRUE;
431 gdk_color_alloc (colormap, &colors[cnt].color);
435 image = gdk_image_new (GDK_IMAGE_FASTEST, visual, width, height);
440 /* The pixmap mask is just a bits pattern.
441 * Color 0 is used for background and 1 for foreground.
442 * We don't care about the colormap, we just need 0 and 1.
444 GdkColor mask_pattern;
446 *mask = gdk_pixmap_new (window, width, height, 1);
447 gc = gdk_gc_new (*mask);
449 mask_pattern.pixel = 0;
450 gdk_gc_set_foreground (gc, &mask_pattern);
451 gdk_draw_rectangle (*mask, gc, TRUE, 0, 0, -1, -1);
453 mask_pattern.pixel = 1;
454 gdk_gc_set_foreground (gc, &mask_pattern);
457 for (ycnt = 0; ycnt < height; ycnt++)
459 gdk_pixmap_read_string (infile, &buffer, &buffer_size);
461 for (n = 0, cnt = 0, xcnt = 0; n < (width * cpp); n += cpp, xcnt++)
463 strncpy (pixel_str, &buffer[n], cpp);
468 while (color == NULL)
470 if (strcmp (pixel_str, colors[ns].color_string) == 0)
476 gdk_image_put_pixel (image, xcnt, ycnt, color->color.pixel);
478 if (mask && color->transparent)
481 gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
486 if (mask && (cnt < xcnt))
487 gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
493 pixmap = gdk_pixmap_new (window, width, height, visual->depth);
495 gc = gdk_gc_new (pixmap);
496 gdk_gc_set_foreground (gc, transparent_color);
497 gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
499 gdk_image_destroy (image);
508 for (cnt = 0; cnt < num_cols; cnt++)
509 g_free (colors[cnt].color_string);
518 gdk_pixmap_create_from_xpm_d (GdkWindow *window,
520 GdkColor *transparent_color,
523 GdkPixmap *pixmap = NULL;
524 GdkImage *image = NULL;
525 GdkColormap *colormap;
529 gint width, height, num_cols, cpp, cnt, n, ns, xcnt, ycnt, i;
530 gchar *buffer, *color_name = NULL, pixel_str[32];
531 _GdkPixmapColor *colors = NULL, *color = NULL;
534 g_return_val_if_fail (window != NULL, NULL);
538 sscanf (buffer,"%d %d %d %d", &width, &height, &num_cols, &cpp);
540 colors = g_new(_GdkPixmapColor, num_cols);
542 colormap = gdk_window_get_colormap (window);
543 visual = gdk_window_get_visual (window);
545 if (transparent_color == NULL)
547 gdk_color_white (colormap, &tmp_color);
548 transparent_color = &tmp_color;
551 for (cnt = 0; cnt < num_cols; cnt++)
555 colors[cnt].color_string = g_new(gchar, cpp + 1);
556 for (n = 0; n < cpp; n++)
557 colors[cnt].color_string[n] = buffer[n];
558 colors[cnt].color_string[n] = 0;
559 colors[cnt].transparent = FALSE;
561 if (color_name != NULL)
564 color_name = gdk_pixmap_extract_color (&buffer[cpp]);
566 if (color_name != NULL)
568 if (gdk_color_parse (color_name, &colors[cnt].color) == FALSE)
570 colors[cnt].color = *transparent_color;
571 colors[cnt].transparent = TRUE;
576 colors[cnt].color = *transparent_color;
577 colors[cnt].transparent = TRUE;
580 gdk_color_alloc (colormap, &colors[cnt].color);
584 image = gdk_image_new (GDK_IMAGE_FASTEST, visual, width, height);
589 /* The pixmap mask is just a bits pattern.
590 * Color 0 is used for background and 1 for foreground.
591 * We don't care about the colormap, we just need 0 and 1.
593 GdkColor mask_pattern;
595 *mask = gdk_pixmap_new (window, width, height, 1);
596 gc = gdk_gc_new (*mask);
598 mask_pattern.pixel = 0;
599 gdk_gc_set_foreground (gc, &mask_pattern);
600 gdk_draw_rectangle (*mask, gc, TRUE, 0, 0, -1, -1);
602 mask_pattern.pixel = 1;
603 gdk_gc_set_foreground (gc, &mask_pattern);
606 for (ycnt = 0; ycnt < height; ycnt++)
610 for (n = 0, cnt = 0, xcnt = 0; n < (width * cpp); n += cpp, xcnt++)
612 strncpy (pixel_str, &buffer[n], cpp);
617 while (color == NULL)
619 if (strcmp (pixel_str, colors[ns].color_string) == 0)
625 gdk_image_put_pixel (image, xcnt, ycnt, color->color.pixel);
627 if (mask && color->transparent)
630 gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
635 if (mask && (cnt < xcnt))
636 gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
642 pixmap = gdk_pixmap_new (window, width, height, visual->depth);
644 gc = gdk_gc_new (pixmap);
645 gdk_gc_set_foreground (gc, transparent_color);
646 gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
648 gdk_image_destroy (image);
652 for (cnt = 0; cnt < num_cols; cnt++)
653 g_free (colors[cnt].color_string);
661 gdk_pixmap_ref (GdkPixmap *pixmap)
663 GdkWindowPrivate *private = (GdkWindowPrivate *)pixmap;
664 g_return_val_if_fail (pixmap != NULL, NULL);
666 private->ref_count += 1;
671 gdk_pixmap_unref (GdkPixmap *pixmap)
673 GdkWindowPrivate *private = (GdkWindowPrivate *)pixmap;
674 g_return_if_fail(pixmap != NULL);
676 private->ref_count -= 1;
677 if (private->ref_count == 0)
679 XFreePixmap (private->xdisplay, private->xwindow);
680 gdk_xid_table_remove (private->xwindow);
686 gdk_bitmap_ref (GdkBitmap *bitmap)
688 return (GdkBitmap *)gdk_pixmap_ref ((GdkPixmap *)bitmap);
692 gdk_bitmap_unref (GdkBitmap *bitmap)
694 gdk_pixmap_unref ((GdkPixmap *)bitmap);