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.
20 #include "gdkprivate.h"
23 static gint gdk_colormap_match_color (GdkColormap *cmap,
25 const gchar *available);
26 static void gdk_colormap_add (GdkColormap *cmap);
27 static void gdk_colormap_remove (GdkColormap *cmap);
28 static guint gdk_colormap_hash (Colormap *cmap);
29 static gint gdk_colormap_cmp (Colormap *a,
31 static void gdk_colormap_real_destroy (GdkColormap *colormap);
33 static GHashTable *colormap_hash = NULL;
37 gdk_colormap_new (GdkVisual *visual,
40 GdkColormap *colormap;
41 GdkColormapPrivate *private;
43 XColor default_colors[256];
47 g_return_val_if_fail (visual != NULL, NULL);
49 private = g_new (GdkColormapPrivate, 1);
50 colormap = (GdkColormap*) private;
52 private->xdisplay = gdk_display;
53 private->visual = visual;
54 private->next_color = 0;
55 private->ref_count = 1;
56 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
60 case GDK_VISUAL_GRAYSCALE:
61 case GDK_VISUAL_PSEUDO_COLOR:
62 private->private_val = private_cmap;
63 private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window,
64 xvisual, (private_cmap) ? (AllocAll) : (AllocNone));
68 for (i = 0; i < 256; i++)
69 default_colors[i].pixel = i;
71 XQueryColors (private->xdisplay,
72 DefaultColormap (private->xdisplay, gdk_screen),
73 default_colors, visual->colormap_size);
75 for (i = 0; i < visual->colormap_size; i++)
77 colormap->colors[i].pixel = default_colors[i].pixel;
78 colormap->colors[i].red = default_colors[i].red;
79 colormap->colors[i].green = default_colors[i].green;
80 colormap->colors[i].blue = default_colors[i].blue;
83 gdk_colormap_change (colormap, visual->colormap_size);
87 case GDK_VISUAL_DIRECT_COLOR:
88 private->private_val = TRUE;
89 private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window,
92 size = 1 << visual->red_prec;
93 for (i = 0; i < size; i++)
94 colormap->colors[i].red = i * 65535 / (size - 1);
96 size = 1 << visual->green_prec;
97 for (i = 0; i < size; i++)
98 colormap->colors[i].green = i * 65535 / (size - 1);
100 size = 1 << visual->blue_prec;
101 for (i = 0; i < size; i++)
102 colormap->colors[i].blue = i * 65535 / (size - 1);
104 gdk_colormap_change (colormap, visual->colormap_size);
107 case GDK_VISUAL_STATIC_GRAY:
108 case GDK_VISUAL_STATIC_COLOR:
109 case GDK_VISUAL_TRUE_COLOR:
110 private->private_val = FALSE;
111 private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window,
116 gdk_colormap_add (colormap);
122 gdk_colormap_real_destroy (GdkColormap *colormap)
124 GdkColormapPrivate *private = (GdkColormapPrivate*) colormap;
126 g_return_if_fail (colormap != NULL);
128 if (private->ref_count > 0)
131 gdk_colormap_remove (colormap);
132 XFreeColormap (private->xdisplay, private->xcolormap);
137 gdk_colormap_ref (GdkColormap *cmap)
139 GdkColormapPrivate *private = (GdkColormapPrivate *)cmap;
140 g_return_val_if_fail (cmap != NULL, NULL);
142 private->ref_count += 1;
147 gdk_colormap_unref (GdkColormap *cmap)
149 GdkColormapPrivate *private = (GdkColormapPrivate *)cmap;
150 g_return_if_fail (cmap != NULL);
152 private->ref_count -= 1;
153 if (private->ref_count == 0)
154 gdk_colormap_real_destroy (cmap);
158 gdk_colormap_get_system (void)
160 static GdkColormap *colormap = NULL;
161 GdkColormapPrivate *private;
162 XColor xpalette[256];
167 private = g_new (GdkColormapPrivate, 1);
168 colormap = (GdkColormap*) private;
170 private->xdisplay = gdk_display;
171 private->xcolormap = DefaultColormap (gdk_display, gdk_screen);
172 private->visual = gdk_visual_get_system ();
173 private->private_val = FALSE;
174 private->next_color = 0;
175 private->ref_count = 1;
177 for (i = 0; i < 256; i++)
179 xpalette[i].pixel = i;
181 xpalette[i].green = 0;
182 xpalette[i].blue = 0;
185 XQueryColors (gdk_display, private->xcolormap, xpalette,
186 private->visual->colormap_size);
188 for (i = 0; i < 256; i++)
190 colormap->colors[i].pixel = xpalette[i].pixel;
191 colormap->colors[i].red = xpalette[i].red;
192 colormap->colors[i].green = xpalette[i].green;
193 colormap->colors[i].blue = xpalette[i].blue;
196 gdk_colormap_add (colormap);
203 gdk_colormap_get_system_size (void)
205 return DisplayCells (gdk_display, gdk_screen);
209 gdk_colormap_change (GdkColormap *colormap,
212 GdkColormapPrivate *private;
220 g_return_if_fail (colormap != NULL);
222 private = (GdkColormapPrivate*) colormap;
223 switch (private->visual->type)
225 case GDK_VISUAL_GRAYSCALE:
226 case GDK_VISUAL_PSEUDO_COLOR:
227 for (i = 0; i < ncolors; i++)
229 palette[i].pixel = colormap->colors[i].pixel;
230 palette[i].red = colormap->colors[i].red;
231 palette[i].green = colormap->colors[i].green;
232 palette[i].blue = colormap->colors[i].blue;
233 palette[i].flags = DoRed | DoGreen | DoBlue;
236 XStoreColors (private->xdisplay, private->xcolormap, palette, ncolors);
237 private->next_color = MAX (private->next_color, ncolors);
240 case GDK_VISUAL_DIRECT_COLOR:
241 visual = private->visual;
243 shift = visual->red_shift;
244 max_colors = 1 << visual->red_prec;
245 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
247 for (i = 0; i < size; i++)
249 palette[i].pixel = i << shift;
250 palette[i].red = colormap->colors[i].red;
251 palette[i].flags = DoRed;
254 XStoreColors (private->xdisplay, private->xcolormap, palette, size);
256 shift = visual->green_shift;
257 max_colors = 1 << visual->green_prec;
258 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
260 for (i = 0; i < size; i++)
262 palette[i].pixel = i << shift;
263 palette[i].green = colormap->colors[i].green;
264 palette[i].flags = DoGreen;
267 XStoreColors (private->xdisplay, private->xcolormap, palette, size);
269 shift = visual->blue_shift;
270 max_colors = 1 << visual->blue_prec;
271 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
273 for (i = 0; i < size; i++)
275 palette[i].pixel = i << shift;
276 palette[i].blue = colormap->colors[i].blue;
277 palette[i].flags = DoBlue;
280 XStoreColors (private->xdisplay, private->xcolormap, palette, size);
289 gdk_colors_store (GdkColormap *colormap,
295 for (i = 0; i < ncolors; i++)
297 colormap->colors[i].pixel = colors[i].pixel;
298 colormap->colors[i].red = colors[i].red;
299 colormap->colors[i].green = colors[i].green;
300 colormap->colors[i].blue = colors[i].blue;
303 gdk_colormap_change (colormap, ncolors);
307 gdk_colors_alloc (GdkColormap *colormap,
314 GdkColormapPrivate *private;
317 g_return_val_if_fail (colormap != NULL, 0);
319 private = (GdkColormapPrivate*) colormap;
321 return_val = XAllocColorCells (private->xdisplay, private->xcolormap,
322 contiguous, planes, nplanes, pixels, npixels);
328 gdk_colors_free (GdkColormap *colormap,
333 GdkColormapPrivate *private;
335 g_return_if_fail (colormap != NULL);
337 private = (GdkColormapPrivate*) colormap;
339 XFreeColors (private->xdisplay, private->xcolormap,
340 pixels, npixels, planes);
344 gdk_color_white (GdkColormap *colormap,
349 g_return_val_if_fail (colormap != NULL, FALSE);
353 color->pixel = WhitePixel (gdk_display, gdk_screen);
355 color->green = 65535;
358 return_val = gdk_color_alloc (colormap, color);
367 gdk_color_black (GdkColormap *colormap,
372 g_return_val_if_fail (colormap != NULL, FALSE);
376 color->pixel = BlackPixel (gdk_display, gdk_screen);
381 return_val = gdk_color_alloc (colormap, color);
390 gdk_color_parse (const gchar *spec,
397 g_return_val_if_fail (spec != NULL, FALSE);
398 g_return_val_if_fail (color != NULL, FALSE);
400 xcolormap = DefaultColormap (gdk_display, gdk_screen);
402 if (XParseColor (gdk_display, xcolormap, spec, &xcolor))
405 color->red = xcolor.red;
406 color->green = xcolor.green;
407 color->blue = xcolor.blue;
416 gdk_color_alloc (GdkColormap *colormap,
419 GdkColormapPrivate *private;
422 gchar available[256];
427 g_return_val_if_fail (colormap != NULL, FALSE);
428 g_return_val_if_fail (color != NULL, FALSE);
430 xcolor.red = color->red;
431 xcolor.green = color->green;
432 xcolor.blue = color->blue;
433 xcolor.pixel = color->pixel;
434 xcolor.flags = DoRed | DoGreen | DoBlue;
437 private = (GdkColormapPrivate*) colormap;
439 switch (private->visual->type)
441 case GDK_VISUAL_GRAYSCALE:
442 case GDK_VISUAL_PSEUDO_COLOR:
443 if (private->private_val)
445 if (private->next_color > 255)
447 for (i = 0; i < 256; i++)
450 index = gdk_colormap_match_color (colormap, color, available);
453 available[index] = FALSE;
454 *color = colormap->colors[index];
464 xcolor.pixel = 255 - private->next_color;
465 color->pixel = xcolor.pixel;
466 private->next_color += 1;
468 XStoreColor (private->xdisplay, private->xcolormap, &xcolor);
478 if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor))
480 color->pixel = xcolor.pixel;
481 color->red = xcolor.red;
482 color->green = xcolor.green;
483 color->blue = xcolor.blue;
485 colormap->colors[color->pixel] = *color;
495 for (i = 0; i < 256; i++)
499 index = gdk_colormap_match_color (colormap, color, available);
502 available[index] = FALSE;
503 xcolor.red = colormap->colors[index].red;
504 xcolor.green = colormap->colors[index].green;
505 xcolor.blue = colormap->colors[index].blue;
517 case GDK_VISUAL_DIRECT_COLOR:
518 visual = private->visual;
519 xcolor.pixel = (((xcolor.red >> (16 - visual->red_prec)) << visual->red_shift) +
520 ((xcolor.green >> (16 - visual->green_prec)) << visual->green_shift) +
521 ((xcolor.blue >> (16 - visual->blue_prec)) << visual->blue_shift));
522 color->pixel = xcolor.pixel;
526 case GDK_VISUAL_STATIC_GRAY:
527 case GDK_VISUAL_STATIC_COLOR:
528 case GDK_VISUAL_TRUE_COLOR:
529 if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor))
531 color->pixel = xcolor.pixel;
543 gdk_color_change (GdkColormap *colormap,
546 GdkColormapPrivate *private;
549 g_return_val_if_fail (colormap != NULL, FALSE);
550 g_return_val_if_fail (color != NULL, FALSE);
552 xcolor.pixel = color->pixel;
553 xcolor.red = color->red;
554 xcolor.green = color->green;
555 xcolor.blue = color->blue;
556 xcolor.flags = DoRed | DoGreen | DoBlue;
558 private = (GdkColormapPrivate*) colormap;
559 XStoreColor (private->xdisplay, private->xcolormap, &xcolor);
565 gdk_color_equal (GdkColor *colora,
568 g_return_val_if_fail (colora != NULL, FALSE);
569 g_return_val_if_fail (colorb != NULL, FALSE);
571 return ((colora->red == colorb->red) &&
572 (colora->green == colorb->green) &&
573 (colora->blue == colorb->blue));
577 gdkx_colormap_get (Colormap xcolormap)
579 GdkColormap *colormap;
580 GdkColormapPrivate *private;
581 XColor xpalette[256];
584 colormap = gdk_colormap_lookup (xcolormap);
588 if (xcolormap == DefaultColormap (gdk_display, gdk_screen))
589 return gdk_colormap_get_system ();
591 private = g_new (GdkColormapPrivate, 1);
592 colormap = (GdkColormap*) private;
594 private->xdisplay = gdk_display;
595 private->xcolormap = xcolormap;
596 private->visual = NULL;
597 private->private_val = TRUE;
598 private->next_color = 0;
600 for (i = 0; i < 256; i++)
602 xpalette[i].pixel = i;
604 xpalette[i].green = 0;
605 xpalette[i].blue = 0;
608 XQueryColors (gdk_display, private->xcolormap, xpalette, 256);
610 for (i = 0; i < 256; i++)
612 colormap->colors[i].pixel = xpalette[i].pixel;
613 colormap->colors[i].red = xpalette[i].red;
614 colormap->colors[i].green = xpalette[i].green;
615 colormap->colors[i].blue = xpalette[i].blue;
618 gdk_colormap_add (colormap);
625 gdk_colormap_match_color (GdkColormap *cmap,
627 const gchar *available)
631 gint rdiff, gdiff, bdiff;
634 g_return_val_if_fail (cmap != NULL, 0);
635 g_return_val_if_fail (color != NULL, 0);
637 colors = cmap->colors;
641 for (i = 0; i < 256; i++)
643 if ((!available) || (available && available[i]))
645 rdiff = (color->red - colors[i].red);
646 gdiff = (color->green - colors[i].green);
647 bdiff = (color->blue - colors[i].blue);
649 sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
664 gdk_colormap_lookup (Colormap xcolormap)
671 cmap = g_hash_table_lookup (colormap_hash, &xcolormap);
676 gdk_colormap_add (GdkColormap *cmap)
678 GdkColormapPrivate *private;
681 colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
682 (GCompareFunc) gdk_colormap_cmp);
684 private = (GdkColormapPrivate*) cmap;
686 g_hash_table_insert (colormap_hash, &private->xcolormap, cmap);
690 gdk_colormap_remove (GdkColormap *cmap)
692 GdkColormapPrivate *private;
695 colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
696 (GCompareFunc) gdk_colormap_cmp);
698 private = (GdkColormapPrivate*) cmap;
700 g_hash_table_remove (colormap_hash, &private->xcolormap);
704 gdk_colormap_hash (Colormap *cmap)
710 gdk_colormap_cmp (Colormap *a,