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 Lesser 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 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser 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.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
30 #include "gdkinternals.h"
32 #include "gdkprivate-x11.h"
33 #include "gdkscreen-x11.h"
35 typedef struct _GdkColormapPrivateX11 GdkColormapPrivateX11;
37 struct _GdkColormapPrivateX11
46 time_t last_sync_time;
51 #define GDK_COLORMAP_PRIVATE_DATA(cmap) ((GdkColormapPrivateX11 *) GDK_COLORMAP (cmap)->windowing_data)
53 static gint gdk_colormap_match_color (GdkColormap *cmap,
55 const gchar *available);
56 static void gdk_colormap_add (GdkColormap *cmap);
57 static void gdk_colormap_remove (GdkColormap *cmap);
59 static GdkColormap *gdk_colormap_lookup (GdkScreen *screen,
62 static guint gdk_colormap_hash (Colormap *cmap);
63 static gboolean gdk_colormap_equal (Colormap *a,
65 static void gdk_colormap_sync (GdkColormap *colormap,
68 static void gdk_colormap_init (GdkColormap *colormap);
69 static void gdk_colormap_class_init (GdkColormapClass *klass);
70 static void gdk_colormap_finalize (GObject *object);
72 static gpointer parent_class = NULL;
75 gdk_colormap_get_type (void)
77 static GType object_type = 0;
81 static const GTypeInfo object_info =
83 sizeof (GdkColormapClass),
85 (GBaseFinalizeFunc) NULL,
86 (GClassInitFunc) gdk_colormap_class_init,
87 NULL, /* class_finalize */
88 NULL, /* class_data */
91 (GInstanceInitFunc) gdk_colormap_init,
94 object_type = g_type_register_static (G_TYPE_OBJECT,
103 gdk_colormap_init (GdkColormap *colormap)
105 GdkColormapPrivateX11 *private;
107 private = g_new (GdkColormapPrivateX11, 1);
109 colormap->windowing_data = private;
111 private->screen = NULL;
112 private->hash = NULL;
113 private->last_sync_time = 0;
114 private->info = NULL;
117 colormap->colors = NULL;
121 gdk_colormap_class_init (GdkColormapClass *klass)
123 GObjectClass *object_class = G_OBJECT_CLASS (klass);
125 parent_class = g_type_class_peek_parent (klass);
127 object_class->finalize = gdk_colormap_finalize;
131 gdk_colormap_finalize (GObject *object)
133 GdkColormap *colormap = GDK_COLORMAP (object);
134 GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
136 gdk_colormap_remove (colormap);
138 if (!private->screen->closed)
139 XFreeColormap (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap);
142 g_hash_table_destroy (private->hash);
144 g_free (private->info);
145 g_free (colormap->colors);
147 G_OBJECT_CLASS (parent_class)->finalize (object);
152 * @visual: a #GdkVisual.
153 * @allocate: if %TRUE, the newly created colormap will be
154 * a private colormap, and all colors in it will be
155 * allocated for the applications use.
157 * Creates a new colormap for the given visual.
159 * Return value: the new #GdkColormap.
162 gdk_colormap_new (GdkVisual *visual,
165 GdkColormap *colormap;
166 GdkColormapPrivateX11 *private;
173 /* FIXME when object properties settle down, there needs to be some
174 * kind of default construction (and construct-only arguments)
177 g_return_val_if_fail (visual != NULL, NULL);
179 colormap = g_object_new (GDK_TYPE_COLORMAP, NULL);
180 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
182 colormap->visual = visual;
183 private->screen = gdk_visual_get_screen (visual);
185 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
186 xdisplay = GDK_SCREEN_XDISPLAY (private->screen);
187 xrootwin = GDK_SCREEN_XROOTWIN (private->screen);
189 colormap->size = visual->colormap_size;
191 switch (visual->type)
193 case GDK_VISUAL_GRAYSCALE:
194 case GDK_VISUAL_PSEUDO_COLOR:
195 private->info = g_new0 (GdkColorInfo, colormap->size);
196 colormap->colors = g_new (GdkColor, colormap->size);
198 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
199 (GEqualFunc) gdk_color_equal);
201 private->private_val = allocate;
202 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
203 xvisual, (allocate) ? (AllocAll) : (AllocNone));
207 XColor *default_colors;
209 default_colors = g_new (XColor, colormap->size);
211 for (i = 0; i < colormap->size; i++)
212 default_colors[i].pixel = i;
214 XQueryColors (xdisplay,
215 DefaultColormapOfScreen (GDK_SCREEN_X11 (private->screen)->xscreen),
216 default_colors, colormap->size);
218 for (i = 0; i < colormap->size; i++)
220 colormap->colors[i].pixel = default_colors[i].pixel;
221 colormap->colors[i].red = default_colors[i].red;
222 colormap->colors[i].green = default_colors[i].green;
223 colormap->colors[i].blue = default_colors[i].blue;
226 gdk_colormap_change (colormap, colormap->size);
228 g_free (default_colors);
232 case GDK_VISUAL_DIRECT_COLOR:
233 private->private_val = TRUE;
234 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
236 colormap->colors = g_new (GdkColor, colormap->size);
238 size = 1 << visual->red_prec;
239 for (i = 0; i < size; i++)
240 colormap->colors[i].red = i * 65535 / (size - 1);
242 size = 1 << visual->green_prec;
243 for (i = 0; i < size; i++)
244 colormap->colors[i].green = i * 65535 / (size - 1);
246 size = 1 << visual->blue_prec;
247 for (i = 0; i < size; i++)
248 colormap->colors[i].blue = i * 65535 / (size - 1);
250 gdk_colormap_change (colormap, colormap->size);
253 case GDK_VISUAL_STATIC_GRAY:
254 case GDK_VISUAL_STATIC_COLOR:
255 private->private_val = FALSE;
256 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
259 colormap->colors = g_new (GdkColor, colormap->size);
260 gdk_colormap_sync (colormap, TRUE);
263 case GDK_VISUAL_TRUE_COLOR:
264 private->private_val = FALSE;
265 private->xcolormap = XCreateColormap (xdisplay, xrootwin,
270 gdk_colormap_add (colormap);
276 gdk_colormap_sync_palette (GdkColormap *colormap)
278 GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
284 xpalette = g_new (XColor, colormap->size);
286 for (i = 0; i < colormap->size; i++)
288 if (!private->info || private->info[i].ref_count == 0)
290 xpalette[nlookup].pixel = i;
291 xpalette[nlookup].red = 0;
292 xpalette[nlookup].green = 0;
293 xpalette[nlookup].blue = 0;
298 XQueryColors (GDK_SCREEN_XDISPLAY (private->screen),
299 private->xcolormap, xpalette, nlookup);
301 for (i = 0; i < nlookup; i++)
303 gulong pixel = xpalette[i].pixel;
304 colormap->colors[pixel].pixel = pixel;
305 colormap->colors[pixel].red = xpalette[i].red;
306 colormap->colors[pixel].green = xpalette[i].green;
307 colormap->colors[pixel].blue = xpalette[i].blue;
314 gdk_colormap_sync_direct_color (GdkColormap *colormap)
316 GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
317 GdkVisual *visual = colormap->visual;
321 xpalette = g_new (XColor, colormap->size);
323 for (i = 0; i < colormap->size; i++)
326 (((i << visual->red_shift) & visual->red_mask) |
327 ((i << visual->green_shift) & visual->green_mask) |
328 ((i << visual->blue_shift) & visual->blue_mask));
331 XQueryColors (GDK_SCREEN_XDISPLAY (private->screen),
332 private->xcolormap, xpalette, colormap->size);
334 for (i = 0; i < colormap->size; i++)
336 colormap->colors[i].pixel = xpalette[i].pixel;
337 colormap->colors[i].red = xpalette[i].red;
338 colormap->colors[i].green = xpalette[i].green;
339 colormap->colors[i].blue = xpalette[i].blue;
345 #define MIN_SYNC_TIME 2
348 gdk_colormap_sync (GdkColormap *colormap,
352 GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
354 g_return_if_fail (GDK_IS_COLORMAP (colormap));
356 if (private->screen->closed)
359 current_time = time (NULL);
360 if (!force && ((current_time - private->last_sync_time) < MIN_SYNC_TIME))
363 private->last_sync_time = current_time;
365 if (colormap->visual->type == GDK_VISUAL_DIRECT_COLOR)
366 gdk_colormap_sync_direct_color (colormap);
368 gdk_colormap_sync_palette (colormap);
372 * gdk_screen_get_system_colormap:
373 * @screen: a #GdkScreen
375 * Gets the system's default colormap for @screen
377 * Returns: the default colormap for @screen.
380 gdk_screen_get_system_colormap (GdkScreen *screen)
382 GdkColormap *colormap = NULL;
383 GdkColormapPrivateX11 *private;
384 GdkScreenX11 *screen_x11;
386 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
387 screen_x11 = GDK_SCREEN_X11 (screen);
389 if (screen_x11->system_colormap)
390 return screen_x11->system_colormap;
392 colormap = g_object_new (GDK_TYPE_COLORMAP, NULL);
393 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
395 private->screen = screen;
396 colormap->visual = gdk_screen_get_system_visual (screen);
398 private->xcolormap = DefaultColormapOfScreen (screen_x11->xscreen);
399 private->private_val = FALSE;
401 private->hash = NULL;
402 private->last_sync_time = 0;
403 private->info = NULL;
405 colormap->colors = NULL;
406 colormap->size = colormap->visual->colormap_size;
408 switch (colormap->visual->type)
410 case GDK_VISUAL_GRAYSCALE:
411 case GDK_VISUAL_PSEUDO_COLOR:
412 private->info = g_new0 (GdkColorInfo, colormap->size);
413 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
414 (GEqualFunc) gdk_color_equal);
416 case GDK_VISUAL_STATIC_GRAY:
417 case GDK_VISUAL_STATIC_COLOR:
418 case GDK_VISUAL_DIRECT_COLOR:
419 colormap->colors = g_new (GdkColor, colormap->size);
420 gdk_colormap_sync (colormap, TRUE);
422 case GDK_VISUAL_TRUE_COLOR:
426 gdk_colormap_add (colormap);
427 screen_x11->system_colormap = colormap;
433 * gdk_colormap_get_system_size:
435 * Returns the size of the system's default colormap.
436 * (See the description of struct #GdkColormap for an
437 * explanation of the size of a colormap.)
439 * Return value: the size of the system's default colormap.
442 gdk_colormap_get_system_size (void)
444 return DisplayCells (GDK_SCREEN_XDISPLAY (gdk_screen_get_default()),
445 GDK_SCREEN_X11 (gdk_screen_get_default())->screen_num);
449 * gdk_colormap_change:
450 * @colormap: a #GdkColormap.
451 * @ncolors: the number of colors to change.
453 * Changes the value of the first @ncolors in a private colormap
454 * to match the values in the <structfield>colors</structfield>
455 * array in the colormap. This function is obsolete and
456 * should not be used. See gdk_color_change().
459 gdk_colormap_change (GdkColormap *colormap,
462 GdkColormapPrivateX11 *private;
471 g_return_if_fail (GDK_IS_COLORMAP (colormap));
473 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
475 if (private->screen->closed)
478 xdisplay = GDK_SCREEN_XDISPLAY (private->screen);
479 palette = g_new (XColor, ncolors);
481 switch (colormap->visual->type)
483 case GDK_VISUAL_GRAYSCALE:
484 case GDK_VISUAL_PSEUDO_COLOR:
485 for (i = 0; i < ncolors; i++)
487 palette[i].pixel = colormap->colors[i].pixel;
488 palette[i].red = colormap->colors[i].red;
489 palette[i].green = colormap->colors[i].green;
490 palette[i].blue = colormap->colors[i].blue;
491 palette[i].flags = DoRed | DoGreen | DoBlue;
494 XStoreColors (xdisplay, private->xcolormap, palette, ncolors);
497 case GDK_VISUAL_DIRECT_COLOR:
498 visual = colormap->visual;
500 shift = visual->red_shift;
501 max_colors = 1 << visual->red_prec;
502 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
504 for (i = 0; i < size; i++)
506 palette[i].pixel = i << shift;
507 palette[i].red = colormap->colors[i].red;
508 palette[i].flags = DoRed;
511 XStoreColors (xdisplay, private->xcolormap, palette, size);
513 shift = visual->green_shift;
514 max_colors = 1 << visual->green_prec;
515 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
517 for (i = 0; i < size; i++)
519 palette[i].pixel = i << shift;
520 palette[i].green = colormap->colors[i].green;
521 palette[i].flags = DoGreen;
524 XStoreColors (xdisplay, private->xcolormap, palette, size);
526 shift = visual->blue_shift;
527 max_colors = 1 << visual->blue_prec;
528 size = (ncolors < max_colors) ? (ncolors) : (max_colors);
530 for (i = 0; i < size; i++)
532 palette[i].pixel = i << shift;
533 palette[i].blue = colormap->colors[i].blue;
534 palette[i].flags = DoBlue;
537 XStoreColors (xdisplay, private->xcolormap, palette, size);
549 * @colormap: a #GdkColormap.
550 * @contiguous: if %TRUE, the colors should be allocated
551 * in contiguous color cells.
552 * @planes: an array in which to store the plane masks.
553 * @nplanes: the number of planes to allocate. (Or zero,
554 * to indicate that the color allocation should not be planar.)
555 * @pixels: an array into which to store allocated pixel values.
556 * @npixels: the number of pixels in each plane to allocate.
558 * Allocates colors from a colormap. This function
559 * is obsolete. See gdk_colormap_alloc_colors().
560 * For full documentation of the fields, see
561 * the Xlib documentation for <function>XAllocColorCells()</function>.
566 gdk_colors_alloc (GdkColormap *colormap,
573 GdkColormapPrivateX11 *private;
577 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), 0);
579 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
581 if (private->screen->closed)
584 return_val = XAllocColorCells (GDK_SCREEN_XDISPLAY (private->screen),
585 private->xcolormap,contiguous, planes,
586 nplanes, pixels, npixels);
589 for (i=0; i<npixels; i++)
591 private->info[pixels[i]].ref_count++;
592 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
596 return return_val != 0;
599 /* This is almost identical to gdk_colormap_free_colors.
606 * @colormap: a #GdkColormap.
607 * @in_pixels: the pixel values of the colors to free.
608 * @in_npixels: the number of values in @pixels.
609 * @planes: the plane masks for all planes to free, OR'd together.
611 * Frees colors allocated with gdk_colors_alloc(). This
612 * function is obsolete. See gdk_colormap_free_colors().
615 gdk_colors_free (GdkColormap *colormap,
620 GdkColormapPrivateX11 *private;
625 g_return_if_fail (GDK_IS_COLORMAP (colormap));
626 g_return_if_fail (in_pixels != NULL);
628 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
630 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
631 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
634 pixels = g_new (gulong, in_npixels);
636 for (i=0; i<in_npixels; i++)
638 gulong pixel = in_pixels[i];
640 if (private->info[pixel].ref_count)
642 private->info[pixel].ref_count--;
644 if (private->info[pixel].ref_count == 0)
646 pixels[npixels++] = pixel;
647 if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
648 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
649 private->info[pixel].flags = 0;
654 if (npixels && !private->screen->closed)
655 XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
656 pixels, npixels, planes);
660 /* This is almost identical to gdk_colors_free.
665 * gdk_colormap_free_colors:
666 * @colormap: a #GdkColormap.
667 * @colors: the colors to free.
668 * @ncolors: the number of colors in @colors.
670 * Frees previously allocated colors.
673 gdk_colormap_free_colors (GdkColormap *colormap,
677 GdkColormapPrivateX11 *private;
682 g_return_if_fail (GDK_IS_COLORMAP (colormap));
683 g_return_if_fail (colors != NULL);
685 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
687 if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
688 (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
691 pixels = g_new (gulong, ncolors);
693 for (i=0; i<ncolors; i++)
695 gulong pixel = colors[i].pixel;
697 if (private->info[pixel].ref_count)
699 private->info[pixel].ref_count--;
701 if (private->info[pixel].ref_count == 0)
703 pixels[npixels++] = pixel;
704 if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
705 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
706 private->info[pixel].flags = 0;
711 if (npixels && !private->screen->closed)
712 XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
718 /********************
720 ********************/
722 /* Try to allocate a single color using XAllocColor. If it succeeds,
723 * cache the result in our colormap, and store in ret.
726 gdk_colormap_alloc1 (GdkColormap *colormap,
730 GdkColormapPrivateX11 *private;
733 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
735 xcolor.red = color->red;
736 xcolor.green = color->green;
737 xcolor.blue = color->blue;
738 xcolor.pixel = color->pixel;
739 xcolor.flags = DoRed | DoGreen | DoBlue;
741 if (XAllocColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor))
743 ret->pixel = xcolor.pixel;
744 ret->red = xcolor.red;
745 ret->green = xcolor.green;
746 ret->blue = xcolor.blue;
748 if (ret->pixel < colormap->size)
750 if (private->info[ret->pixel].ref_count) /* got a duplicate */
752 XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
753 &xcolor.pixel, 1, 0);
757 colormap->colors[ret->pixel] = *color;
758 colormap->colors[ret->pixel].pixel = ret->pixel;
759 private->info[ret->pixel].ref_count = 1;
761 g_hash_table_insert (private->hash,
762 &colormap->colors[ret->pixel],
763 &colormap->colors[ret->pixel]);
775 gdk_colormap_alloc_colors_writeable (GdkColormap *colormap,
782 GdkColormapPrivateX11 *private;
787 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
789 if (private->private_val)
792 for (i=0; i<ncolors; i++)
794 while ((index < colormap->size) && (private->info[index].ref_count != 0))
797 if (index < colormap->size)
799 colors[i].pixel = index;
801 private->info[index].ref_count++;
802 private->info[i].flags |= GDK_COLOR_WRITEABLE;
811 pixels = g_new (gulong, ncolors);
812 /* Allocation of a writeable color cells */
814 status = XAllocColorCells (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
815 FALSE, NULL, 0, pixels, ncolors);
818 for (i=0; i<ncolors; i++)
820 colors[i].pixel = pixels[i];
821 private->info[pixels[i]].ref_count++;
822 private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
828 return status ? ncolors : 0;
833 gdk_colormap_alloc_colors_private (GdkColormap *colormap,
840 GdkColormapPrivateX11 *private;
842 XColor *store = g_new (XColor, ncolors);
846 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
849 /* First, store the colors we have room for */
852 for (i=0; i<ncolors; i++)
856 while ((index < colormap->size) && (private->info[index].ref_count != 0))
859 if (index < colormap->size)
861 store[nstore].red = colors[i].red;
862 store[nstore].blue = colors[i].blue;
863 store[nstore].green = colors[i].green;
864 store[nstore].pixel = index;
869 colors[i].pixel = index;
870 private->info[index].ref_count++;
877 XStoreColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
881 if (nremaining > 0 && best_match)
883 /* Get best matches for remaining colors */
885 gchar *available = g_new (gchar, colormap->size);
886 for (i = 0; i < colormap->size; i++)
889 for (i=0; i<ncolors; i++)
893 index = gdk_colormap_match_color (colormap,
898 colors[i] = colormap->colors[index];
899 private->info[index].ref_count++;
909 return (ncolors - nremaining);
913 gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
920 GdkColormapPrivateX11 *private;
925 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
928 for (i=0; i<ncolors; i++)
932 if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i]))
940 if (nremaining > 0 && best_match)
942 gchar *available = g_new (gchar, colormap->size);
943 for (i = 0; i < colormap->size; i++)
944 available[i] = ((private->info[i].ref_count == 0) ||
945 !(private->info[i].flags & GDK_COLOR_WRITEABLE));
946 gdk_colormap_sync (colormap, FALSE);
948 while (nremaining > 0)
950 for (i=0; i<ncolors; i++)
954 index = gdk_colormap_match_color (colormap, &colors[i], available);
957 if (private->info[index].ref_count)
959 private->info[index].ref_count++;
960 colors[i] = colormap->colors[index];
966 if (gdk_colormap_alloc1 (colormap,
967 &colormap->colors[index],
976 available[index] = FALSE;
984 success[i] = 2; /* flag as permanent failure */
992 /* Change back the values we flagged as permanent failures */
995 for (i=0; i<ncolors; i++)
998 nremaining = nfailed;
1001 return (ncolors - nremaining);
1005 gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
1009 gboolean best_match,
1012 GdkColormapPrivateX11 *private;
1013 GdkColor *lookup_color;
1015 gint nremaining = 0;
1017 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1019 /* Check for an exact match among previously allocated colors */
1021 for (i=0; i<ncolors; i++)
1025 lookup_color = g_hash_table_lookup (private->hash, &colors[i]);
1028 private->info[lookup_color->pixel].ref_count++;
1029 colors[i].pixel = lookup_color->pixel;
1037 /* If that failed, we try to allocate a new color, or approxmiate
1038 * with what we can get if best_match is TRUE.
1042 if (private->private_val)
1043 return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success);
1045 return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success);
1052 * gdk_colormap_alloc_colors:
1053 * @colormap: a #GdkColormap.
1054 * @colors: The color values to allocate. On return, the pixel
1055 * values for allocated colors will be filled in.
1056 * @ncolors: The number of colors in @colors.
1057 * @writeable: If %TRUE, the colors are allocated writeable
1058 * (their values can later be changed using gdk_color_change()).
1059 * Writeable colors cannot be shared between applications.
1060 * @best_match: If %TRUE, GDK will attempt to do matching against
1061 * existing colors if the colors cannot be allocated as requested.
1062 * @success: An array of length @ncolors. On return, this
1063 * indicates whether the corresponding color in @colors was
1064 * sucessfully allocated or not.
1066 * Allocates colors from a colormap.
1068 * Return value: The number of colors that were not sucessfully
1072 gdk_colormap_alloc_colors (GdkColormap *colormap,
1076 * gdk_colormap_alloc_colors:
1077 * @colormap: a #GdkColormap.
1078 * @colors: The color values to allocate. On return, the pixel
1079 * values for allocated colors will be filled in.
1080 * @ncolors: The number of colors in @colors.
1081 * @writeable: If %TRUE, the colors are allocated writeable
1082 * (their values can later be changed using gdk_color_change()).
1083 * Writeable colors cannot be shared between applications.
1084 * @best_match: If %TRUE, GDK will attempt to do matching against
1085 * existing colors if the colors cannot be allocated as requested.
1086 * @success: An array of length @ncolors. On return, this
1087 * indicates whether the corresponding color in @colors was
1088 * sucessfully allocated or not.
1090 * Allocates colors from a colormap.
1092 * Return value: The number of colors that were not sucessfully
1096 gboolean best_match,
1099 GdkColormapPrivateX11 *private;
1102 gint nremaining = 0;
1105 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), ncolors);
1106 g_return_val_if_fail (colors != NULL, ncolors);
1108 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1110 if (private->screen->closed)
1113 for (i=0; i<ncolors; i++)
1118 switch (colormap->visual->type)
1120 case GDK_VISUAL_PSEUDO_COLOR:
1121 case GDK_VISUAL_GRAYSCALE:
1123 return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors,
1124 writeable, best_match, success);
1126 return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors,
1127 writeable, best_match, success);
1130 case GDK_VISUAL_DIRECT_COLOR:
1131 case GDK_VISUAL_TRUE_COLOR:
1132 visual = colormap->visual;
1134 for (i=0; i<ncolors; i++)
1136 colors[i].pixel = (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
1137 ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
1138 ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift));
1142 case GDK_VISUAL_STATIC_GRAY:
1143 case GDK_VISUAL_STATIC_COLOR:
1144 for (i=0; i<ncolors; i++)
1146 xcolor.red = colors[i].red;
1147 xcolor.green = colors[i].green;
1148 xcolor.blue = colors[i].blue;
1149 xcolor.pixel = colors[i].pixel;
1150 xcolor.flags = DoRed | DoGreen | DoBlue;
1152 if (XAllocColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor))
1154 colors[i].pixel = xcolor.pixel;
1166 * gdk_colormap_query_color:
1167 * @colormap: a #GdkColormap
1168 * @pixel: pixel value in hardware display format
1169 * @result: #GdkColor with red, green, blue fields initialized
1171 * Locates the RGB color in @colormap corresponding to the given
1172 * hardware pixel @pixel. @pixel must be a valid pixel in the
1173 * colormap; it's a programmer error to call this function with a
1174 * pixel which is not in the colormap. Hardware pixels are normally
1175 * obtained from gdk_colormap_alloc_colors(), or from a #GdkImage. (A
1176 * #GdkImage contains image data in hardware format, a #GdkPixbuf
1177 * contains image data in a canonical 24-bit RGB format.)
1179 * This function is rarely useful; it's used for example to
1180 * implement the eyedropper feature in #GtkColorSelection.
1184 gdk_colormap_query_color (GdkColormap *colormap,
1190 GdkColormapPrivateX11 *private;
1192 g_return_if_fail (GDK_IS_COLORMAP (colormap));
1194 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1196 visual = gdk_colormap_get_visual (colormap);
1198 switch (visual->type) {
1199 case GDK_VISUAL_DIRECT_COLOR:
1200 case GDK_VISUAL_TRUE_COLOR:
1201 result->red = 65535. * (double)((pixel & visual->red_mask) >> visual->red_shift) / ((1 << visual->red_prec) - 1);
1202 result->green = 65535. * (double)((pixel & visual->green_mask) >> visual->green_shift) / ((1 << visual->green_prec) - 1);
1203 result->blue = 65535. * (double)((pixel & visual->blue_mask) >> visual->blue_shift) / ((1 << visual->blue_prec) - 1);
1205 case GDK_VISUAL_STATIC_GRAY:
1206 case GDK_VISUAL_GRAYSCALE:
1207 result->red = result->green = result->blue = 65535. * (double)pixel/((1<<visual->depth) - 1);
1209 case GDK_VISUAL_STATIC_COLOR:
1210 xcolor.pixel = pixel;
1211 if (!private->screen->closed)
1213 XQueryColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor);
1214 result->red = xcolor.red;
1215 result->green = xcolor.green;
1216 result->blue = xcolor.blue;
1219 result->red = result->green = result->blue = 0;
1221 case GDK_VISUAL_PSEUDO_COLOR:
1222 g_return_if_fail (pixel < colormap->size);
1223 result->red = colormap->colors[pixel].red;
1224 result->green = colormap->colors[pixel].green;
1225 result->blue = colormap->colors[pixel].blue;
1228 g_assert_not_reached ();
1235 * @colormap: a #GdkColormap.
1236 * @color: a #GdkColor, with the color to change
1237 * in the <structfield>pixel</structfield> field,
1238 * and the new value in the remaining fields.
1240 * Changes the value of a color that has already
1241 * been allocated. If @colormap is not a private
1242 * colormap, then the color must have been allocated
1243 * using gdk_colormap_alloc_colors() with the
1244 * @writeable set to %TRUE.
1246 * Return value: %TRUE if the color was successfully changed.
1249 gdk_color_change (GdkColormap *colormap,
1252 GdkColormapPrivateX11 *private;
1255 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
1256 g_return_val_if_fail (color != NULL, FALSE);
1258 xcolor.pixel = color->pixel;
1259 xcolor.red = color->red;
1260 xcolor.green = color->green;
1261 xcolor.blue = color->blue;
1262 xcolor.flags = DoRed | DoGreen | DoBlue;
1264 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1265 if (!private->screen->closed)
1266 XStoreColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor);
1272 * gdk_x11_colormap_foreign_new:
1273 * @visual: a #GdkVisual
1274 * @xcolormap: The XID of a colormap with visual @visual
1276 * If xcolormap refers to a colormap previously known to GTK+,
1277 * returns a new reference to the existing #GdkColormap object,
1278 * otherwise creates a new GdkColormap object and returns that
1280 * Return value: the #GdkColormap object for @xcolormap.
1281 * Free with g_object_unref(). Note that for colormap created
1282 * with gdk_x11_colormap_foreign_new(), unref'ing the last
1283 * reference to the object will only free the #GdkColoramp
1284 * object and not call XFreeColormap()
1287 gdk_x11_colormap_foreign_new (GdkVisual *visual,
1290 GdkColormap *colormap;
1292 GdkColormapPrivateX11 *private;
1294 g_return_val_if_fail (GDK_IS_VISUAL (visual), NULL);
1295 g_return_val_if_fail (xcolormap != None, NULL);
1297 screen = gdk_visual_get_screen (visual);
1299 if (xcolormap == DefaultColormap (GDK_SCREEN_XDISPLAY (screen),
1300 GDK_SCREEN_XNUMBER (screen)));
1301 return g_object_ref (gdk_screen_get_system_colormap (screen));
1303 colormap = gdk_colormap_lookup (screen, xcolormap);
1305 return g_object_ref (colormap);
1307 colormap = g_object_new (GDK_TYPE_COLORMAP, NULL);
1308 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1310 colormap->visual = visual;
1312 private->screen = screen;
1313 private->xcolormap = xcolormap;
1314 private->xdisplay = GDK_SCREEN_XDISPLAY (screen);
1315 private->private_val = FALSE;
1317 colormap->size = visual->colormap_size;
1319 switch (colormap->visual->type)
1321 case GDK_VISUAL_GRAYSCALE:
1322 case GDK_VISUAL_PSEUDO_COLOR:
1323 private->info = g_new0 (GdkColorInfo, colormap->size);
1324 private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
1325 (GEqualFunc) gdk_color_equal);
1327 case GDK_VISUAL_STATIC_GRAY:
1328 case GDK_VISUAL_STATIC_COLOR:
1329 case GDK_VISUAL_DIRECT_COLOR:
1330 colormap->colors = g_new (GdkColor, colormap->size);
1331 gdk_colormap_sync (colormap, TRUE);
1333 case GDK_VISUAL_TRUE_COLOR:
1337 gdk_colormap_add (colormap);
1344 * gdkx_colormap_get:
1345 * @xcolormap: the XID of a colormap for the default screen.
1347 * Returns a #GdkColormap corresponding to a X colormap;
1348 * this function only works if the colormap is already
1349 * known to GTK+ (a colormap created by GTK+ or the default
1350 * colormap for the screen), since GTK+
1352 * Always use gdk_x11_colormap_foreign_new() instead.
1354 * Return value: the existing #GdkColormap object if it was
1355 * already known to GTK+, otherwise warns and return
1359 gdkx_colormap_get (Colormap xcolormap)
1361 GdkScreen *screen = gdk_screen_get_default ();
1362 GdkColormap *colormap;
1364 if (xcolormap == DefaultColormap (GDK_SCREEN_XDISPLAY (screen),
1365 GDK_SCREEN_XNUMBER (screen)));
1366 return g_object_ref (gdk_screen_get_system_colormap (screen));
1368 colormap = gdk_colormap_lookup (screen, xcolormap);
1370 return g_object_ref (colormap);
1372 g_warning ("Colormap passed to gdkx_colormap_get\n"
1373 "does not previously exist");
1379 gdk_colormap_match_color (GdkColormap *cmap,
1381 const gchar *available)
1385 gint rdiff, gdiff, bdiff;
1388 g_return_val_if_fail (cmap != NULL, 0);
1389 g_return_val_if_fail (color != NULL, 0);
1391 colors = cmap->colors;
1395 for (i = 0; i < cmap->size; i++)
1397 if ((!available) || (available && available[i]))
1399 rdiff = (color->red - colors[i].red);
1400 gdiff = (color->green - colors[i].green);
1401 bdiff = (color->blue - colors[i].blue);
1403 sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1418 gdk_colormap_lookup (GdkScreen *screen,
1421 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1423 if (screen_x11->colormap_hash)
1424 return g_hash_table_lookup (screen_x11->colormap_hash, &xcolormap);
1430 gdk_colormap_add (GdkColormap *cmap)
1432 GdkScreenX11 *screen_x11;
1433 GdkColormapPrivateX11 *private;
1435 private = GDK_COLORMAP_PRIVATE_DATA (cmap);
1436 screen_x11 = GDK_SCREEN_X11 (private->screen);
1438 if (!screen_x11->colormap_hash)
1439 screen_x11->colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
1440 (GEqualFunc) gdk_colormap_equal);
1442 g_hash_table_insert (screen_x11->colormap_hash, &private->xcolormap, cmap);
1446 gdk_colormap_remove (GdkColormap *cmap)
1448 GdkScreenX11 *screen_x11;
1449 GdkColormapPrivateX11 *private;
1451 private = GDK_COLORMAP_PRIVATE_DATA (cmap);
1452 screen_x11 = GDK_SCREEN_X11 (private->screen);
1454 if (screen_x11->colormap_hash)
1455 g_hash_table_remove (screen_x11->colormap_hash, &private->xcolormap);
1459 gdk_colormap_hash (Colormap *colormap)
1465 gdk_colormap_equal (Colormap *a,
1472 * gdk_x11_colormap_get_xdisplay:
1473 * @colormap: a #GdkColormap.
1475 * Returns the display of a #GdkColormap.
1477 * Return value: an Xlib <type>Display*</type>.
1480 gdk_x11_colormap_get_xdisplay (GdkColormap *colormap)
1482 GdkColormapPrivateX11 *private;
1484 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), NULL);
1486 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1488 return private->xdisplay;
1492 * gdk_x11_colormap_get_xcolormap:
1493 * @colormap: a #GdkColormap.
1495 * Returns the X colormap belonging to a #GdkColormap.
1497 * Return value: an Xlib <type>Colormap</type>.
1500 gdk_x11_colormap_get_xcolormap (GdkColormap *colormap)
1502 GdkColormapPrivateX11 *private;
1504 g_return_val_if_fail (GDK_IS_COLORMAP (colormap), None);
1506 private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1508 if (private->screen->closed)
1511 return private->xcolormap;
1515 * gdk_colormap_get_screen:
1516 * @cmap: a #GdkColormap
1518 * Gets the screen for which this colormap was created.
1520 * Return value: the screen for which this colormap was created.
1523 gdk_colormap_get_screen (GdkColormap *cmap)
1525 g_return_val_if_fail (GDK_IS_COLORMAP (cmap), NULL);
1527 return GDK_COLORMAP_PRIVATE_DATA (cmap)->screen;